aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-03 14:10:23 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-07-03 14:10:23 +0000
commit145449b1e420787bb99721a429341fa6be3adfb6 (patch)
tree1d56ae694a6de602e348dd80165cf881a36600ed /llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
parentecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (diff)
downloadsrc-145449b1e420787bb99721a429341fa6be3adfb6.tar.gz
src-145449b1e420787bb99721a429341fa6be3adfb6.zip
Vendor import of llvm-project main llvmorg-15-init-15358-g53dc0f107877.vendor/llvm-project/llvmorg-15-init-15358-g53dc0f107877
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp127
1 files changed, 85 insertions, 42 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
index 09694d50468f..90a796a0939e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
@@ -511,7 +511,8 @@ Instruction *InstCombinerImpl::foldPHIArgGEPIntoPHI(PHINode &PN) {
// Scan to see if all operands are the same opcode, and all have one user.
for (Value *V : drop_begin(PN.incoming_values())) {
GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(V);
- if (!GEP || !GEP->hasOneUser() || GEP->getType() != FirstInst->getType() ||
+ if (!GEP || !GEP->hasOneUser() ||
+ GEP->getSourceElementType() != FirstInst->getSourceElementType() ||
GEP->getNumOperands() != FirstInst->getNumOperands())
return nullptr;
@@ -657,6 +658,10 @@ static bool isSafeAndProfitableToSinkLoad(LoadInst *L) {
Instruction *InstCombinerImpl::foldPHIArgLoadIntoPHI(PHINode &PN) {
LoadInst *FirstLI = cast<LoadInst>(PN.getIncomingValue(0));
+ // Can't forward swifterror through a phi.
+ if (FirstLI->getOperand(0)->isSwiftError())
+ return nullptr;
+
// FIXME: This is overconservative; this transform is allowed in some cases
// for atomic operations.
if (FirstLI->isAtomic())
@@ -693,6 +698,10 @@ Instruction *InstCombinerImpl::foldPHIArgLoadIntoPHI(PHINode &PN) {
LI->getPointerAddressSpace() != LoadAddrSpace)
return nullptr;
+ // Can't forward swifterror through a phi.
+ if (LI->getOperand(0)->isSwiftError())
+ return nullptr;
+
// We can't sink the load if the loaded value could be modified between
// the load and the PHI.
if (LI->getParent() != InBB || !isSafeAndProfitableToSinkLoad(LI))
@@ -1112,6 +1121,13 @@ Instruction *InstCombinerImpl::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) {
return nullptr;
}
+ // If the incoming value is a PHI node before a catchswitch, we cannot
+ // extract the value within that BB because we cannot insert any non-PHI
+ // instructions in the BB.
+ for (auto *Pred : PN->blocks())
+ if (Pred->getFirstInsertionPt() == Pred->end())
+ return nullptr;
+
for (User *U : PN->users()) {
Instruction *UserI = cast<Instruction>(U);
@@ -1260,12 +1276,12 @@ static Value *simplifyUsingControlFlow(InstCombiner &Self, PHINode &PN,
// ... ...
// \ /
// phi [true] [false]
- if (!PN.getType()->isIntegerTy(1))
- return nullptr;
-
- if (PN.getNumOperands() != 2)
- return nullptr;
-
+ // and
+ // switch (cond)
+ // case v1: / \ case v2:
+ // ... ...
+ // \ /
+ // phi [v1] [v2]
// Make sure all inputs are constants.
if (!all_of(PN.operands(), [](Value *V) { return isa<ConstantInt>(V); }))
return nullptr;
@@ -1275,50 +1291,77 @@ static Value *simplifyUsingControlFlow(InstCombiner &Self, PHINode &PN,
if (!DT.isReachableFromEntry(BB))
return nullptr;
- // Same inputs.
- if (PN.getOperand(0) == PN.getOperand(1))
- return PN.getOperand(0);
+ // Determine which value the condition of the idom has for which successor.
+ LLVMContext &Context = PN.getContext();
+ auto *IDom = DT.getNode(BB)->getIDom()->getBlock();
+ Value *Cond;
+ SmallDenseMap<ConstantInt *, BasicBlock *, 8> SuccForValue;
+ SmallDenseMap<BasicBlock *, unsigned, 8> SuccCount;
+ auto AddSucc = [&](ConstantInt *C, BasicBlock *Succ) {
+ SuccForValue[C] = Succ;
+ ++SuccCount[Succ];
+ };
+ if (auto *BI = dyn_cast<BranchInst>(IDom->getTerminator())) {
+ if (BI->isUnconditional())
+ return nullptr;
- BasicBlock *TruePred = nullptr, *FalsePred = nullptr;
- for (auto *Pred : predecessors(BB)) {
- auto *Input = cast<ConstantInt>(PN.getIncomingValueForBlock(Pred));
- if (Input->isAllOnesValue())
- TruePred = Pred;
- else
- FalsePred = Pred;
+ Cond = BI->getCondition();
+ AddSucc(ConstantInt::getTrue(Context), BI->getSuccessor(0));
+ AddSucc(ConstantInt::getFalse(Context), BI->getSuccessor(1));
+ } else if (auto *SI = dyn_cast<SwitchInst>(IDom->getTerminator())) {
+ Cond = SI->getCondition();
+ ++SuccCount[SI->getDefaultDest()];
+ for (auto Case : SI->cases())
+ AddSucc(Case.getCaseValue(), Case.getCaseSuccessor());
+ } else {
+ return nullptr;
}
- assert(TruePred && FalsePred && "Must be!");
- // Check which edge of the dominator dominates the true input. If it is the
- // false edge, we should invert the condition.
- auto *IDom = DT.getNode(BB)->getIDom()->getBlock();
- auto *BI = dyn_cast<BranchInst>(IDom->getTerminator());
- if (!BI || BI->isUnconditional())
+ if (Cond->getType() != PN.getType())
return nullptr;
// Check that edges outgoing from the idom's terminators dominate respective
// inputs of the Phi.
- BasicBlockEdge TrueOutEdge(IDom, BI->getSuccessor(0));
- BasicBlockEdge FalseOutEdge(IDom, BI->getSuccessor(1));
+ Optional<bool> Invert;
+ for (auto Pair : zip(PN.incoming_values(), PN.blocks())) {
+ auto *Input = cast<ConstantInt>(std::get<0>(Pair));
+ BasicBlock *Pred = std::get<1>(Pair);
+ auto IsCorrectInput = [&](ConstantInt *Input) {
+ // The input needs to be dominated by the corresponding edge of the idom.
+ // This edge cannot be a multi-edge, as that would imply that multiple
+ // different condition values follow the same edge.
+ auto It = SuccForValue.find(Input);
+ return It != SuccForValue.end() && SuccCount[It->second] == 1 &&
+ DT.dominates(BasicBlockEdge(IDom, It->second),
+ BasicBlockEdge(Pred, BB));
+ };
+
+ // Depending on the constant, the condition may need to be inverted.
+ bool NeedsInvert;
+ if (IsCorrectInput(Input))
+ NeedsInvert = false;
+ else if (IsCorrectInput(cast<ConstantInt>(ConstantExpr::getNot(Input))))
+ NeedsInvert = true;
+ else
+ return nullptr;
+
+ // Make sure the inversion requirement is always the same.
+ if (Invert && *Invert != NeedsInvert)
+ return nullptr;
- BasicBlockEdge TrueIncEdge(TruePred, BB);
- BasicBlockEdge FalseIncEdge(FalsePred, BB);
+ Invert = NeedsInvert;
+ }
- auto *Cond = BI->getCondition();
- if (DT.dominates(TrueOutEdge, TrueIncEdge) &&
- DT.dominates(FalseOutEdge, FalseIncEdge))
- // This Phi is actually equivalent to branching condition of IDom.
+ if (!*Invert)
return Cond;
- if (DT.dominates(TrueOutEdge, FalseIncEdge) &&
- DT.dominates(FalseOutEdge, TrueIncEdge)) {
- // This Phi is actually opposite to branching condition of IDom. We invert
- // the condition that will potentially open up some opportunities for
- // sinking.
- auto InsertPt = BB->getFirstInsertionPt();
- if (InsertPt != BB->end()) {
- Self.Builder.SetInsertPoint(&*InsertPt);
- return Self.Builder.CreateNot(Cond);
- }
+
+ // This Phi is actually opposite to branching condition of IDom. We invert
+ // the condition that will potentially open up some opportunities for
+ // sinking.
+ auto InsertPt = BB->getFirstInsertionPt();
+ if (InsertPt != BB->end()) {
+ Self.Builder.SetInsertPoint(&*InsertPt);
+ return Self.Builder.CreateNot(Cond);
}
return nullptr;
@@ -1327,7 +1370,7 @@ static Value *simplifyUsingControlFlow(InstCombiner &Self, PHINode &PN,
// PHINode simplification
//
Instruction *InstCombinerImpl::visitPHINode(PHINode &PN) {
- if (Value *V = SimplifyInstruction(&PN, SQ.getWithInstruction(&PN)))
+ if (Value *V = simplifyInstruction(&PN, SQ.getWithInstruction(&PN)))
return replaceInstUsesWith(PN, V);
if (Instruction *Result = foldPHIArgZextsIntoPHI(PN))