Index: src/hydrogen-instructions.cc |
=================================================================== |
--- src/hydrogen-instructions.cc (revision 10356) |
+++ src/hydrogen-instructions.cc (working copy) |
@@ -108,16 +108,62 @@ |
} |
-int32_t Range::Mask() const { |
- if (lower_ == upper_) return lower_; |
- if (lower_ >= 0) { |
- int32_t res = 1; |
- while (res < upper_) { |
- res = (res << 1) | 1; |
- } |
- return res; |
+class BitRange { |
+ public: |
+ BitRange() : known_(0), bits_(0) { } |
+ BitRange(int32_t known, int32_t bits) |
+ : known_(known), bits_(bits & known) { } |
+ |
+ static void SetFromRange(BitRange* bits, int32_t lower, int32_t upper) { |
+ // Find a mask for the most significant bits that are the same for all |
+ // values in the range. |
+ int32_t same = ~(lower ^ upper); |
+ // Flood zeros to any bits lower than the most significant zero. |
+ same &= (same >> 1); |
+ same &= (same >> 2); |
+ same &= (same >> 4); |
+ same &= (same >> 8); |
+ same &= (same >> 16); |
+ |
+ bits->known_ = same; |
+ bits->bits_ = lower & same; |
} |
- return 0xffffffff; |
+ |
+ void ExtendRange(int32_t* lower, int32_t* upper) { |
+ int32_t limit1 = (~known_ & 0x80000000) | bits_; |
+ int32_t limit2 = (~known_ & 0x7fffffff) | bits_; |
+ *lower = Min(*lower, Min(limit1, limit2)); |
+ *upper = Max(*upper, Max(limit1, limit2)); |
+ } |
+ |
+ static BitRange And(BitRange a, BitRange b) { |
+ int32_t known = a.known_ & b.known_; |
+ // Zeros in either operand become known. |
+ known |= (a.known_ & ~a.bits_); |
+ known |= (b.known_ & ~b.bits_); |
+ return BitRange(known, a.bits_ & b.bits_); |
+ } |
+ |
+ static BitRange Or(BitRange a, BitRange b) { |
+ int32_t known = a.known_ & b.known_; |
+ // Ones in either operand become known. |
+ known |= (a.known_ & a.bits_); |
+ known |= (b.known_ & b.bits_); |
+ return BitRange(known, a.bits_ | b.bits_); |
+ } |
+ |
+ static BitRange Xor(BitRange a, BitRange b) { |
+ return BitRange(a.known_ & b.known_, a.bits_ ^ b.bits_); |
+ } |
+ |
+ private: |
+ int32_t known_; // A mask of known bits. |
+ int32_t bits_; // Values of known bits, zero elsewhere. |
+}; |
+ |
+ |
+void Range::ToBitRange(BitRange* bits) const { |
+ BitRange::SetFromRange(bits, lower_, upper_); |
} |
@@ -1243,19 +1289,36 @@ |
Range* HBitwise::InferRange() { |
- if (op() == Token::BIT_XOR) return HValue::InferRange(); |
- int32_t left_mask = (left()->range() != NULL) |
- ? left()->range()->Mask() |
- : 0xffffffff; |
- int32_t right_mask = (right()->range() != NULL) |
- ? right()->range()->Mask() |
- : 0xffffffff; |
- int32_t result_mask = (op() == Token::BIT_AND) |
- ? left_mask & right_mask |
- : left_mask | right_mask; |
- return (result_mask >= 0) |
- ? new Range(0, result_mask) |
- : HValue::InferRange(); |
+ if (representation().IsInteger32()) { |
+ BitRange left_bits, right_bits; |
+ |
+ if (left()->range() != NULL) |
+ left()->range()->ToBitRange(&left_bits); |
+ |
+ if (right()->range() != NULL) |
+ right()->range()->ToBitRange(&right_bits); |
+ |
+ BitRange result; |
+ switch (op()) { |
+ case Token::BIT_AND: |
+ result = BitRange::And(left_bits, right_bits); |
+ break; |
+ case Token::BIT_OR: |
+ result = BitRange::Or(left_bits, right_bits); |
+ break; |
+ case Token::BIT_XOR: |
+ result = BitRange::Xor(left_bits, right_bits); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ |
+ int32_t lower = kMaxInt, upper = kMinInt; // 'empty' range. |
+ result.ExtendRange(&lower, &upper); |
fschneider
2012/02/28 13:26:52
I'd simplify this by propagating the inputs kMaxIn
sra1
2013/06/11 05:19:15
This looks a little strange but let me explain.
T
fschneider
2013/06/11 10:22:37
Thanks for the explanation. The code just looked s
|
+ return new Range(lower, upper); |
+ } else { |
+ return HValue::InferRange(); |
+ } |
} |