[llvm-branch-commits] [clang] [llvm] release/22.x: [SystemZ] Enable -fpatchable-function-entry=M, N (#178191) (PR #194365)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Apr 27 06:21:08 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-systemz

Author: llvmbot

<details>
<summary>Changes</summary>

Backport 355898a

Requested by: @<!-- -->dominik-steenken

---
Full diff: https://github.com/llvm/llvm-project/pull/194365.diff


7 Files Affected:

- (modified) clang/include/clang/Basic/Attr.td (+4-3) 
- (modified) clang/include/clang/Basic/AttrDocs.td (+1-1) 
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (+1-1) 
- (modified) llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp (+21) 
- (modified) llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp (+5) 
- (modified) llvm/lib/Target/SystemZ/SystemZInstrInfo.h (+2) 
- (added) llvm/test/CodeGen/SystemZ/patchable-function-entry.ll (+102) 


``````````diff
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index efa64dbe4b51e..e98592f62b023 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -967,9 +967,10 @@ def XRayLogArgs : InheritableAttr {
 
 def PatchableFunctionEntry
     : InheritableAttr,
-      TargetSpecificAttr<TargetArch<
-          ["aarch64", "aarch64_be", "loongarch32", "loongarch64", "riscv32",
-           "riscv64", "x86", "x86_64", "ppc", "ppc64", "ppc64le"]>> {
+      TargetSpecificAttr<
+          TargetArch<["aarch64", "aarch64_be", "loongarch32", "loongarch64",
+                      "riscv32", "riscv64", "x86", "x86_64", "ppc", "ppc64",
+                      "ppc64le", "systemz"]>> {
   let Spellings = [GCC<"patchable_function_entry">];
   let Subjects = SubjectList<[Function, ObjCMethod]>;
   let Args = [UnsignedArgument<"Count">, DefaultIntArgument<"Offset", 0>,
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 812b48058d189..3854e0dff88f3 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -6749,7 +6749,7 @@ if omitted.``Section`` defaults  to the ``-fpatchable-function-entry`` section n
 set, or to ``__patchable_function_entries`` otherwise.
 
 This attribute is only supported on
-aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64/ppc/ppc64/ppc64le targets.
+aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64/ppc/ppc64/ppc64le/s390x targets.
 For ppc/ppc64 targets, AIX is still not supported.
 }];
 }
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 18933cb8ad7c2..3fd5eef60b019 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6777,7 +6777,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     StringRef S0 = A->getValue(), S = S0;
     unsigned Size, Offset = 0;
     if (!Triple.isAArch64() && !Triple.isLoongArch() && !Triple.isRISCV() &&
-        !Triple.isX86() &&
+        !Triple.isX86() && !Triple.isSystemZ() &&
         !(!Triple.isOSAIX() && (Triple.getArch() == llvm::Triple::ppc ||
                                 Triple.getArch() == llvm::Triple::ppc64 ||
                                 Triple.getArch() == llvm::Triple::ppc64le)))
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index fcde175b42643..15ac5a4af0d29 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -901,6 +901,27 @@ void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
 
 void SystemZAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
     const MachineInstr &MI, SystemZMCInstLower &Lower) {
+
+  const MachineFunction &MF = *(MI.getParent()->getParent());
+  const Function &F = MF.getFunction();
+
+  // If patchable-function-entry is set, emit in-function nops here.
+  if (F.hasFnAttribute("patchable-function-entry")) {
+    unsigned Num;
+    // get M-N from function attribute (CodeGenFunction subtracts N
+    // from M to yield the correct patchable-function-entry).
+    if (F.getFnAttribute("patchable-function-entry")
+            .getValueAsString()
+            .getAsInteger(10, Num))
+      return;
+    // Emit M-N 2-byte nops. Use getNop() here instead of emitNops()
+    // to keep it aligned with the common code implementation emitting
+    // the prefix nops.
+    for (unsigned I = 0; I < Num; ++I)
+      EmitToStreamer(*OutStreamer, MF.getSubtarget().getInstrInfo()->getNop());
+    return;
+  }
+  // Otherwise, emit xray sled.
   // .begin:
   //   j .end    # -> stmg    %r2, %r15, 16(%r15)
   //   nop
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
index 913c62f9f8449..6397f237666e6 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
@@ -33,6 +33,7 @@
 #include "llvm/CodeGen/TargetOpcodes.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/CodeGen/VirtRegMap.h"
+#include "llvm/MC/MCInstBuilder.h"
 #include "llvm/MC/MCInstrDesc.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/Support/BranchProbability.h"
@@ -2378,3 +2379,7 @@ SystemZInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
       {MO_ADA_DIRECT_FUNC_DESC, "systemz-ada-directfuncdesc"}};
   return ArrayRef(TargetFlags);
 }
+
+MCInst SystemZInstrInfo::getNop() const {
+  return MCInstBuilder(SystemZ::NOPR).addReg(0);
+}
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
index 6fc66c72a25e6..29ae9e0ed80e7 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
@@ -391,6 +391,8 @@ class SystemZInstrInfo : public SystemZGenInstrInfo {
 
   ArrayRef<std::pair<unsigned, const char *>>
   getSerializableDirectMachineOperandTargetFlags() const override;
+
+  MCInst getNop() const override;
 };
 
 } // end namespace llvm
