https://github.com/Luminyx1 updated 
https://github.com/llvm/llvm-project/pull/175145

>From 46343d8b637d3d82e6316c9e9248ce7610b9399e Mon Sep 17 00:00:00 2001
From: Luminyx <[email protected]>
Date: Fri, 9 Jan 2026 04:26:53 -0500
Subject: [PATCH 1/5] [clang][llvm][PPC] PreserveAll attribute

---
 clang/include/clang/Basic/AttrDocs.td       |  7 +-
 clang/lib/Basic/Targets/PPC.h               | 11 +++
 llvm/lib/Target/PowerPC/PPCCallingConv.td   | 84 +++++++++++++++++++++
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp |  7 ++
 llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp | 81 ++++++++++++++++++++
 5 files changed, 188 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 812b48058d189..7e4bb5eaf2f39 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -6584,7 +6584,7 @@ in the future.
 def PreserveAllDocs : Documentation {
   let Category = DocCatCallingConvs;
   let Content = [{
-On X86-64 and AArch64 targets, this attribute changes the calling convention of
+On X86-64, AArch64, and PowerPC targets, this attribute changes the calling 
convention of
 a function. The ``preserve_all`` calling convention attempts to make the code
 in the caller even less intrusive than the ``preserve_most`` calling 
convention.
 This calling convention also behaves identical to the ``C`` calling convention
@@ -6599,10 +6599,13 @@ returned in callee-saved registers.
   R11. R11 can be used as a scratch register. Furthermore it also preserves
   all floating-point registers (XMMs/YMMs).
 
-- On AArch64 the callee preserve all general purpose registers, except X0-X8 
and
+- On AArch64 the callee preserves all general purpose registers, except X0-X8 
and
   X16-X18. Furthermore it also preserves lower 128 bits of V8-V31 SIMD - 
floating
   point registers.
 
+- On PowerPC the callee preserves all general purpose registers, except R1 and 
R2.
+  Furthermore it also preserves all floating-point and vector registers.
+
 The idea behind this convention is to support calls to runtime functions
 that don't need to call out to any other functions.
 
diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h
index 664c9e15d8d18..d49f23b3fa68d 100644
--- a/clang/lib/Basic/Targets/PPC.h
+++ b/clang/lib/Basic/Targets/PPC.h
@@ -428,6 +428,16 @@ class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public 
PPCTargetInfo {
   std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
     return std::make_pair(32, 32);
   }
+
+  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override 
{
+    switch (CC) {
+    default:
+      return CCCR_Warning;
+    case CC_PreserveAll:
+    case CC_C:
+      return CCCR_OK;
+    }
+  }
 };
 
 // Note: ABI differences may eventually require us to have a separate
@@ -490,6 +500,7 @@ class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public 
PPCTargetInfo {
   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override 
{
     switch (CC) {
     case CC_Swift:
+    case CC_PreserveAll:
       return CCCR_OK;
     case CC_SwiftAsync:
       return CCCR_Error;
diff --git a/llvm/lib/Target/PowerPC/PPCCallingConv.td 
b/llvm/lib/Target/PowerPC/PPCCallingConv.td
index 5d4fe06ebdddd..b564b30a94bbe 100644
--- a/llvm/lib/Target/PowerPC/PPCCallingConv.td
+++ b/llvm/lib/Target/PowerPC/PPCCallingConv.td
@@ -343,6 +343,90 @@ def CSR_PPC64_R2_Altivec : CalleeSavedRegs<(add 
CSR_PPC64_Altivec, X2)>;
 
 def CSR_NoRegs : CalleeSavedRegs<(add)>;
 
+def CSR_PPC32_PreserveMost : CalleeSavedRegs<(add R0, (sequence "R%u", 3, 31),
+                                 (sequence "CR%u", 0, 7))>;
+
+def CSR_PPC32_PreserveMost_NonVoid
+    : CalleeSavedRegs<(sub CSR_PPC32_PreserveMost, R3)>;
+
+def CSR_PPC32_PreserveAll
+    : CalleeSavedRegs<(add CSR_PPC32_PreserveMost, (sequence "F%u", 0, 31))>;
+
+def CSR_PPC32_PreserveAll_Unknown
+    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll, R3, R4, F1)>;
+
+def CSR_PPC32_PreserveAll_NonVoid
+    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll, R3)>;
+
+def CSR_PPC32_PreserveAll_NonVoid_64
+    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_NonVoid, R4)>;
+
+def CSR_PPC32_PreserveAll_NonVoid_Float
+    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll, F1)>;
+
+def CSR_PPC32_PreserveAll_Altivec
+    : CalleeSavedRegs<(add CSR_PPC32_PreserveAll, (sequence "V%u", 0, 31))>;
+
+def CSR_PPC32_PreserveAll_Altivec_Unknown
+    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_Altivec, R3, R4, F1, V2)>;
+
+def CSR_PPC32_PreserveAll_Altivec_NonVoid
+    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_Altivec, R3)>;
+
+def CSR_PPC32_PreserveAll_Altivec_NonVoid_64
+    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_Altivec_NonVoid, R4)>;
+
+def CSR_PPC32_PreserveAll_Altivec_NonVoid_Vec
+    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_Altivec, V2)>;
+
+def CSR_PPC32_PreserveAll_Altivec_NonVoid_Float
+    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_Altivec, F1)>;
+
+def CSR_PPC32_PreserveAll_SPE
+    : CalleeSavedRegs<(add CSR_PPC32_PreserveMost, (sequence "S%u", 3, 31))>;
+
+def CSR_PPC32_PreserveAll_SPE_NonVoid
+    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_SPE, R3, S3)>;
+
+def CSR_PPC64_PreserveMost : CalleeSavedRegs<(add X0, (sequence "X%u", 3, 31),
+                                 (sequence "CR%u", 0, 7))>;
+
+def CSR_PPC64_PreserveMost_NonVoid
+    : CalleeSavedRegs<(sub CSR_PPC64_PreserveMost, X3)>;
+
+def CSR_PPC64_PreserveAll
+    : CalleeSavedRegs<(add CSR_PPC64_PreserveMost, (sequence "F%u", 0, 31))>;
+
+def CSR_PPC64_PreserveAll_Unknown
+    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll, X3, X4, F1)>;
+
+def CSR_PPC64_PreserveAll_NonVoid
+    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll, X3)>;
+
+def CSR_PPC64_PreserveAll_NonVoid_Float
+    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll, F1)>;
+
+def CSR_PPC64_PreserveAll_NonVoid_128
+    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll_NonVoid, X4)>;
+
+def CSR_PPC64_PreserveAll_Altivec
+    : CalleeSavedRegs<(add CSR_PPC64_PreserveAll, (sequence "V%u", 0, 31))>;
+
+def CSR_PPC64_PreserveAll_Altivec_NonVoid
+    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll_Altivec, X3)>;
+
+def CSR_PPC64_PreserveAll_Altivec_Unknown
+    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll_Altivec, X3, X4, F1, V2)>;
+
+def CSR_PPC64_PreserveAll_Altivec_NonVoid_Float
+    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll_Altivec, F1)>;
+
+def CSR_PPC64_PreserveAll_Altivec_NonVoid_Vec
+    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll_Altivec, V2)>;
+
+def CSR_PPC64_PreserveAll_Altivec_NonVoid_128
+    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll_Altivec_NonVoid, X4)>;
+
 // coldcc calling convection marks most registers as non-volatile.
 // Do not include r1 since the stack pointer is never considered a CSR.
 // Do not include r2, since it is the TOC register and is added depending
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp 
b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index ef211bf8c8982..2b68774e73937 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -7804,11 +7804,18 @@ PPCTargetLowering::LowerReturn(SDValue Chain, 
CallingConv::ID CallConv,
   SDValue Glue;
   SmallVector<SDValue, 4> RetOps(1, Chain);
 
+  MachineFunction &MF = DAG.getMachineFunction();
+  bool ShouldDisableCalleeSavedRegister =
+      MF.getFunction().hasFnAttribute("preserve_all");
+
   // Copy the result values into the output registers.
   for (unsigned i = 0, RealResIdx = 0; i != RVLocs.size(); ++i, ++RealResIdx) {
     CCValAssign &VA = RVLocs[i];
     assert(VA.isRegLoc() && "Can only return in registers!");
 
+    if (ShouldDisableCalleeSavedRegister)
+      MF.getRegInfo().disableCalleeSavedRegister(VA.getLocReg());
+
     SDValue Arg = OutVals[RealResIdx];
 
     switch (VA.getLocInfo()) {
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp 
b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index b3a7c829958ec..2712eb6b1f7cb 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -199,6 +199,76 @@ PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction 
*MF) const {
     return CSR_64_AllRegs_SaveList;
   }
 
+  const Type *const ReturnTy = MF->getFunction().getReturnType();
+
+  // Preserve registers for PreserveAll attribute
+  // We need to skip r3 (return register) if the function isn't void
+  // however for floats it's f1 instead
+  // We also need to skip r4 if the return value is 64-bit on PPC32
+  // or 128-bit on PPC64
+  bool RetVec = ReturnTy->isVectorTy();
+  bool RetFloat = ReturnTy->isFloatingPointTy();
+  bool RetInt = ReturnTy->isIntOrPtrTy();
+  TypeSize RetIntSize = ReturnTy->getPrimitiveSizeInBits();
+  bool RetVoid = ReturnTy->isVoidTy();
+
+  if (MF->getFunction().getCallingConv() == CallingConv::PreserveAll) {
+    if (Subtarget.hasSPE() || Subtarget.pairedVectorMemops() ||
+        Subtarget.isAIXABI())
+      report_fatal_error("PreserveAll unimplemented on this target.");
+
+    if (TM.isPPC64()) {
+      if (RetVoid) {
+        if (Subtarget.hasAltivec())
+          return CSR_PPC64_PreserveAll_Altivec_SaveList;
+        return CSR_PPC64_PreserveAll_SaveList;
+      }
+      if (RetVec) {
+        if (Subtarget.hasAltivec())
+          return CSR_PPC64_PreserveAll_Altivec_NonVoid_Vec_SaveList;
+        report_fatal_error("Returning vector without vector extension");
+      }
+      if (RetFloat) {
+        if (Subtarget.hasAltivec())
+          return CSR_PPC64_PreserveAll_Altivec_NonVoid_Float_SaveList;
+        return CSR_PPC64_PreserveAll_NonVoid_Float_SaveList;
+      }
+      if (RetInt) {
+        if (Subtarget.hasAltivec())
+          return RetIntSize == 128
+                     ? CSR_PPC64_PreserveAll_Altivec_NonVoid_128_SaveList
+                     : CSR_PPC64_PreserveAll_Altivec_NonVoid_SaveList;
+        return RetIntSize == 128 ? CSR_PPC64_PreserveAll_NonVoid_128_SaveList
+                                 : CSR_PPC64_PreserveAll_NonVoid_SaveList;
+      }
+      report_fatal_error("Unhandled return type");
+    }
+    // PPC32:
+    if (RetVoid) {
+      if (Subtarget.hasAltivec())
+        return CSR_PPC32_PreserveAll_Altivec_SaveList;
+      return CSR_PPC32_PreserveAll_SaveList;
+    }
+    if (RetVec) {
+      if (Subtarget.hasAltivec())
+        return CSR_PPC32_PreserveAll_Altivec_NonVoid_Vec_SaveList;
+      report_fatal_error("Returning vector without vector extension");
+    }
+    if (RetFloat) {
+      if (Subtarget.hasAltivec())
+        return CSR_PPC32_PreserveAll_Altivec_NonVoid_Float_SaveList;
+      return CSR_PPC32_PreserveAll_NonVoid_Float_SaveList;
+    }
+    if (RetInt) {
+      if (Subtarget.hasAltivec())
+        return RetIntSize == 64
+                   ? CSR_PPC32_PreserveAll_Altivec_NonVoid_64_SaveList
+                   : CSR_PPC32_PreserveAll_Altivec_NonVoid_SaveList;
+      return RetIntSize == 64 ? CSR_PPC32_PreserveAll_NonVoid_64_SaveList
+                              : CSR_PPC32_PreserveAll_NonVoid_SaveList;
+    }
+  }
+
   // On PPC64, we might need to save r2 (but only if it is not reserved).
   // We do not need to treat R2 as callee-saved when using PC-Relative calls
   // because any direct uses of R2 will cause it to be reserved. If the 
function
@@ -291,6 +361,17 @@ PPCRegisterInfo::getCallPreservedMask(const 
MachineFunction &MF,
     return CSR_64_AllRegs_RegMask;
   }
 
+  if (CC == CallingConv::PreserveAll) {
+    if (TM.isPPC64()) {
+      if (Subtarget.hasAltivec())
+        return CSR_PPC64_PreserveAll_Altivec_Unknown_RegMask;
+      return CSR_PPC64_PreserveAll_Unknown_RegMask;
+    }
+    if (Subtarget.hasAltivec())
+      return CSR_PPC32_PreserveAll_Altivec_Unknown_RegMask;
+    return CSR_PPC32_PreserveAll_Unknown_RegMask;
+  }
+
   if (Subtarget.isAIXABI()) {
     if (Subtarget.pairedVectorMemops()) {
       if (!TM.getAIXExtendedAltivecABI())

>From adb7d54e85983a32aec891aad2c5b3bd77d9fe3e Mon Sep 17 00:00:00 2001
From: Luminyx <[email protected]>
Date: Sun, 14 Jun 2026 00:29:09 -0400
Subject: [PATCH 2/5] No return/cr saving, parity with AArch64

---
 clang/include/clang/Basic/AttrDocs.td       |  5 +-
 llvm/lib/Target/PowerPC/PPCCallingConv.td   | 84 +++-----------------
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp |  7 --
 llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp | 87 ++++-----------------
 4 files changed, 30 insertions(+), 153 deletions(-)

diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index ed0e1835f5b36..76e1a69391f0f 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -6711,8 +6711,9 @@ returned in callee-saved registers.
   X16-X18. Furthermore it also preserves lower 128 bits of V8-V31 SIMD - 
floating
   point registers.
 
-- On PowerPC the callee preserves all general purpose registers, except R1 and 
R2.
-  Furthermore it also preserves all floating-point and vector registers.
+- On PowerPC the callee preserves all general purpose registers, except for
+  R0-R4, R12, and R13. Furthermore it also preserves all
+  floating-point registers, except F1, and all vector registers, except V2.
 
 The idea behind this convention is to support calls to runtime functions
 that don't need to call out to any other functions.
diff --git a/llvm/lib/Target/PowerPC/PPCCallingConv.td 
b/llvm/lib/Target/PowerPC/PPCCallingConv.td
index b564b30a94bbe..ea90a62508690 100644
--- a/llvm/lib/Target/PowerPC/PPCCallingConv.td
+++ b/llvm/lib/Target/PowerPC/PPCCallingConv.td
@@ -343,89 +343,25 @@ def CSR_PPC64_R2_Altivec : CalleeSavedRegs<(add 
CSR_PPC64_Altivec, X2)>;
 
 def CSR_NoRegs : CalleeSavedRegs<(add)>;
 
-def CSR_PPC32_PreserveMost : CalleeSavedRegs<(add R0, (sequence "R%u", 3, 31),
-                                 (sequence "CR%u", 0, 7))>;
-
-def CSR_PPC32_PreserveMost_NonVoid
-    : CalleeSavedRegs<(sub CSR_PPC32_PreserveMost, R3)>;
-
 def CSR_PPC32_PreserveAll
-    : CalleeSavedRegs<(add CSR_PPC32_PreserveMost, (sequence "F%u", 0, 31))>;
-
-def CSR_PPC32_PreserveAll_Unknown
-    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll, R3, R4, F1)>;
-
-def CSR_PPC32_PreserveAll_NonVoid
-    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll, R3)>;
-
-def CSR_PPC32_PreserveAll_NonVoid_64
-    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_NonVoid, R4)>;
-
-def CSR_PPC32_PreserveAll_NonVoid_Float
-    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll, F1)>;
+    : CalleeSavedRegs<(add (sequence "R%u", 5, 10), (sequence "R%u", 14, 31),
+                           F0, (sequence "F%u", 2, 31))>;
 
 def CSR_PPC32_PreserveAll_Altivec
-    : CalleeSavedRegs<(add CSR_PPC32_PreserveAll, (sequence "V%u", 0, 31))>;
-
-def CSR_PPC32_PreserveAll_Altivec_Unknown
-    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_Altivec, R3, R4, F1, V2)>;
-
-def CSR_PPC32_PreserveAll_Altivec_NonVoid
-    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_Altivec, R3)>;
-
-def CSR_PPC32_PreserveAll_Altivec_NonVoid_64
-    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_Altivec_NonVoid, R4)>;
-
-def CSR_PPC32_PreserveAll_Altivec_NonVoid_Vec
-    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_Altivec, V2)>;
-
-def CSR_PPC32_PreserveAll_Altivec_NonVoid_Float
-    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_Altivec, F1)>;
+    : CalleeSavedRegs<(add CSR_PPC32_PreserveAll,
+                           (sequence "V%u", 0, 1), (sequence "V%u", 3, 31))>;
 
 def CSR_PPC32_PreserveAll_SPE
-    : CalleeSavedRegs<(add CSR_PPC32_PreserveMost, (sequence "S%u", 3, 31))>;
-
-def CSR_PPC32_PreserveAll_SPE_NonVoid
-    : CalleeSavedRegs<(sub CSR_PPC32_PreserveAll_SPE, R3, S3)>;
-
-def CSR_PPC64_PreserveMost : CalleeSavedRegs<(add X0, (sequence "X%u", 3, 31),
-                                 (sequence "CR%u", 0, 7))>;
-
-def CSR_PPC64_PreserveMost_NonVoid
-    : CalleeSavedRegs<(sub CSR_PPC64_PreserveMost, X3)>;
+    : CalleeSavedRegs<(add (sequence "R%u", 5, 10), (sequence "R%u", 14, 31),
+                           (sequence "S%u", 5, 31))>;
 
 def CSR_PPC64_PreserveAll
