[turbofan] remove some of the dependency of Instruction on Schedule

R=bmeurer@chromium.org

BUG=

Review URL: https://codereview.chromium.org/646393002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24584 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
dcarney@chromium.org 2014-10-14 08:51:22 +00:00
parent 173b07faa9
commit 75d15894f6
18 changed files with 222 additions and 161 deletions

View File

@ -193,7 +193,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
break;
}
case kArchJmp:
__ b(code_->GetLabel(i.InputBlock(0)));
__ b(code_->GetLabel(i.InputRpo(0)));
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
case kArchNop:
@ -485,8 +485,10 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr,
// Emit a branch. The true and false targets are always the last two inputs
// to the instruction.
BasicBlock* tblock = i.InputBlock(instr->InputCount() - 2);
BasicBlock* fblock = i.InputBlock(instr->InputCount() - 1);
BasicBlock::RpoNumber tblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 2);
BasicBlock::RpoNumber fblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 1);
bool fallthru = IsNextInAssemblyOrder(fblock);
Label* tlabel = code()->GetLabel(tblock);
Label* flabel = fallthru ? &done : code()->GetLabel(fblock);

View File

@ -164,7 +164,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
break;
}
case kArchJmp:
__ B(code_->GetLabel(i.InputBlock(0)));
__ B(code_->GetLabel(i.InputRpo(0)));
break;
case kArchNop:
// don't emit code for nops.
@ -526,8 +526,10 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr,
// Emit a branch. The true and false targets are always the last two inputs
// to the instruction.
BasicBlock* tblock = i.InputBlock(instr->InputCount() - 2);
BasicBlock* fblock = i.InputBlock(instr->InputCount() - 1);
BasicBlock::RpoNumber tblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 2);
BasicBlock::RpoNumber fblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 1);
bool fallthru = IsNextInAssemblyOrder(fblock);
Label* tlabel = code()->GetLabel(tblock);
Label* flabel = fallthru ? &done : code()->GetLabel(fblock);

View File

