re PR tree-optimization/65650 (CCP does not propgate copies)

2015-04-21  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/65650
	* tree-ssa-ccp.c (valid_lattice_transition): Allow lattice
	transitions involving copies.
	(set_lattice_value): Adjust for copy lattice state.
	(ccp_lattice_meet): Do not merge UNDEFINED and a copy to the copy
	if that doesn't dominate the merge point.
	(bit_value_unop): Adjust what we treat as varying mask.
	(bit_value_binop): Likewise.
	(bit_value_assume_aligned): Likewise.
	(evaluate_stmt): When we simplified to a SSA name record a copy
	instead of dropping to varying.
	(visit_assignment): Simplify.

	* gimple-match.h (gimple_simplify): Add another callback.
	* gimple-fold.c (fold_stmt_1): Adjust caller.
	(gimple_fold_stmt_to_constant_1): Likewise - pass valueize
	for the 2nd callback.
	* gimple-match-head.c (gimple_simplify): Add a callback that is
	used to valueize the stmt operands and use it that way.

	* gcc.dg/tree-ssa/ssa-ccp-37.c: New testcase.
	* gcc.dg/tree-ssa/forwprop-11.c: Adjust.
	* gcc.dg/tree-ssa/ssa-fre-3.c: Likewise.
	* gcc.dg/tree-ssa/ssa-fre-4.c: Likewise.
	* gcc.dg/tree-ssa/ssa-fre-5.c: Likewise.
	* gcc.dg/tree-ssa/ssa-fre-32.c: Likewise.

From-SVN: r222267
This commit is contained in:
Richard Biener 2015-04-21 12:52:43 +00:00 committed by Richard Biener
parent 9588d24871
commit 0ff093d855
12 changed files with 142 additions and 73 deletions

View File

@ -1,3 +1,25 @@
2015-04-21 Richard Biener <rguenther@suse.de>
PR tree-optimization/65650
* tree-ssa-ccp.c (valid_lattice_transition): Allow lattice
transitions involving copies.
(set_lattice_value): Adjust for copy lattice state.
(ccp_lattice_meet): Do not merge UNDEFINED and a copy to the copy
if that doesn't dominate the merge point.
(bit_value_unop): Adjust what we treat as varying mask.
(bit_value_binop): Likewise.
(bit_value_assume_aligned): Likewise.
(evaluate_stmt): When we simplified to a SSA name record a copy
instead of dropping to varying.
(visit_assignment): Simplify.
* gimple-match.h (gimple_simplify): Add another callback.
* gimple-fold.c (fold_stmt_1): Adjust caller.
(gimple_fold_stmt_to_constant_1): Likewise - pass valueize
for the 2nd callback.
* gimple-match-head.c (gimple_simplify): Add a callback that is
used to valueize the stmt operands and use it that way.
2015-04-21 Richard Biener <rguenther@suse.de>
PR tree-optimization/65788

View File

@ -3621,7 +3621,8 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree))
gimple_seq seq = NULL;
code_helper rcode;
tree ops[3] = {};
if (gimple_simplify (stmt, &rcode, ops, inplace ? NULL : &seq, valueize))
if (gimple_simplify (stmt, &rcode, ops, inplace ? NULL : &seq,
valueize, valueize))
{
if (replace_stmt_with_simplification (gsi, rcode, ops, &seq, inplace))
changed = true;
@ -4928,7 +4929,7 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree),
edges if there are intermediate VARYING defs. For this reason
do not follow SSA edges here even though SCCVN can technically
just deal fine with that. */
if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize)
if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize)
&& rcode.is_tree_code ()
&& (TREE_CODE_LENGTH ((tree_code) rcode) == 0
|| ((tree_code) rcode) == ADDR_EXPR)

View File

