Commit 032191e9 authored by Dan Carney's avatar Dan Carney

[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}
parent 7e2ebd4c
This diff is collapsed.
......@@ -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
......
......@@ -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);
......
......@@ -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);
......
......@@ -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) {
......
......@@ -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_;
......
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