[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