PPC/S390: [regalloc] Improve gap resolver algorithm
Port: a77dd89e4c
Bug: v8:5210, chromium:1269989, chromium:1313647
Change-Id: I91cb97d7d807c70939a8da4b80386d5aed5f3c8b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3677453
Commit-Queue: Milad Farazmand <mfarazma@redhat.com>
Reviewed-by: Thibaud Michaud <thibaudm@chromium.org>
Reviewed-by: Junliang Yan <junyan@redhat.com>
Cr-Commit-Position: refs/heads/main@{#80873}
This commit is contained in:
parent
b1f896337d
commit
5c445ebbea
@ -1376,6 +1376,11 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
|||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MoveCycleState {
|
||||||
|
// Whether a move in the cycle needs a double scratch register.
|
||||||
|
bool pending_double_scratch_register_use = false;
|
||||||
|
};
|
||||||
|
|
||||||
#define ACCESS_MASM(masm) masm->
|
#define ACCESS_MASM(masm) masm->
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -1786,6 +1786,11 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
|||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MoveCycleState {
|
||||||
|
// Whether a move in the cycle needs a double scratch register.
|
||||||
|
bool pending_double_scratch_register_use = false;
|
||||||
|
};
|
||||||
|
|
||||||
#define ACCESS_MASM(masm) masm->
|
#define ACCESS_MASM(masm) masm->
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -4277,11 +4277,90 @@ void CodeGenerator::PrepareForDeoptimizationExits(
|
|||||||
__ CheckTrampolinePoolQuick(total_size);
|
__ CheckTrampolinePoolQuick(total_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CodeGenerator::MoveToTempLocation(InstructionOperand* source) {
|
||||||
|
// Must be kept in sync with {MoveTempLocationTo}.
|
||||||
|
auto rep = LocationOperand::cast(source)->representation();
|
||||||
|
if (!IsFloatingPoint(rep) ||
|
||||||
|
((IsFloatingPoint(rep) &&
|
||||||
|
!move_cycle_.pending_double_scratch_register_use))) {
|
||||||
|
// The scratch register for this rep is available.
|
||||||
|
int scratch_reg_code =
|
||||||
|
!IsFloatingPoint(rep) ? kScratchReg.code() : kScratchDoubleReg.code();
|
||||||
|
AllocatedOperand scratch(LocationOperand::REGISTER, rep, scratch_reg_code);
|
||||||
|
DCHECK(!AreAliased(kScratchReg, r0, ip));
|
||||||
|
AssembleMove(source, &scratch);
|
||||||
|
} else {
|
||||||
|
DCHECK(!source->IsRegister() && !source->IsStackSlot());
|
||||||
|
// The scratch register is blocked by pending moves. Use the stack instead.
|
||||||
|
int new_slots = ElementSizeInPointers(rep);
|
||||||
|
PPCOperandConverter g(this, nullptr);
|
||||||
|
if (source->IsFloatStackSlot() || source->IsDoubleStackSlot()) {
|
||||||
|
__ LoadU64(r0, g.ToMemOperand(source), r0);
|
||||||
|
__ Push(r0);
|
||||||
|
} else {
|
||||||
|
// Bump the stack pointer and assemble the move.
|
||||||
|
int last_frame_slot_id =
|
||||||
|
frame_access_state_->frame()->GetTotalFrameSlotCount() - 1;
|
||||||
|
int sp_delta = frame_access_state_->sp_delta();
|
||||||
|
int temp_slot = last_frame_slot_id + sp_delta + new_slots;
|
||||||
|
__ addi(sp, sp, Operand(-(new_slots * kSystemPointerSize)));
|
||||||
|
AllocatedOperand temp(LocationOperand::STACK_SLOT, rep, temp_slot);
|
||||||
|
AssembleMove(source, &temp);
|
||||||
|
}
|
||||||
|
frame_access_state()->IncreaseSPDelta(new_slots);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeGenerator::MoveTempLocationTo(InstructionOperand* dest,
|
||||||
|
MachineRepresentation rep) {
|
||||||
|
if (!IsFloatingPoint(rep) ||
|
||||||
|
((IsFloatingPoint(rep) &&
|
||||||
|
!move_cycle_.pending_double_scratch_register_use))) {
|
||||||
|
int scratch_reg_code =
|
||||||
|
!IsFloatingPoint(rep) ? kScratchReg.code() : kScratchDoubleReg.code();
|
||||||
|
AllocatedOperand scratch(LocationOperand::REGISTER, rep, scratch_reg_code);
|
||||||
|
DCHECK(!AreAliased(kScratchReg, r0, ip));
|
||||||
|
AssembleMove(&scratch, dest);
|
||||||
|
} else {
|
||||||
|
DCHECK(!dest->IsRegister() && !dest->IsStackSlot());
|
||||||
|
PPCOperandConverter g(this, nullptr);
|
||||||
|
int new_slots = ElementSizeInPointers(rep);
|
||||||
|
frame_access_state()->IncreaseSPDelta(-new_slots);
|
||||||
|
if (dest->IsFloatStackSlot() || dest->IsDoubleStackSlot()) {
|
||||||
|
UseScratchRegisterScope temps(tasm());
|
||||||
|
Register scratch = temps.Acquire();
|
||||||
|
__ Pop(scratch);
|
||||||
|
__ StoreU64(scratch, g.ToMemOperand(dest), r0);
|
||||||
|
} else {
|
||||||
|
int last_frame_slot_id =
|
||||||
|
frame_access_state_->frame()->GetTotalFrameSlotCount() - 1;
|
||||||
|
int sp_delta = frame_access_state_->sp_delta();
|
||||||
|
int temp_slot = last_frame_slot_id + sp_delta + new_slots;
|
||||||
|
AllocatedOperand temp(LocationOperand::STACK_SLOT, rep, temp_slot);
|
||||||
|
AssembleMove(&temp, dest);
|
||||||
|
__ addi(sp, sp, Operand(new_slots * kSystemPointerSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
move_cycle_ = MoveCycleState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeGenerator::SetPendingMove(MoveOperands* move) {
|
||||||
|
if (move->source().IsFPStackSlot() && !move->destination().IsFPRegister()) {
|
||||||
|
move_cycle_.pending_double_scratch_register_use = true;
|
||||||
|
} else if (move->source().IsConstant() &&
|
||||||
|
(move->destination().IsDoubleStackSlot() ||
|
||||||
|
move->destination().IsFloatStackSlot())) {
|
||||||
|
move_cycle_.pending_double_scratch_register_use = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CodeGenerator::AssembleMove(InstructionOperand* source,
|
void CodeGenerator::AssembleMove(InstructionOperand* source,
|
||||||
InstructionOperand* destination) {
|
InstructionOperand* destination) {
|
||||||
PPCOperandConverter g(this, nullptr);
|
PPCOperandConverter g(this, nullptr);
|
||||||
// Dispatch on the source and destination operand kinds. Not all
|
// Dispatch on the source and destination operand kinds. Not all
|
||||||
// combinations are possible.
|
// combinations are possible.
|
||||||
|
// If a move type needs the scratch register, this also needs to be recorded
|
||||||
|
// in {SetPendingMove} to avoid conflicts with the gap resolver.
|
||||||
if (source->IsRegister()) {
|
if (source->IsRegister()) {
|
||||||
DCHECK(destination->IsRegister() || destination->IsStackSlot());
|
DCHECK(destination->IsRegister() || destination->IsStackSlot());
|
||||||
Register src = g.ToRegister(source);
|
Register src = g.ToRegister(source);
|
||||||
@ -4296,15 +4375,14 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
|||||||
if (destination->IsRegister()) {
|
if (destination->IsRegister()) {
|
||||||
__ LoadU64(g.ToRegister(destination), src, r0);
|
__ LoadU64(g.ToRegister(destination), src, r0);
|
||||||
} else {
|
} else {
|
||||||
Register temp = kScratchReg;
|
Register temp = ip;
|
||||||
__ LoadU64(temp, src, r0);
|
__ LoadU64(temp, src, r0);
|
||||||
__ StoreU64(temp, g.ToMemOperand(destination), r0);
|
__ StoreU64(temp, g.ToMemOperand(destination), r0);
|
||||||
}
|
}
|
||||||
} else if (source->IsConstant()) {
|
} else if (source->IsConstant()) {
|
||||||
Constant src = g.ToConstant(source);
|
Constant src = g.ToConstant(source);
|
||||||
if (destination->IsRegister() || destination->IsStackSlot()) {
|
if (destination->IsRegister() || destination->IsStackSlot()) {
|
||||||
Register dst =
|
Register dst = destination->IsRegister() ? g.ToRegister(destination) : ip;
|
||||||
destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
|
|
||||||
switch (src.type()) {
|
switch (src.type()) {
|
||||||
case Constant::kInt32:
|
case Constant::kInt32:
|
||||||
#if V8_ENABLE_WEBASSEMBLY && !V8_TARGET_ARCH_PPC64
|
#if V8_ENABLE_WEBASSEMBLY && !V8_TARGET_ARCH_PPC64
|
||||||
@ -4392,7 +4470,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
|||||||
? base::Double(static_cast<double>(src.ToFloat32()))
|
? base::Double(static_cast<double>(src.ToFloat32()))
|
||||||
: base::Double(src.ToFloat64());
|
: base::Double(src.ToFloat64());
|
||||||
#endif
|
#endif
|
||||||
__ LoadDoubleLiteral(dst, value, kScratchReg);
|
__ LoadDoubleLiteral(dst, value, r0);
|
||||||
if (destination->IsDoubleStackSlot()) {
|
if (destination->IsDoubleStackSlot()) {
|
||||||
__ StoreF64(dst, g.ToMemOperand(destination), r0);
|
__ StoreF64(dst, g.ToMemOperand(destination), r0);
|
||||||
} else if (destination->IsFloatStackSlot()) {
|
} else if (destination->IsFloatStackSlot()) {
|
||||||
|
@ -3584,11 +3584,88 @@ void CodeGenerator::FinishCode() {}
|
|||||||
void CodeGenerator::PrepareForDeoptimizationExits(
|
void CodeGenerator::PrepareForDeoptimizationExits(
|
||||||
ZoneDeque<DeoptimizationExit*>* exits) {}
|
ZoneDeque<DeoptimizationExit*>* exits) {}
|
||||||
|
|
||||||
|
void CodeGenerator::MoveToTempLocation(InstructionOperand* source) {
|
||||||
|
// Must be kept in sync with {MoveTempLocationTo}.
|
||||||
|
auto rep = LocationOperand::cast(source)->representation();
|
||||||
|
if (!IsFloatingPoint(rep) ||
|
||||||
|
((IsFloatingPoint(rep) &&
|
||||||
|
!move_cycle_.pending_double_scratch_register_use))) {
|
||||||
|
// The scratch register for this rep is available.
|
||||||
|
int scratch_reg_code =
|
||||||
|
!IsFloatingPoint(rep) ? kScratchReg.code() : kScratchDoubleReg.code();
|
||||||
|
AllocatedOperand scratch(LocationOperand::REGISTER, rep, scratch_reg_code);
|
||||||
|
DCHECK(!AreAliased(kScratchReg, r0, r1));
|
||||||
|
AssembleMove(source, &scratch);
|
||||||
|
} else {
|
||||||
|
DCHECK(!source->IsRegister() && !source->IsStackSlot());
|
||||||
|
// The scratch register is blocked by pending moves. Use the stack instead.
|
||||||
|
int new_slots = ElementSizeInPointers(rep);
|
||||||
|
S390OperandConverter g(this, nullptr);
|
||||||
|
if (source->IsFloatStackSlot() || source->IsDoubleStackSlot()) {
|
||||||
|
__ LoadU64(r1, g.ToMemOperand(source));
|
||||||
|
__ Push(r1);
|
||||||
|
} else {
|
||||||
|
// Bump the stack pointer and assemble the move.
|
||||||
|
int last_frame_slot_id =
|
||||||
|
frame_access_state_->frame()->GetTotalFrameSlotCount() - 1;
|
||||||
|
int sp_delta = frame_access_state_->sp_delta();
|
||||||
|
int temp_slot = last_frame_slot_id + sp_delta + new_slots;
|
||||||
|
__ lay(sp, MemOperand(sp, -(new_slots * kSystemPointerSize)));
|
||||||
|
AllocatedOperand temp(LocationOperand::STACK_SLOT, rep, temp_slot);
|
||||||
|
AssembleMove(source, &temp);
|
||||||
|
}
|
||||||
|
frame_access_state()->IncreaseSPDelta(new_slots);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeGenerator::MoveTempLocationTo(InstructionOperand* dest,
|
||||||
|
MachineRepresentation rep) {
|
||||||
|
if (!IsFloatingPoint(rep) ||
|
||||||
|
((IsFloatingPoint(rep) &&
|
||||||
|
!move_cycle_.pending_double_scratch_register_use))) {
|
||||||
|
int scratch_reg_code =
|
||||||
|
!IsFloatingPoint(rep) ? kScratchReg.code() : kScratchDoubleReg.code();
|
||||||
|
AllocatedOperand scratch(LocationOperand::REGISTER, rep, scratch_reg_code);
|
||||||
|
DCHECK(!AreAliased(kScratchReg, r0, r1));
|
||||||
|
AssembleMove(&scratch, dest);
|
||||||
|
} else {
|
||||||
|
DCHECK(!dest->IsRegister() && !dest->IsStackSlot());
|
||||||
|
S390OperandConverter g(this, nullptr);
|
||||||
|
int new_slots = ElementSizeInPointers(rep);
|
||||||
|
frame_access_state()->IncreaseSPDelta(-new_slots);
|
||||||
|
if (dest->IsFloatStackSlot() || dest->IsDoubleStackSlot()) {
|
||||||
|
__ Pop(r1);
|
||||||
|
__ StoreU64(r1, g.ToMemOperand(dest));
|
||||||
|
} else {
|
||||||
|
int last_frame_slot_id =
|
||||||
|
frame_access_state_->frame()->GetTotalFrameSlotCount() - 1;
|
||||||
|
int sp_delta = frame_access_state_->sp_delta();
|
||||||
|
int temp_slot = last_frame_slot_id + sp_delta + new_slots;
|
||||||
|
AllocatedOperand temp(LocationOperand::STACK_SLOT, rep, temp_slot);
|
||||||
|
AssembleMove(&temp, dest);
|
||||||
|
__ lay(sp, MemOperand(sp, new_slots * kSystemPointerSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
move_cycle_ = MoveCycleState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeGenerator::SetPendingMove(MoveOperands* move) {
|
||||||
|
if (move->source().IsFPStackSlot() && !move->destination().IsFPRegister()) {
|
||||||
|
move_cycle_.pending_double_scratch_register_use = true;
|
||||||
|
} else if (move->source().IsConstant() &&
|
||||||
|
(move->destination().IsDoubleStackSlot() ||
|
||||||
|
move->destination().IsFloatStackSlot())) {
|
||||||
|
move_cycle_.pending_double_scratch_register_use = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CodeGenerator::AssembleMove(InstructionOperand* source,
|
void CodeGenerator::AssembleMove(InstructionOperand* source,
|
||||||
InstructionOperand* destination) {
|
InstructionOperand* destination) {
|
||||||
S390OperandConverter g(this, nullptr);
|
S390OperandConverter g(this, nullptr);
|
||||||
// Dispatch on the source and destination operand kinds. Not all
|
// Dispatch on the source and destination operand kinds. Not all
|
||||||
// combinations are possible.
|
// combinations are possible.
|
||||||
|
// If a move type needs the scratch register, this also needs to be recorded
|
||||||
|
// in {SetPendingMove} to avoid conflicts with the gap resolver.
|
||||||
if (source->IsRegister()) {
|
if (source->IsRegister()) {
|
||||||
DCHECK(destination->IsRegister() || destination->IsStackSlot());
|
DCHECK(destination->IsRegister() || destination->IsStackSlot());
|
||||||
Register src = g.ToRegister(source);
|
Register src = g.ToRegister(source);
|
||||||
@ -3603,15 +3680,14 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
|||||||
if (destination->IsRegister()) {
|
if (destination->IsRegister()) {
|
||||||
__ LoadU64(g.ToRegister(destination), src);
|
__ LoadU64(g.ToRegister(destination), src);
|
||||||
} else {
|
} else {
|
||||||
Register temp = kScratchReg;
|
Register temp = r1;
|
||||||
__ LoadU64(temp, src, r0);
|
__ LoadU64(temp, src, r0);
|
||||||
__ StoreU64(temp, g.ToMemOperand(destination));
|
__ StoreU64(temp, g.ToMemOperand(destination));
|
||||||
}
|
}
|
||||||
} else if (source->IsConstant()) {
|
} else if (source->IsConstant()) {
|
||||||
Constant src = g.ToConstant(source);
|
Constant src = g.ToConstant(source);
|
||||||
if (destination->IsRegister() || destination->IsStackSlot()) {
|
if (destination->IsRegister() || destination->IsStackSlot()) {
|
||||||
Register dst =
|
Register dst = destination->IsRegister() ? g.ToRegister(destination) : r1;
|
||||||
destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
|
|
||||||
switch (src.type()) {
|
switch (src.type()) {
|
||||||
case Constant::kInt32:
|
case Constant::kInt32:
|
||||||
__ mov(dst, Operand(src.ToInt32()));
|
__ mov(dst, Operand(src.ToInt32()));
|
||||||
@ -3672,9 +3748,9 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
|||||||
? src.ToFloat32()
|
? src.ToFloat32()
|
||||||
: src.ToFloat64().value();
|
: src.ToFloat64().value();
|
||||||
if (src.type() == Constant::kFloat32) {
|
if (src.type() == Constant::kFloat32) {
|
||||||
__ LoadF32<float>(dst, src.ToFloat32(), kScratchReg);
|
__ LoadF32<float>(dst, src.ToFloat32(), r1);
|
||||||
} else {
|
} else {
|
||||||
__ LoadF64<double>(dst, value, kScratchReg);
|
__ LoadF64<double>(dst, value, r1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destination->IsFloatStackSlot()) {
|
if (destination->IsFloatStackSlot()) {
|
||||||
@ -3692,7 +3768,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
|||||||
} else {
|
} else {
|
||||||
DCHECK(destination->IsSimd128StackSlot());
|
DCHECK(destination->IsSimd128StackSlot());
|
||||||
__ StoreV128(g.ToSimd128Register(source), g.ToMemOperand(destination),
|
__ StoreV128(g.ToSimd128Register(source), g.ToMemOperand(destination),
|
||||||
kScratchReg);
|
r1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DoubleRegister src = g.ToDoubleRegister(source);
|
DoubleRegister src = g.ToDoubleRegister(source);
|
||||||
@ -3721,7 +3797,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
|||||||
} else {
|
} else {
|
||||||
DCHECK_EQ(MachineRepresentation::kSimd128, op->representation());
|
DCHECK_EQ(MachineRepresentation::kSimd128, op->representation());
|
||||||
__ LoadV128(g.ToSimd128Register(destination), g.ToMemOperand(source),
|
__ LoadV128(g.ToSimd128Register(destination), g.ToMemOperand(source),
|
||||||
kScratchReg);
|
r1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LocationOperand* op = LocationOperand::cast(source);
|
LocationOperand* op = LocationOperand::cast(source);
|
||||||
@ -3734,9 +3810,8 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
|||||||
__ StoreF32(temp, g.ToMemOperand(destination));
|
__ StoreF32(temp, g.ToMemOperand(destination));
|
||||||
} else {
|
} else {
|
||||||
DCHECK_EQ(MachineRepresentation::kSimd128, op->representation());
|
DCHECK_EQ(MachineRepresentation::kSimd128, op->representation());
|
||||||
__ LoadV128(kScratchDoubleReg, g.ToMemOperand(source), kScratchReg);
|
__ LoadV128(kScratchDoubleReg, g.ToMemOperand(source), r1);
|
||||||
__ StoreV128(kScratchDoubleReg, g.ToMemOperand(destination),
|
__ StoreV128(kScratchDoubleReg, g.ToMemOperand(destination), r1);
|
||||||
kScratchReg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user