break;
}
case kArchJmp:
- __ b(code_->GetLabel(i.InputBlock(0)));
+ __ b(code_->GetLabel(i.InputRpo(0)));
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
case kArchNop:
// 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);
break;
}
case kArchJmp:
- __ B(code_->GetLabel(i.InputBlock(0)));
+ __ B(code_->GetLabel(i.InputRpo(0)));
break;
case kArchNop:
// don't emit code for nops.
// 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);
#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 {
}
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) {
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),
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());
// 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.
};
InstructionSequence* code_;
- BasicBlock* current_block_;
+ BasicBlock::RpoNumber current_block_;
SourcePosition current_source_position_;
MacroAssembler masm_;
GapResolver resolver_;
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(
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";
}
break;
}
case kArchJmp:
- __ jmp(code()->GetLabel(i.InputBlock(0)));
+ __ jmp(code()->GetLabel(i.InputRpo(0)));
break;
case kArchNop:
// don't emit code for nops.
// 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);
InstructionOperand* Label(BasicBlock* block) {
// TODO(bmeurer): We misuse ImmediateOperand here.
- return TempImmediate(block->id().ToInt());
+ return TempImmediate(block->rpo_number());
}
protected:
// 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);
}
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());
}
}
// 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;
}
#include "src/compiler/common-operator.h"
#include "src/compiler/generic-node-inl.h"
+#include "src/compiler/graph.h"
namespace v8 {
namespace internal {
: 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(),
}
-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);
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());
}
}
}
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) {
}
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";
#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"
// 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));
private:
explicit BlockStartInstruction(BasicBlock* block)
- : GapInstruction(kBlockStartInstruction), block_(block) {}
+ : GapInstruction(kBlockStartInstruction),
+ rpo_number_(block->GetRpoNumber()) {}
- BasicBlock* block_;
+ BasicBlock::RpoNumber rpo_number_;
Label label_;
};
return block->loop_header();
}
- int GetLoopEnd(BasicBlock* block) const { return block->loop_end(); }
-
BasicBlock* GetBasicBlock(int instruction_index);
int GetVirtualRegister(const Node* node);
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(); }
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);
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_;
break;
}
case kArchJmp:
- __ Branch(code_->GetLabel(i.InputBlock(0)));
+ __ Branch(code_->GetLabel(i.InputRpo(0)));
break;
case kArchNop:
// don't emit code for nops.
// 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);
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();
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);
}
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)) {
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);
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
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
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);
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);
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;
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);
}
DCHECK(hint != NULL);
LifetimePosition block_start = LifetimePosition::FromInstructionIndex(
- block->first_instruction_index());
+ code()->first_instruction_index(block));
Define(block_start, phi_operand, hint);
}
// 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()) {
// 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()) {
if (block == end_block && !end_block->IsLoopHeader()) return end;
return LifetimePosition::FromInstructionIndex(
- block->first_instruction_index());
+ code()->first_instruction_index(block));
}
loop_header_(NULL),
loop_depth_(0),
loop_end_(-1),
- code_start_(-1),
- code_end_(-1),
- deferred_(false),
control_(kNone),
control_input_(NULL),
nodes_(zone),
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;
}
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(); }
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;
// 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.
break;
}
case kArchJmp:
- __ jmp(code_->GetLabel(i.InputBlock(0)));
+ __ jmp(code_->GetLabel(i.InputRpo(0)));
break;
case kArchNop:
// don't emit code for nops.
// 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);
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)
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) {
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());
}
}
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);
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)));
}
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());
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());
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());