From 6fe5b643133869ad3f81e8ee7d81983ec6620053 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 24 Jun 2014 20:41:08 -0400
Subject: [PATCH 175/249] Add rtx_jump_table_data::get_labels method

See e.g. stmt.c:emit_case_dispatch_table for how the rtvec is set up.

gcc/
	* rtl.h (rtx_jump_table_data::get_labels): New method.
	* cfgbuild.c (make_edges): Replace hand-coded lookup of labels
	with use of the new rtx_jump_table_data::get_labels method.
	(purge_dead_tablejump_edges): Strengthen param "table" from rtx
	to rtx_jump_table_data *.  Simplify by using get_labels method.
	* cfgrtl.c (delete_insn): Replace use of JUMP_TABLE_DATA_P with
	a dyn_cast, introducing local "table", using it to replace
	label-lookup logic with a get_labels method call.
	(patch_jump_insn): Simplify using get_labels method.
	* dwarf2cfi.c (create_trace_edges): Likewise.
	* rtlanal.c (label_is_jump_target_p): Likewise.
---
 gcc/cfgbuild.c  | 14 +++-----------
 gcc/cfgrtl.c    | 14 +++++---------
 gcc/dwarf2cfi.c |  5 +----
 gcc/rtl.h       | 24 ++++++++++++++++++++++++
 gcc/rtlanal.c   |  3 +--
 5 files changed, 34 insertions(+), 26 deletions(-)

diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c
index 8bbf325..3cd782c 100644
--- a/gcc/cfgbuild.c
+++ b/gcc/cfgbuild.c
@@ -263,14 +263,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);
@@ -398,7 +393,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_insn *insn = BB_END (bb);
   rtx tmp;
@@ -407,10 +402,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 a31214f..e8990c4 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -197,16 +197,15 @@ delete_insn (rtx insn)
       remove_note (insn, note);
     }
 
-  if (JUMP_TABLE_DATA_P (insn))
+  if (rtx_jump_table_data *table = dyn_cast <rtx_jump_table_data *> (insn))
     {
-      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
@@ -1187,10 +1186,7 @@ patch_jump_insn (rtx_insn *insn, rtx_insn *old_label, basic_block new_bb)
 
       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 7abe48c..bcfc9dd 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -2298,10 +2298,7 @@ create_trace_edges (rtx insn)
 
       if (tablejump_p (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 84ecbfc..1b06430 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -490,6 +490,21 @@ class GTY(()) rtx_jump_table_data : public rtx_insn
      This is an instance of:
        DEF_RTL_EXPR(JUMP_TABLE_DATA, "jump_table_data", "uuBe0000", RTX_INSN)
      from rtl.def.  */
+
+public:
+
+  /* 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.
+
+     This method gets the underlying vec.  */
+
+  inline rtvec get_labels () const;
 };
 
 class GTY(()) rtx_barrier : public rtx_insn
@@ -1226,6 +1241,15 @@ inline rtx& SET_NEXT_INSN (rtx insn)
    -1 means this instruction has not been recognized yet.  */
 #define INSN_CODE(INSN) XINT (INSN, 5)
 
+inline rtvec rtx_jump_table_data::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 13f9b78..9481d52 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -3801,8 +3801,7 @@ label_is_jump_target_p (const_rtx label, const_rtx jump_insn)
 
   if (tablejump_p (jump_insn, NULL, &table))
     {
-      rtvec vec = XVEC (PATTERN (table),
-			GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC);
+      rtvec vec = table->get_labels ();
       int i, veclen = GET_NUM_ELEM (vec);
 
       for (i = 0; i < veclen; ++i)
-- 
1.8.5.3

