Commit 472cb045 authored by bbudge's avatar bbudge Committed by Commit bot

[Turbofan] Reduce register allocation work when we can.

- Track representations of virtual registers in InstructionSequence.
- Skip extra aliasing work when no floats or SIMD registers are used.

LOG=N
BUG=v8:4124

Review-Url: https://codereview.chromium.org/2468233004
Cr-Commit-Position: refs/heads/master@{#40870}
parent 0700bc1b
......@@ -814,6 +814,7 @@ InstructionSequence::InstructionSequence(Isolate* isolate,
next_virtual_register_(0),
reference_maps_(zone()),
representations_(zone()),
representation_mask_(0),
deoptimization_entries_(zone()),
current_block_(nullptr) {}
......@@ -919,6 +920,7 @@ void InstructionSequence::MarkAsRepresentation(MachineRepresentation rep,
DCHECK_IMPLIES(representations_[virtual_register] != rep,
representations_[virtual_register] == DefaultRepresentation());
representations_[virtual_register] = rep;
representation_mask_ |= 1 << static_cast<int>(rep);
}
int InstructionSequence::AddDeoptimizationEntry(
......
......@@ -1389,6 +1389,7 @@ class V8_EXPORT_PRIVATE InstructionSequence final
}
MachineRepresentation GetRepresentation(int virtual_register) const;
void MarkAsRepresentation(MachineRepresentation rep, int virtual_register);
int representation_mask() const { return representation_mask_; }
bool IsReference(int virtual_register) const {
return CanBeTaggedPointer(GetRepresentation(virtual_register));
......@@ -1396,14 +1397,6 @@ class V8_EXPORT_PRIVATE InstructionSequence final
bool IsFP(int virtual_register) const {
return IsFloatingPoint(GetRepresentation(virtual_register));
}
bool IsFloat(int virtual_register) const {
return GetRepresentation(virtual_register) ==
MachineRepresentation::kFloat32;
}
bool IsDouble(int virtual_register) const {
return GetRepresentation(virtual_register) ==
MachineRepresentation::kFloat64;
}
Instruction* GetBlockStart(RpoNumber rpo) const;
......@@ -1523,6 +1516,7 @@ class V8_EXPORT_PRIVATE InstructionSequence final
int next_virtual_register_;
ReferenceMapDeque reference_maps_;
ZoneVector<MachineRepresentation> representations_;
int representation_mask_;
DeoptimizationVector deoptimization_entries_;
// Used at construction time
......
......@@ -19,6 +19,11 @@ namespace compiler {
namespace {
static const int kFloatRepBit =
1 << static_cast<int>(MachineRepresentation::kFloat32);
static const int kSimd128RepBit =
1 << static_cast<int>(MachineRepresentation::kSimd128);
void RemoveElement(ZoneVector<LiveRange*>* v, LiveRange* range) {
auto it = std::find(v->begin(), v->end(), range);
DCHECK(it != v->end());
......@@ -2022,6 +2027,13 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
int block_start = block->first_instruction_index();
LifetimePosition block_start_position =
LifetimePosition::GapFromInstructionIndex(block_start);
bool fixed_float_live_ranges = false;
bool fixed_simd128_live_ranges = false;
if (!kSimpleFPAliasing) {
int mask = data()->code()->representation_mask();
fixed_float_live_ranges = (mask & kFloatRepBit) != 0;
fixed_simd128_live_ranges = (mask & kSimd128RepBit) != 0;
}
for (int index = block->last_instruction_index(); index >= block_start;
index--) {
......@@ -2081,22 +2093,27 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
}
// Clobber fixed float registers on archs with non-simple aliasing.
if (!kSimpleFPAliasing) {
for (int i = 0; i < config()->num_allocatable_float_registers(); ++i) {
// Add a UseInterval for all FloatRegisters. See comment above for
// general registers.
int code = config()->GetAllocatableFloatCode(i);
TopLevelLiveRange* range =
FixedFPLiveRangeFor(code, MachineRepresentation::kFloat32);
range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone());
if (fixed_float_live_ranges) {
for (int i = 0; i < config()->num_allocatable_float_registers();
++i) {
// Add a UseInterval for all FloatRegisters. See comment above for
// general registers.
int code = config()->GetAllocatableFloatCode(i);
TopLevelLiveRange* range =
FixedFPLiveRangeFor(code, MachineRepresentation::kFloat32);
range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone());
}
}
for (int i = 0; i < config()->num_allocatable_simd128_registers();
++i) {
int code = config()->GetAllocatableSimd128Code(i);
TopLevelLiveRange* range =
FixedFPLiveRangeFor(code, MachineRepresentation::kSimd128);
range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone());
if (fixed_simd128_live_ranges) {
for (int i = 0; i < config()->num_allocatable_simd128_registers();
++i) {
int code = config()->GetAllocatableSimd128Code(i);
TopLevelLiveRange* range =
FixedFPLiveRangeFor(code, MachineRepresentation::kSimd128);
range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone());
}
}
}
}
......@@ -2210,7 +2227,6 @@ void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block,
}
}
void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block,
BitVector* live) {
for (PhiInstruction* phi : block->phis()) {
......@@ -2520,7 +2536,13 @@ RegisterAllocator::RegisterAllocator(RegisterAllocationData* data,
num_allocatable_registers_(
GetAllocatableRegisterCount(data->config(), kind)),
allocatable_register_codes_(
GetAllocatableRegisterCodes(data->config(), kind)) {}
GetAllocatableRegisterCodes(data->config(), kind)),
check_fp_aliasing_(false) {
if (!kSimpleFPAliasing && kind == FP_REGISTERS) {
check_fp_aliasing_ = (data->code()->representation_mask() &
(kFloatRepBit | kSimd128RepBit)) != 0;
}
}
LifetimePosition RegisterAllocator::GetSplitPositionForInstruction(
const LiveRange* range, int instruction_index) {
......@@ -2747,7 +2769,7 @@ void LinearScanAllocator::AllocateRegisters() {
for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) {
if (current != nullptr) AddToInactive(current);
}
if (!kSimpleFPAliasing) {
if (!kSimpleFPAliasing && check_fp_aliasing()) {
for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) {
if (current != nullptr) AddToInactive(current);
}
......@@ -2969,7 +2991,7 @@ void LinearScanAllocator::FindFreeRegistersForRange(
for (LiveRange* cur_active : active_live_ranges()) {
int cur_reg = cur_active->assigned_register();
if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
if (kSimpleFPAliasing || !check_fp_aliasing()) {
positions[cur_reg] = LifetimePosition::GapFromInstructionIndex(0);
TRACE("Register %s is free until pos %d (1)\n", RegisterName(cur_reg),
LifetimePosition::GapFromInstructionIndex(0).value());
......@@ -2990,7 +3012,7 @@ void LinearScanAllocator::FindFreeRegistersForRange(
LifetimePosition next_intersection = cur_inactive->FirstIntersection(range);
if (!next_intersection.IsValid()) continue;
int cur_reg = cur_inactive->assigned_register();
if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
if (kSimpleFPAliasing || !check_fp_aliasing()) {
positions[cur_reg] = Min(positions[cur_reg], next_intersection);
TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg),
Min(positions[cur_reg], next_intersection).value());
......@@ -3154,7 +3176,7 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) {
int cur_reg = range->assigned_register();
bool is_fixed_or_cant_spill =
range->TopLevel()->IsFixed() || !range->CanBeSpilled(current->Start());
if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
if (kSimpleFPAliasing || !check_fp_aliasing()) {
if (is_fixed_or_cant_spill) {
block_pos[cur_reg] = use_pos[cur_reg] =
LifetimePosition::GapFromInstructionIndex(0);
......@@ -3186,7 +3208,7 @@ void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) {
if (!next_intersection.IsValid()) continue;
int cur_reg = range->assigned_register();
bool is_fixed = range->TopLevel()->IsFixed();
if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
if (kSimpleFPAliasing || !check_fp_aliasing()) {
if (is_fixed) {
block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection);
use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]);
......@@ -3260,7 +3282,7 @@ void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) {
LifetimePosition split_pos = current->Start();
for (size_t i = 0; i < active_live_ranges().size(); ++i) {
LiveRange* range = active_live_ranges()[i];
if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
if (kSimpleFPAliasing || !check_fp_aliasing()) {
if (range->assigned_register() != reg) continue;
} else {
if (!data()->config()->AreAliases(current->representation(), reg,
......@@ -3295,7 +3317,7 @@ void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) {
LiveRange* range = inactive_live_ranges()[i];
DCHECK(range->End() > current->Start());
if (range->TopLevel()->IsFixed()) continue;
if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
if (kSimpleFPAliasing || !check_fp_aliasing()) {
if (range->assigned_register() != reg) continue;
} else {
if (!data()->config()->AreAliases(current->representation(), reg,
......
......@@ -982,6 +982,8 @@ class RegisterAllocator : public ZoneObject {
const int* allocatable_register_codes() const {
return allocatable_register_codes_;
}
// Returns true iff. we must check float register aliasing.
bool check_fp_aliasing() const { return check_fp_aliasing_; }
// TODO(mtrofin): explain why splitting in gap START is always OK.
LifetimePosition GetSplitPositionForInstruction(const LiveRange* range,
......@@ -1032,6 +1034,7 @@ class RegisterAllocator : public ZoneObject {
const int num_registers_;
int num_allocatable_registers_;
const int* allocatable_register_codes_;
bool check_fp_aliasing_;
private:
bool no_combining_;
......
......@@ -29,9 +29,14 @@ enum class MachineRepresentation : uint8_t {
kFloat32,
kFloat64,
kSimd128,
kFirstFPRepresentation = kFloat32
kFirstFPRepresentation = kFloat32,
kLastRepresentation = kSimd128
};
static_assert(static_cast<int>(MachineRepresentation::kLastRepresentation) <
kIntSize * kBitsPerByte,
"Bit masks of MachineRepresentation should fit in an int");
const char* MachineReprToString(MachineRepresentation);
enum class MachineSemantic : uint8_t {
......
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