| Index: runtime/vm/intermediate_language_x64.cc
|
| diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
|
| index a13034474da6675a27c22cbe47ef662103d0881f..fa3e7ad48004d163cd419deea81f6a60980b9633 100644
|
| --- a/runtime/vm/intermediate_language_x64.cc
|
| +++ b/runtime/vm/intermediate_language_x64.cc
|
| @@ -113,6 +113,147 @@ void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| }
|
|
|
|
|
| +static Condition NegateCondition(Condition condition) {
|
| + switch (condition) {
|
| + case EQUAL: return NOT_EQUAL;
|
| + case NOT_EQUAL: return EQUAL;
|
| + case LESS: return GREATER_EQUAL;
|
| + case LESS_EQUAL: return GREATER;
|
| + case GREATER: return LESS_EQUAL;
|
| + case GREATER_EQUAL: return LESS;
|
| + case BELOW: return ABOVE_EQUAL;
|
| + case BELOW_EQUAL: return ABOVE;
|
| + case ABOVE: return BELOW_EQUAL;
|
| + case ABOVE_EQUAL: return BELOW;
|
| + default:
|
| + OS::Print("Error %d\n", condition);
|
| + UNIMPLEMENTED();
|
| + return EQUAL;
|
| + }
|
| +}
|
| +
|
| +
|
| +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));
|
| +}
|
| +
|
| +
|
| +// Detect pattern when one value is increment of another.
|
| +static bool IsIncrementKind(intptr_t v1, intptr_t v2) {
|
| + return ((v1 == v2 + 1) || (v1 + 1 == v2));
|
| +}
|
| +
|
| +
|
| +bool IfThenElseInstr::IsSupported() {
|
| + return true;
|
| +}
|
| +
|
| +
|
| +bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
|
| + Value* v1,
|
| + Value* v2) {
|
| + if (!(comparison->IsStrictCompare() &&
|
| + !comparison->AsStrictCompare()->needs_number_check()) &&
|
| + !(comparison->IsEqualityCompare() &&
|
| + (comparison->AsEqualityCompare()->receiver_class_id() == kSmiCid))) {
|
| + return false;
|
| + }
|
| +
|
| + intptr_t v1_value, v2_value;
|
| +
|
| + if (!BindsToSmiConstant(v1, &v1_value) ||
|
| + !BindsToSmiConstant(v2, &v2_value)) {
|
| + return false;
|
| + }
|
| +
|
| + if (IsPowerOfTwoKind(v1_value, v2_value) ||
|
| + IsIncrementKind(v1_value, v2_value)) {
|
| + return true;
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +
|
| +LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
|
| + 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.
|
| + locs->set_out(Location::RegisterLocation(RDX));
|
| + return locs;
|
| +}
|
| +
|
| +
|
| +void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + ASSERT(locs()->out().reg() == RDX);
|
| + ASSERT(Token::IsEqualityOperator(kind()));
|
| +
|
| + Location left = locs()->in(0);
|
| + Location right = locs()->in(1);
|
| + 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.
|
| + __ xorq(RDX, RDX);
|
| +
|
| + // 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 {
|
| + __ cmpq(left.reg(), right.reg());
|
| + }
|
| +
|
| + Condition true_condition =
|
| + ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQUAL
|
| + : NOT_EQUAL;
|
| +
|
| + const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
|
| +
|
| + const intptr_t base = Utils::Minimum(if_true_, if_false_);
|
| +
|
| + if (if_true_ == base) {
|
| + // We need to have zero in RDX on true_condition.
|
| + true_condition = NegateCondition(true_condition);
|
| + }
|
| +
|
| + __ setcc(true_condition, DL);
|
| +
|
| + if (is_power_of_two_kind) {
|
| + const intptr_t shift =
|
| + Utils::ShiftForPowerOfTwo(Utils::Maximum(if_true_, if_false_));
|
| + __ shlq(RDX, Immediate(shift + kSmiTagSize));
|
| + } else {
|
| + ASSERT(kSmiTagSize == 1);
|
| + __ leaq(RDX, Address(RDX, TIMES_2, base << kSmiTagSize));
|
| + }
|
| +}
|
| +
|
| +
|
| LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
|
| const intptr_t kNumInputs = 0;
|
| const intptr_t kNumTemps = 1;
|
| @@ -3096,26 +3237,6 @@ void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| }
|
|
|
|
|
| -static Condition NegateCondition(Condition condition) {
|
| - switch (condition) {
|
| - case EQUAL: return NOT_EQUAL;
|
| - case NOT_EQUAL: return EQUAL;
|
| - case LESS: return GREATER_EQUAL;
|
| - case LESS_EQUAL: return GREATER;
|
| - case GREATER: return LESS_EQUAL;
|
| - case GREATER_EQUAL: return LESS;
|
| - case BELOW: return ABOVE_EQUAL;
|
| - case BELOW_EQUAL: return ABOVE;
|
| - case ABOVE: return BELOW_EQUAL;
|
| - case ABOVE_EQUAL: return BELOW;
|
| - default:
|
| - OS::Print("Error %d\n", condition);
|
| - UNIMPLEMENTED();
|
| - return EQUAL;
|
| - }
|
| -}
|
| -
|
| -
|
| void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
|
| bool value) {
|
| if (value && !compiler->CanFallThroughTo(true_successor())) {
|
|
|