diff --git a/gcc/match.pd b/gcc/match.pd index 80a17ba..ed497cf 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1290,6 +1290,79 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (cst && !TREE_OVERFLOW (cst)) (plus { cst; } @0)))) +/* ((T)(A + CST1)) + CST2 -> (T)(A) + CST */ +#if GIMPLE + (simplify + (plus (convert (plus@3 @0 INTEGER_CST@1)) INTEGER_CST@2) + (if (INTEGRAL_TYPE_P (type) + && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@3))) + /* Combine CST1 and CST2 to CST and convert to outer type if + (A + CST1)'s range does not wrap. */ + (with + { + tree inner_type = TREE_TYPE (@3); + wide_int wmin0, wmax0; + wide_int w1 = @1; + wide_int w2 = @2; + wide_int combined_cst; + + bool ovf_undef = TYPE_OVERFLOW_UNDEFINED (inner_type); + bool min_ovf = true, max_ovf = false; + + enum value_range_type vr0 = + get_range_info (@0, &wmin0, &wmax0); + + if (ovf_undef || vr0 == VR_RANGE) + { + bool ovf = true; + if (!ovf_undef && vr0 == VR_RANGE) + { + wi::add (wmin0, w1, TYPE_SIGN (inner_type), &min_ovf); + wi::add (wmax0, w1, TYPE_SIGN (inner_type), &max_ovf); + ovf = min_ovf || max_ovf; + } + + /* Extend CST1 to TYPE. */ + w1 = w1.from (w1, TYPE_PRECISION (type), + ovf ? SIGNED : TYPE_SIGN (inner_type)); + } + } + (if (ovf_undef || !((min_ovf && !max_ovf) || (!min_ovf && max_ovf))) + (plus (convert @0) { wide_int_to_tree (type, wi::add (w1, w2)); } + ))))) +#endif + +/* ((T)(A)) + CST -> (T)(A + CST) */ +#if GIMPLE + (simplify + (plus (convert SSA_NAME@0) INTEGER_CST@1) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && INTEGRAL_TYPE_P (type) + && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@0)) + && int_fits_type_p (@1, TREE_TYPE (@0))) + /* Perform binary operation inside the cast if the constant fits + and (A + CST)'s range does not wrap. */ + (with + { + bool min_ovf = true, max_ovf = false; + tree inner_type = TREE_TYPE (@0); + + wide_int w1 = @1; + w1 = w1.from (w1, TYPE_PRECISION (inner_type), TYPE_SIGN + (inner_type)); + + wide_int wmin0, wmax0; + if (get_range_info (@0, &wmin0, &wmax0) == VR_RANGE) + { + wi::add (wmin0, w1, TYPE_SIGN (inner_type), &min_ovf); + wi::add (wmax0, w1, TYPE_SIGN (inner_type), &max_ovf); + } + } + (if (!((min_ovf && !max_ovf) || (!min_ovf && max_ovf)) ) + (convert (plus @0 { {wide_int_to_tree (TREE_TYPE (@0), w1)}; }))) + ))) +#endif + /* ~A + A -> -1 */ (simplify (plus:c (bit_not @0) @0)