diff options
Diffstat (limited to 'gnu/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp')
| -rw-r--r-- | gnu/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp | 94 |
1 files changed, 48 insertions, 46 deletions
diff --git a/gnu/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp b/gnu/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp index 71980e85e8c..76fe91884c7 100644 --- a/gnu/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp +++ b/gnu/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp @@ -210,7 +210,7 @@ namespace { bool runOnLoop(Loop *L, LPPassManager &LPM) override; bool processCurrentLoop(); - + bool isUnreachableDueToPreviousUnswitching(BasicBlock *); /// This transformation requires natural loop information & requires that /// loop preheaders be inserted into the CFG. /// @@ -483,6 +483,35 @@ bool LoopUnswitch::runOnLoop(Loop *L, LPPassManager &LPM_Ref) { return Changed; } +// Return true if the BasicBlock BB is unreachable from the loop header. +// Return false, otherwise. +bool LoopUnswitch::isUnreachableDueToPreviousUnswitching(BasicBlock *BB) { + auto *Node = DT->getNode(BB)->getIDom(); + BasicBlock *DomBB = Node->getBlock(); + while (currentLoop->contains(DomBB)) { + BranchInst *BInst = dyn_cast<BranchInst>(DomBB->getTerminator()); + + Node = DT->getNode(DomBB)->getIDom(); + DomBB = Node->getBlock(); + + if (!BInst || !BInst->isConditional()) + continue; + + Value *Cond = BInst->getCondition(); + if (!isa<ConstantInt>(Cond)) + continue; + + BasicBlock *UnreachableSucc = + Cond == ConstantInt::getTrue(Cond->getContext()) + ? BInst->getSuccessor(1) + : BInst->getSuccessor(0); + + if (DT->dominates(UnreachableSucc, BB)) + return true; + } + return false; +} + /// Do actual work and unswitch loop if possible and profitable. bool LoopUnswitch::processCurrentLoop() { bool Changed = false; @@ -593,6 +622,12 @@ bool LoopUnswitch::processCurrentLoop() { continue; if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { + // Some branches may be rendered unreachable because of previous + // unswitching. + // Unswitch only those branches that are reachable. + if (isUnreachableDueToPreviousUnswitching(*I)) + continue; + // If this isn't branching on an invariant condition, we can't unswitch // it. if (BI->isConditional()) { @@ -742,42 +777,6 @@ static Loop *CloneLoop(Loop *L, Loop *PL, ValueToValueMapTy &VM, return &New; } -static void copyMetadata(Instruction *DstInst, const Instruction *SrcInst, - bool Swapped) { - if (!SrcInst || !SrcInst->hasMetadata()) - return; - - SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; - SrcInst->getAllMetadata(MDs); - for (auto &MD : MDs) { - switch (MD.first) { - default: - break; - case LLVMContext::MD_prof: - if (Swapped && MD.second->getNumOperands() == 3 && - isa<MDString>(MD.second->getOperand(0))) { - MDString *MDName = cast<MDString>(MD.second->getOperand(0)); - if (MDName->getString() == "branch_weights") { - auto *ValT = cast_or_null<ConstantAsMetadata>( - MD.second->getOperand(1))->getValue(); - auto *ValF = cast_or_null<ConstantAsMetadata>( - MD.second->getOperand(2))->getValue(); - assert(ValT && ValF && "Invalid Operands of branch_weights"); - auto NewMD = - MDBuilder(DstInst->getParent()->getContext()) - .createBranchWeights(cast<ConstantInt>(ValF)->getZExtValue(), - cast<ConstantInt>(ValT)->getZExtValue()); - MD.second = NewMD; - } - } - // fallthrough. - case LLVMContext::MD_make_implicit: - case LLVMContext::MD_dbg: - DstInst->setMetadata(MD.first, MD.second); - } - } -} - /// Emit a conditional branch on two values if LIC == Val, branch to TrueDst, /// otherwise branch to FalseDest. Insert the code immediately before InsertPt. void LoopUnswitch::EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val, @@ -799,8 +798,10 @@ void LoopUnswitch::EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val, } // Insert the new branch. - BranchInst *BI = BranchInst::Create(TrueDest, FalseDest, BranchVal, InsertPt); - copyMetadata(BI, TI, Swapped); + BranchInst *BI = + IRBuilder<>(InsertPt).CreateCondBr(BranchVal, TrueDest, FalseDest, TI); + if (Swapped) + BI->swapProfMetadata(); // If either edge is critical, split it. This helps preserve LoopSimplify // form for enclosing loops. @@ -1078,10 +1079,6 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, F->getBasicBlockList(), NewBlocks[0]->getIterator(), F->end()); - // FIXME: We could register any cloned assumptions instead of clearing the - // whole function's cache. - AC->clear(); - // Now we create the new Loop object for the versioned loop. Loop *NewLoop = CloneLoop(L, L->getParentLoop(), VMap, LI, LPM); @@ -1131,10 +1128,15 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, } // Rewrite the code to refer to itself. - for (unsigned i = 0, e = NewBlocks.size(); i != e; ++i) - for (Instruction &I : *NewBlocks[i]) + for (unsigned i = 0, e = NewBlocks.size(); i != e; ++i) { + for (Instruction &I : *NewBlocks[i]) { RemapInstruction(&I, VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); + if (auto *II = dyn_cast<IntrinsicInst>(&I)) + if (II->getIntrinsicID() == Intrinsic::assume) + AC->registerAssumption(II); + } + } // Rewrite the original preheader to select between versions of the loop. BranchInst *OldBR = cast<BranchInst>(loopPreheader->getTerminator()); @@ -1380,8 +1382,8 @@ void LoopUnswitch::SimplifyCode(std::vector<Instruction*> &Worklist, Loop *L) { Pred->getInstList().splice(BI->getIterator(), Succ->getInstList(), Succ->begin(), Succ->end()); LPM->deleteSimpleAnalysisValue(BI, L); - BI->eraseFromParent(); RemoveFromWorklist(BI, Worklist); + BI->eraseFromParent(); // Remove Succ from the loop tree. LI->removeBlock(Succ); |
