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>
|
||||
|
||||
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>
|
||||
|
||||
* 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
|
||||
into all uses), replace all uses on this stmt with their
|
||||
leaders. */
|
||||
bool modified = false;
|
||||
use_operand_p use_p;
|
||||
ssa_op_iter iter;
|
||||
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))))
|
||||
{
|
||||
propagate_value (use_p, sprime);
|
||||
gimple_set_modified (stmt, true);
|
||||
modified = true;
|
||||
if (TREE_CODE (sprime) == SSA_NAME
|
||||
&& !is_gimple_debug (stmt))
|
||||
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
|
||||
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))
|
||||
{
|
||||
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))
|
||||
{
|
||||
tree otr_type = obj_type_ref_class (fn);
|
||||
unsigned HOST_WIDE_INT otr_tok
|
||||
= tree_to_uhwi (OBJ_TYPE_REF_TOKEN (fn));
|
||||
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;
|
||||
|
||||
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),
|
||||
tree_to_uhwi
|
||||
(OBJ_TYPE_REF_TOKEN (fn)),
|
||||
context,
|
||||
&final);
|
||||
otr_tok, context, &final);
|
||||
if (dump_file)
|
||||
dump_possible_polymorphic_call_targets (dump_file,
|
||||
obj_type_ref_class (fn),
|
||||
tree_to_uhwi
|
||||
(OBJ_TYPE_REF_TOKEN (fn)),
|
||||
context);
|
||||
otr_tok, context);
|
||||
if (final && targets.length () <= 1 && dbg_cnt (devirt))
|
||||
{
|
||||
tree fn;
|
||||
@ -4632,7 +4656,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
|
||||
fn = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
|
||||
if (dump_enabled_p ())
|
||||
{
|
||||
location_t loc = gimple_location_safe (stmt);
|
||||
location_t loc = gimple_location (stmt);
|
||||
dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
|
||||
"converting indirect call to "
|
||||
"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
|
||||
is needed to fix up the noreturn call. */
|
||||
if (!was_noreturn && gimple_call_noreturn_p (stmt))
|
||||
el_to_fixup.safe_push (stmt);
|
||||
}
|
||||
else
|
||||
{
|
||||
fold_stmt (&gsi);
|
||||
stmt = gsi_stmt (gsi);
|
||||
if ((gimple_code (stmt) == GIMPLE_COND
|
||||
&& (gimple_cond_true_p (as_a <gcond *> (stmt))
|
||||
|| gimple_cond_false_p (as_a <gcond *> (stmt))))
|
||||
|| (gimple_code (stmt) == GIMPLE_SWITCH
|
||||
&& TREE_CODE (gimple_switch_index (
|
||||
as_a <gswitch *> (stmt)))
|
||||
== INTEGER_CST))
|
||||
el_todo |= TODO_cleanup_cfg;
|
||||
}
|
||||
/* When changing a call into a noreturn call, cfg cleanup
|
||||
is needed to fix up the noreturn call. */
|
||||
if (!was_noreturn
|
||||
&& is_gimple_call (stmt) && gimple_call_noreturn_p (stmt))
|
||||
el_to_fixup.safe_push (stmt);
|
||||
/* When changing a condition or switch into one we know what
|
||||
edge will be executed, schedule a cfg cleanup. */
|
||||
if ((gimple_code (stmt) == GIMPLE_COND
|
||||
&& (gimple_cond_true_p (as_a <gcond *> (stmt))
|
||||
|| gimple_cond_false_p (as_a <gcond *> (stmt))))
|
||||
|| (gimple_code (stmt) == GIMPLE_SWITCH
|
||||
&& TREE_CODE (gimple_switch_index
|
||||
(as_a <gswitch *> (stmt))) == INTEGER_CST))
|
||||
el_todo |= TODO_cleanup_cfg;
|
||||
/* If we removed EH side-effects from the statement, clean
|
||||
its EH information. */
|
||||
if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
|
||||
|
Loading…
Reference in New Issue
Block a user