Index: runtime/vm/intermediate_language.cc |
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc |
index 0c64c347fe51721707a272bef7e638cfb00ed102..702cbc8624e600d33733b027e613f5a6ff01abe0 100644 |
--- a/runtime/vm/intermediate_language.cc |
+++ b/runtime/vm/intermediate_language.cc |
@@ -607,6 +607,7 @@ BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked) |
is_checked_(is_checked), |
constrained_type_(NULL), |
constant_target_(NULL) { |
+ ASSERT(comparison->env() == NULL); |
for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) { |
comparison->InputAt(i)->set_instruction(this); |
} |
@@ -636,6 +637,7 @@ void BranchInstr::SetComparison(ComparisonInstr* comp) { |
} |
// There should be no need to copy or unuse an environment. |
ASSERT(comparison()->env() == NULL); |
+ ASSERT(comp->env() == NULL); |
// Remove the current comparison's input uses. |
srdjan
2013/04/15 20:27:27
Would be probable more readable if CompareInstr* w
Vyacheslav Egorov (Google)
2013/04/16 11:51:16
I think instr is somewhat confusing as well. I ren
|
comparison()->UnuseAllInputs(); |
ASSERT(!comp->HasUses()); |
@@ -1233,6 +1235,23 @@ Definition* AssertAssignableInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
} |
+static bool RecognizeTestPattern(Value* left, Value* right) { |
srdjan
2013/04/15 20:27:27
Add comment what pattern is being recognized.
Vyacheslav Egorov (Google)
2013/04/16 11:51:16
Done.
|
+ if (!right->BindsToConstant()) { |
+ return false; |
+ } |
+ |
+ const Object& value = right->BoundConstant(); |
+ if (!value.IsSmi() || (Smi::Cast(value).Value() != 0)) { |
+ return false; |
+ } |
+ |
+ Definition* left_defn = left->definition(); |
+ return left_defn->IsBinarySmiOp() && |
+ (left_defn->AsBinarySmiOp()->op_kind() == Token::kBIT_AND) && |
+ left_defn->HasOnlyUse(left); |
+} |
+ |
+ |
Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
// Only handle strict-compares. |
if (comparison()->IsStrictCompare()) { |
@@ -1261,6 +1280,7 @@ Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
RemoveEnvironment(); |
InheritDeoptTarget(comp); |
+ comp->RemoveEnvironment(); |
comp->RemoveFromGraph(); |
SetComparison(comp); |
if (FLAG_trace_optimization) { |
@@ -1272,6 +1292,25 @@ Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
comp->ClearSSATempIndex(); |
comp->ClearTempIndex(); |
} |
+ } else if (comparison()->IsSmiEquality()) { |
+ BinarySmiOpInstr* bit_and = NULL; |
+ if (RecognizeTestPattern(comparison()->left(), comparison()->right())) { |
+ bit_and = comparison()->left()->definition()->AsBinarySmiOp(); |
+ } else if (RecognizeTestPattern(comparison()->right(), |
+ comparison()->left())) { |
+ bit_and = comparison()->right()->definition()->AsBinarySmiOp(); |
+ } |
+ |
+ if (bit_and != NULL) { |
+ TestSmiInstr* test = new TestSmiInstr(comparison()->kind(), |
+ bit_and->left()->Copy(), |
+ bit_and->right()->Copy()); |
+ ASSERT(!CanDeoptimize()); |
+ InheritDeoptTarget(bit_and); |
+ RemoveEnvironment(); |
+ SetComparison(test); |
+ bit_and->RemoveFromGraph(); |
+ } |
} |
return this; |
} |