Commit f4c88a5e authored by jarin's avatar jarin Committed by Commit bot

[turbofan] Support virtual register redirection in instruction selector.

Review-Url: https://codereview.chromium.org/2349983002
Cr-Commit-Position: refs/heads/master@{#39492}
parent 20693493
...@@ -38,13 +38,13 @@ InstructionSelector::InstructionSelector( ...@@ -38,13 +38,13 @@ InstructionSelector::InstructionSelector(
effect_level_(node_count, 0, zone), effect_level_(node_count, 0, zone),
virtual_registers_(node_count, virtual_registers_(node_count,
InstructionOperand::kInvalidVirtualRegister, zone), InstructionOperand::kInvalidVirtualRegister, zone),
virtual_register_rename_(zone),
scheduler_(nullptr), scheduler_(nullptr),
enable_scheduling_(enable_scheduling), enable_scheduling_(enable_scheduling),
frame_(frame) { frame_(frame) {
instructions_.reserve(node_count); instructions_.reserve(node_count);
} }
void InstructionSelector::SelectInstructions() { void InstructionSelector::SelectInstructions() {
// Mark the inputs of all phis in loop headers as used. // Mark the inputs of all phis in loop headers as used.
BasicBlockVector* blocks = schedule()->rpo_order(); BasicBlockVector* blocks = schedule()->rpo_order();
...@@ -74,11 +74,15 @@ void InstructionSelector::SelectInstructions() { ...@@ -74,11 +74,15 @@ void InstructionSelector::SelectInstructions() {
for (auto const block : *blocks) { for (auto const block : *blocks) {
InstructionBlock* instruction_block = InstructionBlock* instruction_block =
sequence()->InstructionBlockAt(RpoNumber::FromInt(block->rpo_number())); sequence()->InstructionBlockAt(RpoNumber::FromInt(block->rpo_number()));
for (size_t i = 0; i < instruction_block->phis().size(); i++) {
UpdateRenamesInPhi(instruction_block->PhiAt(i));
}
size_t end = instruction_block->code_end(); size_t end = instruction_block->code_end();
size_t start = instruction_block->code_start(); size_t start = instruction_block->code_start();
DCHECK_LE(end, start); DCHECK_LE(end, start);
StartBlock(RpoNumber::FromInt(block->rpo_number())); StartBlock(RpoNumber::FromInt(block->rpo_number()));
while (start-- > end) { while (start-- > end) {
UpdateRenames(instructions_[start]);
AddInstruction(instructions_[start]); AddInstruction(instructions_[start]);
} }
EndBlock(RpoNumber::FromInt(block->rpo_number())); EndBlock(RpoNumber::FromInt(block->rpo_number()));
...@@ -253,6 +257,53 @@ bool InstructionSelector::IsOnlyUserOfNodeInSameBlock(Node* user, ...@@ -253,6 +257,53 @@ bool InstructionSelector::IsOnlyUserOfNodeInSameBlock(Node* user,
return true; return true;
} }
void InstructionSelector::UpdateRenames(Instruction* instruction) {
for (size_t i = 0; i < instruction->InputCount(); i++) {
TryRename(instruction->InputAt(i));
}
}
void InstructionSelector::UpdateRenamesInPhi(PhiInstruction* phi) {
for (size_t i = 0; i < phi->operands().size(); i++) {
int vreg = phi->operands()[i];
int renamed = GetRename(vreg);
if (vreg != renamed) {
phi->RenameInput(i, renamed);
}
}
}
int InstructionSelector::GetRename(int virtual_register) {
int rename = virtual_register;
while (true) {
if (static_cast<size_t>(rename) >= virtual_register_rename_.size()) break;
int next = virtual_register_rename_[rename];
if (next == InstructionOperand::kInvalidVirtualRegister) {
break;
}
rename = next;
}
return rename;
}
void InstructionSelector::TryRename(InstructionOperand* op) {
if (!op->IsUnallocated()) return;
int vreg = UnallocatedOperand::cast(op)->virtual_register();
int rename = GetRename(vreg);
if (rename != vreg) {
UnallocatedOperand::cast(op)->set_virtual_register(rename);
}
}
void InstructionSelector::SetRename(const Node* node, const Node* rename) {
int vreg = GetVirtualRegister(node);
if (static_cast<size_t>(vreg) >= virtual_register_rename_.size()) {
int invalid = InstructionOperand::kInvalidVirtualRegister;
virtual_register_rename_.resize(vreg + 1, invalid);
}
virtual_register_rename_[vreg] = GetVirtualRegister(rename);
}
int InstructionSelector::GetVirtualRegister(const Node* node) { int InstructionSelector::GetVirtualRegister(const Node* node) {
DCHECK_NOT_NULL(node); DCHECK_NOT_NULL(node);
size_t const id = node->id(); size_t const id = node->id();
...@@ -1451,7 +1502,8 @@ void InstructionSelector::VisitStackSlot(Node* node) { ...@@ -1451,7 +1502,8 @@ void InstructionSelector::VisitStackSlot(Node* node) {
} }
void InstructionSelector::VisitBitcastWordToTagged(Node* node) { void InstructionSelector::VisitBitcastWordToTagged(Node* node) {
EmitIdentity(node); OperandGenerator g(this);
Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(node->InputAt(0)));
} }
// 32 bit targets do not implement the following instructions. // 32 bit targets do not implement the following instructions.
...@@ -1948,8 +2000,8 @@ Instruction* InstructionSelector::EmitDeoptimize( ...@@ -1948,8 +2000,8 @@ Instruction* InstructionSelector::EmitDeoptimize(
void InstructionSelector::EmitIdentity(Node* node) { void InstructionSelector::EmitIdentity(Node* node) {
OperandGenerator g(this); OperandGenerator g(this);
Node* value = node->InputAt(0); MarkAsUsed(node->InputAt(0));
Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value)); SetRename(node, node->InputAt(0));
} }
void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind, void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind,
......
...@@ -212,6 +212,12 @@ class InstructionSelector final { ...@@ -212,6 +212,12 @@ class InstructionSelector final {
void EmitLookupSwitch(const SwitchInfo& sw, void EmitLookupSwitch(const SwitchInfo& sw,
InstructionOperand& value_operand); InstructionOperand& value_operand);
void TryRename(InstructionOperand* op);
int GetRename(int virtual_register);
void SetRename(const Node* node, const Node* rename);
void UpdateRenames(Instruction* instruction);
void UpdateRenamesInPhi(PhiInstruction* phi);
// Inform the instruction selection that {node} was just defined. // Inform the instruction selection that {node} was just defined.
void MarkAsDefined(Node* node); void MarkAsDefined(Node* node);
...@@ -341,6 +347,7 @@ class InstructionSelector final { ...@@ -341,6 +347,7 @@ class InstructionSelector final {
BoolVector used_; BoolVector used_;
IntVector effect_level_; IntVector effect_level_;
IntVector virtual_registers_; IntVector virtual_registers_;
IntVector virtual_register_rename_;
InstructionScheduler* scheduler_; InstructionScheduler* scheduler_;
EnableScheduling enable_scheduling_; EnableScheduling enable_scheduling_;
Frame* frame_; Frame* frame_;
......
...@@ -568,6 +568,10 @@ void PhiInstruction::SetInput(size_t offset, int virtual_register) { ...@@ -568,6 +568,10 @@ void PhiInstruction::SetInput(size_t offset, int virtual_register) {
operands_[offset] = virtual_register; operands_[offset] = virtual_register;
} }
void PhiInstruction::RenameInput(size_t offset, int virtual_register) {
DCHECK_NE(InstructionOperand::kInvalidVirtualRegister, operands_[offset]);
operands_[offset] = virtual_register;
}
InstructionBlock::InstructionBlock(Zone* zone, RpoNumber rpo_number, InstructionBlock::InstructionBlock(Zone* zone, RpoNumber rpo_number,
RpoNumber loop_header, RpoNumber loop_end, RpoNumber loop_header, RpoNumber loop_end,
......
...@@ -1184,6 +1184,7 @@ class PhiInstruction final : public ZoneObject { ...@@ -1184,6 +1184,7 @@ class PhiInstruction final : public ZoneObject {
PhiInstruction(Zone* zone, int virtual_register, size_t input_count); PhiInstruction(Zone* zone, int virtual_register, size_t input_count);
void SetInput(size_t offset, int virtual_register); void SetInput(size_t offset, int virtual_register);
void RenameInput(size_t offset, int virtual_register);
int virtual_register() const { return virtual_register_; } int virtual_register() const { return virtual_register_; }
const IntVector& operands() const { return operands_; } const IntVector& operands() const { return operands_; }
...@@ -1251,6 +1252,7 @@ class InstructionBlock final : public ZoneObject { ...@@ -1251,6 +1252,7 @@ class InstructionBlock final : public ZoneObject {
typedef ZoneVector<PhiInstruction*> PhiInstructions; typedef ZoneVector<PhiInstruction*> PhiInstructions;
const PhiInstructions& phis() const { return phis_; } const PhiInstructions& phis() const { return phis_; }
PhiInstruction* PhiAt(size_t i) const { return phis_[i]; }
void AddPhi(PhiInstruction* phi) { phis_.push_back(phi); } void AddPhi(PhiInstruction* phi) { phis_.push_back(phi); }
void set_ao_number(RpoNumber ao_number) { ao_number_ = ao_number; } void set_ao_number(RpoNumber ao_number) { ao_number_ = ao_number; }
......
...@@ -1245,8 +1245,7 @@ void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { ...@@ -1245,8 +1245,7 @@ void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
if (ZeroExtendsWord32ToWord64(value)) { if (ZeroExtendsWord32ToWord64(value)) {
// These 32-bit operations implicitly zero-extend to 64-bit on x64, so the // These 32-bit operations implicitly zero-extend to 64-bit on x64, so the
// zero-extension is a no-op. // zero-extension is a no-op.
Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value)); return EmitIdentity(node);
return;
} }
Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value)); Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value));
} }
...@@ -1320,8 +1319,7 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) { ...@@ -1320,8 +1319,7 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
Int64BinopMatcher m(value); Int64BinopMatcher m(value);
if (m.right().Is(32)) { if (m.right().Is(32)) {
if (TryMatchLoadWord64AndShiftRight(this, value, kX64Movl)) { if (TryMatchLoadWord64AndShiftRight(this, value, kX64Movl)) {
Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value)); return EmitIdentity(node);
return;
} }
Emit(kX64Shr, g.DefineSameAsFirst(node), Emit(kX64Shr, g.DefineSameAsFirst(node),
g.UseRegister(m.left().node()), g.TempImmediate(32)); g.UseRegister(m.left().node()), g.TempImmediate(32));
......
...@@ -245,19 +245,13 @@ TARGET_TEST_F(InstructionSelectorTest, FinishRegion) { ...@@ -245,19 +245,13 @@ TARGET_TEST_F(InstructionSelectorTest, FinishRegion) {
m.AddNode(m.common()->FinishRegion(), param, m.graph()->start()); m.AddNode(m.common()->FinishRegion(), param, m.graph()->start());
m.Return(finish); m.Return(finish);
Stream s = m.Build(kAllInstructions); Stream s = m.Build(kAllInstructions);
ASSERT_EQ(4U, s.size()); ASSERT_EQ(3U, s.size());
EXPECT_EQ(kArchNop, s[0]->arch_opcode()); EXPECT_EQ(kArchNop, s[0]->arch_opcode());
ASSERT_EQ(1U, s[0]->OutputCount()); ASSERT_EQ(1U, s[0]->OutputCount());
ASSERT_TRUE(s[0]->Output()->IsUnallocated()); ASSERT_TRUE(s[0]->Output()->IsUnallocated());
EXPECT_EQ(kArchRet, s[1]->arch_opcode());
EXPECT_EQ(s.ToVreg(param), s.ToVreg(s[0]->Output())); EXPECT_EQ(s.ToVreg(param), s.ToVreg(s[0]->Output()));
EXPECT_EQ(kArchNop, s[1]->arch_opcode());
ASSERT_EQ(1U, s[1]->InputCount());
ASSERT_TRUE(s[1]->InputAt(0)->IsUnallocated());
EXPECT_EQ(s.ToVreg(param), s.ToVreg(s[1]->InputAt(0))); EXPECT_EQ(s.ToVreg(param), s.ToVreg(s[1]->InputAt(0)));
ASSERT_EQ(1U, s[1]->OutputCount());
ASSERT_TRUE(s[1]->Output()->IsUnallocated());
EXPECT_TRUE(UnallocatedOperand::cast(s[1]->Output())->HasSameAsInputPolicy());
EXPECT_EQ(s.ToVreg(finish), s.ToVreg(s[1]->Output()));
EXPECT_TRUE(s.IsReference(finish)); EXPECT_TRUE(s.IsReference(finish));
} }
......
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