Skip to content

Commit 7b06d6b

Browse files
committed
GlobalsModRef, ValueTracking: Look through threadlocal.address intrinsic
1 parent 417d510 commit 7b06d6b

File tree

5 files changed

+39
-5
lines changed

5 files changed

+39
-5
lines changed

llvm/include/llvm/Analysis/ValueTracking.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -690,11 +690,11 @@ inline Value *getArgumentAliasingToReturnedPointer(CallBase *Call,
690690
bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(
691691
const CallBase *Call, bool MustPreserveNullness);
692692

693-
/// This method strips off any GEP address adjustments and pointer casts from
694-
/// the specified value, returning the original object being addressed. Note
695-
/// that the returned value has pointer type if the specified value does. If
696-
/// the MaxLookup value is non-zero, it limits the number of instructions to
697-
/// be stripped off.
693+
/// This method strips off any GEP address adjustments, pointer casts
694+
/// or `llvm.threadlocal.address` from the specified value \p V, returning the
695+
/// original object being addressed. Note that the returned value has pointer
696+
/// type if the specified value does. If the \p MaxLookup value is non-zero, it
697+
/// limits the number of instructions to be stripped off.
698698
const Value *getUnderlyingObject(const Value *V, unsigned MaxLookup = 6);
699699
inline Value *getUnderlyingObject(Value *V, unsigned MaxLookup = 6) {
700700
// Force const to avoid infinite recursion.

llvm/lib/Analysis/GlobalsModRef.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,14 @@ bool GlobalsAAResult::AnalyzeUsesOfPointer(Value *V,
344344
if (AnalyzeUsesOfPointer(I, Readers, Writers, OkayStoreDest))
345345
return true;
346346
} else if (auto *Call = dyn_cast<CallBase>(I)) {
347+
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
348+
if (II->getIntrinsicID() == Intrinsic::threadlocal_address &&
349+
V == II->getArgOperand(0)) {
350+
if (AnalyzeUsesOfPointer(II, Readers, Writers))
351+
return true;
352+
continue;
353+
}
354+
}
347355
// Make sure that this is just the function being called, not that it is
348356
// passing into the function.
349357
if (Call->isDataOperand(&U)) {

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6252,6 +6252,9 @@ bool llvm::isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(
62526252
// MustPreserveNullness (and, at time of writing, they are not), but we
62536253
// document this fact out of an abundance of caution.
62546254
case Intrinsic::amdgcn_make_buffer_rsrc:
6255+
// For alias analysis it is best to return the `GlobalValue` representing the
6256+
// TLS variable.
6257+
case Intrinsic::threadlocal_address:
62556258
return true;
62566259
case Intrinsic::ptrmask:
62576260
return !MustPreserveNullness;

llvm/test/Analysis/GlobalsModRef/nonescaping-noalias.ll

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,25 @@ entry:
2222
ret i32 %v
2323
}
2424

25+
@g1_tls = internal thread_local global i32 0
26+
27+
define i32 @test1_tls(ptr %param) {
28+
; Ensure that we can fold a store to a load of a global across a store to
29+
; a parameter when the global is non-escaping.
30+
;
31+
; CHECK-LABEL: @test1_tls(
32+
; CHECK: %p = call ptr @llvm.threadlocal.address.p0(ptr @g1_tls)
33+
; CHECK: store i32 42, ptr %p
34+
; CHECK-NOT: load i32
35+
; CHECK: ret i32 42
36+
entry:
37+
%p = call ptr @llvm.threadlocal.address(ptr @g1_tls)
38+
store i32 42, ptr %p
39+
store i32 7, ptr %param
40+
%v = load i32, ptr %p
41+
ret i32 %v
42+
}
43+
2544
declare ptr @f()
2645

2746
define i32 @test2() {

llvm/unittests/Analysis/ValueTrackingTest.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,19 +1273,23 @@ TEST_F(ValueTrackingTest, getUnderlyingObjectCastsAliases) {
12731273

12741274
TEST_F(ValueTrackingTest, getUnderlyingObjectIntrinsics) {
12751275
parseAssembly(R"IR(
1276+
@tlsvar = thread_local global i32 0
12761277
define void @test(ptr %arg) {
12771278
; intrinsic with Return<> arg attribute
12781279
%A = call ptr @llvm.objc.retain(ptr %arg)
12791280
%A2 = call ptr @llvm.ssa.copy(ptr %arg)
12801281
; special cased intrinsics
12811282
%A3 = call ptr @llvm.launder.invariant.group(ptr %arg)
1283+
%A4 = call ptr @llvm.threadlocal.address(ptr @tlsvar)
12821284
ret void
12831285
}
12841286
)IR");
12851287
Value *arg = F->getArg(0);
12861288
EXPECT_EQ(getUnderlyingObject(A), arg);
12871289
EXPECT_EQ(getUnderlyingObject(A2), arg);
12881290
EXPECT_EQ(getUnderlyingObject(A3), arg);
1291+
Value *tlsvar = M->getNamedGlobal("tlsvar");
1292+
EXPECT_EQ(getUnderlyingObject(A4), tlsvar);
12891293
}
12901294

12911295
TEST_F(ValueTrackingTest, getUnderlyingObjectPtrInt) {

0 commit comments

Comments
 (0)