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:
Milad Fa 2022-05-31 14:17:11 -04:00 committed by V8 LUCI CQ
parent b1f896337d
commit 5c445ebbea
4 changed files with 177 additions and 14 deletions

View File

@ -1376,6 +1376,11 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
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->
} // namespace internal

View File

@ -1786,6 +1786,11 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
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->
} // namespace internal

View File

@ -4277,11 +4277,90 @@ void CodeGenerator::PrepareForDeoptimizationExits(
__ 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,
InstructionOperand* destination) {
PPCOperandConverter g(this, nullptr);
// Dispatch on the source and destination operand kinds. Not all
// 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()) {
DCHECK(destination->IsRegister() || destination->IsStackSlot());
Register src = g.ToRegister(source);
@ -4296,15 +4375,14 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
if (destination->IsRegister()) {
__ LoadU64(g.ToRegister(destination), src, r0);
} else {
Register temp = kScratchReg;
Register temp = ip;
__ LoadU64(temp, src, r0);
__ StoreU64(temp, g.ToMemOperand(destination), r0);
}
} else if (source->IsConstant()) {
Constant src = g.ToConstant(source);
if (destination->IsRegister() || destination->IsStackSlot()) {
Register dst =
destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
Register dst = destination->IsRegister() ? g.ToRegister(destination) : ip;
switch (src.type()) {
case Constant::kInt32:
#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(src.ToFloat64());
#endif
__ LoadDoubleLiteral(dst, value, kScratchReg);
__ LoadDoubleLiteral(dst, value, r0);
if (destination->IsDoubleStackSlot()) {
__ StoreF64(dst, g.ToMemOperand(destination), r0);
} else if (destination->IsFloatStackSlot()) {

View File

@ -3584,11 +3584,88 @@ void CodeGenerator::FinishCode() {}
void CodeGenerator::PrepareForDeoptimizationExits(
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,
InstructionOperand* destination) {
S390OperandConverter g(this, nullptr);
// Dispatch on the source and destination operand kinds. Not all
// 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()) {
DCHECK(destination->IsRegister() || destination->IsStackSlot());
Register src = g.ToRegister(source);
@ -3603,15 +3680,14 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
if (destination->IsRegister()) {
__ LoadU64(g.ToRegister(destination), src);
} else {
Register temp = kScratchReg;
Register temp = r1;
__ LoadU64(temp, src, r0);
__ StoreU64(temp, g.ToMemOperand(destination));
}
} else if (source->IsConstant()) {
Constant src = g.ToConstant(source);
if (destination->IsRegister() || destination->IsStackSlot()) {
Register dst =
destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
Register dst = destination->IsRegister() ? g.ToRegister(destination) : r1;
switch (src.type()) {
case Constant::kInt32:
__ mov(dst, Operand(src.ToInt32()));
@ -3672,9 +3748,9 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
? src.ToFloat32()
: src.ToFloat64().value();
if (src.type() == Constant::kFloat32) {
__ LoadF32<float>(dst, src.ToFloat32(), kScratchReg);
__ LoadF32<float>(dst, src.ToFloat32(), r1);
} else {
__ LoadF64<double>(dst, value, kScratchReg);
__ LoadF64<double>(dst, value, r1);
}
if (destination->IsFloatStackSlot()) {
@ -3692,7 +3768,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
} else {
DCHECK(destination->IsSimd128StackSlot());
__ StoreV128(g.ToSimd128Register(source), g.ToMemOperand(destination),
kScratchReg);
r1);
}
} else {
DoubleRegister src = g.ToDoubleRegister(source);
@ -3721,7 +3797,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
} else {
DCHECK_EQ(MachineRepresentation::kSimd128, op->representation());
__ LoadV128(g.ToSimd128Register(destination), g.ToMemOperand(source),
kScratchReg);
r1);
}
} else {
LocationOperand* op = LocationOperand::cast(source);
@ -3734,9 +3810,8 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
__ StoreF32(temp, g.ToMemOperand(destination));
} else {
DCHECK_EQ(MachineRepresentation::kSimd128, op->representation());
__ LoadV128(kScratchDoubleReg, g.ToMemOperand(source), kScratchReg);
__ StoreV128(kScratchDoubleReg, g.ToMemOperand(destination),
kScratchReg);
__ LoadV128(kScratchDoubleReg, g.ToMemOperand(source), r1);
__ StoreV128(kScratchDoubleReg, g.ToMemOperand(destination), r1);
}
}
} else {