// We can be sure the values are always equal or not if both ranges
// consist of a single value, and then compare them.
- if (wi::eq_p (op1.lower_bound (), op1.upper_bound ())
- && wi::eq_p (op2.lower_bound (), op2.upper_bound ()))
+ bool op1_const = wi::eq_p (op1.lower_bound (), op1.upper_bound ());
+ bool op2_const = wi::eq_p (op2.lower_bound (), op2.upper_bound ());
+ if (op1_const && op2_const)
{
if (wi::eq_p (op1.lower_bound (), op2.upper_bound()))
r = range_true (type);
tmp.intersect (op2);
if (tmp.undefined_p ())
r = range_false (type);
+ // Check if a constant cannot satisfy the bitmask requirements.
+ else if (op2_const && !op1.get_bitmask ().member_p (op2.lower_bound ()))
+ r = range_false (type);
+ else if (op1_const && !op2.get_bitmask ().member_p (op1.lower_bound ()))
+ r = range_false (type);
else
r = range_true_and_false (type);
}
// We can be sure the values are always equal or not if both ranges
// consist of a single value, and then compare them.
- if (wi::eq_p (op1.lower_bound (), op1.upper_bound ())
- && wi::eq_p (op2.lower_bound (), op2.upper_bound ()))
+ bool op1_const = wi::eq_p (op1.lower_bound (), op1.upper_bound ());
+ bool op2_const = wi::eq_p (op2.lower_bound (), op2.upper_bound ());
+ if (op1_const && op2_const)
{
if (wi::ne_p (op1.lower_bound (), op2.upper_bound()))
r = range_true (type);
tmp.intersect (op2);
if (tmp.undefined_p ())
r = range_true (type);
+ // Check if a constant cannot satisfy the bitmask requirements.
+ else if (op2_const && !op1.get_bitmask ().member_p (op2.lower_bound ()))
+ r = range_true (type);
+ else if (op1_const && !op2.get_bitmask ().member_p (op1.lower_bound ()))
+ r = range_true (type);
else
r = range_true_and_false (type);
}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+int
+foo3n(int c, int bb)
+{
+ if ((bb & ~3)!=0) __builtin_unreachable(); // bb = [0,3]
+ if ((bb & 1)==0) __builtin_unreachable(); // bb&1 == 0 // [0],[3]
+ if(bb == 2) __builtin_trap();
+ return bb;
+}
+
+/* { dg-final { scan-tree-dump-not "trap" "evrp" } } */
void verify_mask () const;
void dump (FILE *) const;
+ bool member_p (const wide_int &val) const;
void adjust_range (irange &r) const;
// Convenience functions for nonzero bitmask compatibility.
verify_mask ();
}
+// Return TRUE if val could be a valid value with this bitmask.
+
+inline bool
+irange_bitmask::member_p (const wide_int &val) const
+{
+ if (unknown_p ())
+ return true;
+ wide_int res = m_mask & val;
+ if (m_value != 0)
+ res |= ~m_mask & m_value;
+ return res == val;
+}
+
inline bool
irange_bitmask::operator== (const irange_bitmask &src) const
{