Index: runtime/vm/intermediate_language.cc |
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc |
index 5882cf377e876ad93a460de5e7f68d07c98c0cf4..8abebf8583da9d016f5979119f0edfd6b810c92a 100644 |
--- a/runtime/vm/intermediate_language.cc |
+++ b/runtime/vm/intermediate_language.cc |
@@ -384,6 +384,41 @@ UnboxedConstantInstr::UnboxedConstantInstr(const Object& value) |
FlowGraphBuilder::FindDoubleConstant(Double::Cast(value).value()); |
} |
+ |
+bool Value::BindsTo32BitMaskConstant() const { |
+ if (!definition()->IsUnboxInteger() || !definition()->IsUnboxUint32()) { |
+ return false; |
+ } |
+ // Two cases to consider: UnboxInteger and UnboxUint32. |
+ if (definition()->IsUnboxInteger()) { |
+ 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; |
+ } else if (definition()->IsUnboxUint32()) { |
+ UnboxUint32Instr* instr = definition()->AsUnboxUint32(); |
+ 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; |
+ } |
+ return false; |
+} |
+ |
+ |
// Returns true if the value represents a constant. |
bool Value::BindsToConstant() const { |
return definition()->IsConstant(); |
@@ -1313,7 +1348,7 @@ bool BinarySmiOpInstr::RightIsPowerOfTwoConstant() const { |
} |
-static bool ToIntegerConstant(Value* value, intptr_t* result) { |
+static bool ToIntegerConstant(Value* value, int64_t* result) { |
if (!value->BindsToConstant()) { |
if (value->definition()->IsUnboxDouble()) { |
return ToIntegerConstant(value->definition()->AsUnboxDouble()->value(), |
@@ -1325,28 +1360,36 @@ static bool ToIntegerConstant(Value* value, intptr_t* result) { |
const Object& constant = value->BoundConstant(); |
if (constant.IsDouble()) { |
const Double& double_constant = Double::Cast(constant); |
- *result = static_cast<intptr_t>(double_constant.value()); |
+ *result = static_cast<int64_t>(double_constant.value()); |
return (static_cast<double>(*result) == double_constant.value()); |
} else if (constant.IsSmi()) { |
*result = Smi::Cast(constant).Value(); |
return true; |
+ } else if (constant.IsMint()) { |
+ *result = Mint::Cast(constant).value(); |
+ return true; |
} |
return false; |
} |
-static Definition* CanonicalizeCommutativeArithmetic(Token::Kind op, |
- intptr_t cid, |
- Value* left, |
- Value* right) { |
+static Definition* CanonicalizeCommutativeArithmetic( |
+ Token::Kind op, |
+ intptr_t cid, |
+ Value* left, |
+ Value* right, |
+ int64_t mask = static_cast<int64_t>(0xFFFFFFFFFFFFFFFF)) { |
ASSERT((cid == kSmiCid) || (cid == kDoubleCid) || (cid == kMintCid)); |
- intptr_t left_value; |
+ int64_t left_value; |
if (!ToIntegerConstant(left, &left_value)) { |
return NULL; |
} |
+ // Apply truncation mask to left_value. |
+ left_value &= mask; |
+ |
switch (op) { |
case Token::kMUL: |
if (left_value == 1) { |
@@ -1377,7 +1420,7 @@ static Definition* CanonicalizeCommutativeArithmetic(Token::Kind op, |
ASSERT(cid != kDoubleCid); |
if (left_value == 0) { |
return left->definition(); |
- } else if (left_value == -1) { |
+ } else if (left_value == mask) { |
return right->definition(); |
} |
break; |
@@ -1385,7 +1428,7 @@ static Definition* CanonicalizeCommutativeArithmetic(Token::Kind op, |
ASSERT(cid != kDoubleCid); |
if (left_value == 0) { |
return right->definition(); |
- } else if (left_value == -1) { |
+ } else if (left_value == mask) { |
return left->definition(); |
} |
break; |
@@ -1511,6 +1554,33 @@ Definition* BinaryMintOpInstr::Canonicalize(FlowGraph* flow_graph) { |
} |
+Definition* BinaryUint32OpInstr::Canonicalize(FlowGraph* flow_graph) { |
+ Definition* result = NULL; |
+ |
+ const int64_t truncation_mask = static_cast<int64_t>(0xFFFFFFFF); |
+ |
+ result = CanonicalizeCommutativeArithmetic(op_kind(), |
+ kMintCid, |
+ left(), |
+ right(), |
+ truncation_mask); |
+ if (result != NULL) { |
+ return result; |
+ } |
+ |
+ result = CanonicalizeCommutativeArithmetic(op_kind(), |
+ kMintCid, |
+ right(), |
+ left(), |
+ truncation_mask); |
+ if (result != NULL) { |
+ return result; |
+ } |
+ |
+ return this; |
+} |
+ |
+ |
// Optimizations that eliminate or simplify individual instructions. |
Instruction* Instruction::Canonicalize(FlowGraph* flow_graph) { |
return this; |