diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1c4c016f46fb23d1444475c94ced8b43f1afe394..ec00174d26dd112a40003002e1b4c19b4e1d58cb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2019-09-24  Jakub Jelinek  <jakub@redhat.com>
+
+	PR middle-end/91866
+	* match.pd (((T)(A)) + CST -> (T)(A + CST)): Formatting fix.
+	(((T)(A + CST1)) + CST2 -> (T)(A) + (T)CST1 + CST2): New optimization.
+
 2019-09-24  Martin Liska  <mliska@suse.cz>
 
 	* cfgexpand.c (gimple_assign_rhs_to_tree): Use switch statement
diff --git a/gcc/match.pd b/gcc/match.pd
index 4fd7590cc39fee6c58262fc68791de71952fdb32..23ce376802f670dccf2c008cd43410db00aecfab 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2265,8 +2265,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 			  max_ovf = wi::OVF_OVERFLOW;
         tree inner_type = TREE_TYPE (@0);
 
-        wide_int w1 = wide_int::from (wi::to_wide (@1), TYPE_PRECISION (inner_type),
-	    TYPE_SIGN (inner_type));
+	wide_int w1
+	  = wide_int::from (wi::to_wide (@1), TYPE_PRECISION (inner_type),
+			    TYPE_SIGN (inner_type));
 
         wide_int wmin0, wmax0;
         if (get_range_info (@0, &wmin0, &wmax0) == VR_RANGE)
@@ -2280,6 +2281,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
      )))
 #endif
 
+/* ((T)(A + CST1)) + CST2 -> (T)(A) + (T)CST1 + CST2  */
+#if GIMPLE
+  (for op (plus minus)
+   (simplify
+    (plus (convert:s (op:s @0 INTEGER_CST@1)) INTEGER_CST@2)
+     (if (TREE_CODE (TREE_TYPE (@0)) == INTEGER_TYPE
+	  && TREE_CODE (type) == INTEGER_TYPE
+	  && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@0))
+	  && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+	  && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0))
+	  && TYPE_OVERFLOW_WRAPS (type))
+       (plus (convert @0) (op @2 (convert @1))))))
+#endif
+
   /* ~A + A -> -1 */
   (simplify
    (plus:c (bit_not @0) @0)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 11710ba145d4ca7c52dd840d61ac4e516339bfc5..582a2a4c69f03948252a1b136cf9632b3fe6e74b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2019-09-24  Jakub Jelinek  <jakub@redhat.com>
+
+	PR middle-end/91866
+	* gcc.dg/tree-ssa/pr91866.c: New test.
+
 2019-09-24  Martin Jambor  <mjambor@suse.cz>
 
 	PR ipa/91831
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr91866.c b/gcc/testsuite/gcc.dg/tree-ssa/pr91866.c
new file mode 100644
index 0000000000000000000000000000000000000000..9f5bf197ff6fba256ba810e0b11c73b762eba5ba
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr91866.c
@@ -0,0 +1,12 @@
+/* PR middle-end/91866 */
+/* { dg-do compile { target { ilp32 || lp64 } } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } * /
+/* { dg-final { scan-tree-dump-times " \\+ 11;" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " \[+-] \[0-9-]\[0-9]*;" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\\(long long unsigned int\\) x_" 5 "optimized" } } */
+
+unsigned long long f1 (int x) { return (x + 1) - 1ULL; }
+unsigned long long f2 (int x) { return (x - 5) + 5ULL; }
+unsigned long long f3 (int x) { return (x - 15) + 26ULL; }
+unsigned long long f4 (int x) { return (x + 6) + 5ULL; }
+unsigned long long f5 (int x) { return (x - (-1 - __INT_MAX__)) + 10ULL - __INT_MAX__; }