[turbofan] move register allocation phases to pipeline

BUG=
R=bmeurer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#25379}
This commit is contained in:
Dan Carney 2014-11-17 13:36:58 +01:00
parent 7e2ebd4c00
commit 032191e9be
6 changed files with 281 additions and 249 deletions

View File

@ -43,39 +43,9 @@ namespace compiler {
class PipelineData {
public:
PipelineData(CompilationInfo* info, ZonePool* zone_pool,
PipelineStatistics* pipeline_statistics)
explicit PipelineData(ZonePool* zone_pool, CompilationInfo* info)
: isolate_(info->zone()->isolate()),
info_(info),
outer_zone_(info->zone()),
zone_pool_(zone_pool),
pipeline_statistics_(pipeline_statistics),
compilation_failed_(false),
code_(Handle<Code>::null()),
graph_zone_scope_(zone_pool_),
graph_zone_(graph_zone_scope_.zone()),
graph_(new (graph_zone()) Graph(graph_zone())),
source_positions_(new SourcePositionTable(graph())),
machine_(new (graph_zone()) MachineOperatorBuilder(
graph_zone(), kMachPtr,
InstructionSelector::SupportedMachineOperatorFlags())),
common_(new (graph_zone()) CommonOperatorBuilder(graph_zone())),
javascript_(new (graph_zone()) JSOperatorBuilder(graph_zone())),
jsgraph_(new (graph_zone())
JSGraph(graph(), common(), javascript(), machine())),
typer_(new Typer(graph(), info->context())),
context_node_(nullptr),
schedule_(nullptr),
instruction_zone_scope_(zone_pool_),
instruction_zone_(instruction_zone_scope_.zone()),
sequence_(nullptr),
frame_(nullptr) {}
// For machine graph testing only.
PipelineData(Graph* graph, Schedule* schedule, ZonePool* zone_pool)
: isolate_(graph->zone()->isolate()),
info_(nullptr),
outer_zone_(nullptr),
zone_pool_(zone_pool),
pipeline_statistics_(nullptr),
@ -83,25 +53,57 @@ class PipelineData {
code_(Handle<Code>::null()),
graph_zone_scope_(zone_pool_),
graph_zone_(nullptr),
graph_(graph),
source_positions_(new SourcePositionTable(graph)),
graph_(nullptr),
machine_(nullptr),
common_(nullptr),
javascript_(nullptr),
jsgraph_(nullptr),
typer_(nullptr),
context_node_(nullptr),
schedule_(schedule),
schedule_(nullptr),
instruction_zone_scope_(zone_pool_),
instruction_zone_(instruction_zone_scope_.zone()),
instruction_zone_(nullptr),
sequence_(nullptr),
frame_(nullptr) {}
frame_(nullptr),
register_allocator_(nullptr) {}
~PipelineData() {
DeleteInstructionZone();
DeleteGraphZone();
}
// For main entry point.
void Initialize(PipelineStatistics* pipeline_statistics) {
outer_zone_ = info()->zone();
pipeline_statistics_ = pipeline_statistics;
graph_zone_ = graph_zone_scope_.zone();
graph_ = new (graph_zone()) Graph(graph_zone());
source_positions_.Reset(new SourcePositionTable(graph()));
machine_ = new (graph_zone()) MachineOperatorBuilder(
graph_zone(), kMachPtr,
InstructionSelector::SupportedMachineOperatorFlags());
common_ = new (graph_zone()) CommonOperatorBuilder(graph_zone());
javascript_ = new (graph_zone()) JSOperatorBuilder(graph_zone());
jsgraph_ =
new (graph_zone()) JSGraph(graph(), common(), javascript(), machine());
typer_.Reset(new Typer(graph(), info()->context()));
instruction_zone_ = instruction_zone_scope_.zone();
}
// For machine graph testing entry point.
void Initialize(Graph* graph, Schedule* schedule) {
graph_ = graph;
source_positions_.Reset(new SourcePositionTable(graph));
schedule_ = schedule;
instruction_zone_ = instruction_zone_scope_.zone();
}
// For register allocation entry point.
void Initialize(InstructionSequence* sequence) {
instruction_zone_ = sequence->zone();
sequence_ = sequence;
}
Isolate* isolate() const { return isolate_; }
CompilationInfo* info() const { return info_; }
ZonePool* zone_pool() const { return zone_pool_; }
@ -142,15 +144,8 @@ class PipelineData {
Zone* instruction_zone() const { return instruction_zone_; }
InstructionSequence* sequence() const { return sequence_; }
void set_sequence(InstructionSequence* sequence) {
DCHECK_EQ(nullptr, sequence_);
sequence_ = sequence;
}
Frame* frame() const { return frame_; }
void set_frame(Frame* frame) {
DCHECK_EQ(nullptr, frame_);
frame_ = frame;
}
RegisterAllocator* register_allocator() const { return register_allocator_; }
void DeleteGraphZone() {
// Destroy objects with destructors first.
@ -175,13 +170,33 @@ class PipelineData {
instruction_zone_ = nullptr;
sequence_ = nullptr;
frame_ = nullptr;
register_allocator_ = nullptr;
}
void InitializeInstructionSequence() {
DCHECK_EQ(nullptr, sequence_);
InstructionBlocks* instruction_blocks =
InstructionSequence::InstructionBlocksFor(instruction_zone(),
schedule());
sequence_ = new (instruction_zone())
InstructionSequence(instruction_zone(), instruction_blocks);
}
void InitializeRegisterAllocator(Zone* local_zone,
const RegisterConfiguration* config,
const char* debug_name) {
DCHECK_EQ(nullptr, register_allocator_);
DCHECK_EQ(nullptr, frame_);
frame_ = new (instruction_zone()) Frame();
register_allocator_ = new (instruction_zone())
RegisterAllocator(config, local_zone, frame(), sequence(), debug_name);
}
private:
Isolate* isolate_;
CompilationInfo* info_;
Zone* outer_zone_;
ZonePool* zone_pool_;
ZonePool* const zone_pool_;
PipelineStatistics* pipeline_statistics_;
bool compilation_failed_;
Handle<Code> code_;
@ -209,6 +224,7 @@ class PipelineData {
Zone* instruction_zone_;
InstructionSequence* sequence_;
Frame* frame_;
RegisterAllocator* register_allocator_;
DISALLOW_COPY_AND_ASSIGN(PipelineData);
};
@ -317,15 +333,6 @@ void Pipeline::Run(Arg0 arg_0) {
}
// TODO(dcarney): this one should be unecessary.
template <typename Phase, typename Arg0, typename Arg1>
void Pipeline::Run(Arg0 arg_0, Arg1 arg_1) {
PipelineRunScope scope(this->data_, Phase::phase_name());
Phase phase;
phase.Run(this->data_, scope.zone(), arg_0, arg_1);
}
struct GraphBuilderPhase {
static const char* phase_name() { return "graph builder"; }
@ -490,45 +497,74 @@ struct InstructionSelectionPhase {
};
// TODO(dcarney): break this up.
struct RegisterAllocationPhase {
static const char* phase_name() { return nullptr; }
struct MeetRegisterConstraintsPhase {
static const char* phase_name() { return "meet register constraints"; }
void Run(PipelineData* data, Zone* temp_zone) {
int node_count = data->sequence()->VirtualRegisterCount();
if (node_count > UnallocatedOperand::kMaxVirtualRegisters) {
data->set_compilation_failed();
return;
}
data->register_allocator()->MeetRegisterConstraints();
}
};
SmartArrayPointer<char> debug_name;
#ifdef DEBUG
if (data->info() != nullptr) {
debug_name = GetDebugName(data->info());
}
#endif
RegisterAllocator allocator(RegisterConfiguration::ArchDefault(), temp_zone,
data->frame(), data->sequence(),
debug_name.get());
struct ResolvePhisPhase {
static const char* phase_name() { return "resolve phis"; }
if (!allocator.Allocate(data->pipeline_statistics())) {
data->set_compilation_failed();
return;
}
void Run(PipelineData* data, Zone* temp_zone) {
data->register_allocator()->ResolvePhis();
}
};
if (FLAG_trace_turbo) {
OFStream os(stdout);
PrintableInstructionSequence printable = {
RegisterConfiguration::ArchDefault(), data->sequence()};
os << "----- Instruction sequence after register allocation -----\n"
<< printable;
}
if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
TurboCfgFile tcf(data->isolate());
tcf << AsC1VAllocator("CodeGen", &allocator);
}
struct BuildLiveRangesPhase {
static const char* phase_name() { return "build live ranges"; }
void Run(PipelineData* data, Zone* temp_zone) {
data->register_allocator()->BuildLiveRanges();
}
};
struct AllocateGeneralRegistersPhase {
static const char* phase_name() { return "allocate general registers"; }
void Run(PipelineData* data, Zone* temp_zone) {
data->register_allocator()->AllocateGeneralRegisters();
}
};
struct AllocateDoubleRegistersPhase {
static const char* phase_name() { return "allocate double registers"; }
void Run(PipelineData* data, Zone* temp_zone) {
data->register_allocator()->AllocateDoubleRegisters();
}
};
struct PopulatePointerMapsPhase {
static const char* phase_name() { return "populate pointer maps"; }
void Run(PipelineData* data, Zone* temp_zone) {
data->register_allocator()->PopulatePointerMaps();
}
};
struct ConnectRangesPhase {
static const char* phase_name() { return "connect ranges"; }
void Run(PipelineData* data, Zone* temp_zone) {
data->register_allocator()->ConnectRanges();
}
};
struct ResolveControlFlowPhase {
static const char* phase_name() { return "resolve control flow"; }
void Run(PipelineData* data, Zone* temp_zone) {
data->register_allocator()->ResolveControlFlow();
}
};
@ -536,9 +572,9 @@ struct RegisterAllocationPhase {
struct GenerateCodePhase {
static const char* phase_name() { return "generate code"; }
void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage,
CompilationInfo* info) {
CodeGenerator generator(data->frame(), linkage, data->sequence(), info);
void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) {
CodeGenerator generator(data->frame(), linkage, data->sequence(),
data->info());
data->set_code(generator.GenerateCode());
}
};
@ -600,6 +636,13 @@ struct VerifyGraphPhase {
};
void Pipeline::BeginPhaseKind(const char* phase_kind_name) {
if (data_->pipeline_statistics() != NULL) {
data_->pipeline_statistics()->BeginPhaseKind("phase_kind_name");
}
}
void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) {
if (FLAG_trace_turbo) {
Run<PrintGraphPhase>(phase);
@ -630,11 +673,13 @@ Handle<Code> Pipeline::GenerateCode() {
if (FLAG_turbo_stats) {
pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool));
pipeline_statistics->BeginPhaseKind("graph creation");
}
PipelineData data(info(), &zone_pool, pipeline_statistics.get());
PipelineData data(&zone_pool, info());
this->data_ = &data;
data.Initialize(pipeline_statistics.get());
BeginPhaseKind("graph creation");
if (FLAG_trace_turbo) {
OFStream os(stdout);
@ -679,9 +724,7 @@ Handle<Code> Pipeline::GenerateCode() {
RunPrintAndVerify("Typed");
}
if (!pipeline_statistics.is_empty()) {
data.pipeline_statistics()->BeginPhaseKind("lowering");
}
BeginPhaseKind("lowering");
if (info()->is_typing_enabled()) {
// Lower JSOperators where we can determine types.
@ -706,9 +749,7 @@ Handle<Code> Pipeline::GenerateCode() {
// TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
RunPrintAndVerify("Lowered generic", true);
if (!pipeline_statistics.is_empty()) {
data.pipeline_statistics()->BeginPhaseKind("block building");
}
BeginPhaseKind("block building");
data.source_positions()->RemoveDecorator();
@ -742,7 +783,8 @@ Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage,
Schedule* schedule) {
ZonePool zone_pool(isolate());
CHECK(SupportedBackend());
PipelineData data(graph, schedule, &zone_pool);
PipelineData data(&zone_pool, info());
data.Initialize(graph, schedule);
this->data_ = &data;
if (schedule == NULL) {
// TODO(rossberg): Should this really be untyped?
@ -766,6 +808,20 @@ Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage,
}
bool Pipeline::AllocateRegisters(const RegisterConfiguration* config,
InstructionSequence* sequence,
bool run_verifier) {
CompilationInfo info(sequence->zone()->isolate(), sequence->zone());
ZonePool zone_pool(sequence->zone()->isolate());
PipelineData data(&zone_pool, &info);
data.Initialize(sequence);
Pipeline pipeline(&info);
pipeline.data_ = &data;
pipeline.AllocateRegisters(config, run_verifier);
return !data.compilation_failed();
}
void Pipeline::GenerateCode(Linkage* linkage) {
PipelineData* data = this->data_;
@ -780,11 +836,7 @@ void Pipeline::GenerateCode(Linkage* linkage) {
data->schedule());
}
InstructionBlocks* instruction_blocks =
InstructionSequence::InstructionBlocksFor(data->instruction_zone(),
data->schedule());
data->set_sequence(new (data->instruction_zone()) InstructionSequence(
data->instruction_zone(), instruction_blocks));
data->InitializeInstructionSequence();
// Select and schedule instructions covering the scheduled graph.
Run<InstructionSelectionPhase>(linkage);
@ -797,36 +849,23 @@ void Pipeline::GenerateCode(Linkage* linkage) {
data->DeleteGraphZone();
if (data->pipeline_statistics() != NULL) {
data->pipeline_statistics()->BeginPhaseKind("register allocation");
}
BeginPhaseKind("register allocation");
bool run_verifier = false;
#ifdef DEBUG
// Don't track usage for this zone in compiler stats.
Zone verifier_zone(info()->isolate());
RegisterAllocatorVerifier verifier(
&verifier_zone, RegisterConfiguration::ArchDefault(), data->sequence());
run_verifier = true;
#endif
// Allocate registers.
data->set_frame(new (data->instruction_zone()) Frame);
Run<RegisterAllocationPhase>();
AllocateRegisters(RegisterConfiguration::ArchDefault(), run_verifier);
if (data->compilation_failed()) {
info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
return;
}
#ifdef DEBUG
verifier.VerifyAssignment();
verifier.VerifyGapMoves();
#endif
if (data->pipeline_statistics() != NULL) {
data->pipeline_statistics()->BeginPhaseKind("code generation");
}
BeginPhaseKind("code generation");
// Generate native sequence.
Run<GenerateCodePhase>(linkage, info());
Run<GenerateCodePhase>(linkage);
if (profiler_data != NULL) {
#if ENABLE_DISASSEMBLER
@ -838,6 +877,77 @@ void Pipeline::GenerateCode(Linkage* linkage) {
}
void Pipeline::AllocateRegisters(const RegisterConfiguration* config,
bool run_verifier) {
PipelineData* data = this->data_;
int node_count = data->sequence()->VirtualRegisterCount();
if (node_count > UnallocatedOperand::kMaxVirtualRegisters) {
data->set_compilation_failed();
return;
}
// Don't track usage for this zone in compiler stats.
SmartPointer<Zone> verifier_zone;
RegisterAllocatorVerifier* verifier = nullptr;
if (run_verifier) {
verifier_zone.Reset(new Zone(info()->isolate()));
verifier = new (verifier_zone.get()) RegisterAllocatorVerifier(
verifier_zone.get(), config, data->sequence());
}
SmartArrayPointer<char> debug_name;
#ifdef DEBUG
debug_name = GetDebugName(data->info());
#endif
ZonePool::Scope zone_scope(data->zone_pool());
data->InitializeRegisterAllocator(zone_scope.zone(), config,
debug_name.get());
Run<MeetRegisterConstraintsPhase>();
Run<ResolvePhisPhase>();
Run<BuildLiveRangesPhase>();
if (FLAG_trace_turbo) {
OFStream os(stdout);
PrintableInstructionSequence printable = {config, data->sequence()};
os << "----- Instruction sequence before register allocation -----\n"
<< printable;
}
DCHECK(!data->register_allocator()->ExistsUseWithoutDefinition());
Run<AllocateGeneralRegistersPhase>();
if (!data->register_allocator()->AllocationOk()) {
data->set_compilation_failed();
return;
}
Run<AllocateDoubleRegistersPhase>();
if (!data->register_allocator()->AllocationOk()) {
data->set_compilation_failed();
return;
}
Run<PopulatePointerMapsPhase>();
Run<ConnectRangesPhase>();
Run<ResolveControlFlowPhase>();
if (FLAG_trace_turbo) {
OFStream os(stdout);
PrintableInstructionSequence printable = {config, data->sequence()};
os << "----- Instruction sequence after register allocation -----\n"
<< printable;
}
if (verifier != nullptr) {
verifier->VerifyAssignment();
verifier->VerifyGapMoves();
}
if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
TurboCfgFile tcf(data->isolate());
tcf << AsC1VAllocator("CodeGen", data->register_allocator());
}
}
void Pipeline::SetUp() {
InstructionOperand::SetUpCaches();
}

View File

@ -18,8 +18,10 @@ namespace compiler {
// Clients of this interface shouldn't depend on lots of compiler internals.
class Graph;
class InstructionSequence;
class Linkage;
class PipelineData;
class RegisterConfiguration;
class Schedule;
class Pipeline {
@ -34,6 +36,10 @@ class Pipeline {
Handle<Code> GenerateCodeForMachineGraph(Linkage* linkage, Graph* graph,
Schedule* schedule = NULL);
static bool AllocateRegisters(const RegisterConfiguration* config,
InstructionSequence* sequence,
bool run_verifier);
static inline bool SupportedBackend() { return V8_TURBOFAN_BACKEND != 0; }
static inline bool SupportedTarget() { return V8_TURBOFAN_TARGET != 0; }
@ -49,14 +55,15 @@ class Pipeline {
void Run();
template <typename Phase, typename Arg0>
void Run(Arg0 arg_0);
template <typename Phase, typename Arg0, typename Arg1>
void Run(Arg0 arg_0, Arg1 arg_1);
CompilationInfo* info() const { return info_; }
Isolate* isolate() { return info_->isolate(); }
void BeginPhaseKind(const char* phase_kind);
void RunPrintAndVerify(const char* phase, bool untyped = false);
void GenerateCode(Linkage* linkage);
void AllocateRegisters(const RegisterConfiguration* config,
bool run_verifier);
};
} // namespace compiler

View File

@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "src/compiler/linkage.h"
#include "src/compiler/pipeline-statistics.h"
#include "src/compiler/register-allocator.h"
#include "src/string-stream.h"
@ -536,6 +535,12 @@ RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config,
// when allocating local arrays.
DCHECK(this->config()->num_double_registers() >=
this->config()->num_general_registers());
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());
frame->SetAllocatedRegisters(assigned_registers_);
frame->SetAllocatedDoubleRegisters(assigned_double_registers_);
}
@ -1116,59 +1121,6 @@ void RegisterAllocator::ResolvePhis(const InstructionBlock* block) {
}
bool RegisterAllocator::Allocate(PipelineStatistics* stats) {
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());
{
PhaseScope phase_scope(stats, "meet register constraints");
MeetRegisterConstraints();
}
{
PhaseScope phase_scope(stats, "resolve phis");
ResolvePhis();
}
{
PhaseScope phase_scope(stats, "build live ranges");
BuildLiveRanges();
}
if (FLAG_trace_turbo) {
OFStream os(stdout);
PrintableInstructionSequence printable = {config(), code()};
os << "----- Instruction sequence before register allocation -----\n"
<< printable;
}
// This can be triggered in debug mode.
DCHECK(!ExistsUseWithoutDefinition());
{
PhaseScope phase_scope(stats, "allocate general registers");
AllocateGeneralRegisters();
}
if (!AllocationOk()) return false;
{
PhaseScope phase_scope(stats, "allocate double registers");
AllocateDoubleRegisters();
}
if (!AllocationOk()) return false;
{
PhaseScope phase_scope(stats, "populate pointer maps");
PopulatePointerMaps();
}
{
PhaseScope phase_scope(stats, "connect ranges");
ConnectRanges();
}
{
PhaseScope phase_scope(stats, "resolve control flow");
ResolveControlFlow();
}
frame()->SetAllocatedRegisters(assigned_registers_);
frame()->SetAllocatedDoubleRegisters(assigned_double_registers_);
return true;
}
void RegisterAllocator::MeetRegisterConstraints() {
for (auto block : code()->instruction_blocks()) {
MeetRegisterConstraints(block);

View File

@ -12,8 +12,6 @@ namespace v8 {
namespace internal {
namespace compiler {
class PipelineStatistics;
enum RegisterKind {
UNALLOCATED_REGISTERS,
GENERAL_REGISTERS,
@ -320,17 +318,14 @@ class LiveRange FINAL : public ZoneObject {
};
class RegisterAllocator FINAL {
class RegisterAllocator FINAL : public ZoneObject {
public:
explicit RegisterAllocator(const RegisterConfiguration* config,
Zone* local_zone, Frame* frame,
InstructionSequence* code,
const char* debug_name = nullptr);
bool Allocate(PipelineStatistics* stats = NULL);
bool AllocationOk() { return allocation_ok_; }
BitVector* assigned_registers() { return assigned_registers_; }
BitVector* assigned_double_registers() { return assigned_double_registers_; }
const ZoneList<LiveRange*>& live_ranges() const { return live_ranges_; }
const ZoneVector<LiveRange*>& fixed_live_ranges() const {
@ -343,6 +338,30 @@ class RegisterAllocator FINAL {
// This zone is for datastructures only needed during register allocation.
Zone* local_zone() const { return local_zone_; }
// Phase 1 : insert moves to account for fixed register operands.
void MeetRegisterConstraints();
// Phase 2: deconstruct SSA by inserting moves in successors and the headers
// of blocks containing phis.
void ResolvePhis();
// Phase 3: compute liveness of all virtual register.
void BuildLiveRanges();
bool ExistsUseWithoutDefinition();
// Phase 4: compute register assignments.
void AllocateGeneralRegisters();
void AllocateDoubleRegisters();
// Phase 5: compute values for pointer maps.
void PopulatePointerMaps(); // TODO(titzer): rename to PopulateReferenceMaps.
// Phase 6: reconnect split ranges with moves.
void ConnectRanges();
// Phase 7: insert moves to connect ranges across basic blocks.
void ResolveControlFlow();
private:
int GetVirtualRegister() {
int vreg = code()->NextVirtualRegister();
@ -365,18 +384,13 @@ class RegisterAllocator FINAL {
// allocation.
Zone* code_zone() const { return code()->zone(); }
BitVector* assigned_registers() { return assigned_registers_; }
BitVector* assigned_double_registers() { return assigned_double_registers_; }
#ifdef DEBUG
void Verify() const;
#endif
void MeetRegisterConstraints();
void ResolvePhis();
void BuildLiveRanges();
void AllocateGeneralRegisters();
void AllocateDoubleRegisters();
void ConnectRanges();
void ResolveControlFlow();
void PopulatePointerMaps(); // TODO(titzer): rename to PopulateReferenceMaps.
void AllocateRegisters();
bool CanEagerlyResolveControlFlow(const InstructionBlock* block) const;
bool SafePointsAreInOrder() const;
@ -388,7 +402,6 @@ class RegisterAllocator FINAL {
bool IsOutputRegisterOf(Instruction* instr, int index);
bool IsOutputDoubleRegisterOf(Instruction* instr, int index);
void ProcessInstructions(const InstructionBlock* block, BitVector* live);
bool ExistsUseWithoutDefinition();
void MeetRegisterConstraints(const InstructionBlock* block);
void MeetConstraintsBetween(Instruction* first, Instruction* second,
int gap_index);

View File

@ -64,38 +64,10 @@ class DeoptCodegenTester {
os << *schedule;
}
// Initialize the codegen and generate code.
Linkage* linkage = new (scope_->main_zone()) Linkage(info.zone(), &info);
InstructionBlocks* instruction_blocks =
TestInstrSeq::InstructionBlocksFor(scope_->main_zone(), schedule);
code = new (scope_->main_zone())
TestInstrSeq(scope_->main_zone(), instruction_blocks);
SourcePositionTable source_positions(graph);
InstructionSelector selector(scope_->main_zone(), graph, linkage, code,
schedule, &source_positions);
selector.SelectInstructions();
if (FLAG_trace_turbo) {
PrintableInstructionSequence printable = {
RegisterConfiguration::ArchDefault(), code};
os << "----- Instruction sequence before register allocation -----\n"
<< printable;
}
Frame frame;
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"
<< printable;
}
compiler::CodeGenerator generator(&frame, linkage, code, &info);
result_code = generator.GenerateCode();
Pipeline pipeline(&info);
result_code =
pipeline.GenerateCodeForMachineGraph(linkage, graph, schedule);
#ifdef OBJECT_PRINT
if (FLAG_print_opt_code || FLAG_trace_turbo) {

View File

@ -3,8 +3,8 @@
// found in the LICENSE file.
#include "src/base/utils/random-number-generator.h"
#include "src/compiler/register-allocator.h"
#include "src/compiler/register-allocator-verifier.h"
#include "src/compiler/instruction.h"
#include "src/compiler/pipeline.h"
#include "test/unittests/test-utils.h"
#include "testing/gmock/include/gmock/gmock.h"
@ -167,14 +167,6 @@ class RegisterAllocatorTest : public TestWithZone {
return sequence_;
}
RegisterAllocator* allocator() {
if (allocator_.is_empty()) {
allocator_.Reset(
new RegisterAllocator(config(), zone(), frame(), sequence()));
}
return allocator_.get();
}
void StartLoop(int loop_blocks) {
CHECK(current_block_ == nullptr);
if (!loop_blocks_.empty()) {
@ -227,20 +219,7 @@ class RegisterAllocatorTest : public TestWithZone {
void Allocate() {
CHECK_EQ(nullptr, current_block_);
WireBlocks();
RegisterAllocatorVerifier verifier(zone(), config(), sequence());
if (FLAG_trace_alloc || FLAG_trace_turbo) {
OFStream os(stdout);
PrintableInstructionSequence printable = {config(), sequence()};
os << "Before: " << std::endl << printable << std::endl;
}
allocator()->Allocate();
if (FLAG_trace_alloc || FLAG_trace_turbo) {
OFStream os(stdout);
PrintableInstructionSequence printable = {config(), sequence()};
os << "After: " << std::endl << printable << std::endl;
}
verifier.VerifyAssignment();
verifier.VerifyGapMoves();
Pipeline::AllocateRegisters(config(), sequence(), true);
}
TestOperand Imm(int32_t imm = 0) {
@ -520,7 +499,6 @@ class RegisterAllocatorTest : public TestWithZone {
SmartPointer<RegisterConfiguration> config_;
Frame* frame_;
SmartPointer<RegisterAllocator> allocator_;
InstructionSequence* sequence_;
int num_general_registers_;
int num_double_registers_;