@@ -1290,6 +1290,70 @@ 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 overflow. */
+ (with
+ {
+ tree inner_type = TREE_TYPE (@3);
+ wide_int wmin0, wmax0;
+ wide_int w1 = @1;
+
+ bool ovf_undef = TYPE_OVERFLOW_UNDEFINED (inner_type);
+ bool min_ovf = true, max_ovf = true;
+
+ enum value_range_type vr0 = get_range_info (@0, &wmin0, &wmax0);
+
+ if (ovf_undef || vr0 == VR_RANGE)
+ {
+ 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);
+ }
+ w1 = w1.from (@1, TYPE_PRECISION (type), TYPE_SIGN (inner_type));
+ }
+ }
+ (if (ovf_undef || !(min_ovf || max_ovf))
+ (plus (convert @0) { wide_int_to_tree (type, wi::add (w1, @2)); }
+ )))))
+#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 overflow. */
+ (with
+ {
+ bool min_ovf = true, max_ovf = true;
+ tree inner_type = TREE_TYPE (@0);
+
+ wide_int w1 = w1.from (@1, 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)
+ (convert (plus @0 { {wide_int_to_tree (TREE_TYPE (@0), w1)}; })))
+ )))
+#endif
+
/* ~A + A -> -1 */
(simplify
(plus:c (bit_not @0) @0)