(shift @0 (bit_and @1 (minus @2 { build_int_cst (TREE_TYPE (@2),
1); }))))))
(simplify
- (mod @0 (convert?@3 (power_of_two_cand@1 @2)))
- (if ((TYPE_UNSIGNED (type)
- || tree_expr_nonnegative_p (@0))
- && tree_nop_conversion_p (type, TREE_TYPE (@3))
- && integer_pow2p (@2) && tree_int_cst_sgn (@2) > 0)
- (bit_and @0 (convert (minus @1 { build_int_cst (TREE_TYPE (@1), 1); }))))))
+ (mod @0 (convert? (power_of_two_cand@1 @2)))
+ (if ((TYPE_UNSIGNED (type) || tree_expr_nonnegative_p (@0))
+ /* Allow any integral conversions of the divisor, except
+ conversion from narrower signed to wider unsigned type
+ where if @1 would be negative power of two, the divisor
+ would not be a power of two. */
+ && INTEGRAL_TYPE_P (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1))
+ || TYPE_UNSIGNED (TREE_TYPE (@1))
+ || !TYPE_UNSIGNED (type))
+ && integer_pow2p (@2) && tree_int_cst_sgn (@2) > 0)
+ (with { tree utype = TREE_TYPE (@1);
+ if (!TYPE_OVERFLOW_WRAPS (utype))
+ utype = unsigned_type_for (utype); }
+ (bit_and @0 (convert (minus (convert:utype @1)
+ { build_one_cst (utype); })))))))
/* Simplify (unsigned t * 2)/2 -> unsigned t & 0x7FFFFFFF. */
(simplify
--- /dev/null
+/* PR tree-optimization/99079 */
+
+__attribute__((noipa)) unsigned long long
+foo (int x)
+{
+ unsigned long long s = 1 << x;
+ return 4897637220ULL % s;
+}
+
+int
+main ()
+{
+ if (__SIZEOF_INT__ * __CHAR_BIT__ != 32)
+ return 0;
+ if (foo (31) != 4897637220ULL)
+ __builtin_abort ();
+ return 0;
+}
--- /dev/null
+/* PR tree-optimization/99079 */
+/* { dg-do compile { target { lp64 || ilp32 } } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+unsigned int
+foo1 (unsigned int a, unsigned int b)
+{
+ return a % (1 << b);
+}
+
+int
+foo2 (int b)
+{
+ return 371 % (1U << b);
+}
+
+long long
+foo3 (int b)
+{
+ return 371LL % (1U << b);
+}
+
+unsigned long long
+foo4 (unsigned long long a, int b)
+{
+ return a % (1U << b);
+}
+
+unsigned
+foo5 (unsigned a, int b)
+{
+ return a % (unsigned) (1ULL << b);
+}
+
+int
+foo6 (int b)
+{
+ return 371 % (int) (1ULL << b);
+}
+
+long long
+foo7 (int b)
+{
+ return 371LL % (1 << b);
+}
+
+/* { dg-final { scan-tree-dump-not " % " "optimized" } } */