+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
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;
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)
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))
{
|| 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;
}
{
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;
}
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;
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;
}
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;
}
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;
}
/* ??? 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;
}
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;
}
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;
}
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;
}
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;
}
};
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);
+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
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" } } */
--- /dev/null
+/* { dg-do compile } */\r
+/* { dg-options "-O -fdump-tree-ccp1" } */\r
+\r
+int foo (int i)\r
+{\r
+ int j = i;\r
+ int k = 0;\r
+ int l = j + k;\r
+ int m = l - j;\r
+ return m;\r
+}\r
+\r
+/* { dg-final { scan-tree-dump "return 0;" "ccp1" } } */\r
+/* { dg-final { cleanup-tree-dump "ccp1" } } */\r
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. */
/* { 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;
/* 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. */
/* { 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. */
/* 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
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. */
*/
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. */
*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
{
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))
{
/* 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;
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))