| Issue |
167219
|
| Summary |
Incorrect alignment assumption for emulated TLS on ARMv7
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
goottime
|
## Description
The LLVM compiler generates incorrect ARM assembly code that assumes 128-bit alignment for emulated TLS variables, when only 32-bit (4-byte) alignment is guaranteed.
## Reproducer
Given the following LLVM IR:
```llvm
@test = internal thread_local(localdynamic) global [64 x i8] c"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1 immarg)
define void @testfunc() {
%1 = alloca [64 x i8], align 1
%a = getelementptr inbounds [64 x i8], [64 x i8]* %1, i32 0, i32 0
%b = getelementptr inbounds [64 x i8], [64 x i8]* @test, i32 0, i32 0
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a, i8* %b, i32 64, i1 false)
ret void
}
```
Compiled with: `llc -O3 -emulated-tls -mtriple=armv7-linux-gnueabihf`
## Actual Output
```asm
testfunc: @ @testfunc
push {r11, lr}
sub sp, sp, #64
movw r0, :lower16:__emutls_v.test
movt r0, :upper16:__emutls_v.test
bl __emutls_get_address
vld1.64 {d16, d17}, [r0:128]!
vld1.64 {d18, d19}, [r0:128]!
vld1.64 {d20, d21}, [r0:128]!
vld1.64 {d22, d23}, [r0:128]
mov r0, sp
vst1.64 {d16, d17}, [r0]!
vst1.64 {d18, d19}, [r0]!
vst1.64 {d20, d21}, [r0]!
vst1.64 {d22, d23}, [r0]
add sp, sp, #64
pop {r11, pc}
__emutls_v.test:
.long 64 @ 0x40
.long 1 @ 0x1
.long 0
.long __emutls_t.test
__emutls_t.test:
.zero 64,65
```
## Problem
The generated code uses `vld1.64` instructions with `:128` alignment specifiers, which require 128-bit (16-byte) alignment. However, emulated TLS only guarantees 4-byte alignment on ARMv7.
>From the emulated TLS implementation in [_compiler-rt/lib/builtins/emutls.c_](https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/builtins/emutls.c):
```c
static __inline void *emutls_allocate_object(__emutls_control *control) {
size_t size = control->size;
size_t align = control->align;
void *base;
if (align < sizeof(void *))
align = sizeof(void *); // Only guarantees pointer-size alignment (4 bytes on ARMv7)
// ...
}
```
This mismatch between assumed alignment (128-bit) and actual alignment (32-bit) will cause crashes or undefined behavior at runtime.
## Expected Behavior
The compiler should either:
- Use unaligned load instructions when emulated TLS is enabled, or
- Ensure emulated TLS allocations meet the alignment requirements used in the generated code
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs