Chromium Code Reviews| Index: runtime/vm/intermediate_language.cc |
| diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc |
| index 552fcfa9f167822ce524e1d213e8e5af5754879b..6c5f47e57641aae6a1d1b84a3b71d3666eff8121 100644 |
| --- a/runtime/vm/intermediate_language.cc |
| +++ b/runtime/vm/intermediate_language.cc |
| @@ -337,6 +337,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(); |
| @@ -1266,7 +1301,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(), |
| @@ -1278,28 +1313,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) { |
| @@ -1464,6 +1507,51 @@ Definition* BinaryMintOpInstr::Canonicalize(FlowGraph* flow_graph) { |
| } |
| +static bool IsUint32Mask(BinaryUint32OpInstr* defn) { |
| + ASSERT(defn != NULL); |
| + if (defn->op_kind() != Token::kBIT_AND) { |
| + // Not a mask. |
| + return false; |
| + } |
| + Value* left = defn->left(); |
| + Value* right = defn->right(); |
| + return left->BindsTo32BitMaskConstant() != right->BindsTo32BitMaskConstant(); |
| +} |
| + |
| + |
| +Definition* BinaryUint32OpInstr::Canonicalize(FlowGraph* flow_graph) { |
| + // If this is (value & 0xFFFFFFFF) the mask operation can be dropped because |
| + // all Uint32 operations are implicitly masked with 0xFFFFFFFF. |
| + if (IsUint32Mask(this)) { |
|
Vyacheslav Egorov (Google)
2014/07/11 16:00:08
I think this is not needed anymore once you replac
Cutch
2014/07/11 22:04:13
Done.
|
| + return NULL; |
| + } |
| + |
| + 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; |