From aa43616c59fceefa8ad06bfd60e88f17ad31f063 Mon Sep 17 00:00:00 2001 From: Richard Henderson <rth@redhat.com> Date: Wed, 16 Mar 2016 09:50:18 -0700 Subject: [PATCH] re PR middle-end/70199 (Crash at -O2 when using labels.) PR middle-end/70199 * function.h (struct function): Add has_forced_label_in_static. * gimplify.c (force_labels_r): Set it. * lto-streamer-in.c (input_struct_function_base): Read it. * lto-streamer-out.c (output_struct_function_base): Write it. * tree-inline.c (has_label_address_in_static_1): Remove. (copy_forbidden): Remove fndecl parameter; test has_forced_label_in_static. (inline_forbidden_p): Update call to copy_forbidden. (tree_versionable_function_p): Likewise. * ipa-chkp.c (chkp_instrumentable_p): Likewise. (chkp_versioning): Likewise. * tree-inline.h (copy_forbidden): Update decl. testsuite/ * gcc.c-torture/compile/pr70199.c: New. From-SVN: r234261 --- gcc/ChangeLog | 16 +++++++ gcc/function.h | 4 ++ gcc/gimplify.c | 5 ++- gcc/ipa-chkp.c | 20 ++++----- gcc/lto-streamer-in.c | 1 + gcc/lto-streamer-out.c | 1 + gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.c-torture/compile/pr70199.c | 20 +++++++++ gcc/tree-inline.c | 45 ++++--------------- gcc/tree-inline.h | 2 +- 10 files changed, 71 insertions(+), 48 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr70199.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0af222ed70f6..b673443c1038 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2016-03-16 Richard Henderson <rth@redhat.com> + + PR middle-end/70199 + * function.h (struct function): Add has_forced_label_in_static. + * gimplify.c (force_labels_r): Set it. + * lto-streamer-in.c (input_struct_function_base): Read it. + * lto-streamer-out.c (output_struct_function_base): Write it. + * tree-inline.c (has_label_address_in_static_1): Remove. + (copy_forbidden): Remove fndecl parameter; test + has_forced_label_in_static. + (inline_forbidden_p): Update call to copy_forbidden. + (tree_versionable_function_p): Likewise. + * ipa-chkp.c (chkp_instrumentable_p): Likewise. + (chkp_versioning): Likewise. + * tree-inline.h (copy_forbidden): Update decl. + 2016-03-16 Marek Polacek <polacek@redhat.com> PR c/70093 diff --git a/gcc/function.h b/gcc/function.h index c4368cda7f22..501ef6848401 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -328,6 +328,10 @@ struct GTY(()) function { from nested functions. */ unsigned int has_nonlocal_label : 1; + /* Nonzero if function being compiled has a forced label + placed into static storage. */ + unsigned int has_forced_label_in_static : 1; + /* Nonzero if we've set cannot_be_copied_reason. I.e. if (cannot_be_copied_set && !cannot_be_copied_reason), the function can in fact be copied. */ diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 692d168c3b4e..84ce46ea1a31 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1414,7 +1414,10 @@ force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) if (TYPE_P (*tp)) *walk_subtrees = 0; if (TREE_CODE (*tp) == LABEL_DECL) - FORCED_LABEL (*tp) = 1; + { + FORCED_LABEL (*tp) = 1; + cfun->has_forced_label_in_static = 1; + } return NULL_TREE; } diff --git a/gcc/ipa-chkp.c b/gcc/ipa-chkp.c index 4a6b43e7a8a3..5f5df6483a79 100644 --- a/gcc/ipa-chkp.c +++ b/gcc/ipa-chkp.c @@ -470,7 +470,7 @@ chkp_instrumentable_p (tree fndecl) return (!lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (fndecl)) && (!flag_chkp_instrument_marked_only || lookup_attribute ("bnd_instrument", DECL_ATTRIBUTES (fndecl))) - && (!fn || !copy_forbidden (fn, fndecl))); + && (!fn || !copy_forbidden (fn))); } /* Return clone created for instrumentation of NODE or NULL. */ @@ -644,22 +644,22 @@ chkp_versioning (void) FOR_EACH_DEFINED_FUNCTION (node) { + tree decl = node->decl; if (!node->instrumentation_clone && !node->instrumented_version && !node->alias && !node->thunk.thunk_p - && (!DECL_BUILT_IN (node->decl) - || (DECL_BUILT_IN_CLASS (node->decl) == BUILT_IN_NORMAL - && DECL_FUNCTION_CODE (node->decl) < BEGIN_CHKP_BUILTINS))) + && (!DECL_BUILT_IN (decl) + || (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (decl) < BEGIN_CHKP_BUILTINS))) { - if (chkp_instrumentable_p (node->decl)) - chkp_maybe_create_clone (node->decl); - else if ((reason = copy_forbidden (DECL_STRUCT_FUNCTION (node->decl), - node->decl))) + if (chkp_instrumentable_p (decl)) + chkp_maybe_create_clone (decl); + else if ((reason = copy_forbidden (DECL_STRUCT_FUNCTION (decl)))) { - if (warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wchkp, + if (warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wchkp, "function cannot be instrumented")) - inform (DECL_SOURCE_LOCATION (node->decl), reason, node->decl); + inform (DECL_SOURCE_LOCATION (decl), reason, decl); } } } diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 48a1c868bac9..dd48777effa2 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -1008,6 +1008,7 @@ input_struct_function_base (struct function *fn, struct data_in *data_in, fn->after_inlining = bp_unpack_value (&bp, 1); fn->stdarg = bp_unpack_value (&bp, 1); fn->has_nonlocal_label = bp_unpack_value (&bp, 1); + fn->has_forced_label_in_static = bp_unpack_value (&bp, 1); fn->calls_alloca = bp_unpack_value (&bp, 1); fn->calls_setjmp = bp_unpack_value (&bp, 1); fn->has_force_vectorize_loops = bp_unpack_value (&bp, 1); diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index 997a28b01598..6703d4106dee 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -2014,6 +2014,7 @@ output_struct_function_base (struct output_block *ob, struct function *fn) bp_pack_value (&bp, fn->after_inlining, 1); bp_pack_value (&bp, fn->stdarg, 1); bp_pack_value (&bp, fn->has_nonlocal_label, 1); + bp_pack_value (&bp, fn->has_forced_label_in_static, 1); bp_pack_value (&bp, fn->calls_alloca, 1); bp_pack_value (&bp, fn->calls_setjmp, 1); bp_pack_value (&bp, fn->has_force_vectorize_loops, 1); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8bbcf35ba27d..451e65365fcc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-03-16 Richard Henderson <rth@redhat.com> + + PR middle-end/70199 + * gcc.c-torture/compile/pr70199.c: New. + 2016-03-16 H.J. Lu <hongjiu.lu@intel.com> * gcc.dg/uninit-19.c: Run dos2unix. diff --git a/gcc/testsuite/gcc.c-torture/compile/pr70199.c b/gcc/testsuite/gcc.c-torture/compile/pr70199.c new file mode 100644 index 000000000000..a4323f09f234 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr70199.c @@ -0,0 +1,20 @@ +static volatile int v = 0; +static +void benchmark(long runs) { + void* labels[] = { + &&l0, &&l1, &&l2 + }; + for(unsigned int mask = 0x1F; mask > 0; mask >>= 1) { + unsigned lfsr = 0xACE1u; + long n = 10000000; + while(n > 0) { + l2: v; + l1: v; + goto *labels[lfsr & mask]; + l0: n--; + } + } +} +int f(void) { + benchmark(10000000); +} diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index d52e0c6e2027..9d4f8f7815d5 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -3504,33 +3504,13 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest, return use; } -/* Callback through walk_tree. Determine if a DECL_INITIAL makes reference - to a local label. */ - -static tree -has_label_address_in_static_1 (tree *nodep, int *walk_subtrees, void *fnp) -{ - tree node = *nodep; - tree fn = (tree) fnp; - - if (TREE_CODE (node) == LABEL_DECL && DECL_CONTEXT (node) == fn) - return node; - - if (TYPE_P (node)) - *walk_subtrees = 0; - - return NULL_TREE; -} - /* Determine if the function can be copied. If so return NULL. If not return a string describng the reason for failure. */ const char * -copy_forbidden (struct function *fun, tree fndecl) +copy_forbidden (struct function *fun) { const char *reason = fun->cannot_be_copied_reason; - tree decl; - unsigned ix; /* Only examine the function once. */ if (fun->cannot_be_copied_set) @@ -3549,19 +3529,12 @@ copy_forbidden (struct function *fun, tree fndecl) goto fail; } - FOR_EACH_LOCAL_DECL (fun, ix, decl) - if (TREE_CODE (decl) == VAR_DECL - && TREE_STATIC (decl) - && !DECL_EXTERNAL (decl) - && DECL_INITIAL (decl) - && walk_tree_without_duplicates (&DECL_INITIAL (decl), - has_label_address_in_static_1, - fndecl)) - { - reason = G_("function %q+F can never be copied because it saves " - "address of local label in a static variable"); - goto fail; - } + if (fun->has_forced_label_in_static) + { + reason = G_("function %q+F can never be copied because it saves " + "address of local label in a static variable"); + goto fail; + } fail: fun->cannot_be_copied_reason = reason; @@ -3705,7 +3678,7 @@ inline_forbidden_p (tree fndecl) bool forbidden_p = false; /* First check for shared reasons not to copy the code. */ - inline_forbidden_reason = copy_forbidden (fun, fndecl); + inline_forbidden_reason = copy_forbidden (fun); if (inline_forbidden_reason != NULL) return true; @@ -5552,7 +5525,7 @@ bool tree_versionable_function_p (tree fndecl) { return (!lookup_attribute ("noclone", DECL_ATTRIBUTES (fndecl)) - && copy_forbidden (DECL_STRUCT_FUNCTION (fndecl), fndecl) == NULL); + && copy_forbidden (DECL_STRUCT_FUNCTION (fndecl)) == NULL); } /* Delete all unreachable basic blocks and update callgraph. diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h index 4cc1f19223a3..9ca2a91f08f2 100644 --- a/gcc/tree-inline.h +++ b/gcc/tree-inline.h @@ -217,7 +217,7 @@ extern tree remap_type (tree type, copy_body_data *id); extern gimple_seq copy_gimple_seq_and_replace_locals (gimple_seq seq); extern bool debug_find_tree (tree, tree); extern tree copy_fn (tree, tree&, tree&); -extern const char *copy_forbidden (struct function *fun, tree fndecl); +extern const char *copy_forbidden (struct function *fun); /* This is in tree-inline.c since the routine uses data structures from the inliner. */ -- GitLab