ChuanqiXu updated this revision to Diff 444880.
ChuanqiXu marked 3 inline comments as done.
ChuanqiXu added a comment.
Address comments and remove verifier due to the automatic merging for constant
expression I mentioned above.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D125291/new/
https://reviews.llvm.org/D125291
Files:
llvm/docs/LangRef.rst
llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
llvm/include/llvm/IR/IRBuilder.h
llvm/include/llvm/IR/Intrinsics.td
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
llvm/lib/IR/IRBuilder.cpp
llvm/test/CodeGen/X86/threadlocal_address.ll
Index: llvm/test/CodeGen/X86/threadlocal_address.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/X86/threadlocal_address.ll
@@ -0,0 +1,41 @@
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -stop-after=finalize-isel %s -o - | FileCheck %s
+
+@i = thread_local global i32 0, align 4
+
+define noundef i32 @foo() {
+; CHECK: %0:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg :: (load (s64) from got)
+; CHECK: %1:gr32 = MOV32rm %0, 1, $noreg, 0, $fs :: (load (s32) from %ir.0)
+; CHECK: %2:gr32 = nsw INC32r %1, implicit-def dead $eflags
+; CHECK: MOV32mr %0, 1, $noreg, 0, $fs, %2 :: (store (s32) into %ir.0)
+; CHECK: $eax = COPY %2
+; CHECK: RET 0, $eax
+entry:
+ %0 = call ptr @llvm.threadlocal.address(ptr @i)
+ %1 = load i32, ptr %0, align 4
+ %inc = add nsw i32 %1, 1
+ store i32 %inc, ptr %0, align 4
+ %2 = call ptr @llvm.threadlocal.address(ptr @i)
+ %3 = load i32, ptr %2, align 4
+ ret i32 %3
+}
+
+@j = thread_local addrspace(1) global i32 addrspace(0)* @i, align 4
+define noundef i32 @bar() {
+; CHECK: %0:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gottpoff) @j, $noreg :: (load (s64) from got)
+; CHECK: %1:gr32 = MOV32rm %0, 1, $noreg, 0, $fs :: (load (s32) from %ir.0, addrspace 1)
+; CHECK: %2:gr32 = nsw INC32r %1, implicit-def dead $eflags
+; CHECK: MOV32mr %0, 1, $noreg, 0, $fs, %2 :: (store (s32) into %ir.0, addrspace 1)
+; CHECK: $eax = COPY %2
+; CHECK: RET 0, $eax
+entry:
+ %0 = call ptr addrspace(1) @llvm.threadlocal.address.p1(ptr addrspace(1) @j)
+ %1 = load i32, ptr addrspace(1) %0, align 4
+ %inc = add nsw i32 %1, 1
+ store i32 %inc, ptr addrspace(1) %0, align 4
+ %2 = call ptr addrspace(1) @llvm.threadlocal.address.p1(ptr addrspace(1) @j)
+ %3 = load i32, ptr addrspace(1) %2, align 4
+ ret i32 %3
+}
+
+declare ptr @llvm.threadlocal.address(ptr) nounwind readnone willreturn
+declare ptr addrspace(1) @llvm.threadlocal.address.p1(ptr addrspace(1)) nounwind readnone willreturn
Index: llvm/lib/IR/IRBuilder.cpp
===================================================================
--- llvm/lib/IR/IRBuilder.cpp
+++ llvm/lib/IR/IRBuilder.cpp
@@ -528,6 +528,13 @@
return createCallHelper(TheFn, Ops, this);
}
+CallInst *IRBuilderBase::CreateThreadLocalAddress(Value *Ptr) {
+ assert(isa<GlobalValue>(Ptr) && cast<GlobalValue>(Ptr)->isThreadLocal() &&
+ "threadlocal_address only applies to thread local variables.");
+ return CreateIntrinsic(llvm::Intrinsic::threadlocal_address, {Ptr->getType()},
+ {Ptr});
+}
+
CallInst *
IRBuilderBase::CreateAssumption(Value *Cond,
ArrayRef<OperandBundleDef> OpBundles) {
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7167,6 +7167,10 @@
DAG.getZExtOrTrunc(Const, sdl, PtrVT)));
return;
}
+ case Intrinsic::threadlocal_address: {
+ setValue(&I, getValue(I.getOperand(0)));
+ return;
+ }
case Intrinsic::get_active_lane_mask: {
EVT CCVT = TLI.getValueType(DAG.getDataLayout(), I.getType());
SDValue Index = getValue(I.getOperand(0));
Index: llvm/include/llvm/IR/Intrinsics.td
===================================================================
--- llvm/include/llvm/IR/Intrinsics.td
+++ llvm/include/llvm/IR/Intrinsics.td
@@ -1402,6 +1402,10 @@
def int_ptrmask: DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>, llvm_anyint_ty],
[IntrNoMem, IntrSpeculatable, IntrWillReturn]>;
+// Intrinsic to wrap a thread local variable.
+def int_threadlocal_address : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>],
+ [IntrNoMem, IntrSpeculatable, IntrWillReturn]>;
+
def int_experimental_stepvector : DefaultAttrsIntrinsic<[llvm_anyvector_ty],
[], [IntrNoMem]>;
Index: llvm/include/llvm/IR/IRBuilder.h
===================================================================
--- llvm/include/llvm/IR/IRBuilder.h
+++ llvm/include/llvm/IR/IRBuilder.h
@@ -749,6 +749,9 @@
/// If the pointer isn't i8* it will be converted.
CallInst *CreateInvariantStart(Value *Ptr, ConstantInt *Size = nullptr);
+ /// Create a call to llvm.threadlocal.address intrinsic.
+ CallInst *CreateThreadLocalAddress(Value *Ptr);
+
/// Create a call to Masked Load intrinsic
CallInst *CreateMaskedLoad(Type *Ty, Value *Ptr, Align Alignment, Value *Mask,
Value *PassThru = nullptr, const Twine &Name = "");
Index: llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
===================================================================
--- llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -649,6 +649,7 @@
case Intrinsic::coro_align:
case Intrinsic::coro_suspend:
case Intrinsic::coro_subfn_addr:
+ case Intrinsic::threadlocal_address:
// These intrinsics don't actually represent code after lowering.
return 0;
}
Index: llvm/docs/LangRef.rst
===================================================================
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -24528,6 +24528,30 @@
mask argument does not match the pointer size of the target, the mask is
zero-extended or truncated accordingly.
+.. _int_threadlocal_address:
+
+'``llvm.threadlocal.address``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare ptr @llvm.threadlocal.address(ptr) nounwind readnone willreturn
+
+Arguments:
+""""""""""
+
+The first argument is a pointer, which refers to a thread local variable.
+
+Semantics:
+""""""""""
+
+The address of a thread local variable is not a constant, since it depends on
+the calling thread. The `llvm.threadlocal.address` intrinsic returns the
+address of the given thread local variable in the calling thread.
+
.. _int_vscale:
'``llvm.vscale``' Intrinsic
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits