Skip to content

Commit c6cd460

Browse files
authored
IRVerifier: Allow GlobalValue as llvm.threadlocal.address operand (#88321)
Loosen `llvm.threadlocal.address` verifier checks to allow any `GlobalValue` with `isThreadLocal()` set to true.
1 parent 0f82469 commit c6cd460

File tree

4 files changed

+53
-5
lines changed

4 files changed

+53
-5
lines changed

llvm/docs/LangRef.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28130,7 +28130,8 @@ Syntax:
2813028130
Arguments:
2813128131
""""""""""
2813228132

28133-
The first argument is a thread local :ref:`global variable <globalvars>`.
28133+
The `llvm.threadlocal.address` intrinsic requires a global value argument (a
28134+
:ref:`global variable <globalvars>` or alias) that is thread local.
2813428135

2813528136
Semantics:
2813628137
""""""""""

llvm/lib/IR/Verifier.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6226,10 +6226,10 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
62266226
}
62276227
case Intrinsic::threadlocal_address: {
62286228
const Value &Arg0 = *Call.getArgOperand(0);
6229-
Check(isa<GlobalVariable>(Arg0),
6230-
"llvm.threadlocal.address first argument must be a GlobalVariable");
6231-
Check(cast<GlobalVariable>(Arg0).isThreadLocal(),
6232-
"llvm.threadlocal.address operand isThreadLocal() must no be false");
6229+
Check(isa<GlobalValue>(Arg0),
6230+
"llvm.threadlocal.address first argument must be a GlobalValue");
6231+
Check(cast<GlobalValue>(Arg0).isThreadLocal(),
6232+
"llvm.threadlocal.address operand isThreadLocal() must be true");
62336233
break;
62346234
}
62356235
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
; RUN: opt -passes=verify -S < %s | FileCheck %s
2+
3+
@var = thread_local global i32 0
4+
@alias = thread_local alias i32, ptr @var
5+
6+
; CHECK-LABEL: @should_pass
7+
define void @should_pass() {
8+
%p0 = call ptr @llvm.threadlocal.address(ptr @var)
9+
store i32 42, ptr %p0, align 4
10+
%p1 = call ptr @llvm.threadlocal.address(ptr @alias)
11+
store i32 13, ptr %p1, align 4
12+
ret void
13+
}

llvm/test/Verifier/threadlocal.ll

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
2+
3+
@var = global i32 0
4+
@tlsvar = thread_local addrspace(1) global i32 0
5+
6+
define void @fail0(ptr %arg) {
7+
; CHECK: llvm.threadlocal.address first argument must be a GlobalValue
8+
%p0 = call ptr @llvm.threadlocal.address(ptr %arg)
9+
store i32 42, ptr %p0, align 4
10+
ret void
11+
}
12+
13+
define void @fail1() {
14+
; CHECK: llvm.threadlocal.address first argument must be a GlobalValue
15+
%p0 = call ptr @llvm.threadlocal.address.p0(ptr addrspacecast (ptr addrspace(1) @tlsvar to ptr addrspace(0)))
16+
store i32 42, ptr %p0, align 4
17+
ret void
18+
}
19+
20+
21+
22+
define void @fail2() {
23+
; CHECK: llvm.threadlocal.address operand isThreadLocal() must be true
24+
%p0 = call ptr @llvm.threadlocal.address(ptr @var)
25+
store i32 42, ptr %p0, align 4
26+
ret void
27+
}
28+
29+
define void @fail3() {
30+
; CHECK: llvm.threadlocal.address operand isThreadLocal() must be true
31+
%p0 = call ptr @llvm.threadlocal.address(ptr @fail2)
32+
store i32 42, ptr %p0, align 4
33+
ret void
34+
}

0 commit comments

Comments
 (0)