[turbofan] Use a map to cache values definition in instruction scheduler.
R=jarin@chromium.org Review-Url: https://codereview.chromium.org/2193063003 Cr-Commit-Position: refs/heads/master@{#38632}
This commit is contained in:
parent
f8776c5d39
commit
75a204583f
@ -83,8 +83,8 @@ InstructionScheduler::InstructionScheduler(Zone* zone,
|
||||
last_side_effect_instr_(nullptr),
|
||||
pending_loads_(zone),
|
||||
last_live_in_reg_marker_(nullptr),
|
||||
last_deopt_(nullptr) {
|
||||
}
|
||||
last_deopt_(nullptr),
|
||||
operands_map_(zone) {}
|
||||
|
||||
|
||||
void InstructionScheduler::StartBlock(RpoNumber rpo) {
|
||||
@ -93,6 +93,7 @@ void InstructionScheduler::StartBlock(RpoNumber rpo) {
|
||||
DCHECK(pending_loads_.empty());
|
||||
DCHECK(last_live_in_reg_marker_ == nullptr);
|
||||
DCHECK(last_deopt_ == nullptr);
|
||||
DCHECK(operands_map_.empty());
|
||||
sequence()->StartBlock(rpo);
|
||||
}
|
||||
|
||||
@ -109,6 +110,7 @@ void InstructionScheduler::EndBlock(RpoNumber rpo) {
|
||||
pending_loads_.clear();
|
||||
last_live_in_reg_marker_ = nullptr;
|
||||
last_deopt_ = nullptr;
|
||||
operands_map_.clear();
|
||||
}
|
||||
|
||||
|
||||
@ -165,9 +167,26 @@ void InstructionScheduler::AddInstruction(Instruction* instr) {
|
||||
}
|
||||
|
||||
// Look for operand dependencies.
|
||||
for (ScheduleGraphNode* node : graph_) {
|
||||
if (HasOperandDependency(node->instruction(), instr)) {
|
||||
node->AddSuccessor(new_node);
|
||||
for (size_t i = 0; i < instr->InputCount(); ++i) {
|
||||
const InstructionOperand* input = instr->InputAt(i);
|
||||
if (input->IsUnallocated()) {
|
||||
int32_t vreg = UnallocatedOperand::cast(input)->virtual_register();
|
||||
auto it = operands_map_.find(vreg);
|
||||
if (it != operands_map_.end()) {
|
||||
it->second->AddSuccessor(new_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Record the virtual registers defined by this instruction.
|
||||
for (size_t i = 0; i < instr->OutputCount(); ++i) {
|
||||
const InstructionOperand* output = instr->OutputAt(i);
|
||||
if (output->IsUnallocated()) {
|
||||
operands_map_[UnallocatedOperand::cast(output)->virtual_register()] =
|
||||
new_node;
|
||||
} else if (output->IsConstant()) {
|
||||
operands_map_[ConstantOperand::cast(output)->virtual_register()] =
|
||||
new_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -317,33 +336,6 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const {
|
||||
}
|
||||
|
||||
|
||||
bool InstructionScheduler::HasOperandDependency(
|
||||
const Instruction* instr1, const Instruction* instr2) const {
|
||||
for (size_t i = 0; i < instr1->OutputCount(); ++i) {
|
||||
for (size_t j = 0; j < instr2->InputCount(); ++j) {
|
||||
const InstructionOperand* output = instr1->OutputAt(i);
|
||||
const InstructionOperand* input = instr2->InputAt(j);
|
||||
|
||||
if (output->IsUnallocated() && input->IsUnallocated() &&
|
||||
(UnallocatedOperand::cast(output)->virtual_register() ==
|
||||
UnallocatedOperand::cast(input)->virtual_register())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (output->IsConstant() && input->IsUnallocated() &&
|
||||
(ConstantOperand::cast(output)->virtual_register() ==
|
||||
UnallocatedOperand::cast(input)->virtual_register())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(bafsa): Do we need to look for anti-dependencies/output-dependencies?
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool InstructionScheduler::IsBlockTerminator(const Instruction* instr) const {
|
||||
return ((GetInstructionFlags(instr) & kIsBlockTerminator) ||
|
||||
(instr->flags_mode() == kFlags_branch));
|
||||
|
@ -156,10 +156,6 @@ class InstructionScheduler final : public ZoneObject {
|
||||
int GetInstructionFlags(const Instruction* instr) const;
|
||||
int GetTargetInstructionFlags(const Instruction* instr) const;
|
||||
|
||||
// Return true if instr2 uses any value defined by instr1.
|
||||
bool HasOperandDependency(const Instruction* instr1,
|
||||
const Instruction* instr2) const;
|
||||
|
||||
// Return true if the instruction is a basic block terminator.
|
||||
bool IsBlockTerminator(const Instruction* instr) const;
|
||||
|
||||
@ -214,6 +210,10 @@ class InstructionScheduler final : public ZoneObject {
|
||||
|
||||
// Last deoptimization instruction encountered while building the graph.
|
||||
ScheduleGraphNode* last_deopt_;
|
||||
|
||||
// Keep track of definition points for virtual registers. This is used to
|
||||
// record operand dependencies in the scheduling graph.
|
||||
ZoneMap<int32_t, ScheduleGraphNode*> operands_map_;
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
|
Loading…
Reference in New Issue
Block a user