diff --git a/llvm/include/llvm/IR/CallingConv.h b/llvm/include/llvm/IR/CallingConv.h --- a/llvm/include/llvm/IR/CallingConv.h +++ b/llvm/include/llvm/IR/CallingConv.h @@ -245,6 +245,9 @@ /// placement. Preserves active lane values for input VGPRs. AMDGPU_CS_ChainPreserve = 105, + /// Used by GraalVM. Two additional registers are reserved. + GRAAL = 106, + /// The highest possible ID. Must be some 2^k - 1. MaxID = 1023 }; diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -6269,6 +6269,7 @@ case CallingConv::Swift: case CallingConv::SwiftTail: case CallingConv::Tail: + case CallingConv::GRAAL: if (Subtarget->isTargetWindows() && IsVarArg) { if (Subtarget->isWindowsArm64EC()) return CC_AArch64_Arm64EC_VarArg; @@ -9724,9 +9725,10 @@ getRegisterByName(const char* RegName, LLT VT, const MachineFunction &MF) const { Register Reg = MatchRegisterName(RegName); if (AArch64::X1 <= Reg && Reg <= AArch64::X28) { - const MCRegisterInfo *MRI = Subtarget->getRegisterInfo(); + const AArch64RegisterInfo *MRI = Subtarget->getRegisterInfo(); unsigned DwarfRegNum = MRI->getDwarfRegNum(Reg, false); - if (!Subtarget->isXRegisterReserved(DwarfRegNum)) + if (!Subtarget->isXRegisterReserved(DwarfRegNum) && + !MRI->isReservedReg(MF, Reg)) Reg = 0; } if (Reg) diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -442,6 +442,13 @@ markSuperRegs(Reserved, AArch64::FPCR); + if (MF.getFunction().getCallingConv() == CallingConv::GRAAL) { + markSuperRegs(Reserved, AArch64::X27); + markSuperRegs(Reserved, AArch64::X28); + markSuperRegs(Reserved, AArch64::W27); + markSuperRegs(Reserved, AArch64::W28); + } + assert(checkAllSuperRegsMarked(Reserved)); return Reserved; } diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -15999,6 +15999,7 @@ report_fatal_error("Unsupported calling convention"); case CallingConv::C: case CallingConv::Fast: + case CallingConv::GRAAL: break; case CallingConv::GHC: if (!Subtarget.hasStdExtFOrZfinx() || !Subtarget.hasStdExtDOrZdinx()) diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -119,6 +119,11 @@ markSuperRegs(Reserved, RISCV::FRM); markSuperRegs(Reserved, RISCV::FFLAGS); + if (MF.getFunction().getCallingConv() == CallingConv::GRAAL) { + markSuperRegs(Reserved, RISCV::X23); + markSuperRegs(Reserved, RISCV::X27); + } + assert(checkAllSuperRegsMarked(Reserved)); return Reserved; } diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -26987,11 +26987,13 @@ const TargetFrameLowering &TFI = *Subtarget.getFrameLowering(); Register Reg = StringSwitch(RegName) - .Case("esp", X86::ESP) - .Case("rsp", X86::RSP) - .Case("ebp", X86::EBP) - .Case("rbp", X86::RBP) - .Default(0); + .Case("esp", X86::ESP) + .Case("rsp", X86::RSP) + .Case("ebp", X86::EBP) + .Case("rbp", X86::RBP) + .Case("r14", X86::R14) + .Case("r15", X86::R15) + .Default(0); if (Reg == X86::EBP || Reg == X86::RBP) { if (!TFI.hasFP(MF)) diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -610,6 +610,13 @@ } } + if (MF.getFunction().getCallingConv() == CallingConv::GRAAL) { + for (MCRegAliasIterator AI(X86::R14, this, true); AI.isValid(); ++AI) + Reserved.set(*AI); + for (MCRegAliasIterator AI(X86::R15, this, true); AI.isValid(); ++AI) + Reserved.set(*AI); + } + assert(checkAllSuperRegsMarked(Reserved, {X86::SIL, X86::DIL, X86::BPL, X86::SPL, X86::SIH, X86::DIH, X86::BPH, X86::SPH})); diff --git a/llvm/test/CodeGen/AArch64/aarch64-graal-callingconv.ll b/llvm/test/CodeGen/AArch64/aarch64-graal-callingconv.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/aarch64-graal-callingconv.ll @@ -0,0 +1,11 @@ +; RUN: llc -mtriple=arm64-linux-gnu -o - %s | FileCheck %s + +@var = global [30 x i64] zeroinitializer + +define cc 106 void @keep_live() { + %val = load volatile [30 x i64], ptr @var + store volatile [30 x i64] %val, ptr @var +; CHECK-NOT: ldr x27 +; CHECK-NOT: ldr x28 + ret void +} diff --git a/llvm/test/CodeGen/RISCV/rv64-graal-callingconv.ll b/llvm/test/CodeGen/RISCV/rv64-graal-callingconv.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rv64-graal-callingconv.ll @@ -0,0 +1,13 @@ +; RUN: llc -mtriple=riscv64-unknown-linux-gnu -o - %s | FileCheck %s + +@var = global [30 x i64] zeroinitializer + +define cc 106 void @keep_live() { + %val = load volatile [30 x i64], ptr @var + store volatile [30 x i64] %val, ptr @var +; CHECK-NOT: lw s7, +; CHECK-NOT: ld s7, +; CHECK-NOT: lw s11, +; CHECK-NOT: ld s11, + ret void +} diff --git a/llvm/test/CodeGen/X86/x86-graal-callingconv.ll b/llvm/test/CodeGen/X86/x86-graal-callingconv.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/x86-graal-callingconv.ll @@ -0,0 +1,13 @@ +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -o - %s | FileCheck %s + +@var = global [30 x i64] zeroinitializer + +define cc 106 void @keep_live() { + %val = load volatile [30 x i64], ptr @var + store volatile [30 x i64] %val, ptr @var +; CHECK-NOT: movq {{[0-9]+}}(%{{[a-z]+}}), %r14 +; CHECK-NOT: movq {{[0-9]+}}(%{{[a-z]+}}), %r15 +; CHECK-NOT: movq %r14, +; CHECK-NOT: movq %r15, + ret void +}