Bootstrapped / tested on x86_64-unknown-linux-gnu, applied. Richard.
2016-07-15 Richard Biener <rguent...@suse.de> PR tree-optimization/71887 * tree-ssa-phiopt.c (absorbing_element_p): Add rhs arg and verify it is not zero for division / modulo handling. (value_replacement): Adjust. * gcc.dg/torture/pr71887.c: New testcase. Index: gcc/tree-ssa-phiopt.c =================================================================== *** gcc/tree-ssa-phiopt.c (revision 238364) --- gcc/tree-ssa-phiopt.c (working copy) *************** neutral_element_p (tree_code code, tree *** 812,818 **** /* Returns true if ARG is an absorbing element for operation CODE. */ static bool ! absorbing_element_p (tree_code code, tree arg, bool right) { switch (code) { --- 812,818 ---- /* Returns true if ARG is an absorbing element for operation CODE. */ static bool ! absorbing_element_p (tree_code code, tree arg, bool right, tree rval) { switch (code) { *************** absorbing_element_p (tree_code code, tre *** 827,832 **** --- 827,834 ---- case RSHIFT_EXPR: case LROTATE_EXPR: case RROTATE_EXPR: + return !right && integer_zerop (arg); + case TRUNC_DIV_EXPR: case CEIL_DIV_EXPR: case FLOOR_DIV_EXPR: *************** absorbing_element_p (tree_code code, tre *** 836,842 **** case CEIL_MOD_EXPR: case FLOOR_MOD_EXPR: case ROUND_MOD_EXPR: ! return !right && integer_zerop (arg); default: return false; --- 838,846 ---- case CEIL_MOD_EXPR: case FLOOR_MOD_EXPR: case ROUND_MOD_EXPR: ! return (!right ! && integer_zerop (arg) ! && tree_single_nonzero_warnv_p (rval, NULL)); default: return false; *************** value_replacement (basic_block cond_bb, *** 1010,1018 **** && neutral_element_p (code_def, cond_rhs, false)) || (operand_equal_for_phi_arg_p (arg1, cond_rhs) && ((operand_equal_for_phi_arg_p (rhs2, cond_lhs) ! && absorbing_element_p (code_def, cond_rhs, true)) || (operand_equal_for_phi_arg_p (rhs1, cond_lhs) ! && absorbing_element_p (code_def, cond_rhs, false)))))) { gsi = gsi_for_stmt (cond); if (INTEGRAL_TYPE_P (TREE_TYPE (lhs))) --- 1014,1023 ---- && neutral_element_p (code_def, cond_rhs, false)) || (operand_equal_for_phi_arg_p (arg1, cond_rhs) && ((operand_equal_for_phi_arg_p (rhs2, cond_lhs) ! && absorbing_element_p (code_def, cond_rhs, true, rhs2)) || (operand_equal_for_phi_arg_p (rhs1, cond_lhs) ! && absorbing_element_p (code_def, ! cond_rhs, false, rhs2)))))) { gsi = gsi_for_stmt (cond); if (INTEGRAL_TYPE_P (TREE_TYPE (lhs))) Index: gcc/testsuite/gcc.dg/torture/pr71887.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr71887.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr71887.c (working copy) *************** *** 0 **** --- 1,11 ---- + /* { dg-do run } */ + + char a; + int b; + + int main () + { + unsigned char c = a, d = a; + b = d == 0 ? c : c % d; + return 0; + }