VM-codegen: Clean up the way we emit code for comparison instructions.

Removes some redundancy in the Emit* methods in intermediate_language_*.cc for
the 6 architectures we support.

This is a reapplication of https://codereview.chromium.org/2937933002/ -
see the comments there.  It fixes a bug in the way the TestCids
instruction was emitted on DBC.

R=vegorov@google.com
BUG=

Review-Url: https://codereview.chromium.org/2947633002 .
This commit is contained in:
Erik Corry 2017-06-20 17:41:09 +02:00
parent 9d495064f7
commit dfb67ecbf8
16 changed files with 333 additions and 902 deletions

View file

@ -162,10 +162,20 @@ class Condition : public ValueObject {
: public BitField<uword, RelationOperator, kRelOpPos, kRelOpSize> {};
class ImmBits : public BitField<uword, uint16_t, kImmPos, kImmSize> {};
Register left() const { return LeftBits::decode(bits_); }
Register right() const { return RightBits::decode(bits_); }
Register left() const {
ASSERT(IsValid());
return LeftBits::decode(bits_);
}
Register right() const {
ASSERT(IsValid());
return RightBits::decode(bits_);
}
RelationOperator rel_op() const { return RelOpBits::decode(bits_); }
int16_t imm() const { return static_cast<int16_t>(ImmBits::decode(bits_)); }
int16_t imm() const {
ASSERT(IsValid());
return static_cast<int16_t>(ImmBits::decode(bits_));
}
static bool IsValidImm(int32_t value) {
// We want both value and value + 1 to fit in an int16_t.
@ -177,8 +187,10 @@ class Condition : public ValueObject {
bits_ = RelOpBits::update(value, bits_);
}
bool IsValid() const { return rel_op() != INVALID_RELATION; }
// Uninitialized condition.
Condition() : ValueObject(), bits_(0) {}
Condition() : ValueObject(), bits_(RelOpBits::update(INVALID_RELATION, 0)) {}
// Copy constructor.
Condition(const Condition& other) : ValueObject(), bits_(other.bits_) {}
@ -200,11 +212,19 @@ class Condition : public ValueObject {
ASSERT((imm != 0) == ((left == IMM) || (right == IMM)));
set_left(left);
set_right(right);
set_rel_op(rel_op);
if (rel_op == INVALID_RELATION) {
SetToInvalidState();
} else {
set_rel_op(rel_op);
}
set_imm(imm);
}
private:
void SetToInvalidState() {
bits_ = RelOpBits::update(INVALID_RELATION, bits_);
}
static bool IsValidRelOp(RelationOperator value) {
return (AL <= value) && (value <= ULE);
}

View file

@ -354,7 +354,8 @@ enum Condition {
LE = 13, // signed less than or equal
AL = 14, // always (unconditional)
kSpecialCondition = 15, // special condition (refer to section A3.2.1)
kMaxCondition = 16,
kNumberOfConditions = 16,
kInvalidCondition = 16
};

View file

@ -193,7 +193,8 @@ enum Condition {
LE = 13, // signed less than or equal
AL = 14, // always (unconditional)
NV = 15, // special condition (refer to section C1.2.3)
kMaxCondition = 16,
kNumberOfConditions = 16,
kInvalidCondition = 16
};
static inline Condition InvertCondition(Condition c) {

View file

@ -996,7 +996,7 @@ const intptr_t kNumberOfFpuRegisters = 1;
// instruction is executed if the comparison is true and skipped over overwise.
// Condition NEXT_IS_FALSE means the following instruction is executed if the
// comparison is false and skipped over otherwise.
enum Condition { NEXT_IS_TRUE, NEXT_IS_FALSE };
enum Condition { NEXT_IS_TRUE, NEXT_IS_FALSE, INVALID_CONDITION };
} // namespace dart

View file

@ -122,7 +122,9 @@ enum Condition {
NEGATIVE = SIGN,
POSITIVE = NOT_SIGN,
CARRY = BELOW,
NOT_CARRY = ABOVE_EQUAL
NOT_CARRY = ABOVE_EQUAL,
INVALID_CONDITION = 16
};

View file

@ -256,6 +256,7 @@ enum RelationOperator {
UGE, // unsigned greater equal
ULT, // unsigned less than
ULE, // unsigned less equal
INVALID_RELATION
};

View file

@ -147,7 +147,9 @@ enum Condition {
NEGATIVE = SIGN,
POSITIVE = NOT_SIGN,
CARRY = BELOW,
NOT_CARRY = ABOVE_EQUAL
NOT_CARRY = ABOVE_EQUAL,
INVALID_CONDITION = 16
};
#define R(reg) (1 << (reg))

View file

@ -96,7 +96,7 @@ void ARMDecoder::Print(const char* str) {
// These condition names are defined in a way to match the native disassembler
// formatting. See for example the command "objdump -d <binary file>".
static const char* cond_names[kMaxCondition] = {
static const char* cond_names[kNumberOfConditions] = {
"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
"hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
};

View file

@ -125,7 +125,7 @@ static const char* extend_names[kMaxExtend] = {
// These condition names are defined in a way to match the native disassembler
// formatting. See for example the command "objdump -d <binary file>".
static const char* cond_names[kMaxCondition] = {
static const char* cond_names[kNumberOfConditions] = {
"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
"hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
};

View file

@ -536,6 +536,26 @@ FOR_EACH_ABSTRACT_INSTRUCTION(FORWARD_DECLARATION)
DECLARE_INSTRUCTION_NO_BACKEND(type) \
DECLARE_INSTRUCTION_BACKEND()
#if defined(TARGET_ARCH_DBC)
#define DECLARE_COMPARISON_METHODS \
virtual LocationSummary* MakeLocationSummary(Zone* zone, bool optimizing) \
const; \
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler, \
BranchLabels labels); \
virtual Condition GetNextInstructionCondition(FlowGraphCompiler* compiler, \
BranchLabels labels);
#else
#define DECLARE_COMPARISON_METHODS \
virtual LocationSummary* MakeLocationSummary(Zone* zone, bool optimizing) \
const; \
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler, \
BranchLabels labels);
#endif
#define DECLARE_COMPARISON_INSTRUCTION(type) \
DECLARE_INSTRUCTION_NO_BACKEND(type) \
DECLARE_COMPARISON_METHODS
#ifndef PRODUCT
#define PRINT_TO_SUPPORT virtual void PrintTo(BufferFormatter* f) const;
#else
@ -966,6 +986,13 @@ class Instruction : public ZoneAllocated {
};
struct BranchLabels {
Label* true_label;
Label* false_label;
Label* fall_through;
};
class PureInstruction : public Instruction {
public:
explicit PureInstruction(intptr_t deopt_id) : Instruction(deopt_id) {}
@ -1920,13 +1947,6 @@ class TemplateDefinition : public CSETrait<Definition, PureDefinition>::Base {
};
struct BranchLabels {
Label* true_label;
Label* false_label;
Label* fall_through;
};
class InductionVariableInfo;
@ -2345,12 +2365,34 @@ class ComparisonInstr : public Definition {
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right) = 0;
virtual void EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) = 0;
// Emits instructions to do the comparison and branch to the true or false
// label depending on the result. This implementation will call
// EmitComparisonCode and then generate the branch instructions afterwards.
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
// Used by EmitBranchCode and EmitNativeCode depending on whether the boolean
// is to be turned into branches or instantiated. May return a valid
// condition in which case the caller is expected to emit a branch to the
// true label based on that condition (or a branch to the false label on the
// opposite condition). May also branch directly to the labels.
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
BranchLabels labels) = 0;
#if defined(TARGET_ARCH_DBC)
// On the DBC platform EmitNativeCode needs to know ahead of time what
// 'Condition' will be returned by EmitComparisonCode. This call must return
// the same result as EmitComparisonCode, but should not emit any
// instructions.
virtual Condition GetNextInstructionCondition(FlowGraphCompiler* compiler,
BranchLabels labels) = 0;
#endif
// Emits code that generates 'true' or 'false', depending on the comparison.
// This implementation will call EmitComparisonCode. If EmitComparisonCode
// does not use the labels (merely returning a condition) then EmitNativeCode
// may be able to use the condition to avoid a branch.
virtual void EmitNativeCode(FlowGraphCompiler* compiler);
void SetDeoptId(const Instruction& instr) { CopyDeoptIdFrom(instr); }
// Operation class id is computed from collected ICData.
@ -3038,7 +3080,7 @@ class StrictCompareInstr : public TemplateComparison<2, NoThrow, Pure> {
bool needs_number_check,
intptr_t deopt_id);
DECLARE_INSTRUCTION(StrictCompare)
DECLARE_COMPARISON_INSTRUCTION(StrictCompare)
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
@ -3048,11 +3090,6 @@ class StrictCompareInstr : public TemplateComparison<2, NoThrow, Pure> {
virtual Definition* Canonicalize(FlowGraph* flow_graph);
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
BranchLabels labels);
bool needs_number_check() const { return needs_number_check_; }
void set_needs_number_check(bool value) { needs_number_check_ = value; }
@ -3083,7 +3120,7 @@ class TestSmiInstr : public TemplateComparison<2, NoThrow, Pure> {
SetInputAt(1, right);
}
DECLARE_INSTRUCTION(TestSmi);
DECLARE_COMPARISON_INSTRUCTION(TestSmi);
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
@ -3095,11 +3132,6 @@ class TestSmiInstr : public TemplateComparison<2, NoThrow, Pure> {
return kTagged;
}
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
BranchLabels labels);
private:
DISALLOW_COPY_AND_ASSIGN(TestSmiInstr);
};
@ -3124,7 +3156,7 @@ class TestCidsInstr : public TemplateComparison<1, NoThrow, Pure> {
return cid_results_;
}
DECLARE_INSTRUCTION(TestCids);
DECLARE_COMPARISON_INSTRUCTION(TestCids);
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
@ -3142,11 +3174,6 @@ class TestCidsInstr : public TemplateComparison<1, NoThrow, Pure> {
virtual bool AttributesEqual(Instruction* other) const;
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
BranchLabels labels);
void set_licm_hoisted(bool value) { licm_hoisted_ = value; }
PRINT_OPERANDS_TO_SUPPORT
@ -3173,7 +3200,7 @@ class EqualityCompareInstr : public TemplateComparison<2, NoThrow, Pure> {
set_operation_cid(cid);
}
DECLARE_INSTRUCTION(EqualityCompare)
DECLARE_COMPARISON_INSTRUCTION(EqualityCompare)
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
@ -3181,11 +3208,6 @@ class EqualityCompareInstr : public TemplateComparison<2, NoThrow, Pure> {
virtual bool ComputeCanDeoptimize() const { return false; }
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
BranchLabels labels);
virtual Representation RequiredInputRepresentation(intptr_t idx) const {
ASSERT((idx == 0) || (idx == 1));
if (operation_cid() == kDoubleCid) return kUnboxedDouble;
@ -3215,7 +3237,7 @@ class RelationalOpInstr : public TemplateComparison<2, NoThrow, Pure> {
set_operation_cid(cid);
}
DECLARE_INSTRUCTION(RelationalOp)
DECLARE_COMPARISON_INSTRUCTION(RelationalOp)
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
@ -3223,11 +3245,6 @@ class RelationalOpInstr : public TemplateComparison<2, NoThrow, Pure> {
virtual bool ComputeCanDeoptimize() const { return false; }
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
BranchLabels labels);
virtual Representation RequiredInputRepresentation(intptr_t idx) const {
ASSERT((idx == 0) || (idx == 1));
if (operation_cid() == kDoubleCid) return kUnboxedDouble;
@ -5348,7 +5365,8 @@ class DoubleTestOpInstr : public TemplateComparison<1, NoThrow, Pure> {
PRINT_OPERANDS_TO_SUPPORT
DECLARE_INSTRUCTION(DoubleTestOp)
DECLARE_COMPARISON_INSTRUCTION(DoubleTestOp)
virtual CompileType ComputeType() const;
virtual Definition* Canonicalize(FlowGraph* flow_graph);
@ -5360,11 +5378,6 @@ class DoubleTestOpInstr : public TemplateComparison<1, NoThrow, Pure> {
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
virtual void EmitBranchCode(FlowGraphCompiler* compiler, BranchInstr* branch);
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
BranchLabels labels);
private:
const MethodRecognizer::Kind op_kind_;
@ -6934,6 +6947,14 @@ class CheckedSmiComparisonInstr : public TemplateComparison<2, Throws> {
virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
BranchLabels labels);
#if defined(TARGET_ARCH_DBC)
virtual Condition GetNextInstructionCondition(FlowGraphCompiler* compiler,
BranchLabels labels) {
UNREACHABLE();
return INVALID_CONDITION;
}
#endif
virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
private:

View file

@ -169,8 +169,11 @@ void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ eor(result, result, Operand(result));
// Emit comparison code. This must not overwrite the result register.
// IfThenElseInstr::Supports() should prevent EmitComparisonCode from using
// the labels or returning an invalid condition.
BranchLabels labels = {NULL, NULL, NULL};
Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
ASSERT(true_condition != kInvalidCondition);
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
@ -666,6 +669,7 @@ static Condition TokenKindToDoubleCondition(Token::Kind kind) {
static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
LocationSummary* locs,
BranchLabels labels,
Token::Kind kind) {
const QRegister left = locs->in(0).fpu_reg();
const QRegister right = locs->in(1).fpu_reg();
@ -674,6 +678,11 @@ static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
__ vcmpd(dleft, dright);
__ vmstat();
Condition true_condition = TokenKindToDoubleCondition(kind);
if (true_condition != NE) {
// Special case for NaN comparison. Result is always false unless
// relational operator is !=.
__ b(labels.false_label, VS);
}
return true_condition;
}
@ -686,51 +695,11 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
return EmitUnboxedMintEqualityOp(compiler, locs(), kind());
} else {
ASSERT(operation_cid() == kDoubleCid);
return EmitDoubleComparisonOp(compiler, locs(), kind());
return EmitDoubleComparisonOp(compiler, locs(), labels, kind());
}
}
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
// The ARM code does not use true- and false-labels here.
BranchLabels labels = {NULL, NULL, NULL};
Condition true_condition = EmitComparisonCode(compiler, labels);
const Register result = locs()->out(0).reg();
if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) {
__ LoadObject(result, Bool::True(), true_condition);
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
} else {
ASSERT(operation_cid() == kDoubleCid);
Label done;
__ LoadObject(result, Bool::False());
if (true_condition != NE) {
__ b(&done, VS); // x == NaN -> false, x != NaN -> true.
}
__ LoadObject(result, Bool::True(), true_condition);
__ Bind(&done);
}
}
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
if (operation_cid() == kDoubleCid) {
Label* nan_result =
(true_condition == NE) ? labels.true_label : labels.false_label;
__ b(nan_result, VS);
}
EmitBranchOnCondition(compiler, true_condition, labels);
}
LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
@ -760,20 +729,6 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// Never emitted outside of the BranchInstr.
UNREACHABLE();
}
void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
@ -826,30 +781,9 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
} else {
__ b(deopt);
}
// Dummy result as the last instruction is a jump, any conditional
// branch using the result will therefore be skipped.
return EQ;
}
void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
EmitComparisonCode(compiler, labels);
}
void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register result_reg = locs()->out(0).reg();
Label is_true, is_false, done;
BranchLabels labels = {&is_true, &is_false, &is_false};
EmitComparisonCode(compiler, labels);
__ Bind(&is_false);
__ LoadObject(result_reg, Bool::False());
__ b(&done);
__ Bind(&is_true);
__ LoadObject(result_reg, Bool::True());
__ Bind(&done);
// Dummy result as this method already did the jump, there's no need
// for the caller to branch on a condition.
return kInvalidCondition;
}
@ -898,54 +832,7 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
return EmitUnboxedMintComparisonOp(compiler, locs(), kind(), labels);
} else {
ASSERT(operation_cid() == kDoubleCid);
return EmitDoubleComparisonOp(compiler, locs(), kind());
}
}
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
const Register result = locs()->out(0).reg();
if (operation_cid() == kSmiCid) {
__ LoadObject(result, Bool::True(), true_condition);
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
} else if (operation_cid() == kMintCid) {
EmitBranchOnCondition(compiler, true_condition, labels);
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ b(&done);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
} else {
ASSERT(operation_cid() == kDoubleCid);
Label done;
__ LoadObject(result, Bool::False());
if (true_condition != NE) {
__ b(&done, VS); // x == NaN -> false, x != NaN -> true.
}
__ LoadObject(result, Bool::True(), true_condition);
__ Bind(&done);
}
}
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) {
EmitBranchOnCondition(compiler, true_condition, labels);
} else if (operation_cid() == kDoubleCid) {
Label* nan_result =
(true_condition == NE) ? labels.true_label : labels.false_label;
__ b(nan_result, VS);
EmitBranchOnCondition(compiler, true_condition, labels);
return EmitDoubleComparisonOp(compiler, locs(), labels, kind());
}
}
@ -3428,6 +3315,7 @@ void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
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());
}
@ -3441,6 +3329,7 @@ void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
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(), NegateCondition(true_condition));
@ -4404,38 +4293,6 @@ Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
}
void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT(compiler->is_optimizing());
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(compiler->is_optimizing());
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
const Register result = locs()->out(0).reg();
if (op_kind() == MethodRecognizer::kDouble_getIsNaN) {
__ LoadObject(result, Bool::True(), true_condition);
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
} else {
ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite);
EmitBranchOnCondition(compiler, true_condition, labels);
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ b(&done);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
}
}
LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
@ -7217,26 +7074,40 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
// The ARM code does not use true- and false-labels here.
BranchLabels labels = {NULL, NULL, NULL};
void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// The ARM code may not use true- and false-labels here.
Label is_true, is_false, done;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
const Register result = locs()->out(0).reg();
__ LoadObject(result, Bool::True(), true_condition);
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
const Register result = this->locs()->out(0).reg();
if (is_false.IsLinked() || is_true.IsLinked()) {
if (true_condition != kInvalidCondition) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ b(&done);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
} else {
// If EmitComparisonCode did not use the labels and just returned
// a condition we can avoid the branch and use conditional loads.
ASSERT(true_condition != kInvalidCondition);
__ LoadObject(result, Bool::True(), true_condition);
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
}
}
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
if (true_condition != kInvalidCondition) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
}

