Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 236122) +++ gcc/tree-vrp.c (working copy) @@ -8940,6 +8940,8 @@ gassign *newop = gimple_build_assign (tem, BIT_XOR_EXPR, op0, op1); gsi_insert_before (gsi, newop, GSI_SAME_STMT); + if (TYPE_PRECISION (TREE_TYPE (tem)) > 1) + set_range_info (tem, VR_RANGE, 0, 1); gimple_assign_set_rhs_with_ops (gsi, NOP_EXPR, tem); } /* Or without. */ @@ -9648,7 +9650,6 @@ { tree innerop, middleop, finaltype; gimple *def_stmt; - value_range *innervr; signop inner_sgn, middle_sgn, final_sgn; unsigned inner_prec, middle_prec, final_prec; widest_int innermin, innermed, innermax, middlemin, middlemed, middlemax; @@ -9666,18 +9667,16 @@ || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop)) return false; - /* Get the value-range of the inner operand. */ - innervr = get_value_range (innerop); - if (innervr->type != VR_RANGE - || TREE_CODE (innervr->min) != INTEGER_CST - || TREE_CODE (innervr->max) != INTEGER_CST) + /* Get the value-range of the inner operand. Use get_range_info in + case innerop was created during substitute-and-fold. */ + wide_int imin, imax; + if (get_range_info (innerop, &imin, &imax) != VR_RANGE) return false; + innermin = widest_int::from (imin, TYPE_SIGN (TREE_TYPE (innerop))); + innermax = widest_int::from (imax, TYPE_SIGN (TREE_TYPE (innerop))); /* Simulate the conversion chain to check if the result is equal if the middle conversion is removed. */ - innermin = wi::to_widest (innervr->min); - innermax = wi::to_widest (innervr->max); - inner_prec = TYPE_PRECISION (TREE_TYPE (innerop)); middle_prec = TYPE_PRECISION (TREE_TYPE (middleop)); final_prec = TYPE_PRECISION (finaltype);