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(
effect_level_(node_count, 0, zone),
virtual_registers_(node_count,
InstructionOperand::kInvalidVirtualRegister, zone),
virtual_register_rename_(zone),
scheduler_(nullptr),
enable_scheduling_(enable_scheduling),
frame_(frame) {
instructions_.reserve(node_count);
}
void InstructionSelector::SelectInstructions() {
// Mark the inputs of all phis in loop headers as used.
BasicBlockVector* blocks = schedule()->rpo_order();
......@@ -74,11 +74,15 @@ void InstructionSelector::SelectInstructions() {
for (auto const block : *blocks) {
InstructionBlock* instruction_block =
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 start = instruction_block->code_start();
DCHECK_LE(end, start);
StartBlock(RpoNumber::FromInt(block->rpo_number()));
while (start-- > end) {
UpdateRenames(instructions_[start]);
AddInstruction(instructions_[start]);
}
EndBlock(RpoNumber::FromInt(block->rpo_number()));
......@@ -253,6 +257,53 @@ bool InstructionSelector::IsOnlyUserOfNodeInSameBlock(Node* user,
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) {
DCHECK_NOT_NULL(node);
size_t const id = node->id();
......@@ -1451,7 +1502,8 @@ void InstructionSelector::VisitStackSlot(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.
......@@ -1948,8 +2000,8 @@ Instruction* InstructionSelector::EmitDeoptimize(
void InstructionSelector::EmitIdentity(Node* node) {
OperandGenerator g(this);
Node* value = node->InputAt(0);
Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
MarkAsUsed(node->InputAt(0));
SetRename(node, node->InputAt(0));
}
void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind,
......
......@@ -212,6 +212,12 @@ class InstructionSelector final {
void EmitLookupSwitch(const SwitchInfo& sw,
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.
void MarkAsDefined(Node* node);
......@@ -341,6 +347,7 @@ class InstructionSelector final {
BoolVector used_;
IntVector effect_level_;
IntVector virtual_registers_;
IntVector virtual_register_rename_;
InstructionScheduler* scheduler_;
EnableScheduling enable_scheduling_;
Frame* frame_;
......
......@@ -568,6 +568,10 @@ void PhiInstruction::SetInput(size_t offset, int 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,
RpoNumber loop_header, RpoNumber loop_end,
......
......@@ -1184,6 +1184,7 @@ class PhiInstruction final : public ZoneObject {
PhiInstruction(Zone* zone, int virtual_register, size_t input_count);
void SetInput(size_t offset, int virtual_register);
void RenameInput(size_t offset, int virtual_register);
int virtual_register() const { return virtual_register_; }
const IntVector& operands() const { return operands_; }
......@@ -1251,6 +1252,7 @@ class InstructionBlock final : public ZoneObject {
typedef ZoneVector<PhiInstruction*> PhiInstructions;
const PhiInstructions& phis() const { return phis_; }
PhiInstruction* PhiAt(size_t i) const { return phis_[i]; }
void AddPhi(PhiInstruction* phi) { phis_.push_back(phi); }
void set_ao_number(RpoNumber ao_number) { ao_number_ = ao_number; }
......
......@@ -1245,8 +1245,7 @@ void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
if (ZeroExtendsWord32ToWord64(value)) {
// These 32-bit operations implicitly zero-extend to 64-bit on x64, so the
// zero-extension is a no-op.
Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
return;
return EmitIdentity(node);
}
Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value));
}
......@@ -1320,8 +1319,7 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
Int64BinopMatcher m(value);
if (m.right().Is(32)) {
if (TryMatchLoadWord64AndShiftRight(this, value, kX64Movl)) {
Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
return;
return EmitIdentity(node);
}
Emit(kX64Shr, g.DefineSameAsFirst(node),
g.UseRegister(m.left().node()), g.TempImmediate(32));
......
......@@ -245,19 +245,13 @@ TARGET_TEST_F(InstructionSelectorTest, FinishRegion) {
m.AddNode(m.common()->FinishRegion(), param, m.graph()->start());
m.Return(finish);
Stream s = m.Build(kAllInstructions);
ASSERT_EQ(4U, s.size());
ASSERT_EQ(3U, s.size());
EXPECT_EQ(kArchNop, s[0]->arch_opcode());
ASSERT_EQ(1U, s[0]->OutputCount());
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(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)));
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));
}
......
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