(for div (trunc_div ceil_div floor_div round_div exact_div)
(simplify
(div (mult:c @0 @1) @1)
- (if (ANY_INTEGRAL_TYPE_P (type)
- && TYPE_OVERFLOW_UNDEFINED (type))
- @0)))
+ (if (ANY_INTEGRAL_TYPE_P (type))
+ (if (TYPE_OVERFLOW_UNDEFINED (type))
+ @0
+#if GIMPLE
+ (if (TREE_CODE (@0) == SSA_NAME
+ && (TREE_CODE (@1) == SSA_NAME || TREE_CODE (@1) == INTEGER_CST))
+ (with
+ {
+ bool overflowed = true;
+ wide_int wmin0, wmax0;
+ if (get_range_info (@0, &wmin0, &wmax0) == VR_RANGE)
+ {
+ /* If the multiplication can't overflow/wrap around, then
+ it can be optimized too. */
+ wide_int wmin1, wmax1;
+ wi::overflow_type min_ovf, max_ovf;
+ if (TREE_CODE (@1) == INTEGER_CST)
+ {
+ wmin1 = wi::to_wide (@1);
+ wi::mul (wmin0, wmin1, TYPE_SIGN (type), &min_ovf);
+ wi::mul (wmax0, wmin1, TYPE_SIGN (type), &max_ovf);
+ if (min_ovf == wi::OVF_NONE && max_ovf == wi::OVF_NONE)
+ overflowed = false;
+ }
+ else if (get_range_info (@1, &wmin1, &wmax1) == VR_RANGE)
+ {
+ wi::mul (wmin0, wmin1, TYPE_SIGN (type), &min_ovf);
+ wi::mul (wmax0, wmax1, TYPE_SIGN (type), &max_ovf);
+ if (min_ovf == wi::OVF_NONE && max_ovf == wi::OVF_NONE)
+ {
+ wi::mul (wmin0, wmax1, TYPE_SIGN (type), &min_ovf);
+ wi::mul (wmax0, wmin1, TYPE_SIGN (type), &max_ovf);
+ if (min_ovf == wi::OVF_NONE && max_ovf == wi::OVF_NONE)
+ overflowed = false;
+ }
+ }
+ }
+ }
+ (if (!overflowed)
+ @0)))
+#endif
+ ))))
(for op (negate abs)
/* Simplify cos(-x) and cos(|x|) -> cos(x). Similarly for cosh. */
--- /dev/null
+/* PR tree-optimization/97997 */
+/* { dg-do compile { target { ilp32 || lp64 } } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "return x_\[0-9]*\\\(D\\\);" 6 "optimized" } } */
+/* { dg-final { scan-tree-dump-not " / " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " \\* " "optimized" } } */
+
+unsigned short
+f1 (unsigned short x)
+{
+ return x * 10 / 10;
+}
+
+unsigned short
+f2 (unsigned short x)
+{
+ int a = x;
+ int b = 10;
+ int c = 10;
+ return a * b / c;
+}
+
+unsigned short
+f3 (unsigned short x)
+{
+ return x * 10U / 10;
+}
+
+unsigned short
+f4 (unsigned short x)
+{
+ unsigned a = x;
+ unsigned b = 10;
+ unsigned c = 10;
+ return a * b / c;
+}
+
+unsigned short
+f5 (unsigned short x, unsigned short y)
+{
+ return (unsigned) x * y / y;
+}
+
+unsigned int
+f6 (unsigned int x, unsigned int y)
+{
+ if (x >= 30000)
+ __builtin_unreachable ();
+ if (y >= ~0U / 30000)
+ __builtin_unreachable ();
+ return x * y / y;
+}
--- /dev/null
+/* PR tree-optimization/97997 */
+/* { dg-do compile { target { ilp32 || lp64 } } } */
+/* { dg-options "-O2 -fdump-tree-optimized -fwrapv" } */
+/* { dg-final { scan-tree-dump-times "return x_\[0-9]*\\\(D\\\);" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-not " / " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " \\* " "optimized" } } */
+
+unsigned short
+f1 (unsigned short x)
+{
+ return x * 10 / 10;
+}
+
+unsigned short
+f2 (unsigned short x)
+{
+ int a = x;
+ int b = 10;
+ int c = 10;
+ return a * b / c;
+}
+
+short
+f3 (short x, short y)
+{
+ return x * y / y;
+}
+
+int
+f4 (int x, int y)
+{
+ if (x >= 30000)
+ __builtin_unreachable ();
+ if (x <= -30000)
+ __builtin_unreachable ();
+ if (y >= __INT_MAX__ / 30000)
+ __builtin_unreachable ();
+ if (y <= -__INT_MAX__ / 30000)
+ __builtin_unreachable ();
+ return x * y / y;
+}