&& TREE_CODE (@3) == INTEGER_CST
&& (mul = wi::mul (wi::to_wide (@2), wi::to_wide (@3),
TYPE_SIGN (type), &overflow),
- !overflow))
+ !overflow)
+ && (TYPE_UNSIGNED (type)
+ /* Not using unsigned arithmetics is unsafe if factor
+ isn't 1 and if for op plus @0 and @2 could have different
+ sign or for op minus @0 and @2 could have the same sign. */
+ || known_eq (factor, 1)
+ || (get_range_pos_neg (@0)
+ | (((op == PLUS_EXPR) ^ (tree_int_cst_sgn (@2) < 0))
+ ? 1 : 2)) != 3))
(op (mult @0 { wide_int_to_tree (type, factor); })
{ wide_int_to_tree (type, mul); })
(with { tree utype = unsigned_type_for (type); }
/* { dg-final { scan-tree-dump-not {<[a-z]*_div_expr,} "optimized" } } */
/* { dg-final { scan-tree-dump-not {<rshift_expr,} "optimized" } } */
-/* { dg-final { scan-tree-dump-not {<nop_expr,} "optimized" } } */
+/* { dg-final { scan-tree-dump-times {<nop_expr,} 8 "optimized" } } */
/* { dg-final { scan-tree-dump {<mult_expr, [^,]*, [^,]*, 3,} "optimized" } } */
/* { dg-final { scan-tree-dump {<mult_expr, [^,]*, [^,]*, 5,} "optimized" } } */
/* { dg-final { scan-tree-dump {<mult_expr, [^,]*, [^,]*, 20,} "optimized" } } */
--- /dev/null
+/* PR tree-optimization/117692 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-final { scan-tree-dump " \\\* 25;" "vrp1" } } */
+/* { dg-final { scan-tree-dump " \\\+ 800;" "vrp1" } } */
+/* { dg-final { scan-tree-dump " = \\\(unsigned int\\\) " "vrp1" } } */
+/* { dg-final { scan-tree-dump " = \\\(int\\\) " "vrp1" } } */
+
+int
+foo (int x)
+{
+ if (x & 7)
+ __builtin_unreachable ();
+ x /= 8;
+ x += 4;
+ return x * 200;
+}
/* Return 1 if ARG interpreted as signed in its precision is known to be
- always positive or 2 if ARG is known to be always negative, or 3 if
- ARG may be positive or negative. */
+ always non-negative or 2 if ARG is known to be always negative, or 3 if
+ ARG may be non-negative or negative. */
int
get_range_pos_neg (tree arg)