Commit e8df3439 authored by zhengxing.li's avatar zhengxing.li Committed by Commit bot

X87: [turbofan] Introduce DeoptimizeIf And DeoptimizeUnless common operators.

  port c129aa4d (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}
parent 4db99810
...@@ -1610,8 +1610,16 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { ...@@ -1610,8 +1610,16 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
X87OperandConverter i(this, instr); X87OperandConverter i(this, instr);
Label::Distance flabel_distance = Label::Distance flabel_distance =
branch->fallthru ? Label::kNear : Label::kFar; 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) { switch (branch->condition) {
case kUnorderedEqual: case kUnorderedEqual:
__ j(parity_even, flabel, flabel_distance); __ j(parity_even, flabel, flabel_distance);
...@@ -1661,6 +1669,34 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { ...@@ -1661,6 +1669,34 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
} }
// Add a jump if not falling through to the next block. // Add a jump if not falling through to the next block.
if (!branch->fallthru) __ jmp(flabel); 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) { ...@@ -365,10 +365,11 @@ void InstructionSelector::VisitCheckedStore(Node* node) {
} }
} }
namespace {
// Shared routine for multiple binary operations. // Shared routine for multiple binary operations.
static void VisitBinop(InstructionSelector* selector, Node* node, void VisitBinop(InstructionSelector* selector, Node* node,
InstructionCode opcode, FlagsContinuation* cont) { InstructionCode opcode, FlagsContinuation* cont) {
X87OperandGenerator g(selector); X87OperandGenerator g(selector);
Int32BinopMatcher m(node); Int32BinopMatcher m(node);
Node* left = m.left().node(); Node* left = m.left().node();
...@@ -417,18 +418,24 @@ static void VisitBinop(InstructionSelector* selector, Node* node, ...@@ -417,18 +418,24 @@ static void VisitBinop(InstructionSelector* selector, Node* node,
DCHECK_GE(arraysize(inputs), input_count); DCHECK_GE(arraysize(inputs), input_count);
DCHECK_GE(arraysize(outputs), output_count); DCHECK_GE(arraysize(outputs), output_count);
selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, opcode = cont->Encode(opcode);
inputs); 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. // Shared routine for multiple binary operations.
static void VisitBinop(InstructionSelector* selector, Node* node, void VisitBinop(InstructionSelector* selector, Node* node,
InstructionCode opcode) { InstructionCode opcode) {
FlagsContinuation cont; FlagsContinuation cont;
VisitBinop(selector, node, opcode, &cont); VisitBinop(selector, node, opcode, &cont);
} }
} // namespace
void InstructionSelector::VisitWord32And(Node* node) { void InstructionSelector::VisitWord32And(Node* node) {
VisitBinop(this, node, kX87And); VisitBinop(this, node, kX87And);
...@@ -1011,6 +1018,9 @@ void VisitCompareWithMemoryOperand(InstructionSelector* selector, ...@@ -1011,6 +1018,9 @@ void VisitCompareWithMemoryOperand(InstructionSelector* selector,
inputs[input_count++] = g.Label(cont->true_block()); inputs[input_count++] = g.Label(cont->true_block());
inputs[input_count++] = g.Label(cont->false_block()); inputs[input_count++] = g.Label(cont->false_block());
selector->Emit(opcode, 0, nullptr, input_count, inputs); selector->Emit(opcode, 0, nullptr, input_count, inputs);
} else if (cont->IsDeoptimize()) {
selector->EmitDeoptimize(opcode, 0, nullptr, input_count, inputs,
cont->frame_state());
} else { } else {
DCHECK(cont->IsSet()); DCHECK(cont->IsSet());
InstructionOperand output = g.DefineAsRegister(cont->result()); InstructionOperand output = g.DefineAsRegister(cont->result());
...@@ -1038,13 +1048,16 @@ void VisitCompare(InstructionSelector* selector, InstructionCode opcode, ...@@ -1038,13 +1048,16 @@ void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
InstructionOperand left, InstructionOperand right, InstructionOperand left, InstructionOperand right,
FlagsContinuation* cont) { FlagsContinuation* cont) {
X87OperandGenerator g(selector); X87OperandGenerator g(selector);
opcode = cont->Encode(opcode);
if (cont->IsBranch()) { 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())); 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 { } else {
DCHECK(cont->IsSet()); DCHECK(cont->IsSet());
selector->Emit(cont->Encode(opcode), g.DefineAsByteRegister(cont->result()), selector->Emit(opcode, g.DefineAsByteRegister(cont->result()), left, right);
left, right);
} }
} }
...@@ -1070,6 +1083,10 @@ void VisitFloat32Compare(InstructionSelector* selector, Node* node, ...@@ -1070,6 +1083,10 @@ void VisitFloat32Compare(InstructionSelector* selector, Node* node,
if (cont->IsBranch()) { if (cont->IsBranch()) {
selector->Emit(cont->Encode(kX87Float32Cmp), g.NoOutput(), selector->Emit(cont->Encode(kX87Float32Cmp), g.NoOutput(),
g.Label(cont->true_block()), g.Label(cont->false_block())); 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 { } else {
DCHECK(cont->IsSet()); DCHECK(cont->IsSet());
selector->Emit(cont->Encode(kX87Float32Cmp), selector->Emit(cont->Encode(kX87Float32Cmp),
...@@ -1087,6 +1104,10 @@ void VisitFloat64Compare(InstructionSelector* selector, Node* node, ...@@ -1087,6 +1104,10 @@ void VisitFloat64Compare(InstructionSelector* selector, Node* node,
if (cont->IsBranch()) { if (cont->IsBranch()) {
selector->Emit(cont->Encode(kX87Float64Cmp), g.NoOutput(), selector->Emit(cont->Encode(kX87Float64Cmp), g.NoOutput(),
g.Label(cont->true_block()), g.Label(cont->false_block())); 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 { } else {
DCHECK(cont->IsSet()); DCHECK(cont->IsSet());
selector->Emit(cont->Encode(kX87Float64Cmp), selector->Emit(cont->Encode(kX87Float64Cmp),
...@@ -1145,6 +1166,9 @@ void VisitWordCompare(InstructionSelector* selector, Node* node, ...@@ -1145,6 +1166,9 @@ void VisitWordCompare(InstructionSelector* selector, Node* node,
if (cont->IsBranch()) { if (cont->IsBranch()) {
selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()), selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()),
g.Label(cont->false_block())); g.Label(cont->false_block()));
} else if (cont->IsDeoptimize()) {
selector->EmitDeoptimize(opcode, 0, nullptr, 0, nullptr,
cont->frame_state());
} else { } else {
DCHECK(cont->IsSet()); DCHECK(cont->IsSet());
selector->Emit(opcode, g.DefineAsRegister(cont->result())); selector->Emit(opcode, g.DefineAsRegister(cont->result()));
...@@ -1254,6 +1278,17 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, ...@@ -1254,6 +1278,17 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
VisitWordCompareZero(this, branch, branch->InputAt(0), &cont); 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) { void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
X87OperandGenerator g(this); X87OperandGenerator g(this);
...@@ -1284,7 +1319,7 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { ...@@ -1284,7 +1319,7 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
void InstructionSelector::VisitWord32Equal(Node* const node) { void InstructionSelector::VisitWord32Equal(Node* const node) {
FlagsContinuation cont(kEqual, node); FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
Int32BinopMatcher m(node); Int32BinopMatcher m(node);
if (m.right().Is(0)) { if (m.right().Is(0)) {
return VisitWordCompareZero(this, m.node(), m.left().node(), &cont); return VisitWordCompareZero(this, m.node(), m.left().node(), &cont);
...@@ -1294,32 +1329,34 @@ void InstructionSelector::VisitWord32Equal(Node* const node) { ...@@ -1294,32 +1329,34 @@ void InstructionSelector::VisitWord32Equal(Node* const node) {
void InstructionSelector::VisitInt32LessThan(Node* node) { void InstructionSelector::VisitInt32LessThan(Node* node) {
FlagsContinuation cont(kSignedLessThan, node); FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node);
VisitWordCompare(this, node, &cont); VisitWordCompare(this, node, &cont);
} }
void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) { void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) {
FlagsContinuation cont(kSignedLessThanOrEqual, node); FlagsContinuation cont =
FlagsContinuation::ForSet(kSignedLessThanOrEqual, node);
VisitWordCompare(this, node, &cont); VisitWordCompare(this, node, &cont);
} }
void InstructionSelector::VisitUint32LessThan(Node* node) { void InstructionSelector::VisitUint32LessThan(Node* node) {
FlagsContinuation cont(kUnsignedLessThan, node); FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node);
VisitWordCompare(this, node, &cont); VisitWordCompare(this, node, &cont);
} }
void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) { void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
FlagsContinuation cont(kUnsignedLessThanOrEqual, node); FlagsContinuation cont =
FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node);
VisitWordCompare(this, node, &cont); VisitWordCompare(this, node, &cont);
} }
void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
if (Node* ovf = NodeProperties::FindProjection(node, 1)) { if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
FlagsContinuation cont(kOverflow, ovf); FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
return VisitBinop(this, node, kX87Add, &cont); return VisitBinop(this, node, kX87Add, &cont);
} }
FlagsContinuation cont; FlagsContinuation cont;
...@@ -1329,7 +1366,7 @@ void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { ...@@ -1329,7 +1366,7 @@ void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
if (Node* ovf = NodeProperties::FindProjection(node, 1)) { if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
FlagsContinuation cont(kOverflow, ovf); FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
return VisitBinop(this, node, kX87Sub, &cont); return VisitBinop(this, node, kX87Sub, &cont);
} }
FlagsContinuation cont; FlagsContinuation cont;
...@@ -1338,37 +1375,41 @@ void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { ...@@ -1338,37 +1375,41 @@ void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
void InstructionSelector::VisitFloat32Equal(Node* node) { void InstructionSelector::VisitFloat32Equal(Node* node) {
FlagsContinuation cont(kUnorderedEqual, node); FlagsContinuation cont = FlagsContinuation::ForSet(kUnorderedEqual, node);
VisitFloat32Compare(this, node, &cont); VisitFloat32Compare(this, node, &cont);
} }
void InstructionSelector::VisitFloat32LessThan(Node* node) { void InstructionSelector::VisitFloat32LessThan(Node* node) {
FlagsContinuation cont(kUnsignedGreaterThan, node); FlagsContinuation cont =
FlagsContinuation::ForSet(kUnsignedGreaterThan, node);
VisitFloat32Compare(this, node, &cont); VisitFloat32Compare(this, node, &cont);
} }
void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) { void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) {
FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node); FlagsContinuation cont =
FlagsContinuation::ForSet(kUnsignedGreaterThanOrEqual, node);
VisitFloat32Compare(this, node, &cont); VisitFloat32Compare(this, node, &cont);
} }
void InstructionSelector::VisitFloat64Equal(Node* node) { void InstructionSelector::VisitFloat64Equal(Node* node) {
FlagsContinuation cont(kUnorderedEqual, node); FlagsContinuation cont = FlagsContinuation::ForSet(kUnorderedEqual, node);
VisitFloat64Compare(this, node, &cont); VisitFloat64Compare(this, node, &cont);
} }
void InstructionSelector::VisitFloat64LessThan(Node* node) { void InstructionSelector::VisitFloat64LessThan(Node* node) {
FlagsContinuation cont(kUnsignedGreaterThan, node); FlagsContinuation cont =
FlagsContinuation::ForSet(kUnsignedGreaterThan, node);
VisitFloat64Compare(this, node, &cont); VisitFloat64Compare(this, node, &cont);
} }
void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node); FlagsContinuation cont =
FlagsContinuation::ForSet(kUnsignedGreaterThanOrEqual, node);
VisitFloat64Compare(this, node, &cont); VisitFloat64Compare(this, node, &cont);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment