backport: re PR tree-optimization/82060 (ICE in refs_may_alias_p_1 with devirtualization enabled)
2017-12-15 Richard Biener <rguenther@suse.de> Backport from mainline PR tree-optimization/82060 * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): Move devirtualization after stmt folding and before EH/AB/noreturn cleanup to get the stmt refs canonicalized. Use a bool instead of gimple_modified_p since that doesn't work for NOPs. Schedule NOPs generated by folding for removal. * g++.dg/torture/pr82060.C: New testcase. From-SVN: r255682
This commit is contained in:
parent
c49c3117e3
commit
2c44df49aa
@ -1,3 +1,13 @@
|
|||||||
|
2017-12-15 Richard Biener <rguenther@suse.de>
|
||||||
|
|
||||||
|
Backport from mainline
|
||||||
|
PR tree-optimization/82060
|
||||||
|
* tree-ssa-pre.c (eliminate_dom_walker::before_dom_children):
|
||||||
|
Move devirtualization after stmt folding and before EH/AB/noreturn
|
||||||
|
cleanup to get the stmt refs canonicalized. Use a bool instead
|
||||||
|
of gimple_modified_p since that doesn't work for NOPs. Schedule
|
||||||
|
NOPs generated by folding for removal.
|
||||||
|
|
||||||
2017-12-15 Richard Biener <rguenther@suse.de>
|
2017-12-15 Richard Biener <rguenther@suse.de>
|
||||||
|
|
||||||
Backport from mainline
|
Backport from mainline
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
2017-12-15 Richard Biener <rguenther@suse.de>
|
||||||
|
|
||||||
|
Backport from mainline
|
||||||
|
PR tree-optimization/82060
|
||||||
|
* g++.dg/torture/pr82060.C: New testcase.
|
||||||
|
|
||||||
2017-12-15 Sudakshina Das <sudi.das@arm.com>
|
2017-12-15 Sudakshina Das <sudi.das@arm.com>
|
||||||
|
|
||||||
* gcc.target/arm/armv8_2-fp16-move-2.c: Remove dg-add-options.
|
* gcc.target/arm/armv8_2-fp16-move-2.c: Remove dg-add-options.
|
||||||
|
32
gcc/testsuite/g++.dg/torture/pr82060.C
Normal file
32
gcc/testsuite/g++.dg/torture/pr82060.C
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// { dg-do compile }
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
char a[1]; // must be char array
|
||||||
|
};
|
||||||
|
|
||||||
|
struct B
|
||||||
|
{
|
||||||
|
A& a() { return ma; } // must be accessed through a getter
|
||||||
|
A ma;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct C
|
||||||
|
{
|
||||||
|
B& b() { return mb; } // must be accessed through a getter
|
||||||
|
B mb;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct D
|
||||||
|
{
|
||||||
|
virtual A getA() = 0; // must be virtual
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
foo(D& d) // The D object must not be created locally
|
||||||
|
// (so that getA implementation is not known at compile time?)
|
||||||
|
{
|
||||||
|
C c;
|
||||||
|
for (;;) // must be in a loop
|
||||||
|
c.b().a() = d.getA();
|
||||||
|
}
|
@ -4566,6 +4566,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
|
|||||||
/* If we didn't replace the whole stmt (or propagate the result
|
/* If we didn't replace the whole stmt (or propagate the result
|
||||||
into all uses), replace all uses on this stmt with their
|
into all uses), replace all uses on this stmt with their
|
||||||
leaders. */
|
leaders. */
|
||||||
|
bool modified = false;
|
||||||
use_operand_p use_p;
|
use_operand_p use_p;
|
||||||
ssa_op_iter iter;
|
ssa_op_iter iter;
|
||||||
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
|
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
|
||||||
@ -4587,7 +4588,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
|
|||||||
|| !bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (sprime))))
|
|| !bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (sprime))))
|
||||||
{
|
{
|
||||||
propagate_value (use_p, sprime);
|
propagate_value (use_p, sprime);
|
||||||
gimple_set_modified (stmt, true);
|
modified = true;
|
||||||
if (TREE_CODE (sprime) == SSA_NAME
|
if (TREE_CODE (sprime) == SSA_NAME
|
||||||
&& !is_gimple_debug (stmt))
|
&& !is_gimple_debug (stmt))
|
||||||
gimple_set_plf (SSA_NAME_DEF_STMT (sprime),
|
gimple_set_plf (SSA_NAME_DEF_STMT (sprime),
|
||||||
@ -4595,8 +4596,34 @@ eliminate_dom_walker::before_dom_children (basic_block b)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fold the stmt if modified, this canonicalizes MEM_REFs we propagated
|
||||||
|
into which is a requirement for the IPA devirt machinery. */
|
||||||
|
gimple *old_stmt = stmt;
|
||||||
|
if (modified)
|
||||||
|
{
|
||||||
|
/* If a formerly non-invariant ADDR_EXPR is turned into an
|
||||||
|
invariant one it was on a separate stmt. */
|
||||||
|
if (gimple_assign_single_p (stmt)
|
||||||
|
&& TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR)
|
||||||
|
recompute_tree_invariant_for_addr_expr (gimple_assign_rhs1 (stmt));
|
||||||
|
if (is_gimple_call (stmt))
|
||||||
|
{
|
||||||
|
/* ??? Only fold calls inplace for now, this may create new
|
||||||
|
SSA names which in turn will confuse free_scc_vn SSA name
|
||||||
|
release code. */
|
||||||
|
fold_stmt_inplace (&gsi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fold_stmt (&gsi);
|
||||||
|
stmt = gsi_stmt (gsi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Visit indirect calls and turn them into direct calls if
|
/* Visit indirect calls and turn them into direct calls if
|
||||||
possible using the devirtualization machinery. */
|
possible using the devirtualization machinery. Do this before
|
||||||
|
checking for required EH/abnormal/noreturn cleanup as devird
|
||||||
|
may expose more of those. */
|
||||||
if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
|
if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
|
||||||
{
|
{
|
||||||
tree fn = gimple_call_fn (call_stmt);
|
tree fn = gimple_call_fn (call_stmt);
|
||||||
@ -4605,24 +4632,21 @@ eliminate_dom_walker::before_dom_children (basic_block b)
|
|||||||
&& virtual_method_call_p (fn))
|
&& virtual_method_call_p (fn))
|
||||||
{
|
{
|
||||||
tree otr_type = obj_type_ref_class (fn);
|
tree otr_type = obj_type_ref_class (fn);
|
||||||
|
unsigned HOST_WIDE_INT otr_tok
|
||||||
|
= tree_to_uhwi (OBJ_TYPE_REF_TOKEN (fn));
|
||||||
tree instance;
|
tree instance;
|
||||||
ipa_polymorphic_call_context context (current_function_decl, fn, stmt, &instance);
|
ipa_polymorphic_call_context context (current_function_decl,
|
||||||
|
fn, stmt, &instance);
|
||||||
|
context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (fn),
|
||||||
|
otr_type, stmt);
|
||||||
bool final;
|
bool final;
|
||||||
|
|
||||||
context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (fn), otr_type, stmt);
|
|
||||||
|
|
||||||
vec <cgraph_node *> targets
|
vec <cgraph_node *> targets
|
||||||
= possible_polymorphic_call_targets (obj_type_ref_class (fn),
|
= possible_polymorphic_call_targets (obj_type_ref_class (fn),
|
||||||
tree_to_uhwi
|
otr_tok, context, &final);
|
||||||
(OBJ_TYPE_REF_TOKEN (fn)),
|
|
||||||
context,
|
|
||||||
&final);
|
|
||||||
if (dump_file)
|
if (dump_file)
|
||||||
dump_possible_polymorphic_call_targets (dump_file,
|
dump_possible_polymorphic_call_targets (dump_file,
|
||||||
obj_type_ref_class (fn),
|
obj_type_ref_class (fn),
|
||||||
tree_to_uhwi
|
otr_tok, context);
|
||||||
(OBJ_TYPE_REF_TOKEN (fn)),
|
|
||||||
context);
|
|
||||||
if (final && targets.length () <= 1 && dbg_cnt (devirt))
|
if (final && targets.length () <= 1 && dbg_cnt (devirt))
|
||||||
{
|
{
|
||||||
tree fn;
|
tree fn;
|
||||||
@ -4632,7 +4656,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
|
|||||||
fn = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
|
fn = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
|
||||||
if (dump_enabled_p ())
|
if (dump_enabled_p ())
|
||||||
{
|
{
|
||||||
location_t loc = gimple_location_safe (stmt);
|
location_t loc = gimple_location (stmt);
|
||||||
dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
|
dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
|
||||||
"converting indirect call to "
|
"converting indirect call to "
|
||||||
"function %s\n",
|
"function %s\n",
|
||||||
@ -4654,38 +4678,22 @@ eliminate_dom_walker::before_dom_children (basic_block b)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gimple_modified_p (stmt))
|
if (modified)
|
||||||
{
|
{
|
||||||
/* If a formerly non-invariant ADDR_EXPR is turned into an
|
|
||||||
invariant one it was on a separate stmt. */
|
|
||||||
if (gimple_assign_single_p (stmt)
|
|
||||||
&& TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR)
|
|
||||||
recompute_tree_invariant_for_addr_expr (gimple_assign_rhs1 (stmt));
|
|
||||||
gimple *old_stmt = stmt;
|
|
||||||
if (is_gimple_call (stmt))
|
|
||||||
{
|
|
||||||
/* ??? Only fold calls inplace for now, this may create new
|
|
||||||
SSA names which in turn will confuse free_scc_vn SSA name
|
|
||||||
release code. */
|
|
||||||
fold_stmt_inplace (&gsi);
|
|
||||||
/* When changing a call into a noreturn call, cfg cleanup
|
/* When changing a call into a noreturn call, cfg cleanup
|
||||||
is needed to fix up the noreturn call. */
|
is needed to fix up the noreturn call. */
|
||||||
if (!was_noreturn && gimple_call_noreturn_p (stmt))
|
if (!was_noreturn
|
||||||
|
&& is_gimple_call (stmt) && gimple_call_noreturn_p (stmt))
|
||||||
el_to_fixup.safe_push (stmt);
|
el_to_fixup.safe_push (stmt);
|
||||||
}
|
/* When changing a condition or switch into one we know what
|
||||||
else
|
edge will be executed, schedule a cfg cleanup. */
|
||||||
{
|
|
||||||
fold_stmt (&gsi);
|
|
||||||
stmt = gsi_stmt (gsi);
|
|
||||||
if ((gimple_code (stmt) == GIMPLE_COND
|
if ((gimple_code (stmt) == GIMPLE_COND
|
||||||
&& (gimple_cond_true_p (as_a <gcond *> (stmt))
|
&& (gimple_cond_true_p (as_a <gcond *> (stmt))
|
||||||
|| gimple_cond_false_p (as_a <gcond *> (stmt))))
|
|| gimple_cond_false_p (as_a <gcond *> (stmt))))
|
||||||
|| (gimple_code (stmt) == GIMPLE_SWITCH
|
|| (gimple_code (stmt) == GIMPLE_SWITCH
|
||||||
&& TREE_CODE (gimple_switch_index (
|
&& TREE_CODE (gimple_switch_index
|
||||||
as_a <gswitch *> (stmt)))
|
(as_a <gswitch *> (stmt))) == INTEGER_CST))
|
||||||
== INTEGER_CST))
|
|
||||||
el_todo |= TODO_cleanup_cfg;
|
el_todo |= TODO_cleanup_cfg;
|
||||||
}
|
|
||||||
/* If we removed EH side-effects from the statement, clean
|
/* If we removed EH side-effects from the statement, clean
|
||||||
its EH information. */
|
its EH information. */
|
||||||
if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
|
if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
|
||||||
|
Loading…
Reference in New Issue
Block a user