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"); |