Skip to content

IRVerifier: Allow GlobalValue as llvm.threadlocal.address operand #88321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28130,7 +28130,8 @@ Syntax:
Arguments:
""""""""""

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

Semantics:
""""""""""
Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6226,10 +6226,10 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
}
case Intrinsic::threadlocal_address: {
const Value &Arg0 = *Call.getArgOperand(0);
Check(isa<GlobalVariable>(Arg0),
"llvm.threadlocal.address first argument must be a GlobalVariable");
Check(cast<GlobalVariable>(Arg0).isThreadLocal(),
"llvm.threadlocal.address operand isThreadLocal() must no be false");
Check(isa<GlobalValue>(Arg0),
"llvm.threadlocal.address first argument must be a GlobalValue");
Check(cast<GlobalValue>(Arg0).isThreadLocal(),
"llvm.threadlocal.address operand isThreadLocal() must be true");
break;
}
};
Expand Down
13 changes: 13 additions & 0 deletions llvm/test/Verifier/threadlocal-pass.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
; RUN: opt -passes=verify -S < %s | FileCheck %s

@var = thread_local global i32 0
@alias = thread_local alias i32, ptr @var

; CHECK-LABEL: @should_pass
define void @should_pass() {
%p0 = call ptr @llvm.threadlocal.address(ptr @var)
store i32 42, ptr %p0, align 4
%p1 = call ptr @llvm.threadlocal.address(ptr @alias)
store i32 13, ptr %p1, align 4
ret void
}
34 changes: 34 additions & 0 deletions llvm/test/Verifier/threadlocal.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s

@var = global i32 0
@tlsvar = thread_local addrspace(1) global i32 0

define void @fail0(ptr %arg) {
; CHECK: llvm.threadlocal.address first argument must be a GlobalValue
%p0 = call ptr @llvm.threadlocal.address(ptr %arg)
store i32 42, ptr %p0, align 4
ret void
}

define void @fail1() {
; CHECK: llvm.threadlocal.address first argument must be a GlobalValue
%p0 = call ptr @llvm.threadlocal.address.p0(ptr addrspacecast (ptr addrspace(1) @tlsvar to ptr addrspace(0)))
store i32 42, ptr %p0, align 4
ret void
}



define void @fail2() {
; CHECK: llvm.threadlocal.address operand isThreadLocal() must be true
%p0 = call ptr @llvm.threadlocal.address(ptr @var)
store i32 42, ptr %p0, align 4
ret void
}

define void @fail3() {
; CHECK: llvm.threadlocal.address operand isThreadLocal() must be true
%p0 = call ptr @llvm.threadlocal.address(ptr @fail2)
store i32 42, ptr %p0, align 4
ret void
}