From 2587e12ad631cc307c4d290b5ad0ba8107634396 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 10 Jan 2014 12:06:54 -0500
Subject: [PATCH 148/159] FIXME: rtx_jump_table_data_def::get_labels

---
 gcc/cfgbuild.c  | 14 +++-----------
 gcc/cfgrtl.c    | 14 +++++---------
 gcc/dwarf2cfi.c |  5 +----
 gcc/rtl.h       | 31 +++++++++++++++++++++++++++++++
 gcc/rtlanal.c   |  3 +--
 5 files changed, 41 insertions(+), 26 deletions(-)

diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c
index 5f76985..0115cd7 100644
--- a/gcc/cfgbuild.c
+++ b/gcc/cfgbuild.c
@@ -262,14 +262,9 @@ make_edges (basic_block min, basic_block max, int update_p)
 	  /* Recognize a tablejump and do the right thing.  */
 	  else if (tablejump_p (insn, NULL, &table))
 	    {
-	      rtvec vec;
+	      rtvec vec = table->get_labels ();
 	      int j;
 
-	      if (GET_CODE (PATTERN (table)) == ADDR_VEC)
-		vec = XVEC (PATTERN (table), 0);
-	      else
-		vec = XVEC (PATTERN (table), 1);
-
 	      for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
 		make_label_edge (edge_cache, bb,
 				 XEXP (RTVEC_ELT (vec, j), 0), 0);
@@ -399,7 +394,7 @@ mark_tablejump_edge (rtx label)
 }
 
 static void
-purge_dead_tablejump_edges (basic_block bb, rtx table)
+purge_dead_tablejump_edges (basic_block bb, rtx_jump_table_data table)
 {
   rtx_base_insn insn = BB_END (bb);
   rtx tmp;
@@ -408,10 +403,7 @@ purge_dead_tablejump_edges (basic_block bb, rtx table)
   edge_iterator ei;
   edge e;
 
-  if (GET_CODE (PATTERN (table)) == ADDR_VEC)
-    vec = XVEC (PATTERN (table), 0);
-  else
-    vec = XVEC (PATTERN (table), 1);
+  vec = table->get_labels ();
 
   for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
     mark_tablejump_edge (XEXP (RTVEC_ELT (vec, j), 0));
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index af2c7ab..2c8b2a6 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -198,16 +198,15 @@ delete_insn (rtx insn)
       remove_note (insn, note);
     }
 
-  if (JUMP_TABLE_DATA_P (insn))
+  if (rtx_jump_table_data table = insn->dyn_cast_rtx_jump_table_data ())
     {
-      rtx pat = PATTERN (insn);
-      int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC;
-      int len = XVECLEN (pat, diff_vec_p);
+      rtvec vec = table->get_labels ();
+      int len = GET_NUM_ELEM (vec);
       int i;
 
       for (i = 0; i < len; i++)
 	{
-	  rtx label = XEXP (XVECEXP (pat, diff_vec_p, i), 0);
+	  rtx label = XEXP (RTVEC_ELT (vec, i), 0);
 
 	  /* When deleting code in bulk (e.g. removing many unreachable
 	     blocks) we can delete a label that's a target of the vector
@@ -1191,10 +1190,7 @@ patch_jump_insn (rtx_base_insn insn, rtx_base_insn old_label,
 
       if (new_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
 	return false;
-      if (GET_CODE (PATTERN (table)) == ADDR_VEC)
-	vec = XVEC (PATTERN (table), 0);
-      else
-	vec = XVEC (PATTERN (table), 1);
+      vec = table->get_labels ();
 
       for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
 	if (XEXP (RTVEC_ELT (vec, j), 0) == old_label)
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index 7eb92bb..3196046 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -2280,10 +2280,7 @@ create_trace_edges (rtx insn)
       /* TODO: remove the cast in the next line.  */
       if (tablejump_p (insn->as_an_rtx_base_insn (), NULL, &table))
 	{
-	  rtvec vec;
-
-	  tmp = PATTERN (table);
-	  vec = XVEC (tmp, GET_CODE (tmp) == ADDR_DIFF_VEC);
+	  rtvec vec = table->get_labels ();
 
 	  n = GET_NUM_ELEM (vec);
 	  for (i = 0; i < n; ++i)
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 97f8c80..876d6f9 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -455,6 +455,11 @@ public:
     return dyn_cast <rtx_call_insn_def> (this);
   }
 
+  inline rtx_jump_table_data
+  dyn_cast_rtx_jump_table_data ()
+  {
+    return dyn_cast <rtx_jump_table_data_def> (this);
+  }
 
 public:
 
@@ -635,6 +640,23 @@ is_a_helper <rtx_call_insn_def>::test (rtx rt)
 struct GTY(()) rtx_jump_table_data_def : public rtx_base_insn_def
 {
   /* No extra fields, but adds invariant: (GET_CODE (X) == JUMP_TABLE_DATA).  */
+
+public:
+
+  /* Examination of stmt.c:emit_case_dispatch_table shows that this can be
+     either:
+
+       (a) a table of absolute jumps, in which case PATTERN (this) is an
+           ADDR_VEC with arg 0 a vector of labels, or
+
+       (b) a table of relative jumps (e.g. for -fPIC), in which case
+           PATTERN (this) is an ADDR_DIFF_VEC, with arg 0 a LABEL_REF and
+	   arg 1 the vector of labels.
+
+     Get the underlying vec.  */
+
+  inline rtvec get_labels () const;
+
 };
 
 template <>
@@ -1293,6 +1315,15 @@ inline void rtx_def::set_next_insn (rtx new_next)
    -1 means this instruction has not been recognized yet.  */
 #define INSN_CODE(INSN) XINT (INSN, 6)
 
+inline rtvec rtx_jump_table_data_def::get_labels () const
+{
+  rtx pat = PATTERN (this);
+  if (GET_CODE (pat) == ADDR_VEC)
+    return XVEC (pat, 0);
+  else
+    return XVEC (pat, 1); /* presumably an ADDR_DIFF_VEC */
+}
+
 #define RTX_FRAME_RELATED_P(RTX)					\
   (RTL_FLAG_CHECK6 ("RTX_FRAME_RELATED_P", (RTX), DEBUG_INSN, INSN,	\
 		    CALL_INSN, JUMP_INSN, BARRIER, SET)->frame_related)
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 10f3d93..3066ace 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -3768,8 +3768,7 @@ label_is_jump_target_p (const_rtx label, const_rtx_base_insn jump_insn)
 
   if (tablejump_p (jump_insn, NULL, &jump_table_data))
     {
-      rtvec vec = XVEC (PATTERN (jump_table_data),
-			GET_CODE (PATTERN (jump_table_data)) == ADDR_DIFF_VEC);
+      rtvec vec = jump_table_data->get_labels ();
       int i, veclen = GET_NUM_ELEM (vec);
 
       for (i = 0; i < veclen; ++i)
-- 
1.7.11.7

