From 413a27f0af4163d5aedd56d2efbea59b7b4551a7 Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Fri, 4 Apr 2025 17:05:47 +0200 Subject: [PATCH 1/3] SaveCalleeSaveRegisters LIR phase now stores non-allocatable register directly into virtual stack slot. --- .../lir/alloc/SaveCalleeSaveRegisters.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java index e61fbbdf7ce7..6e6de26e67d3 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package jdk.graal.compiler.lir.alloc; import java.util.ArrayList; +import java.util.List; import jdk.graal.compiler.core.common.LIRKind; import jdk.graal.compiler.core.common.cfg.BasicBlock; @@ -32,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; @@ -43,6 +43,7 @@ import jdk.vm.ci.code.RegisterArray; 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 { @@ -54,7 +55,7 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreA return; } LIR lir = lirGenRes.getLIR(); - RegisterMap savedRegisters = saveAtEntry(lir, context.lirGen, lirGenRes, calleeSaveRegisters, target.arch); + RegisterMap savedRegisters = saveAtEntry(lir, context.lirGen, lirGenRes, calleeSaveRegisters, target.arch); for (int blockId : lir.getBlocks()) { if (LIR.isBlockDeleted(blockId)) { @@ -67,7 +68,7 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreA } } - private static RegisterMap saveAtEntry(LIR lir, LIRGeneratorTool lirGen, LIRGenerationResult lirGenRes, RegisterArray calleeSaveRegisters, Architecture arch) { + private static RegisterMap saveAtEntry(LIR lir, LIRGeneratorTool lirGen, LIRGenerationResult lirGenRes, RegisterArray calleeSaveRegisters, Architecture arch) { BasicBlock startBlock = lir.getControlFlowGraph().getStartBlock(); ArrayList instructions = lir.getLIRforBlock(startBlock); int insertionIndex = lirGenRes.getFirstInsertPosition(); @@ -76,12 +77,13 @@ private static RegisterMap saveAtEntry(LIR lir, LIRGeneratorTool lirGe StandardOp.LabelOp entry = (StandardOp.LabelOp) instructions.get(insertionIndex - 1); RegisterValue[] savedRegisterValues = new RegisterValue[calleeSaveRegisters.size()]; int savedRegisterValueIndex = 0; - RegisterMap saveMap = new RegisterMap<>(arch); + List allocatables = lirGenRes.getRegisterConfig().getAllocatableRegisters().asList(); + RegisterMap saveMap = new RegisterMap<>(arch); for (Register register : calleeSaveRegisters) { PlatformKind registerPlatformKind = arch.getLargestStorableKind(register.getRegisterCategory()); LIRKind lirKind = LIRKind.value(registerPlatformKind); RegisterValue registerValue = register.asValue(lirKind); - Variable saveVariable = lirGen.newVariable(lirKind); + 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"); @@ -93,14 +95,14 @@ private static RegisterMap saveAtEntry(LIR lir, LIRGeneratorTool lirGe return saveMap; } - private static void restoreAtExit(LIR lir, MoveFactory moveFactory, LIRGenerationResult lirGenRes, RegisterMap calleeSaveRegisters, BasicBlock block) { + private static void restoreAtExit(LIR lir, MoveFactory moveFactory, LIRGenerationResult lirGenRes, RegisterMap calleeSaveRegisters, BasicBlock block) { ArrayList 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"); From e248837efee779d608c4cd809f9ca50db545c3cf Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Fri, 4 Apr 2025 17:20:18 +0200 Subject: [PATCH 2/3] Backup only the lower 128bits of the XMM callee save registers on Windows --- .../lir/alloc/SaveCalleeSaveRegisters.java | 2 +- .../amd64/SubstrateAMD64RegisterConfig.java | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java index 6e6de26e67d3..4b236dc5a230 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java @@ -80,7 +80,7 @@ private static RegisterMap saveAtEntry(LIR lir, LIRGeneratorTo List allocatables = lirGenRes.getRegisterConfig().getAllocatableRegisters().asList(); RegisterMap 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); AllocatableValue saveVariable = allocatables.contains(registerValue.getRegister()) ? lirGen.newVariable(lirKind) : lirGenRes.getFrameMapBuilder().allocateSpillSlot(lirKind); diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java index 66d1df2a37bb..59a2f6a89279 100644 --- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java +++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +63,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; @@ -85,6 +86,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; @@ -234,6 +236,16 @@ public RegisterArray getCalleeSaveRegisters() { return calleeSaveRegisters; } + @Override + public PlatformKind getCalleeSaveRegisterStorageKind(Architecture arch, Register calleeSaveRegister) { + if (Platform.includedIn(Platform.WINDOWS.class)) { + if (AMD64.XMM.equals(calleeSaveRegister.getRegisterCategory()) && calleeSaveRegister.encoding() >= xmm6.encoding() && calleeSaveRegister.encoding() <= xmm15.encoding()) { + return V128_QWORD; + } + } + return SubstrateRegisterConfig.super.getCalleeSaveRegisterStorageKind(arch, calleeSaveRegister); + } + @Override public RegisterArray getCallerSaveRegisters() { return getAllocatableRegisters(); @@ -405,7 +417,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); From d9f2b9181687abc4c01338516a17b1e9c3aace58 Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Tue, 8 Apr 2025 12:17:00 +0200 Subject: [PATCH 3/3] address comment. --- .../svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java index 59a2f6a89279..61fc073933ff 100644 --- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java +++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java @@ -238,10 +238,9 @@ public RegisterArray getCalleeSaveRegisters() { @Override public PlatformKind getCalleeSaveRegisterStorageKind(Architecture arch, Register calleeSaveRegister) { - if (Platform.includedIn(Platform.WINDOWS.class)) { - if (AMD64.XMM.equals(calleeSaveRegister.getRegisterCategory()) && calleeSaveRegister.encoding() >= xmm6.encoding() && calleeSaveRegister.encoding() <= xmm15.encoding()) { - return V128_QWORD; - } + 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 %s", calleeSaveRegister); + return V128_QWORD; } return SubstrateRegisterConfig.super.getCalleeSaveRegisterStorageKind(arch, calleeSaveRegister); }