int_range_max vr0;
if (ovf1 == wi::OVF_NONE && ovf2 == wi::OVF_NONE
&& gimple_match_range_of_expr (vr0, @4, @5)
- && !vr0.varying_p () && !vr0.undefined_p ())
+ && !vr0.varying_p ())
{
wide_int wmin0 = vr0.lower_bound ();
wide_int wmax0 = vr0.upper_bound ();
int_range_max vr0;
if (ovf1 == wi::OVF_NONE && ovf2 == wi::OVF_NONE
&& gimple_match_range_of_expr (vr0, @0, @4)
- && !vr0.varying_p () && !vr0.undefined_p ())
+ && !vr0.varying_p ())
{
wide_int wmin0 = vr0.lower_bound ();
wide_int wmax0 = vr0.upper_bound ();
/* "X+(N*M)" doesn't overflow. */
&& range_op_handler (PLUS_EXPR).overflow_free_p (vr0, vr3)
&& gimple_match_range_of_expr (vr4, @4)
- && !vr4.undefined_p ()
/* "X+N*M" is not with opposite sign as "X". */
&& (TYPE_UNSIGNED (type)
|| (vr0.nonnegative_p () && vr4.nonnegative_p ())
/* "X - (N*M)" doesn't overflow. */
&& range_op_handler (MINUS_EXPR).overflow_free_p (vr0, vr3)
&& gimple_match_range_of_expr (vr4, @4)
- && !vr4.undefined_p ()
/* "X-N*M" is not with opposite sign as "X". */
&& (TYPE_UNSIGNED (type)
|| (vr0.nonnegative_p () && vr4.nonnegative_p ())
/* (y << x) == x -> false and (y << x) != x -> true when y != 0. */
(for cmp (eq ne)
(simplify
- (cmp:c (nop_convert1? (lshift @0 @1)) (nop_convert2? @1))
- (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ (cmp:c (nop_convert1? (lshift @0 @1)) (convert2? @1))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
&& tree_expr_nonzero_p (@0))
{ constant_boolean_node (cmp != EQ_EXPR, type); })))
+#if GIMPLE
+/* (y << x) {<,<=} x -> false and (y << x) {>,>=} x -> true when y != 0
+ and (y << x) >> x == y and for signed comparison (y << x) >= 0. */
+(for cmp (gt ge lt le)
+ (simplify
+ (cmp:c (nop_convert1?@3 (lshift@2 @0 @1)) (convert2? @1))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))
+ (with { bool ok = false;
+ int_range_max vr0, vr1;
+ if (gimple_match_range_of_expr (vr0, @0, @2)
+ && !vr0.varying_p ()
+ && gimple_match_range_of_expr (vr1, @1, @2)
+ && !vr1.varying_p ()
+ && !vr0.contains_p (wi::zero (TYPE_PRECISION (TREE_TYPE (@0)))))
+ {
+ unsigned lz = wi::clz (vr0.get_nonzero_bits ());
+ if (!wi::neg_p (vr1.upper_bound (), TYPE_SIGN (TREE_TYPE (@1)))
+ && wi::ltu_p (vr1.upper_bound (),
+ wi::uhwi (lz + TYPE_UNSIGNED (TREE_TYPE (@3)),
+ TYPE_PRECISION (TREE_TYPE (@1)))))
+ ok = true;
+ } }
+ (if (ok)
+ { constant_boolean_node (cmp == GT_EXPR || cmp == GE_EXPR, type); })))))
+#endif
+
/* Fold (1 << (C - x)) where C = precision(type) - 1
into ((1 << C) >> x). */
(simplify
TYPE_SIGN (inner_type));
int_range_max vr;
- if (gimple_match_range_of_expr (vr, @0, @2)
- && !vr.varying_p () && !vr.undefined_p ())
+ if (gimple_match_range_of_expr (vr, @0, @2) && !vr.varying_p ())
{
wide_int wmin0 = vr.lower_bound ();
wide_int wmax0 = vr.upper_bound ();
|| wi::to_widest (@2) == wi::to_widest (@3) + 1))
(with {
int_range_max r;
- if (!gimple_match_range_of_expr (r, @0, @4)
- || r.undefined_p ())
+ if (!gimple_match_range_of_expr (r, @0, @4))
r.set_varying (TREE_TYPE (@0));
wide_int min = r.lower_bound ();
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "return 0;" 4 "optimized" { target bitint575 } } } */
+/* { dg-final { scan-tree-dump-times "return 0;" 2 "optimized" { target { ! bitint575 } } } } */
+/* { dg-final { scan-tree-dump-not " << " "optimized" } } */
+
+bool
+foo (unsigned long long x, unsigned y)
+{
+ if (x >= 64 || x == 0)
+ __builtin_unreachable ();
+ if (y > sizeof (unsigned long long) * __CHAR_BIT__ - 6)
+ __builtin_unreachable ();
+ return (x << y) <= y;
+}
+
+#if __BITINT_MAXWIDTH__ >= 575
+bool
+bar (unsigned _BitInt(575) x, unsigned y)
+{
+ if (x >= 1361129467683753853853498429727072845823uwb || x == 0)
+ __builtin_unreachable ();
+ if (y > 575 - 130)
+ __builtin_unreachable ();
+ return (x << y) < y;
+}
+
+bool
+baz (unsigned _BitInt(575) x, unsigned y)
+{
+ if (x >= 1361129467683753853853498429727072845823uwb || x == 0)
+ __builtin_unreachable ();
+ if (y >= 575 - 130)
+ __builtin_unreachable ();
+ return ((signed _BitInt(575)) (x << y)) < y;
+}
+#endif
+
+bool
+qux (int x, int y)
+{
+ if (x >= 128 || x <= 0)
+ __builtin_unreachable ();
+ if (y >= sizeof (int) * __CHAR_BIT__ - 7)
+ __builtin_unreachable ();
+ return (x << y) <= y;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "return 1;" 4 "optimized" { target bitint575 } } } */
+/* { dg-final { scan-tree-dump-times "return 1;" 2 "optimized" { target { ! bitint575 } } } } */
+/* { dg-final { scan-tree-dump-not " << " "optimized" } } */
+
+bool
+foo (unsigned long long x, unsigned y)
+{
+ if (x >= 64 || x == 0)
+ __builtin_unreachable ();
+ if (y > sizeof (unsigned long long) * __CHAR_BIT__ - 6)
+ __builtin_unreachable ();
+ return (x << y) >= y;
+}
+
+#if __BITINT_MAXWIDTH__ >= 575
+bool
+bar (unsigned _BitInt(575) x, unsigned y)
+{
+ if (x >= 1361129467683753853853498429727072845823uwb || x == 0)
+ __builtin_unreachable ();
+ if (y > 575 - 130)
+ __builtin_unreachable ();
+ return (x << y) > y;
+}
+
+bool
+baz (unsigned _BitInt(575) x, unsigned y)
+{
+ if (x >= 1361129467683753853853498429727072845823uwb || x == 0)
+ __builtin_unreachable ();
+ if (y >= 575 - 130)
+ __builtin_unreachable ();
+ return ((signed _BitInt(575)) (x << y)) > y;
+}
+#endif
+
+bool
+qux (int x, int y)
+{
+ if (x >= 128 || x <= 0)
+ __builtin_unreachable ();
+ if (y >= sizeof (int) * __CHAR_BIT__ - 7)
+ __builtin_unreachable ();
+ return (x << y) >= y;
+}