@ -6,14 +6,9 @@
#define V8_COMPILER_CODE_GENERATOR_IMPL_H_
#include "src/compiler/code-generator.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/generic-graph.h"
#include "src/compiler/instruction.h"
#include "src/compiler/linkage.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node.h"
#include "src/compiler/opcodes.h"
#include "src/compiler/operator.h"
namespace v8 {
namespace internal {
@ -61,12 +56,12 @@ class InstructionOperandConverter {
}
Label* InputLabel(int index) {
return gen_->code()->GetLabel(InputBlock(index));
return gen_->code()->GetLabel(InputRpo(index));
}
BasicBlock* InputBlock(int index) {
int block_id = InputInt32(index);
return gen_->schedule()->GetBlockById(BasicBlock::Id::FromInt(block_id));
BasicBlock::RpoNumber InputRpo(int index) {
int rpo_number = InputInt32(index);
return BasicBlock::RpoNumber::FromInt(rpo_number);
}
Register OutputRegister(int index = 0) {

View File

@ -14,7 +14,7 @@ namespace compiler {
CodeGenerator::CodeGenerator(InstructionSequence* code)
: code_(code),
current_block_(NULL),
current_block_(BasicBlock::RpoNumber::Invalid()),
current_source_position_(SourcePosition::Invalid()),
masm_(code->zone()->isolate(), NULL, 0),
resolver_(this),
@ -103,11 +103,12 @@ void CodeGenerator::AssembleInstruction(Instruction* instr) {
if (instr->IsBlockStart()) {
// Bind a label for a block start and handle parallel moves.
BlockStartInstruction* block_start = BlockStartInstruction::cast(instr);
current_block_ = block_start->block();
current_block_ = block_start->rpo_number();
if (FLAG_code_comments) {
// TODO(titzer): these code comments are a giant memory leak.
Vector<char> buffer = Vector<char>::New(32);
SNPrintF(buffer, "-- B%d start --", block_start->block()->id().ToInt());
// TODO(dcarney): should not be rpo number there
SNPrintF(buffer, "-- B%d (rpo) start --", current_block_.ToInt());
masm()->RecordComment(buffer.start());
}
masm()->bind(block_start->label());

View File

@ -39,9 +39,8 @@ class CodeGenerator FINAL : public GapResolver::Assembler {
// Checks if {block} will appear directly after {current_block_} when
// assembling code, in which case, a fall-through can be used.
bool IsNextInAssemblyOrder(const BasicBlock* block) const {
return block->rpo_number() == (current_block_->rpo_number() + 1) &&
block->deferred() == current_block_->deferred();
bool IsNextInAssemblyOrder(BasicBlock::RpoNumber block) const {
return current_block_.IsNext(block);
}
// Record a safepoint with the given pointer map.
@ -119,7 +118,7 @@ class CodeGenerator FINAL : public GapResolver::Assembler {
};
InstructionSequence* code_;
BasicBlock* current_block_;
BasicBlock::RpoNumber current_block_;
SourcePosition current_source_position_;
MacroAssembler masm_;
GapResolver resolver_;

View File

@ -591,9 +591,9 @@ void GraphC1Visualizer::PrintSchedule(const char* phase,
PrintIntProperty("loop_depth", current->loop_depth());
if (current->code_start() >= 0) {
int first_index = current->first_instruction_index();
int last_index = current->last_instruction_index();
if (instructions->code_start(current) >= 0) {
int first_index = instructions->first_instruction_index(current);
int last_index = instructions->last_instruction_index(current);
PrintIntProperty("first_lir_id", LifetimePosition::FromInstructionIndex(
first_index).Value());
PrintIntProperty("last_lir_id", LifetimePosition::FromInstructionIndex(
@ -672,8 +672,8 @@ void GraphC1Visualizer::PrintSchedule(const char* phase,
if (instructions != NULL) {
Tag LIR_tag(this, "LIR");
for (int j = current->first_instruction_index();
j <= current->last_instruction_index(); j++) {
for (int j = instructions->first_instruction_index(current);
j <= instructions->last_instruction_index(current); j++) {
PrintIndent();
os_ << j << " " << *instructions->InstructionAt(j) << " <|@\n";
}

View File

@ -195,7 +195,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
break;
}
case kArchJmp:
__ jmp(code()->GetLabel(i.InputBlock(0)));
__ jmp(code()->GetLabel(i.InputRpo(0)));
break;
case kArchNop:
// don't emit code for nops.
@ -470,8 +470,10 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr,
// Emit a branch. The true and false targets are always the last two inputs
// to the instruction.
BasicBlock* tblock = i.InputBlock(instr->InputCount() - 2);
BasicBlock* fblock = i.InputBlock(instr->InputCount() - 1);
BasicBlock::RpoNumber tblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 2);
BasicBlock::RpoNumber fblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 1);
bool fallthru = IsNextInAssemblyOrder(fblock);
Label* tlabel = code()->GetLabel(tblock);
Label* flabel = fallthru ? &done : code()->GetLabel(fblock);

View File

@ -130,7 +130,7 @@ class OperandGenerator {
InstructionOperand* Label(BasicBlock* block) {
// TODO(bmeurer): We misuse ImmediateOperand here.
return TempImmediate(block->id().ToInt());
return TempImmediate(block->rpo_number());
}
protected:

View File

@ -55,11 +55,11 @@ void InstructionSelector::SelectInstructions() {
// Schedule the selected instructions.
for (BasicBlockVectorIter i = blocks->begin(); i != blocks->end(); ++i) {
BasicBlock* block = *i;
size_t end = block->code_end();
size_t start = block->code_start();
size_t end = sequence()->code_end(block);
size_t start = sequence()->code_start(block);
sequence()->StartBlock(block);
while (start-- > end) {
sequence()->AddInstruction(instructions_[start], block);
sequence()->AddInstruction(instructions_[start]);
}
sequence()->EndBlock(block);
}
@ -141,8 +141,7 @@ Instruction* InstructionSelector::Emit(Instruction* instr) {
bool InstructionSelector::IsNextInAssemblyOrder(const BasicBlock* block) const {
return block->rpo_number() == (current_block_->rpo_number() + 1) &&
block->deferred() == current_block_->deferred();
return current_block_->GetRpoNumber().IsNext(block->GetRpoNumber());
}
@ -384,9 +383,8 @@ void InstructionSelector::VisitBlock(BasicBlock* block) {
}
// We're done with the block.
// TODO(bmeurer): We should not mutate the schedule.
block->set_code_start(static_cast<int>(instructions_.size()));
block->set_code_end(current_block_end);
sequence()->set_code_start(block, static_cast<int>(instructions_.size()));
sequence()->set_code_end(block, current_block_end);
current_block_ = NULL;
}

View File

@ -6,6 +6,7 @@
#include "src/compiler/common-operator.h"
#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph.h"
namespace v8 {
namespace internal {
@ -321,6 +322,7 @@ InstructionSequence::InstructionSequence(Linkage* linkage, Graph* graph,
: zone_(schedule->zone()),
node_count_(graph->NodeCount()),
node_map_(zone()->NewArray<int>(node_count_)),
block_data_(schedule->BasicBlockCount(), zone()),
linkage_(linkage),
schedule_(schedule),
constants_(ConstantMap::key_compare(),
@ -346,32 +348,36 @@ int InstructionSequence::GetVirtualRegister(const Node* node) {
}
Label* InstructionSequence::GetLabel(BasicBlock* block) {
return GetBlockStart(block)->label();
Label* InstructionSequence::GetLabel(BasicBlock::RpoNumber rpo) {
return GetBlockStart(rpo)->label();
}
BlockStartInstruction* InstructionSequence::GetBlockStart(BasicBlock* block) {
return BlockStartInstruction::cast(InstructionAt(block->code_start()));
BlockStartInstruction* InstructionSequence::GetBlockStart(
BasicBlock::RpoNumber rpo) {
BlockStartInstruction* block_start =
BlockStartInstruction::cast(InstructionAt(code_start(rpo)));
DCHECK_EQ(rpo.ToInt(), block_start->rpo_number().ToInt());
return block_start;
}
void InstructionSequence::StartBlock(BasicBlock* block) {
block->set_code_start(static_cast<int>(instructions_.size()));
set_code_start(block, static_cast<int>(instructions_.size()));
BlockStartInstruction* block_start =
BlockStartInstruction::New(zone(), block);
AddInstruction(block_start, block);
AddInstruction(block_start);
}
void InstructionSequence::EndBlock(BasicBlock* block) {
int end = static_cast<int>(instructions_.size());
DCHECK(block->code_start() >= 0 && block->code_start() < end);
block->set_code_end(end);
DCHECK(code_start(block) >= 0 && code_start(block) < end);
set_code_end(block, end);
}
int InstructionSequence::AddInstruction(Instruction* instr, BasicBlock* block) {
int InstructionSequence::AddInstruction(Instruction* instr) {
// TODO(titzer): the order of these gaps is a holdover from Lithium.
GapInstruction* gap = GapInstruction::New(zone());
if (instr->IsControl()) instructions_.push_back(gap);
@ -395,7 +401,8 @@ BasicBlock* InstructionSequence::GetBasicBlock(int instruction_index) {
DCHECK_LE(0, instruction_index);
Instruction* instruction = InstructionAt(instruction_index--);
if (instruction->IsBlockStart()) {
return BlockStartInstruction::cast(instruction)->block();
return schedule()->rpo_order()->at(
BlockStartInstruction::cast(instruction)->rpo_number().ToSize());
}
}
}
@ -537,8 +544,8 @@ std::ostream& operator<<(std::ostream& os, const InstructionSequence& code) {
os << " loop blocks: [" << block->rpo_number() << ", "
<< block->loop_end() << ")";
}
os << " instructions: [" << block->code_start() << ", "
<< block->code_end() << ")\n predecessors:";
os << " instructions: [" << code.code_start(block) << ", "
<< code.code_end(block) << ")\n predecessors:";
for (BasicBlock::Predecessors::iterator iter = block->predecessors_begin();
iter != block->predecessors_end(); ++iter) {
@ -560,8 +567,8 @@ std::ostream& operator<<(std::ostream& os, const InstructionSequence& code) {
}
ScopedVector<char> buf(32);
for (int j = block->first_instruction_index();
j <= block->last_instruction_index(); j++) {
for (int j = code.first_instruction_index(block);
j <= code.last_instruction_index(block); j++) {
// TODO(svenpanne) Add some basic formatting to our streams.
SNPrintF(buf, "%5d", j);
os << " " << buf.start() << ": " << *code.InstructionAt(j) << "\n";

View File

@ -12,10 +12,10 @@
#include "src/compiler/common-operator.h"
#include "src/compiler/frame.h"
#include "src/compiler/graph.h"
#include "src/compiler/instruction-codes.h"
#include "src/compiler/opcodes.h"
#include "src/compiler/schedule.h"
#include "src/compiler/source-position.h"
// TODO(titzer): don't include the macro-assembler?
#include "src/macro-assembler.h"
#include "src/zone-allocator.h"
@ -596,8 +596,8 @@ class GapInstruction : public Instruction {
// TODO(titzer): move code_start and code_end from BasicBlock to here.
class BlockStartInstruction FINAL : public GapInstruction {
public:
BasicBlock* block() const { return block_; }
Label* label() { return &label_; }
BasicBlock::RpoNumber rpo_number() const { return rpo_number_; }
static BlockStartInstruction* New(Zone* zone, BasicBlock* block) {
void* buffer = zone->New(sizeof(BlockStartInstruction));
@ -611,9 +611,10 @@ class BlockStartInstruction FINAL : public GapInstruction {
private:
explicit BlockStartInstruction(BasicBlock* block)
: GapInstruction(kBlockStartInstruction), block_(block) {}
: GapInstruction(kBlockStartInstruction),
rpo_number_(block->GetRpoNumber()) {}
BasicBlock* block_;
BasicBlock::RpoNumber rpo_number_;
Label label_;
};
@ -781,8 +782,6 @@ class InstructionSequence FINAL {
return block->loop_header();
}
int GetLoopEnd(BasicBlock* block) const { return block->loop_end(); }
BasicBlock* GetBasicBlock(int instruction_index);
int GetVirtualRegister(const Node* node);
@ -797,8 +796,8 @@ class InstructionSequence FINAL {
void AddGapMove(int index, InstructionOperand* from, InstructionOperand* to);
Label* GetLabel(BasicBlock* block);
BlockStartInstruction* GetBlockStart(BasicBlock* block);
Label* GetLabel(BasicBlock::RpoNumber rpo);
BlockStartInstruction* GetBlockStart(BasicBlock::RpoNumber rpo);
typedef InstructionDeque::const_iterator const_iterator;
const_iterator begin() const { return instructions_.begin(); }
@ -821,10 +820,32 @@ class InstructionSequence FINAL {
const PointerMapDeque* pointer_maps() const { return &pointer_maps_; }
Zone* zone() const { return zone_; }
// Used by the code generator while adding instructions.
int AddInstruction(Instruction* instr, BasicBlock* block);
// Used by the instruction selector while adding instructions.
int AddInstruction(Instruction* instr);
void StartBlock(BasicBlock* block);
void EndBlock(BasicBlock* block);
void set_code_start(BasicBlock* block, int start) {
return GetBlockData(block->GetRpoNumber()).set_code_start(start);
}
void set_code_end(BasicBlock* block, int end) {
return GetBlockData(block->GetRpoNumber()).set_code_end(end);
}
// TODO(dcarney): use RpoNumber for all of the below.
int code_start(BasicBlock::RpoNumber rpo_number) const {
return GetBlockData(rpo_number).code_start();
}
int code_start(BasicBlock* block) const {
return GetBlockData(block->GetRpoNumber()).code_start();
}
int code_end(BasicBlock* block) const {
return GetBlockData(block->GetRpoNumber()).code_end();
}
int first_instruction_index(BasicBlock* block) const {
return GetBlockData(block->GetRpoNumber()).first_instruction_index();
}
int last_instruction_index(BasicBlock* block) const {
return GetBlockData(block->GetRpoNumber()).last_instruction_index();
}
int AddConstant(Node* node, Constant constant) {
int virtual_register = GetVirtualRegister(node);
@ -868,14 +889,51 @@ class InstructionSequence FINAL {
int GetFrameStateDescriptorCount();
private:
class BlockData {
public:
BlockData() : code_start_(-1), code_end_(-1) {}
// Instruction indexes (used by the register allocator).
int first_instruction_index() const {
DCHECK(code_start_ >= 0);
DCHECK(code_end_ > 0);
DCHECK(code_end_ >= code_start_);
return code_start_;
}
int last_instruction_index() const {
DCHECK(code_start_ >= 0);
DCHECK(code_end_ > 0);
DCHECK(code_end_ >= code_start_);
return code_end_ - 1;
}
int32_t code_start() const { return code_start_; }
void set_code_start(int32_t start) { code_start_ = start; }
int32_t code_end() const { return code_end_; }
void set_code_end(int32_t end) { code_end_ = end; }
private:
int32_t code_start_; // start index of arch-specific code.
int32_t code_end_; // end index of arch-specific code.
};
const BlockData& GetBlockData(BasicBlock::RpoNumber rpo_number) const {
return block_data_[rpo_number.ToSize()];
}
BlockData& GetBlockData(BasicBlock::RpoNumber rpo_number) {
return block_data_[rpo_number.ToSize()];
}
friend std::ostream& operator<<(std::ostream& os,
const InstructionSequence& code);
typedef std::set<int, std::less<int>, ZoneIntAllocator> VirtualRegisterSet;
typedef ZoneVector<BlockData> BlockDataVector;
Zone* zone_;
int node_count_;
int* node_map_;
BlockDataVector block_data_;
Linkage* linkage_;
Schedule* schedule_;
ConstantMap constants_;

View File

@ -154,7 +154,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
break;
}
case kArchJmp:
__ Branch(code_->GetLabel(i.InputBlock(0)));
__ Branch(code_->GetLabel(i.InputRpo(0)));
break;
case kArchNop:
// don't emit code for nops.
@ -393,8 +393,10 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr,
// Emit a branch. The true and false targets are always the last two inputs
// to the instruction.
BasicBlock* tblock = i.InputBlock(instr->InputCount() - 2);
BasicBlock* fblock = i.InputBlock(instr->InputCount() - 1);
BasicBlock::RpoNumber tblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 2);
BasicBlock::RpoNumber fblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 1);
bool fallthru = IsNextInAssemblyOrder(fblock);
Label* tlabel = code()->GetLabel(tblock);
Label* flabel = fallthru ? &done : code()->GetLabel(fblock);

View File

@ -559,10 +559,11 @@ void RegisterAllocator::AddInitialIntervals(BasicBlock* block,
BitVector* live_out) {
// Add an interval that includes the entire block to the live range for
// each live_out value.
LifetimePosition start =
LifetimePosition::FromInstructionIndex(block->first_instruction_index());
LifetimePosition end = LifetimePosition::FromInstructionIndex(
block->last_instruction_index()).NextInstruction();
LifetimePosition start = LifetimePosition::FromInstructionIndex(
code()->first_instruction_index(block));
LifetimePosition end =
LifetimePosition::FromInstructionIndex(
code()->last_instruction_index(block)).NextInstruction();
BitVector::Iterator iterator(live_out);
while (!iterator.Done()) {
int operand_index = iterator.Current();
@ -651,7 +652,7 @@ LiveRange* RegisterAllocator::LiveRangeFor(int index) {
GapInstruction* RegisterAllocator::GetLastGap(BasicBlock* block) {
int last_instruction = block->last_instruction_index();
int last_instruction = code()->last_instruction_index(block);
return code()->GapAt(last_instruction - 1);
}
@ -729,8 +730,8 @@ void RegisterAllocator::AddConstraintsGapMove(int index,
void RegisterAllocator::MeetRegisterConstraints(BasicBlock* block) {
int start = block->first_instruction_index();
int end = block->last_instruction_index();
int start = code()->first_instruction_index(block);
int end = code()->last_instruction_index(block);
DCHECK_NE(-1, start);
for (int i = start; i <= end; ++i) {
if (code()->IsGapAt(i)) {
@ -752,7 +753,7 @@ void RegisterAllocator::MeetRegisterConstraints(BasicBlock* block) {
void RegisterAllocator::MeetRegisterConstraintsForLastInstructionInBlock(
BasicBlock* block) {
int end = block->last_instruction_index();
int end = code()->last_instruction_index(block);
Instruction* last_instruction = InstructionAt(end);
for (size_t i = 0; i < last_instruction->OutputCount(); i++) {
InstructionOperand* output_operand = last_instruction->OutputAt(i);
@ -773,7 +774,7 @@ void RegisterAllocator::MeetRegisterConstraintsForLastInstructionInBlock(
for (BasicBlock::Successors::iterator succ = block->successors_begin();
succ != block->successors_end(); ++succ) {
DCHECK((*succ)->PredecessorCount() == 1);
int gap_index = (*succ)->first_instruction_index() + 1;
int gap_index = code()->first_instruction_index(*succ) + 1;
DCHECK(code()->IsGapAt(gap_index));
// Create an unconstrained operand for the same virtual register
@ -790,7 +791,7 @@ void RegisterAllocator::MeetRegisterConstraintsForLastInstructionInBlock(
for (BasicBlock::Successors::iterator succ = block->successors_begin();
succ != block->successors_end(); ++succ) {
DCHECK((*succ)->PredecessorCount() == 1);
int gap_index = (*succ)->first_instruction_index() + 1;
int gap_index = code()->first_instruction_index(*succ) + 1;
range->SetSpillStartIndex(gap_index);
// This move to spill operand is not a real use. Liveness analysis
@ -937,12 +938,12 @@ bool RegisterAllocator::IsOutputDoubleRegisterOf(Instruction* instr,
void RegisterAllocator::ProcessInstructions(BasicBlock* block,
BitVector* live) {
int block_start = block->first_instruction_index();
int block_start = code()->first_instruction_index(block);
LifetimePosition block_start_position =
LifetimePosition::FromInstructionIndex(block_start);
for (int index = block->last_instruction_index(); index >= block_start;
for (int index = code()->last_instruction_index(block); index >= block_start;
index--) {
LifetimePosition curr_position =
LifetimePosition::FromInstructionIndex(index);
@ -1081,19 +1082,21 @@ void RegisterAllocator::ResolvePhis(BasicBlock* block) {
BasicBlock* cur_block = block->PredecessorAt(j);
// The gap move must be added without any special processing as in
// the AddConstraintsGapMove.
code()->AddGapMove(cur_block->last_instruction_index() - 1, operand,
code()->AddGapMove(code()->last_instruction_index(cur_block) - 1, operand,
phi_operand);
Instruction* branch = InstructionAt(cur_block->last_instruction_index());
Instruction* branch =
InstructionAt(code()->last_instruction_index(cur_block));
DCHECK(!branch->HasPointerMap());
USE(branch);
}
LiveRange* live_range = LiveRangeFor(phi_vreg);
BlockStartInstruction* block_start = code()->GetBlockStart(block);
BlockStartInstruction* block_start =
code()->GetBlockStart(block->GetRpoNumber());
block_start->GetOrCreateParallelMove(GapInstruction::START, code_zone())
->AddMove(phi_operand, live_range->GetSpillOperand(), code_zone());
live_range->SetSpillStartIndex(block->first_instruction_index());
live_range->SetSpillStartIndex(code()->first_instruction_index(block));
// We use the phi-ness of some nodes in some later heuristics.
live_range->set_is_phi(true);
@ -1147,10 +1150,10 @@ void RegisterAllocator::ResolvePhis() {
void RegisterAllocator::ResolveControlFlow(LiveRange* range, BasicBlock* block,
BasicBlock* pred) {
LifetimePosition pred_end =
LifetimePosition::FromInstructionIndex(pred->last_instruction_index());
LifetimePosition cur_start =
LifetimePosition::FromInstructionIndex(block->first_instruction_index());
LifetimePosition pred_end = LifetimePosition::FromInstructionIndex(
code()->last_instruction_index(pred));
LifetimePosition cur_start = LifetimePosition::FromInstructionIndex(
code()->first_instruction_index(block));
LiveRange* pred_cover = NULL;
LiveRange* cur_cover = NULL;
LiveRange* cur_range = range;
@ -1175,12 +1178,13 @@ void RegisterAllocator::ResolveControlFlow(LiveRange* range, BasicBlock* block,
if (!pred_op->Equals(cur_op)) {
GapInstruction* gap = NULL;
if (block->PredecessorCount() == 1) {
gap = code()->GapAt(block->first_instruction_index());
gap = code()->GapAt(code()->first_instruction_index(block));
} else {
DCHECK(pred->SuccessorCount() == 1);
gap = GetLastGap(pred);
Instruction* branch = InstructionAt(pred->last_instruction_index());
Instruction* branch =
InstructionAt(code()->last_instruction_index(pred));
DCHECK(!branch->HasPointerMap());
USE(branch);
}
@ -1320,7 +1324,7 @@ void RegisterAllocator::BuildLiveRanges() {
DCHECK(hint != NULL);
LifetimePosition block_start = LifetimePosition::FromInstructionIndex(
block->first_instruction_index());
code()->first_instruction_index(block));
Define(block_start, phi_operand, hint);
}
@ -1333,9 +1337,9 @@ void RegisterAllocator::BuildLiveRanges() {
// for each value live on entry to the header.
BitVector::Iterator iterator(live);
LifetimePosition start = LifetimePosition::FromInstructionIndex(
block->first_instruction_index());
code()->first_instruction_index(block));
int end_index =
code()->BlockAt(block->loop_end())->last_instruction_index();
code()->last_instruction_index(code()->BlockAt(block->loop_end()));
LifetimePosition end =
LifetimePosition::FromInstructionIndex(end_index).NextInstruction();
while (!iterator.Done()) {
@ -1967,7 +1971,7 @@ LifetimePosition RegisterAllocator::FindOptimalSpillingPos(
// If possible try to move spilling position backwards to loop header.
// This will reduce number of memory moves on the back edge.
LifetimePosition loop_start = LifetimePosition::FromInstructionIndex(
loop_header->first_instruction_index());
code()->first_instruction_index(loop_header));
if (range->Covers(loop_start)) {
if (prev_use == NULL || prev_use->pos().Value() < loop_start.Value()) {
@ -2105,7 +2109,7 @@ LifetimePosition RegisterAllocator::FindOptimalSplitPos(LifetimePosition start,
if (block == end_block && !end_block->IsLoopHeader()) return end;
return LifetimePosition::FromInstructionIndex(
block->first_instruction_index());
code()->first_instruction_index(block));
}

View File

@ -18,9 +18,6 @@ BasicBlock::BasicBlock(Zone* zone, Id id)
loop_header_(NULL),
loop_depth_(0),
loop_end_(-1),
code_start_(-1),
code_end_(-1),
deferred_(false),
control_(kNone),
control_input_(NULL),
nodes_(zone),
@ -86,14 +83,6 @@ void BasicBlock::set_rpo_number(int32_t rpo_number) {
void BasicBlock::set_loop_end(int32_t loop_end) { loop_end_ = loop_end; }
void BasicBlock::set_code_start(int32_t code_start) {
code_start_ = code_start;
}
void BasicBlock::set_code_end(int32_t code_end) { code_end_ = code_end; }
void BasicBlock::set_loop_header(BasicBlock* loop_header) {
loop_header_ = loop_header;
}

View File

@ -50,24 +50,28 @@ class BasicBlock FINAL : public ZoneObject {
size_t index_;
};
class RpoNumber FINAL {
public:
int ToInt() const { return static_cast<int>(index_); }
size_t ToSize() const { return index_; }
static RpoNumber FromInt(int index) {
return RpoNumber(static_cast<size_t>(index));
}
static RpoNumber Invalid() { return RpoNumber(static_cast<size_t>(-1)); }
bool IsNext(const RpoNumber other) const {
return other.index_ == this->index_ + 1;
}
private:
explicit RpoNumber(size_t index) : index_(index) {}
size_t index_;
};
BasicBlock(Zone* zone, Id id);
Id id() const { return id_; }
// Instruction indexes (used by the register allocator).
int first_instruction_index() {
DCHECK(code_start_ >= 0);
DCHECK(code_end_ > 0);
DCHECK(code_end_ >= code_start_);
return code_start_;
}
int last_instruction_index() {
DCHECK(code_start_ >= 0);
DCHECK(code_end_ > 0);
DCHECK(code_end_ >= code_start_);
return code_end_ - 1;
}
// Predecessors and successors.
typedef ZoneVector<BasicBlock*> Predecessors;
Predecessors::iterator predecessors_begin() { return predecessors_.begin(); }
@ -126,17 +130,10 @@ class BasicBlock FINAL : public ZoneObject {
int32_t loop_end() const { return loop_end_; }
void set_loop_end(int32_t loop_end);
RpoNumber GetRpoNumber() const { return RpoNumber::FromInt(rpo_number_); }
int32_t rpo_number() const { return rpo_number_; }
void set_rpo_number(int32_t rpo_number);
int32_t code_start() const { return code_start_; }
void set_code_start(int32_t start);
int32_t code_end() const { return code_end_; }
void set_code_end(int32_t end);
bool deferred() const { return deferred_; }
// Loop membership helpers.
inline bool IsLoopHeader() const { return loop_end_ >= 0; }
bool LoopContains(BasicBlock* block) const;
@ -150,10 +147,7 @@ class BasicBlock FINAL : public ZoneObject {
// enclosing loop header.
int32_t loop_depth_; // loop nesting, 0 is top-level
int32_t loop_end_; // end of the loop, if this block is a loop header.
int32_t code_start_; // start index of arch-specific code.
int32_t code_end_; // end index of arch-specific code.
bool deferred_; // {true} if this block is considered the slow
// path.
Control control_; // Control at the end of the block.
Node* control_input_; // Input value for control.
NodeVector nodes_; // nodes of this block in forward order.

View File

@ -233,7 +233,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
break;
}
case kArchJmp:
__ jmp(code_->GetLabel(i.InputBlock(0)));
__ jmp(code_->GetLabel(i.InputRpo(0)));
break;
case kArchNop:
// don't emit code for nops.
@ -583,8 +583,10 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr,
// Emit a branch. The true and false targets are always the last two inputs
// to the instruction.
BasicBlock* tblock = i.InputBlock(static_cast<int>(instr->InputCount()) - 2);
BasicBlock* fblock = i.InputBlock(static_cast<int>(instr->InputCount()) - 1);
BasicBlock::RpoNumber tblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 2);
BasicBlock::RpoNumber fblock =
i.InputRpo(static_cast<int>(instr->InputCount()) - 1);
bool fallthru = IsNextInAssemblyOrder(fblock);
Label* tlabel = code()->GetLabel(tblock);
Label* flabel = fallthru ? &done : code()->GetLabel(fblock);

View File

@ -23,6 +23,12 @@ class ZoneVector : public std::vector<T, zone_allocator<T> > {
explicit ZoneVector(Zone* zone)
: std::vector<T, zone_allocator<T> >(zone_allocator<T>(zone)) {}
// Constructs a new vector and fills it with {size} elements, each
// constructed via the default constructor.
ZoneVector(int size, Zone* zone)
: std::vector<T, zone_allocator<T> >(size, T(), zone_allocator<T>(zone)) {
}
// Constructs a new vector and fills it with {size} elements, each
// having the value {def}.
ZoneVector(int size, T def, Zone* zone)

View File

@ -81,10 +81,10 @@ class InstructionTester : public HandleAndZoneScope {
return node;
}
int NewInstr(BasicBlock* block) {
int NewInstr() {
InstructionCode opcode = static_cast<InstructionCode>(110);
TestInstr* instr = TestInstr::New(zone(), opcode);
return code->AddInstruction(instr, block);
return code->AddInstruction(instr);
}
UnallocatedOperand* NewUnallocated(int vreg) {
@ -122,7 +122,7 @@ TEST(InstructionBasic) {
i++, index++) {
BasicBlock* block = *i;
CHECK_EQ(block, R.code->BlockAt(index));
CHECK_EQ(-1, R.code->GetLoopEnd(block));
CHECK_EQ(-1, block->loop_end());
}
}
@ -142,19 +142,19 @@ TEST(InstructionGetBasicBlock) {
R.allocCode();
R.code->StartBlock(b0);
int i0 = R.NewInstr(b0);
int i1 = R.NewInstr(b0);
int i0 = R.NewInstr();
int i1 = R.NewInstr();
R.code->EndBlock(b0);
R.code->StartBlock(b1);
int i2 = R.NewInstr(b1);
int i3 = R.NewInstr(b1);
int i4 = R.NewInstr(b1);
int i5 = R.NewInstr(b1);
int i2 = R.NewInstr();
int i3 = R.NewInstr();
int i4 = R.NewInstr();
int i5 = R.NewInstr();
R.code->EndBlock(b1);
R.code->StartBlock(b2);
int i6 = R.NewInstr(b2);
int i7 = R.NewInstr(b2);
int i8 = R.NewInstr(b2);
int i6 = R.NewInstr();
int i7 = R.NewInstr();
int i8 = R.NewInstr();
R.code->EndBlock(b2);
R.code->StartBlock(b3);
R.code->EndBlock(b3);
@ -171,17 +171,17 @@ TEST(InstructionGetBasicBlock) {
CHECK_EQ(b2, R.code->GetBasicBlock(i7));
CHECK_EQ(b2, R.code->GetBasicBlock(i8));
CHECK_EQ(b0, R.code->GetBasicBlock(b0->first_instruction_index()));
CHECK_EQ(b0, R.code->GetBasicBlock(b0->last_instruction_index()));
CHECK_EQ(b0, R.code->GetBasicBlock(R.code->first_instruction_index(b0)));
CHECK_EQ(b0, R.code->GetBasicBlock(R.code->last_instruction_index(b0)));
CHECK_EQ(b1, R.code->GetBasicBlock(b1->first_instruction_index()));
CHECK_EQ(b1, R.code->GetBasicBlock(b1->last_instruction_index()));
CHECK_EQ(b1, R.code->GetBasicBlock(R.code->first_instruction_index(b1)));
CHECK_EQ(b1, R.code->GetBasicBlock(R.code->last_instruction_index(b1)));
CHECK_EQ(b2, R.code->GetBasicBlock(b2->first_instruction_index()));
CHECK_EQ(b2, R.code->GetBasicBlock(b2->last_instruction_index()));
CHECK_EQ(b2, R.code->GetBasicBlock(R.code->first_instruction_index(b2)));
CHECK_EQ(b2, R.code->GetBasicBlock(R.code->last_instruction_index(b2)));
CHECK_EQ(b3, R.code->GetBasicBlock(b3->first_instruction_index()));
CHECK_EQ(b3, R.code->GetBasicBlock(b3->last_instruction_index()));
CHECK_EQ(b3, R.code->GetBasicBlock(R.code->first_instruction_index(b3)));
CHECK_EQ(b3, R.code->GetBasicBlock(R.code->last_instruction_index(b3)));
}
@ -195,8 +195,8 @@ TEST(InstructionIsGapAt) {
TestInstr* i0 = TestInstr::New(R.zone(), 100);
TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl();
R.code->StartBlock(b0);
R.code->AddInstruction(i0, b0);
R.code->AddInstruction(g, b0);
R.code->AddInstruction(i0);
R.code->AddInstruction(g);
R.code->EndBlock(b0);
CHECK_EQ(true, R.code->InstructionAt(0)->IsBlockStart());
@ -222,15 +222,15 @@ TEST(InstructionIsGapAt2) {
TestInstr* i0 = TestInstr::New(R.zone(), 100);
TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl();
R.code->StartBlock(b0);
R.code->AddInstruction(i0, b0);
R.code->AddInstruction(g, b0);
R.code->AddInstruction(i0);
R.code->AddInstruction(g);
R.code->EndBlock(b0);
TestInstr* i1 = TestInstr::New(R.zone(), 102);
TestInstr* g1 = TestInstr::New(R.zone(), 104)->MarkAsControl();
R.code->StartBlock(b1);
R.code->AddInstruction(i1, b1);
R.code->AddInstruction(g1, b1);
R.code->AddInstruction(i1);
R.code->AddInstruction(g1);
R.code->EndBlock(b1);
CHECK_EQ(true, R.code->InstructionAt(0)->IsBlockStart());
@ -263,8 +263,8 @@ TEST(InstructionAddGapMove) {
TestInstr* i0 = TestInstr::New(R.zone(), 100);
TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl();
R.code->StartBlock(b0);
R.code->AddInstruction(i0, b0);
R.code->AddInstruction(g, b0);
R.code->AddInstruction(i0);
R.code->AddInstruction(g);
R.code->EndBlock(b0);
CHECK_EQ(true, R.code->InstructionAt(0)->IsBlockStart());