aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2016-03-16 09:50:18 -0700
committerRichard Henderson <rth@gcc.gnu.org>2016-03-16 09:50:18 -0700
commitaa43616c59fceefa8ad06bfd60e88f17ad31f063 (patch)
treef650bc6e08ced3e2299e88208f3fcabd0e84f968
parent59608fe587074a6f704d39fd08b6a05f6fb11bf2 (diff)
downloadgcc-aa43616c59fceefa8ad06bfd60e88f17ad31f063.zip
gcc-aa43616c59fceefa8ad06bfd60e88f17ad31f063.tar.gz
gcc-aa43616c59fceefa8ad06bfd60e88f17ad31f063.tar.bz2
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
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/function.h4
-rw-r--r--gcc/gimplify.c5
-rw-r--r--gcc/ipa-chkp.c20
-rw-r--r--gcc/lto-streamer-in.c1
-rw-r--r--gcc/lto-streamer-out.c1
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr70199.c20
-rw-r--r--gcc/tree-inline.c45
-rw-r--r--gcc/tree-inline.h2
10 files changed, 71 insertions, 48 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0af222e..b673443 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 c4368cd..501ef68 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 692d168..84ce46e 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 4a6b43e..5f5df64 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 48a1c86..dd48777 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 997a28b..6703d41 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 8bbcf35..451e653 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 0000000..a4323f0
--- /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 d52e0c6..9d4f8f7 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 4cc1f19..9ca2a91 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. */