Index: runtime/vm/intermediate_language.cc |
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc |
index 1891ef263759a1ae89dc76992cfc3ebcff98bf67..34d632bdaccc420108225ec842132258b604f505 100644 |
--- a/runtime/vm/intermediate_language.cc |
+++ b/runtime/vm/intermediate_language.cc |
@@ -343,6 +343,45 @@ bool Value::BindsToConstant() const { |
} |
+bool Value::BindsTo32BitMint() const { |
+ if (!definition()->IsMintDefinition()) { |
+ return false; |
+ } |
+ if (definition()->IsBinaryMintOp()) { |
+ BinaryMintOpInstr* instr = definition()->AsBinaryMintOp(); |
+ return instr->is_32_bit(); |
+ } else if (definition()->IsShiftMintOp()) { |
+ ShiftMintOpInstr* instr = definition()->AsShiftMintOp(); |
+ return instr->is_32_bit(); |
+ } else if (definition()->IsUnboxInteger()) { |
+ UnboxIntegerInstr* instr = definition()->AsUnboxInteger(); |
+ return instr->is_32_bit(); |
+ } else if (definition()->IsUnaryMintOp()) { |
+ UnaryMintOpInstr* instr = definition()->AsUnaryMintOp(); |
+ return instr->is_32_bit(); |
+ } |
+ return false; |
+} |
+ |
+ |
+bool Value::BindsTo32BitMaskConstant() const { |
+ if (!definition()->IsUnboxInteger()) { |
+ return false; |
+ } |
+ UnboxIntegerInstr* instr = definition()->AsUnboxInteger(); |
+ if (!instr->value()->BindsToConstant()) { |
+ return false; |
+ } |
+ const Object& obj = instr->value()->BoundConstant(); |
+ if (!obj.IsMint()) { |
+ return false; |
+ } |
+ Mint& mint = Mint::Handle(); |
+ mint ^= obj.raw(); |
+ return mint.value() == kMaxUint32; |
+} |
+ |
+ |
// Returns true if the value represents constant null. |
bool Value::BindsToConstantNull() const { |
ConstantInstr* constant = definition()->AsConstant(); |
@@ -3217,6 +3256,13 @@ void BinarySmiOpInstr::InferRange() { |
} |
+Representation BinaryMintOpInstr::RequiredInputRepresentation( |
+ intptr_t idx) const { |
+ ASSERT((idx == 0) || (idx == 1)); |
+ return InputAt(idx)->BindsTo32BitMint() ? kUnboxedMint32 : kUnboxedMint; |
+} |
+ |
+ |
void BinaryMintOpInstr::InferRange() { |
// TODO(vegorov): canonicalize BinaryMintOpInstr to always have constant on |
// the right and a non-constant on the left. |
@@ -3458,12 +3504,25 @@ bool Range::And(const Range* left_range, |
ASSERT(result_min != NULL); |
ASSERT(result_max != NULL); |
+ // Both ranges are >= 0. |
+ if ((Range::ConstantMin(left_range).ConstantValue() >= 0) && |
+ (Range::ConstantMin(right_range).ConstantValue() >= 0)) { |
+ *result_min = RangeBoundary::FromConstant(0); |
+ // Take minimum value as new range. |
+ *result_max = RangeBoundary::Min(Range::ConstantMax(left_range), |
+ Range::ConstantMax(right_range), |
+ RangeBoundary::kRangeBoundaryInt64); |
+ return true; |
+ } |
+ |
+ // Right range is >= 0. |
if (Range::ConstantMin(right_range).ConstantValue() >= 0) { |
*result_min = RangeBoundary::FromConstant(0); |
*result_max = Range::ConstantMax(right_range); |
return true; |
} |
+ // Left range is >= 0. |
if (Range::ConstantMin(left_range).ConstantValue() >= 0) { |
*result_min = RangeBoundary::FromConstant(0); |
*result_max = Range::ConstantMax(left_range); |