Chromium Code Reviews| Index: runtime/vm/intermediate_language_mips.cc |
| =================================================================== |
| --- runtime/vm/intermediate_language_mips.cc (revision 29815) |
| +++ runtime/vm/intermediate_language_mips.cc (working copy) |
| @@ -111,27 +111,176 @@ |
| } |
| +static Condition NegateCondition(Condition condition) { |
| + switch (condition) { |
| + case EQ: return NE; |
| + case NE: return EQ; |
| + case LT: return GE; |
| + case LE: return GT; |
| + case GT: return LE; |
| + case GE: return LT; |
| + default: |
| + OS::Print("Error: Condition not recognized: %d\n", condition); |
| + UNIMPLEMENTED(); |
| + return EQ; |
| + } |
| +} |
| + |
| + |
| +static bool BindsToSmiConstant(Value* val, intptr_t* smi_value) { |
| + if (!val->BindsToConstant()) { |
| + return false; |
| + } |
| + |
| + const Object& bound_constant = val->BoundConstant(); |
| + if (!bound_constant.IsSmi()) { |
| + return false; |
| + } |
| + |
| + *smi_value = Smi::Cast(bound_constant).Value(); |
| + return true; |
| +} |
| + |
| + |
| +// Detect pattern when one value is zero and another is a power of 2. |
| +static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| + return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| + (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
| +} |
| + |
| + |
| bool IfThenElseInstr::IsSupported() { |
| - return false; |
| + return true; |
| } |
| bool IfThenElseInstr::Supports(ComparisonInstr* comparison, |
| Value* v1, |
| Value* v2) { |
| - UNREACHABLE(); |
| - return false; |
| + if (!(comparison->IsStrictCompare() && |
| + !comparison->AsStrictCompare()->needs_number_check()) && |
| + !(comparison->IsEqualityCompare() && |
| + (comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) { |
| + return false; |
| + } |
| + |
| + intptr_t v1_value, v2_value; |
| + |
| + if (!BindsToSmiConstant(v1, &v1_value) || |
| + !BindsToSmiConstant(v2, &v2_value)) { |
| + return false; |
| + } |
| + |
| + return true; |
| } |
| LocationSummary* IfThenElseInstr::MakeLocationSummary() const { |
| - UNREACHABLE(); |
| - return NULL; |
| + const intptr_t kNumInputs = 2; |
| + const intptr_t kNumTemps = 0; |
| + LocationSummary* locs = |
| + new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| + locs->set_in(0, Location::RegisterOrConstant(left())); |
| + locs->set_in(1, Location::RegisterOrConstant(right())); |
| + // TODO(vegorov): support byte register constraints in the register allocator. |
|
Florian Schneider
2013/11/05 16:57:53
Comment not relevant here.
zra
2013/11/05 18:32:13
Done.
|
| + locs->set_out(Location::RegisterLocation(V0)); |
| + return locs; |
| } |
| void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| - UNREACHABLE(); |
| + const Register result = locs()->out().reg(); |
| + ASSERT(result == V0); |
| + ASSERT(Token::IsEqualityOperator(kind())); |
| + |
| + Location left = locs()->in(0); |
| + Location right = locs()->in(1); |
| + if (left.IsConstant() && right.IsConstant()) { |
| + // TODO(srdjan): Determine why this instruction was not eliminated. |
| + bool res = (left.constant().raw() == right.constant().raw()); |
| + if ((kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)) { |
| + res = !res; |
| + } |
| + __ LoadImmediate(result, |
| + reinterpret_cast<int32_t>(Smi::New(res ? if_true_ : if_false_))); |
| + return; |
| + } |
| + |
| + ASSERT(!left.IsConstant() || !right.IsConstant()); |
| + |
| + // Clear upper part of the out register. We are going to use setcc on it |
| + // which is a byte move. |
|
Florian Schneider
2013/11/05 16:57:53
Update comment.
zra
2013/11/05 18:32:13
Done.
|
| + __ mov(result, ZR); |
| + |
| + // Compare left and right. For now only equality comparison is supported. |
| + // TODO(vegorov): reuse code from the other comparison instructions instead of |
| + // generating it inline here. |
| + if (left.IsConstant()) { |
| + __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant()); |
| + } else if (right.IsConstant()) { |
| + __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant()); |
| + } else { |
| + __ slt(CMPRES1, left.reg(), right.reg()); |
| + __ slt(CMPRES2, right.reg(), left.reg()); |
| + } |
| + |
| + Condition true_condition = |
| + ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQ : NE; |
| + |
| + const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
| + |
| + intptr_t true_value = if_true_; |
| + intptr_t false_value = if_false_; |
| + |
| + if (is_power_of_two_kind) { |
| + if (true_value == 0) { |
| + // We need to have zero in result on true_condition. |
| + true_condition = NegateCondition(true_condition); |
| + } |
| + } else { |
| + if (true_value == 0) { |
| + // Swap values so that false_value is zero. |
| + intptr_t temp = true_value; |
| + true_value = false_value; |
| + false_value = temp; |
| + } else { |
| + true_condition = NegateCondition(true_condition); |
| + } |
| + } |
| + |
| + switch (true_condition) { |
|
Florian Schneider
2013/11/05 16:57:53
true_condition can only be EQ or NE here. The othe
zra
2013/11/05 18:32:13
Done.
|
| + case EQ: |
| + __ xor_(result, CMPRES1, CMPRES2); |
| + __ xori(result, result, Immediate(1)); |
| + break; |
| + case NE: __ xor_(result, CMPRES1, CMPRES2); break; |
| + case GT: __ mov(result, CMPRES2); break; |
| + case GE: __ xori(result, CMPRES1, Immediate(1)); break; |
| + case LT: __ mov(result, CMPRES1); break; |
| + case LE: __ xori(result, CMPRES2, Immediate(1)); break; |
| + default: |
| + UNREACHABLE(); |
| + break; |
| + } |
| + |
| + if (is_power_of_two_kind) { |
| + const intptr_t shift = |
| + Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
| + __ sll(result, result, shift + kSmiTagSize); |
| + } else { |
| + __ AddImmediate(result, result, -1); |
| + const int32_t val = |
| + Smi::RawValue(true_value) - Smi::RawValue(false_value); |
| + if (Utils::IsUint(kImmBits, val)) { |
|
Florian Schneider
2013/11/05 16:57:53
AndImmediate
zra
2013/11/05 18:32:13
Done.
|
| + __ andi(result, result, Immediate(val)); |
| + } else { |
| + __ LoadImmediate(TMP, val); |
| + __ and_(result, result, TMP); |
| + } |
| + if (false_value != 0) { |
| + __ AddImmediate(result, result, Smi::RawValue(false_value)); |
| + } |
| + } |
| } |
| @@ -3547,22 +3696,6 @@ |
| } |
| -static Condition NegateCondition(Condition condition) { |
| - switch (condition) { |
| - case EQ: return NE; |
| - case NE: return EQ; |
| - case LT: return GE; |
| - case LE: return GT; |
| - case GT: return LE; |
| - case GE: return LT; |
| - default: |
| - OS::Print("Error: Condition not recognized: %d\n", condition); |
| - UNIMPLEMENTED(); |
| - return EQ; |
| - } |
| -} |
| - |
| - |
| void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, |
| bool value) { |
| __ TraceSimMsg("ControlInstruction::EmitBranchOnValue"); |