diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c
index 6f0d69e..642f57e 100644
--- a/gcc/cfgbuild.c
+++ b/gcc/cfgbuild.c
@@ -216,7 +216,7 @@ make_edges (basic_block min, basic_block max, int update_p)
   /* Heavy use of computed goto in machine-generated code can lead to
      nearly fully-connected CFGs.  In that case we spend a significant
      amount of time searching the edge lists for duplicates.  */
-  if (forced_labels || cfun->cfg->max_jumptable_ents > 100)
+  if (!VEC_empty (rtx, forced_labels) || cfun->cfg->max_jumptable_ents > 100)
     edge_cache = sbitmap_alloc (last_basic_block);
 
   /* By nature of the way these get numbered, ENTRY_BLOCK_PTR->next_bb block
@@ -296,8 +296,9 @@ make_edges (basic_block min, basic_block max, int update_p)
 	     everything on the forced_labels list.  */
 	  else if (computed_jump_p (insn))
 	    {
-	      for (x = forced_labels; x; x = XEXP (x, 1))
-		make_label_edge (edge_cache, bb, XEXP (x, 0), EDGE_ABNORMAL);
+	      unsigned int ix;
+	      FOR_EACH_VEC_ELT_REVERSE (rtx, forced_labels, ix, x)
+		make_label_edge (edge_cache, bb, x, EDGE_ABNORMAL);
 	    }
 
 	  /* Returns create an exit out.  */
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index c450ca0..e01b7bb 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -65,7 +65,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "df.h"
 
 static int can_delete_note_p (const_rtx);
-static int can_delete_label_p (const_rtx);
+static bool can_delete_label_p (const_rtx);
 static basic_block rtl_split_edge (edge);
 static bool rtl_move_block_after (basic_block, basic_block);
 static int rtl_verify_flow_info (void);
@@ -101,13 +101,20 @@ can_delete_note_p (const_rtx note)
 
 /* True if a given label can be deleted.  */
 
-static int
+static bool
 can_delete_label_p (const_rtx label)
 {
-  return (!LABEL_PRESERVE_P (label)
-	  /* User declared labels must be preserved.  */
-	  && LABEL_NAME (label) == 0
-	  && !in_expr_list_p (forced_labels, label));
+  rtx x;
+  unsigned int ix;
+
+  if (LABEL_PRESERVE_P (label) || LABEL_NAME (label) != 0)
+    return false;
+
+  FOR_EACH_VEC_ELT_REVERSE (rtx, forced_labels, ix, x)
+    if (x == label)
+      return false;
+
+  return true;
 }
 
 /* Delete INSN by patching it out.  Return the next insn.  */
diff --git a/gcc/except.c b/gcc/except.c
index 5c6359e..858dde7 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -1233,8 +1233,7 @@ sjlj_emit_dispatch_table (rtx dispatch_label, int num_dispatch)
      label on the nonlocal_goto_label list.  Since we're modeling these
      CFG edges more exactly, we can use the forced_labels list instead.  */
   LABEL_PRESERVE_P (dispatch_label) = 1;
-  forced_labels
-    = gen_rtx_EXPR_LIST (VOIDmode, dispatch_label, forced_labels);
+  note_forced_label (dispatch_label);
 #endif
 
   /* Load up exc_ptr and filter values from the function context.  */
diff --git a/gcc/function.h b/gcc/function.h
index fa44958..5b1ebfe 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -137,7 +137,7 @@ struct GTY(()) expr_status {
   rtx x_apply_args_value;
 
   /* List of labels that must never be deleted.  */
-  rtx x_forced_labels;
+  VEC(rtx,gc) *x_forced_labels;
 };
 
 typedef struct call_site_record_d *call_site_record;
@@ -463,6 +463,14 @@ extern GTY(()) struct rtl_data x_rtl;
    want to do differently.  */
 #define crtl (&x_rtl)
 
+/* Add X to the forced_labels list.  */
+
+static inline void
+note_forced_label (rtx x)
+{
+  VEC_safe_push (rtx, gc, forced_labels, x);
+}
+
 struct GTY(()) stack_usage
 {
   /* # of bytes of static stack space allocated by the function.  */
diff --git a/gcc/jump.c b/gcc/jump.c
index 39fc234..7977f3d 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -76,7 +76,8 @@ static int returnjump_p_1 (rtx *, void *);
 static void
 rebuild_jump_labels_1 (rtx f, bool count_forced)
 {
-  rtx insn;
+  rtx x;
+  unsigned int ix;
 
   timevar_push (TV_REBUILD_JUMP);
   init_label_info (f);
@@ -87,9 +88,9 @@ rebuild_jump_labels_1 (rtx f, bool count_forced)
      count doesn't drop to zero.  */
 
   if (count_forced)
-    for (insn = forced_labels; insn; insn = XEXP (insn, 1))
-      if (LABEL_P (XEXP (insn, 0)))
-	LABEL_NUSES (XEXP (insn, 0))++;
+    FOR_EACH_VEC_ELT_REVERSE (rtx, forced_labels, ix, x)
+      if (LABEL_P (x))
+	LABEL_NUSES (x)++;
   timevar_pop (TV_REBUILD_JUMP);
 }
 
diff --git a/gcc/reload1.c b/gcc/reload1.c
index ea7df99..29b33ce 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -3903,11 +3903,14 @@ static void
 set_initial_label_offsets (void)
 {
   rtx x;
+  unsigned int ix;
   memset (offsets_known_at, 0, num_labels);
 
-  for (x = forced_labels; x; x = XEXP (x, 1))
-    if (XEXP (x, 0))
-      set_label_offsets (XEXP (x, 0), NULL_RTX, 1);
+  FOR_EACH_VEC_ELT_REVERSE (rtx, forced_labels, ix, x)
+    {
+      gcc_assert (x != NULL_RTX);
+      set_label_offsets (x, NULL_RTX, 1);
+    }
 
   for_each_eh_label (set_initial_eh_label_offset);
 }
diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c
index 2c00907..19ced7e 100644
--- a/gcc/sched-rgn.c
+++ b/gcc/sched-rgn.c
@@ -259,7 +259,7 @@ is_cfg_nonregular (void)
     return 1;
 
   /* If we have any forced labels, then the cfg is not well structured.  */
-  if (forced_labels)
+  if (!VEC_empty (rtx, forced_labels))
     return 1;
 
   /* If we have exception handlers, then we consider the cfg not well
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 1a9f9e5..b54551c 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -158,7 +158,7 @@ force_label_rtx (tree label)
 
   gcc_assert (function);
 
-  forced_labels = gen_rtx_EXPR_LIST (VOIDmode, ref, forced_labels);
+  note_forced_label (ref);
   return ref;
 }
 
@@ -218,7 +218,7 @@ expand_label (tree label)
     }
 
   if (FORCED_LABEL (label))
-    forced_labels = gen_rtx_EXPR_LIST (VOIDmode, label_r, forced_labels);
+    note_forced_label (label_r);
 
   if (DECL_NONLOCAL (label) || FORCED_LABEL (label))
     maybe_set_first_label_num (label_r);
