From 2a14259fd0ec065f8e09e5e910d3d6ce28ef4280 Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Wed, 31 Mar 2021 22:10:42 +0000 Subject: [PATCH] [vm/compiler] Cleanup CheckedSmi* instructions This is a final cleanup of CheckedSmiOpInstr and CheckedSmiComparisonInstr instructions. Their uses were removed in the following changes: https://dart-review.googlesource.com/c/sdk/+/191761 https://dart-review.googlesource.com/c/sdk/+/191760 https://dart-review.googlesource.com/c/sdk/+/193447 TEST=ci Issue: https://github.com/dart-lang/sdk/issues/44852 Change-Id: Ica52ab9e2fcabab1913228818642a27a8d842f92 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193449 Commit-Queue: Alexander Markov Reviewed-by: Ryan Macnak --- runtime/vm/clustered_snapshot.cc | 7 - .../vm/compiler/aot/aot_call_specializer.h | 4 +- .../compiler/backend/constant_propagator.cc | 9 - .../vm/compiler/backend/flow_graph_compiler.h | 2 - runtime/vm/compiler/backend/il.cc | 73 ---- runtime/vm/compiler/backend/il.h | 96 ----- runtime/vm/compiler/backend/il_arm.cc | 328 ----------------- runtime/vm/compiler/backend/il_arm64.cc | 305 ---------------- runtime/vm/compiler/backend/il_ia32.cc | 39 -- runtime/vm/compiler/backend/il_printer.cc | 16 - runtime/vm/compiler/backend/il_test_helper.cc | 3 +- runtime/vm/compiler/backend/il_x64.cc | 336 ------------------ .../vm/compiler/backend/type_propagator.cc | 24 -- 13 files changed, 3 insertions(+), 1239 deletions(-) diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc index af19ffa07f2..4a638434506 100644 --- a/runtime/vm/clustered_snapshot.cc +++ b/runtime/vm/clustered_snapshot.cc @@ -3249,13 +3249,6 @@ class MegamorphicCacheDeserializationCluster : public DeserializationCluster { // In --use-bare-instruction we reduce the extra indirection via the // [Function] object by storing the entry point directly into the hashmap. // - // Currently our AOT compiler will emit megamorphic calls in certain - // situations (namely in slow-path code of CheckedSmi* instructions). - // - // TODO(compiler-team): Change the CheckedSmi* slow path code to use - // normal switchable calls instead of megamorphic calls. (This is also a - // memory balance beause [MegamorphicCache]s are per-selector while - // [ICData] are per-callsite.) auto& cache = MegamorphicCache::Handle(d->zone()); for (intptr_t i = start_index_; i < stop_index_; ++i) { cache ^= refs.At(i); diff --git a/runtime/vm/compiler/aot/aot_call_specializer.h b/runtime/vm/compiler/aot/aot_call_specializer.h index fd23ebf233c..b537ae85d9f 100644 --- a/runtime/vm/compiler/aot/aot_call_specializer.h +++ b/runtime/vm/compiler/aot/aot_call_specializer.h @@ -59,12 +59,12 @@ class AotCallSpecializer : public CallSpecializer { const Function& InterfaceTargetForTableDispatch(InstanceCallBaseInstr* call); // Try to replace a call with a more specialized instruction working on - // integers (e.g. BinaryInt64OpInstr, CheckedSmiComparisonInstr, + // integers (e.g. BinaryInt64OpInstr, EqualityCompareInstr, // RelationalOpInstr) bool TryOptimizeIntegerOperation(TemplateDartCall<0>* call, Token::Kind kind); // Try to replace a call with a more specialized instruction working on - // doubles (e.g. BinaryDoubleOpInstr, CheckedSmiComparisonInstr, + // doubles (e.g. BinaryDoubleOpInstr, EqualityCompareInstr, // RelationalOpInstr) bool TryOptimizeDoubleOperation(TemplateDartCall<0>* call, Token::Kind kind); diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc index df2b9dfea97..1ba1c368c4e 100644 --- a/runtime/vm/compiler/backend/constant_propagator.cc +++ b/runtime/vm/compiler/backend/constant_propagator.cc @@ -1155,15 +1155,6 @@ void ConstantPropagator::VisitBinaryIntegerOp(BinaryIntegerOpInstr* binary_op) { SetValue(binary_op, non_constant_); } -void ConstantPropagator::VisitCheckedSmiOp(CheckedSmiOpInstr* instr) { - SetValue(instr, non_constant_); -} - -void ConstantPropagator::VisitCheckedSmiComparison( - CheckedSmiComparisonInstr* instr) { - SetValue(instr, non_constant_); -} - void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) { VisitBinaryIntegerOp(instr); } diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h index e05c5680f65..6973f625094 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.h +++ b/runtime/vm/compiler/backend/flow_graph_compiler.h @@ -983,8 +983,6 @@ class FlowGraphCompiler : public ValueObject { friend class StoreIndexedInstr; // For AddPcRelativeCallStubTarget(). friend class StoreInstanceFieldInstr; // For AddPcRelativeCallStubTarget(). friend class CheckStackOverflowSlowPath; // For pending_deoptimization_env_. - friend class CheckedSmiSlowPath; // Same. - friend class CheckedSmiComparisonSlowPath; // Same. friend class GraphInstrinsicCodeGenScope; // For optimizing_. // Architecture specific implementation of simple native moves. diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index eb31e79ba6e..0bdc1dfc8be 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -2437,79 +2437,6 @@ BinaryIntegerOpInstr* BinaryIntegerOpInstr::Make( return op; } -Definition* CheckedSmiOpInstr::Canonicalize(FlowGraph* flow_graph) { - if ((left()->Type()->ToCid() == kSmiCid) && - (right()->Type()->ToCid() == kSmiCid)) { - Definition* replacement = NULL; - // Operations that can't deoptimize are specialized here: These include - // bit-wise operators and comparisons. Other arithmetic operations can - // overflow or divide by 0 and can't be specialized unless we have extra - // range information. - switch (op_kind()) { - case Token::kBIT_AND: - FALL_THROUGH; - case Token::kBIT_OR: - FALL_THROUGH; - case Token::kBIT_XOR: - replacement = new BinarySmiOpInstr( - op_kind(), new Value(left()->definition()), - new Value(right()->definition()), DeoptId::kNone); - FALL_THROUGH; - default: - break; - } - if (replacement != NULL) { - flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue); - return replacement; - } - } - return this; -} - -ComparisonInstr* CheckedSmiComparisonInstr::CopyWithNewOperands(Value* left, - Value* right) { - UNREACHABLE(); - return NULL; -} - -Definition* CheckedSmiComparisonInstr::Canonicalize(FlowGraph* flow_graph) { - CompileType* left_type = left()->Type(); - CompileType* right_type = right()->Type(); - intptr_t op_cid = kIllegalCid; - SpeculativeMode speculative_mode = kGuardInputs; - - if ((left_type->ToCid() == kSmiCid) && (right_type->ToCid() == kSmiCid)) { - op_cid = kSmiCid; - } else if ( // TODO(dartbug.com/30480): handle nullable types here - left_type->IsNullableInt() && !left_type->is_nullable() && - right_type->IsNullableInt() && !right_type->is_nullable()) { - op_cid = kMintCid; - speculative_mode = kNotSpeculative; - } - - if (op_cid != kIllegalCid) { - Definition* replacement = NULL; - if (Token::IsRelationalOperator(kind())) { - replacement = new RelationalOpInstr( - source(), kind(), left()->CopyWithType(), right()->CopyWithType(), - op_cid, DeoptId::kNone, speculative_mode); - } else if (Token::IsEqualityOperator(kind())) { - replacement = new EqualityCompareInstr( - source(), kind(), left()->CopyWithType(), right()->CopyWithType(), - op_cid, DeoptId::kNone, /*null_aware=*/false, speculative_mode); - } - if (replacement != NULL) { - if (FLAG_trace_strong_mode_types && (op_cid == kMintCid)) { - THR_Print("[Strong mode] Optimization: replacing %s with %s\n", - ToCString(), replacement->ToCString()); - } - flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue); - return replacement; - } - } - return this; -} - Definition* BinaryIntegerOpInstr::Canonicalize(FlowGraph* flow_graph) { // If both operands are constants evaluate this expression. Might // occur due to load forwarding after constant propagation pass diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h index ae23adf7f51..fc050852e2b 100644 --- a/runtime/vm/compiler/backend/il.h +++ b/runtime/vm/compiler/backend/il.h @@ -440,8 +440,6 @@ struct InstrAttrs { M(AllocateUninitializedContext, _) \ M(CloneContext, _) \ M(BinarySmiOp, kNoGC) \ - M(CheckedSmiComparison, _) \ - M(CheckedSmiOp, _) \ M(BinaryInt32Op, kNoGC) \ M(UnarySmiOp, kNoGC) \ M(UnaryDoubleOp, kNoGC) \ @@ -7617,100 +7615,6 @@ class UnaryInt64OpInstr : public UnaryIntegerOpInstr { DISALLOW_COPY_AND_ASSIGN(UnaryInt64OpInstr); }; -class CheckedSmiOpInstr : public TemplateDefinition<2, Throws> { - public: - CheckedSmiOpInstr(Token::Kind op_kind, - Value* left, - Value* right, - TemplateDartCall<0>* call) - : TemplateDefinition(call->deopt_id()), call_(call), op_kind_(op_kind) { - ASSERT(call->type_args_len() == 0); - ASSERT(!call->IsInstanceCallBase() || - call->AsInstanceCallBase()->CanReceiverBeSmiBasedOnInterfaceTarget( - Thread::Current()->zone())); - - SetInputAt(0, left); - SetInputAt(1, right); - } - - TemplateDartCall<0>* call() const { return call_; } - Token::Kind op_kind() const { return op_kind_; } - Value* left() const { return inputs_[0]; } - Value* right() const { return inputs_[1]; } - - virtual bool ComputeCanDeoptimize() const { return false; } - - virtual CompileType ComputeType() const; - virtual bool RecomputeType(); - - virtual bool HasUnknownSideEffects() const { return true; } - virtual bool CanCallDart() const { return true; } - - virtual Definition* Canonicalize(FlowGraph* flow_graph); - - PRINT_OPERANDS_TO_SUPPORT - - DECLARE_INSTRUCTION(CheckedSmiOp) - - private: - TemplateDartCall<0>* call_; - const Token::Kind op_kind_; - DISALLOW_COPY_AND_ASSIGN(CheckedSmiOpInstr); -}; - -class CheckedSmiComparisonInstr : public TemplateComparison<2, Throws> { - public: - CheckedSmiComparisonInstr(Token::Kind op_kind, - Value* left, - Value* right, - TemplateDartCall<0>* call) - : TemplateComparison(call->source(), op_kind, call->deopt_id()), - call_(call), - is_negated_(false) { - ASSERT(call->type_args_len() == 0); - ASSERT(!call->IsInstanceCallBase() || - call->AsInstanceCallBase()->CanReceiverBeSmiBasedOnInterfaceTarget( - Thread::Current()->zone())); - - SetInputAt(0, left); - SetInputAt(1, right); - } - - TemplateDartCall<0>* call() const { return call_; } - - virtual bool ComputeCanDeoptimize() const { return false; } - - virtual CompileType ComputeType() const; - - virtual Definition* Canonicalize(FlowGraph* flow_graph); - - virtual void NegateComparison() { - ComparisonInstr::NegateComparison(); - is_negated_ = !is_negated_; - } - - bool is_negated() const { return is_negated_; } - - virtual bool HasUnknownSideEffects() const { return true; } - virtual bool CanCallDart() const { return true; } - - PRINT_OPERANDS_TO_SUPPORT - - DECLARE_INSTRUCTION(CheckedSmiComparison) - - virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch); - - virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler, - BranchLabels labels); - - virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right); - - private: - TemplateDartCall<0>* call_; - bool is_negated_; - DISALLOW_COPY_AND_ASSIGN(CheckedSmiComparisonInstr); -}; - class BinaryIntegerOpInstr : public TemplateDefinition<2, NoThrow, Pure> { public: BinaryIntegerOpInstr(Token::Kind op_kind, diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc index ebebbe653c9..c8b681f79a9 100644 --- a/runtime/vm/compiler/backend/il_arm.cc +++ b/runtime/vm/compiler/backend/il_arm.cc @@ -3897,334 +3897,6 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, } } -class CheckedSmiSlowPath : public TemplateSlowPathCode { - public: - CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) - : TemplateSlowPathCode(instruction), try_index_(try_index) {} - - static constexpr intptr_t kNumSlowPathArgs = 2; - - virtual void EmitNativeCode(FlowGraphCompiler* compiler) { - if (compiler::Assembler::EmittingComments()) { - __ Comment("slow path smi operation"); - } - __ Bind(entry_label()); - LocationSummary* locs = instruction()->locs(); - Register result = locs->out(0).reg(); - locs->live_registers()->Remove(Location::RegisterLocation(result)); - - compiler->SaveLiveRegisters(locs); - if (instruction()->env() != NULL) { - Environment* env = - compiler->SlowPathEnvironmentFor(instruction(), kNumSlowPathArgs); - compiler->pending_deoptimization_env_ = env; - } - __ Push(locs->in(0).reg()); - __ Push(locs->in(1).reg()); - const auto& selector = String::Handle(instruction()->call()->Selector()); - const auto& arguments_descriptor = - Array::Handle(ArgumentsDescriptor::NewBoxed( - /*type_args_len=*/0, /*num_arguments=*/2)); - compiler->EmitMegamorphicInstanceCall( - selector, arguments_descriptor, instruction()->call()->deopt_id(), - instruction()->source(), locs, try_index_, kNumSlowPathArgs); - __ mov(result, compiler::Operand(R0)); - compiler->RestoreLiveRegisters(locs); - __ b(exit_label()); - compiler->pending_deoptimization_env_ = NULL; - } - - private: - intptr_t try_index_; -}; - -LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, - bool opt) const { - const intptr_t kNumInputs = 2; - const intptr_t kNumTemps = 0; - LocationSummary* summary = new (zone) LocationSummary( - zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); - summary->set_in(0, Location::RequiresRegister()); - summary->set_in(1, Location::RequiresRegister()); - summary->set_out(0, Location::RequiresRegister()); - return summary; -} - -void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - CheckedSmiSlowPath* slow_path = - new CheckedSmiSlowPath(this, compiler->CurrentTryIndex()); - compiler->AddSlowPathCode(slow_path); - // Test operands if necessary. - Register left = locs()->in(0).reg(); - Register right = locs()->in(1).reg(); - Register result = locs()->out(0).reg(); - intptr_t left_cid = this->left()->Type()->ToCid(); - intptr_t right_cid = this->right()->Type()->ToCid(); - bool combined_smi_check = false; - if (FLAG_use_slow_path) { - __ b(slow_path->entry_label()); - } else if (this->left()->definition() == this->right()->definition()) { - __ BranchIfNotSmi(left, slow_path->entry_label()); - } else if (left_cid == kSmiCid) { - __ BranchIfNotSmi(right, slow_path->entry_label()); - } else if (right_cid == kSmiCid) { - __ BranchIfNotSmi(left, slow_path->entry_label()); - } else { - combined_smi_check = true; - __ orr(result, left, compiler::Operand(right)); - __ BranchIfNotSmi(result, slow_path->entry_label()); - } - switch (op_kind()) { - case Token::kADD: - __ adds(result, left, compiler::Operand(right)); - __ b(slow_path->entry_label(), VS); - break; - case Token::kSUB: - __ subs(result, left, compiler::Operand(right)); - __ b(slow_path->entry_label(), VS); - break; - case Token::kMUL: - __ SmiUntag(IP, left); - __ smull(result, IP, IP, right); - // IP: result bits 32..63. - __ cmp(IP, compiler::Operand(result, ASR, 31)); - __ b(slow_path->entry_label(), NE); - break; - case Token::kBIT_OR: - // Operation may be part of combined smi check. - if (!combined_smi_check) { - __ orr(result, left, compiler::Operand(right)); - } - break; - case Token::kBIT_AND: - __ and_(result, left, compiler::Operand(right)); - break; - case Token::kBIT_XOR: - __ eor(result, left, compiler::Operand(right)); - break; - case Token::kSHL: - ASSERT(result != left); - ASSERT(result != right); - __ CompareImmediate( - right, compiler::target::ToRawSmi(compiler::target::kSmiBits)); - __ b(slow_path->entry_label(), HI); - - __ SmiUntag(TMP, right); - // Check for overflow by shifting left and shifting back arithmetically. - // If the result is different from the original, there was overflow. - __ Lsl(result, left, TMP); - __ cmp(left, compiler::Operand(result, ASR, TMP)); - __ b(slow_path->entry_label(), NE); - break; - case Token::kSHR: - ASSERT(result != left); - ASSERT(result != right); - __ CompareImmediate( - right, compiler::target::ToRawSmi(compiler::target::kSmiBits)); - __ b(slow_path->entry_label(), HI); - - __ SmiUntag(result, right); - __ SmiUntag(TMP, left); - __ Asr(result, TMP, result); - __ SmiTag(result); - break; - case Token::kUSHR: { - ASSERT(result != left); - ASSERT(result != right); - __ CompareImmediate(right, compiler::target::ToRawSmi(kBitsPerInt64)); - __ b(slow_path->entry_label(), UNSIGNED_GREATER_EQUAL); - - compiler::Label done; - __ SmiUntag(result, right); - // 64-bit representation of left operand value: - // - // ss...sssss s s xxxxxxxxxxxxx - // | | | | | | - // 63 32 31 30 kSmiBits-1 0 - // - // Where 's' is a sign bit. - // - // If left operand is negative (sign bit is set), then - // result will fit into Smi range if and only if - // the shift amount >= 64 - kSmiBits. - // - // If left operand is non-negative, the result always - // fits into Smi range. - // - __ CompareImmediate(result, 64 - compiler::target::kSmiBits); - // Shift amount >= 64 - kSmiBits > 32, but < 64. - // Result is guaranteed to fit into Smi range. - // Low (Smi) part of the left operand is shifted out. - // High part is filled with sign bits. - __ sub(result, result, compiler::Operand(32), GE); - __ Asr(TMP, left, compiler::Operand(31), GE); - __ Lsr(result, TMP, result, GE); - __ SmiTag(result, GE); - __ b(&done, GE); - // Shift amount < 64 - kSmiBits. - // If left is negative, then result will not fit into Smi range. - // Also deopt in case of negative shift amount. - __ tst(left, compiler::Operand(left)); - __ b(slow_path->entry_label(), MI); - // At this point left operand is non-negative, so unsigned shift - // can't overflow. - __ CompareImmediate(result, compiler::target::kSmiBits); - // Left operand >= 0, shift amount >= kSmiBits. Result is 0. - __ LoadImmediate(result, 0, GE); - // Left operand >= 0, shift amount < kSmiBits < 32. - __ SmiUntag(TMP, left, LT); - __ Lsr(result, TMP, result, LT); - __ SmiTag(result, LT); - __ Bind(&done); - break; - } - default: - UNREACHABLE(); - } - __ Bind(slow_path->exit_label()); -} - -class CheckedSmiComparisonSlowPath - : public TemplateSlowPathCode { - public: - static constexpr intptr_t kNumSlowPathArgs = 2; - - CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, - Environment* env, - intptr_t try_index, - BranchLabels labels, - bool merged) - : TemplateSlowPathCode(instruction), - try_index_(try_index), - labels_(labels), - merged_(merged), - env_(env) { - // The environment must either come from the comparison or the environment - // was cleared from the comparison (and moved to a branch). - ASSERT(env == instruction->env() || - (merged && instruction->env() == nullptr)); - } - - virtual void EmitNativeCode(FlowGraphCompiler* compiler) { - if (compiler::Assembler::EmittingComments()) { - __ Comment("slow path smi operation"); - } - __ Bind(entry_label()); - LocationSummary* locs = instruction()->locs(); - Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); - locs->live_registers()->Remove(Location::RegisterLocation(result)); - - compiler->SaveLiveRegisters(locs); - if (env_ != nullptr) { - compiler->pending_deoptimization_env_ = - compiler->SlowPathEnvironmentFor(env_, locs, kNumSlowPathArgs); - } - __ Push(locs->in(0).reg()); - __ Push(locs->in(1).reg()); - const auto& selector = String::Handle(instruction()->call()->Selector()); - const auto& arguments_descriptor = - Array::Handle(ArgumentsDescriptor::NewBoxed( - /*type_args_len=*/0, /*num_arguments=*/2)); - compiler->EmitMegamorphicInstanceCall( - selector, arguments_descriptor, instruction()->call()->deopt_id(), - instruction()->source(), locs, try_index_, kNumSlowPathArgs); - __ mov(result, compiler::Operand(R0)); - compiler->RestoreLiveRegisters(locs); - compiler->pending_deoptimization_env_ = nullptr; - if (merged_) { - __ CompareObject(result, Bool::True()); - __ b(instruction()->is_negated() ? labels_.false_label - : labels_.true_label, - EQ); - __ b(instruction()->is_negated() ? labels_.true_label - : labels_.false_label); - } else { - if (instruction()->is_negated()) { - // Need to negate the result of slow path call. - __ CompareObject(result, Bool::True()); - __ LoadObject(result, Bool::True(), NE); - __ LoadObject(result, Bool::False(), EQ); - } - __ b(exit_label()); - } - } - - private: - intptr_t try_index_; - BranchLabels labels_; - bool merged_; - Environment* env_; -}; - -LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( - Zone* zone, - bool opt) const { - const intptr_t kNumInputs = 2; - const intptr_t kNumTemps = 1; - LocationSummary* summary = new (zone) LocationSummary( - zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); - summary->set_in(0, Location::RequiresRegister()); - summary->set_in(1, Location::RequiresRegister()); - summary->set_temp(0, Location::RequiresRegister()); - summary->set_out(0, Location::RequiresRegister()); - return summary; -} - -Condition CheckedSmiComparisonInstr::EmitComparisonCode( - FlowGraphCompiler* compiler, - BranchLabels labels) { - return EmitSmiComparisonOp(compiler, locs(), kind()); -} - -#define EMIT_SMI_CHECK \ - Register left = locs()->in(0).reg(); \ - Register right = locs()->in(1).reg(); \ - Register temp = locs()->temp(0).reg(); \ - intptr_t left_cid = this->left()->Type()->ToCid(); \ - intptr_t right_cid = this->right()->Type()->ToCid(); \ - if (FLAG_use_slow_path) { \ - __ b(slow_path->entry_label()); \ - } else if (this->left()->definition() == this->right()->definition()) { \ - __ BranchIfNotSmi(left, slow_path->entry_label()); \ - } else if (left_cid == kSmiCid) { \ - __ BranchIfNotSmi(right, slow_path->entry_label()); \ - } else if (right_cid == kSmiCid) { \ - __ BranchIfNotSmi(left, slow_path->entry_label()); \ - } else { \ - __ orr(temp, left, compiler::Operand(right)); \ - __ BranchIfNotSmi(temp, slow_path->entry_label()); \ - } - -void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, - BranchInstr* branch) { - BranchLabels labels = compiler->CreateBranchLabels(branch); - CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( - this, branch->env(), compiler->CurrentTryIndex(), labels, - /* merged = */ true); - compiler->AddSlowPathCode(slow_path); - EMIT_SMI_CHECK; - Condition true_condition = EmitComparisonCode(compiler, labels); - ASSERT(true_condition != kInvalidCondition); - EmitBranchOnCondition(compiler, true_condition, labels); - __ Bind(slow_path->exit_label()); -} - -void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - BranchLabels labels = {NULL, NULL, NULL}; - CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( - this, env(), compiler->CurrentTryIndex(), labels, - /* merged = */ false); - compiler->AddSlowPathCode(slow_path); - EMIT_SMI_CHECK; - Condition true_condition = EmitComparisonCode(compiler, labels); - ASSERT(true_condition != kInvalidCondition); - Register result = locs()->out(0).reg(); - __ LoadObject(result, Bool::True(), true_condition); - __ LoadObject(result, Bool::False(), InvertCondition(true_condition)); - __ Bind(slow_path->exit_label()); -} -#undef EMIT_SMI_CHECK - LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, bool opt) const { const intptr_t kNumInputs = 2; diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc index 49613ff9791..84bcb800c20 100644 --- a/runtime/vm/compiler/backend/il_arm64.cc +++ b/runtime/vm/compiler/backend/il_arm64.cc @@ -3467,311 +3467,6 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, } } -class CheckedSmiSlowPath : public TemplateSlowPathCode { - public: - static constexpr intptr_t kNumSlowPathArgs = 2; - - CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) - : TemplateSlowPathCode(instruction), try_index_(try_index) {} - - virtual void EmitNativeCode(FlowGraphCompiler* compiler) { - if (compiler::Assembler::EmittingComments()) { - __ Comment("slow path smi operation"); - } - __ Bind(entry_label()); - LocationSummary* locs = instruction()->locs(); - Register result = locs->out(0).reg(); - locs->live_registers()->Remove(Location::RegisterLocation(result)); - - compiler->SaveLiveRegisters(locs); - if (instruction()->env() != NULL) { - Environment* env = - compiler->SlowPathEnvironmentFor(instruction(), kNumSlowPathArgs); - compiler->pending_deoptimization_env_ = env; - } - __ PushPair(locs->in(1).reg(), locs->in(0).reg()); - const auto& selector = String::Handle(instruction()->call()->Selector()); - const auto& arguments_descriptor = - Array::Handle(ArgumentsDescriptor::NewBoxed( - /*type_args_len=*/0, /*num_arguments=*/2)); - compiler->EmitMegamorphicInstanceCall( - selector, arguments_descriptor, instruction()->call()->deopt_id(), - instruction()->source(), locs, try_index_, kNumSlowPathArgs); - __ mov(result, R0); - compiler->RestoreLiveRegisters(locs); - __ b(exit_label()); - compiler->pending_deoptimization_env_ = NULL; - } - - private: - intptr_t try_index_; -}; - -LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, - bool opt) const { - const intptr_t kNumInputs = 2; - const intptr_t kNumTemps = 0; - LocationSummary* summary = new (zone) LocationSummary( - zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); - summary->set_in(0, Location::RequiresRegister()); - summary->set_in(1, Location::RequiresRegister()); - summary->set_out(0, Location::RequiresRegister()); - return summary; -} - -void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - CheckedSmiSlowPath* slow_path = - new CheckedSmiSlowPath(this, compiler->CurrentTryIndex()); - compiler->AddSlowPathCode(slow_path); - // Test operands if necessary. - Register left = locs()->in(0).reg(); - Register right = locs()->in(1).reg(); - Register result = locs()->out(0).reg(); - intptr_t left_cid = this->left()->Type()->ToCid(); - intptr_t right_cid = this->right()->Type()->ToCid(); - bool combined_smi_check = false; - if (FLAG_use_slow_path) { - __ b(slow_path->entry_label()); - } else if (this->left()->definition() == this->right()->definition()) { - __ BranchIfNotSmi(left, slow_path->entry_label()); - } else if (left_cid == kSmiCid) { - __ BranchIfNotSmi(right, slow_path->entry_label()); - } else if (right_cid == kSmiCid) { - __ BranchIfNotSmi(left, slow_path->entry_label()); - } else { - combined_smi_check = true; - __ orr(result, left, compiler::Operand(right)); - __ BranchIfNotSmi(result, slow_path->entry_label()); - } - - switch (op_kind()) { - case Token::kADD: - __ adds(result, left, compiler::Operand(right), compiler::kObjectBytes); - __ b(slow_path->entry_label(), VS); - break; - case Token::kSUB: - __ subs(result, left, compiler::Operand(right), compiler::kObjectBytes); - __ b(slow_path->entry_label(), VS); - break; - case Token::kMUL: - __ SmiUntag(TMP, left); -#if !defined(DART_COMPRESSED_POINTERS) - __ mul(result, TMP, right); - __ smulh(TMP, TMP, right); - // TMP: result bits 64..127. -#else - __ smull(result, TMP, right); - __ AsrImmediate(TMP, result, 31); - // TMP: result bits 32..63. -#endif - __ cmp(TMP, compiler::Operand(result, ASR, 63)); - __ b(slow_path->entry_label(), NE); - break; - case Token::kBIT_OR: - // Operation may be part of combined smi check. - if (!combined_smi_check) { - __ orr(result, left, compiler::Operand(right)); - } - break; - case Token::kBIT_AND: - __ and_(result, left, compiler::Operand(right)); - break; - case Token::kBIT_XOR: - __ eor(result, left, compiler::Operand(right)); - break; - case Token::kSHL: - ASSERT(result != left); - ASSERT(result != right); - __ CompareObject(right, Smi::ZoneHandle(Smi::New(Smi::kBits))); - __ b(slow_path->entry_label(), CS); - - __ SmiUntag(TMP, right); - __ lslv(result, left, TMP, compiler::kObjectBytes); - __ asrv(TMP2, result, TMP, compiler::kObjectBytes); - __ cmp(left, compiler::Operand(TMP2), compiler::kObjectBytes); - __ b(slow_path->entry_label(), NE); // Overflow. - break; - case Token::kSHR: - ASSERT(result != left); - ASSERT(result != right); - __ CompareObject(right, Smi::ZoneHandle(Smi::New(Smi::kBits))); - __ b(slow_path->entry_label(), CS); - - __ SmiUntag(result, right); - __ SmiUntag(TMP, left); - __ asrv(result, TMP, result, compiler::kObjectBytes); - __ SmiTag(result); - break; - case Token::kUSHR: - ASSERT(result != left); - ASSERT(result != right); - __ CompareObject(right, Smi::ZoneHandle(Smi::New(kBitsPerInt64))); - __ b(slow_path->entry_label(), UNSIGNED_GREATER_EQUAL); - - __ SmiUntag(result, right); - __ SmiUntag(TMP, left); - __ lsrv(result, TMP, result); - __ SmiTagAndBranchIfOverflow(result, slow_path->entry_label()); - break; - default: - UNIMPLEMENTED(); - } - __ Bind(slow_path->exit_label()); -} - -class CheckedSmiComparisonSlowPath - : public TemplateSlowPathCode { - public: - static constexpr intptr_t kNumSlowPathArgs = 2; - - CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, - Environment* env, - intptr_t try_index, - BranchLabels labels, - bool merged) - : TemplateSlowPathCode(instruction), - try_index_(try_index), - labels_(labels), - merged_(merged), - env_(env) { - // The environment must either come from the comparison or the environment - // was cleared from the comparison (and moved to a branch). - ASSERT(env == instruction->env() || - (merged && instruction->env() == nullptr)); - } - - virtual void EmitNativeCode(FlowGraphCompiler* compiler) { - if (compiler::Assembler::EmittingComments()) { - __ Comment("slow path smi operation"); - } - __ Bind(entry_label()); - LocationSummary* locs = instruction()->locs(); - Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); - locs->live_registers()->Remove(Location::RegisterLocation(result)); - - compiler->SaveLiveRegisters(locs); - if (env_ != nullptr) { - compiler->pending_deoptimization_env_ = - compiler->SlowPathEnvironmentFor(env_, locs, kNumSlowPathArgs); - } - __ PushPair(locs->in(1).reg(), locs->in(0).reg()); - const auto& selector = String::Handle(instruction()->call()->Selector()); - const auto& arguments_descriptor = - Array::Handle(ArgumentsDescriptor::NewBoxed( - /*type_args_len=*/0, /*num_arguments=*/2)); - compiler->EmitMegamorphicInstanceCall( - selector, arguments_descriptor, instruction()->call()->deopt_id(), - instruction()->source(), locs, try_index_, kNumSlowPathArgs); - __ mov(result, R0); - compiler->RestoreLiveRegisters(locs); - compiler->pending_deoptimization_env_ = nullptr; - if (merged_) { - __ CompareObject(result, Bool::True()); - __ b(instruction()->is_negated() ? labels_.false_label - : labels_.true_label, - EQ); - __ b(instruction()->is_negated() ? labels_.true_label - : labels_.false_label); - ASSERT(exit_label()->IsUnused()); - } else { - ASSERT(!instruction()->is_negated()); - __ b(exit_label()); - } - } - - private: - intptr_t try_index_; - BranchLabels labels_; - bool merged_; - Environment* env_; -}; - -LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( - Zone* zone, - bool opt) const { - const intptr_t kNumInputs = 2; - const intptr_t kNumTemps = 1; - LocationSummary* summary = new (zone) LocationSummary( - zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); - summary->set_in(0, Location::RequiresRegister()); - summary->set_in(1, Location::RequiresRegister()); - summary->set_temp(0, Location::RequiresRegister()); - summary->set_out(0, Location::RequiresRegister()); - return summary; -} - -Condition CheckedSmiComparisonInstr::EmitComparisonCode( - FlowGraphCompiler* compiler, - BranchLabels labels) { - return EmitSmiComparisonOp(compiler, locs(), kind(), labels); -} - -#define EMIT_SMI_CHECK \ - Register left = locs()->in(0).reg(); \ - Register right = locs()->in(1).reg(); \ - Register temp = locs()->temp(0).reg(); \ - intptr_t left_cid = this->left()->Type()->ToCid(); \ - intptr_t right_cid = this->right()->Type()->ToCid(); \ - if (FLAG_use_slow_path) { \ - __ b(slow_path->entry_label()); \ - } else if (this->left()->definition() == this->right()->definition()) { \ - __ BranchIfNotSmi(left, slow_path->entry_label()); \ - } else if (left_cid == kSmiCid) { \ - __ BranchIfNotSmi(right, slow_path->entry_label()); \ - } else if (right_cid == kSmiCid) { \ - __ BranchIfNotSmi(left, slow_path->entry_label()); \ - } else { \ - __ orr(temp, left, compiler::Operand(right)); \ - __ BranchIfNotSmi(temp, slow_path->entry_label()); \ - } - -void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, - BranchInstr* branch) { - BranchLabels labels = compiler->CreateBranchLabels(branch); - CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( - this, branch->env(), compiler->CurrentTryIndex(), labels, - /* merged = */ true); - compiler->AddSlowPathCode(slow_path); - EMIT_SMI_CHECK; - Condition true_condition = EmitComparisonCode(compiler, labels); - if (true_condition != kInvalidCondition) { - EmitBranchOnCondition(compiler, true_condition, labels); - } - // No need to bind slow_path->exit_label() as slow path exits through - // true/false branch labels. -} - -void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - // Zone-allocate labels to pass them to slow-path which outlives local scope. - compiler::Label* true_label = new (Z) compiler::Label(); - compiler::Label* false_label = new (Z) compiler::Label(); - compiler::Label done; - BranchLabels labels = {true_label, false_label, false_label}; - // In case of negated comparison result of a slow path call should be negated. - // For this purpose, 'merged' slow path is generated: it tests - // result of a call and jumps directly to true or false label. - CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( - this, env(), compiler->CurrentTryIndex(), labels, - /* merged = */ is_negated()); - compiler->AddSlowPathCode(slow_path); - EMIT_SMI_CHECK; - Condition true_condition = EmitComparisonCode(compiler, labels); - if (true_condition != kInvalidCondition) { - EmitBranchOnCondition(compiler, true_condition, labels); - } - Register result = locs()->out(0).reg(); - __ Bind(false_label); - __ LoadObject(result, Bool::False()); - __ b(&done); - __ Bind(true_label); - __ LoadObject(result, Bool::True()); - __ Bind(&done); - // In case of negated comparison slow path exits through true/false labels. - if (!is_negated()) { - __ Bind(slow_path->exit_label()); - } -} - LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, bool opt) const { const intptr_t kNumInputs = 2; diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc index bb3261df70b..8c6fe6d0316 100644 --- a/runtime/vm/compiler/backend/il_ia32.cc +++ b/runtime/vm/compiler/backend/il_ia32.cc @@ -3127,45 +3127,6 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, } } -LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, - bool opt) const { - // Only for precompiled code, not on ia32 currently. - UNIMPLEMENTED(); - return NULL; -} - -void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - // Only for precompiled code, not on ia32 currently. - UNIMPLEMENTED(); -} - -LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( - Zone* zone, - bool opt) const { - // Only for precompiled code, not on ia32 currently. - UNIMPLEMENTED(); - return NULL; -} - -Condition CheckedSmiComparisonInstr::EmitComparisonCode( - FlowGraphCompiler* compiler, - BranchLabels labels) { - // Only for precompiled code, not on ia32 currently. - UNIMPLEMENTED(); - return ZERO; -} - -void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, - BranchInstr* instr) { - // Only for precompiled code, not on ia32 currently. - UNIMPLEMENTED(); -} - -void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - // Only for precompiled code, not on ia32 currently. - UNIMPLEMENTED(); -} - static bool IsSmiValue(const Object& constant, intptr_t value) { return constant.IsSmi() && (Smi::Cast(constant).Value() == value); } diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc index b42d9dedec7..57734019fd7 100644 --- a/runtime/vm/compiler/backend/il_printer.cc +++ b/runtime/vm/compiler/backend/il_printer.cc @@ -730,22 +730,6 @@ void UnaryIntegerOpInstr::PrintOperandsTo(BaseTextBuffer* f) const { value()->PrintTo(f); } -void CheckedSmiOpInstr::PrintOperandsTo(BaseTextBuffer* f) const { - f->Printf("%s", Token::Str(op_kind())); - f->AddString(", "); - left()->PrintTo(f); - f->AddString(", "); - right()->PrintTo(f); -} - -void CheckedSmiComparisonInstr::PrintOperandsTo(BaseTextBuffer* f) const { - f->Printf("%s", Token::Str(kind())); - f->AddString(", "); - left()->PrintTo(f); - f->AddString(", "); - right()->PrintTo(f); -} - void BinaryIntegerOpInstr::PrintOperandsTo(BaseTextBuffer* f) const { f->Printf("%s", Token::Str(op_kind())); if (is_truncating()) { diff --git a/runtime/vm/compiler/backend/il_test_helper.cc b/runtime/vm/compiler/backend/il_test_helper.cc index b860562ba9a..a99374cbfe7 100644 --- a/runtime/vm/compiler/backend/il_test_helper.cc +++ b/runtime/vm/compiler/backend/il_test_helper.cc @@ -202,8 +202,7 @@ void TestPipeline::CompileGraphAndAttachFunction() { // We expect there to be no deoptimizations. if (mode_ == CompilerPass::kAOT) { - // TODO(kustermann): Enable this once we get rid of [CheckedSmiSlowPath]s. - // EXPECT(deopt_info_array.IsNull() || deopt_info_array.Length() == 0); + EXPECT(deopt_info_array.IsNull() || deopt_info_array.Length() == 0); } } diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc index 1b5a09af363..ed081c78bb0 100644 --- a/runtime/vm/compiler/backend/il_x64.cc +++ b/runtime/vm/compiler/backend/il_x64.cc @@ -3554,342 +3554,6 @@ static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, } } -class CheckedSmiSlowPath : public TemplateSlowPathCode { - public: - CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) - : TemplateSlowPathCode(instruction), try_index_(try_index) {} - - static constexpr intptr_t kNumSlowPathArgs = 2; - - virtual void EmitNativeCode(FlowGraphCompiler* compiler) { - if (compiler::Assembler::EmittingComments()) { - __ Comment("slow path smi operation"); - } - __ Bind(entry_label()); - LocationSummary* locs = instruction()->locs(); - Register result = locs->out(0).reg(); - locs->live_registers()->Remove(Location::RegisterLocation(result)); - - compiler->SaveLiveRegisters(locs); - if (instruction()->env() != NULL) { - Environment* env = - compiler->SlowPathEnvironmentFor(instruction(), kNumSlowPathArgs); - compiler->pending_deoptimization_env_ = env; - } - __ pushq(locs->in(0).reg()); - __ pushq(locs->in(1).reg()); - const auto& selector = String::Handle(instruction()->call()->Selector()); - const auto& arguments_descriptor = - Array::Handle(ArgumentsDescriptor::NewBoxed( - /*type_args_len=*/0, /*num_arguments=*/2)); - compiler->EmitMegamorphicInstanceCall( - selector, arguments_descriptor, instruction()->call()->deopt_id(), - instruction()->source(), locs, try_index_, kNumSlowPathArgs); - __ MoveRegister(result, RAX); - compiler->RestoreLiveRegisters(locs); - __ jmp(exit_label()); - compiler->pending_deoptimization_env_ = NULL; - } - - private: - intptr_t try_index_; -}; - -LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, - bool opt) const { - bool is_shift = (op_kind() == Token::kSHL) || (op_kind() == Token::kSHR) || - (op_kind() == Token::kUSHR); - const intptr_t kNumInputs = 2; - const intptr_t kNumTemps = is_shift ? 1 : 0; - LocationSummary* summary = new (zone) LocationSummary( - zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); - summary->set_in(0, Location::RequiresRegister()); - summary->set_in(1, Location::RequiresRegister()); - switch (op_kind()) { - case Token::kADD: - case Token::kSUB: - case Token::kMUL: - case Token::kSHL: - case Token::kSHR: - case Token::kUSHR: - summary->set_out(0, Location::RequiresRegister()); - break; - case Token::kBIT_OR: - case Token::kBIT_AND: - case Token::kBIT_XOR: - summary->set_out(0, Location::SameAsFirstInput()); - break; - default: - UNIMPLEMENTED(); - } - if (is_shift) { - summary->set_temp(0, Location::RegisterLocation(RCX)); - } - return summary; -} - -void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - CheckedSmiSlowPath* slow_path = - new CheckedSmiSlowPath(this, compiler->CurrentTryIndex()); - compiler->AddSlowPathCode(slow_path); - // Test operands if necessary. - - intptr_t left_cid = left()->Type()->ToCid(); - intptr_t right_cid = right()->Type()->ToCid(); - Register left = locs()->in(0).reg(); - Register right = locs()->in(1).reg(); - if (FLAG_use_slow_path) { - __ jmp(slow_path->entry_label()); - } else if (this->left()->definition() == this->right()->definition()) { - __ BranchIfNotSmi(left, slow_path->entry_label()); - } else if (left_cid == kSmiCid) { - __ BranchIfNotSmi(right, slow_path->entry_label()); - } else if (right_cid == kSmiCid) { - __ BranchIfNotSmi(left, slow_path->entry_label()); - } else { - __ movq(TMP, left); - __ orq(TMP, right); - __ BranchIfNotSmi(TMP, slow_path->entry_label()); - } - Register result = locs()->out(0).reg(); - switch (op_kind()) { - case Token::kADD: - __ movq(result, left); - __ OBJ(add)(result, right); - __ j(OVERFLOW, slow_path->entry_label()); - break; - case Token::kSUB: - __ movq(result, left); - __ OBJ(sub)(result, right); - __ j(OVERFLOW, slow_path->entry_label()); - break; - case Token::kMUL: - __ movq(result, left); - __ SmiUntag(result); - __ OBJ(imul)(result, right); - __ j(OVERFLOW, slow_path->entry_label()); - break; - case Token::kBIT_OR: - ASSERT(left == result); - __ orq(result, right); - break; - case Token::kBIT_AND: - ASSERT(left == result); - __ andq(result, right); - break; - case Token::kBIT_XOR: - ASSERT(left == result); - __ xorq(result, right); - break; - case Token::kSHL: - ASSERT(result != right); - ASSERT(locs()->temp(0).reg() == RCX); - __ CompareObject(right, Smi::ZoneHandle(Smi::New(Smi::kBits))); - __ j(ABOVE_EQUAL, slow_path->entry_label()); - - __ movq(RCX, right); - __ SmiUntag(RCX); - __ movq(result, left); - __ shlq(result, RCX); - __ movq(TMP, result); - __ OBJ(sar)(TMP, RCX); - __ OBJ(cmp)(TMP, left); - __ j(NOT_EQUAL, slow_path->entry_label()); - break; - case Token::kSHR: - ASSERT(result != right); - ASSERT(locs()->temp(0).reg() == RCX); - __ CompareObject(right, Smi::ZoneHandle(Smi::New(Smi::kBits))); - __ j(ABOVE_EQUAL, slow_path->entry_label()); - - __ movq(RCX, right); - __ SmiUntag(RCX); - __ movq(result, left); - __ SmiUntag(result); - __ OBJ(sar)(result, RCX); - __ SmiTag(result); - break; - case Token::kUSHR: { - ASSERT(result != right); - ASSERT(locs()->temp(0).reg() == RCX); - __ CompareObject(right, Smi::ZoneHandle(Smi::New(kBitsPerInt64))); - __ j(ABOVE_EQUAL, slow_path->entry_label()); - - __ movq(RCX, right); - __ SmiUntag(RCX); - __ movq(result, left); - __ SmiUntagAndSignExtend(result); - __ shrq(result, RCX); - __ shlq(result, compiler::Immediate(1)); // SmiTag, keep hi bits. - __ j(OVERFLOW, slow_path->entry_label()); -#if defined(DART_COMPRESSED_POINTERS) - const Register temp = locs()->temp(0).reg(); - __ movsxd(temp, result); - __ cmpq(temp, result); - __ j(NOT_EQUAL, slow_path->entry_label()); -#endif // defined(DART_COMPRESSED_POINTERS) - break; - } - default: - UNIMPLEMENTED(); - } - __ Bind(slow_path->exit_label()); -} - -class CheckedSmiComparisonSlowPath - : public TemplateSlowPathCode { - public: - static constexpr intptr_t kNumSlowPathArgs = 2; - - CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, - Environment* env, - intptr_t try_index, - BranchLabels labels, - bool merged) - : TemplateSlowPathCode(instruction), - try_index_(try_index), - labels_(labels), - merged_(merged), - env_(env) { - // The environment must either come from the comparison or the environment - // was cleared from the comparison (and moved to a branch). - ASSERT(env == instruction->env() || - (merged && instruction->env() == nullptr)); - } - - virtual void EmitNativeCode(FlowGraphCompiler* compiler) { - if (compiler::Assembler::EmittingComments()) { - __ Comment("slow path smi comparison"); - } - __ Bind(entry_label()); - LocationSummary* locs = instruction()->locs(); - Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); - locs->live_registers()->Remove(Location::RegisterLocation(result)); - - compiler->SaveLiveRegisters(locs); - if (env_ != nullptr) { - compiler->pending_deoptimization_env_ = - compiler->SlowPathEnvironmentFor(env_, locs, kNumSlowPathArgs); - } - __ pushq(locs->in(0).reg()); - __ pushq(locs->in(1).reg()); - - const auto& selector = String::Handle(instruction()->call()->Selector()); - const auto& arguments_descriptor = - Array::Handle(ArgumentsDescriptor::NewBoxed( - /*type_args_len=*/0, /*num_arguments=*/2)); - - compiler->EmitMegamorphicInstanceCall( - selector, arguments_descriptor, instruction()->call()->deopt_id(), - instruction()->source(), locs, try_index_, kNumSlowPathArgs); - __ MoveRegister(result, RAX); - compiler->RestoreLiveRegisters(locs); - compiler->pending_deoptimization_env_ = nullptr; - if (merged_) { - __ CompareObject(result, Bool::True()); - __ j(EQUAL, instruction()->is_negated() ? labels_.false_label - : labels_.true_label); - __ jmp(instruction()->is_negated() ? labels_.true_label - : labels_.false_label); - ASSERT(exit_label()->IsUnused()); - } else { - ASSERT(!instruction()->is_negated()); - __ jmp(exit_label()); - } - } - - private: - intptr_t try_index_; - BranchLabels labels_; - bool merged_; - Environment* env_; -}; - -LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( - Zone* zone, - bool opt) const { - const intptr_t kNumInputs = 2; - const intptr_t kNumTemps = 1; - LocationSummary* summary = new (zone) LocationSummary( - zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); - summary->set_in(0, Location::RequiresRegister()); - summary->set_in(1, Location::RequiresRegister()); - summary->set_temp(0, Location::RequiresRegister()); - summary->set_out(0, Location::RequiresRegister()); - return summary; -} - -Condition CheckedSmiComparisonInstr::EmitComparisonCode( - FlowGraphCompiler* compiler, - BranchLabels labels) { - return EmitSmiComparisonOp(compiler, *locs(), kind()); -} - -#define EMIT_SMI_CHECK \ - intptr_t left_cid = left()->Type()->ToCid(); \ - intptr_t right_cid = right()->Type()->ToCid(); \ - Register left = locs()->in(0).reg(); \ - Register right = locs()->in(1).reg(); \ - if (FLAG_use_slow_path) { \ - __ jmp(slow_path->entry_label()); \ - } else if (this->left()->definition() == this->right()->definition()) { \ - __ BranchIfNotSmi(left, slow_path->entry_label()); \ - } else if (left_cid == kSmiCid) { \ - __ BranchIfNotSmi(right, slow_path->entry_label()); \ - } else if (right_cid == kSmiCid) { \ - __ BranchIfNotSmi(left, slow_path->entry_label()); \ - } else { \ - __ movq(TMP, left); \ - __ orq(TMP, right); \ - __ BranchIfNotSmi(TMP, slow_path->entry_label()); \ - } - -void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, - BranchInstr* branch) { - BranchLabels labels = compiler->CreateBranchLabels(branch); - CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( - this, branch->env(), compiler->CurrentTryIndex(), labels, - /* merged = */ true); - compiler->AddSlowPathCode(slow_path); - EMIT_SMI_CHECK; - Condition true_condition = EmitComparisonCode(compiler, labels); - ASSERT(true_condition != kInvalidCondition); - EmitBranchOnCondition(compiler, true_condition, labels); - // No need to bind slow_path->exit_label() as slow path exits through - // true/false branch labels. -} - -void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - // Zone-allocate labels to pass them to slow-path which outlives local scope. - compiler::Label* true_label = new (Z) compiler::Label(); - compiler::Label* false_label = new (Z) compiler::Label(); - compiler::Label done; - BranchLabels labels = {true_label, false_label, false_label}; - // In case of negated comparison result of a slow path call should be negated. - // For this purpose, 'merged' slow path is generated: it tests - // result of a call and jumps directly to true or false label. - CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( - this, env(), compiler->CurrentTryIndex(), labels, - /* merged = */ is_negated()); - compiler->AddSlowPathCode(slow_path); - EMIT_SMI_CHECK; - Condition true_condition = EmitComparisonCode(compiler, labels); - ASSERT(true_condition != kInvalidCondition); - EmitBranchOnCondition(compiler, true_condition, labels, - compiler::Assembler::kNearJump); - Register result = locs()->out(0).reg(); - __ Bind(false_label); - __ LoadObject(result, Bool::False()); - __ jmp(&done, compiler::Assembler::kNearJump); - __ Bind(true_label); - __ LoadObject(result, Bool::True()); - __ Bind(&done); - // In case of negated comparison slow path exits through true/false labels. - if (!is_negated()) { - __ Bind(slow_path->exit_label()); - } -} - static bool CanBeImmediate(const Object& constant) { return constant.IsSmi() && compiler::Immediate(static_cast(constant.ptr())).is_int32(); diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc index c8e01c49730..164e8bbc07b 100644 --- a/runtime/vm/compiler/backend/type_propagator.cc +++ b/runtime/vm/compiler/backend/type_propagator.cc @@ -1595,30 +1595,6 @@ CompileType UnaryInt64OpInstr::ComputeType() const { return CompileType::Int(); } -CompileType CheckedSmiOpInstr::ComputeType() const { - if (left()->Type()->IsNullableInt() && right()->Type()->IsNullableInt()) { - const AbstractType& abstract_type = - AbstractType::ZoneHandle(Type::IntType()); - TraceStrongModeType(this, abstract_type); - return CompileType::FromAbstractType(abstract_type, - CompileType::kNonNullable); - } else { - CompileType* type = call()->Type(); - TraceStrongModeType(this, type); - return *type; - } -} - -bool CheckedSmiOpInstr::RecomputeType() { - return UpdateType(ComputeType()); -} - -CompileType CheckedSmiComparisonInstr::ComputeType() const { - CompileType* type = call()->Type(); - TraceStrongModeType(this, type); - return *type; -} - CompileType BoxIntegerInstr::ComputeType() const { return ValueFitsSmi() ? CompileType::FromCid(kSmiCid) : CompileType::Int(); }