tree-ssa-sccvn.c (visit_reference_op_call): Value number virtual definition to virtual use if...

2016-09-23  Richard Biener  <rguenther@suse.de>

	* tree-ssa-sccvn.c (visit_reference_op_call): Value number
	virtual definition to virtual use if the call devirtualizes
	to a const or pure function.
	(visit_use): Also visit calls we can devirtualize to a
	const or pure function.

	* gcc.dg/tree-ssa/ssa-fre-56.c: New testcase.

From-SVN: r240431
This commit is contained in:
Richard Biener 2016-09-23 12:39:05 +00:00 committed by Richard Biener
parent 26bedff5fd
commit 113d06a486
4 changed files with 68 additions and 3 deletions

View file

@ -1,3 +1,11 @@
2016-09-23 Richard Biener <rguenther@suse.de>
* tree-ssa-sccvn.c (visit_reference_op_call): Value number
virtual definition to virtual use if the call devirtualizes
to a const or pure function.
(visit_use): Also visit calls we can devirtualize to a
const or pure function.
2016-09-23 Richard Biener <rguenther@suse.de>
PR tree-optimization/77697

View file

@ -1,3 +1,7 @@
2016-09-23 Richard Biener <rguenther@suse.de>
* gcc.dg/tree-ssa/ssa-fre-56.c: New testcase.
2016-09-23 Matthew Wahab <matthew.wahab@arm.com>
* gcc.target/advsimd-intrinsics/advsimd-intrinsics.exp: Enable

View file

@ -0,0 +1,26 @@
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-fre1" } */
int x = 1;
int __attribute__((noinline,noclone)) fn ()
{
return x;
}
int (*f)();
int main ()
{
int res;
f = fn;
x = 0;
res = f ();
res += x;
if (res != 0)
__builtin_abort ();
return 0;
}
/* We should be able to optimize the load from x in main and thus the
addition. */
/* { dg-final { scan-tree-dump-times "= x;" 1 "fre1" } } */
/* { dg-final { scan-tree-dump-times " \\\+ " 0 "fre1" } } */

View file

@ -3484,8 +3484,24 @@ visit_reference_op_call (tree lhs, gcall *stmt)
{
vn_reference_t vr2;
vn_reference_s **slot;
tree vdef_val = vdef;
if (vdef)
changed |= set_ssa_val_to (vdef, vdef);
{
/* If we value numbered an indirect functions function to
one not clobbering memory value number its VDEF to its
VUSE. */
tree fn = gimple_call_fn (stmt);
if (fn && TREE_CODE (fn) == SSA_NAME)
{
fn = SSA_VAL (fn);
if (TREE_CODE (fn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& (flags_from_decl_or_type (TREE_OPERAND (fn, 0))
& (ECF_CONST | ECF_PURE)))
vdef_val = vuse_ssa_val (gimple_vuse (stmt));
}
changed |= set_ssa_val_to (vdef, vdef_val);
}
if (lhs)
changed |= set_ssa_val_to (lhs, lhs);
vr2 = current_info->references_pool->allocate ();
@ -3498,7 +3514,7 @@ visit_reference_op_call (tree lhs, gcall *stmt)
vr2->set = vr1.set;
vr2->hashcode = vr1.hashcode;
vr2->result = lhs;
vr2->result_vdef = vdef;
vr2->result_vdef = vdef_val;
slot = current_info->references->find_slot_with_hash (vr2, vr2->hashcode,
INSERT);
gcc_assert (!*slot);
@ -3912,11 +3928,22 @@ visit_use (tree use)
}
}
/* Pick up flags from a devirtualization target. */
tree fn = gimple_call_fn (stmt);
int extra_fnflags = 0;
if (fn && TREE_CODE (fn) == SSA_NAME)
{
fn = SSA_VAL (fn);
if (TREE_CODE (fn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
extra_fnflags = flags_from_decl_or_type (TREE_OPERAND (fn, 0));
}
if (!gimple_call_internal_p (call_stmt)
&& (/* Calls to the same function with the same vuse
and the same operands do not necessarily return the same
value, unless they're pure or const. */
gimple_call_flags (call_stmt) & (ECF_PURE | ECF_CONST)
((gimple_call_flags (call_stmt) | extra_fnflags)
& (ECF_PURE | ECF_CONST))
/* If calls have a vdef, subsequent calls won't have
the same incoming vuse. So, if 2 calls with vdef have the
same vuse, we know they're not subsequent.