Skip to content

[GR-64008] Improve saving of the callee save registers #10984

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import jdk.graal.compiler.lir.LIRInsertionBuffer;
import jdk.graal.compiler.lir.LIRInstruction;
import jdk.graal.compiler.lir.StandardOp;
import jdk.graal.compiler.lir.Variable;
import jdk.graal.compiler.lir.gen.LIRGenerationResult;
import jdk.graal.compiler.lir.gen.LIRGeneratorTool;
import jdk.graal.compiler.lir.gen.MoveFactory;
Expand All @@ -43,6 +42,7 @@
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterValue;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.PlatformKind;

public class SaveCalleeSaveRegisters extends PreAllocationOptimizationPhase {
Expand All @@ -54,7 +54,7 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreA
return;
}
LIR lir = lirGenRes.getLIR();
RegisterMap<Variable> savedRegisters = saveAtEntry(lir, context.lirGen, lirGenRes, calleeSaveRegisters, target.arch);
RegisterMap<AllocatableValue> savedRegisters = saveAtEntry(lir, context.lirGen, lirGenRes, calleeSaveRegisters, target.arch);

for (int blockId : lir.getBlocks()) {
if (LIR.isBlockDeleted(blockId)) {
Expand All @@ -67,7 +67,7 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreA
}
}

private static RegisterMap<Variable> saveAtEntry(LIR lir, LIRGeneratorTool lirGen, LIRGenerationResult lirGenRes, List<Register> calleeSaveRegisters, Architecture arch) {
private static RegisterMap<AllocatableValue> saveAtEntry(LIR lir, LIRGeneratorTool lirGen, LIRGenerationResult lirGenRes, List<Register> calleeSaveRegisters, Architecture arch) {
BasicBlock<?> startBlock = lir.getControlFlowGraph().getStartBlock();
ArrayList<LIRInstruction> instructions = lir.getLIRforBlock(startBlock);
int insertionIndex = lirGenRes.getFirstInsertPosition();
Expand All @@ -76,12 +76,15 @@ private static RegisterMap<Variable> saveAtEntry(LIR lir, LIRGeneratorTool lirGe
StandardOp.LabelOp entry = (StandardOp.LabelOp) instructions.get(insertionIndex - 1);
RegisterValue[] savedRegisterValues = new RegisterValue[calleeSaveRegisters.size()];
int savedRegisterValueIndex = 0;
RegisterMap<Variable> saveMap = new RegisterMap<>(arch);
List<Register> allocatables = lirGenRes.getRegisterConfig().getAllocatableRegisters();
RegisterMap<AllocatableValue> saveMap = new RegisterMap<>(arch);
for (Register register : calleeSaveRegisters) {
PlatformKind registerPlatformKind = arch.getLargestStorableKind(register.getRegisterCategory());
PlatformKind registerPlatformKind = lirGenRes.getRegisterConfig().getCalleeSaveRegisterStorageKind(arch, register);
LIRKind lirKind = LIRKind.value(registerPlatformKind);
RegisterValue registerValue = register.asValue(lirKind);
Variable saveVariable = lirGen.newVariable(lirKind);
// Force a non-allocatable register to be saved to a stack slot
// so as to avoid unnecessary register pressure.
AllocatableValue saveVariable = allocatables.contains(registerValue.getRegister()) ? lirGen.newVariable(lirKind) : lirGenRes.getFrameMapBuilder().allocateSpillSlot(lirKind);
LIRInstruction save = lirGen.getSpillMoveFactory().createMove(saveVariable, registerValue);
buffer.append(insertionIndex, save);
save.setComment(lirGenRes, "SaveCalleeSavedRegisters: saveAtEntry");
Expand All @@ -93,14 +96,14 @@ private static RegisterMap<Variable> saveAtEntry(LIR lir, LIRGeneratorTool lirGe
return saveMap;
}

private static void restoreAtExit(LIR lir, MoveFactory moveFactory, LIRGenerationResult lirGenRes, RegisterMap<Variable> calleeSaveRegisters, BasicBlock<?> block) {
private static void restoreAtExit(LIR lir, MoveFactory moveFactory, LIRGenerationResult lirGenRes, RegisterMap<AllocatableValue> calleeSaveRegisters, BasicBlock<?> block) {
ArrayList<LIRInstruction> instructions = lir.getLIRforBlock(block);
int insertionIndex = instructions.size() - 1;
LIRInsertionBuffer buffer = new LIRInsertionBuffer();
buffer.init(instructions);
LIRInstruction lirInstruction = instructions.get(insertionIndex);
assert lirInstruction instanceof StandardOp.BlockEndOp : lirInstruction;
calleeSaveRegisters.forEach((Register register, Variable saved) -> {
calleeSaveRegisters.forEach((Register register, AllocatableValue saved) -> {
LIRInstruction restore = moveFactory.createMove(register.asValue(saved.getValueKind()), saved);
buffer.append(insertionIndex, restore);
restore.setComment(lirGenRes, "SaveCalleeSavedRegisters: restoreAtExit");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import static jdk.vm.ci.amd64.AMD64.xmm7;
import static jdk.vm.ci.amd64.AMD64.xmm8;
import static jdk.vm.ci.amd64.AMD64.xmm9;
import static jdk.vm.ci.amd64.AMD64Kind.V128_QWORD;

import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -87,6 +88,7 @@
import jdk.graal.compiler.core.common.LIRKind;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.CallingConvention.Type;
import jdk.vm.ci.code.Register;
Expand Down Expand Up @@ -239,6 +241,15 @@ public List<Register> getCalleeSaveRegisters() {
return calleeSaveRegisters;
}

@Override
public PlatformKind getCalleeSaveRegisterStorageKind(Architecture arch, Register calleeSaveRegister) {
if (Platform.includedIn(Platform.WINDOWS.class) && AMD64.XMM.equals(calleeSaveRegister.getRegisterCategory())) {
VMError.guarantee(calleeSaveRegister.encoding() >= xmm6.encoding() && calleeSaveRegister.encoding() <= xmm15.encoding(), "unexpected callee saved register");
return V128_QWORD;
}
return SubstrateRegisterConfig.super.getCalleeSaveRegisterStorageKind(arch, calleeSaveRegister);
}

@Override
public List<Register> getCallerSaveRegisters() {
return getAllocatableRegisters();
Expand Down Expand Up @@ -410,7 +421,7 @@ public CallingConvention getCallingConvention(Type t, JavaType returnType, JavaT
kinds = Arrays.copyOf(kinds, kinds.length + 1);
locations = Arrays.copyOf(locations, locations.length + 1);
kinds[kinds.length - 1] = JavaKind.Int;
locations[locations.length - 1] = AMD64.rax.asValue(LIRKind.value(AMD64Kind.DWORD));
locations[locations.length - 1] = rax.asValue(LIRKind.value(AMD64Kind.DWORD));
if (type.customABI()) {
var extendsParametersAssignment = Arrays.copyOf(type.fixedParameterAssignment, type.fixedParameterAssignment.length + 1);
extendsParametersAssignment[extendsParametersAssignment.length - 1] = AssignedLocation.forRegister(rax, JavaKind.Long);
Expand Down