This fixes fallout of my SCEV correctness change where reassoc no longer sees the ~A + A simplification opportunity due to casts that are in the way.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2016-02-29 Richard Biener <rguent...@suse.de> PR tree-optimization/69994 * tree-ssa-reassoc.c (gimple_nop_conversion_p): New function. (get_unary_op): Look through nop conversions. (ops_equal_values_p): New function, look for equality diregarding nop conversions. (eliminate_plus_minus_pair): Use ops_equal_values_p (repropagate_negates): Do not use get_unary_op here. Index: gcc/tree-ssa-reassoc.c =================================================================== *** gcc/tree-ssa-reassoc.c (revision 233803) --- gcc/tree-ssa-reassoc.c (working copy) *************** is_reassociable_op (gimple *stmt, enum t *** 605,610 **** --- 605,625 ---- } + /* Return true if STMT is a nop-conversion. */ + + static bool + gimple_nop_conversion_p (gimple *stmt) + { + if (gassign *ass = dyn_cast <gassign *> (stmt)) + { + if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (ass)) + && tree_nop_conversion_p (TREE_TYPE (gimple_assign_lhs (ass)), + TREE_TYPE (gimple_assign_rhs1 (ass)))) + return true; + } + return false; + } + /* Given NAME, if NAME is defined by a unary operation OPCODE, return the operand of the negate operation. Otherwise, return NULL. */ *************** get_unary_op (tree name, enum tree_code *** 613,618 **** --- 628,638 ---- { gimple *stmt = SSA_NAME_DEF_STMT (name); + /* Look through nop conversions (sign changes). */ + if (gimple_nop_conversion_p (stmt) + && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME) + stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt)); + if (!is_gimple_assign (stmt)) return NULL_TREE; *************** get_unary_op (tree name, enum tree_code *** 621,626 **** --- 641,680 ---- return NULL_TREE; } + /* Return true if OP1 and OP2 have the same value if casted to either type. */ + + static bool + ops_equal_values_p (tree op1, tree op2) + { + if (op1 == op2) + return true; + + if (TREE_CODE (op1) == SSA_NAME) + { + gimple *stmt = SSA_NAME_DEF_STMT (op1); + if (gimple_nop_conversion_p (stmt)) + { + op1 = gimple_assign_rhs1 (stmt); + if (op1 == op2) + return true; + } + } + + if (TREE_CODE (op2) == SSA_NAME) + { + gimple *stmt = SSA_NAME_DEF_STMT (op2); + if (gimple_nop_conversion_p (stmt)) + { + op2 = gimple_assign_rhs1 (stmt); + if (op1 == op2) + return true; + } + } + + return false; + } + + /* If CURR and LAST are a pair of ops that OPCODE allows us to eliminate through equivalences, do so, remove them from OPS, and return true. Otherwise, return false. */ *************** eliminate_plus_minus_pair (enum tree_cod *** 731,739 **** && oe->rank >= curr->rank - 1 ; i++) { ! if (oe->op == negateop) { - if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Equivalence: "); --- 785,793 ---- && oe->rank >= curr->rank - 1 ; i++) { ! if (negateop ! && ops_equal_values_p (oe->op, negateop)) { if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Equivalence: "); *************** eliminate_plus_minus_pair (enum tree_cod *** 750,756 **** return true; } ! else if (oe->op == notop) { tree op_type = TREE_TYPE (oe->op); --- 804,811 ---- return true; } ! else if (notop ! && ops_equal_values_p (oe->op, notop)) { tree op_type = TREE_TYPE (oe->op); *************** eliminate_plus_minus_pair (enum tree_cod *** 772,780 **** } } ! /* CURR->OP is a negate expr in a plus expr: save it for later ! inspection in repropagate_negates(). */ ! if (negateop != NULL_TREE) plus_negates.safe_push (curr->op); return false; --- 827,836 ---- } } ! /* If CURR->OP is a negate expr without nop conversion in a plus expr: ! save it for later inspection in repropagate_negates(). */ ! if (negateop != NULL_TREE ! && gimple_assign_rhs_code (SSA_NAME_DEF_STMT (curr->op)) == NEGATE_EXPR) plus_negates.safe_push (curr->op); return false; *************** repropagate_negates (void) *** 4211,4217 **** if (gimple_assign_rhs2 (user) == negate) { tree rhs1 = gimple_assign_rhs1 (user); ! tree rhs2 = get_unary_op (negate, NEGATE_EXPR); gimple_stmt_iterator gsi = gsi_for_stmt (user); gimple_assign_set_rhs_with_ops (&gsi, MINUS_EXPR, rhs1, rhs2); update_stmt (user); --- 4267,4273 ---- if (gimple_assign_rhs2 (user) == negate) { tree rhs1 = gimple_assign_rhs1 (user); ! tree rhs2 = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (negate)); gimple_stmt_iterator gsi = gsi_for_stmt (user); gimple_assign_set_rhs_with_ops (&gsi, MINUS_EXPR, rhs1, rhs2); update_stmt (user);