Chromium Code Reviews| Index: runtime/vm/intermediate_language_arm.cc |
| =================================================================== |
| --- runtime/vm/intermediate_language_arm.cc (revision 29815) |
| +++ runtime/vm/intermediate_language_arm.cc (working copy) |
| @@ -109,27 +109,166 @@ |
| } |
| +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; |
| + case CC: return CS; |
| + case LS: return HI; |
| + case HI: return LS; |
| + case CS: return CC; |
| + default: |
| + UNREACHABLE(); |
| + 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() { |
|
Florian Schneider
2013/11/05 16:57:53
Now that IsSupported is true on all platform, you
zra
2013/11/05 18:32:13
Done.
|
| - 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
This TODO is not relevant here.
zra
2013/11/05 18:32:13
Done.
|
| + locs->set_out(Location::RegisterLocation(R0)); |
| + return locs; |
| } |
| void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| - UNREACHABLE(); |
| + const Register result = locs()->out().reg(); |
| + ASSERT(result == R0); |
| + 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(locs()->out().reg(), |
| + 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 |
|
Florian Schneider
2013/11/05 16:57:53
Update this comment for ARM.
zra
2013/11/05 18:32:13
Done.
|
| + // which is a byte move. |
| + __ eor(result, result, ShifterOperand(result)); |
| + |
| + // 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(right.reg(), left.constant()); |
| + } else if (right.IsConstant()) { |
| + __ CompareObject(left.reg(), right.constant()); |
| + } else { |
| + __ cmp(left.reg(), ShifterOperand(right.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); |
| + } |
| + } |
| + |
| + __ mov(result, ShifterOperand(1), true_condition); |
| + |
| + if (is_power_of_two_kind) { |
| + const intptr_t shift = |
| + Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
| + __ Lsl(result, result, shift + kSmiTagSize); |
| + } else { |
| + __ sub(result, result, ShifterOperand(1)); |
| + const int32_t val = |
| + Smi::RawValue(true_value) - Smi::RawValue(false_value); |
| + ShifterOperand op; |
| + if (ShifterOperand::CanHold(val, &op)) { |
|
Florian Schneider
2013/11/05 16:57:53
I'd add an AndImmediate macro-instruction for this
zra
2013/11/05 18:32:13
Done.
|
| + __ and_(result, result, ShifterOperand(op)); |
| + } else { |
| + __ LoadImmediate(TMP, val); |
| + __ and_(result, result, ShifterOperand(TMP)); |
| + } |
| + if (false_value != 0) { |
| + __ AddImmediate(result, Smi::RawValue(false_value)); |
| + } |
| + } |
| } |
| @@ -339,25 +478,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; |
| - case CC: return CS; |
| - case LS: return HI; |
| - case HI: return LS; |
| - case CS: return CC; |
| - default: |
| - UNREACHABLE(); |
| - return EQ; |
| - } |
| -} |
| - |
| - |
| static Condition FlipCondition(Condition condition) { |
| switch (condition) { |
| case EQ: return EQ; |