Heejin Ahn 5a90168fa3
[ValueTracking] Provide getUnderlyingObjectAggressive fallback (#123019)
This callsite assumes `getUnderlyingObjectAggressive` returns a non-null
pointer:

273a94b3d5/llvm/lib/Transforms/IPO/FunctionAttrs.cpp (L124)

But it can return null when there are cycles in the value chain so there
is no more `Worklist` item anymore to explore, in which case it just
returns `Object` at the end of the function without ever setting it:
9b5857a683/llvm/lib/Analysis/ValueTracking.cpp (L6866-L6867)
9b5857a683/llvm/lib/Analysis/ValueTracking.cpp (L6889)

`getUnderlyingObject` does not seem to return null either judging by
looking at its code and its callsites, so I think it is not likely to be
the author's intention that `getUnderlyingObjectAggressive` returns
null.

So this checks whether `Object` is null at the end, and if so, falls
back to the original first value.

---

The test case here was reduced by bugpoint and further reduced manually,
but I find it hard to reduce it further.

To trigger this bug, the memory operation should not be reachable from
the entry BB, because the `phi`s should form a cycle without introducing
another value from the entry. I tried a minimal `phi` cycle with three
BBs (entry BB + two BBs in a cycle), but it was skipped here:
273a94b3d5/llvm/lib/Transforms/IPO/FunctionAttrs.cpp (L121-L122)
To get the result that's not `ModRefInfo::NoModRef`, the length of `phi`
chain needed to be greater than the `MaxLookup` value set in this
function:

02403f4e45/llvm/lib/Analysis/BasicAliasAnalysis.cpp (L744)

But just lengthening the `phi` chain to 8 didn't trigger the same error
in `getUnderlyingObjectAggressive` because `getUnderlyingObject` here
passes through a single-chain `phi`s so not all `phi`s end up in
`Visited`:

9b5857a683/llvm/lib/Analysis/ValueTracking.cpp (L6863)

So I just submit here the smallest test case I managed to create.

---

Fixes #117308 and fixes #122166.
2025-01-15 11:53:51 -08:00

53 lines
1.8 KiB
LLVM

; RUN: opt -passes=function-attrs -S < %s
; Regression test for a null-returning bug of getUnderlyingObjectAggressive().
; This should not crash.
define void @phi_cycle() {
bb:
unreachable
bb1: ; preds = %bb17
br label %bb2
bb2: ; preds = %bb5, %bb1
%phi = phi ptr [ %phi6, %bb1 ], [ %phi6, %bb5 ]
br i1 poison, label %bb4, label %bb3
bb3: ; preds = %bb2
%getelementptr = getelementptr inbounds i8, ptr %phi, i32 poison
br label %bb5
bb4: ; preds = %bb2
br label %bb7
bb5: ; preds = %bb15, %bb3
%phi6 = phi ptr [ %getelementptr, %bb3 ], [ %phi16, %bb15 ]
br i1 poison, label %bb17, label %bb2
bb7: ; preds = %bb15, %bb4
%phi8 = phi ptr [ %phi, %bb4 ], [ %phi16, %bb15 ]
br i1 poison, label %bb11, label %bb9
bb9: ; preds = %bb7
%getelementptr10 = getelementptr inbounds i8, ptr %phi8, i32 1
store i8 poison, ptr %phi8, align 1
br label %bb15
bb11: ; preds = %bb7
br i1 poison, label %bb13, label %bb12
bb12: ; preds = %bb11
br label %bb13
bb13: ; preds = %bb12, %bb11
%getelementptr14 = getelementptr inbounds i8, ptr %phi8, i32 poison
br label %bb15
bb15: ; preds = %bb13, %bb9
%phi16 = phi ptr [ %getelementptr14, %bb13 ], [ %getelementptr10, %bb9 ]
br i1 poison, label %bb5, label %bb7
bb17: ; preds = %bb5
br label %bb1
}