[turbofan] add RegisterConfiguration to decouple arch specific register layouts from compiler

R=bmeurer@chromium.org

BUG=

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

Cr-Commit-Position: refs/heads/master@{#25097}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25097 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
dcarney@chromium.org 2014-11-04 09:21:12 +00:00
parent 470be4ac0c
commit 7cb25f5020
14 changed files with 311 additions and 137 deletions

View File

@ -571,6 +571,8 @@ source_set("v8_base") {
"src/compiler/raw-machine-assembler.h",
"src/compiler/register-allocator.cc",
"src/compiler/register-allocator.h",
"src/compiler/register-configuration.cc",
"src/compiler/register-configuration.h",
"src/compiler/representation-change.h",
"src/compiler/schedule.cc",
"src/compiler/schedule.h",

View File

@ -680,7 +680,9 @@ void GraphC1Visualizer::PrintSchedule(const char* phase,
for (int j = instruction_block->first_instruction_index();
j <= instruction_block->last_instruction_index(); j++) {
PrintIndent();
os_ << j << " " << *instructions->InstructionAt(j) << " <|@\n";
PrintableInstruction printable = {RegisterConfiguration::ArchDefault(),
instructions->InstructionAt(j)};
os_ << j << " " << printable << " <|@\n";
}
}
}

View File

@ -6,17 +6,15 @@
#include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph.h"
#include "src/compiler/instruction.h"
#include "src/macro-assembler.h"
namespace v8 {
namespace internal {
namespace compiler {
STATIC_ASSERT(kMaxGeneralRegisters >= Register::kNumRegisters);
STATIC_ASSERT(kMaxDoubleRegisters >= DoubleRegister::kMaxNumRegisters);
std::ostream& operator<<(std::ostream& os, const InstructionOperand& op) {
std::ostream& operator<<(std::ostream& os,
const PrintableInstructionOperand& printable) {
const InstructionOperand& op = *printable.op_;
const RegisterConfiguration* conf = printable.register_configuration_;
switch (op.kind()) {
case InstructionOperand::INVALID:
return os << "(0)";
@ -30,10 +28,10 @@ std::ostream& operator<<(std::ostream& os, const InstructionOperand& op) {
case UnallocatedOperand::NONE:
return os;
case UnallocatedOperand::FIXED_REGISTER:
return os << "(=" << Register::AllocationIndexToString(
return os << "(=" << conf->general_register_name(
unalloc->fixed_register_index()) << ")";
case UnallocatedOperand::FIXED_DOUBLE_REGISTER:
return os << "(=" << DoubleRegister::AllocationIndexToString(
return os << "(=" << conf->double_register_name(
unalloc->fixed_register_index()) << ")";
case UnallocatedOperand::MUST_HAVE_REGISTER:
return os << "(R)";
@ -52,11 +50,9 @@ std::ostream& operator<<(std::ostream& os, const InstructionOperand& op) {
case InstructionOperand::DOUBLE_STACK_SLOT:
return os << "[double_stack:" << op.index() << "]";
case InstructionOperand::REGISTER:
return os << "[" << Register::AllocationIndexToString(op.index())
<< "|R]";
return os << "[" << conf->general_register_name(op.index()) << "|R]";
case InstructionOperand::DOUBLE_REGISTER:
return os << "[" << DoubleRegister::AllocationIndexToString(op.index())
<< "|R]";
return os << "[" << conf->double_register_name(op.index()) << "|R]";
}
UNREACHABLE();
return os;
@ -101,9 +97,17 @@ void InstructionOperand::TearDownCaches() {
}
std::ostream& operator<<(std::ostream& os, const MoveOperands& mo) {
os << *mo.destination();
if (!mo.source()->Equals(mo.destination())) os << " = " << *mo.source();
std::ostream& operator<<(std::ostream& os,
const PrintableMoveOperands& printable) {
const MoveOperands& mo = *printable.move_operands_;
PrintableInstructionOperand printable_op = {printable.register_configuration_,
mo.destination()};
os << printable_op;
if (!mo.source()->Equals(mo.destination())) {
printable_op.op_ = mo.source();
os << " = " << printable_op;
}
return os << ";";
}
@ -116,14 +120,17 @@ bool ParallelMove::IsRedundant() const {
}
std::ostream& operator<<(std::ostream& os, const ParallelMove& pm) {
std::ostream& operator<<(std::ostream& os,
const PrintableParallelMove& printable) {
const ParallelMove& pm = *printable.parallel_move_;
bool first = true;
for (ZoneList<MoveOperands>::iterator move = pm.move_operands()->begin();
move != pm.move_operands()->end(); ++move) {
if (move->IsEliminated()) continue;
if (!first) os << " ";
first = false;
os << *move;
PrintableMoveOperands pmo = {printable.register_configuration_, move};
os << pmo;
}
return os;
}
@ -256,11 +263,16 @@ std::ostream& operator<<(std::ostream& os, const FlagsCondition& fc) {
}
std::ostream& operator<<(std::ostream& os, const Instruction& instr) {
std::ostream& operator<<(std::ostream& os,
const PrintableInstruction& printable) {
const Instruction& instr = *printable.instr_;
PrintableInstructionOperand printable_op = {printable.register_configuration_,
NULL};
if (instr.OutputCount() > 1) os << "(";
for (size_t i = 0; i < instr.OutputCount(); i++) {
if (i > 0) os << ", ";
os << *instr.OutputAt(i);
printable_op.op_ = instr.OutputAt(i);
os << printable_op;
}
if (instr.OutputCount() > 1) os << ") = ";
@ -272,7 +284,11 @@ std::ostream& operator<<(std::ostream& os, const Instruction& instr) {
for (int i = GapInstruction::FIRST_INNER_POSITION;
i <= GapInstruction::LAST_INNER_POSITION; i++) {
os << "(";
if (gap->parallel_moves_[i] != NULL) os << *gap->parallel_moves_[i];
if (gap->parallel_moves_[i] != NULL) {
PrintableParallelMove ppm = {printable.register_configuration_,
gap->parallel_moves_[i]};
os << ppm;
}
os << ") ";
}
} else if (instr.IsSourcePosition()) {
@ -293,7 +309,8 @@ std::ostream& operator<<(std::ostream& os, const Instruction& instr) {
}
if (instr.InputCount() > 0) {
for (size_t i = 0; i < instr.InputCount(); i++) {
os << " " << *instr.InputAt(i);
printable_op.op_ = instr.InputAt(i);
os << " " << printable_op;
}
}
return os;
@ -585,7 +602,9 @@ void FrameStateDescriptor::SetType(size_t index, MachineType type) {
}
std::ostream& operator<<(std::ostream& os, const InstructionSequence& code) {
std::ostream& operator<<(std::ostream& os,
const PrintableInstructionSequence& printable) {
const InstructionSequence& code = *printable.sequence_;
for (size_t i = 0; i < code.immediates_.size(); ++i) {
Constant constant = code.immediates_[i];
os << "IMM#" << i << ": " << constant << "\n";
@ -626,20 +645,16 @@ std::ostream& operator<<(std::ostream& os, const InstructionSequence& code) {
}
ScopedVector<char> buf(32);
PrintableInstruction printable_instr;
printable_instr.register_configuration_ = printable.register_configuration_;
for (int j = block->first_instruction_index();
j <= block->last_instruction_index(); j++) {
// TODO(svenpanne) Add some basic formatting to our streams.
SNPrintF(buf, "%5d", j);
os << " " << buf.start() << ": " << *code.InstructionAt(j) << "\n";
printable_instr.instr_ = code.InstructionAt(j);
os << " " << buf.start() << ": " << printable_instr << "\n";
}
// TODO(dcarney): add this back somehow?
// os << " " << block->control();
// if (block->control_input() != NULL) {
// os << " v" << block->control_input()->id();
// }
for (auto succ : block->successors()) {
const InstructionBlock* succ_block = code.InstructionBlockAt(succ);
os << " B" << succ_block->id();

View File

@ -14,6 +14,7 @@
#include "src/compiler/frame.h"
#include "src/compiler/instruction-codes.h"
#include "src/compiler/opcodes.h"
#include "src/compiler/register-configuration.h"
#include "src/compiler/schedule.h"
#include "src/compiler/source-position.h"
#include "src/zone-allocator.h"
@ -27,18 +28,13 @@ const InstructionCode kGapInstruction = -1;
const InstructionCode kBlockStartInstruction = -2;
const InstructionCode kSourcePositionInstruction = -3;
// Platform independent maxes.
static const int kMaxGeneralRegisters = 32;
static const int kMaxDoubleRegisters = 32;
#define INSTRUCTION_OPERAND_LIST(V) \
V(Constant, CONSTANT, 0) \
V(Immediate, IMMEDIATE, 0) \
V(StackSlot, STACK_SLOT, 128) \
V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \
V(Register, REGISTER, kMaxGeneralRegisters) \
V(DoubleRegister, DOUBLE_REGISTER, kMaxDoubleRegisters)
#define INSTRUCTION_OPERAND_LIST(V) \
V(Constant, CONSTANT, 0) \
V(Immediate, IMMEDIATE, 0) \
V(StackSlot, STACK_SLOT, 128) \
V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \
V(Register, REGISTER, RegisterConfiguration::kMaxGeneralRegisters) \
V(DoubleRegister, DOUBLE_REGISTER, RegisterConfiguration::kMaxDoubleRegisters)
class InstructionOperand : public ZoneObject {
public:
@ -87,7 +83,13 @@ class InstructionOperand : public ZoneObject {
typedef ZoneVector<InstructionOperand*> InstructionOperandVector;
std::ostream& operator<<(std::ostream& os, const InstructionOperand& op);
struct PrintableInstructionOperand {
const RegisterConfiguration* register_configuration_;
const InstructionOperand* op_;
};
std::ostream& operator<<(std::ostream& os,
const PrintableInstructionOperand& op);
class UnallocatedOperand : public InstructionOperand {
public:
@ -306,7 +308,15 @@ class MoveOperands FINAL {
InstructionOperand* destination_;
};
std::ostream& operator<<(std::ostream& os, const MoveOperands& mo);
struct PrintableMoveOperands {
const RegisterConfiguration* register_configuration_;
const MoveOperands* move_operands_;
};
std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo);
template <InstructionOperand::Kind kOperandKind, int kNumCachedOperands>
class SubKindOperand FINAL : public InstructionOperand {
@ -359,7 +369,15 @@ class ParallelMove FINAL : public ZoneObject {
ZoneList<MoveOperands> move_operands_;
};
std::ostream& operator<<(std::ostream& os, const ParallelMove& pm);
struct PrintableParallelMove {
const RegisterConfiguration* register_configuration_;
const ParallelMove* parallel_move_;
};
std::ostream& operator<<(std::ostream& os, const PrintableParallelMove& pm);
class PointerMap FINAL : public ZoneObject {
public:
@ -534,7 +552,13 @@ class Instruction : public ZoneObject {
InstructionOperand* operands_[1];
};
std::ostream& operator<<(std::ostream& os, const Instruction& instr);
struct PrintableInstruction {
const RegisterConfiguration* register_configuration_;
const Instruction* instr_;
};
std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr);
// Represents moves inserted before an instruction due to register allocation.
// TODO(titzer): squash GapInstruction back into Instruction, since essentially
@ -585,7 +609,8 @@ class GapInstruction : public Instruction {
}
private:
friend std::ostream& operator<<(std::ostream& os, const Instruction& instr);
friend std::ostream& operator<<(std::ostream& os,
const PrintableInstruction& instr);
ParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
};
@ -847,6 +872,9 @@ typedef ZoneDeque<PointerMap*> PointerMapDeque;
typedef ZoneVector<FrameStateDescriptor*> DeoptimizationVector;
typedef ZoneVector<InstructionBlock*> InstructionBlocks;
struct PrintableInstructionSequence;
// Represents architecture-specific generated code before, during, and after
// register allocation.
// TODO(titzer): s/IsDouble/IsFloat64/
@ -961,7 +989,7 @@ class InstructionSequence FINAL {
private:
friend std::ostream& operator<<(std::ostream& os,
const InstructionSequence& code);
const PrintableInstructionSequence& code);
typedef std::set<int, std::less<int>, ZoneIntAllocator> VirtualRegisterSet;
@ -977,7 +1005,15 @@ class InstructionSequence FINAL {
DeoptimizationVector deoptimization_entries_;
};
std::ostream& operator<<(std::ostream& os, const InstructionSequence& code);
struct PrintableInstructionSequence {
const RegisterConfiguration* register_configuration_;
const InstructionSequence* sequence_;
};
std::ostream& operator<<(std::ostream& os,
const PrintableInstructionSequence& code);
} // namespace compiler
} // namespace internal

View File

@ -558,8 +558,10 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) {
if (FLAG_trace_turbo) {
OFStream os(stdout);
PrintableInstructionSequence printable = {
RegisterConfiguration::ArchDefault(), &sequence};
os << "----- Instruction sequence before register allocation -----\n"
<< sequence;
<< printable;
TurboCfgFile tcf(isolate());
tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(),
&sequence);
@ -587,7 +589,7 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) {
#endif
RegisterAllocator allocator(RegisterAllocator::PlatformConfig(),
RegisterAllocator allocator(RegisterConfiguration::ArchDefault(),
zone_scope.zone(), &frame, &sequence,
debug_name.get());
if (!allocator.Allocate(data->pipeline_statistics())) {
@ -602,8 +604,10 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) {
if (FLAG_trace_turbo) {
OFStream os(stdout);
PrintableInstructionSequence printable = {
RegisterConfiguration::ArchDefault(), &sequence};
os << "----- Instruction sequence after register allocation -----\n"
<< sequence;
<< printable;
}
if (data->pipeline_statistics() != NULL) {

View File

@ -5,7 +5,6 @@
#include "src/compiler/linkage.h"
#include "src/compiler/pipeline-statistics.h"
#include "src/compiler/register-allocator.h"
#include "src/macro-assembler.h" // TODO(dcarney): remove this.
#include "src/string-stream.h"
namespace v8 {
@ -507,22 +506,9 @@ LifetimePosition LiveRange::FirstIntersection(LiveRange* other) {
}
RegisterAllocator::Config RegisterAllocator::PlatformConfig() {
DCHECK_EQ(Register::kMaxNumAllocatableRegisters,
Register::NumAllocatableRegisters());
Config config;
config.num_general_registers_ = Register::kMaxNumAllocatableRegisters;
config.num_double_registers_ = DoubleRegister::kMaxNumAllocatableRegisters;
config.num_aliased_double_registers_ =
DoubleRegister::NumAllocatableAliasedRegisters();
config.GeneralRegisterName = Register::AllocationIndexToString;
config.DoubleRegisterName = DoubleRegister::AllocationIndexToString;
return config;
}
RegisterAllocator::RegisterAllocator(const Config& config, Zone* local_zone,
Frame* frame, InstructionSequence* code,
RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config,
Zone* local_zone, Frame* frame,
InstructionSequence* code,
const char* debug_name)
: zone_(local_zone),
frame_(frame),
@ -531,8 +517,8 @@ RegisterAllocator::RegisterAllocator(const Config& config, Zone* local_zone,
config_(config),
live_in_sets_(code->InstructionBlockCount(), zone()),
live_ranges_(code->VirtualRegisterCount() * 2, zone()),
fixed_live_ranges_(this->config().num_general_registers_, NULL, zone()),
fixed_double_live_ranges_(this->config().num_double_registers_, NULL,
fixed_live_ranges_(this->config()->num_general_registers(), NULL, zone()),
fixed_double_live_ranges_(this->config()->num_double_registers(), NULL,
zone()),
unhandled_live_ranges_(code->VirtualRegisterCount() * 2, zone()),
active_live_ranges_(8, zone()),
@ -541,12 +527,14 @@ RegisterAllocator::RegisterAllocator(const Config& config, Zone* local_zone,
mode_(UNALLOCATED_REGISTERS),
num_registers_(-1),
allocation_ok_(true) {
DCHECK(this->config().num_general_registers_ <= kMaxGeneralRegisters);
DCHECK(this->config().num_double_registers_ <= kMaxDoubleRegisters);
DCHECK(this->config()->num_general_registers() <=
RegisterConfiguration::kMaxGeneralRegisters);
DCHECK(this->config()->num_double_registers() <=
RegisterConfiguration::kMaxDoubleRegisters);
// TryAllocateFreeReg and AllocateBlockedReg assume this
// when allocating local arrays.
DCHECK(this->config().num_double_registers_ >=
this->config().num_general_registers_);
DCHECK(this->config()->num_double_registers() >=
this->config()->num_general_registers());
}
@ -603,7 +591,7 @@ void RegisterAllocator::AddInitialIntervals(const InstructionBlock* block,
int RegisterAllocator::FixedDoubleLiveRangeID(int index) {
return -index - 1 - config().num_general_registers_;
return -index - 1 - config()->num_general_registers();
}
@ -635,7 +623,7 @@ InstructionOperand* RegisterAllocator::AllocateFixed(
LiveRange* RegisterAllocator::FixedLiveRangeFor(int index) {
DCHECK(index < config().num_general_registers_);
DCHECK(index < config()->num_general_registers());
LiveRange* result = fixed_live_ranges_[index];
if (result == NULL) {
// TODO(titzer): add a utility method to allocate a new LiveRange:
@ -653,7 +641,7 @@ LiveRange* RegisterAllocator::FixedLiveRangeFor(int index) {
LiveRange* RegisterAllocator::FixedDoubleLiveRangeFor(int index) {
DCHECK(index < config().num_aliased_double_registers_);
DCHECK(index < config()->num_aliased_double_registers());
LiveRange* result = fixed_double_live_ranges_[index];
if (result == NULL) {
result = new (zone()) LiveRange(FixedDoubleLiveRangeID(index), code_zone());
@ -1031,7 +1019,7 @@ void RegisterAllocator::ProcessInstructions(const InstructionBlock* block,
}
if (instr->ClobbersRegisters()) {
for (int i = 0; i < config().num_general_registers_; ++i) {
for (int i = 0; i < config()->num_general_registers(); ++i) {
if (!IsOutputRegisterOf(instr, i)) {
LiveRange* range = FixedLiveRangeFor(i);
range->AddUseInterval(curr_position, curr_position.InstructionEnd(),
@ -1041,7 +1029,7 @@ void RegisterAllocator::ProcessInstructions(const InstructionBlock* block,
}
if (instr->ClobbersDoubleRegisters()) {
for (int i = 0; i < config().num_aliased_double_registers_; ++i) {
for (int i = 0; i < config()->num_aliased_double_registers(); ++i) {
if (!IsOutputDoubleRegisterOf(instr, i)) {
LiveRange* range = FixedDoubleLiveRangeFor(i);
range->AddUseInterval(curr_position, curr_position.InstructionEnd(),
@ -1126,10 +1114,10 @@ void RegisterAllocator::ResolvePhis(const InstructionBlock* block) {
bool RegisterAllocator::Allocate(PipelineStatistics* stats) {
assigned_registers_ =
new (code_zone()) BitVector(config().num_general_registers_, code_zone());
assigned_registers_ = new (code_zone())
BitVector(config()->num_general_registers(), code_zone());
assigned_double_registers_ = new (code_zone())
BitVector(config().num_aliased_double_registers_, code_zone());
BitVector(config()->num_aliased_double_registers(), code_zone());
{
PhaseScope phase_scope(stats, "meet register constraints");
MeetRegisterConstraints();
@ -1535,14 +1523,14 @@ void RegisterAllocator::PopulatePointerMaps() {
void RegisterAllocator::AllocateGeneralRegisters() {
num_registers_ = config().num_general_registers_;
num_registers_ = config()->num_general_registers();
mode_ = GENERAL_REGISTERS;
AllocateRegisters();
}
void RegisterAllocator::AllocateDoubleRegisters() {
num_registers_ = config().num_aliased_double_registers_;
num_registers_ = config()->num_aliased_double_registers();
mode_ = DOUBLE_REGISTERS;
AllocateRegisters();
}
@ -1566,7 +1554,7 @@ void RegisterAllocator::AllocateRegisters() {
DCHECK(inactive_live_ranges_.is_empty());
if (mode_ == DOUBLE_REGISTERS) {
for (int i = 0; i < config().num_aliased_double_registers_; ++i) {
for (int i = 0; i < config()->num_aliased_double_registers(); ++i) {
LiveRange* current = fixed_double_live_ranges_.at(i);
if (current != NULL) {
AddToInactive(current);
@ -1658,9 +1646,9 @@ void RegisterAllocator::AllocateRegisters() {
const char* RegisterAllocator::RegisterName(int allocation_index) {
if (mode_ == GENERAL_REGISTERS) {
return config().GeneralRegisterName(allocation_index);
return config()->general_register_name(allocation_index);
} else {
return config().DoubleRegisterName(allocation_index);
return config()->double_register_name(allocation_index);
}
}
@ -1805,7 +1793,7 @@ void RegisterAllocator::InactiveToActive(LiveRange* range) {
bool RegisterAllocator::TryAllocateFreeReg(LiveRange* current) {
LifetimePosition free_until_pos[kMaxDoubleRegisters];
LifetimePosition free_until_pos[RegisterConfiguration::kMaxDoubleRegisters];
for (int i = 0; i < num_registers_; i++) {
free_until_pos[i] = LifetimePosition::MaxPosition();
@ -1888,8 +1876,8 @@ void RegisterAllocator::AllocateBlockedReg(LiveRange* current) {
return;
}
LifetimePosition use_pos[kMaxGeneralRegisters];
LifetimePosition block_pos[kMaxDoubleRegisters];
LifetimePosition use_pos[RegisterConfiguration::kMaxGeneralRegisters];
LifetimePosition block_pos[RegisterConfiguration::kMaxDoubleRegisters];
for (int i = 0; i < num_registers_; i++) {
use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition();

View File

@ -319,19 +319,9 @@ class LiveRange FINAL : public ZoneObject {
class RegisterAllocator FINAL {
public:
class Config {
public:
int num_general_registers_;
int num_double_registers_;
int num_aliased_double_registers_;
const char* (*GeneralRegisterName)(int allocation_index);
const char* (*DoubleRegisterName)(int allocation_index);
};
static Config PlatformConfig();
explicit RegisterAllocator(const Config& config, Zone* local_zone,
Frame* frame, InstructionSequence* code,
explicit RegisterAllocator(const RegisterConfiguration* config,
Zone* local_zone, Frame* frame,
InstructionSequence* code,
const char* debug_name = nullptr);
bool Allocate(PipelineStatistics* stats = NULL);
@ -502,14 +492,14 @@ class RegisterAllocator FINAL {
Frame* frame() const { return frame_; }
const char* debug_name() const { return debug_name_; }
const Config& config() const { return config_; }
const RegisterConfiguration* config() const { return config_; }
Zone* const zone_;
Frame* const frame_;
InstructionSequence* const code_;
const char* const debug_name_;
const Config config_;
const RegisterConfiguration* config_;
// During liveness analysis keep a mapping from block id to live_in sets
// for blocks already analyzed.

View File

@ -0,0 +1,68 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/register-configuration.h"
#include "src/macro-assembler.h"
namespace v8 {
namespace internal {
namespace compiler {
namespace {
STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >=
Register::kNumRegisters);
STATIC_ASSERT(RegisterConfiguration::kMaxDoubleRegisters >=
DoubleRegister::kMaxNumRegisters);
class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
public:
ArchDefaultRegisterConfiguration()
: RegisterConfiguration(Register::kMaxNumAllocatableRegisters,
DoubleRegister::kMaxNumAllocatableRegisters,
DoubleRegister::NumAllocatableAliasedRegisters(),
general_register_name_table_,
double_register_name_table_) {
DCHECK_EQ(Register::kMaxNumAllocatableRegisters,
Register::NumAllocatableRegisters());
for (int i = 0; i < Register::kMaxNumAllocatableRegisters; ++i) {
general_register_name_table_[i] = Register::AllocationIndexToString(i);
}
for (int i = 0; i < DoubleRegister::kMaxNumAllocatableRegisters; ++i) {
double_register_name_table_[i] =
DoubleRegister::AllocationIndexToString(i);
}
}
const char*
general_register_name_table_[Register::kMaxNumAllocatableRegisters];
const char*
double_register_name_table_[DoubleRegister::kMaxNumAllocatableRegisters];
};
static base::LazyInstance<ArchDefaultRegisterConfiguration>::type
kDefaultRegisterConfiguration = LAZY_INSTANCE_INITIALIZER;
} // namepace
const RegisterConfiguration* RegisterConfiguration::ArchDefault() {
return &kDefaultRegisterConfiguration.Get();
}
RegisterConfiguration::RegisterConfiguration(
int num_general_registers, int num_double_registers,
int num_aliased_double_registers, const char* const* general_register_names,
const char* const* double_register_names)
: num_general_registers_(num_general_registers),
num_double_registers_(num_double_registers),
num_aliased_double_registers_(num_aliased_double_registers),
general_register_names_(general_register_names),
double_register_names_(double_register_names) {}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,56 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMPILER_REGISTER_CONFIGURATION_H_
#define V8_COMPILER_REGISTER_CONFIGURATION_H_
#include "src/v8.h"
namespace v8 {
namespace internal {
namespace compiler {
// An architecture independent representation of the sets of registers available
// for instruction creation.
class RegisterConfiguration {
public:
// Architecture independent maxes.
static const int kMaxGeneralRegisters = 32;
static const int kMaxDoubleRegisters = 32;
static const RegisterConfiguration* ArchDefault();
RegisterConfiguration(int num_general_registers, int num_double_registers,
int num_aliased_double_registers,
const char* const* general_register_name,
const char* const* double_register_name);
int num_general_registers() const { return num_general_registers_; }
int num_double_registers() const { return num_double_registers_; }
int num_aliased_double_registers() const {
return num_aliased_double_registers_;
}
const char* general_register_name(int offset) const {
DCHECK(offset >= 0 && offset < kMaxGeneralRegisters);
return general_register_names_[offset];
}
const char* double_register_name(int offset) const {
DCHECK(offset >= 0 && offset < kMaxDoubleRegisters);
return double_register_names_[offset];
}
private:
const int num_general_registers_;
const int num_double_registers_;
const int num_aliased_double_registers_;
const char* const* general_register_names_;
const char* const* double_register_names_;
};
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_REGISTER_CONFIGURATION_H_

View File

@ -75,18 +75,22 @@ class DeoptCodegenTester {
selector.SelectInstructions();
if (FLAG_trace_turbo) {
PrintableInstructionSequence printable = {
RegisterConfiguration::ArchDefault(), code};
os << "----- Instruction sequence before register allocation -----\n"
<< *code;
<< printable;
}
Frame frame;
RegisterAllocator allocator(RegisterAllocator::PlatformConfig(),
RegisterAllocator allocator(RegisterConfiguration::ArchDefault(),
scope_->main_zone(), &frame, code);
CHECK(allocator.Allocate());
if (FLAG_trace_turbo) {
PrintableInstructionSequence printable = {
RegisterConfiguration::ArchDefault(), code};
os << "----- Instruction sequence after register allocation -----\n"
<< *code;
<< printable;
}
compiler::CodeGenerator generator(&frame, linkage, code, &info);

View File

@ -65,7 +65,9 @@ class InterpreterState {
if (it != is.values_.begin()) os << " ";
InstructionOperand source(it->first.first, it->first.second);
InstructionOperand destination(it->second.first, it->second.second);
os << MoveOperands(&source, &destination);
MoveOperands mo(&source, &destination);
PrintableMoveOperands pmo = {RegisterConfiguration::ArchDefault(), &mo};
os << pmo;
}
return os;
}

View File

@ -46,8 +46,10 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
selector.SelectInstructions();
if (FLAG_trace_turbo) {
OFStream out(stdout);
PrintableInstructionSequence printable = {
RegisterConfiguration::ArchDefault(), &sequence};
out << "=== Code sequence after instruction selection ===" << std::endl
<< sequence;
<< printable;
}
Stream s;
// Map virtual registers.

View File

@ -15,29 +15,22 @@ typedef BasicBlock::RpoNumber Rpo;
namespace {
static const char* general_register_names_[kMaxGeneralRegisters];
static const char* double_register_names_[kMaxDoubleRegisters];
static char register_names_[10 * (kMaxGeneralRegisters + kMaxDoubleRegisters)];
static const char* GeneralRegisterName(int allocation_index) {
return general_register_names_[allocation_index];
}
static const char* DoubleRegisterName(int allocation_index) {
return double_register_names_[allocation_index];
}
static const char*
general_register_names_[RegisterConfiguration::kMaxGeneralRegisters];
static const char*
double_register_names_[RegisterConfiguration::kMaxDoubleRegisters];
static char register_names_[10 * (RegisterConfiguration::kMaxGeneralRegisters +
RegisterConfiguration::kMaxDoubleRegisters)];
static void InitializeRegisterNames() {
char* loc = register_names_;
for (int i = 0; i < kMaxGeneralRegisters; ++i) {
for (int i = 0; i < RegisterConfiguration::kMaxGeneralRegisters; ++i) {
general_register_names_[i] = loc;
loc += base::OS::SNPrintF(loc, 100, "gp_%d", i);
*loc++ = 0;
}
for (int i = 0; i < kMaxDoubleRegisters; ++i) {
for (int i = 0; i < RegisterConfiguration::kMaxDoubleRegisters; ++i) {
double_register_names_[i] = loc;
loc += base::OS::SNPrintF(loc, 100, "fp_%d", i) + 1;
*loc++ = 0;
@ -54,15 +47,21 @@ class RegisterAllocatorTest : public TestWithZone {
static const int kDefaultNRegs = 4;
RegisterAllocatorTest()
: basic_blocks_(zone()),
: num_general_registers_(kDefaultNRegs),
num_double_registers_(kDefaultNRegs),
basic_blocks_(zone()),
instruction_blocks_(zone()),
current_block_(NULL) {
InitializeRegisterNames();
config_.num_general_registers_ = kDefaultNRegs;
config_.num_double_registers_ = kDefaultNRegs;
config_.num_aliased_double_registers_ = kDefaultNRegs;
config_.GeneralRegisterName = GeneralRegisterName;
config_.DoubleRegisterName = DoubleRegisterName;
}
RegisterConfiguration* config() {
if (config_.is_empty()) {
config_.Reset(new RegisterConfiguration(
num_general_registers_, num_double_registers_, num_double_registers_,
general_register_names_, double_register_names_));
}
return config_.get();
}
Frame* frame() {
@ -82,7 +81,7 @@ class RegisterAllocatorTest : public TestWithZone {
RegisterAllocator* allocator() {
if (allocator_.is_empty()) {
allocator_.Reset(
new RegisterAllocator(config_, zone(), frame(), sequence()));
new RegisterAllocator(config(), zone(), frame(), sequence()));
}
return allocator_.get();
}
@ -118,12 +117,14 @@ class RegisterAllocatorTest : public TestWithZone {
void Allocate() {
if (FLAG_trace_alloc) {
OFStream os(stdout);
os << "Before: " << std::endl << *sequence() << std::endl;
PrintableInstructionSequence printable = {config(), sequence()};
os << "Before: " << std::endl << printable << std::endl;
}
allocator()->Allocate();
if (FLAG_trace_alloc) {
OFStream os(stdout);
os << "After: " << std::endl << *sequence() << std::endl;
PrintableInstructionSequence printable = {config(), sequence()};
os << "After: " << std::endl << printable << std::endl;
}
}
@ -167,7 +168,9 @@ class RegisterAllocatorTest : public TestWithZone {
return op;
}
RegisterAllocator::Config config_;
int num_general_registers_;
int num_double_registers_;
SmartPointer<RegisterConfiguration> config_;
ZoneVector<BasicBlock*> basic_blocks_;
InstructionBlocks instruction_blocks_;
InstructionBlock* current_block_;

View File

@ -484,6 +484,8 @@
'../../src/compiler/raw-machine-assembler.h',
'../../src/compiler/register-allocator.cc',
'../../src/compiler/register-allocator.h',
'../../src/compiler/register-configuration.cc',
'../../src/compiler/register-configuration.h',
'../../src/compiler/representation-change.h',
'../../src/compiler/schedule.cc',
'../../src/compiler/schedule.h',