View file

@ -165,8 +165,11 @@ void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(!left.IsConstant() || !right.IsConstant());
// Emit comparison code. This must not overwrite the result register.
// IfThenElseInstr::Supports() should prevent EmitComparisonCode from using
// the labels or returning an invalid condition.
BranchLabels labels = {NULL, NULL, NULL};
Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
ASSERT(true_condition != kInvalidCondition);
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
@ -540,11 +543,17 @@ static Condition TokenKindToDoubleCondition(Token::Kind kind) {
static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
LocationSummary* locs,
BranchLabels labels,
Token::Kind kind) {
const VRegister left = locs->in(0).fpu_reg();
const VRegister right = locs->in(1).fpu_reg();
__ fcmpd(left, right);
Condition true_condition = TokenKindToDoubleCondition(kind);
if (true_condition != NE) {
// Special case for NaN comparison. Result is always false unless
// relational operator is !=.
__ b(labels.false_label, VS);
}
return true_condition;
}
@ -555,50 +564,11 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
return EmitSmiComparisonOp(compiler, locs(), kind());
} else {
ASSERT(operation_cid() == kDoubleCid);
return EmitDoubleComparisonOp(compiler, locs(), kind());
return EmitDoubleComparisonOp(compiler, locs(), labels, kind());
}
}
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
if ((operation_cid() == kDoubleCid) && (true_condition != NE)) {
// Special case for NaN comparison. Result is always false unless
// relational operator is !=.
__ b(&is_false, VS);
}
EmitBranchOnCondition(compiler, true_condition, labels);
// TODO(zra): instead of branching, use the csel instruction to get
// True or False into result.
const Register result = locs()->out(0).reg();
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ b(&done);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
}
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
if ((operation_cid() == kDoubleCid) && (true_condition != NE)) {
// Special case for NaN comparison. Result is always false unless
// relational operator is !=.
__ b(labels.false_label, VS);
}
EmitBranchOnCondition(compiler, true_condition, labels);
}
LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
@ -628,20 +598,6 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// Never emitted outside of the BranchInstr.
UNREACHABLE();
}
void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
@ -694,32 +650,9 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
} else {
__ b(deopt);
}
// Dummy result as the last instruction is a jump, any conditional
// branch using the result will therefore be skipped.
return EQ;
}
void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
EmitComparisonCode(compiler, labels);
}
void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register result_reg = locs()->out(0).reg();
Label is_true, is_false, done;
BranchLabels labels = {&is_true, &is_false, &is_false};
EmitComparisonCode(compiler, labels);
// TODO(zra): instead of branching, use the csel instruction to get
// True or False into result.
__ Bind(&is_false);
__ LoadObject(result_reg, Bool::False());
__ b(&done);
__ Bind(&is_true);
__ LoadObject(result_reg, Bool::True());
__ Bind(&done);
// Dummy result as this method already did the jump, there's no need
// for the caller to branch on a condition.
return kInvalidCondition;
}
@ -755,47 +688,11 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
return EmitSmiComparisonOp(compiler, locs(), kind());
} else {
ASSERT(operation_cid() == kDoubleCid);
return EmitDoubleComparisonOp(compiler, locs(), kind());
return EmitDoubleComparisonOp(compiler, locs(), labels, kind());
}
}
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
if ((operation_cid() == kDoubleCid) && (true_condition != NE)) {
// Special case for NaN comparison. Result is always false unless
// relational operator is !=.
__ b(&is_false, VS);
}
EmitBranchOnCondition(compiler, true_condition, labels);
// TODO(zra): instead of branching, use the csel instruction to get
// True or False into result.
const Register result = locs()->out(0).reg();
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ b(&done);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
}
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
if ((operation_cid() == kDoubleCid) && (true_condition != NE)) {
// Special case for NaN comparison. Result is always false unless
// relational operator is !=.
__ b(labels.false_label, VS);
}
EmitBranchOnCondition(compiler, true_condition, labels);
}
LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
return MakeCallSummary(zone);
@ -3136,6 +3033,7 @@ void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
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());
}
@ -3150,6 +3048,7 @@ void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
compiler->AddSlowPathCode(slow_path);
EMIT_SMI_CHECK;
Condition true_condition = EmitComparisonCode(compiler, labels);
ASSERT(true_condition != kInvalidCondition);
EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out(0).reg();
__ Bind(&false_label);
@ -3778,33 +3677,6 @@ Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT(compiler->is_optimizing());
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(compiler->is_optimizing());
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
const Register result = locs()->out(0).reg();
if (op_kind() == MethodRecognizer::kDouble_getIsNaN) {
__ LoadObject(result, Bool::False());
__ LoadObject(TMP, Bool::True());
__ csel(result, TMP, result, true_condition);
} else {
__ LoadObject(result, Bool::False());
__ LoadObject(TMP, Bool::True());
__ csel(result, TMP, result, true_condition);
}
}
LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
@ -6008,16 +5880,16 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ Comment("StrictCompareInstr");
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
const Register result = this->locs()->out(0).reg();
const Register result = locs()->out(0).reg();
// TODO(dartbug.com/29908): Use csel here for better branch prediction?
if (true_condition != kInvalidCondition) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
@ -6028,13 +5900,13 @@ void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
if (true_condition != kInvalidCondition) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
}

