The following makes CCP track copies which avoids pass ordering issues between CCP and copyprop as seen from the testcase.
Bootstrapped and tested on x86_64-unknown-linux-gnu, queued for stage1. For stage1 I'd like to get rid of copyprop completely, a 2nd patch in the series will remove the copyprop instances immediately preceeding/following CCP. CCP needs some TLC and I'm going to apply that during stage1. Thanks, Richard. 2015-04-02 Richard Biener <rguent...@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. (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-36.c: New testcase. Index: gcc/tree-ssa-ccp.c =================================================================== *** gcc/tree-ssa-ccp.c.orig 2015-04-01 15:13:46.424457049 +0200 --- gcc/tree-ssa-ccp.c 2015-04-01 16:33:50.194715581 +0200 *************** valid_lattice_transition (ccp_prop_value *** 439,444 **** --- 439,455 ---- /* 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 *************** set_lattice_value (tree var, ccp_prop_va *** 527,535 **** 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))) { /* ??? We would like to delay creation of INTEGER_CSTs from partially constants here. */ --- 538,547 ---- 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) != 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. */ *************** ccp_finalize (void) *** 958,969 **** static void ccp_lattice_meet (ccp_prop_value_t *val1, ccp_prop_value_t *val2) { ! if (val1->lattice_val == UNDEFINED) { /* UNDEFINED M any = any */ *val1 = *val2; } ! else if (val2->lattice_val == UNDEFINED) { /* any M UNDEFINED = any Nothing to do. VAL1 already contains the value we want. */ --- 970,989 ---- static void ccp_lattice_meet (ccp_prop_value_t *val1, ccp_prop_value_t *val2) { ! if (val1->lattice_val == UNDEFINED ! /* For UNDEFINED M SSA we can't use SSA because its definition ! may not dominate the PHI node. */ ! && (val2->lattice_val != CONSTANT ! || TREE_CODE (val2->value) != SSA_NAME)) { /* UNDEFINED M any = any */ *val1 = *val2; } ! else if (val2->lattice_val == UNDEFINED ! /* For UNDEFINED M SSA we can't use SSA because its definition ! may not dominate the PHI node. */ ! && (val1->lattice_val != CONSTANT ! || TREE_CODE (val1->value) != SSA_NAME)) { /* any M UNDEFINED = any Nothing to do. VAL1 already contains the value we want. */ *************** bit_value_unop (enum tree_code code, tre *** 1513,1519 **** || rval.mask == -1); bit_value_unop_1 (code, type, &value, &mask, TREE_TYPE (rhs), value_to_wide_int (rval), rval.mask); ! if (mask != -1) { val.lattice_val = CONSTANT; val.mask = mask; --- 1533,1539 ---- || rval.mask == -1); bit_value_unop_1 (code, type, &value, &mask, TREE_TYPE (rhs), value_to_wide_int (rval), rval.mask); ! if (wi::sext (mask, TYPE_PRECISION (type)) != -1) { val.lattice_val = CONSTANT; val.mask = mask; *************** bit_value_binop (enum tree_code code, tr *** 1568,1574 **** bit_value_binop_1 (code, type, &value, &mask, TREE_TYPE (rhs1), value_to_wide_int (r1val), r1val.mask, TREE_TYPE (rhs2), value_to_wide_int (r2val), r2val.mask); ! if (mask != -1) { val.lattice_val = CONSTANT; val.mask = mask; --- 1588,1594 ---- bit_value_binop_1 (code, type, &value, &mask, TREE_TYPE (rhs1), value_to_wide_int (r1val), r1val.mask, TREE_TYPE (rhs2), value_to_wide_int (r2val), r2val.mask); ! if (wi::sext (mask, TYPE_PRECISION (type)) != -1) { val.lattice_val = CONSTANT; val.mask = mask; *************** bit_value_assume_aligned (gimple stmt, t *** 1669,1675 **** bit_value_binop_1 (BIT_AND_EXPR, type, &value, &mask, type, value_to_wide_int (ptrval), ptrval.mask, type, value_to_wide_int (alignval), alignval.mask); ! if (mask != -1) { val.lattice_val = CONSTANT; val.mask = mask; --- 1689,1695 ---- bit_value_binop_1 (BIT_AND_EXPR, type, &value, &mask, type, value_to_wide_int (ptrval), ptrval.mask, type, value_to_wide_int (alignval), alignval.mask); ! if (wi::sext (mask, TYPE_PRECISION (type)) != -1) { val.lattice_val = CONSTANT; val.mask = mask; *************** evaluate_stmt (gimple stmt) *** 1946,1960 **** if (likelyvalue == UNDEFINED) { val.lattice_val = likelyvalue; val.mask = 0; } else { val.lattice_val = VARYING; val.mask = -1; } - - val.value = NULL_TREE; } return val; --- 1966,1988 ---- if (likelyvalue == UNDEFINED) { val.lattice_val = likelyvalue; + val.value = NULL_TREE; val.mask = 0; } + /* The statement produced a copy. */ + else if (simplified && TREE_CODE (simplified) == SSA_NAME + && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (simplified)) + { + val.lattice_val = CONSTANT; + val.value = simplified; + val.mask = -1; + } else { val.lattice_val = VARYING; + val.value = NULL_TREE; val.mask = -1; } } return val; *************** static enum ssa_prop_result *** 2266,2292 **** visit_assignment (gimple stmt, tree *output_p) { ccp_prop_value_t val; ! enum ssa_prop_result retval; 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) { /* If STMT is an assignment to an SSA_NAME, we only have one value to set. */ if (set_lattice_value (lhs, val)) --- 2294,2308 ---- visit_assignment (gimple stmt, tree *output_p) { ccp_prop_value_t val; ! enum ssa_prop_result retval = SSA_PROP_NOT_INTERESTING; tree lhs = gimple_get_lhs (stmt); 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)) Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-36.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-36.c 2015-04-01 15:14:45.183125909 +0200 *************** *** 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" } } */ Index: gcc/gimple-match.h =================================================================== *** gcc/gimple-match.h.orig 2015-01-08 13:25:14.965227263 +0100 --- gcc/gimple-match.h 2015-04-01 15:14:45.183125909 +0200 *************** private: *** 41,47 **** }; bool gimple_simplify (gimple, code_helper *, tree *, gimple_seq *, ! 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); --- 41,47 ---- }; bool gimple_simplify (gimple, code_helper *, tree *, gimple_seq *, ! 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); Index: gcc/gimple-fold.c =================================================================== *** gcc/gimple-fold.c.orig 2015-03-19 13:22:12.073305248 +0100 --- gcc/gimple-fold.c 2015-04-01 15:14:45.184125920 +0200 *************** fold_stmt_1 (gimple_stmt_iterator *gsi, *** 3621,3627 **** gimple_seq seq = NULL; code_helper rcode; tree ops[3] = {}; ! if (gimple_simplify (stmt, &rcode, ops, inplace ? NULL : &seq, valueize)) { if (replace_stmt_with_simplification (gsi, rcode, ops, &seq, inplace)) changed = true; --- 3621,3628 ---- gimple_seq seq = NULL; code_helper rcode; tree ops[3] = {}; ! if (gimple_simplify (stmt, &rcode, ops, inplace ? NULL : &seq, ! valueize, valueize)) { if (replace_stmt_with_simplification (gsi, rcode, ops, &seq, inplace)) changed = true; *************** gimple_fold_stmt_to_constant_1 (gimple s *** 4928,4934 **** 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) && rcode.is_tree_code () && (TREE_CODE_LENGTH ((tree_code) rcode) == 0 || ((tree_code) rcode) == ADDR_EXPR) --- 4929,4935 ---- 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, valueize) && rcode.is_tree_code () && (TREE_CODE_LENGTH ((tree_code) rcode) == 0 || ((tree_code) rcode) == ADDR_EXPR) Index: gcc/gimple-match-head.c =================================================================== *** gcc/gimple-match-head.c.orig 2015-01-19 14:56:30.246131739 +0100 --- gcc/gimple-match-head.c 2015-04-01 15:14:45.184125920 +0200 *************** gimple_simplify (enum built_in_function *** 601,607 **** bool gimple_simplify (gimple stmt, code_helper *rcode, tree *ops, ! gimple_seq *seq, tree (*valueize)(tree)) { switch (gimple_code (stmt)) { --- 601,608 ---- bool gimple_simplify (gimple stmt, code_helper *rcode, tree *ops, ! gimple_seq *seq, ! tree (*valueize)(tree), tree (*top_valueize)(tree)) { switch (gimple_code (stmt)) { *************** gimple_simplify (gimple stmt, *** 617,625 **** || code == VIEW_CONVERT_EXPR) { tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0); ! if (valueize && TREE_CODE (op0) == SSA_NAME) { ! tree tem = valueize (op0); if (tem) op0 = tem; } --- 618,626 ---- || code == VIEW_CONVERT_EXPR) { tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0); ! if (top_valueize && TREE_CODE (op0) == SSA_NAME) { ! tree tem = top_valueize (op0); if (tem) op0 = tem; } *************** gimple_simplify (gimple stmt, *** 631,639 **** { tree rhs1 = gimple_assign_rhs1 (stmt); tree op0 = TREE_OPERAND (rhs1, 0); ! if (valueize && TREE_CODE (op0) == SSA_NAME) { ! tree tem = valueize (op0); if (tem) op0 = tem; } --- 632,640 ---- { tree rhs1 = gimple_assign_rhs1 (stmt); tree op0 = TREE_OPERAND (rhs1, 0); ! if (top_valueize && TREE_CODE (op0) == SSA_NAME) { ! tree tem = top_valueize (op0); if (tem) op0 = tem; } *************** gimple_simplify (gimple stmt, *** 644,653 **** return gimple_resimplify3 (seq, rcode, type, ops, valueize); } else if (code == SSA_NAME ! && valueize) { tree op0 = gimple_assign_rhs1 (stmt); ! tree valueized = valueize (op0); if (!valueized || op0 == valueized) return false; ops[0] = valueized; --- 645,654 ---- return gimple_resimplify3 (seq, rcode, type, ops, valueize); } else if (code == SSA_NAME ! && top_valueize) { tree op0 = gimple_assign_rhs1 (stmt); ! tree valueized = top_valueize (op0); if (!valueized || op0 == valueized) return false; ops[0] = valueized; *************** gimple_simplify (gimple stmt, *** 658,666 **** case GIMPLE_UNARY_RHS: { tree rhs1 = gimple_assign_rhs1 (stmt); ! if (valueize && TREE_CODE (rhs1) == SSA_NAME) { ! tree tem = valueize (rhs1); if (tem) rhs1 = tem; } --- 659,667 ---- case GIMPLE_UNARY_RHS: { tree rhs1 = gimple_assign_rhs1 (stmt); ! if (top_valueize && TREE_CODE (rhs1) == SSA_NAME) { ! tree tem = top_valueize (rhs1); if (tem) rhs1 = tem; } *************** gimple_simplify (gimple stmt, *** 671,686 **** case GIMPLE_BINARY_RHS: { tree rhs1 = gimple_assign_rhs1 (stmt); ! if (valueize && TREE_CODE (rhs1) == SSA_NAME) { ! tree tem = valueize (rhs1); if (tem) rhs1 = tem; } tree rhs2 = gimple_assign_rhs2 (stmt); ! if (valueize && TREE_CODE (rhs2) == SSA_NAME) { ! tree tem = valueize (rhs2); if (tem) rhs2 = tem; } --- 672,687 ---- case GIMPLE_BINARY_RHS: { tree rhs1 = gimple_assign_rhs1 (stmt); ! if (top_valueize && TREE_CODE (rhs1) == SSA_NAME) { ! tree tem = top_valueize (rhs1); if (tem) rhs1 = tem; } tree rhs2 = gimple_assign_rhs2 (stmt); ! if (top_valueize && TREE_CODE (rhs2) == SSA_NAME) { ! tree tem = top_valueize (rhs2); if (tem) rhs2 = tem; } *************** gimple_simplify (gimple stmt, *** 692,714 **** case GIMPLE_TERNARY_RHS: { tree rhs1 = gimple_assign_rhs1 (stmt); ! if (valueize && TREE_CODE (rhs1) == SSA_NAME) { ! tree tem = valueize (rhs1); if (tem) rhs1 = tem; } tree rhs2 = gimple_assign_rhs2 (stmt); ! if (valueize && TREE_CODE (rhs2) == SSA_NAME) { ! tree tem = valueize (rhs2); if (tem) rhs2 = tem; } tree rhs3 = gimple_assign_rhs3 (stmt); ! if (valueize && TREE_CODE (rhs3) == SSA_NAME) { ! tree tem = valueize (rhs3); if (tem) rhs3 = tem; } --- 693,715 ---- case GIMPLE_TERNARY_RHS: { tree rhs1 = gimple_assign_rhs1 (stmt); ! if (top_valueize && TREE_CODE (rhs1) == SSA_NAME) { ! tree tem = top_valueize (rhs1); if (tem) rhs1 = tem; } tree rhs2 = gimple_assign_rhs2 (stmt); ! if (top_valueize && TREE_CODE (rhs2) == SSA_NAME) { ! tree tem = top_valueize (rhs2); if (tem) rhs2 = tem; } tree rhs3 = gimple_assign_rhs3 (stmt); ! if (top_valueize && TREE_CODE (rhs3) == SSA_NAME) { ! tree tem = top_valueize (rhs3); if (tem) rhs3 = tem; } *************** gimple_simplify (gimple stmt, *** 732,740 **** /* ??? Internal function support missing. */ if (!fn) return false; ! if (valueize && TREE_CODE (fn) == SSA_NAME) { ! tree tem = valueize (fn); if (tem) fn = tem; } --- 733,741 ---- /* ??? Internal function support missing. */ if (!fn) return false; ! if (top_valueize && TREE_CODE (fn) == SSA_NAME) { ! tree tem = top_valueize (fn); if (tem) fn = tem; } *************** gimple_simplify (gimple stmt, *** 754,762 **** case 1: { tree arg1 = gimple_call_arg (stmt, 0); ! if (valueize && TREE_CODE (arg1) == SSA_NAME) { ! tree tem = valueize (arg1); if (tem) arg1 = tem; } --- 755,763 ---- case 1: { tree arg1 = gimple_call_arg (stmt, 0); ! if (top_valueize && TREE_CODE (arg1) == SSA_NAME) { ! tree tem = top_valueize (arg1); if (tem) arg1 = tem; } *************** gimple_simplify (gimple stmt, *** 767,782 **** case 2: { tree arg1 = gimple_call_arg (stmt, 0); ! if (valueize && TREE_CODE (arg1) == SSA_NAME) { ! tree tem = valueize (arg1); if (tem) arg1 = tem; } tree arg2 = gimple_call_arg (stmt, 1); ! if (valueize && TREE_CODE (arg2) == SSA_NAME) { ! tree tem = valueize (arg2); if (tem) arg2 = tem; } --- 768,783 ---- case 2: { tree arg1 = gimple_call_arg (stmt, 0); ! if (top_valueize && TREE_CODE (arg1) == SSA_NAME) { ! tree tem = top_valueize (arg1); if (tem) arg1 = tem; } tree arg2 = gimple_call_arg (stmt, 1); ! if (top_valueize && TREE_CODE (arg2) == SSA_NAME) { ! tree tem = top_valueize (arg2); if (tem) arg2 = tem; } *************** gimple_simplify (gimple stmt, *** 788,810 **** case 3: { tree arg1 = gimple_call_arg (stmt, 0); ! if (valueize && TREE_CODE (arg1) == SSA_NAME) { ! tree tem = valueize (arg1); if (tem) arg1 = tem; } tree arg2 = gimple_call_arg (stmt, 1); ! if (valueize && TREE_CODE (arg2) == SSA_NAME) { ! tree tem = valueize (arg2); if (tem) arg2 = tem; } tree arg3 = gimple_call_arg (stmt, 2); ! if (valueize && TREE_CODE (arg3) == SSA_NAME) { ! tree tem = valueize (arg3); if (tem) arg3 = tem; } --- 789,811 ---- case 3: { tree arg1 = gimple_call_arg (stmt, 0); ! if (top_valueize && TREE_CODE (arg1) == SSA_NAME) { ! tree tem = top_valueize (arg1); if (tem) arg1 = tem; } tree arg2 = gimple_call_arg (stmt, 1); ! if (top_valueize && TREE_CODE (arg2) == SSA_NAME) { ! tree tem = top_valueize (arg2); if (tem) arg2 = tem; } tree arg3 = gimple_call_arg (stmt, 2); ! if (top_valueize && TREE_CODE (arg3) == SSA_NAME) { ! tree tem = top_valueize (arg3); if (tem) arg3 = tem; } *************** gimple_simplify (gimple stmt, *** 823,838 **** case GIMPLE_COND: { tree lhs = gimple_cond_lhs (stmt); ! if (valueize && TREE_CODE (lhs) == SSA_NAME) { ! tree tem = valueize (lhs); if (tem) lhs = tem; } tree rhs = gimple_cond_rhs (stmt); ! if (valueize && TREE_CODE (rhs) == SSA_NAME) { ! tree tem = valueize (rhs); if (tem) rhs = tem; } --- 824,839 ---- case GIMPLE_COND: { tree lhs = gimple_cond_lhs (stmt); ! if (top_valueize && TREE_CODE (lhs) == SSA_NAME) { ! tree tem = top_valueize (lhs); if (tem) lhs = tem; } tree rhs = gimple_cond_rhs (stmt); ! if (top_valueize && TREE_CODE (rhs) == SSA_NAME) { ! tree tem = top_valueize (rhs); if (tem) rhs = tem; }