1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
|
From 9b15701c8add66db542f66fe20a5a0e9caef7e4d Mon Sep 17 00:00:00 2001
From: Josh Stone <jistone@redhat.com>
Date: Mon, 25 Aug 2025 15:31:27 -0700
Subject: [PATCH] [PowerPC] Indicate that PPC32PICGOT clobbers LR (#154654)
This pseudo-instruction emits a local `bl` writing LR, so that must be
saved and restored for the function to return to the right place. If
not, we'll return to the inline `.long` that the `bl` stepped over.
This fixes the `SIGILL` seen in rayon-rs/rayon#1268.
---
llvm/lib/Target/PowerPC/PPCInstrInfo.td | 3 ++-
llvm/test/CodeGen/PowerPC/tls-picgot.ll | 31 +++++++++++++++++++++++++
2 files changed, 33 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/PowerPC/tls-picgot.ll
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index 69f8ddc0ea70..151df8800aa9 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -3224,7 +3224,8 @@ def PPC32GOT: PPCEmitTimePseudo<(outs gprc:$rD), (ins), "#PPC32GOT",
// Get the _GLOBAL_OFFSET_TABLE_ in PIC mode.
// This uses two output registers, the first as the real output, the second as a
-// temporary register, used internally in code generation.
+// temporary register, used internally in code generation. A "bl" also clobbers LR.
+let Defs = [LR] in
def PPC32PICGOT: PPCEmitTimePseudo<(outs gprc:$rD, gprc:$rT), (ins), "#PPC32PICGOT",
[]>, NoEncode<"$rT">;
diff --git a/llvm/test/CodeGen/PowerPC/tls-picgot.ll b/llvm/test/CodeGen/PowerPC/tls-picgot.ll
new file mode 100644
index 000000000000..6562d864d1ba
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/tls-picgot.ll
@@ -0,0 +1,31 @@
+; RUN: llc -verify-machineinstrs -relocation-model=pic < %s | FileCheck %s
+
+target triple = "powerpc-unknown-linux-gnu"
+
+; Test that LR is preserved when PPC32PICGOT clobbers it with a local "bl".
+
+@TLS = external thread_local global i8
+
+; CHECK-LABEL: tls_addr:
+; CHECK: mflr [[SAVED_REG:[0-9]+]]
+
+; CHECK: bl [[JUMP:\.L[[:alnum:]_]+]]
+; CHECK-NEXT: [[OFFSET:\.L[[:alnum:]_]+]]:
+; CHECK-NEXT: .long _GLOBAL_OFFSET_TABLE_-[[OFFSET]]
+; CHECK-NEXT: [[JUMP]]
+; CHECK-NEXT: mflr {{[0-9]+}}
+
+; CHECK: mtlr [[SAVED_REG]]
+; CHECK-NEXT: blr
+
+define ptr @tls_addr() unnamed_addr {
+ %1 = call ptr @llvm.threadlocal.address.p0(ptr @TLS)
+ ret ptr %1
+}
+
+declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 8, !"PIC Level", i32 2}
+!1 = !{i32 7, !"PIE Level", i32 2}
--
2.51.0
|