| Index: runtime/vm/intermediate_language.cc | 
| diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc | 
| index 0c64c347fe51721707a272bef7e638cfb00ed102..e09e6c8505bf7edbddc69c3df590ff9e8c78a9cb 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); | 
| } | 
| @@ -628,18 +629,19 @@ void BranchInstr::ReplaceWith(ComparisonInstr* other, | 
| } | 
|  | 
|  | 
| -void BranchInstr::SetComparison(ComparisonInstr* comp) { | 
| -  for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) { | 
| -    Value* input = comp->InputAt(i); | 
| +void BranchInstr::SetComparison(ComparisonInstr* new_comparison) { | 
| +  for (intptr_t i = new_comparison->InputCount() - 1; i >= 0; --i) { | 
| +    Value* input = new_comparison->InputAt(i); | 
| input->definition()->AddInputUse(input); | 
| input->set_instruction(this); | 
| } | 
| // There should be no need to copy or unuse an environment. | 
| ASSERT(comparison()->env() == NULL); | 
| +  ASSERT(new_comparison->env() == NULL); | 
| // Remove the current comparison's input uses. | 
| comparison()->UnuseAllInputs(); | 
| -  ASSERT(!comp->HasUses()); | 
| -  comparison_ = comp; | 
| +  ASSERT(!new_comparison->HasUses()); | 
| +  comparison_ = new_comparison; | 
| } | 
|  | 
|  | 
| @@ -1233,6 +1235,25 @@ Definition* AssertAssignableInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 
| } | 
|  | 
|  | 
| +// Recognize the bpattern (a & b) == 0 where left is a bitwise and operation | 
| +// and right is a constant 0. | 
| +static bool RecognizeTestPattern(Value* left, Value* right) { | 
| +  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 +1282,7 @@ Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 
| RemoveEnvironment(); | 
| InheritDeoptTarget(comp); | 
|  | 
| +      comp->RemoveEnvironment(); | 
| comp->RemoveFromGraph(); | 
| SetComparison(comp); | 
| if (FLAG_trace_optimization) { | 
| @@ -1272,6 +1294,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; | 
| } | 
|  |