diff --git a/llvm/test/CodeGen/SystemZ/patchable-function-entry.ll b/llvm/test/CodeGen/SystemZ/patchable-function-entry.ll
new file mode 100644
index 0000000000000..24c5ab4502bf0
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/patchable-function-entry.ll
@@ -0,0 +1,102 @@
+; RUN: llc -mtriple=s390x-ibm-linux %s -o - | FileCheck %s
+; RUN: llc -mtriple=s390x-ibm-linux -function-sections %s -o - | FileCheck %s
+; RUN: llc -mtriple=s390x-ibm-linux -function-sections %s -o - | FileCheck %s
+; RUN: llc -mtriple=s390x-ibm-linux -no-integrated-as -binutils-version=2.35 %s -o - | FileCheck --check-prefix=NOLINK %s
+; RUN: llc -mtriple=s390x-ibm-linux -no-integrated-as -binutils-version=2.36 %s -o - | FileCheck %s
+
+;; GNU ld < 2.36 did not support mixed SHF_LINK_ORDER and non-SHF_LINK_ORDER sections.
+; NOLINK-NOT: "awo"
+
+define i32 @f0() "patchable-function-entry"="0" {
+; CHECK-LABEL: f0:
+; CHECK-NEXT: .Lfunc_begin0:
+; CHECK-NOT:   nopr
+; CHECK:       lhi     %r2, 0
+; CHECK-NOT:   .section __patchable_function_entries
+  ret i32 0
+}
+
+define i32 @f1() "patchable-function-entry"="1" {
+; CHECK-LABEL: f1:
+; CHECK-NEXT: .Lfunc_begin1:
+; CHECK:       nopr
+; CHECK-NEXT:  lhi     %r2, 0
+; CHECK:       .section __patchable_function_entries,"awo", at progbits,f1{{$}}
+; CHECK-NEXT:  .p2align 3, 0x0
+; CHECK-NEXT: .quad   .Lfunc_begin1
+  ret i32 0
+}
+
+;; Without -function-sections, f2 is in the same text section as f1.
+;; They share the __patchable_function_entries section.
+;; With -function-sections, f1 and f2 are in different text sections.
+;; Use separate __patchable_function_entries.
+define void @f2() "patchable-function-entry"="2" {
+; CHECK-LABEL: f2:
+; CHECK-NEXT: .Lfunc_begin2:
+; CHECK-COUNT-2: nopr
+; CHECK-NEXT:  br      %r14
+; CHECK:       .section __patchable_function_entries,"awo", at progbits,f2{{$}}
+; CHECK-NEXT:  .p2align 3, 0x0
+; CHECK-NEXT: .quad   .Lfunc_begin2
+  ret void
+}
+
+$f3 = comdat any
+define void @f3() "patchable-function-entry"="3" comdat {
+; CHECK-LABEL: f3:
+; CHECK-NEXT: .Lfunc_begin3:
+; CHECK-COUNT-3: nopr
+; CHECK-NEXT:  br      %r14
+; CHECK:       .section __patchable_function_entries,"awoG", at progbits,f3,f3,comdat{{$}}
+; CHECK-NEXT:  .p2align 3, 0x0
+; CHECK-NEXT: .quad   .Lfunc_begin3
+  ret void
+}
+
+$f5 = comdat any
+define void @f5() "patchable-function-entry"="5" comdat {
+; CHECK-LABEL: f5:
+; CHECK-NEXT: .Lfunc_begin4:
+; CHECK-COUNT-5: nopr
+; CHECK-NEXT:  aghi    %r15, -176
+; CHECK:       .section __patchable_function_entries,"awoG", at progbits,f5,f5,comdat{{$}}
+; CHECK:       .p2align 3, 0x0
+; CHECK-NEXT: .quad   .Lfunc_begin4
+  %frame = alloca i8, i32 16
+  ret void
+}
+
+;; -fpatchable-function-entry=3,2
+;; "patchable-function-prefix" emits data before the function entry label.
+define void @f3_2() "patchable-function-entry"="1" "patchable-function-prefix"="2" {
+; CHECK-LABEL: .type f3_2, at function
+; CHECK-NEXT: .Ltmp0:
+; CHECK-NEXT:  nopr
+; CHECK-NEXT:  nopr
+; CHECK-NEXT: f3_2:  # @f3_2
+; CHECK:      # %bb.0:
+; CHECK-NEXT:  nopr
+; CHECK-NEXT:  br      %r14
+;; .size does not include the prefix.
+; CHECK:      .Lfunc_end5:
+; CHECK-NEXT: .size f3_2, .Lfunc_end5-f3_2
+; CHECK:      .section __patchable_function_entries,"awo", at progbits,f3_2{{$}}
+; CHECK:      .p2align 3, 0x0
+; CHECK-NEXT: .quad   .Ltmp0
+  ret void
+}
+
+;; When prefix data is used, arbitrarily place noprs after prefix data.
+define void @prefix() "patchable-function-entry"="0" "patchable-function-prefix"="1" prefix i32 1 {
+; CHECK-LABEL: .type prefix, at function
+; CHECK-NEXT: .long 1 # 0x1
+; CHECK:      .Ltmp1:
+; CHECK:       nopr
+; CHECK-NEXT: prefix:  # @prefix
+;; Emit a __patchable_function_entries entry even if "patchable-function-entry" is 0.
+; CHECK:      .section __patchable_function_entries,"awo", at progbits,prefix{{$}}
+; CHECK:      .p2align        3, 0x0
+; CHECK-NEXT: .quad   .Ltmp1
+  ret void
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/194365


More information about the llvm-branch-commits mailing list