diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-03 14:10:23 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-07-03 14:10:23 +0000 |
commit | 145449b1e420787bb99721a429341fa6be3adfb6 (patch) | |
tree | 1d56ae694a6de602e348dd80165cf881a36600ed /llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp | |
parent | ecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (diff) | |
download | src-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.cpp | 127 |
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)) |