Skip to content

Commit e246fff

Browse files
Reland "[InstructionSimplify] Enhance simplifySelectInst() (#163453)" (#164694)
This reverts commit f1c1063. PR #163453 was merged and reverted since it exposed a crash. After investigation the crash was unrelated and is then fixed in #164628. This is an attempt to reland #163453.
1 parent 7ebc3db commit e246fff

File tree

2 files changed

+508
-1
lines changed

2 files changed

+508
-1
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4866,6 +4866,89 @@ static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
48664866
return nullptr;
48674867
}
48684868

4869+
/// Look for the following pattern and simplify %to_fold to %identicalPhi.
4870+
/// Here %phi, %to_fold and %phi.next perform the same functionality as
4871+
/// %identicalPhi and hence the select instruction %to_fold can be folded
4872+
/// into %identicalPhi.
4873+
///
4874+
/// BB1:
4875+
/// %identicalPhi = phi [ X, %BB0 ], [ %identicalPhi.next, %BB1 ]
4876+
/// %phi = phi [ X, %BB0 ], [ %phi.next, %BB1 ]
4877+
/// ...
4878+
/// %identicalPhi.next = select %cmp, %val, %identicalPhi
4879+
/// (or select %cmp, %identicalPhi, %val)
4880+
/// %to_fold = select %cmp2, %identicalPhi, %phi
4881+
/// %phi.next = select %cmp, %val, %to_fold
4882+
/// (or select %cmp, %to_fold, %val)
4883+
///
4884+
/// Prove that %phi and %identicalPhi are the same by induction:
4885+
///
4886+
/// Base case: Both %phi and %identicalPhi are equal on entry to the loop.
4887+
/// Inductive case:
4888+
/// Suppose %phi and %identicalPhi are equal at iteration i.
4889+
/// We look at their values at iteration i+1 which are %phi.next and
4890+
/// %identicalPhi.next. They would have become different only when %cmp is
4891+
/// false and the corresponding values %to_fold and %identicalPhi differ
4892+
/// (similar reason for the other "or" case in the bracket).
4893+
///
4894+
/// The only condition when %to_fold and %identicalPh could differ is when %cmp2
4895+
/// is false and %to_fold is %phi, which contradicts our inductive hypothesis
4896+
/// that %phi and %identicalPhi are equal. Thus %phi and %identicalPhi are
4897+
/// always equal at iteration i+1.
4898+
bool isSelectWithIdenticalPHI(PHINode &PN, PHINode &IdenticalPN) {
4899+
if (PN.getParent() != IdenticalPN.getParent())
4900+
return false;
4901+
if (PN.getNumIncomingValues() != 2)
4902+
return false;
4903+
4904+
// Check that only the backedge incoming value is different.
4905+
unsigned DiffVals = 0;
4906+
BasicBlock *DiffValBB = nullptr;
4907+
for (unsigned i = 0; i < 2; i++) {
4908+
BasicBlock *PredBB = PN.getIncomingBlock(i);
4909+
if (PN.getIncomingValue(i) !=
4910+
IdenticalPN.getIncomingValueForBlock(PredBB)) {
4911+
DiffVals++;
4912+
DiffValBB = PredBB;
4913+
}
4914+
}
4915+
if (DiffVals != 1)
4916+
return false;
4917+
// Now check that the backedge incoming values are two select
4918+
// instructions with the same condition. Either their true
4919+
// values are the same, or their false values are the same.
4920+
auto *SI = dyn_cast<SelectInst>(PN.getIncomingValueForBlock(DiffValBB));
4921+
auto *IdenticalSI =
4922+
dyn_cast<SelectInst>(IdenticalPN.getIncomingValueForBlock(DiffValBB));
4923+
if (!SI || !IdenticalSI)
4924+
return false;
4925+
if (SI->getCondition() != IdenticalSI->getCondition())
4926+
return false;
4927+
4928+
SelectInst *SIOtherVal = nullptr;
4929+
Value *IdenticalSIOtherVal = nullptr;
4930+
if (SI->getTrueValue() == IdenticalSI->getTrueValue()) {
4931+
SIOtherVal = dyn_cast<SelectInst>(SI->getFalseValue());
4932+
IdenticalSIOtherVal = IdenticalSI->getFalseValue();
4933+
} else if (SI->getFalseValue() == IdenticalSI->getFalseValue()) {
4934+
SIOtherVal = dyn_cast<SelectInst>(SI->getTrueValue());
4935+
IdenticalSIOtherVal = IdenticalSI->getTrueValue();
4936+
} else {
4937+
return false;
4938+
}
4939+
4940+
// Now check that the other values in select, i.e., %to_fold and
4941+
// %identicalPhi, are essentially the same value.
4942+
if (!SIOtherVal || IdenticalSIOtherVal != &IdenticalPN)
4943+
return false;
4944+
if (!(SIOtherVal->getTrueValue() == &IdenticalPN &&
4945+
SIOtherVal->getFalseValue() == &PN) &&
4946+
!(SIOtherVal->getTrueValue() == &PN &&
4947+
SIOtherVal->getFalseValue() == &IdenticalPN))
4948+
return false;
4949+
return true;
4950+
}
4951+
48694952
/// Given operands for a SelectInst, see if we can fold the result.
48704953
/// If not, this returns null.
48714954
static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
@@ -5041,7 +5124,14 @@ static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
50415124
std::optional<bool> Imp = isImpliedByDomCondition(Cond, Q.CxtI, Q.DL);
50425125
if (Imp)
50435126
return *Imp ? TrueVal : FalseVal;
5044-
5127+
// Look for same PHIs in the true and false values.
5128+
if (auto *TruePHI = dyn_cast<PHINode>(TrueVal))
5129+
if (auto *FalsePHI = dyn_cast<PHINode>(FalseVal)) {
5130+
if (isSelectWithIdenticalPHI(*TruePHI, *FalsePHI))
5131+
return FalseVal;
5132+
if (isSelectWithIdenticalPHI(*FalsePHI, *TruePHI))
5133+
return TrueVal;
5134+
}
50455135
return nullptr;
50465136
}
50475137

0 commit comments

Comments
 (0)