From 5aae6fcd89e5005c061345f6be7622f50bde2583 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 26 Dec 2013 13:35:10 -0500
Subject: [PATCH 001/159] FIXME: introduce rtx_code_label

---
 gcc/basic-block.h   |   2 +-
 gcc/builtins.c      |   4 +-
 gcc/cfgexpand.c     |   6 +--
 gcc/cfgrtl.c        |  11 ++---
 gcc/coretypes.h     |   4 ++
 gcc/dojump.c        | 115 ++++++++++++++++++++++++++++------------------------
 gcc/emit-rtl.c      |   8 ++--
 gcc/expmed.c        |  40 ++++++++++--------
 gcc/expr.c          |  31 +++++++-------
 gcc/expr.h          |  20 +++++----
 gcc/function.h      |   4 +-
 gcc/loop-doloop.c   |   5 ++-
 gcc/loop-unswitch.c |   6 +--
 gcc/optabs.c        |   7 ++--
 gcc/rtl.h           |  56 ++++++++++++++++++++++---
 gcc/stmt.c          |  17 ++++----
 16 files changed, 203 insertions(+), 133 deletions(-)

diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index 58bacc3..b199762 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -802,7 +802,7 @@ extern bitmap compute_idf (bitmap, struct bitmap_head_def *);
 extern basic_block * single_pred_before_succ_order (void);
 
 /* In cfgrtl.c  */
-extern rtx block_label (basic_block);
+extern rtx_code_label block_label (basic_block);
 extern rtx bb_note (basic_block);
 extern bool purge_all_dead_edges (void);
 extern bool purge_dead_edges (basic_block);
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 4f1c818..ff95c11 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1982,12 +1982,12 @@ mathfn_built_in (tree type, enum built_in_function fn)
 static void
 expand_errno_check (tree exp, rtx target)
 {
-  rtx lab = gen_label_rtx ();
+  rtx_code_label lab = gen_label_rtx ();
 
   /* Test the result; if it is NaN, set errno=EDOM because
      the argument was not in the domain.  */
   do_compare_rtx_and_jump (target, target, EQ, 0, GET_MODE (target),
-			   NULL_RTX, NULL_RTX, lab,
+			   NULL_RTX, NULL_RTX_CODE_LABEL, lab,
 			   /* The jump is very likely.  */
 			   REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1));
 
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 853ace2..65aefcb 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -1909,7 +1909,7 @@ static struct pointer_map_t *lab_rtx_for_bb;
 
 /* Returns the label_rtx expression for a label starting basic block BB.  */
 
-static rtx
+static rtx_code_label
 label_rtx_for_bb (basic_block bb ATTRIBUTE_UNUSED)
 {
   gimple_stmt_iterator gsi;
@@ -1922,7 +1922,7 @@ label_rtx_for_bb (basic_block bb ATTRIBUTE_UNUSED)
 
   elt = pointer_map_contains (lab_rtx_for_bb, bb);
   if (elt)
-    return (rtx) *elt;
+    return (rtx_code_label) *elt;
 
   /* Find the tree label if it is present.  */
 
@@ -1941,7 +1941,7 @@ label_rtx_for_bb (basic_block bb ATTRIBUTE_UNUSED)
 
   elt = pointer_map_insert (lab_rtx_for_bb, bb);
   *elt = gen_label_rtx ();
-  return (rtx) *elt;
+  return (rtx_code_label) *elt;
 }
 
 
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 63f44af..bd13e1d 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -970,18 +970,18 @@ rtl_can_merge_blocks (basic_block a, basic_block b)
 /* Return the label in the head of basic block BLOCK.  Create one if it doesn't
    exist.  */
 
-rtx
+rtx_code_label
 block_label (basic_block block)
 {
   if (block == EXIT_BLOCK_PTR_FOR_FN (cfun))
-    return NULL_RTX;
+    return NULL_RTX_CODE_LABEL;
 
   if (!LABEL_P (BB_HEAD (block)))
     {
       BB_HEAD (block) = emit_label_before (gen_label_rtx (), BB_HEAD (block));
     }
 
-  return BB_HEAD (block);
+  return BB_HEAD (block)->as_an_rtx_code_label ();
 }
 
 /* Attempt to perform edge redirection by replacing possibly complex jump
@@ -4902,7 +4902,8 @@ rtl_lv_add_condition_to_bb (basic_block first_head ,
 			    basic_block second_head ATTRIBUTE_UNUSED,
 			    basic_block cond_bb, void *comp_rtx)
 {
-  rtx label, seq, jump;
+  rtx_code_label label;
+  rtx seq, jump;
   rtx op0 = XEXP ((rtx)comp_rtx, 0);
   rtx op1 = XEXP ((rtx)comp_rtx, 1);
   enum rtx_code comp = GET_CODE ((rtx)comp_rtx);
@@ -4918,7 +4919,7 @@ rtl_lv_add_condition_to_bb (basic_block first_head ,
   op0 = force_operand (op0, NULL_RTX);
   op1 = force_operand (op1, NULL_RTX);
   do_compare_rtx_and_jump (op0, op1, comp, 0,
-			   mode, NULL_RTX, NULL_RTX, label, -1);
+			   mode, NULL_RTX, NULL_RTX_CODE_LABEL, label, -1);
   jump = get_last_insn ();
   JUMP_LABEL (jump) = label;
   LABEL_NUSES (label)++;
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 5d60240..753a5e4 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -58,6 +58,10 @@ typedef const struct rtx_def *const_rtx;
 struct rtvec_def;
 typedef struct rtvec_def *rtvec;
 typedef const struct rtvec_def *const_rtvec;
+
+struct rtx_code_label_def;
+typedef struct rtx_code_label_def *rtx_code_label;
+
 union tree_node;
 typedef union tree_node *tree;
 typedef const union tree_node *const_tree;
diff --git a/gcc/dojump.c b/gcc/dojump.c
index 73df6d1..5c6d1f0 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -37,10 +37,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm_p.h"
 
 static bool prefer_and_bit_test (enum machine_mode, int);
-static void do_jump_by_parts_greater (tree, tree, int, rtx, rtx, int);
-static void do_jump_by_parts_equality (tree, tree, rtx, rtx, int);
-static void do_compare_and_jump	(tree, tree, enum rtx_code, enum rtx_code, rtx,
-				 rtx, int);
+static void do_jump_by_parts_greater (tree, tree, int, rtx_code_label, rtx_code_label, int);
+static void do_jump_by_parts_equality (tree, tree, rtx_code_label, rtx_code_label, int);
+static void do_compare_and_jump (tree, tree, enum rtx_code, enum rtx_code,
+				 rtx_code_label, rtx_code_label, int);
 
 /* Invert probability if there is any.  -1 stands for unknown.  */
 
