mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
59608fe587
commit
aa43616c59
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue