Skip to content

[clang][IR] Overload @llvm.thread.pointer to support non-AS0 targets #132489

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 3 commits into from
May 14, 2025
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
5 changes: 3 additions & 2 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5905,8 +5905,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_thread_pointer: {
if (!getContext().getTargetInfo().isTLSSupported())
CGM.ErrorUnsupported(E, "__builtin_thread_pointer");
// Fall through - it's already mapped to the intrinsic by ClangBuiltin.
break;

return RValue::get(Builder.CreateIntrinsic(llvm::Intrinsic::thread_pointer,
{GlobalsInt8PtrTy}, {}));
}
case Builtin::BI__builtin_os_log_format:
return emitBuiltinOSLogFormat(*E);
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/builtins-arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ void f0(void *a, void *b) {

void *tp (void) {
return __builtin_thread_pointer ();
// CHECK-LINUX: call {{.*}} @llvm.thread.pointer()
// CHECK-LINUX: call {{.*}} @llvm.thread.pointer.p0()
}

// CHECK: call {{.*}} @llvm.bitreverse.i32(i32 %a)
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/builtins-wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -743,5 +743,5 @@ __externref_t externref_null() {

void *tp (void) {
return __builtin_thread_pointer ();
// WEBASSEMBLY: call {{.*}} @llvm.thread.pointer()
// WEBASSEMBLY: call {{.*}} @llvm.thread.pointer.p0()
}
9 changes: 7 additions & 2 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3120,6 +3120,9 @@ as follows:
program memory space defaults to the default address space of 0,
which corresponds to a Von Neumann architecture that has code
and data in the same space.

.. _globals_addrspace:

``G<address space>``
Specifies the address space to be used by default when creating global
variables. If omitted, the globals address space defaults to the default
Expand Down Expand Up @@ -14968,7 +14971,8 @@ Syntax:

::

declare ptr @llvm.thread.pointer()
declare ptr @llvm.thread.pointer.p0()
declare ptr addrspace(5) @llvm.thread.pointer.p5()

Overview:
"""""""""
Expand All @@ -14985,7 +14989,8 @@ specific: it may point to the start of TLS area, to the end, or somewhere
in the middle. Depending on the target, this intrinsic may read a register,
call a helper function, read from an alternate memory space, or perform
other operations necessary to locate the TLS area. Not all targets support
this intrinsic.
this intrinsic. The address space must be the :ref:`globals address space
<globals_addrspace>`.

'``llvm.call.preallocated.setup``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/IR/Intrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,7 @@ def int_stackrestore : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty]>,

def int_get_dynamic_area_offset : DefaultAttrsIntrinsic<[llvm_anyint_ty]>;

def int_thread_pointer : DefaultAttrsIntrinsic<[llvm_ptr_ty], [], [IntrNoMem]>,
def int_thread_pointer : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [], [IntrNoMem]>,
ClangBuiltin<"__builtin_thread_pointer">;

// IntrInaccessibleMemOrArgMemOnly is a little more pessimistic than strictly
Expand Down
12 changes: 10 additions & 2 deletions llvm/lib/IR/AutoUpgrade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,8 +645,8 @@ static bool upgradeArmOrAarch64IntrinsicFunction(bool IsArm, Function *F,

if (Name == "thread.pointer") {
// '(arm|aarch64).thread.pointer'.
NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(),
Intrinsic::thread_pointer);
NewFn = Intrinsic::getOrInsertDeclaration(
F->getParent(), Intrinsic::thread_pointer, F->getReturnType());
return true;
}

Expand Down Expand Up @@ -1419,6 +1419,14 @@ static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn,
}
break;

case 't':
if (Name == "thread.pointer") {
NewFn = Intrinsic::getDeclaration(
F->getParent(), Intrinsic::thread_pointer, F->getReturnType());
return true;
}
break;

case 'v': {
if (Name == "var.annotation" && F->arg_size() == 4) {
rename(F);
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6527,6 +6527,14 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
&Call);
break;
}
case Intrinsic::thread_pointer: {
Check(Call.getType()->getPointerAddressSpace() ==
DL.getDefaultGlobalsAddressSpace(),
"llvm.thread.pointer intrinsic return type must be for the globals "
"address space",
&Call);
break;
}
case Intrinsic::threadlocal_address: {
const Value &Arg0 = *Call.getArgOperand(0);
Check(isa<GlobalValue>(Arg0),
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28166,8 +28166,8 @@ bool AArch64TargetLowering::shouldNormalizeToSelectSequence(LLVMContext &,

static Value *UseTlsOffset(IRBuilderBase &IRB, unsigned Offset) {
Module *M = IRB.GetInsertBlock()->getParent()->getParent();
Function *ThreadPointerFunc =
Intrinsic::getOrInsertDeclaration(M, Intrinsic::thread_pointer);
Function *ThreadPointerFunc = Intrinsic::getOrInsertDeclaration(
M, Intrinsic::thread_pointer, IRB.getPtrTy());
return IRB.CreatePointerCast(
IRB.CreateConstGEP1_32(IRB.getInt8Ty(), IRB.CreateCall(ThreadPointerFunc),
Offset),
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22916,8 +22916,8 @@ bool RISCVTargetLowering::preferScalarizeSplat(SDNode *N) const {

static Value *useTpOffset(IRBuilderBase &IRB, unsigned Offset) {
Module *M = IRB.GetInsertBlock()->getModule();
Function *ThreadPointerFunc =
Intrinsic::getOrInsertDeclaration(M, Intrinsic::thread_pointer);
Function *ThreadPointerFunc = Intrinsic::getOrInsertDeclaration(
M, Intrinsic::thread_pointer, IRB.getPtrTy());
return IRB.CreateConstGEP1_32(IRB.getInt8Ty(),
IRB.CreateCall(ThreadPointerFunc), Offset);
}
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,9 @@ Value *getAndroidSlotPtr(IRBuilder<> &IRB, int Slot) {
Module *M = IRB.GetInsertBlock()->getParent()->getParent();
// Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER
// in Bionic's libc/private/bionic_tls.h.
Function *ThreadPointerFunc =
Intrinsic::getOrInsertDeclaration(M, Intrinsic::thread_pointer);
Function *ThreadPointerFunc = Intrinsic::getOrInsertDeclaration(
M, Intrinsic::thread_pointer,
IRB.getPtrTy(M->getDataLayout().getDefaultGlobalsAddressSpace()));
return IRB.CreateConstGEP1_32(IRB.getInt8Ty(),
IRB.CreateCall(ThreadPointerFunc), 8 * Slot);
}
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Assembler/autoupgrade-thread-pointer.ll
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ declare ptr @llvm.arm.thread.pointer()

define ptr @test1() {
; CHECK-LABEL: define ptr @test1()
; CHECK: call ptr @llvm.thread.pointer()
; CHECK: call ptr @llvm.thread.pointer.p0()
%1 = call ptr @llvm.aarch64.thread.pointer()
ret ptr %1
}

define ptr @test2() {
; CHECK-LABEL: define ptr @test2()
; CHECK: call ptr @llvm.thread.pointer()
; CHECK: call ptr @llvm.thread.pointer.p0()
%1 = call ptr @llvm.arm.thread.pointer()
ret ptr %1
}
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/AArch64/stack-tagging-prologue.ll
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ entry:

; INSTR-LABEL: define void @OneVar(
; INSTR: [[BASE:%.*]] = call ptr @llvm.aarch64.irg.sp(i64 0)
; INSTR: [[TLS:%.*]] = call ptr @llvm.thread.pointer()
; INSTR: [[TLS:%.*]] = call ptr @llvm.thread.pointer.p0()
; INSTR: [[TLS_SLOT:%.*]] = getelementptr i8, ptr [[TLS]], i32 -24
; INSTR: [[TLS_VALUE:%.*]] = load i64, ptr [[TLS_SLOT]], align 8
; INSTR: [[FP:%.*]] = call ptr @llvm.frameaddress.p0(i32 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ declare void @use(ptr, ptr)
define void @test_alloca() sanitize_hwaddress {
; CHECK-LABEL: define void @test_alloca
; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.thread.pointer()
; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.thread.pointer.p0()
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP1]], i32 48
; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 8
; CHECK-NEXT: [[TMP4:%.*]] = ashr i64 [[TMP3]], 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ declare void @use32(ptr)
define void @test_alloca() sanitize_hwaddress {
; CHECK-LABEL: define void @test_alloca
; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.thread.pointer()
; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.thread.pointer.p0()
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP1]], i32 48
; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 8
; CHECK-NEXT: [[TMP4:%.*]] = ashr i64 [[TMP3]], 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ define void @test_alloca() sanitize_hwaddress {
; CHECK-LABEL: define void @test_alloca
; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = call ptr @llvm.thread.pointer()
; CHECK-NEXT: [[TMP0:%.*]] = call ptr @llvm.thread.pointer.p0()
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 48
; CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
; CHECK-NEXT: [[TMP3:%.*]] = ashr i64 [[TMP2]], 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ define void @test() sanitize_hwaddress personality ptr @__gxx_personality_v0 {
; CHECK-LABEL: define void @test
; CHECK-SAME: () #[[ATTR0:[0-9]+]] personality ptr @__gxx_personality_v0 {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = call ptr @llvm.thread.pointer()
; CHECK-NEXT: [[TMP0:%.*]] = call ptr @llvm.thread.pointer.p0()
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 48
; CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
; CHECK-NEXT: [[TMP3:%.*]] = ashr i64 [[TMP2]], 3
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Instrumentation/HWAddressSanitizer/prologue.ll
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ define void @test_alloca() sanitize_hwaddress {
; CHECK-LABEL: define void @test_alloca
; CHECK-SAME: () #[[ATTR0]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = call ptr @llvm.thread.pointer()
; CHECK-NEXT: [[TMP0:%.*]] = call ptr @llvm.thread.pointer.p0()
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 48
; CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
; CHECK-NEXT: [[TMP3:%.*]] = ashr i64 [[TMP2]], 3
Expand Down Expand Up @@ -134,7 +134,7 @@ define void @test_alloca() sanitize_hwaddress {
; NOIFUNC-TLS-HISTORY-LABEL: define void @test_alloca
; NOIFUNC-TLS-HISTORY-SAME: () #[[ATTR0]] {
; NOIFUNC-TLS-HISTORY-NEXT: entry:
; NOIFUNC-TLS-HISTORY-NEXT: [[TMP0:%.*]] = call ptr @llvm.thread.pointer()
; NOIFUNC-TLS-HISTORY-NEXT: [[TMP0:%.*]] = call ptr @llvm.thread.pointer.p0()
; NOIFUNC-TLS-HISTORY-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 48
; NOIFUNC-TLS-HISTORY-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
; NOIFUNC-TLS-HISTORY-NEXT: [[TMP3:%.*]] = ashr i64 [[TMP2]], 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ define dso_local noundef i1 @_Z6targetv() sanitize_hwaddress {
; CHECK-LABEL: define dso_local noundef i1 @_Z6targetv
; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = call ptr @llvm.thread.pointer()
; CHECK-NEXT: [[TMP0:%.*]] = call ptr @llvm.thread.pointer.p0()
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[TMP0]], i32 48
; CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
; CHECK-NEXT: [[TMP3:%.*]] = ashr i64 [[TMP2]], 3
Expand Down
Loading