aboutsummaryrefslogtreecommitdiff
path: root/gcc/range-op.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/range-op.cc')
-rw-r--r--gcc/range-op.cc60
1 files changed, 59 insertions, 1 deletions
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 35b3e18..e2b9c82 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -164,6 +164,8 @@ dispatch_trio (unsigned lhs, unsigned op1, unsigned op2)
// These are the supported dispatch patterns. These map to the parameter list
// of the routines in range_operator. Note the last 3 characters are
// shorthand for the LHS, OP1, and OP2 range discriminator class.
+// Reminder, single operand instructions use the LHS type for op2, even if
+// unused. so FLOAT = INT would be RO_FIF.
const unsigned RO_III = dispatch_trio (VR_IRANGE, VR_IRANGE, VR_IRANGE);
const unsigned RO_IFI = dispatch_trio (VR_IRANGE, VR_FRANGE, VR_IRANGE);
@@ -246,6 +248,10 @@ range_op_handler::fold_range (vrange &r, tree type,
return m_operator->fold_range (as_a <frange> (r), type,
as_a <irange> (lh),
as_a <irange> (rh), rel);
+ case RO_FIF:
+ return m_operator->fold_range (as_a <frange> (r), type,
+ as_a <irange> (lh),
+ as_a <frange> (rh), rel);
case RO_PPP:
return m_operator->fold_range (as_a <prange> (r), type,
as_a <prange> (lh),
@@ -292,6 +298,10 @@ range_op_handler::op1_range (vrange &r, tree type,
return m_operator->op1_range (as_a <irange> (r), type,
as_a <irange> (lhs),
as_a <irange> (op2), rel);
+ case RO_IFF:
+ return m_operator->op1_range (as_a <irange> (r), type,
+ as_a <frange> (lhs),
+ as_a <frange> (op2), rel);
case RO_PPP:
return m_operator->op1_range (as_a <prange> (r), type,
as_a <prange> (lhs),
@@ -312,6 +322,10 @@ range_op_handler::op1_range (vrange &r, tree type,
return m_operator->op1_range (as_a <frange> (r), type,
as_a <irange> (lhs),
as_a <frange> (op2), rel);
+ case RO_FII:
+ return m_operator->op1_range (as_a <frange> (r), type,
+ as_a <irange> (lhs),
+ as_a <irange> (op2), rel);
case RO_FFF:
return m_operator->op1_range (as_a <frange> (r), type,
as_a <frange> (lhs),
@@ -761,6 +775,30 @@ range_operator::fold_range (irange &r, tree type,
return true;
}
+
+bool
+range_operator::fold_range (frange &, tree, const irange &,
+ const frange &, relation_trio) const
+{
+ return false;
+}
+
+bool
+range_operator::op1_range (irange &, tree, const frange &,
+ const frange &, relation_trio) const
+{
+ return false;
+}
+
+bool
+range_operator::op1_range (frange &, tree, const irange &,
+ const irange &, relation_trio) const
+{
+ return false;
+}
+
+
+
// The default for op1_range is to return false.
bool
@@ -3678,14 +3716,34 @@ operator_bitwise_and::op1_range (irange &r, tree type,
return true;
}
+ if (!op2.singleton_p (mask))
+ return true;
+
// For 0 = op1 & MASK, op1 is ~MASK.
- if (lhs.zero_p () && op2.singleton_p ())
+ if (lhs.zero_p ())
{
wide_int nz = wi::bit_not (op2.get_nonzero_bits ());
int_range<2> tmp (type);
tmp.set_nonzero_bits (nz);
r.intersect (tmp);
}
+
+ irange_bitmask lhs_bm = lhs.get_bitmask ();
+ // given [5,7] mask 0x3 value 0x4 = N & [7, 7] mask 0x0 value 0x7
+ // Nothing is known about the bits not specified in the mask value (op2),
+ // Start with the mask, 1's will occur where values were masked.
+ wide_int op1_mask = ~mask;
+ // Any bits that are unknown on the LHS are also unknown in op1,
+ // so union the current mask with the LHS mask.
+ op1_mask |= lhs_bm.mask ();
+ // The resulting zeros correspond to known bits in the LHS mask, and
+ // the LHS value should tell us what they are. Mask off any
+ // extraneous values thats are not convered by the mask.
+ wide_int op1_value = lhs_bm.value () & ~op1_mask;
+ irange_bitmask op1_bm (op1_value, op1_mask);
+ // INtersect this mask with anything already known about the value.
+ op1_bm.intersect (r.get_bitmask ());
+ r.update_bitmask (op1_bm);
return true;
}