Commit 113d06a4 by Richard Biener Committed by Richard Biener

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
parent 26bedff5
2016-09-23 Richard Biener <rguenther@suse.de> 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 PR tree-optimization/77697
* tree-ssa-forwprop.c (defcodefor_name): Remove bogus code, * tree-ssa-forwprop.c (defcodefor_name): Remove bogus code,
signal error if we have sth ternary or unhandled. signal error if we have sth ternary or unhandled.
......
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> 2016-09-23 Matthew Wahab <matthew.wahab@arm.com>
* gcc.target/advsimd-intrinsics/advsimd-intrinsics.exp: Enable * gcc.target/advsimd-intrinsics/advsimd-intrinsics.exp: Enable
......
/* { 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" } } */
...@@ -3484,8 +3484,24 @@ visit_reference_op_call (tree lhs, gcall *stmt) ...@@ -3484,8 +3484,24 @@ visit_reference_op_call (tree lhs, gcall *stmt)
{ {
vn_reference_t vr2; vn_reference_t vr2;
vn_reference_s **slot; vn_reference_s **slot;
tree vdef_val = vdef;
if (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) if (lhs)
changed |= set_ssa_val_to (lhs, lhs); changed |= set_ssa_val_to (lhs, lhs);
vr2 = current_info->references_pool->allocate (); vr2 = current_info->references_pool->allocate ();
...@@ -3498,7 +3514,7 @@ visit_reference_op_call (tree lhs, gcall *stmt) ...@@ -3498,7 +3514,7 @@ visit_reference_op_call (tree lhs, gcall *stmt)
vr2->set = vr1.set; vr2->set = vr1.set;
vr2->hashcode = vr1.hashcode; vr2->hashcode = vr1.hashcode;
vr2->result = lhs; vr2->result = lhs;
vr2->result_vdef = vdef; vr2->result_vdef = vdef_val;
slot = current_info->references->find_slot_with_hash (vr2, vr2->hashcode, slot = current_info->references->find_slot_with_hash (vr2, vr2->hashcode,
INSERT); INSERT);
gcc_assert (!*slot); gcc_assert (!*slot);
...@@ -3912,11 +3928,22 @@ visit_use (tree use) ...@@ -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) if (!gimple_call_internal_p (call_stmt)
&& (/* Calls to the same function with the same vuse && (/* Calls to the same function with the same vuse
and the same operands do not necessarily return the same and the same operands do not necessarily return the same
value, unless they're pure or const. */ 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 /* If calls have a vdef, subsequent calls won't have
the same incoming vuse. So, if 2 calls with vdef have the the same incoming vuse. So, if 2 calls with vdef have the
same vuse, we know they're not subsequent. same vuse, we know they're not subsequent.
......
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