@@ -127,29 +127,29 @@ restore_pending_stack_adjust (saved_pending_stack_adjust *save)
    functions here.  */
 
 void
-jumpifnot (tree exp, rtx label, int prob)
+jumpifnot (tree exp, rtx_code_label label, int prob)
 {
-  do_jump (exp, label, NULL_RTX, inv (prob));
+  do_jump (exp, label, NULL_RTX_CODE_LABEL, inv (prob));
 }
 
 void
-jumpifnot_1 (enum tree_code code, tree op0, tree op1, rtx label, int prob)
+jumpifnot_1 (enum tree_code code, tree op0, tree op1, rtx_code_label label, int prob)
 {
-  do_jump_1 (code, op0, op1, label, NULL_RTX, inv (prob));
+  do_jump_1 (code, op0, op1, label, NULL_RTX_CODE_LABEL, inv (prob));
 }
 
 /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero.  */
 
 void
-jumpif (tree exp, rtx label, int prob)
+jumpif (tree exp, rtx_code_label label, int prob)
 {
-  do_jump (exp, NULL_RTX, label, prob);
+  do_jump (exp, NULL_RTX_CODE_LABEL, label, prob);
 }
 
 void
-jumpif_1 (enum tree_code code, tree op0, tree op1, rtx label, int prob)
+jumpif_1 (enum tree_code code, tree op0, tree op1, rtx_code_label label, int prob)
 {
-  do_jump_1 (code, op0, op1, NULL_RTX, label, prob);
+  do_jump_1 (code, op0, op1, NULL_RTX_CODE_LABEL, label, prob);
 }
 
 /* Used internally by prefer_and_bit_test.  */
@@ -201,10 +201,10 @@ prefer_and_bit_test (enum machine_mode mode, int bitnum)
 
 void
 do_jump_1 (enum tree_code code, tree op0, tree op1,
-	   rtx if_false_label, rtx if_true_label, int prob)
+	   rtx_code_label if_false_label, rtx_code_label if_true_label, int prob)
 {
   enum machine_mode mode;
-  rtx drop_through_label = 0;
+  rtx_code_label drop_through_label = 0;
 
   switch (code)
     {
@@ -357,12 +357,12 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
         if (if_false_label == NULL_RTX)
           {
             drop_through_label = gen_label_rtx ();
-            do_jump (op0, drop_through_label, NULL_RTX, op0_prob);
-            do_jump (op1, NULL_RTX, if_true_label, op1_prob);
+            do_jump (op0, drop_through_label, NULL_RTX_CODE_LABEL, op0_prob);
+            do_jump (op1, NULL_RTX_CODE_LABEL, if_true_label, op1_prob);
           }
         else
           {
-            do_jump (op0, if_false_label, NULL_RTX, op0_prob);
+            do_jump (op0, if_false_label, NULL_RTX_CODE_LABEL, op0_prob);
             do_jump (op1, if_false_label, if_true_label, op1_prob);
           }
         break;
@@ -385,12 +385,12 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
         if (if_true_label == NULL_RTX)
           {
             drop_through_label = gen_label_rtx ();
-            do_jump (op0, NULL_RTX, drop_through_label, op0_prob);
-            do_jump (op1, if_false_label, NULL_RTX, op1_prob);
+            do_jump (op0, NULL_RTX_CODE_LABEL, drop_through_label, op0_prob);
+            do_jump (op1, if_false_label, NULL_RTX_CODE_LABEL, op1_prob);
           }
         else
           {
-            do_jump (op0, NULL_RTX, if_true_label, op0_prob);
+            do_jump (op0, NULL_RTX_CODE_LABEL, if_true_label, op0_prob);
             do_jump (op1, if_false_label, if_true_label, op1_prob);
           }
         break;
@@ -419,14 +419,14 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
    PROB is probability of jump to if_true_label, or -1 if unknown.  */
 
 void
-do_jump (tree exp, rtx if_false_label, rtx if_true_label, int prob)
+do_jump (tree exp, rtx_code_label if_false_label, rtx_code_label if_true_label, int prob)
 {
   enum tree_code code = TREE_CODE (exp);
   rtx temp;
   int i;
   tree type;
   enum machine_mode mode;
-  rtx drop_through_label = 0;
+  rtx_code_label drop_through_label = 0;
 
   switch (code)
     {
@@ -476,7 +476,7 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label, int prob)
 
     case COND_EXPR:
       {
-	rtx label1 = gen_label_rtx ();
+	rtx_code_label label1 = gen_label_rtx ();
 	if (!if_true_label || !if_false_label)
 	  {
 	    drop_through_label = gen_label_rtx ();
@@ -487,7 +487,7 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label, int prob)
 	  }
 
         do_pending_stack_adjust ();
-	do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX, -1);
+	do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX_CODE_LABEL, -1);
 	do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label, prob);
         emit_label (label1);
 	do_jump (TREE_OPERAND (exp, 2), if_false_label, if_true_label, prob);
