As $SUBJECT suggests. The memory savings from this conversion is negligible; the real benefit, IMHO, is use of a proper container instead of EXPR_LIST.
remove_node_from_expr_list is unused after this patch; I will delete it as an obvious followon patch if this patch is approved. Tested on x86_64-unknown-linux-gnu. OK to commit? -Nathan * function.h (struct rtl_data) [x_nonlocal_goto_handler_labels]: Convert to a VEC. (note_nonlocal_goto_handler_label): New function. (remove_from_nonlocal_goto_handler_labels): New function. * builtins.c (expand_builtin): Call them. * cfgrtl.c (delete_insn): Call remove_from_nonlocal_goto_handler_labels. * stmt.c (expand_label): Call note_nonlocal_goto_handler_label. * cfgbuild.c (make_edges): Adjust for new type of nonlocal_goto_handler_labels. * cfglayout.c (cfg_layout_initialize): Likewise. * except.c (insn_nothrow_p): Likewise. * recog.c (peep2_attempt): Likewise. * sched-rgn.c (is_cfg_nonregular): Likewise. diff --git a/gcc/builtins.c b/gcc/builtins.c index b2534ce..839b212 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -6168,9 +6168,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, /* This is copied from the handling of non-local gotos. */ expand_builtin_setjmp_setup (buf_addr, label_r); - nonlocal_goto_handler_labels - = gen_rtx_EXPR_LIST (VOIDmode, label_r, - nonlocal_goto_handler_labels); + note_nonlocal_goto_handler_label (label_r); /* ??? Do not let expand_label treat us as such since we would not want to be both on the list of non-local labels and on the list of forced labels. */ @@ -6188,7 +6186,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, /* Remove the dispatcher label from the list of non-local labels since the receiver labels have been added to it above. */ - remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels); + remove_from_nonlocal_goto_handler_labels (label_r); return const0_rtx; } break; diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c index 6f0d69e..82b5e63 100644 --- a/gcc/cfgbuild.c +++ b/gcc/cfgbuild.c @@ -338,7 +338,8 @@ make_edges (basic_block min, basic_block max, int update_p) /* Add any appropriate EH edges. */ rtl_make_eh_edge (edge_cache, bb, insn); - if (code == CALL_INSN && nonlocal_goto_handler_labels) + if (code == CALL_INSN + && !VEC_empty (rtx, nonlocal_goto_handler_labels)) { /* ??? This could be made smarter: in some cases it's possible to tell that certain calls will not do a nonlocal goto. @@ -347,9 +348,13 @@ make_edges (basic_block min, basic_block max, int update_p) those functions or to other nested functions that use them could possibly do nonlocal gotos. */ if (can_nonlocal_goto (insn)) - for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1)) - make_label_edge (edge_cache, bb, XEXP (x, 0), - EDGE_ABNORMAL | EDGE_ABNORMAL_CALL); + { + unsigned int ix; + FOR_EACH_VEC_ELT_REVERSE (rtx, nonlocal_goto_handler_labels, + ix, x) + make_label_edge (edge_cache, bb, x, + EDGE_ABNORMAL | EDGE_ABNORMAL_CALL); + } } } diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c index 548e21f..38db3f4 100644 --- a/gcc/cfglayout.c +++ b/gcc/cfglayout.c @@ -1291,6 +1291,7 @@ cfg_layout_initialize (unsigned int flags) { rtx x; basic_block bb; + unsigned int ix; initialize_original_copy_tables (); @@ -1299,9 +1300,9 @@ cfg_layout_initialize (unsigned int flags) record_effective_endpoints (); /* Make sure that the targets of non local gotos are marked. */ - for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1)) + FOR_EACH_VEC_ELT_REVERSE (rtx, nonlocal_goto_handler_labels, ix, x) { - bb = BLOCK_FOR_INSN (XEXP (x, 0)); + bb = BLOCK_FOR_INSN (x); bb->flags |= BB_NON_LOCAL_GOTO_TARGET; } diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index c450ca0..a3e1202 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -134,7 +134,7 @@ delete_insn (rtx insn) NOTE_DELETED_LABEL_NAME (insn) = name; } - remove_node_from_expr_list (insn, &nonlocal_goto_handler_labels); + remove_from_nonlocal_goto_handler_labels (insn); } if (really_delete) diff --git a/gcc/except.c b/gcc/except.c index 5c6359e..c8da137 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -1819,7 +1819,7 @@ insn_nothrow_p (const_rtx insn) bool can_nonlocal_goto (const_rtx insn) { - if (nonlocal_goto_handler_labels && CALL_P (insn)) + if (!VEC_empty (rtx, nonlocal_goto_handler_labels) && CALL_P (insn)) { rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX); if (!note || INTVAL (XEXP (note, 0)) != INT_MIN) diff --git a/gcc/function.h b/gcc/function.h index fa44958..7d91994 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -268,9 +268,8 @@ struct GTY(()) rtl_data { Used for detecting stack clobbers. */ tree stack_protect_guard; - /* List (chain of EXPR_LIST) of labels heading the current handlers for - nonlocal gotos. */ - rtx x_nonlocal_goto_handler_labels; + /* List of labels heading the current handlers for nonlocal gotos. */ + VEC(rtx,gc) *x_nonlocal_goto_handler_labels; /* Label that will go on function epilogue. Jumping to this label serves as a "return" instruction @@ -463,6 +462,30 @@ extern GTY(()) struct rtl_data x_rtl; want to do differently. */ #define crtl (&x_rtl) +/* Add X to the nonlocal_goto_handler_labels list. */ + +static inline void +note_nonlocal_goto_handler_label (rtx x) +{ + VEC_safe_push (rtx, gc, nonlocal_goto_handler_labels, x); +} + +/* Remove X from the nonlocal_goto_handler_labels list. */ + +static inline void +remove_from_nonlocal_goto_handler_labels (rtx label) +{ + unsigned ix; + rtx x; + + FOR_EACH_VEC_ELT_REVERSE (rtx, nonlocal_goto_handler_labels, ix, x) + if (x == label) + { + VEC_unordered_remove (rtx, nonlocal_goto_handler_labels, ix); + return; + } +} + struct GTY(()) stack_usage { /* # of bytes of static stack space allocated by the function. */ diff --git a/gcc/recog.c b/gcc/recog.c index afe985e..1c4db90 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -3291,7 +3291,7 @@ peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt) delete_insn_chain (insn, peep2_insn_data[i].insn, false); /* Re-insert the EH_REGION notes. */ - if (note || (was_call && nonlocal_goto_handler_labels)) + if (note || (was_call && !VEC_empty (rtx, nonlocal_goto_handler_labels))) { edge eh_edge; edge_iterator ei; diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c index 2c00907..cf4c5f6 100644 --- a/gcc/sched-rgn.c +++ b/gcc/sched-rgn.c @@ -255,7 +255,7 @@ is_cfg_nonregular (void) /* If we have a label that could be the target of a nonlocal goto, then the cfg is not well structured. */ - if (nonlocal_goto_handler_labels) + if (!VEC_empty (rtx, nonlocal_goto_handler_labels)) return 1; /* If we have any forced labels, then the cfg is not well structured. */ diff --git a/gcc/stmt.c b/gcc/stmt.c index 1a9f9e5..9c303de 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -212,9 +212,7 @@ expand_label (tree label) if (DECL_NONLOCAL (label)) { expand_nl_goto_receiver (); - nonlocal_goto_handler_labels - = gen_rtx_EXPR_LIST (VOIDmode, label_r, - nonlocal_goto_handler_labels); + note_nonlocal_goto_handler_label (label_r); } if (FORCED_LABEL (label))