Index: runtime/vm/intermediate_language.cc |
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc |
index 552fcfa9f167822ce524e1d213e8e5af5754879b..05b25cbb12f664b6b74b83eafc3d6380c6a058c7 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(); |
@@ -1464,6 +1499,46 @@ 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) { |
+ Definition* result = NULL; |
+ |
+ result = CanonicalizeCommutativeArithmetic(op_kind(), |
+ kMintCid, |
+ left(), |
+ right()); |
+ if (result != NULL) { |
+ return result; |
+ } |
+ |
+ result = CanonicalizeCommutativeArithmetic(op_kind(), |
+ kMintCid, |
+ right(), |
+ left()); |
+ if (result != NULL) { |
+ return result; |
+ } |
+ |
+ // If this is (value & 0xFFFFFFFF) the mask operation can be dropped. |
+ if (IsUint32Mask(this)) { |
Vyacheslav Egorov (Google)
2014/07/08 12:39:31
I would fold it into CanonicalizeCommutativeArithm
Cutch
2014/07/09 17:48:26
This specific case can't be folded into Canonicali
|
+ return NULL; |
+ } |
+ |
+ return this; |
+} |
+ |
+ |
// Optimizations that eliminate or simplify individual instructions. |
Instruction* Instruction::Canonicalize(FlowGraph* flow_graph) { |
return this; |