[llvm] [InstCombine] Support well-defined recurrences in isGuaranteedNotToBeUndefOrPoison (PR #150420)
Cullen Rhodes via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 25 05:45:33 PDT 2025
================
@@ -7569,6 +7569,66 @@ bool llvm::impliesPoison(const Value *ValAssumedPoison, const Value *V) {
static bool programUndefinedIfUndefOrPoison(const Value *V, bool PoisonOnly);
+Use *llvm::canFoldFreezeIntoRecurrence(
+ PHINode *PN, DominatorTree *DT, bool &StartNeedsFreeze,
+ SmallVectorImpl<Instruction *> *DropFlags) {
+ // Detect whether this is a recurrence with a start value and some number of
+ // backedge values. We'll check whether we can push the freeze through the
+ // backedge values (possibly dropping poison flags along the way) until we
+ // reach the phi again. In that case, we can move the freeze to the start
+ // value.
+ Use *StartU = nullptr;
+ SmallVector<Value *> Worklist;
+ for (Use &U : PN->incoming_values()) {
+ if (DT && DT->dominates(PN->getParent(), PN->getIncomingBlock(U))) {
+ // Add backedge value to worklist.
+ Worklist.push_back(U.get());
+ continue;
+ }
+
+ // Don't bother handling multiple start values.
+ if (StartU)
+ return nullptr;
+ StartU = &U;
+ }
+
+ if (!StartU || Worklist.empty())
+ return nullptr; // Not a recurrence.
+
+ Value *StartV = StartU->get();
+ BasicBlock *StartBB = PN->getIncomingBlock(*StartU);
+ StartNeedsFreeze = !isGuaranteedNotToBeUndefOrPoison(StartV);
+ // We can't insert freeze if the start value is the result of the
+ // terminator (e.g. an invoke).
+ if (StartNeedsFreeze && StartBB->getTerminator() == StartV)
+ return nullptr;
+
+ SmallPtrSet<Value *, 32> Visited;
+ while (!Worklist.empty()) {
+ Value *V = Worklist.pop_back_val();
+ if (!Visited.insert(V).second)
+ continue;
+
+ if (Visited.size() > 32)
+ return nullptr; // Limit the total number of values we inspect.
+
+ // Assume that PN is non-poison, because it will be after the transform.
+ if (V == PN || isGuaranteedNotToBeUndefOrPoison(V))
----------------
c-rhodes wrote:
Looking at `isGuaranteedNotToBeUndefOrPoison` it's only used as long as the `AssumptionCache` and `CtxI` are passed. I've tried your suggestion (see patch below), but it makes no testable difference so I'm not sure it's worth it, unless you're aware of some case that's missing?
```
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index a9dcc65d02a0..a4f8c22226e0 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -780,9 +780,11 @@ LLVM_ABI bool impliesPoison(const Value *ValAssumedPoison, const Value *V);
/// values. We'll check whether we can push the freeze through the backedge
/// values (possibly dropping poison flags along the way) until we reach the
/// phi again. In that case, we can move the freeze to the start value.
-LLVM_ABI Use *canFoldFreezeIntoRecurrence(
- PHINode *PN, DominatorTree *DT, bool &StartNeedsFreeze,
- SmallVectorImpl<Instruction *> *DropFlags = nullptr, unsigned Depth = 0);
+LLVM_ABI Use *
+canFoldFreezeIntoRecurrence(PHINode *PN, AssumptionCache *AC, Instruction *CtxI,
+ DominatorTree *DT, bool &StartNeedsFreeze,
+ SmallVectorImpl<Instruction *> *DropFlags = nullptr,
+ unsigned Depth = 0);
/// Return true if this function can prove that V does not have undef bits
/// and is never poison. If V is an aggregate value or vector, check whether
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 948562c90709..fdb0725e361d 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7570,8 +7570,9 @@ bool llvm::impliesPoison(const Value *ValAssumedPoison, const Value *V) {
static bool programUndefinedIfUndefOrPoison(const Value *V, bool PoisonOnly);
Use *llvm::canFoldFreezeIntoRecurrence(
- PHINode *PN, DominatorTree *DT, bool &StartNeedsFreeze,
- SmallVectorImpl<Instruction *> *DropFlags, unsigned Depth) {
+ PHINode *PN, AssumptionCache *AC, Instruction *CtxI, DominatorTree *DT,
+ bool &StartNeedsFreeze, SmallVectorImpl<Instruction *> *DropFlags,
+ unsigned Depth) {
// Detect whether this is a recurrence with a start value and some number of
// backedge values. We'll check whether we can push the freeze through the
// backedge values (possibly dropping poison flags along the way) until we
@@ -7723,8 +7724,9 @@ static bool isGuaranteedNotToBeUndefOrPoison(
bool StartNeedsFreeze;
if (canFoldFreezeIntoRecurrence(
- const_cast<PHINode *>(PN), const_cast<DominatorTree *>(DT),
- StartNeedsFreeze, /*DropFlags=*/nullptr, Depth) &&
+ const_cast<PHINode *>(PN), AC, const_cast<Instruction *>(CtxI),
+ const_cast<DominatorTree *>(DT), StartNeedsFreeze,
+ /*DropFlags=*/nullptr, Depth) &&
!StartNeedsFreeze)
return true;
} else if (!::canCreateUndefOrPoison(Opr, Kind,
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index e28f2abdede7..b32c39faafc8 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -4962,8 +4962,8 @@ Instruction *InstCombinerImpl::foldFreezeIntoRecurrence(FreezeInst &FI,
PHINode *PN) {
bool StartNeedsFreeze;
SmallVector<Instruction *> DropFlags;
- Use *StartU =
- canFoldFreezeIntoRecurrence(PN, &DT, StartNeedsFreeze, &DropFlags);
+ Use *StartU = canFoldFreezeIntoRecurrence(PN, &AC, PN, &DT, StartNeedsFreeze,
+ &DropFlags);
if (!StartU)
return nullptr;
```
https://github.com/llvm/llvm-project/pull/150420
More information about the llvm-commits
mailing list