@@ -531,7 +531,7 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label, int prob)
       if (integer_onep (TREE_OPERAND (exp, 1)))
 	{
 	  tree exp0 = TREE_OPERAND (exp, 0);
-	  rtx set_label, clr_label;
+	  rtx_code_label set_label, clr_label;
 	  int setclr_prob = prob;
 
 	  /* Strip narrowing integral type conversions.  */
@@ -660,11 +660,11 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label, int prob)
 
 static void
 do_jump_by_parts_greater_rtx (enum machine_mode mode, int unsignedp, rtx op0,
-			      rtx op1, rtx if_false_label, rtx if_true_label,
-			      int prob)
+			      rtx op1, rtx_code_label if_false_label,
+			      rtx_code_label if_true_label, int prob)
 {
   int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
-  rtx drop_through_label = 0;
+  rtx_code_label drop_through_label = 0;
   bool drop_through_if_true = false, drop_through_if_false = false;
   enum rtx_code code = GT;
   int i;
@@ -711,7 +711,8 @@ do_jump_by_parts_greater_rtx (enum machine_mode mode, int unsignedp, rtx op0,
 
       /* All but high-order word must be compared as unsigned.  */
       do_compare_rtx_and_jump (op0_word, op1_word, code, (unsignedp || i > 0),
-			       word_mode, NULL_RTX, NULL_RTX, if_true_label,
+			       word_mode, NULL_RTX,
+			       NULL_RTX_CODE_LABEL, if_true_label,
 			       prob);
 
       /* Emit only one comparison for 0.  Do not emit the last cond jump.  */
@@ -720,7 +721,8 @@ do_jump_by_parts_greater_rtx (enum machine_mode mode, int unsignedp, rtx op0,
 
       /* Consider lower words only if these are equal.  */
       do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode,
-			       NULL_RTX, NULL_RTX, if_false_label, inv (prob));
+			       NULL_RTX, NULL_RTX_CODE_LABEL, if_false_label,
+			       inv (prob));
     }
 
   if (!drop_through_if_false)
@@ -736,7 +738,8 @@ do_jump_by_parts_greater_rtx (enum machine_mode mode, int unsignedp, rtx op0,
 
 static void
 do_jump_by_parts_greater (tree treeop0, tree treeop1, int swap,
-			  rtx if_false_label, rtx if_true_label, int prob)
+			  rtx_code_label if_false_label, rtx_code_label if_true_label,
+			  int prob)
 {
   rtx op0 = expand_normal (swap ? treeop1 : treeop0);
   rtx op1 = expand_normal (swap ? treeop0 : treeop1);
@@ -754,7 +757,7 @@ do_jump_by_parts_greater (tree treeop0, tree treeop1, int swap,
 
 static void
 do_jump_by_parts_zero_rtx (enum machine_mode mode, rtx op0,
-			   rtx if_false_label, rtx if_true_label, int prob)
+			   rtx_code_label if_false_label, rtx_code_label if_true_label, int prob)
 {
   int nwords = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
   rtx part;
@@ -787,7 +790,7 @@ do_jump_by_parts_zero_rtx (enum machine_mode mode, rtx op0,
   for (i = 0; i < nwords; i++)
     do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
                              const0_rtx, EQ, 1, word_mode, NULL_RTX,
-			     if_false_label, NULL_RTX, prob);
+			     if_false_label, NULL_RTX_CODE_LABEL, prob);
 
   if (if_true_label)
     emit_jump (if_true_label);
@@ -798,12 +801,13 @@ do_jump_by_parts_zero_rtx (enum machine_mode mode, rtx op0,
 
 /* Test for the equality of two RTX expressions OP0 and OP1 in mode MODE,
    where MODE is an integer mode too wide to be compared with one insn.
-   Either (but not both) of IF_TRUE_LABEL and IF_FALSE_LABEL may be NULL_RTX
-   to indicate drop through.  */
+   Either (but not both) of IF_TRUE_LABEL and IF_FALSE_LABEL may be
+   NULL_RTX_CODE_LABEL to indicate drop through.  */
 
 static void
 do_jump_by_parts_equality_rtx (enum machine_mode mode, rtx op0, rtx op1,
-			       rtx if_false_label, rtx if_true_label, int prob)
+			       rtx_code_label if_false_label,
+			       rtx_code_label if_true_label, int prob)
 {
   int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
   rtx drop_through_label = 0;
@@ -829,7 +833,7 @@ do_jump_by_parts_equality_rtx (enum machine_mode mode, rtx op0, rtx op1,
     do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
                              operand_subword_force (op1, i, mode),
                              EQ, 0, word_mode, NULL_RTX,
-			     if_false_label, NULL_RTX, prob);
+			     if_false_label, NULL_RTX_CODE_LABEL, prob);
 
   if (if_true_label)
     emit_jump (if_true_label);
@@ -841,8 +845,9 @@ do_jump_by_parts_equality_rtx (enum machine_mode mode, rtx op0, rtx op1,
    with one insn, test the comparison and jump to the appropriate label.  */
 
 static void
-do_jump_by_parts_equality (tree treeop0, tree treeop1, rtx if_false_label,
-			   rtx if_true_label, int prob)
+do_jump_by_parts_equality (tree treeop0, tree treeop1,
+			   rtx_code_label if_false_label, rtx_code_label if_true_label,
+			   int prob)
 {
   rtx op0 = expand_normal (treeop0);
   rtx op1 = expand_normal (treeop1);
@@ -937,11 +942,11 @@ split_comparison (enum rtx_code code, enum machine_mode mode,
 
 void
 do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
-			 enum machine_mode mode, rtx size, rtx if_false_label,
-			 rtx if_true_label, int prob)
+			 enum machine_mode mode, rtx size,
+			 rtx_code_label if_false_label, rtx_code_label if_true_label,
+			 int prob)
 {
-  rtx tem;
-  rtx dummy_label = NULL_RTX;
+  rtx_code_label dummy_label = NULL_RTX_CODE_LABEL;
 
   /* Reverse the comparison if that is safe and we want to jump if it is
      false.  Also convert to the reverse comparison if the target can
@@ -963,7 +968,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
       if (can_compare_p (rcode, mode, ccp_jump)
 	  || (code == ORDERED && ! can_compare_p (ORDERED, mode, ccp_jump)))
 	{
-          tem = if_true_label;
+          rtx_code_label tem = if_true_label;
           if_true_label = if_false_label;
           if_false_label = tem;
 	  code = rcode;
@@ -976,7 +981,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
 
   if (swap_commutative_operands_p (op0, op1))
     {
-      tem = op0;
+      rtx tem = op0;
       op0 = op1;
       op1 = tem;
       code = swap_condition (code);
@@ -984,14 +989,16 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
 
   do_pending_stack_adjust ();
 
+  rtx tem;
+
   code = unsignedp ? unsigned_condition (code) : code;
   if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode,
 						 op0, op1)))
     {
       if (CONSTANT_P (tem))
 	{
-	  rtx label = (tem == const0_rtx || tem == CONST0_RTX (mode))
-		      ? if_false_label : if_true_label;
+	  rtx_code_label label = (tem == const0_rtx || tem == CONST0_RTX (mode))
+		            ? if_false_label : if_true_label;
 	  if (label)
 	    emit_jump (label);
 	  return;
@@ -1105,7 +1112,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
 	    {
 	      if (and_them)
 		{
-		  rtx dest_label;
+		  rtx_code_label dest_label;
 		  /* If we only jump if true, just bypass the second jump.  */
 		  if (! if_false_label)
 		    {
@@ -1116,11 +1123,13 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
 		  else
 		    dest_label = if_false_label;
                   do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode,
-					   size, dest_label, NULL_RTX, prob);
+					   size, dest_label, NULL_RTX_CODE_LABEL,
+					   prob);
 		}
               else
                 do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode,
-					 size, NULL_RTX, if_true_label, prob);
+					 size, NULL_RTX_CODE_LABEL, if_true_label,
+					 prob);
 	    }
 	}
 
