[llvm] aeedc07 - [IR] Add GraalVM calling conventions

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 17 08:30:49 PST 2023


Author: Sacha Coppey
Date: 2023-11-17T16:30:09Z
New Revision: aeedc0763772b398a725ab34d8a9cc1d698c60cb

URL: https://github.com/llvm/llvm-project/commit/aeedc0763772b398a725ab34d8a9cc1d698c60cb
DIFF: https://github.com/llvm/llvm-project/commit/aeedc0763772b398a725ab34d8a9cc1d698c60cb.diff

LOG: [IR] Add GraalVM calling conventions

Adds GraalVM calling conventions. The only difference with the default calling conventions is that GraalVM reserves two registers for the heap base and the thread. Since the registers are then accessed by name, getRegisterByName has to be updated accordingly.

This patch implements the calling conventions only for X86, AArch64 and RISC-V.

For X86, the reserved registers are X14 and X15. For AArch64, they are X27 and X28. For RISC-V, they are X23 and X27.

This patch has been used by the LLVM backend of GraalVM's Native Image project in production for around 4 months with no major issues.

Differential Revision: https://reviews.llvm.org/D151107

Added: 
    llvm/test/CodeGen/AArch64/graalcc.ll
    llvm/test/CodeGen/RISCV/graalcc.ll
    llvm/test/CodeGen/X86/graalcc.ll

Modified: 
    llvm/include/llvm/AsmParser/LLToken.h
    llvm/include/llvm/IR/CallingConv.h
    llvm/lib/AsmParser/LLLexer.cpp
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/IR/AsmWriter.cpp
    llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
    llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp
    llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
    llvm/lib/Target/X86/X86ISelLowering.cpp
    llvm/lib/Target/X86/X86RegisterInfo.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h
index c9dcd29b31955dc..1eb3986e65e9154 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -176,6 +176,7 @@ enum Kind {
   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
index 668f0ab4e54de44..3a522c239ad59eb 100644
--- a/llvm/include/llvm/IR/CallingConv.h
+++ b/llvm/include/llvm/IR/CallingConv.h
@@ -248,6 +248,9 @@ namespace CallingConv {
     /// 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
index da9e9f4a3c9833b..fb111042f674d10 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -633,6 +633,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   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
index b12074375461bf2..2d2c1bf65311c01 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1999,6 +1999,7 @@ void LLParser::parseOptionalDLLStorageClass(unsigned &Res) {
 ///   ::= 'amdgpu_kernel'
 ///   ::= 'tailcc'
 ///   ::= 'm68k_rtdcc'
+///   ::= 'graalcc'
 ///   ::= 'cc' UINT
 ///
 bool LLParser::parseOptionalCallingConv(unsigned &CC) {
@@ -2067,6 +2068,7 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) {
   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
index a7d667d79880c1a..c37adb423397059 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -307,6 +307,7 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
   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
index e21d5da5a2357c1..fd4df07f04bfe0b 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -6382,6 +6382,7 @@ CCAssignFn *AArch64TargetLowering::CCAssignFnForCall(CallingConv::ID CC,
   case CallingConv::Swift:
   case CallingConv::SwiftTail:
   case CallingConv::Tail:
+  case CallingConv::GRAAL:
     if (Subtarget->isTargetWindows()) {
       if (IsVarArg) {
         if (Subtarget->isWindowsArm64EC())
@@ -9889,9 +9890,10 @@ Register AArch64TargetLowering::
 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
index f431daee8712d91..ed64a7b4984c17c 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -442,6 +442,13 @@ AArch64RegisterInfo::getStrictlyReservedRegs(const MachineFunction &MF) const {
 
   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
index d0d62150b56c9ec..f1a1047fc14b989 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -17331,6 +17331,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
   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
index cd0bcb8e6cfc495..475ccc01df1fa3e 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -85,10 +85,11 @@ RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
 BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   const RISCVFrameLowering *TFI = getFrameLowering(MF);
   BitVector Reserved(getNumRegs());
+  auto &Subtarget = MF.getSubtarget<RISCVSubtarget>();
 
   // Mark any registers requested to be reserved as such
   for (size_t Reg = 0; Reg < getNumRegs(); Reg++) {
-    if (MF.getSubtarget<RISCVSubtarget>().isRegisterReservedByUser(Reg))
+    if (Subtarget.isRegisterReservedByUser(Reg))
       markSuperRegs(Reserved, Reg);
   }
 
@@ -119,6 +120,13 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   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
index cf667077e882a4f..310805b6f26393d 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -27017,11 +27017,13 @@ Register X86TargetLowering::getRegisterByName(const char* RegName, LLT VT,
   const TargetFrameLowering &TFI = *Subtarget.getFrameLowering();
 
   Register Reg = StringSwitch<unsigned>(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
index 8b121d74023d2b3..379a9d448a963ca 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -619,6 +619,13 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
   if (!Is64Bit || !MF.getSubtarget<X86Subtarget>().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
index 000000000000000..9c99827e5c6c250
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/graalcc.ll
@@ -0,0 +1,11 @@
+; RUN: llc -mtriple=arm64 -o - %s | FileCheck %s
+
+ at 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
index 000000000000000..7ce3e17bf50e249
--- /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
+
+ at 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
index 000000000000000..3464fadf06a800a
--- /dev/null
+++ b/llvm/test/CodeGen/X86/graalcc.ll
@@ -0,0 +1,13 @@
+; RUN: llc -mtriple=x86_64 -o - %s | FileCheck %s
+
+ at 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
+}


        


More information about the llvm-commits mailing list