X87: [turbofan] Introduce DeoptimizeIf And DeoptimizeUnless common operators.
port c129aa4d39
(r34239)
original commit message:
These macro operators represent a conditional eager deoptimization exit
without explicit branching, which greatly reduces overhead of both
scheduling and register allocation, and thereby greatly reduces overall
compilation time, esp. when there are a lot of eager deoptimization
exits.
BUG=
Review URL: https://codereview.chromium.org/1762483003
Cr-Commit-Position: refs/heads/master@{#34453}
This commit is contained in:
parent
4db99810da
commit
e8df3439c8
@ -1610,8 +1610,16 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
||||
X87OperandConverter i(this, instr);
|
||||
Label::Distance flabel_distance =
|
||||
branch->fallthru ? Label::kNear : Label::kFar;
|
||||
Label* tlabel = branch->true_label;
|
||||
Label* flabel = branch->false_label;
|
||||
|
||||
Label done;
|
||||
Label tlabel_tmp;
|
||||
Label flabel_tmp;
|
||||
Label* tlabel = &tlabel_tmp;
|
||||
Label* flabel = &flabel_tmp;
|
||||
|
||||
Label* tlabel_dst = branch->true_label;
|
||||
Label* flabel_dst = branch->false_label;
|
||||
|
||||
switch (branch->condition) {
|
||||
case kUnorderedEqual:
|
||||
__ j(parity_even, flabel, flabel_distance);
|
||||
@ -1661,6 +1669,34 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
||||
}
|
||||
// Add a jump if not falling through to the next block.
|
||||
if (!branch->fallthru) __ jmp(flabel);
|
||||
|
||||
__ jmp(&done);
|
||||
__ bind(&tlabel_tmp);
|
||||
FlagsMode mode = FlagsModeField::decode(instr->opcode());
|
||||
if (mode == kFlags_deoptimize) {
|
||||
int double_register_param_count = 0;
|
||||
int x87_layout = 0;
|
||||
for (size_t i = 0; i < instr->InputCount(); i++) {
|
||||
if (instr->InputAt(i)->IsDoubleRegister()) {
|
||||
double_register_param_count++;
|
||||
}
|
||||
}
|
||||
// Currently we use only one X87 register. If double_register_param_count
|
||||
// is bigger than 1, it means duplicated double register is added to input
|
||||
// of this instruction.
|
||||
if (double_register_param_count > 0) {
|
||||
x87_layout = (0 << 3) | 1;
|
||||
}
|
||||
// The layout of x87 register stack is loaded on the top of FPU register
|
||||
// stack for deoptimization.
|
||||
__ push(Immediate(x87_layout));
|
||||
__ fild_s(MemOperand(esp, 0));
|
||||
__ lea(esp, Operand(esp, kPointerSize));
|
||||
}
|
||||
__ jmp(tlabel_dst);
|
||||
__ bind(&flabel_tmp);
|
||||
__ jmp(flabel_dst);
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
|
||||
|
@ -365,10 +365,11 @@ void InstructionSelector::VisitCheckedStore(Node* node) {
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Shared routine for multiple binary operations.
|
||||
static void VisitBinop(InstructionSelector* selector, Node* node,
|
||||
InstructionCode opcode, FlagsContinuation* cont) {
|
||||
void VisitBinop(InstructionSelector* selector, Node* node,
|
||||
InstructionCode opcode, FlagsContinuation* cont) {
|
||||
X87OperandGenerator g(selector);
|
||||
Int32BinopMatcher m(node);
|
||||
Node* left = m.left().node();
|
||||
@ -417,18 +418,24 @@ static void VisitBinop(InstructionSelector* selector, Node* node,
|
||||
DCHECK_GE(arraysize(inputs), input_count);
|
||||
DCHECK_GE(arraysize(outputs), output_count);
|
||||
|
||||
selector->Emit(cont->Encode(opcode), output_count, outputs, input_count,
|
||||
inputs);
|
||||
opcode = cont->Encode(opcode);
|
||||
if (cont->IsDeoptimize()) {
|
||||
selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
|
||||
cont->frame_state());
|
||||
} else {
|
||||
selector->Emit(opcode, output_count, outputs, input_count, inputs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Shared routine for multiple binary operations.
|
||||
static void VisitBinop(InstructionSelector* selector, Node* node,
|
||||
InstructionCode opcode) {
|
||||
void VisitBinop(InstructionSelector* selector, Node* node,
|
||||
InstructionCode opcode) {
|
||||
FlagsContinuation cont;
|
||||
VisitBinop(selector, node, opcode, &cont);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void InstructionSelector::VisitWord32And(Node* node) {
|
||||
VisitBinop(this, node, kX87And);
|
||||
@ -1011,6 +1018,9 @@ void VisitCompareWithMemoryOperand(InstructionSelector* selector,
|
||||
inputs[input_count++] = g.Label(cont->true_block());
|
||||
inputs[input_count++] = g.Label(cont->false_block());
|
||||
selector->Emit(opcode, 0, nullptr, input_count, inputs);
|
||||
} else if (cont->IsDeoptimize()) {
|
||||
selector->EmitDeoptimize(opcode, 0, nullptr, input_count, inputs,
|
||||
cont->frame_state());
|
||||
} else {
|
||||
DCHECK(cont->IsSet());
|
||||
InstructionOperand output = g.DefineAsRegister(cont->result());
|
||||
@ -1038,13 +1048,16 @@ void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
|
||||
InstructionOperand left, InstructionOperand right,
|
||||
FlagsContinuation* cont) {
|
||||
X87OperandGenerator g(selector);
|
||||
opcode = cont->Encode(opcode);
|
||||
if (cont->IsBranch()) {
|
||||
selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right,
|
||||
selector->Emit(opcode, g.NoOutput(), left, right,
|
||||
g.Label(cont->true_block()), g.Label(cont->false_block()));
|
||||
} else if (cont->IsDeoptimize()) {
|
||||
selector->EmitDeoptimize(opcode, g.NoOutput(), left, right,
|
||||
cont->frame_state());
|
||||
} else {
|
||||
DCHECK(cont->IsSet());
|
||||
selector->Emit(cont->Encode(opcode), g.DefineAsByteRegister(cont->result()),
|
||||
left, right);
|
||||
selector->Emit(opcode, g.DefineAsByteRegister(cont->result()), left, right);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1070,6 +1083,10 @@ void VisitFloat32Compare(InstructionSelector* selector, Node* node,
|
||||
if (cont->IsBranch()) {
|
||||
selector->Emit(cont->Encode(kX87Float32Cmp), g.NoOutput(),
|
||||
g.Label(cont->true_block()), g.Label(cont->false_block()));
|
||||
} else if (cont->IsDeoptimize()) {
|
||||
selector->EmitDeoptimize(cont->Encode(kX87Float32Cmp), g.NoOutput(),
|
||||
g.Use(node->InputAt(0)), g.Use(node->InputAt(1)),
|
||||
cont->frame_state());
|
||||
} else {
|
||||
DCHECK(cont->IsSet());
|
||||
selector->Emit(cont->Encode(kX87Float32Cmp),
|
||||
@ -1087,6 +1104,10 @@ void VisitFloat64Compare(InstructionSelector* selector, Node* node,
|
||||
if (cont->IsBranch()) {
|
||||
selector->Emit(cont->Encode(kX87Float64Cmp), g.NoOutput(),
|
||||
g.Label(cont->true_block()), g.Label(cont->false_block()));
|
||||
} else if (cont->IsDeoptimize()) {
|
||||
selector->EmitDeoptimize(cont->Encode(kX87Float64Cmp), g.NoOutput(),
|
||||
g.Use(node->InputAt(0)), g.Use(node->InputAt(1)),
|
||||
cont->frame_state());
|
||||
} else {
|
||||
DCHECK(cont->IsSet());
|
||||
selector->Emit(cont->Encode(kX87Float64Cmp),
|
||||
@ -1145,6 +1166,9 @@ void VisitWordCompare(InstructionSelector* selector, Node* node,
|
||||
if (cont->IsBranch()) {
|
||||
selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()),
|
||||
g.Label(cont->false_block()));
|
||||
} else if (cont->IsDeoptimize()) {
|
||||
selector->EmitDeoptimize(opcode, 0, nullptr, 0, nullptr,
|
||||
cont->frame_state());
|
||||
} else {
|
||||
DCHECK(cont->IsSet());
|
||||
selector->Emit(opcode, g.DefineAsRegister(cont->result()));
|
||||
@ -1254,6 +1278,17 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
|
||||
VisitWordCompareZero(this, branch, branch->InputAt(0), &cont);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitDeoptimizeIf(Node* node) {
|
||||
FlagsContinuation cont =
|
||||
FlagsContinuation::ForDeoptimize(kNotEqual, node->InputAt(1));
|
||||
VisitWordCompareZero(this, node, node->InputAt(0), &cont);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitDeoptimizeUnless(Node* node) {
|
||||
FlagsContinuation cont =
|
||||
FlagsContinuation::ForDeoptimize(kEqual, node->InputAt(1));
|
||||
VisitWordCompareZero(this, node, node->InputAt(0), &cont);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
|
||||
X87OperandGenerator g(this);
|
||||
@ -1284,7 +1319,7 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
|
||||
|
||||
|
||||
void InstructionSelector::VisitWord32Equal(Node* const node) {
|
||||
FlagsContinuation cont(kEqual, node);
|
||||
FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
|
||||
Int32BinopMatcher m(node);
|
||||
if (m.right().Is(0)) {
|
||||
return VisitWordCompareZero(this, m.node(), m.left().node(), &cont);
|
||||
@ -1294,32 +1329,34 @@ void InstructionSelector::VisitWord32Equal(Node* const node) {
|
||||
|
||||
|
||||
void InstructionSelector::VisitInt32LessThan(Node* node) {
|
||||
FlagsContinuation cont(kSignedLessThan, node);
|
||||
FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node);
|
||||
VisitWordCompare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) {
|
||||
FlagsContinuation cont(kSignedLessThanOrEqual, node);
|
||||
FlagsContinuation cont =
|
||||
FlagsContinuation::ForSet(kSignedLessThanOrEqual, node);
|
||||
VisitWordCompare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitUint32LessThan(Node* node) {
|
||||
FlagsContinuation cont(kUnsignedLessThan, node);
|
||||
FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node);
|
||||
VisitWordCompare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
|
||||
FlagsContinuation cont(kUnsignedLessThanOrEqual, node);
|
||||
FlagsContinuation cont =
|
||||
FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node);
|
||||
VisitWordCompare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
|
||||
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
||||
FlagsContinuation cont(kOverflow, ovf);
|
||||
FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
|
||||
return VisitBinop(this, node, kX87Add, &cont);
|
||||
}
|
||||
FlagsContinuation cont;
|
||||
@ -1329,7 +1366,7 @@ void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
|
||||
|
||||
void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
|
||||
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
|
||||
FlagsContinuation cont(kOverflow, ovf);
|
||||
FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
|
||||
return VisitBinop(this, node, kX87Sub, &cont);
|
||||
}
|
||||
FlagsContinuation cont;
|
||||
@ -1338,37 +1375,41 @@ void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat32Equal(Node* node) {
|
||||
FlagsContinuation cont(kUnorderedEqual, node);
|
||||
FlagsContinuation cont = FlagsContinuation::ForSet(kUnorderedEqual, node);
|
||||
VisitFloat32Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat32LessThan(Node* node) {
|
||||
FlagsContinuation cont(kUnsignedGreaterThan, node);
|
||||
FlagsContinuation cont =
|
||||
FlagsContinuation::ForSet(kUnsignedGreaterThan, node);
|
||||
VisitFloat32Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) {
|
||||
FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node);
|
||||
FlagsContinuation cont =
|
||||
FlagsContinuation::ForSet(kUnsignedGreaterThanOrEqual, node);
|
||||
VisitFloat32Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64Equal(Node* node) {
|
||||
FlagsContinuation cont(kUnorderedEqual, node);
|
||||
FlagsContinuation cont = FlagsContinuation::ForSet(kUnorderedEqual, node);
|
||||
VisitFloat64Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64LessThan(Node* node) {
|
||||
FlagsContinuation cont(kUnsignedGreaterThan, node);
|
||||
FlagsContinuation cont =
|
||||
FlagsContinuation::ForSet(kUnsignedGreaterThan, node);
|
||||
VisitFloat64Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
|
||||
FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node);
|
||||
FlagsContinuation cont =
|
||||
FlagsContinuation::ForSet(kUnsignedGreaterThanOrEqual, node);
|
||||
VisitFloat64Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user