[llvm] [InstCombinePHI] Enhance PHI CSE to remove redundant phis (PR #163453)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 21 08:00:06 PDT 2025
================
@@ -4866,6 +4866,89 @@ static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
return nullptr;
}
+// Look for the following pattern and simplify %1 to %identicalPhi.
+// Here %phi, %1 and %phi.next perform the same functionality as
+// %identicalPhi and hence the select instruction %1 can be folded
+// into %identicalPhi.
+//
+// BB1:
+// %identicalPhi = phi [ X, %BB0 ], [ %identicalPhi.next, %BB1 ]
+// %phi = phi [ X, %BB0 ], [ %phi.next, %BB1 ]
+// ...
+// %identicalPhi.next = select %cmp, %val, %identicalPhi
+// (or select %cmp, %identicalPhi, %val)
+// %1 = select %cmp2, %identicalPhi, %phi
+// %phi.next = select %cmp, %val, %1
+// (or select %cmp, %1, %val)
+//
+// Prove that %phi and %identicalPhi are the same by induction:
+//
+// Base case: Both %phi and %identicalPhi are equal on entry to the loop.
+// Inductive case:
+// Suppose %phi and %identicalPhi are equal at iteration i.
+// We look at their values at iteration i+1 which are %phi.next and
+// %identicalPhi.next. They would have become different only when %cmp is
+// false and the corresponding values %1 and %identicalPhi differ
+// (similar reason for the other "or" case in the bracket).
+//
+// The only condition when %1 and %identicalPh could differ is when %cmp2
+// is false and %1 is %phi, which contradicts our inductive hypothesis
+// that %phi and %identicalPhi are equal. Thus %phi and %identicalPhi are
+// always equal at iteration i+1.
+bool isSimplifierIdenticalPHI(PHINode &PN, PHINode &IdenticalPN) {
+ if (PN.getParent() != IdenticalPN.getParent())
+ return false;
+ if (PN.getNumIncomingValues() != 2)
+ return false;
+
+ // Check that only the backedge incoming value is different.
+ unsigned DiffVals = 0;
+ BasicBlock *DiffValBB = nullptr;
+ for (unsigned i = 0; i < 2; i++) {
+ BasicBlock *PredBB = PN.getIncomingBlock(i);
+ if (PN.getIncomingValueForBlock(PredBB) !=
+ IdenticalPN.getIncomingValueForBlock(PredBB)) {
+ DiffVals++;
+ DiffValBB = PredBB;
+ }
+ }
+ if (DiffVals != 1)
+ return false;
+ // Now check that the backedge incoming values are two select
+ // instructions with the same condition. Either their true
+ // values are the same, or their false values are the same.
+ auto *SI = dyn_cast<SelectInst>(PN.getIncomingValueForBlock(DiffValBB));
+ auto *IdenticalSI =
+ dyn_cast<SelectInst>(IdenticalPN.getIncomingValueForBlock(DiffValBB));
+ if (!SI || !IdenticalSI)
+ return false;
+ if (SI->getCondition() != IdenticalSI->getCondition() ||
+ (SI->getTrueValue() != IdenticalSI->getTrueValue() &&
+ SI->getFalseValue() != IdenticalSI->getFalseValue()))
+ return false;
+
+ SelectInst *SIOtherVal = nullptr;
+ Value *IdenticalSIOtherVal = nullptr;
+ if (SI->getTrueValue() == IdenticalSI->getTrueValue()) {
+ SIOtherVal = dyn_cast<SelectInst>(SI->getFalseValue());
+ IdenticalSIOtherVal = IdenticalSI->getFalseValue();
+ } else {
----------------
dtcxzyw wrote:
```suggestion
} else if (SI->getFalseValue() == IdenticalSI->getFalseValue()) {
```
https://github.com/llvm/llvm-project/pull/163453
More information about the llvm-commits
mailing list