@ -601,7 +601,8 @@ gimple_simplify (enum built_in_function fn, tree type,
bool
gimple_simplify (gimple stmt,
code_helper *rcode, tree *ops,
gimple_seq *seq, tree (*valueize)(tree))
gimple_seq *seq,
tree (*valueize)(tree), tree (*top_valueize)(tree))
{
switch (gimple_code (stmt))
{
@ -617,9 +618,9 @@ gimple_simplify (gimple stmt,
|| code == VIEW_CONVERT_EXPR)
{
tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
if (valueize && TREE_CODE (op0) == SSA_NAME)
if (top_valueize && TREE_CODE (op0) == SSA_NAME)
{
tree tem = valueize (op0);
tree tem = top_valueize (op0);
if (tem)
op0 = tem;
}
@ -631,9 +632,9 @@ gimple_simplify (gimple stmt,
{
tree rhs1 = gimple_assign_rhs1 (stmt);
tree op0 = TREE_OPERAND (rhs1, 0);
if (valueize && TREE_CODE (op0) == SSA_NAME)
if (top_valueize && TREE_CODE (op0) == SSA_NAME)
{
tree tem = valueize (op0);
tree tem = top_valueize (op0);
if (tem)
op0 = tem;
}
@ -644,10 +645,10 @@ gimple_simplify (gimple stmt,
return gimple_resimplify3 (seq, rcode, type, ops, valueize);
}
else if (code == SSA_NAME
&& valueize)
&& top_valueize)
{
tree op0 = gimple_assign_rhs1 (stmt);
tree valueized = valueize (op0);
tree valueized = top_valueize (op0);
if (!valueized || op0 == valueized)
return false;
ops[0] = valueized;
@ -658,9 +659,9 @@ gimple_simplify (gimple stmt,
case GIMPLE_UNARY_RHS:
{
tree rhs1 = gimple_assign_rhs1 (stmt);
if (valueize && TREE_CODE (rhs1) == SSA_NAME)
if (top_valueize && TREE_CODE (rhs1) == SSA_NAME)
{
tree tem = valueize (rhs1);
tree tem = top_valueize (rhs1);
if (tem)
rhs1 = tem;
}
@ -671,16 +672,16 @@ gimple_simplify (gimple stmt,
case GIMPLE_BINARY_RHS:
{
tree rhs1 = gimple_assign_rhs1 (stmt);
if (valueize && TREE_CODE (rhs1) == SSA_NAME)
if (top_valueize && TREE_CODE (rhs1) == SSA_NAME)
{
tree tem = valueize (rhs1);
tree tem = top_valueize (rhs1);
if (tem)
rhs1 = tem;
}
tree rhs2 = gimple_assign_rhs2 (stmt);
if (valueize && TREE_CODE (rhs2) == SSA_NAME)
if (top_valueize && TREE_CODE (rhs2) == SSA_NAME)
{
tree tem = valueize (rhs2);
tree tem = top_valueize (rhs2);
if (tem)
rhs2 = tem;
}
@ -692,23 +693,23 @@ gimple_simplify (gimple stmt,
case GIMPLE_TERNARY_RHS:
{
tree rhs1 = gimple_assign_rhs1 (stmt);
if (valueize && TREE_CODE (rhs1) == SSA_NAME)
if (top_valueize && TREE_CODE (rhs1) == SSA_NAME)
{
tree tem = valueize (rhs1);
tree tem = top_valueize (rhs1);
if (tem)
rhs1 = tem;
}
tree rhs2 = gimple_assign_rhs2 (stmt);
if (valueize && TREE_CODE (rhs2) == SSA_NAME)
if (top_valueize && TREE_CODE (rhs2) == SSA_NAME)
{
tree tem = valueize (rhs2);
tree tem = top_valueize (rhs2);
if (tem)
rhs2 = tem;
}
tree rhs3 = gimple_assign_rhs3 (stmt);
if (valueize && TREE_CODE (rhs3) == SSA_NAME)
if (top_valueize && TREE_CODE (rhs3) == SSA_NAME)
{
tree tem = valueize (rhs3);
tree tem = top_valueize (rhs3);
if (tem)
rhs3 = tem;
}
@ -732,9 +733,9 @@ gimple_simplify (gimple stmt,
/* ??? Internal function support missing. */
if (!fn)
return false;
if (valueize && TREE_CODE (fn) == SSA_NAME)
if (top_valueize && TREE_CODE (fn) == SSA_NAME)
{
tree tem = valueize (fn);
tree tem = top_valueize (fn);
if (tem)
fn = tem;
}
@ -754,9 +755,9 @@ gimple_simplify (gimple stmt,
case 1:
{
tree arg1 = gimple_call_arg (stmt, 0);
if (valueize && TREE_CODE (arg1) == SSA_NAME)
if (top_valueize && TREE_CODE (arg1) == SSA_NAME)
{
tree tem = valueize (arg1);
tree tem = top_valueize (arg1);
if (tem)
arg1 = tem;
}
@ -767,16 +768,16 @@ gimple_simplify (gimple stmt,
case 2:
{
tree arg1 = gimple_call_arg (stmt, 0);
if (valueize && TREE_CODE (arg1) == SSA_NAME)
if (top_valueize && TREE_CODE (arg1) == SSA_NAME)
{
tree tem = valueize (arg1);
tree tem = top_valueize (arg1);
if (tem)
arg1 = tem;
}
tree arg2 = gimple_call_arg (stmt, 1);
if (valueize && TREE_CODE (arg2) == SSA_NAME)
if (top_valueize && TREE_CODE (arg2) == SSA_NAME)
{
tree tem = valueize (arg2);
tree tem = top_valueize (arg2);
if (tem)
arg2 = tem;
}
@ -788,23 +789,23 @@ gimple_simplify (gimple stmt,
case 3:
{
tree arg1 = gimple_call_arg (stmt, 0);
if (valueize && TREE_CODE (arg1) == SSA_NAME)
if (top_valueize && TREE_CODE (arg1) == SSA_NAME)
{
tree tem = valueize (arg1);
tree tem = top_valueize (arg1);
if (tem)
arg1 = tem;
}
tree arg2 = gimple_call_arg (stmt, 1);
if (valueize && TREE_CODE (arg2) == SSA_NAME)
if (top_valueize && TREE_CODE (arg2) == SSA_NAME)
{
tree tem = valueize (arg2);
tree tem = top_valueize (arg2);
if (tem)
arg2 = tem;
}
tree arg3 = gimple_call_arg (stmt, 2);
if (valueize && TREE_CODE (arg3) == SSA_NAME)
if (top_valueize && TREE_CODE (arg3) == SSA_NAME)
{
tree tem = valueize (arg3);
tree tem = top_valueize (arg3);
if (tem)
arg3 = tem;
}
@ -823,16 +824,16 @@ gimple_simplify (gimple stmt,
case GIMPLE_COND:
{
tree lhs = gimple_cond_lhs (stmt);
if (valueize && TREE_CODE (lhs) == SSA_NAME)
if (top_valueize && TREE_CODE (lhs) == SSA_NAME)
{
tree tem = valueize (lhs);
tree tem = top_valueize (lhs);
if (tem)
lhs = tem;
}
tree rhs = gimple_cond_rhs (stmt);
if (valueize && TREE_CODE (rhs) == SSA_NAME)
if (top_valueize && TREE_CODE (rhs) == SSA_NAME)
{
tree tem = valueize (rhs);
tree tem = top_valueize (rhs);
if (tem)
rhs = tem;
}

View File

@ -41,7 +41,7 @@ private:
};
bool gimple_simplify (gimple, code_helper *, tree *, gimple_seq *,
tree (*)(tree));
tree (*)(tree), tree (*)(tree));
tree maybe_push_res_to_seq (code_helper, tree, tree *,
gimple_seq *, tree res = NULL_TREE);
void maybe_build_generic_op (enum tree_code, tree, tree *, tree, tree);

View File

@ -1,3 +1,13 @@
2015-04-21 Richard Biener <rguenther@suse.de>
PR tree-optimization/65650
* gcc.dg/tree-ssa/ssa-ccp-37.c: New testcase.
* gcc.dg/tree-ssa/forwprop-11.c: Adjust.
* gcc.dg/tree-ssa/ssa-fre-3.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-4.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-5.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-32.c: Likewise.
2015-04-21 Tom de Vries <tom@codesourcery.com>
PR tree-optimization/65802

View File

@ -16,5 +16,5 @@ int g(int *p, int n)
return q[-1];
}
/* { dg-final { scan-tree-dump-times "= MEM\\\[\\\(int \\\*\\\)\[ap\]_.. \\\+ 4B\\\];" 2 "forwprop1" } } */
/* { dg-final { scan-tree-dump-times "= MEM\\\[\\\(int \\\*\\\)\[ap\]_\[0-9\]+(?:\\(D\\))? \\\+ 4B\\\];" 2 "forwprop1" } } */
/* { dg-final { cleanup-tree-dump "forwprop1" } } */

View File

@ -0,0 +1,14 @@
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-ccp1" } */
int foo (int i)
{
int j = i;
int k = 0;
int l = j + k;
int m = l - j;
return m;
}
/* { dg-final { scan-tree-dump "return 0;" "ccp1" } } */
/* { dg-final { cleanup-tree-dump "ccp1" } } */

View File

@ -6,7 +6,7 @@
When the condition is true, we distribute "(int) (a + b)" as
"(int) a + (int) b", otherwise we keep the original. */
/* { dg-do compile { target { { ! mips64 } && { ! spu-*-* } } } } */
/* { dg-options "-O -fno-tree-forwprop -fwrapv -fdump-tree-fre1-details" } */
/* { dg-options "-O -fno-tree-forwprop -fno-tree-ccp -fwrapv -fdump-tree-fre1-details" } */
/* From PR14844. */

View File

@ -1,5 +1,5 @@
/* { dg-do compile } */
/* { dg-options "-O -fno-tree-forwprop -fdump-tree-fre1-details" } */
/* { dg-options "-O -fno-tree-forwprop -fno-tree-ccp -fdump-tree-fre1-details" } */
_Complex float m;

View File

@ -1,7 +1,7 @@
/* If the target returns false for TARGET_PROMOTE_PROTOTYPES, then there
will be no casts for FRE to eliminate and the test will fail. */
/* { dg-do compile { target i?86-*-* x86_64-*-* hppa*-*-* mips*-*-* m68k*-*-* } } */
/* { dg-options "-O -fno-tree-forwprop -fdump-tree-fre1-details" } */
/* { dg-options "-O -fno-tree-ccp -fno-tree-forwprop -fdump-tree-fre1-details" } */
/* From PR21608. */

View File

@ -1,5 +1,5 @@
/* { dg-do compile } */
/* { dg-options "-O -fno-tree-forwprop -fdump-tree-fre1-details" } */
/* { dg-options "-O -fno-tree-ccp -fno-tree-forwprop -fdump-tree-fre1-details" } */
/* From PR19792. */

View File

@ -439,6 +439,17 @@ valid_lattice_transition (ccp_prop_value_t old_val, ccp_prop_value_t new_val)
/* Now both lattice values are CONSTANT. */
/* Allow arbitrary copy changes as we might look through PHI <a_1, ...>
when only a single copy edge is executable. */
if (TREE_CODE (old_val.value) == SSA_NAME
&& TREE_CODE (new_val.value) == SSA_NAME)
return true;
/* Allow transitioning from a constant to a copy. */
if (is_gimple_min_invariant (old_val.value)
&& TREE_CODE (new_val.value) == SSA_NAME)
return true;
/* Allow transitioning from PHI <&x, not executable> == &x
to PHI <&x, &y> == common alignment. */
if (TREE_CODE (old_val.value) != INTEGER_CST
@ -527,9 +538,10 @@ set_lattice_value (tree var, ccp_prop_value_t new_val)
caller that this was a non-transition. */
if (old_val->lattice_val != new_val.lattice_val
|| (new_val.lattice_val == CONSTANT
&& TREE_CODE (new_val.value) == INTEGER_CST
&& (TREE_CODE (old_val->value) != INTEGER_CST
|| new_val.mask != old_val->mask)))
&& (TREE_CODE (new_val.value) != TREE_CODE (old_val->value)
|| simple_cst_equal (new_val.value, old_val->value) != 1
|| (TREE_CODE (new_val.value) == INTEGER_CST
&& new_val.mask != old_val->mask))))
{
/* ??? We would like to delay creation of INTEGER_CSTs from
partially constants here. */
@ -965,14 +977,23 @@ ccp_finalize (void)
*/
static void
ccp_lattice_meet (ccp_prop_value_t *val1, ccp_prop_value_t *val2)
ccp_lattice_meet (basic_block where,
ccp_prop_value_t *val1, ccp_prop_value_t *val2)
{
if (val1->lattice_val == UNDEFINED)
if (val1->lattice_val == UNDEFINED
/* For UNDEFINED M SSA we can't always SSA because its definition
may not dominate the PHI node. Doing optimistic copy propagation
also causes a lot of gcc.dg/uninit-pred*.c FAILs. */
&& (val2->lattice_val != CONSTANT
|| TREE_CODE (val2->value) != SSA_NAME))
{
/* UNDEFINED M any = any */
*val1 = *val2;
}
else if (val2->lattice_val == UNDEFINED)
else if (val2->lattice_val == UNDEFINED
/* See above. */
&& (val1->lattice_val != CONSTANT
|| TREE_CODE (val1->value) != SSA_NAME))
{
/* any M UNDEFINED = any
Nothing to do. VAL1 already contains the value we want. */
@ -1026,7 +1047,7 @@ ccp_lattice_meet (ccp_prop_value_t *val1, ccp_prop_value_t *val2)
*val1 = get_value_for_expr (val1->value, true);
if (TREE_CODE (val2->value) == ADDR_EXPR)
tem = get_value_for_expr (val2->value, true);
ccp_lattice_meet (val1, &tem);
ccp_lattice_meet (where, val1, &tem);
}
else
{
@ -1095,7 +1116,7 @@ ccp_visit_phi_node (gphi *phi)
tree arg = gimple_phi_arg (phi, i)->def;
ccp_prop_value_t arg_val = get_value_for_expr (arg, false);
ccp_lattice_meet (&new_val, &arg_val);
ccp_lattice_meet (gimple_bb (phi), &new_val, &arg_val);
if (dump_file && (dump_flags & TDF_DETAILS))
{
@ -1929,9 +1950,21 @@ evaluate_stmt (gimple stmt)
/* The statement produced a nonconstant value. */
if (!is_constant)
{
val.lattice_val = VARYING;
val.mask = -1;
val.value = NULL_TREE;
/* The statement produced a copy. */
if (simplified && TREE_CODE (simplified) == SSA_NAME
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (simplified))
{
val.lattice_val = CONSTANT;
val.value = simplified;
val.mask = -1;
}
/* The statement is VARYING. */
else
{
val.lattice_val = VARYING;
val.value = NULL_TREE;
val.mask = -1;
}
}
return val;
@ -2243,27 +2276,15 @@ static enum ssa_prop_result
visit_assignment (gimple stmt, tree *output_p)
{
ccp_prop_value_t val;
enum ssa_prop_result retval;
enum ssa_prop_result retval = SSA_PROP_NOT_INTERESTING;
tree lhs = gimple_get_lhs (stmt);
gcc_assert (gimple_code (stmt) != GIMPLE_CALL
|| gimple_call_lhs (stmt) != NULL_TREE);
if (gimple_assign_single_p (stmt)
&& gimple_assign_rhs_code (stmt) == SSA_NAME)
/* For a simple copy operation, we copy the lattice values. */
val = *get_value (gimple_assign_rhs1 (stmt));
else
/* Evaluate the statement, which could be
either a GIMPLE_ASSIGN or a GIMPLE_CALL. */
val = evaluate_stmt (stmt);
retval = SSA_PROP_NOT_INTERESTING;
/* Set the lattice value of the statement's output. */
if (TREE_CODE (lhs) == SSA_NAME)
{
/* Evaluate the statement, which could be
either a GIMPLE_ASSIGN or a GIMPLE_CALL. */
val = evaluate_stmt (stmt);
/* If STMT is an assignment to an SSA_NAME, we only have one
value to set. */
if (set_lattice_value (lhs, val))