From 7deadb2c88262cea39352e9938392e9cecca7b67 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 2 Jan 2014 16:34:41 -0500
Subject: [PATCH 062/159] FIXME: tablejump_p

---
 gcc/cfgbuild.c   | 14 ++++++++------
 gcc/cfgcleanup.c | 11 ++++++-----
 gcc/cfgrtl.c     | 50 ++++++++++++++++++++++++++++----------------------
 gcc/cse.c        |  2 +-
 gcc/dwarf2cfi.c  |  6 ++++--
 gcc/jump.c       | 10 ++++++----
 gcc/reload.c     |  2 +-
 gcc/reload.h     |  2 +-
 gcc/rtl.h        | 25 ++++++++++++++++++++++---
 gcc/rtlanal.c    | 20 +++++++++++---------
 gcc/targhooks.c  |  4 +++-
 11 files changed, 91 insertions(+), 55 deletions(-)

diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c
index 1c12701..a747837 100644
--- a/gcc/cfgbuild.c
+++ b/gcc/cfgbuild.c
@@ -218,7 +218,8 @@ make_edges (basic_block min, basic_block max, int update_p)
 
   FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
     {
-      rtx insn, x;
+      rtx_base_insn insn;
+      rtx x;
       enum rtx_code code;
       edge e;
       edge_iterator ei;
@@ -251,6 +252,7 @@ make_edges (basic_block min, basic_block max, int update_p)
       /* A branch.  */
       if (code == JUMP_INSN)
 	{
+	  rtx_jump_table_data table;
 	  rtx tmp;
 
 	  /* Recognize a non-local goto as a branch outside the
@@ -259,15 +261,15 @@ 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, &tmp))
+	  else if (tablejump_p (insn, NULL, &table))
 	    {
 	      rtvec vec;
 	      int j;
 
-	      if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
-		vec = XVEC (PATTERN (tmp), 0);
+	      if (GET_CODE (PATTERN (table)) == ADDR_VEC)
+		vec = XVEC (PATTERN (table), 0);
 	      else
-		vec = XVEC (PATTERN (tmp), 1);
+		vec = XVEC (PATTERN (table), 1);
 
 	      for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
 		make_label_edge (edge_cache, bb,
@@ -444,7 +446,7 @@ find_bb_boundaries (basic_block bb)
   basic_block orig_bb = bb;
   rtx_base_insn insn = BB_HEAD (bb);
   rtx end = BB_END (bb), x;
-  rtx table;
+  rtx_jump_table_data table;
   rtx flow_transfer_insn = NULL_RTX;
   edge fallthru = NULL;
 
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 2e85f7d..41cb5a3 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -703,7 +703,8 @@ static void
 merge_blocks_move_successor_nojumps (basic_block a, basic_block b)
 {
   rtx barrier, real_b_end;
-  rtx label, table;
+  rtx_code_label label;
+  rtx_jump_table_data table;
 
   /* If we are partitioning hot/cold basic blocks, we don't want to
      mess up unconditional or indirect jumps that cross between hot
@@ -1674,8 +1675,8 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
   /* Check whether there are tablejumps in the end of BB1 and BB2.
      Return true if they are identical.  */
     {
-      rtx label1, label2;
-      rtx table1, table2;
+      rtx_code_label label1, label2;
+      rtx_jump_table_data table1, table2;
 
       if (tablejump_p (BB_END (bb1), &label1, &table1)
 	  && tablejump_p (BB_END (bb2), &label2, &table2)
@@ -1977,8 +1978,8 @@ try_crossjump_to_edge (int mode, edge e1, edge e2,
      they have been already compared for equivalence in outgoing_edges_match ()
      so replace the references to TABLE1 by references to TABLE2.  */
     {
-      rtx label1, label2;
-      rtx table1, table2;
+      rtx_code_label label1, label2;
+      rtx_jump_table_data table1, table2;
 
       if (tablejump_p (BB_END (osrc1), &label1, &table1)
 	  && tablejump_p (BB_END (osrc2), &label2, &table2)
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 6cd9d3e..cffd54e 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -615,8 +615,8 @@ forwarder_block_p (const_basic_block bb)
 bool
 can_fallthru (basic_block src, basic_block target)
 {
-  rtx insn = BB_END (src);
-  rtx insn2;
+  rtx_base_insn insn = BB_END (src);
+  rtx_base_insn insn2;
   edge e;
   edge_iterator ei;
 
@@ -1098,7 +1098,9 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
   else
     {
       rtx_code_label target_label = block_label (target);
-      rtx barrier, label, table;
+      rtx barrier;
+      rtx_code_label label;
+      rtx_jump_table_data table;
 
       emit_jump_insn_after_noloc (gen_jump (target_label), insn);
       JUMP_LABEL (BB_END (src)) = target_label;
@@ -1169,11 +1171,12 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
    doesn't work.  */
 
 static bool
-patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb)
+patch_jump_insn (rtx_base_insn insn, rtx old_label, basic_block new_bb)
 {
   rtx tmp;
+  rtx_jump_table_data table;
   /* Recognize a tablejump and adjust all matching cases.  */
-  if (tablejump_p (insn, NULL, &tmp))
+  if (tablejump_p (insn, NULL, &table))
     {
       rtvec vec;
       int j;
@@ -1181,10 +1184,10 @@ patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb)
 
       if (new_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
 	return false;
-      if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
-	vec = XVEC (PATTERN (tmp), 0);
+      if (GET_CODE (PATTERN (table)) == ADDR_VEC)
+	vec = XVEC (PATTERN (table), 0);
       else
-	vec = XVEC (PATTERN (tmp), 1);
+	vec = XVEC (PATTERN (table), 1);
 
       for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
 	if (XEXP (RTVEC_ELT (vec, j), 0) == old_label)
@@ -1284,7 +1287,7 @@ patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb)
 static edge
 redirect_branch_edge (edge e, basic_block target)
 {
-  rtx old_label = BB_HEAD (e->dest);
+  rtx_base_insn old_label = BB_HEAD (e->dest);
   basic_block src = e->src;
   rtx_base_insn insn = BB_END (src);
 
@@ -1611,7 +1614,8 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
       /* If the old block ended with a tablejump, skip its table
 	 by searching forward from there.  Otherwise start searching
 	 forward from the last instruction of the old block.  */
-      if (!tablejump_p (BB_END (e->src), NULL, &note))
+      rtx_jump_table_data table;
+      if (!tablejump_p (BB_END (e->src), NULL, &table))
 	note = BB_END (e->src);
       note = NEXT_INSN (note);
 
@@ -1811,7 +1815,7 @@ static basic_block
 rtl_split_edge (edge edge_in)
 {
   basic_block bb, new_bb;
-  rtx before;
+  rtx_base_insn before;
 
   /* Abnormal edges cannot be split.  */
   gcc_assert (!(edge_in->flags & EDGE_ABNORMAL));
@@ -1830,7 +1834,7 @@ rtl_split_edge (edge edge_in)
   if (edge_in->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
     before = BB_HEAD (edge_in->dest);
   else
-    before = NULL_RTX;
+    before = NULL_RTX_BASE_INSN;
 
   /* If this is a fall through edge to the exit block, the blocks might be
      not adjacent, and the right place is after the source.  */
@@ -1901,7 +1905,7 @@ rtl_split_edge (edge edge_in)
 	  /* For asm goto even splitting of fallthru edge might
 	     need insn patching, as other labels might point to the
 	     old label.  */
-	  rtx last = BB_END (edge_in->src);
+	  rtx_base_insn last = BB_END (edge_in->src);
 	  if (last
 	      && JUMP_P (last)
 	      && edge_in->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
@@ -2239,19 +2243,20 @@ update_br_prob_note (basic_block bb)
 rtx
 get_last_bb_insn (basic_block bb)
 {
-  rtx tmp;
-  rtx end = BB_END (bb);
+  rtx_base_insn end = BB_END (bb);
+  rtx_jump_table_data table;
+  rtx_base_insn maybe_barrier;
 
   /* Include any jump table following the basic block.  */
-  if (tablejump_p (end, NULL, &tmp))
-    end = tmp;
+  if (tablejump_p (end, NULL, &table))
+    end = table;
 
   /* Include any barriers that may follow the basic block.  */
-  tmp = next_nonnote_insn_bb (end);
-  while (tmp && BARRIER_P (tmp))
+  maybe_barrier = next_nonnote_insn_bb (end);
+  while (maybe_barrier && BARRIER_P (maybe_barrier))
     {
-      end = tmp;
-      tmp = next_nonnote_insn_bb (end);
+      end = maybe_barrier;
+      maybe_barrier = next_nonnote_insn_bb (end);
     }
 
   return end;
@@ -4978,7 +4983,8 @@ rtl_can_remove_branch_p (const_edge e)
 {
   const_basic_block src = e->src;
   const_basic_block target = EDGE_SUCC (src, EDGE_SUCC (src, 0) == e)->dest;
-  const_rtx insn = BB_END (src), set;
+  const_rtx_base_insn insn = BB_END (src);
+  const_rtx set;
 
   /* The conditions are taken from try_redirect_by_replacing_jump.  */
   if (target == EXIT_BLOCK_PTR_FOR_FN (cfun))
diff --git a/gcc/cse.c b/gcc/cse.c
index e4e958e..8cb4dcf 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -6615,7 +6615,7 @@ cse_main (rtx f ATTRIBUTE_UNUSED, int nregs)
 static int
 check_for_label_ref (rtx *rtl, void *data)
 {
-  rtx insn = (rtx) data;
+  rtx_base_insn insn = (rtx_base_insn) data;
 
   /* If this insn uses a LABEL_REF and there isn't a REG_LABEL_OPERAND
      note for it, we must rerun jump since it needs to place the note.  If
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index f2b7316..ec13817 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -2273,14 +2273,16 @@ create_trace_edges (rtx insn)
 
   if (JUMP_P (insn))
     {
+      rtx_jump_table_data table;
       if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
 	return;
 
-      if (tablejump_p (insn, NULL, &tmp))
+      /* TODO: remove the cast in the next line.  */
+      if (tablejump_p (insn->as_an_rtx_base_insn (), NULL, &table))
 	{
 	  rtvec vec;
 
-	  tmp = PATTERN (tmp);
+	  tmp = PATTERN (table);
 	  vec = XVEC (tmp, GET_CODE (tmp) == ADDR_DIFF_VEC);
 
 	  n = GET_NUM_ELEM (vec);
diff --git a/gcc/jump.c b/gcc/jump.c
index 1dc0543..54cdd51 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -1247,12 +1247,12 @@ mark_jump_label_asm (rtx asmop, rtx insn)
    Usage of this instruction is deprecated.  Use delete_insn instead and
    subsequent cfg_cleanup pass to delete unreachable code if needed.  */
 
-rtx
+rtx_base_insn
 delete_related_insns (rtx insn)
 {
   int was_code_label = (LABEL_P (insn));
   rtx note;
-  rtx next = NEXT_INSN (insn), prev = PREV_INSN (insn);
+  rtx_base_insn next = NEXT_INSN (insn), prev = PREV_INSN (insn);
 
   while (next && INSN_DELETED_P (next))
     next = NEXT_INSN (next);
@@ -1294,15 +1294,17 @@ delete_related_insns (rtx insn)
 
   if (jump_to_label_p (insn))
     {
-      rtx lab = JUMP_LABEL (insn), lab_next;
+      rtx lab = JUMP_LABEL (insn);
+      rtx_jump_table_data lab_next;
 
       if (LABEL_NUSES (lab) == 0)
 	/* This can delete NEXT or PREV,
 	   either directly if NEXT is JUMP_LABEL (INSN),
 	   or indirectly through more levels of jumps.  */
 	delete_related_insns (lab);
-      else if (tablejump_p (insn, NULL, &lab_next))
+      else if (tablejump_p (insn->as_an_rtx_base_insn (), NULL, &lab_next))
 	{
+	  /* TODO: remove the cast from the above.  */
 	  /* If we're deleting the tablejump, delete the dispatch table.
 	     We may not be able to kill the label immediately preceding
 	     just yet, as it might be referenced in code leading up to
diff --git a/gcc/reload.c b/gcc/reload.c
index b4d8fd8..b99b13c 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -6293,7 +6293,7 @@ find_reloads_subreg_address (rtx x, int opnum, enum reload_type type,
    Return the rtx that X translates into; usually X, but modified.  */
 
 void
-subst_reloads (rtx insn)
+subst_reloads (rtx_base_insn insn)
 {
   int i;
 
diff --git a/gcc/reload.h b/gcc/reload.h
index 9a7a1a0..9319361 100644
--- a/gcc/reload.h
+++ b/gcc/reload.h
@@ -374,7 +374,7 @@ extern rtx form_sum (enum machine_mode, rtx, rtx);
 
 /* Substitute into the current INSN the registers into which we have reloaded
    the things that need reloading.  */
-extern void subst_reloads (rtx);
+extern void subst_reloads (rtx_base_insn);
 
 /* Make a copy of any replacements being done into X and move those copies
    to locations in Y, a copy of X.  We only look at the highest level of
diff --git a/gcc/rtl.h b/gcc/rtl.h
index a65e31e..c6a4ee6 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -377,6 +377,12 @@ public:
     return as_a <rtx_base_insn_def> (this);
   }
 
+  inline const_rtx_base_insn
+  as_an_rtx_base_insn () const
+  {
+    return as_a <const rtx_base_insn_def> (this);
+  }
+
   inline rtx_debug_insn
   as_an_rtx_debug_insn ()
   {
@@ -716,6 +722,18 @@ is_a_helper <rtx_base_insn_def>::test (rtx rt)
 	  || LABEL_P (rt));
 }
 
+template <>
+template <>
+inline bool
+is_a_helper <const rtx_base_insn_def>::test (const_rtx rt)
+{
+  return (INSN_P (rt)
+	  || NOTE_P (rt)
+	  || JUMP_TABLE_DATA_P (rt)
+	  || BARRIER_P (rt)
+	  || LABEL_P (rt));
+}
+
 /* Predicate yielding nonzero iff X is a return or simple_return.  */
 #define ANY_RETURN_P(X) \
   (GET_CODE (X) == RETURN || GET_CODE (X) == SIMPLE_RETURN)
@@ -2198,7 +2216,7 @@ extern enum rtx_code signed_condition (enum rtx_code);
 extern void mark_jump_label (rtx, rtx, int);
 
 /* In jump.c */
-extern rtx delete_related_insns (rtx);
+extern rtx_base_insn delete_related_insns (rtx);
 
 /* In recog.c  */
 extern rtx *find_constant_term_loc (rtx *);
@@ -2345,7 +2363,8 @@ extern int inequality_comparisons_p (const_rtx);
 extern rtx replace_rtx (rtx, rtx, rtx);
 extern int replace_label (rtx *, void *);
 extern int rtx_referenced_p (rtx, rtx);
-extern bool tablejump_p (const_rtx, rtx *, rtx *);
+extern bool tablejump_p (const_rtx_base_insn, rtx_code_label *,
+			 rtx_jump_table_data *);
 extern int computed_jump_p (const_rtx);
 
 typedef int (*rtx_function) (rtx *, void *);
@@ -2379,7 +2398,7 @@ extern void remove_node_from_expr_list (const_rtx, rtx *);
 extern int loc_mentioned_in_p (rtx *, const_rtx);
 extern rtx_base_insn find_first_parameter_load (rtx_call_insn, rtx);
 extern bool keep_with_call_p (const_rtx);
-extern bool label_is_jump_target_p (const_rtx, const_rtx);
+extern bool label_is_jump_target_p (const_rtx, const_rtx_base_insn);
 extern int insn_rtx_cost (rtx, bool);
 
 /* Given an insn and condition, return a canonical description of
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 6e9910f..6b6bbc2 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -2754,7 +2754,8 @@ rtx_referenced_p (rtx x, rtx body)
    *LABELP and the jump table to *TABLEP.  LABELP and TABLEP may be NULL.  */
 
 bool
-tablejump_p (const_rtx insn, rtx *labelp, rtx *tablep)
+tablejump_p (const_rtx_base_insn insn, rtx_code_label *labelp,
+	     rtx_jump_table_data *tablep)
 {
   rtx label, table;
 
@@ -2767,9 +2768,9 @@ tablejump_p (const_rtx insn, rtx *labelp, rtx *tablep)
       && JUMP_TABLE_DATA_P (table))
     {
       if (labelp)
-	*labelp = label;
+	*labelp = label->as_an_rtx_code_label ();
       if (tablep)
-	*tablep = table;
+	*tablep = table->as_an_rtx_jump_table_data ();
       return true;
     }
   return false;
@@ -3748,17 +3749,18 @@ keep_with_call_p (const_rtx insn)
    not apply to the fallthru case of a conditional jump.  */
 
 bool
-label_is_jump_target_p (const_rtx label, const_rtx jump_insn)
+label_is_jump_target_p (const_rtx label, const_rtx_base_insn jump_insn)
 {
-  rtx tmp = JUMP_LABEL (jump_insn);
+  rtx direct_label = JUMP_LABEL (jump_insn);
+  rtx_jump_table_data jump_table_data;
 
-  if (label == tmp)
+  if (label == direct_label)
     return true;
 
-  if (tablejump_p (jump_insn, NULL, &tmp))
+  if (tablejump_p (jump_insn, NULL, &jump_table_data))
     {
-      rtvec vec = XVEC (PATTERN (tmp),
-			GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC);
+      rtvec vec = XVEC (PATTERN (jump_table_data),
+			GET_CODE (PATTERN (jump_table_data)) == ADDR_DIFF_VEC);
       int i, veclen = GET_NUM_ELEM (vec);
 
       for (i = 0; i < veclen; ++i)
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index c6a19a9..9b5de16 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -490,7 +490,9 @@ default_invalid_within_doloop (const_rtx insn)
   if (CALL_P (insn))
     return "Function call in loop.";
 
-  if (tablejump_p (insn, NULL, NULL) || computed_jump_p (insn))
+  /* TODO: remove the cast in the next line.  */
+  if (tablejump_p (insn->as_an_rtx_base_insn (), NULL, NULL)
+      || computed_jump_p (insn))
     return "Computed branch in the loop.";
 
   return NULL;
-- 
1.7.11.7

