@@ -148,8 +148,12 @@ along with GCC; see the file COPYING3. If not see
unsigned widen_precision = TYPE_PRECISION (TREE_TYPE (@2));
wide_int max = wi::mask (precision, false, widen_precision);
wide_int c4 = wi::to_wide (@4);
+ /* A source written with < rather than <= puts MAX - 1 in the compare.
+ The sum equal to MAX then takes the other arm, which is also MAX. */
+ wide_int c4_add_1 = wi::add (c4, wi::uhwi (1, widen_precision));
}
- (if (wi::eq_p (c4, max) && widen_precision > precision))))))
+ (if ((wi::eq_p (c4, max) || wi::eq_p (c4_add_1, max))
+ && widen_precision > precision))))))
/* Saturation sub for unsigned integer. */
(if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type))
new file mode 100644
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned long long u64;
+
+/* Written with < rather than <=, so the compare holds MAX - 1. The sum
+ equal to MAX takes the other arm, which is MAX as well. */
+
+u32
+lt32 (u32 a, u32 b)
+{
+ u64 t = (u64) a + b;
+ return (u32) (t < 0xffffffffull ? t : 0xffffffffull);
+}
+
+u32
+le32 (u32 a, u32 b)
+{
+ u64 t = (u64) a + b;
+ return (u32) (t <= 0xffffffffull ? t : 0xffffffffull);
+}
+
+u16
+lt16 (u16 a, u16 b)
+{
+ u32 t = (u32) a + b;
+ return (u16) (t < 0xffffu ? t : 0xffffu);
+}
+
+/* { dg-final { scan-tree-dump-times "\\.SAT_ADD " 3 "optimized" } } */