[llvm] Fix emulated TLS alignment for large variables (PR #171037)
Medha Tiwari via llvm-commits
llvm-commits at lists.llvm.org
Sun Feb 8 22:13:44 PST 2026
https://github.com/medhatiwari updated https://github.com/llvm/llvm-project/pull/171037
>From c86c62e2bb293f1e6cecf4546a4999f9fabdc416 Mon Sep 17 00:00:00 2001
From: Medha Tiwari <medhatiwari at ibm.com>
Date: Sun, 7 Dec 2025 18:38:02 +0530
Subject: [PATCH 1/4] [CodeGen] Fix emulated TLS alignment for large variables
For types larger than a vector register (16 bytes), use the preferred
alignment to ensure the backend can use vectorized load/store instructions.
This fixes crashes when memcpy of large TLS arrays uses ARM NEON vld1.64
which requires 16-byte alignment, but emulated TLS only provided 1-byte
alignment.
Fixes #167219
---
llvm/lib/CodeGen/LowerEmuTLS.cpp | 7 +++++++
llvm/test/CodeGen/ARM/emutls-alignment.ll | 20 ++++++++++++++++++++
2 files changed, 27 insertions(+)
create mode 100644 llvm/test/CodeGen/ARM/emutls-alignment.ll
diff --git a/llvm/lib/CodeGen/LowerEmuTLS.cpp b/llvm/lib/CodeGen/LowerEmuTLS.cpp
index c81f0184cf213..b216dd45d0be9 100644
--- a/llvm/lib/CodeGen/LowerEmuTLS.cpp
+++ b/llvm/lib/CodeGen/LowerEmuTLS.cpp
@@ -150,6 +150,13 @@ bool addEmuTlsVar(Module &M, const GlobalVariable *GV) {
Type *GVType = GV->getValueType();
Align GVAlignment = DL.getValueOrABITypeAlignment(GV->getAlign(), GVType);
+ // For types larger than a vector register, use preferred alignment.
+ // This ensures the backend can use vectorized load/store instructions
+ // (e.g., memcpy of large arrays may use ARM NEON vld1.64 which requires
+ // 16-byte alignment). See https://github.com/llvm/llvm-project/issues/167219
+ if (DL.getTypeStoreSize(GVType) > 16)
+ GVAlignment = std::max(GVAlignment, DL.getPreferredAlign(GV));
+
// Define "__emutls_t.*" if there is InitValue
GlobalVariable *EmuTlsTmplVar = nullptr;
if (InitValue) {
diff --git a/llvm/test/CodeGen/ARM/emutls-alignment.ll b/llvm/test/CodeGen/ARM/emutls-alignment.ll
new file mode 100644
index 0000000000000..9668bd75ce299
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/emutls-alignment.ll
@@ -0,0 +1,20 @@
+; RUN: llc -emulated-tls -mtriple=armv7-linux-android -relocation-model=pic < %s | FileCheck %s
+
+; Test that emulated TLS uses preferred alignment for variables.
+; This fixes a bug where emutls would use lower alignment than expected
+; by the code generator, causing crashes with vectorized accesses.
+; Fixes https://github.com/llvm/llvm-project/issues/167219
+
+; A 64-byte array should get 16-byte alignment (preferred for ARM NEON).
+ at large_array = internal thread_local global [64 x i8] c"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+
+define ptr @get_large_array() {
+entry:
+ ret ptr @large_array
+}
+
+; CHECK-LABEL: __emutls_v.large_array:
+; CHECK-NEXT: .long 64
+; CHECK-NEXT: .long 16
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long __emutls_t.large_array
>From 4cd3183ee6fffa0d0507869df9c8e79571cf447c Mon Sep 17 00:00:00 2001
From: Medha Tiwari <medhavns1 at gmail.com>
Date: Sun, 8 Feb 2026 19:04:04 +0530
Subject: [PATCH 2/4] Resolve review: use getPreferredAlign for all TLS
---
llvm/lib/CodeGen/LowerEmuTLS.cpp | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/llvm/lib/CodeGen/LowerEmuTLS.cpp b/llvm/lib/CodeGen/LowerEmuTLS.cpp
index b216dd45d0be9..3f0c2e2a21e0b 100644
--- a/llvm/lib/CodeGen/LowerEmuTLS.cpp
+++ b/llvm/lib/CodeGen/LowerEmuTLS.cpp
@@ -148,14 +148,7 @@ bool addEmuTlsVar(Module &M, const GlobalVariable *GV) {
return true;
Type *GVType = GV->getValueType();
- Align GVAlignment = DL.getValueOrABITypeAlignment(GV->getAlign(), GVType);
-
- // For types larger than a vector register, use preferred alignment.
- // This ensures the backend can use vectorized load/store instructions
- // (e.g., memcpy of large arrays may use ARM NEON vld1.64 which requires
- // 16-byte alignment). See https://github.com/llvm/llvm-project/issues/167219
- if (DL.getTypeStoreSize(GVType) > 16)
- GVAlignment = std::max(GVAlignment, DL.getPreferredAlign(GV));
+ Align GVAlignment = DL.getPreferredAlign(GV);
// Define "__emutls_t.*" if there is InitValue
GlobalVariable *EmuTlsTmplVar = nullptr;
>From 56cf33b601ff7bb22bdad33376b43ddf60891193 Mon Sep 17 00:00:00 2001
From: Medha Tiwari <medhatiwari at Medhas-MacBook-Pro.local>
Date: Sun, 8 Feb 2026 22:13:46 +0530
Subject: [PATCH 3/4] Update AArch64 emutls test for getPreferredAlign
alignment
---
llvm/test/CodeGen/AArch64/emutls.ll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/emutls.ll b/llvm/test/CodeGen/AArch64/emutls.ll
index 4ca9fd5cd87d6..db3c3c7f7305e 100644
--- a/llvm/test/CodeGen/AArch64/emutls.ll
+++ b/llvm/test/CodeGen/AArch64/emutls.ll
@@ -175,7 +175,7 @@ entry:
; ARM64: .globl __emutls_v.s1
; ARM64-LABEL: __emutls_v.s1:
; ARM64-NEXT: .xword 2
-; ARM64-NEXT: .xword 2
+; ARM64-NEXT: .xword 4
; ARM64-NEXT: .xword 0
; ARM64-NEXT: .xword __emutls_t.s1
@@ -186,7 +186,7 @@ entry:
; ARM64: .data{{$}}
; ARM64-LABEL: __emutls_v.b1:
; ARM64-NEXT: .xword 1
-; ARM64-NEXT: .xword 1
+; ARM64-NEXT: .xword 4
; ARM64-NEXT: .xword 0
; ARM64-NEXT: .xword 0
>From 93145ebee1326e684970d54363eeaec7aa1adab9 Mon Sep 17 00:00:00 2001
From: Medha Tiwari <medhatiwari at Medhas-MacBook-Pro.local>
Date: Mon, 9 Feb 2026 11:43:09 +0530
Subject: [PATCH 4/4] Resolve review: use getPointerAlignment for TLS
---
llvm/lib/CodeGen/LowerEmuTLS.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/LowerEmuTLS.cpp b/llvm/lib/CodeGen/LowerEmuTLS.cpp
index 3f0c2e2a21e0b..aa80ef78baea7 100644
--- a/llvm/lib/CodeGen/LowerEmuTLS.cpp
+++ b/llvm/lib/CodeGen/LowerEmuTLS.cpp
@@ -148,7 +148,7 @@ bool addEmuTlsVar(Module &M, const GlobalVariable *GV) {
return true;
Type *GVType = GV->getValueType();
- Align GVAlignment = DL.getPreferredAlign(GV);
+ Align GVAlignment = GV->getPointerAlignment(DL);
// Define "__emutls_t.*" if there is InitValue
GlobalVariable *EmuTlsTmplVar = nullptr;
More information about the llvm-commits
mailing list