[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