View file

@ -483,6 +483,14 @@ static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
}
Condition StrictCompareInstr::GetNextInstructionCondition(
FlowGraphCompiler* compiler,
BranchLabels labels) {
return (labels.fall_through == labels.false_label) ? NEXT_IS_TRUE
: NEXT_IS_FALSE;
}
Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
BranchLabels labels) {
ASSERT((kind() == Token::kNE_STRICT) || (kind() == Token::kEQ_STRICT));
@ -526,43 +534,68 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT));
DEFINE_MAKE_LOCATION_SUMMARY(StrictCompare,
2,
Location::RequiresRegister(),
needs_number_check() ? LocationSummary::kCall
: LocationSummary::kNoCall)
void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
if (true_condition != INVALID_CONDITION) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
}
EMIT_NATIVE_CODE(StrictCompare,
2,
Location::RequiresRegister(),
needs_number_check() ? LocationSummary::kCall
: LocationSummary::kNoCall) {
ASSERT((kind() == Token::kEQ_STRICT) || (kind() == Token::kNE_STRICT));
void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
Label done;
if (compiler->is_optimizing()) {
const Register result = locs()->out(0).reg();
__ Bind(&is_false);
__ LoadConstant(result, Bool::False());
__ Jump(&done);
__ Bind(&is_true);
__ LoadConstant(result, Bool::True());
__ Bind(&done);
} else {
Condition true_condition =
this->GetNextInstructionCondition(compiler, labels);
if (true_condition == INVALID_CONDITION || !compiler->is_optimizing() ||
is_true.IsLinked() || is_false.IsLinked()) {
Condition actual_condition = EmitComparisonCode(compiler, labels);
ASSERT(actual_condition == true_condition);
if (true_condition != INVALID_CONDITION) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
Label done;
__ Bind(&is_false);
__ PushConstant(Bool::False());
__ Jump(&done);
__ Bind(&is_true);
__ PushConstant(Bool::True());
__ Bind(&done);
} else {
const Register result = this->locs()->out(0).reg();
bool next_is_true = true_condition == NEXT_IS_TRUE;
__ LoadConstant(result, Bool::Get(!next_is_true));
Condition actual_condition = EmitComparisonCode(compiler, labels);
ASSERT(actual_condition == true_condition);
// Although we have a condition to branch on, the comparison code may also
// have contained a direct branch to one of the labels, so they may need to
// be bound.
if (next_is_true && is_true.IsLinked()) {
__ Bind(&is_true);
} else if (!next_is_true && is_false.IsLinked()) {
__ Bind(&is_false);
}
// This instruction is conditionally skipped by EmitComparisonCode.
__ LoadConstant(result, Bool::Get(next_is_true));
// If the other label is linked we need to bind it and emit code that loads
// the correct boolean.
if ((next_is_true && is_false.IsLinked()) ||
(!next_is_true && is_true.IsLinked())) {
Label done;
__ Jump(&done);
__ Bind(next_is_true ? &is_false : &is_true);
__ LoadConstant(result, Bool::Get(!next_is_true));
__ Bind(&done);
}
}
}
@ -601,6 +634,13 @@ EMIT_NATIVE_CODE(Goto, 0) {
}
Condition TestSmiInstr::GetNextInstructionCondition(FlowGraphCompiler* compiler,
BranchLabels labels) {
ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
return (kind() == Token::kEQ) ? NEXT_IS_TRUE : NEXT_IS_FALSE;
}
Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
BranchLabels labels) {
ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
@ -611,21 +651,10 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
EMIT_NATIVE_CODE(TestSmi,
2,
Location::RequiresRegister(),
LocationSummary::kNoCall) {
// Never emitted outside of the BranchInstr.
UNREACHABLE();
}
DEFINE_MAKE_LOCATION_SUMMARY(TestSmi,
2,
Location::RequiresRegister(),
LocationSummary::kNoCall)
Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
@ -662,30 +691,17 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
Condition TestCidsInstr::GetNextInstructionCondition(
FlowGraphCompiler* compiler,
BranchLabels labels) {
return NEXT_IS_TRUE;
}
EMIT_NATIVE_CODE(TestCids,
1,
Location::RequiresRegister(),
LocationSummary::kNoCall) {
Register result_reg = locs()->out(0).reg();
Label is_true, is_false, done;
BranchLabels labels = {&is_true, &is_false, &is_false};
EmitComparisonCode(compiler, labels);
__ Jump(&is_true);
__ Bind(&is_false);
__ LoadConstant(result_reg, Bool::False());
__ Jump(&done);
__ Bind(&is_true);
__ LoadConstant(result_reg, Bool::True());
__ Bind(&done);
}
DEFINE_MAKE_LOCATION_SUMMARY(TestCids,
1,
Location::RequiresRegister(),
LocationSummary::kNoCall)
EMIT_NATIVE_CODE(CreateArray,
@ -1753,15 +1769,7 @@ EMIT_NATIVE_CODE(BinaryDoubleOp, 2, Location::RequiresRegister()) {
Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
BranchLabels labels) {
UNREACHABLE();
return Condition();
}
void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT(compiler->is_optimizing());
BranchLabels labels = compiler->CreateBranchLabels(branch);
const Register value = locs()->in(0).reg();
switch (op_kind()) {
case MethodRecognizer::kDouble_getIsNaN:
@ -1774,31 +1782,21 @@ void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
UNREACHABLE();
}
const bool is_negated = kind() != Token::kEQ;
EmitBranchOnCondition(compiler, is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE,
labels);
return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE;
}
EMIT_NATIVE_CODE(DoubleTestOp, 1, Location::RequiresRegister()) {
ASSERT(compiler->is_optimizing());
const Register value = locs()->in(0).reg();
const Register result = locs()->out(0).reg();
Condition DoubleTestOpInstr::GetNextInstructionCondition(
FlowGraphCompiler* compiler,
BranchLabels labels) {
const bool is_negated = kind() != Token::kEQ;
__ LoadConstant(result, is_negated ? Bool::True() : Bool::False());
switch (op_kind()) {
case MethodRecognizer::kDouble_getIsNaN:
__ DoubleIsNaN(value);
break;
case MethodRecognizer::kDouble_getIsInfinite:
__ DoubleIsInfinite(value);
break;
default:
UNREACHABLE();
}
__ LoadConstant(result, is_negated ? Bool::False() : Bool::True());
return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE;
}
DEFINE_MAKE_LOCATION_SUMMARY(DoubleTestOp, 1, Location::RequiresRegister())
EMIT_NATIVE_CODE(UnaryDoubleOp, 1, Location::RequiresRegister()) {
const Register value = locs()->in(0).reg();
const Register result = locs()->out(0).reg();
@ -1973,7 +1971,8 @@ static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
// If we aren't falling through to the false label, we can save a Jump
// instruction in the case that the true case is the fall through by
// flipping the sense of the test such that the instruction following the
// test is the Jump to the false label.
// test is the Jump to the false label. In the case where both labels are
// null we don't flip the sense of the test.
condition = NEXT_IS_FALSE;
comparison = FlipCondition(kind);
}
@ -2010,29 +2009,20 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
EMIT_NATIVE_CODE(EqualityCompare, 2, Location::RequiresRegister()) {
ASSERT(compiler->is_optimizing());
ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
Label is_true, is_false;
// These labels are not used. They are arranged so that EmitComparisonCode
// emits a test that executes the following instruction when the test
// succeeds.
BranchLabels labels = {&is_true, &is_false, &is_false};
const Register result = locs()->out(0).reg();
__ LoadConstant(result, Bool::False());
Condition true_condition = EmitComparisonCode(compiler, labels);
ASSERT(true_condition == NEXT_IS_TRUE);
__ LoadConstant(result, Bool::True());
Condition EqualityCompareInstr::GetNextInstructionCondition(
FlowGraphCompiler* compiler,
BranchLabels labels) {
if (operation_cid() == kSmiCid) {
return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE
: NEXT_IS_TRUE;
} else {
ASSERT(operation_cid() == kDoubleCid);
return NEXT_IS_TRUE;
}
}
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
DEFINE_MAKE_LOCATION_SUMMARY(EqualityCompare, 2, Location::RequiresRegister());
Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
@ -2046,24 +2036,20 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
EMIT_NATIVE_CODE(RelationalOp, 2, Location::RequiresRegister()) {
ASSERT(compiler->is_optimizing());
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
const Register result = locs()->out(0).reg();
__ LoadConstant(result, Bool::False());
Condition true_condition = EmitComparisonCode(compiler, labels);
ASSERT(true_condition == NEXT_IS_TRUE);
__ LoadConstant(result, Bool::True());
Condition RelationalOpInstr::GetNextInstructionCondition(
FlowGraphCompiler* compiler,
BranchLabels labels) {
if (operation_cid() == kSmiCid) {
return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE
: NEXT_IS_TRUE;
} else {
ASSERT(operation_cid() == kDoubleCid);
return NEXT_IS_TRUE;
}
}
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
DEFINE_MAKE_LOCATION_SUMMARY(RelationalOp, 2, Location::RequiresRegister())
EMIT_NATIVE_CODE(CheckArrayBound, 2) {

View file

@ -600,13 +600,13 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
if (true_condition != INVALID_CONDITION) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
Register result = locs()->out(0).reg();
Label done;
@ -619,13 +619,13 @@ void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
if (true_condition != INVALID_CONDITION) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
}
@ -658,20 +658,6 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// Never emitted outside of the BranchInstr.
UNREACHABLE();
}
void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
@ -723,30 +709,9 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
} else {
__ jmp(deopt);
}
// Dummy result as the last instruction is a jump, any conditional
// branch using the result will therefore be skipped.
return ZERO;
}
void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
EmitComparisonCode(compiler, labels);
}
void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Register result_reg = locs()->out(0).reg();
Label is_true, is_false, done;
BranchLabels labels = {&is_true, &is_false, &is_false};
EmitComparisonCode(compiler, labels);
__ Bind(&is_false);
__ LoadObject(result_reg, Bool::False());
__ jmp(&done, Assembler::kNearJump);
__ Bind(&is_true);
__ LoadObject(result_reg, Bool::True());
__ Bind(&done);
// Dummy result as this method already did the jump, there's no need
// for the caller to branch on a condition.
return INVALID_CONDITION;
}
@ -800,31 +765,6 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out(0).reg();
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ jmp(&done, Assembler::kNearJump);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
}
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
return MakeCallSummary(zone);
@ -3995,32 +3935,6 @@ Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT(compiler->is_optimizing());
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out(0).reg();
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ jmp(&done);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
}
LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
@ -6717,35 +6631,6 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out(0).reg();
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ jmp(&done, Assembler::kNearJump);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
}
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
// 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)) ||
@ -6770,8 +6655,11 @@ void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ xorl(EDX, EDX);
// Emit comparison code. This must not overwrite the result register.
// IfThenElseInstr::Supports() should prevent EmitComparisonCode from using
// the labels or returning an invalid condition.
BranchLabels labels = {NULL, NULL, NULL};
Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
ASSERT(true_condition != INVALID_CONDITION);
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);

