Skip to content

Commit 87c0937

Browse files
committed
[CaptureTracking] Supports analysis for dervied pointers
Fixes issue llvm#132739. This fixes a missed capture detection scenario where only the base pointer is captured. Previously, PointerMayBeCaptured only performed forward def-use analysis on the given pointer, which worked for base pointers (Arguments/Allocas/Calls) but failed to detect captures of derived pointers when their base pointers were captured. The fix: For the input pointer, first trace back to its base pointer using `getUnderlyingObject`, then perform capture analysis on the base. This ensures proper handling of derived pointers with bases captured. Performance considerations: - Most existing callers already pass base pointers (the common case), so the added backtracing has negligible overhead - The few callers (ThreadSanitizer.cpp/SanitizerBinaryMetadata.cpp) passing arbitrary pointers are sanitizer-related components where compilation time is less critical compared to runtime overhead This addresses false negatives in capture detection while maintaining reasonable compilation efficiency.
1 parent 058a4e8 commit 87c0937

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

llvm/lib/Analysis/CaptureTracking.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,10 @@ void llvm::PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker,
424424
if (MaxUsesToExplore == 0)
425425
MaxUsesToExplore = DefaultMaxUsesToExplore;
426426

427+
// When analyzing a derived pointer, we need to analyze its underlying
428+
// object to determine whether it is captured.
429+
// E.g., `ptr + 1` is captured if `ptr` is captured.
430+
V = getUnderlyingObjectAggressive(V);
427431
SmallVector<const Use *, 20> Worklist;
428432
Worklist.reserve(getDefaultMaxUsesToExploreForCaptureTracking());
429433
SmallSet<const Use *, 20> Visited;

llvm/unittests/Analysis/CaptureTrackingTest.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,31 @@ TEST(CaptureTracking, MultipleUsesInSameInstruction) {
132132
EXPECT_EQ(ICmp, CT.Captures[6]->getUser());
133133
EXPECT_EQ(1u, CT.Captures[6]->getOperandNo());
134134
}
135+
136+
TEST(CaptureTracking, DerivedPointerIfBasePointerCaptured) {
137+
StringRef Assembly = R"(
138+
declare void @bar(ptr)
139+
140+
define void @test() {
141+
%stkobj = alloca [2 x i32]
142+
%derived = getelementptr inbounds [2 x i32], ptr %stkobj, i64 0, i64 1
143+
store i32 1, ptr %derived
144+
call void @bar(ptr %stkobj)
145+
ret void
146+
}
147+
)";
148+
149+
LLVMContext Context;
150+
SMDiagnostic Error;
151+
auto M = parseAssemblyString(Assembly, Error, Context);
152+
ASSERT_TRUE(M) << "Bad assembly?";
153+
154+
Function *F = M->getFunction("test");
155+
BasicBlock *BB = &F->getEntryBlock();
156+
Instruction *StackObj = &*BB->begin();
157+
Instruction *DerviedPtr = StackObj->getNextNode();
158+
159+
// The base object and its derived pointer are both captured.
160+
EXPECT_TRUE(PointerMayBeCaptured(StackObj, true));
161+
EXPECT_TRUE(PointerMayBeCaptured(DerviedPtr, true));
162+
}

0 commit comments

Comments
 (0)