@@ -1136,7 +1145,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
 
 /* Generate code for a comparison expression EXP (including code to compute
    the values to be compared) and a conditional jump to IF_FALSE_LABEL and/or
-   IF_TRUE_LABEL.  One of the labels can be NULL_RTX, in which case the
+   IF_TRUE_LABEL.  One of the labels can be NULL_RTX_CODE_LABEL, in which case the
    generated code will drop through.
    SIGNED_CODE should be the rtx operation for this comparison for
    signed data; UNSIGNED_CODE, likewise for use if data is unsigned.
@@ -1146,8 +1155,8 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
 
 static void
 do_compare_and_jump (tree treeop0, tree treeop1, enum rtx_code signed_code,
-		     enum rtx_code unsigned_code, rtx if_false_label,
-		     rtx if_true_label, int prob)
+		     enum rtx_code unsigned_code, rtx_code_label if_false_label,
+		     rtx_code_label if_true_label, int prob)
 {
   rtx op0, op1;
   tree type;
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index d7fa3a5..dfe7bb4 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -2377,11 +2377,11 @@ set_mem_attrs_for_spill (rtx mem)
 
 /* Return a newly created CODE_LABEL rtx with a unique label number.  */
 
-rtx
+rtx_code_label
 gen_label_rtx (void)
 {
   return gen_rtx_CODE_LABEL (VOIDmode, 0, NULL_RTX, NULL_RTX,
-			     NULL, label_num++, NULL);
+			     NULL, label_num++, NULL)->as_an_rtx_code_label ();
 }
 
 /* For procedure integration.  */
@@ -4253,8 +4253,8 @@ emit_barrier_before (rtx before)
 
 /* Emit the label LABEL before the insn BEFORE.  */
 
-rtx
-emit_label_before (rtx label, rtx before)
+rtx_code_label
+emit_label_before (rtx_code_label label, rtx before)
 {
   gcc_checking_assert (INSN_UID (label) == 0);
   INSN_UID (label) = cur_insn_uid++;
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 8e63cd5..612ea35 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -60,7 +60,8 @@ static rtx mask_rtx (enum machine_mode, int, int, int);
 static rtx lshift_value (enum machine_mode, unsigned HOST_WIDE_INT, int);
 static rtx extract_split_bit_field (rtx, unsigned HOST_WIDE_INT,
 				    unsigned HOST_WIDE_INT, int);
-static void do_cmp_and_jump (rtx, rtx, enum rtx_code, enum machine_mode, rtx);
+static void do_cmp_and_jump (rtx, rtx, enum rtx_code, enum machine_mode,
+			     rtx_code_label);
 static rtx expand_smod_pow2 (enum machine_mode, rtx, HOST_WIDE_INT);
 static rtx expand_sdiv_pow2 (enum machine_mode, rtx, HOST_WIDE_INT);
 
@@ -3611,7 +3612,8 @@ static rtx
 expand_smod_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d)
 {
   unsigned HOST_WIDE_INT masklow, maskhigh;
-  rtx result, temp, shift, label;
+  rtx result, temp, shift;
+  rtx_code_label label;
   int logd;
 
   logd = floor_log2 (d);
@@ -3714,7 +3716,8 @@ expand_smod_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d)
 static rtx
 expand_sdiv_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d)
 {
-  rtx temp, label;
+  rtx temp;
+  rtx_code_label label;
   int logd;
 
   logd = floor_log2 (d);
@@ -4448,7 +4451,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
 	    /* This could be computed with a branch-less sequence.
 	       Save that for later.  */
 	    rtx tem;
-	    rtx label = gen_label_rtx ();
+	    rtx_code_label label = gen_label_rtx ();
 	    do_cmp_and_jump (remainder, const0_rtx, EQ, compute_mode, label);
 	    tem = expand_binop (compute_mode, xor_optab, op0, op1,
 				NULL_RTX, 0, OPTAB_WIDEN);
@@ -4462,7 +4465,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
 	/* No luck with division elimination or divmod.  Have to do it
 	   by conditionally adjusting op0 *and* the result.  */
 	{
-	  rtx label1, label2, label3, label4, label5;
+	  rtx_code_label label1, label2, label3, label4, label5;
 	  rtx adjusted_op0;
 	  rtx tem;
 
@@ -4523,7 +4526,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
 				      compute_mode, 1, 1);
 		if (t3 == 0)
 		  {
-		    rtx lab;
+		    rtx_code_label lab;
 		    lab = gen_label_rtx ();
 		    do_cmp_and_jump (t2, const0_rtx, EQ, compute_mode, lab);
 		    expand_inc (t1, const1_rtx);
@@ -4563,7 +4566,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
 	      {
 		/* This could be computed with a branch-less sequence.
 		   Save that for later.  */
-		rtx label = gen_label_rtx ();
+		rtx_code_label label = gen_label_rtx ();
 		do_cmp_and_jump (remainder, const0_rtx, EQ,
 				 compute_mode, label);
 		expand_inc (quotient, const1_rtx);
@@ -4575,7 +4578,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
 	    /* No luck with division elimination or divmod.  Have to do it
 	       by conditionally adjusting op0 *and* the result.  */
 	    {
-	      rtx label1, label2;
+	      rtx_code_label label1, label2;
 	      rtx adjusted_op0, tem;
 
 	      quotient = gen_reg_rtx (compute_mode);
@@ -4620,7 +4623,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
 				      compute_mode, 1, 1);
 		if (t3 == 0)
 		  {
-		    rtx lab;
+		    rtx_code_label lab;
 		    lab = gen_label_rtx ();
 		    do_cmp_and_jump (t2, const0_rtx, EQ, compute_mode, lab);
 		    expand_inc (t1, const1_rtx);
@@ -4660,7 +4663,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
 		/* This could be computed with a branch-less sequence.
 		   Save that for later.  */
 		rtx tem;
-		rtx label = gen_label_rtx ();
+		rtx_code_label label = gen_label_rtx ();
 		do_cmp_and_jump (remainder, const0_rtx, EQ,
 				 compute_mode, label);
 		tem = expand_binop (compute_mode, xor_optab, op0, op1,
@@ -4675,7 +4678,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
 	    /* No luck with division elimination or divmod.  Have to do it
 	       by conditionally adjusting op0 *and* the result.  */
 	    {
-	      rtx label1, label2, label3, label4, label5;
+	      rtx_code_label label1, label2, label3, label4, label5;
 	      rtx adjusted_op0;
 	      rtx tem;
 
@@ -4750,7 +4753,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
 	if (unsignedp)
 	  {
 	    rtx tem;
-	    rtx label;
+	    rtx_code_label label;
 	    label = gen_label_rtx ();
 	    quotient = gen_reg_rtx (compute_mode);
 	    remainder = gen_reg_rtx (compute_mode);
@@ -4773,7 +4776,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
 	else
 	  {
 	    rtx abs_rem, abs_op1, tem, mask;
-	    rtx label;
+	    rtx_code_label label;
 	    label = gen_label_rtx ();
 	    quotient = gen_reg_rtx (compute_mode);
 	    remainder = gen_reg_rtx (compute_mode);
@@ -5723,7 +5726,8 @@ rtx
 emit_store_flag_force (rtx target, enum rtx_code code, rtx op0, rtx op1,
 		       enum machine_mode mode, int unsignedp, int normalizep)
 {
-  rtx tem, label;
+  rtx tem;
+  rtx_code_label label;
   rtx trueval, falseval;
 
   /* First see if emit_store_flag can do the job.  */
@@ -5745,7 +5749,7 @@ emit_store_flag_force (rtx target, enum rtx_code code, rtx op0, rtx op1,
     {
       label = gen_label_rtx ();
       do_compare_rtx_and_jump (target, const0_rtx, EQ, unsignedp,
-			       mode, NULL_RTX, NULL_RTX, label, -1);
+			       mode, NULL_RTX, NULL_RTX_CODE_LABEL, label, -1);
       emit_move_insn (target, trueval);
       emit_label (label);
       return target;
@@ -5783,7 +5787,7 @@ emit_store_flag_force (rtx target, enum rtx_code code, rtx op0, rtx op1,
   emit_move_insn (target, trueval);
   label = gen_label_rtx ();
   do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, NULL_RTX,
-			   NULL_RTX, label, -1);
+			   NULL_RTX_CODE_LABEL, label, -1);
 
   emit_move_insn (target, falseval);
   emit_label (label);
@@ -5797,9 +5801,9 @@ emit_store_flag_force (rtx target, enum rtx_code code, rtx op0, rtx op1,
 
 static void
 do_cmp_and_jump (rtx arg1, rtx arg2, enum rtx_code op, enum machine_mode mode,
-		 rtx label)
+		 rtx_code_label label)
 {
   int unsignedp = (op == LTU || op == LEU || op == GTU || op == GEU);
   do_compare_rtx_and_jump (arg1, arg2, op, unsignedp, mode,
-			   NULL_RTX, NULL_RTX, label, -1);
+			   NULL_RTX, NULL_RTX_CODE_LABEL, label, -1);
 }
diff --git a/gcc/expr.c b/gcc/expr.c
index 2a13d8f..e1ddf0b 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -5179,7 +5179,7 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
 	 side.  This avoids the creation of unnecessary temporaries.
 	 For non-BLKmode, it is more efficient not to do this.  */
 
-      rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
+      rtx_code_label lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
 
       do_pending_stack_adjust ();
       NO_DEFER_POP;
@@ -6201,8 +6201,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
 		  }
 		else
 		  {
-		    rtx loop_start = gen_label_rtx ();
-		    rtx loop_end = gen_label_rtx ();
+		    rtx_code_label loop_start = gen_label_rtx ();
+		    rtx_code_label loop_end = gen_label_rtx ();
 		    tree exit_cond;
 
 		    expand_normal (hi_index);
@@ -8029,6 +8029,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 		    enum expand_modifier modifier)
 {
   rtx op0, op1, op2, temp;
+  rtx_code_label op_label0, op_label1;
   tree type;
   int unsignedp;
   enum machine_mode mode;
@@ -8829,8 +8830,8 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 
 	temp = gen_label_rtx ();
 	do_compare_rtx_and_jump (target, cmpop1, comparison_code,
-				 unsignedp, mode, NULL_RTX, NULL_RTX, temp,
-				 -1);
+				 unsignedp, mode, NULL_RTX, NULL_RTX_CODE_LABEL,
+				 (rtx_code_label )temp, -1);
       }
       emit_move_insn (target, op1);
       emit_label (temp);
@@ -8928,15 +8929,15 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 
       emit_move_insn (target, const0_rtx);
 
-      op1 = gen_label_rtx ();
-      jumpifnot_1 (code, treeop0, treeop1, op1, -1);
+      op_label1 = gen_label_rtx ();
+      jumpifnot_1 (code, treeop0, treeop1, op_label1, -1);
 
       if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
 	emit_move_insn (target, constm1_rtx);
       else
 	emit_move_insn (target, const1_rtx);
 
-      emit_label (op1);
+      emit_label (op_label1);
       return target;
 
     case COMPLEX_EXPR:
@@ -9161,21 +9162,21 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 
       do_pending_stack_adjust ();
       NO_DEFER_POP;
-      op0 = gen_label_rtx ();
-      op1 = gen_label_rtx ();
-      jumpifnot (treeop0, op0, -1);
+      op_label0 = gen_label_rtx ();
+      op_label1 = gen_label_rtx ();
+      jumpifnot (treeop0, op_label0, -1);
       store_expr (treeop1, temp,
 		  modifier == EXPAND_STACK_PARM,
 		  false);
 
-      emit_jump_insn (gen_jump (op1));
+      emit_jump_insn (gen_jump (op_label1));
       emit_barrier ();
-      emit_label (op0);
+      emit_label (op_label0);
       store_expr (treeop2, temp,
 		  modifier == EXPAND_STACK_PARM,
 		  false);
 
-      emit_label (op1);
+      emit_label (op_label1);
       OK_DEFER_POP;
       return temp;
 
@@ -10493,7 +10494,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 	    && integer_onep (DECL_SIZE (TREE_OPERAND (lhs, 1)))
 	    && integer_onep (DECL_SIZE (TREE_OPERAND (TREE_OPERAND (rhs, 1), 1))))
 	  {
-	    rtx label = gen_label_rtx ();
+	    rtx_code_label label = gen_label_rtx ();
 	    int value = TREE_CODE (rhs) == BIT_IOR_EXPR;
 	    do_jump (TREE_OPERAND (rhs, 1),
 		     value ? label : 0,
diff --git a/gcc/expr.h b/gcc/expr.h
index e734ef4..de19a4e 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -500,20 +500,22 @@ extern void restore_pending_stack_adjust (saved_pending_stack_adjust *);
 extern tree string_constant (tree, tree *);
 
 /* Generate code to evaluate EXP and jump to LABEL if the value is zero.  */
-extern void jumpifnot (tree, rtx, int);
-extern void jumpifnot_1 (enum tree_code, tree, tree, rtx, int);
+extern void jumpifnot (tree, rtx_code_label, int);
+extern void jumpifnot_1 (enum tree_code, tree, tree, rtx_code_label, int);
 
 /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero.  */
-extern void jumpif (tree, rtx, int);
-extern void jumpif_1 (enum tree_code, tree, tree, rtx, int);
+extern void jumpif (tree, rtx_code_label, int);
+extern void jumpif_1 (enum tree_code, tree, tree, rtx_code_label, int);
 
 /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
    the result is zero, or IF_TRUE_LABEL if the result is one.  */
-extern void do_jump (tree, rtx, rtx, int);
-extern void do_jump_1 (enum tree_code, tree, tree, rtx, rtx, int);
+extern void do_jump (tree, rtx_code_label, rtx_code_label, int);
+extern void do_jump_1 (enum tree_code, tree, tree, rtx_code_label, rtx_code_label,
+		       int);
 
 extern void do_compare_rtx_and_jump (rtx, rtx, enum rtx_code, int,
-				     enum machine_mode, rtx, rtx, rtx, int);
+				     enum machine_mode, rtx, rtx_code_label,
+				     rtx_code_label, int);
 
 /* Two different ways of generating switch statements.  */
 extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx, int);
@@ -557,12 +559,12 @@ extern void locate_and_pad_parm (enum machine_mode, tree, int, int, int,
 				 struct locate_and_pad_arg_data *);
 
 /* Return the CODE_LABEL rtx for a LABEL_DECL, creating it if necessary.  */
-extern rtx label_rtx (tree);
+extern rtx_code_label label_rtx (tree);
 
 /* As label_rtx, but additionally the label is placed on the forced label
    list of its containing function (i.e. it is treated as reachable even
    if how is not obvious).  */
-extern rtx force_label_rtx (tree);
+extern rtx_code_label force_label_rtx (tree);
 
 /* Return an rtx like arg but sans any constant terms.
    Returns the original rtx if it has no constant terms.
diff --git a/gcc/function.h b/gcc/function.h
index c00bfe2..f1b3918 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -271,12 +271,12 @@ struct GTY(()) rtl_data {
   /* Label that will go on function epilogue.
      Jumping to this label serves as a "return" instruction
      on machines which require execution of the epilogue on all returns.  */
-  rtx x_return_label;
+  rtx_code_label x_return_label;
 
   /* Label that will go on the end of function epilogue.
      Jumping to this label serves as a "naked return" instruction
      on machines which require execution of the epilogue on all returns.  */
-  rtx x_naked_return_label;
+  rtx_code_label x_naked_return_label;
 
   /* List (chain of EXPR_LISTs) of all stack slots in this function.
      Made for the sake of unshare_all_rtl.  */
diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c
index 24e0201..ca435fe 100644
--- a/gcc/loop-doloop.c
+++ b/gcc/loop-doloop.c
@@ -336,7 +336,8 @@ cleanup:
 static bool
 add_test (rtx cond, edge *e, basic_block dest)
 {
-  rtx seq, jump, label;
+  rtx seq, jump;
+  rtx_code_label label;
   enum machine_mode mode;
   rtx op0 = XEXP (cond, 0), op1 = XEXP (cond, 1);
   enum rtx_code code = GET_CODE (cond);
@@ -351,7 +352,7 @@ add_test (rtx cond, edge *e, basic_block dest)
   op1 = force_operand (op1, NULL_RTX);
   label = block_label (dest);
   do_compare_rtx_and_jump (op0, op1, code, 0, mode, NULL_RTX,
-			   NULL_RTX, label, -1);
+			   NULL_RTX_CODE_LABEL, label, -1);
 
   jump = get_last_insn ();
   if (!jump || !JUMP_P (jump))
diff --git a/gcc/loop-unswitch.c b/gcc/loop-unswitch.c
index c8f1281..827dc44 100644
--- a/gcc/loop-unswitch.c
+++ b/gcc/loop-unswitch.c
@@ -86,8 +86,8 @@ static rtx may_unswitch_on (basic_block, struct loop *, rtx *);
    in order to create a jump.  */
 
 rtx
-compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp, rtx label, int prob,
-		      rtx cinsn)
+compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp, rtx_code_label label,
+		      int prob, rtx cinsn)
 {
   rtx seq, jump, cond;
   enum machine_mode mode;
@@ -120,7 +120,7 @@ compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp, rtx label, int prob,
       op0 = force_operand (op0, NULL_RTX);
       op1 = force_operand (op1, NULL_RTX);
       do_compare_rtx_and_jump (op0, op1, comp, 0,
-			       mode, NULL_RTX, NULL_RTX, label, -1);
+			       mode, NULL_RTX, NULL_RTX_CODE_LABEL, label, -1);
       jump = get_last_insn ();
       gcc_assert (JUMP_P (jump));
       JUMP_LABEL (jump) = label;
diff --git a/gcc/optabs.c b/gcc/optabs.c
index e035af1..5515c63 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -1008,7 +1008,7 @@ expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab,
 			 unsigned HOST_WIDE_INT shift_mask)
 {
   rtx superword_op1, tmp, cmp1, cmp2;
-  rtx subword_label, done_label;
+  rtx_code_label subword_label, done_label;
   enum rtx_code cmp_code;
 
   /* See if word-mode shifts by BITS_PER_WORD...BITS_PER_WORD * 2 - 1 will
@@ -3447,7 +3447,8 @@ rtx
 expand_abs (enum machine_mode mode, rtx op0, rtx target,
 	    int result_unsignedp, int safe)
 {
-  rtx temp, op1;
+  rtx temp;
+  rtx_code_label op1;
 
   if (! flag_trapv)
     result_unsignedp = 1;
@@ -3476,7 +3477,7 @@ expand_abs (enum machine_mode mode, rtx op0, rtx target,
   NO_DEFER_POP;
 
   do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
-			   NULL_RTX, NULL_RTX, op1, -1);
+			   NULL_RTX, NULL_RTX_CODE_LABEL, op1, -1);
 
   op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
                      target, target, 0);
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 247a0d0..6cfcee9 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "alias.h"
 #include "hashtab.h"
 #include "flags.h"
+#include "is-a.h"
 
 /* Value used by some passes to "recognize" noop moves as valid
  instructions.  */
@@ -251,8 +252,24 @@ struct GTY(()) object_block {
 
 /* RTL expression ("rtx").  */
 
-struct GTY((chain_next ("RTX_NEXT (&%h)"),
-	    chain_prev ("RTX_PREV (&%h)"), variable_size)) rtx_def {
+/* The GTY "desc" and "tag" options below are a kludge: we need a desc
+   field for for gengtype to recognize that inheritance is occurring,
+   so that all subclasses are redirected to the traversal hook for the
+   base class.
+   However, all of the fields are in the base class, and special-casing
+   is at work.  Hence we use desc and tag of 0, generating a switch
+   statement of the form:
+     switch (0)
+       {
+       case 0: // all the work happens here
+       }
+   in order to work with the existing special-casing in gengtype.  */
+
+struct GTY((desc("0"), tag("0"),
+	    chain_next ("RTX_NEXT (&%h)"),
+	    chain_prev ("RTX_PREV (&%h)"), variable_size))
+  rtx_def
+{
   /* The kind of expression this is.  */
   ENUM_BITFIELD(rtx_code) code: 16;
 
@@ -345,8 +362,36 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
     struct real_value rv;
     struct fixed_value fv;
   } GTY ((special ("rtx_def"), desc ("GET_CODE (&%0)"))) u;
+
+public:
+  /* Downcasting methods, where the expression *must* be of a given kind.
+     The cast is checked in a checked build, and a no-op in an
+     unchecked build.  */
+  inline rtx_code_label
+  as_an_rtx_code_label ()
+  {
+    return as_a <rtx_code_label_def> (this);
+  }
+};
+
+
+/* An expression with the invariant that:
+     GET_CODE (X) == CODE_LABEL
+   i.e. a "code_label".  */
+
+struct GTY(()) rtx_code_label_def : public rtx_def
+{
+  /* No extra fields, but adds invariant: (GET_CODE (X) == CODE_LABEL).  */
 };
 
+template <>
+template <>
+inline bool
+is_a_helper <rtx_code_label_def>::test (rtx rt)
+{
+  return rt->code == CODE_LABEL;
+}
+
 /* The size in bytes of an rtx header (code, mode and flags).  */
 #define RTX_HDR_SIZE offsetof (struct rtx_def, u)
 
@@ -354,6 +399,7 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
 #define RTX_CODE_SIZE(CODE) rtx_code_size[CODE]
 
 #define NULL_RTX (rtx) 0
+#define NULL_RTX_CODE_LABEL (rtx_code_label) 0
 
 /* The "next" and "previous" RTX, relative to this one.  */
 
@@ -1789,7 +1835,7 @@ extern rtx gen_reg_rtx (enum machine_mode);
 extern rtx gen_rtx_REG_offset (rtx, enum machine_mode, unsigned int, int);
 extern rtx gen_reg_rtx_offset (rtx, enum machine_mode, int);
 extern rtx gen_reg_rtx_and_attrs (rtx);
-extern rtx gen_label_rtx (void);
+extern rtx_code_label gen_label_rtx (void);
 extern rtx gen_lowpart_common (enum machine_mode, rtx);
 
 /* In cse.c */
@@ -1866,7 +1912,7 @@ extern rtx emit_debug_insn_before (rtx, rtx);
 extern rtx emit_debug_insn_before_noloc (rtx, rtx);
 extern rtx emit_debug_insn_before_setloc (rtx, rtx, int);
 extern rtx emit_barrier_before (rtx);
-extern rtx emit_label_before (rtx, rtx);
+extern rtx_code_label emit_label_before (rtx_code_label, rtx);
 extern rtx emit_note_before (enum insn_note, rtx);
 extern rtx emit_insn_after (rtx, rtx);
 extern rtx emit_insn_after_noloc (rtx, rtx, basic_block);
@@ -2745,7 +2791,7 @@ extern void get_mode_bounds (enum machine_mode, int, enum machine_mode,
 
 /* In loop-unswitch.c  */
 extern rtx reversed_condition (rtx);
-extern rtx compare_and_jump_seq (rtx, rtx, enum rtx_code, rtx, int, rtx);
+extern rtx compare_and_jump_seq (rtx, rtx, enum rtx_code, rtx_code_label, int, rtx);
 
 /* In loop-iv.c  */
 extern rtx canon_condition (rtx);
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 0d891b4..fad93ed 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -119,28 +119,29 @@ static void emit_case_nodes (rtx, case_node_ptr, rtx, int, tree);
 /* Return the rtx-label that corresponds to a LABEL_DECL,
    creating it if necessary.  */
 
-rtx
+rtx_code_label
 label_rtx (tree label)
 {
   gcc_assert (TREE_CODE (label) == LABEL_DECL);
 
   if (!DECL_RTL_SET_P (label))
     {
-      rtx r = gen_label_rtx ();
+      rtx_code_label r = gen_label_rtx ();
       SET_DECL_RTL (label, r);
       if (FORCED_LABEL (label) || DECL_NONLOCAL (label))
 	LABEL_PRESERVE_P (r) = 1;
     }
 
-  return DECL_RTL (label);
+  /* FIXME: making this typesafe requires making tree labels typesafe.  */
+  return (rtx_code_label)DECL_RTL (label);
 }
 
 /* As above, but also put it on the forced-reference list of the
    function that contains it.  */
-rtx
+rtx_code_label
 force_label_rtx (tree label)
 {
-  rtx ref = label_rtx (label);
+  rtx_code_label ref = label_rtx (label);
   tree function = decl_function_context (label);
 
   gcc_assert (function);
@@ -730,12 +731,12 @@ expand_naked_return (void)
 /* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE. PROB
    is the probability of jumping to LABEL.  */
 static void
-do_jump_if_equal (enum machine_mode mode, rtx op0, rtx op1, rtx label,
+do_jump_if_equal (enum machine_mode mode, rtx op0, rtx op1, rtx_code_label label,
 		  int unsignedp, int prob)
 {
   gcc_assert (prob <= REG_BR_PROB_BASE);
   do_compare_rtx_and_jump (op0, op1, EQ, unsignedp, mode,
-			   NULL_RTX, NULL_RTX, label, prob);
+			   NULL_RTX, NULL_RTX_CODE_LABEL, label, prob);
 }
 
 /* Do the insertion of a case label into case_list.  The labels are
@@ -1342,7 +1343,7 @@ expand_sjlj_dispatch_table (rtx dispatch_index,
       for (int i = 0; i < ncases; i++)
         {
 	  tree elt = dispatch_table[i];
-	  rtx lab = label_rtx (CASE_LABEL (elt));
+	  rtx_code_label lab = label_rtx (CASE_LABEL (elt));
 	  do_jump_if_equal (index_mode, index, zero, lab, 0, -1);
 	  force_expand_binop (index_mode, sub_optab,
 			      index, CONST1_RTX (index_mode),
-- 
1.7.11.7

