Commit aa43616c by Richard Henderson Committed by Richard Henderson

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
parent 59608fe5
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> 2016-03-16 Marek Polacek <polacek@redhat.com>
PR c/70093 PR c/70093
......
...@@ -328,6 +328,10 @@ struct GTY(()) function { ...@@ -328,6 +328,10 @@ struct GTY(()) function {
from nested functions. */ from nested functions. */
unsigned int has_nonlocal_label : 1; 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 /* Nonzero if we've set cannot_be_copied_reason. I.e. if
(cannot_be_copied_set && !cannot_be_copied_reason), the function (cannot_be_copied_set && !cannot_be_copied_reason), the function
can in fact be copied. */ can in fact be copied. */
......
...@@ -1414,7 +1414,10 @@ force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) ...@@ -1414,7 +1414,10 @@ force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
if (TYPE_P (*tp)) if (TYPE_P (*tp))
*walk_subtrees = 0; *walk_subtrees = 0;
if (TREE_CODE (*tp) == LABEL_DECL) if (TREE_CODE (*tp) == LABEL_DECL)
{
FORCED_LABEL (*tp) = 1; FORCED_LABEL (*tp) = 1;
cfun->has_forced_label_in_static = 1;
}
return NULL_TREE; return NULL_TREE;
} }
......
...@@ -470,7 +470,7 @@ chkp_instrumentable_p (tree fndecl) ...@@ -470,7 +470,7 @@ chkp_instrumentable_p (tree fndecl)
return (!lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (fndecl)) return (!lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (fndecl))
&& (!flag_chkp_instrument_marked_only && (!flag_chkp_instrument_marked_only
|| lookup_attribute ("bnd_instrument", DECL_ATTRIBUTES (fndecl))) || 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. */ /* Return clone created for instrumentation of NODE or NULL. */
...@@ -644,22 +644,22 @@ chkp_versioning (void) ...@@ -644,22 +644,22 @@ chkp_versioning (void)
FOR_EACH_DEFINED_FUNCTION (node) FOR_EACH_DEFINED_FUNCTION (node)
{ {
tree decl = node->decl;
if (!node->instrumentation_clone if (!node->instrumentation_clone
&& !node->instrumented_version && !node->instrumented_version
&& !node->alias && !node->alias
&& !node->thunk.thunk_p && !node->thunk.thunk_p
&& (!DECL_BUILT_IN (node->decl) && (!DECL_BUILT_IN (decl)
|| (DECL_BUILT_IN_CLASS (node->decl) == BUILT_IN_NORMAL || (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (node->decl) < BEGIN_CHKP_BUILTINS))) && DECL_FUNCTION_CODE (decl) < BEGIN_CHKP_BUILTINS)))
{ {
if (chkp_instrumentable_p (node->decl)) if (chkp_instrumentable_p (decl))
chkp_maybe_create_clone (node->decl); chkp_maybe_create_clone (decl);
else if ((reason = copy_forbidden (DECL_STRUCT_FUNCTION (node->decl), else if ((reason = copy_forbidden (DECL_STRUCT_FUNCTION (decl))))
node->decl)))
{ {
if (warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wchkp, if (warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wchkp,
"function cannot be instrumented")) "function cannot be instrumented"))
inform (DECL_SOURCE_LOCATION (node->decl), reason, node->decl); inform (DECL_SOURCE_LOCATION (decl), reason, decl);
} }
} }
} }
......
...@@ -1008,6 +1008,7 @@ input_struct_function_base (struct function *fn, struct data_in *data_in, ...@@ -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->after_inlining = bp_unpack_value (&bp, 1);
fn->stdarg = bp_unpack_value (&bp, 1); fn->stdarg = bp_unpack_value (&bp, 1);
fn->has_nonlocal_label = 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_alloca = bp_unpack_value (&bp, 1);
fn->calls_setjmp = bp_unpack_value (&bp, 1); fn->calls_setjmp = bp_unpack_value (&bp, 1);
fn->has_force_vectorize_loops = bp_unpack_value (&bp, 1); fn->has_force_vectorize_loops = bp_unpack_value (&bp, 1);
......
...@@ -2014,6 +2014,7 @@ output_struct_function_base (struct output_block *ob, struct function *fn) ...@@ -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->after_inlining, 1);
bp_pack_value (&bp, fn->stdarg, 1); bp_pack_value (&bp, fn->stdarg, 1);
bp_pack_value (&bp, fn->has_nonlocal_label, 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_alloca, 1);
bp_pack_value (&bp, fn->calls_setjmp, 1); bp_pack_value (&bp, fn->calls_setjmp, 1);
bp_pack_value (&bp, fn->has_force_vectorize_loops, 1); bp_pack_value (&bp, fn->has_force_vectorize_loops, 1);
......
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> 2016-03-16 H.J. Lu <hongjiu.lu@intel.com>
* gcc.dg/uninit-19.c: Run dos2unix. * gcc.dg/uninit-19.c: Run dos2unix.
......
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);
}
...@@ -3504,33 +3504,13 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest, ...@@ -3504,33 +3504,13 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
return use; 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 /* Determine if the function can be copied. If so return NULL. If
not return a string describng the reason for failure. */ not return a string describng the reason for failure. */
const char * const char *
copy_forbidden (struct function *fun, tree fndecl) copy_forbidden (struct function *fun)
{ {
const char *reason = fun->cannot_be_copied_reason; const char *reason = fun->cannot_be_copied_reason;
tree decl;
unsigned ix;
/* Only examine the function once. */ /* Only examine the function once. */
if (fun->cannot_be_copied_set) if (fun->cannot_be_copied_set)
...@@ -3549,14 +3529,7 @@ copy_forbidden (struct function *fun, tree fndecl) ...@@ -3549,14 +3529,7 @@ copy_forbidden (struct function *fun, tree fndecl)
goto fail; goto fail;
} }
FOR_EACH_LOCAL_DECL (fun, ix, decl) if (fun->has_forced_label_in_static)
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 " reason = G_("function %q+F can never be copied because it saves "
"address of local label in a static variable"); "address of local label in a static variable");
...@@ -3705,7 +3678,7 @@ inline_forbidden_p (tree fndecl) ...@@ -3705,7 +3678,7 @@ inline_forbidden_p (tree fndecl)
bool forbidden_p = false; bool forbidden_p = false;
/* First check for shared reasons not to copy the code. */ /* 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) if (inline_forbidden_reason != NULL)
return true; return true;
...@@ -5552,7 +5525,7 @@ bool ...@@ -5552,7 +5525,7 @@ bool
tree_versionable_function_p (tree fndecl) tree_versionable_function_p (tree fndecl)
{ {
return (!lookup_attribute ("noclone", DECL_ATTRIBUTES (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. /* Delete all unreachable basic blocks and update callgraph.
......
...@@ -217,7 +217,7 @@ extern tree remap_type (tree type, copy_body_data *id); ...@@ -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 gimple_seq copy_gimple_seq_and_replace_locals (gimple_seq seq);
extern bool debug_find_tree (tree, tree); extern bool debug_find_tree (tree, tree);
extern tree copy_fn (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 /* This is in tree-inline.c since the routine uses
data structures from the inliner. */ data structures from the inliner. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment