Chromium Code Reviews| 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(); |
| + } |
| } |