View file

@ -178,8 +178,11 @@ void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ LoadImmediate(result, Smi::RawValue(true_value));
// Emit comparison code. This must not overwrite the result register.
// IfThenElseInstr::Supports() should prevent EmitComparisonCode from using
// the labels or returning an invalid condition.
BranchLabels labels = {NULL, NULL, NULL}; // Emit branch-free code.
Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
ASSERT(true_condition.IsValid());
if (swapped) {
true_condition = NegateCondition(true_condition);
}
@ -781,16 +784,15 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
__ Comment("EqualityCompareInstr");
void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
if (true_condition.IsValid()) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
Register result = locs()->out(0).reg();
Register result = this->locs()->out(0).reg();
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
@ -801,14 +803,13 @@ void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
__ Comment("EqualityCompareInstr::EmitBranchCode");
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
if (true_condition.IsValid()) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
}
@ -840,20 +841,6 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// Never emitted outside of the BranchInstr.
UNREACHABLE();
}
void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
@ -906,29 +893,9 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
} else {
__ b(deopt);
}
// Dummy result as the last instruction is a jump or fall through.
return Condition(CMPRES1, ZR, AL);
}
void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
EmitComparisonCode(compiler, labels);
}
void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Register result_reg = locs()->out(0).reg();
Label is_true, is_false, done;
BranchLabels labels = {&is_true, &is_false, &is_false};
EmitComparisonCode(compiler, labels);
__ Bind(&is_false);
__ LoadObject(result_reg, Bool::False());
__ b(&done);
__ Bind(&is_true);
__ LoadObject(result_reg, Bool::True());
__ Bind(&done);
// Dummy result as this method already did the jump, there's no need
// for the caller to branch on a condition.
return Condition(ZR, ZR, INVALID_RELATION);
}
@ -982,35 +949,6 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ Comment("RelationalOpInstr");
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out(0).reg();
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ b(&done);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
}
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
__ Comment("RelationalOpInstr");
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
return MakeCallSummary(zone);
@ -3247,6 +3185,7 @@ void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
compiler->AddSlowPathCode(slow_path);
EMIT_SMI_CHECK;
Condition true_condition = EmitComparisonCode(compiler, labels);
ASSERT(true_condition.IsValid());
EmitBranchOnCondition(compiler, true_condition, labels);
__ Bind(slow_path->exit_label());
}
@ -3261,6 +3200,7 @@ void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
compiler->AddSlowPathCode(slow_path);
EMIT_SMI_CHECK;
Condition true_condition = EmitComparisonCode(compiler, labels);
ASSERT(true_condition.IsValid());
EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out(0).reg();
__ Bind(&false_label);
@ -3975,7 +3915,7 @@ Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
__ b(labels.true_label);
}
return Condition(); // Unused.
return Condition(ZR, ZR, INVALID_RELATION); // Unused.
} else {
ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite);
__ mfc1(CMPRES1, EvenFRegisterOf(value));
@ -3990,38 +3930,6 @@ Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
}
void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT(compiler->is_optimizing());
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
// Branches for isNaN are emitted in EmitComparisonCode already.
if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
}
void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
// Branches for isNaN are emitted in EmitComparisonCode already.
if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
const Register result = locs()->out(0).reg();
Label done;
__ Comment("return bool");
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ b(&done);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
}
LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
UNIMPLEMENTED();
@ -5986,37 +5894,6 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ Comment("StrictCompareInstr");
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out(0).reg();
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ b(&done);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
}
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
__ Comment("StrictCompareInstr::EmitBranchCode");
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
return LocationSummary::Make(zone, 1, Location::RequiresRegister(),

View file

@ -165,8 +165,11 @@ void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ xorq(RDX, RDX);
// Emit comparison code. This must not overwrite the result register.
// IfThenElseInstr::Supports() should prevent EmitComparisonCode from using
// the labels or returning an invalid condition.
BranchLabels labels = {NULL, NULL, NULL};
Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
ASSERT(true_condition != INVALID_CONDITION);
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
@ -573,13 +576,13 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
if (true_condition != INVALID_CONDITION) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
Register result = locs()->out(0).reg();
Label done;
@ -592,13 +595,13 @@ void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
if (true_condition != INVALID_CONDITION) {
EmitBranchOnCondition(compiler, true_condition, labels);
}
}
@ -631,20 +634,6 @@ Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// Never emitted outside of the BranchInstr.
UNREACHABLE();
}
void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
@ -696,30 +685,9 @@ Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
} else {
__ jmp(deopt);
}
// Dummy result as the last instruction is a jump, any conditional
// branch using the result will therefore be skipped.
return ZERO;
}
void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
EmitComparisonCode(compiler, labels);
}
void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Register result_reg = locs()->out(0).reg();
Label is_true, is_false, done;
BranchLabels labels = {&is_true, &is_false, &is_false};
EmitComparisonCode(compiler, labels);
__ Bind(&is_false);
__ LoadObject(result_reg, Bool::False());
__ jmp(&done, Assembler::kNearJump);
__ Bind(&is_true);
__ LoadObject(result_reg, Bool::True());
__ Bind(&done);
// Dummy result as this method already did the jump, there's no need
// for the caller to branch on a condition.
return INVALID_CONDITION;
}
@ -767,31 +735,6 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out(0).reg();
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ jmp(&done);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
}
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
return MakeCallSummary(zone);
@ -3109,6 +3052,7 @@ void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
compiler->AddSlowPathCode(slow_path);
EMIT_SMI_CHECK;
Condition true_condition = EmitComparisonCode(compiler, labels);
ASSERT(true_condition != INVALID_CONDITION);
EmitBranchOnCondition(compiler, true_condition, labels);
__ Bind(slow_path->exit_label());
}
@ -3123,6 +3067,7 @@ void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
compiler->AddSlowPathCode(slow_path);
EMIT_SMI_CHECK;
Condition true_condition = EmitComparisonCode(compiler, labels);
ASSERT(true_condition != INVALID_CONDITION);
EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out(0).reg();
__ Bind(&false_label);
@ -3951,32 +3896,6 @@ Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void DoubleTestOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT(compiler->is_optimizing());
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out(0).reg();
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ jmp(&done);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
}
LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
@ -6638,36 +6557,6 @@ Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
}
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
Label is_true, is_false;
BranchLabels labels = {&is_true, &is_false, &is_false};
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out(0).reg();
Label done;
__ Bind(&is_false);
__ LoadObject(result, Bool::False());
__ jmp(&done);
__ Bind(&is_true);
__ LoadObject(result, Bool::True());
__ Bind(&done);
}
void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
BranchLabels labels = compiler->CreateBranchLabels(branch);
Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;