diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -176,6 +176,7 @@ kw_amdgpu_gfx, kw_tailcc, kw_m68k_rtdcc, + kw_graalcc, // Attributes: kw_attributes, 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 @@ -248,6 +248,9 @@ /// Used for M68k rtd-based CC (similar to X86's stdcall). M68k_RTD = 106, + /// Used by GraalVM. Two additional registers are reserved. + GRAAL = 107, + /// The highest possible ID. Must be some 2^k - 1. MaxID = 1023 }; diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -633,6 +633,7 @@ KEYWORD(amdgpu_gfx); KEYWORD(tailcc); KEYWORD(m68k_rtdcc); + KEYWORD(graalcc); KEYWORD(cc); KEYWORD(c); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -1999,6 +1999,7 @@ /// ::= 'amdgpu_kernel' /// ::= 'tailcc' /// ::= 'm68k_rtdcc' +/// ::= 'graalcc' /// ::= 'cc' UINT /// bool LLParser::parseOptionalCallingConv(unsigned &CC) { @@ -2067,6 +2068,7 @@ case lltok::kw_amdgpu_kernel: CC = CallingConv::AMDGPU_KERNEL; break; case lltok::kw_tailcc: CC = CallingConv::Tail; break; case lltok::kw_m68k_rtdcc: CC = CallingConv::M68k_RTD; break; + case lltok::kw_graalcc: CC = CallingConv::GRAAL; break; case lltok::kw_cc: { Lex.Lex(); return parseUInt32(CC); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -307,6 +307,7 @@ case CallingConv::CXX_FAST_TLS: Out << "cxx_fast_tlscc"; break; case CallingConv::GHC: Out << "ghccc"; break; case CallingConv::Tail: Out << "tailcc"; break; + case CallingConv::GRAAL: Out << "graalcc"; break; case CallingConv::CFGuard_Check: Out << "cfguard_checkcc"; break; case CallingConv::X86_StdCall: Out << "x86_stdcallcc"; break; case CallingConv::X86_FastCall: Out << "x86_fastcallcc"; break; 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 @@ -6382,6 +6382,7 @@ case CallingConv::Swift: case CallingConv::SwiftTail: case CallingConv::Tail: + case CallingConv::GRAAL: if (Subtarget->isTargetWindows()) { if (IsVarArg) { if (Subtarget->isWindowsArm64EC()) @@ -9889,9 +9890,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 @@ -17409,6 +17409,7 @@ case CallingConv::C: case CallingConv::Fast: case CallingConv::SPIR_KERNEL: + 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 @@ -85,10 +85,11 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const { const RISCVFrameLowering *TFI = getFrameLowering(MF); BitVector Reserved(getNumRegs()); + auto &Subtarget = MF.getSubtarget(); // Mark any registers requested to be reserved as such for (size_t Reg = 0; Reg < getNumRegs(); Reg++) { - if (MF.getSubtarget().isRegisterReservedByUser(Reg)) + if (Subtarget.isRegisterReservedByUser(Reg)) markSuperRegs(Reserved, Reg); } @@ -119,6 +120,13 @@ markSuperRegs(Reserved, RISCV::FRM); markSuperRegs(Reserved, RISCV::FFLAGS); + if (MF.getFunction().getCallingConv() == CallingConv::GRAAL) { + if (Subtarget.isRVE()) + report_fatal_error("Graal reserved registers do not exist in RVE"); + 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 @@ -27017,11 +27017,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 @@ -619,6 +619,13 @@ if (!Is64Bit || !MF.getSubtarget().hasEGPR()) Reserved.set(X86::R16, X86::R31WH + 1); + 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/graalcc.ll b/llvm/test/CodeGen/AArch64/graalcc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/graalcc.ll @@ -0,0 +1,11 @@ +; RUN: llc -mtriple=arm64 -o - %s | FileCheck %s + +@var = global [30 x i64] zeroinitializer + +define graalcc 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/graalcc.ll b/llvm/test/CodeGen/RISCV/graalcc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/graalcc.ll @@ -0,0 +1,14 @@ +; RUN: llc -mtriple=riscv32 -o - %s | FileCheck %s +; RUN: llc -mtriple=riscv64 -o - %s | FileCheck %s + +@var = global [30 x i64] zeroinitializer + +define graalcc 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/graalcc.ll b/llvm/test/CodeGen/X86/graalcc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/graalcc.ll @@ -0,0 +1,13 @@ +; RUN: llc -mtriple=x86_64 -o - %s | FileCheck %s + +@var = global [30 x i64] zeroinitializer + +define graalcc 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 +}