diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/include/llvm/Analysis/ValueTracking.h @@ -406,7 +406,7 @@ /// it shouldn't look through the phi above. void getUnderlyingObjects(const Value *V, SmallVectorImpl &Objects, - LoopInfo *LI = nullptr, unsigned MaxLookup = 6); + LoopInfo *LI = nullptr); /// This is a wrapper around getUnderlyingObjects and adds support for basic /// ptrtoint+arithmetic+inttoptr sequences. diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4227,17 +4227,25 @@ void llvm::getUnderlyingObjects(const Value *V, SmallVectorImpl &Objects, - LoopInfo *LI, unsigned MaxLookup) { + LoopInfo *LI) { SmallPtrSet Visited; SmallVector Worklist; Worklist.push_back(V); do { const Value *P = Worklist.pop_back_val(); - P = getUnderlyingObject(P, MaxLookup); + P = getUnderlyingObject(P); if (!Visited.insert(P).second) continue; + const Value *U = P; + P = getUnderlyingObject(P); + if (U != P) { + // Repeat if getUnderlyingObject terminated on MaxLookup. + Worklist.push_back(P); + continue; + } + if (auto *SI = dyn_cast(P)) { Worklist.push_back(SI->getTrueValue()); Worklist.push_back(SI->getFalseValue()); diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp --- a/llvm/unittests/Analysis/ValueTrackingTest.cpp +++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -1430,3 +1430,56 @@ EXPECT_TRUE(CR2.isFullSet()); } } + +TEST_F(ValueTrackingTest, getUnderlyingObjects) { + auto M = parseModule(R"( + define i32* @test() { + %a = alloca i32 + %1 = getelementptr i32, i32* %a, i32 1 + %2 = getelementptr i32, i32* %1, i32 1 + %3 = getelementptr i32, i32* %2, i32 1 + %4 = getelementptr i32, i32* %3, i32 1 + %5 = getelementptr i32, i32* %4, i32 1 + %6 = getelementptr i32, i32* %5, i32 1 + %7 = getelementptr i32, i32* %6, i32 1 + %8 = getelementptr i32, i32* %7, i32 1 + %9 = getelementptr i32, i32* %8, i32 1 + %r = getelementptr i32, i32* %9, i32 1 + ret i32* %r + })"); + Function *F = M->getFunction("test"); + Instruction *I = &findInstructionByName(F, "r"); + SmallVector Objects; + getUnderlyingObjects(I->getOperand(0), Objects); + EXPECT_EQ(1u, Objects.size()); + EXPECT_EQ(1, isa(Objects[0])); +} + +TEST_F(ValueTrackingTest, getUnderlyingObjectsCycle) { + auto M = parseModule(R"( + define void @test() { + entry: + br label %bb1 + + bb1: + %a = phi i32* [ %r, %bb1 ] + %0 = getelementptr i32, i32* %a, i32 1 + %1 = getelementptr i32, i32* %0, i32 1 + %2 = getelementptr i32, i32* %1, i32 1 + %3 = getelementptr i32, i32* %2, i32 1 + %4 = getelementptr i32, i32* %3, i32 1 + %5 = getelementptr i32, i32* %4, i32 1 + %6 = getelementptr i32, i32* %5, i32 1 + %7 = getelementptr i32, i32* %6, i32 1 + %8 = getelementptr i32, i32* %7, i32 1 + %9 = getelementptr i32, i32* %8, i32 1 + %r = getelementptr i32, i32* %9, i32 1 + br label %bb1 + + })"); + Function *F = M->getFunction("test"); + Instruction *I = &findInstructionByName(F, "r"); + SmallVector Objects; + getUnderlyingObjects(I, Objects); + EXPECT_TRUE(Objects.empty()); +}