Commit b3f2277e authored by dcarney@chromium.org's avatar dcarney@chromium.org

[turbofan] decouple register allocation from schedule and graph

R=bmeurer@chromium.org, jarin@chromium.org

BUG=

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24717 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d029d761
......@@ -853,8 +853,17 @@ void InstructionSelector::VisitParameter(Node* node) {
void InstructionSelector::VisitPhi(Node* node) {
// TODO(bmeurer): Emit a PhiInstruction here.
for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) {
MarkAsUsed(*i);
PhiInstruction* phi = new (instruction_zone())
PhiInstruction(instruction_zone(), sequence()->GetVirtualRegister(node));
sequence()->InstructionBlockAt(current_block_->GetRpoNumber())->AddPhi(phi);
Node::Inputs inputs = node->inputs();
size_t j = 0;
for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
++iter, ++j) {
MarkAsUsed(*iter);
// TODO(mstarzinger): Use a ValueInputIterator instead.
if (j >= current_block_->PredecessorCount()) continue;
phi->operands().push_back(sequence()->GetVirtualRegister(*iter));
}
}
......
......@@ -317,12 +317,75 @@ std::ostream& operator<<(std::ostream& os, const Constant& constant) {
}
static BasicBlock::RpoNumber GetRpo(BasicBlock* block) {
if (block == NULL) return BasicBlock::RpoNumber::Invalid();
return block->GetRpoNumber();
}
static BasicBlock::RpoNumber GetLoopEndRpo(const BasicBlock* block) {
if (!block->IsLoopHeader()) return BasicBlock::RpoNumber::Invalid();
return BasicBlock::RpoNumber::FromInt(block->loop_end());
}
InstructionBlock::InstructionBlock(Zone* zone, const BasicBlock* block)
: successors_(block->SuccessorCount(), BasicBlock::RpoNumber::Invalid(),
zone),
predecessors_(block->PredecessorCount(), BasicBlock::RpoNumber::Invalid(),
zone),
phis_(zone),
rpo_number_(block->GetRpoNumber()),
loop_header_(GetRpo(block->loop_header())),
loop_end_(GetLoopEndRpo(block)),
code_start_(-1),
code_end_(-1) {
// Map successors and precessors
size_t index = 0;
for (BasicBlock::Successors::const_iterator it = block->successors_begin();
it != block->successors_end(); ++it, ++index) {
successors_[index] = (*it)->GetRpoNumber();
}
index = 0;
for (BasicBlock::Predecessors::const_iterator
it = block->predecessors_begin();
it != block->predecessors_end(); ++it, ++index) {
predecessors_[index] = (*it)->GetRpoNumber();
}
}
size_t InstructionBlock::PredecessorIndexOf(
BasicBlock::RpoNumber rpo_number) const {
size_t j = 0;
for (InstructionBlock::Predecessors::const_iterator i = predecessors_.begin();
i != predecessors_.end(); ++i, ++j) {
if (*i == rpo_number) break;
}
return j;
}
static void InitializeInstructionBlocks(Zone* zone, const Schedule* schedule,
InstructionBlocks* blocks) {
DCHECK(blocks->size() == schedule->rpo_order()->size());
size_t rpo_number = 0;
for (BasicBlockVector::const_iterator it = schedule->rpo_order()->begin();
it != schedule->rpo_order()->end(); ++it, ++rpo_number) {
DCHECK_EQ(NULL, (*blocks)[rpo_number]);
DCHECK((*it)->GetRpoNumber().ToSize() == rpo_number);
(*blocks)[rpo_number] = new (zone) InstructionBlock(zone, *it);
}
}
InstructionSequence::InstructionSequence(Linkage* linkage, Graph* graph,
Schedule* schedule)
: zone_(schedule->zone()),
: zone_(schedule->zone()), // TODO(dcarney): new zone.
node_count_(graph->NodeCount()),
node_map_(zone()->NewArray<int>(node_count_)),
block_data_(static_cast<int>(schedule->BasicBlockCount()), zone()),
instruction_blocks_(static_cast<int>(schedule->rpo_order()->size()), NULL,
zone()),
linkage_(linkage),
schedule_(schedule),
constants_(ConstantMap::key_compare(),
......@@ -337,6 +400,7 @@ InstructionSequence::InstructionSequence(Linkage* linkage, Graph* graph,
for (int i = 0; i < node_count_; ++i) {
node_map_[i] = -1;
}
InitializeInstructionBlocks(zone(), schedule, &instruction_blocks_);
}
......@@ -408,6 +472,20 @@ BasicBlock* InstructionSequence::GetBasicBlock(int instruction_index) {
}
const InstructionBlock* InstructionSequence::GetInstructionBlock(
int instruction_index) const {
// TODO(turbofan): Optimize this.
for (;;) {
DCHECK_LE(0, instruction_index);
Instruction* instruction = InstructionAt(instruction_index--);
if (instruction->IsBlockStart()) {
return instruction_blocks_
[BlockStartInstruction::cast(instruction)->rpo_number().ToSize()];
}
}
}
bool InstructionSequence::IsReference(int virtual_register) const {
return references_.find(virtual_register) != references_.end();
}
......
......@@ -753,6 +753,81 @@ class FrameStateDescriptor : public ZoneObject {
std::ostream& operator<<(std::ostream& os, const Constant& constant);
// TODO(dcarney): this is a temporary hack. turn into an actual instruction.
class PhiInstruction : public ZoneObject {
public:
PhiInstruction(Zone* zone, int virtual_register)
: virtual_register_(virtual_register), operands_(zone) {}
int virtual_register() const { return virtual_register_; }
const IntVector& operands() const { return operands_; }
IntVector& operands() { return operands_; }
private:
const int virtual_register_;
IntVector operands_;
};
// Analogue of BasicBlock for Instructions instead of Nodes.
class InstructionBlock : public ZoneObject {
public:
explicit InstructionBlock(Zone* zone, const BasicBlock* block);
// 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; }
BasicBlock::RpoNumber rpo_number() const { return rpo_number_; }
BasicBlock::RpoNumber loop_header() const { return loop_header_; }
BasicBlock::RpoNumber loop_end() const {
DCHECK(IsLoopHeader());
return loop_end_;
}
inline bool IsLoopHeader() const { return loop_end_.IsValid(); }
typedef ZoneVector<BasicBlock::RpoNumber> Predecessors;
const Predecessors& predecessors() const { return predecessors_; }
size_t PredecessorCount() const { return predecessors_.size(); }
size_t PredecessorIndexOf(BasicBlock::RpoNumber rpo_number) const;
typedef ZoneVector<BasicBlock::RpoNumber> Successors;
const Successors& successors() const { return successors_; }
size_t SuccessorCount() const { return successors_.size(); }
typedef ZoneVector<PhiInstruction*> PhiInstructions;
const PhiInstructions& phis() const { return phis_; }
void AddPhi(PhiInstruction* phi) { phis_.push_back(phi); }
private:
Successors successors_;
Predecessors predecessors_;
PhiInstructions phis_;
// TODO(dcarney): probably dont't need this.
BasicBlock::RpoNumber rpo_number_;
BasicBlock::RpoNumber loop_header_;
BasicBlock::RpoNumber loop_end_;
int32_t code_start_; // start index of arch-specific code.
int32_t code_end_; // end index of arch-specific code.
};
typedef ZoneDeque<Constant> ConstantDeque;
typedef std::map<int, Constant, std::less<int>,
zone_allocator<std::pair<int, Constant> > > ConstantMap;
......@@ -760,6 +835,7 @@ typedef std::map<int, Constant, std::less<int>,
typedef ZoneDeque<Instruction*> InstructionDeque;
typedef ZoneDeque<PointerMap*> PointerMapDeque;
typedef ZoneVector<FrameStateDescriptor*> DeoptimizationVector;
typedef ZoneVector<InstructionBlock*> InstructionBlocks;
// Represents architecture-specific generated code before, during, and after
// register allocation.
......@@ -774,18 +850,32 @@ class InstructionSequence FINAL {
int node_count() const { return node_count_; }
int BasicBlockCount() const {
return static_cast<int>(schedule_->rpo_order()->size());
return static_cast<int>(instruction_blocks_.size());
}
BasicBlock* BlockAt(int rpo_number) const {
return (*schedule_->rpo_order())[rpo_number];
}
BasicBlock* GetContainingLoop(BasicBlock* block) {
return block->loop_header();
InstructionBlock* InstructionBlockAt(BasicBlock::RpoNumber rpo_number) {
return GetBlock(rpo_number);
}
const InstructionBlock* InstructionBlockAt(
BasicBlock::RpoNumber rpo_number) const {
return GetBlock(rpo_number);
}
// TODO(dcarney): move to register allocator.
const InstructionBlock* GetContainingLoop(
const InstructionBlock* block) const {
BasicBlock::RpoNumber index = block->loop_header();
if (!index.IsValid()) return NULL;
return instruction_blocks_[index.ToInt()];
}
BasicBlock* GetBasicBlock(int instruction_index);
const InstructionBlock* GetInstructionBlock(int instruction_index) const;
int GetVirtualRegister(const Node* node);
// TODO(dcarney): find a way to remove this.
......@@ -828,26 +918,32 @@ class InstructionSequence FINAL {
void StartBlock(BasicBlock* block);
void EndBlock(BasicBlock* block);
void set_code_start(BasicBlock* block, int start) {
return GetBlockData(block->GetRpoNumber()).set_code_start(start);
return GetBlock(block->GetRpoNumber())->set_code_start(start);
}
void set_code_end(BasicBlock* block, int end) {
return GetBlockData(block->GetRpoNumber()).set_code_end(end);
return GetBlock(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();
return GetBlock(rpo_number)->code_start();
}
int code_start(BasicBlock* block) const {
return GetBlockData(block->GetRpoNumber()).code_start();
return GetBlock(block->GetRpoNumber())->code_start();
}
int code_end(BasicBlock* block) const {
return GetBlockData(block->GetRpoNumber()).code_end();
return GetBlock(block->GetRpoNumber())->code_end();
}
int first_instruction_index(BasicBlock* block) const {
return GetBlockData(block->GetRpoNumber()).first_instruction_index();
return GetBlock(block->GetRpoNumber())->first_instruction_index();
}
int last_instruction_index(BasicBlock* block) const {
return GetBlockData(block->GetRpoNumber()).last_instruction_index();
return GetBlock(block->GetRpoNumber())->last_instruction_index();
}
int first_instruction_index(InstructionBlock* block) const {
return GetBlock(block->rpo_number())->first_instruction_index();
}
int last_instruction_index(InstructionBlock* block) const {
return GetBlock(block->rpo_number())->last_instruction_index();
}
int AddConstant(Node* node, Constant constant) {
......@@ -892,51 +988,19 @@ 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()];
InstructionBlock* GetBlock(BasicBlock::RpoNumber rpo_number) const {
return instruction_blocks_[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_;
InstructionBlocks instruction_blocks_;
Linkage* linkage_;
Schedule* schedule_;
ConstantMap constants_;
......
This diff is collapsed.
......@@ -7,8 +7,6 @@
#include "src/allocation.h"
#include "src/compiler/instruction.h"
#include "src/compiler/node.h"
#include "src/compiler/schedule.h"
#include "src/macro-assembler.h"
#include "src/zone.h"
......@@ -378,21 +376,22 @@ class RegisterAllocator BASE_EMBEDDED {
void ResolveControlFlow();
void PopulatePointerMaps(); // TODO(titzer): rename to PopulateReferenceMaps.
void AllocateRegisters();
bool CanEagerlyResolveControlFlow(BasicBlock* block) const;
bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const;
inline bool SafePointsAreInOrder() const;
// Liveness analysis support.
void InitializeLivenessAnalysis();
BitVector* ComputeLiveOut(BasicBlock* block);
void AddInitialIntervals(BasicBlock* block, BitVector* live_out);
BitVector* ComputeLiveOut(const InstructionBlock* block);
void AddInitialIntervals(const InstructionBlock* block, BitVector* live_out);
bool IsOutputRegisterOf(Instruction* instr, int index);
bool IsOutputDoubleRegisterOf(Instruction* instr, int index);
void ProcessInstructions(BasicBlock* block, BitVector* live);
void MeetRegisterConstraints(BasicBlock* block);
void ProcessInstructions(const InstructionBlock* block, BitVector* live);
void MeetRegisterConstraints(const InstructionBlock* block);
void MeetConstraintsBetween(Instruction* first, Instruction* second,
int gap_index);
void MeetRegisterConstraintsForLastInstructionInBlock(BasicBlock* block);
void ResolvePhis(BasicBlock* block);
void MeetRegisterConstraintsForLastInstructionInBlock(
const InstructionBlock* block);
void ResolvePhis(const InstructionBlock* block);
// Helper methods for building intervals.
InstructionOperand* AllocateFixed(UnallocatedOperand* operand, int pos,
......@@ -466,8 +465,8 @@ class RegisterAllocator BASE_EMBEDDED {
bool IsBlockBoundary(LifetimePosition pos);
// Helper methods for resolving control flow.
void ResolveControlFlow(LiveRange* range, BasicBlock* block,
BasicBlock* pred);
void ResolveControlFlow(LiveRange* range, const InstructionBlock* block,
const InstructionBlock* pred);
inline void SetLiveRangeAssignedRegister(LiveRange* range, int reg);
......@@ -476,7 +475,7 @@ class RegisterAllocator BASE_EMBEDDED {
ParallelMove* GetConnectingParallelMove(LifetimePosition pos);
// Return the block which contains give lifetime position.
BasicBlock* GetBlock(LifetimePosition pos);
const InstructionBlock* GetInstructionBlock(LifetimePosition pos);
// Helper methods for the fixed registers.
int RegisterCount() const;
......@@ -485,7 +484,7 @@ class RegisterAllocator BASE_EMBEDDED {
LiveRange* FixedLiveRangeFor(int index);
LiveRange* FixedDoubleLiveRangeFor(int index);
LiveRange* LiveRangeFor(int index);
GapInstruction* GetLastGap(BasicBlock* block);
GapInstruction* GetLastGap(const InstructionBlock* block);
const char* RegisterName(int allocation_index);
......
......@@ -35,12 +35,6 @@ bool BasicBlock::LoopContains(BasicBlock* block) const {
}
BasicBlock* BasicBlock::ContainingLoop() {
if (IsLoopHeader()) return this;
return loop_header();
}
void BasicBlock::AddSuccessor(BasicBlock* successor) {
successors_.push_back(successor);
}
......@@ -88,16 +82,6 @@ void BasicBlock::set_loop_header(BasicBlock* loop_header) {
}
size_t BasicBlock::PredecessorIndexOf(BasicBlock* predecessor) {
size_t j = 0;
for (BasicBlock::Predecessors::iterator i = predecessors_.begin();
i != predecessors_.end(); ++i, ++j) {
if (*i == predecessor) break;
}
return j;
}
std::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c) {
switch (c) {
case BasicBlock::kNone:
......
......@@ -50,22 +50,33 @@ class BasicBlock FINAL : public ZoneObject {
size_t index_;
};
static const int kInvalidRpoNumber = -1;
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));
int ToInt() const {
DCHECK(IsValid());
return index_;
}
size_t ToSize() const {
DCHECK(IsValid());
return static_cast<size_t>(index_);
}
static RpoNumber Invalid() { return RpoNumber(static_cast<size_t>(-1)); }
bool IsValid() const { return index_ != kInvalidRpoNumber; }
static RpoNumber FromInt(int index) { return RpoNumber(index); }
static RpoNumber Invalid() { return RpoNumber(kInvalidRpoNumber); }
bool IsNext(const RpoNumber other) const {
DCHECK(IsValid());
return other.index_ == this->index_ + 1;
}
bool operator==(RpoNumber other) const {
return this->index_ == other.index_;
}
private:
explicit RpoNumber(size_t index) : index_(index) {}
size_t index_;
explicit RpoNumber(int32_t index) : index_(index) {}
int32_t index_;
};
BasicBlock(Zone* zone, Id id);
......@@ -76,14 +87,25 @@ class BasicBlock FINAL : public ZoneObject {
typedef ZoneVector<BasicBlock*> Predecessors;
Predecessors::iterator predecessors_begin() { return predecessors_.begin(); }
Predecessors::iterator predecessors_end() { return predecessors_.end(); }
Predecessors::const_iterator predecessors_begin() const {
return predecessors_.begin();
}
Predecessors::const_iterator predecessors_end() const {
return predecessors_.end();
}
size_t PredecessorCount() const { return predecessors_.size(); }
BasicBlock* PredecessorAt(size_t index) { return predecessors_[index]; }
size_t PredecessorIndexOf(BasicBlock* predecessor);
void AddPredecessor(BasicBlock* predecessor);
typedef ZoneVector<BasicBlock*> Successors;
Successors::iterator successors_begin() { return successors_.begin(); }
Successors::iterator successors_end() { return successors_.end(); }
Successors::const_iterator successors_begin() const {
return successors_.begin();
}
Successors::const_iterator successors_end() const {
return successors_.end();
}
size_t SuccessorCount() const { return successors_.size(); }
BasicBlock* SuccessorAt(size_t index) { return successors_[index]; }
void AddSuccessor(BasicBlock* successor);
......@@ -137,7 +159,6 @@ class BasicBlock FINAL : public ZoneObject {
// Loop membership helpers.
inline bool IsLoopHeader() const { return loop_end_ >= 0; }
bool LoopContains(BasicBlock* block) const;
BasicBlock* ContainingLoop();
private:
int32_t rpo_number_; // special RPO number of the block.
......
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