-    : CalleeSavedRegs<(add CSR_PPC64_PreserveMost, (sequence "F%u", 0, 31))>;
-
-def CSR_PPC64_PreserveAll_Unknown
-    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll, X3, X4, F1)>;
-
-def CSR_PPC64_PreserveAll_NonVoid
-    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll, X3)>;
-
-def CSR_PPC64_PreserveAll_NonVoid_Float
-    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll, F1)>;
-
-def CSR_PPC64_PreserveAll_NonVoid_128
-    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll_NonVoid, X4)>;
+    : CalleeSavedRegs<(add (sequence "X%u", 5, 10), (sequence "X%u", 14, 31),
+                           F0, (sequence "F%u", 2, 31))>;
 
 def CSR_PPC64_PreserveAll_Altivec
-    : CalleeSavedRegs<(add CSR_PPC64_PreserveAll, (sequence "V%u", 0, 31))>;
-
-def CSR_PPC64_PreserveAll_Altivec_NonVoid
-    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll_Altivec, X3)>;
-
-def CSR_PPC64_PreserveAll_Altivec_Unknown
-    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll_Altivec, X3, X4, F1, V2)>;
-
-def CSR_PPC64_PreserveAll_Altivec_NonVoid_Float
-    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll_Altivec, F1)>;
-
-def CSR_PPC64_PreserveAll_Altivec_NonVoid_Vec
-    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll_Altivec, V2)>;
-
-def CSR_PPC64_PreserveAll_Altivec_NonVoid_128
-    : CalleeSavedRegs<(sub CSR_PPC64_PreserveAll_Altivec_NonVoid, X4)>;
+    : CalleeSavedRegs<(add CSR_PPC64_PreserveAll,
+                           (sequence "V%u", 0, 1), (sequence "V%u", 3, 31))>;
 
 // coldcc calling convection marks most registers as non-volatile.
 // Do not include r1 since the stack pointer is never considered a CSR.
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp 
b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index e7937dce02496..200d026dadd7b 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -7806,18 +7806,11 @@ PPCTargetLowering::LowerReturn(SDValue Chain, 
CallingConv::ID CallConv,
   SDValue Glue;
   SmallVector<SDValue, 4> RetOps(1, Chain);
 
-  MachineFunction &MF = DAG.getMachineFunction();
-  bool ShouldDisableCalleeSavedRegister =
-      MF.getFunction().hasFnAttribute("preserve_all");
-
   // Copy the result values into the output registers.
   for (unsigned i = 0, RealResIdx = 0; i != RVLocs.size(); ++i, ++RealResIdx) {
     CCValAssign &VA = RVLocs[i];
     assert(VA.isRegLoc() && "Can only return in registers!");
 
-    if (ShouldDisableCalleeSavedRegister)
-      MF.getRegInfo().disableCalleeSavedRegister(VA.getLocReg());
-
     SDValue Arg = OutVals[RealResIdx];
 
     switch (VA.getLocInfo()) {
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp 
b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index 2712eb6b1f7cb..12330b88d6601 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -199,74 +199,20 @@ PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction 
*MF) const {
     return CSR_64_AllRegs_SaveList;
   }
 
-  const Type *const ReturnTy = MF->getFunction().getReturnType();
-
-  // Preserve registers for PreserveAll attribute
-  // We need to skip r3 (return register) if the function isn't void
-  // however for floats it's f1 instead
-  // We also need to skip r4 if the return value is 64-bit on PPC32
-  // or 128-bit on PPC64
-  bool RetVec = ReturnTy->isVectorTy();
-  bool RetFloat = ReturnTy->isFloatingPointTy();
-  bool RetInt = ReturnTy->isIntOrPtrTy();
-  TypeSize RetIntSize = ReturnTy->getPrimitiveSizeInBits();
-  bool RetVoid = ReturnTy->isVoidTy();
-
   if (MF->getFunction().getCallingConv() == CallingConv::PreserveAll) {
     if (Subtarget.hasSPE() || Subtarget.pairedVectorMemops() ||
         Subtarget.isAIXABI())
       report_fatal_error("PreserveAll unimplemented on this target.");
 
-    if (TM.isPPC64()) {
-      if (RetVoid) {
-        if (Subtarget.hasAltivec())
-          return CSR_PPC64_PreserveAll_Altivec_SaveList;
-        return CSR_PPC64_PreserveAll_SaveList;
-      }
-      if (RetVec) {
-        if (Subtarget.hasAltivec())
-          return CSR_PPC64_PreserveAll_Altivec_NonVoid_Vec_SaveList;
-        report_fatal_error("Returning vector without vector extension");
-      }
-      if (RetFloat) {
-        if (Subtarget.hasAltivec())
-          return CSR_PPC64_PreserveAll_Altivec_NonVoid_Float_SaveList;
-        return CSR_PPC64_PreserveAll_NonVoid_Float_SaveList;
-      }
-      if (RetInt) {
-        if (Subtarget.hasAltivec())
-          return RetIntSize == 128
-                     ? CSR_PPC64_PreserveAll_Altivec_NonVoid_128_SaveList
-                     : CSR_PPC64_PreserveAll_Altivec_NonVoid_SaveList;
-        return RetIntSize == 128 ? CSR_PPC64_PreserveAll_NonVoid_128_SaveList
-                                 : CSR_PPC64_PreserveAll_NonVoid_SaveList;
-      }
-      report_fatal_error("Unhandled return type");
-    }
-    // PPC32:
-    if (RetVoid) {
-      if (Subtarget.hasAltivec())
-        return CSR_PPC32_PreserveAll_Altivec_SaveList;
-      return CSR_PPC32_PreserveAll_SaveList;
-    }
-    if (RetVec) {
-      if (Subtarget.hasAltivec())
-        return CSR_PPC32_PreserveAll_Altivec_NonVoid_Vec_SaveList;
-      report_fatal_error("Returning vector without vector extension");
-    }
-    if (RetFloat) {
-      if (Subtarget.hasAltivec())
-        return CSR_PPC32_PreserveAll_Altivec_NonVoid_Float_SaveList;
-      return CSR_PPC32_PreserveAll_NonVoid_Float_SaveList;
-    }
-    if (RetInt) {
-      if (Subtarget.hasAltivec())
-        return RetIntSize == 64
-                   ? CSR_PPC32_PreserveAll_Altivec_NonVoid_64_SaveList
-                   : CSR_PPC32_PreserveAll_Altivec_NonVoid_SaveList;
-      return RetIntSize == 64 ? CSR_PPC32_PreserveAll_NonVoid_64_SaveList
-                              : CSR_PPC32_PreserveAll_NonVoid_SaveList;
-    }
+    if (TM.isPPC64())
+      return Subtarget.hasAltivec() ? CSR_PPC64_PreserveAll_Altivec_SaveList
+                                    : CSR_PPC64_PreserveAll_SaveList;
+
+    if (Subtarget.hasAltivec())
+      return CSR_PPC32_PreserveAll_Altivec_SaveList;
+    if (Subtarget.hasSPE())
+      return CSR_PPC32_PreserveAll_SPE_SaveList;
+    return CSR_PPC32_PreserveAll_SaveList;
   }
 
   // On PPC64, we might need to save r2 (but only if it is not reserved).
@@ -362,14 +308,15 @@ PPCRegisterInfo::getCallPreservedMask(const 
MachineFunction &MF,
   }
 
   if (CC == CallingConv::PreserveAll) {
-    if (TM.isPPC64()) {
-      if (Subtarget.hasAltivec())
-        return CSR_PPC64_PreserveAll_Altivec_Unknown_RegMask;
-      return CSR_PPC64_PreserveAll_Unknown_RegMask;
-    }
+    if (TM.isPPC64())
+      return Subtarget.hasAltivec() ? CSR_PPC64_PreserveAll_Altivec_RegMask
+                                    : CSR_PPC64_PreserveAll_RegMask;
+
     if (Subtarget.hasAltivec())
-      return CSR_PPC32_PreserveAll_Altivec_Unknown_RegMask;
-    return CSR_PPC32_PreserveAll_Unknown_RegMask;
+      return CSR_PPC32_PreserveAll_Altivec_RegMask;
+    if (Subtarget.hasSPE())
+      return CSR_PPC32_PreserveAll_SPE_RegMask;
+    return CSR_PPC32_PreserveAll_RegMask;
   }
 
   if (Subtarget.isAIXABI()) {

>From 6f911af882fc1c822ac7f90e4a262d18a5e5929e Mon Sep 17 00:00:00 2001
From: Luminyx <[email protected]>
Date: Sun, 14 Jun 2026 00:54:48 -0400
Subject: [PATCH 3/5] Allow SPE in preserve cc path

---
 llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp 
b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index 12330b88d6601..1160d457c0644 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -200,8 +200,7 @@ PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction 
*MF) const {
   }
 
   if (MF->getFunction().getCallingConv() == CallingConv::PreserveAll) {
-    if (Subtarget.hasSPE() || Subtarget.pairedVectorMemops() ||
-        Subtarget.isAIXABI())
+    if (Subtarget.pairedVectorMemops() || Subtarget.isAIXABI())
       report_fatal_error("PreserveAll unimplemented on this target.");
 
     if (TM.isPPC64())

>From 13d5bef014cc65b83face25857eb050971b9dc59 Mon Sep 17 00:00:00 2001
From: Luminyx <[email protected]>
Date: Sun, 14 Jun 2026 01:09:10 -0400
Subject: [PATCH 4/5] Preserve R11

---
 llvm/lib/Target/PowerPC/PPCCallingConv.td | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/PPCCallingConv.td 
b/llvm/lib/Target/PowerPC/PPCCallingConv.td
index ea90a62508690..ba1bcc13d596f 100644
--- a/llvm/lib/Target/PowerPC/PPCCallingConv.td
+++ b/llvm/lib/Target/PowerPC/PPCCallingConv.td
@@ -344,7 +344,7 @@ def CSR_PPC64_R2_Altivec : CalleeSavedRegs<(add 
CSR_PPC64_Altivec, X2)>;
 def CSR_NoRegs : CalleeSavedRegs<(add)>;
 
 def CSR_PPC32_PreserveAll
-    : CalleeSavedRegs<(add (sequence "R%u", 5, 10), (sequence "R%u", 14, 31),
+    : CalleeSavedRegs<(add (sequence "R%u", 5, 11), (sequence "R%u", 14, 31),
                            F0, (sequence "F%u", 2, 31))>;
 
 def CSR_PPC32_PreserveAll_Altivec
@@ -352,11 +352,11 @@ def CSR_PPC32_PreserveAll_Altivec
                            (sequence "V%u", 0, 1), (sequence "V%u", 3, 31))>;
 
 def CSR_PPC32_PreserveAll_SPE
-    : CalleeSavedRegs<(add (sequence "R%u", 5, 10), (sequence "R%u", 14, 31),
+    : CalleeSavedRegs<(add (sequence "R%u", 5, 11), (sequence "R%u", 14, 31),
                            (sequence "S%u", 5, 31))>;
 
 def CSR_PPC64_PreserveAll
-    : CalleeSavedRegs<(add (sequence "X%u", 5, 10), (sequence "X%u", 14, 31),
+    : CalleeSavedRegs<(add (sequence "X%u", 5, 11), (sequence "X%u", 14, 31),
                            F0, (sequence "F%u", 2, 31))>;
 
 def CSR_PPC64_PreserveAll_Altivec

>From 776291b32f59e9e68248b23afdc62210d275daa0 Mon Sep 17 00:00:00 2001
From: Luminyx <[email protected]>
Date: Sun, 14 Jun 2026 01:28:22 -0400
Subject: [PATCH 5/5] Preserve R2 when needed

---
 clang/include/clang/Basic/AttrDocs.td       |  5 ++--
 llvm/lib/Target/PowerPC/PPCCallingConv.td   |  6 +++++
 llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp | 30 ++++++++++++---------
 3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 76e1a69391f0f..ffed3773471a4 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -6712,8 +6712,9 @@ returned in callee-saved registers.
   point registers.
 
 - On PowerPC the callee preserves all general purpose registers, except for
-  R0-R4, R12, and R13. Furthermore it also preserves all
-  floating-point registers, except F1, and all vector registers, except V2.
+  R0, R3, R4, R12, and R13. R2 is preserved on PPC64 when used as the TOC
+  register. Furthermore it also preserves all floating-point registers, except
+  F1, and all vector registers, except V2.
 
 The idea behind this convention is to support calls to runtime functions
 that don't need to call out to any other functions.
diff --git a/llvm/lib/Target/PowerPC/PPCCallingConv.td 
b/llvm/lib/Target/PowerPC/PPCCallingConv.td
index ba1bcc13d596f..55954e2984f1f 100644
--- a/llvm/lib/Target/PowerPC/PPCCallingConv.td
+++ b/llvm/lib/Target/PowerPC/PPCCallingConv.td
@@ -363,6 +363,12 @@ def CSR_PPC64_PreserveAll_Altivec
     : CalleeSavedRegs<(add CSR_PPC64_PreserveAll,
                            (sequence "V%u", 0, 1), (sequence "V%u", 3, 31))>;
 
+def CSR_PPC64_PreserveAll_R2
+    : CalleeSavedRegs<(add CSR_PPC64_PreserveAll, X2)>;
+
+def CSR_PPC64_PreserveAll_R2_Altivec
+    : CalleeSavedRegs<(add CSR_PPC64_PreserveAll_Altivec, X2)>;
+
 // coldcc calling convection marks most registers as non-volatile.
 // Do not include r1 since the stack pointer is never considered a CSR.
 // Do not include r2, since it is the TOC register and is added depending
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp 
b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index 1160d457c0644..d3b592383228b 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -199,13 +199,27 @@ PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction 
*MF) const {
     return CSR_64_AllRegs_SaveList;
   }
 
+  // On PPC64, we might need to save r2 (but only if it is not reserved).
+  // We do not need to treat R2 as callee-saved when using PC-Relative calls
+  // because any direct uses of R2 will cause it to be reserved. If the 
function
+  // is a leaf or the only uses of R2 are implicit uses for calls, the calls
+  // will use the @notoc relocation which will cause this function to set the
+  // st_other bit to 1, thereby communicating to its caller that it arbitrarily
+  // clobbers the TOC.
+  bool SaveR2 = MF->getRegInfo().isAllocatable(PPC::X2) &&
+                !Subtarget.isUsingPCRelativeCalls();
+
   if (MF->getFunction().getCallingConv() == CallingConv::PreserveAll) {
     if (Subtarget.pairedVectorMemops() || Subtarget.isAIXABI())
       report_fatal_error("PreserveAll unimplemented on this target.");
 
-    if (TM.isPPC64())
-      return Subtarget.hasAltivec() ? CSR_PPC64_PreserveAll_Altivec_SaveList
-                                    : CSR_PPC64_PreserveAll_SaveList;
+    if (TM.isPPC64()) {
+      if (Subtarget.hasAltivec())
+        return SaveR2 ? CSR_PPC64_PreserveAll_R2_Altivec_SaveList
+                      : CSR_PPC64_PreserveAll_Altivec_SaveList;
+      return SaveR2 ? CSR_PPC64_PreserveAll_R2_SaveList
+                    : CSR_PPC64_PreserveAll_SaveList;
+    }
 
     if (Subtarget.hasAltivec())
       return CSR_PPC32_PreserveAll_Altivec_SaveList;
@@ -214,16 +228,6 @@ PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction 
*MF) const {
     return CSR_PPC32_PreserveAll_SaveList;
   }
 
-  // On PPC64, we might need to save r2 (but only if it is not reserved).
-  // We do not need to treat R2 as callee-saved when using PC-Relative calls
-  // because any direct uses of R2 will cause it to be reserved. If the 
function
-  // is a leaf or the only uses of R2 are implicit uses for calls, the calls
-  // will use the @notoc relocation which will cause this function to set the
-  // st_other bit to 1, thereby communicating to its caller that it arbitrarily
-  // clobbers the TOC.
-  bool SaveR2 = MF->getRegInfo().isAllocatable(PPC::X2) &&
-                !Subtarget.isUsingPCRelativeCalls();
-
   // Cold calling convention CSRs.
   if (MF->getFunction().getCallingConv() == CallingConv::Cold) {
     if (Subtarget.isAIXABI())

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to