diff options
Diffstat (limited to 'llvm/lib/Transforms/Utils/BasicBlockUtils.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/BasicBlockUtils.cpp | 282 |
1 files changed, 181 insertions, 101 deletions
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp index 58a226fc601c..f06ea89cc61d 100644 --- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -32,6 +32,7 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Type.h" #include "llvm/IR/User.h" @@ -379,8 +380,8 @@ bool llvm::MergeBlockSuccessorsIntoGivenBlocks( /// /// Possible improvements: /// - Check fully overlapping fragments and not only identical fragments. -/// - Support dbg.addr, dbg.declare. dbg.label, and possibly other meta -/// instructions being part of the sequence of consecutive instructions. +/// - Support dbg.declare. dbg.label, and possibly other meta instructions being +/// part of the sequence of consecutive instructions. static bool removeRedundantDbgInstrsUsingBackwardScan(BasicBlock *BB) { SmallVector<DbgValueInst *, 8> ToBeRemoved; SmallDenseSet<DebugVariable> VariableSet; @@ -599,8 +600,8 @@ bool llvm::IsBlockFollowedByDeoptOrUnreachable(const BasicBlock *BB) { unsigned Depth = 0; while (BB && Depth++ < MaxDeoptOrUnreachableSuccessorCheckDepth && VisitedBlocks.insert(BB).second) { - if (BB->getTerminatingDeoptimizeCall() || - isa<UnreachableInst>(BB->getTerminator())) + if (isa<UnreachableInst>(BB->getTerminator()) || + BB->getTerminatingDeoptimizeCall()) return true; BB = BB->getUniqueSuccessor(); } @@ -1470,133 +1471,198 @@ ReturnInst *llvm::FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, return cast<ReturnInst>(NewRet); } -static Instruction * -SplitBlockAndInsertIfThenImpl(Value *Cond, Instruction *SplitBefore, - bool Unreachable, MDNode *BranchWeights, - DomTreeUpdater *DTU, DominatorTree *DT, - LoopInfo *LI, BasicBlock *ThenBlock) { - SmallVector<DominatorTree::UpdateType, 8> Updates; - BasicBlock *Head = SplitBefore->getParent(); - BasicBlock *Tail = Head->splitBasicBlock(SplitBefore->getIterator()); - if (DTU) { - SmallPtrSet<BasicBlock *, 8> UniqueSuccessorsOfHead; - Updates.push_back({DominatorTree::Insert, Head, Tail}); - Updates.reserve(Updates.size() + 2 * succ_size(Tail)); - for (BasicBlock *SuccessorOfHead : successors(Tail)) - if (UniqueSuccessorsOfHead.insert(SuccessorOfHead).second) { - Updates.push_back({DominatorTree::Insert, Tail, SuccessorOfHead}); - Updates.push_back({DominatorTree::Delete, Head, SuccessorOfHead}); - } - } - Instruction *HeadOldTerm = Head->getTerminator(); - LLVMContext &C = Head->getContext(); - Instruction *CheckTerm; - bool CreateThenBlock = (ThenBlock == nullptr); - if (CreateThenBlock) { - ThenBlock = BasicBlock::Create(C, "", Head->getParent(), Tail); - if (Unreachable) - CheckTerm = new UnreachableInst(C, ThenBlock); - else { - CheckTerm = BranchInst::Create(Tail, ThenBlock); - if (DTU) - Updates.push_back({DominatorTree::Insert, ThenBlock, Tail}); - } - CheckTerm->setDebugLoc(SplitBefore->getDebugLoc()); - } else - CheckTerm = ThenBlock->getTerminator(); - BranchInst *HeadNewTerm = - BranchInst::Create(/*ifTrue*/ ThenBlock, /*ifFalse*/ Tail, Cond); - if (DTU) - Updates.push_back({DominatorTree::Insert, Head, ThenBlock}); - HeadNewTerm->setMetadata(LLVMContext::MD_prof, BranchWeights); - ReplaceInstWithInst(HeadOldTerm, HeadNewTerm); - - if (DTU) - DTU->applyUpdates(Updates); - else if (DT) { - if (DomTreeNode *OldNode = DT->getNode(Head)) { - std::vector<DomTreeNode *> Children(OldNode->begin(), OldNode->end()); - - DomTreeNode *NewNode = DT->addNewBlock(Tail, Head); - for (DomTreeNode *Child : Children) - DT->changeImmediateDominator(Child, NewNode); - - // Head dominates ThenBlock. - if (CreateThenBlock) - DT->addNewBlock(ThenBlock, Head); - else - DT->changeImmediateDominator(ThenBlock, Head); - } - } - - if (LI) { - if (Loop *L = LI->getLoopFor(Head)) { - L->addBasicBlockToLoop(ThenBlock, *LI); - L->addBasicBlockToLoop(Tail, *LI); - } - } - - return CheckTerm; -} - Instruction *llvm::SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights, - DominatorTree *DT, LoopInfo *LI, + DomTreeUpdater *DTU, LoopInfo *LI, BasicBlock *ThenBlock) { - return SplitBlockAndInsertIfThenImpl(Cond, SplitBefore, Unreachable, - BranchWeights, - /*DTU=*/nullptr, DT, LI, ThenBlock); + SplitBlockAndInsertIfThenElse( + Cond, SplitBefore, &ThenBlock, /* ElseBlock */ nullptr, + /* UnreachableThen */ Unreachable, + /* UnreachableElse */ false, BranchWeights, DTU, LI); + return ThenBlock->getTerminator(); } -Instruction *llvm::SplitBlockAndInsertIfThen(Value *Cond, + +Instruction *llvm::SplitBlockAndInsertIfElse(Value *Cond, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights, DomTreeUpdater *DTU, LoopInfo *LI, - BasicBlock *ThenBlock) { - return SplitBlockAndInsertIfThenImpl(Cond, SplitBefore, Unreachable, - BranchWeights, DTU, /*DT=*/nullptr, LI, - ThenBlock); + BasicBlock *ElseBlock) { + SplitBlockAndInsertIfThenElse( + Cond, SplitBefore, /* ThenBlock */ nullptr, &ElseBlock, + /* UnreachableThen */ false, + /* UnreachableElse */ Unreachable, BranchWeights, DTU, LI); + return ElseBlock->getTerminator(); } void llvm::SplitBlockAndInsertIfThenElse(Value *Cond, Instruction *SplitBefore, Instruction **ThenTerm, Instruction **ElseTerm, MDNode *BranchWeights, - DomTreeUpdater *DTU) { - BasicBlock *Head = SplitBefore->getParent(); + DomTreeUpdater *DTU, LoopInfo *LI) { + BasicBlock *ThenBlock = nullptr; + BasicBlock *ElseBlock = nullptr; + SplitBlockAndInsertIfThenElse( + Cond, SplitBefore, &ThenBlock, &ElseBlock, /* UnreachableThen */ false, + /* UnreachableElse */ false, BranchWeights, DTU, LI); + + *ThenTerm = ThenBlock->getTerminator(); + *ElseTerm = ElseBlock->getTerminator(); +} + +void llvm::SplitBlockAndInsertIfThenElse( + Value *Cond, Instruction *SplitBefore, BasicBlock **ThenBlock, + BasicBlock **ElseBlock, bool UnreachableThen, bool UnreachableElse, + MDNode *BranchWeights, DomTreeUpdater *DTU, LoopInfo *LI) { + assert((ThenBlock || ElseBlock) && + "At least one branch block must be created"); + assert((!UnreachableThen || !UnreachableElse) && + "Split block tail must be reachable"); + SmallVector<DominatorTree::UpdateType, 8> Updates; SmallPtrSet<BasicBlock *, 8> UniqueOrigSuccessors; - if (DTU) + BasicBlock *Head = SplitBefore->getParent(); + if (DTU) { UniqueOrigSuccessors.insert(succ_begin(Head), succ_end(Head)); + Updates.reserve(4 + 2 * UniqueOrigSuccessors.size()); + } + LLVMContext &C = Head->getContext(); BasicBlock *Tail = Head->splitBasicBlock(SplitBefore->getIterator()); + BasicBlock *TrueBlock = Tail; + BasicBlock *FalseBlock = Tail; + bool ThenToTailEdge = false; + bool ElseToTailEdge = false; + + // Encapsulate the logic around creation/insertion/etc of a new block. + auto handleBlock = [&](BasicBlock **PBB, bool Unreachable, BasicBlock *&BB, + bool &ToTailEdge) { + if (PBB == nullptr) + return; // Do not create/insert a block. + + if (*PBB) + BB = *PBB; // Caller supplied block, use it. + else { + // Create a new block. + BB = BasicBlock::Create(C, "", Head->getParent(), Tail); + if (Unreachable) + (void)new UnreachableInst(C, BB); + else { + (void)BranchInst::Create(Tail, BB); + ToTailEdge = true; + } + BB->getTerminator()->setDebugLoc(SplitBefore->getDebugLoc()); + // Pass the new block back to the caller. + *PBB = BB; + } + }; + + handleBlock(ThenBlock, UnreachableThen, TrueBlock, ThenToTailEdge); + handleBlock(ElseBlock, UnreachableElse, FalseBlock, ElseToTailEdge); + Instruction *HeadOldTerm = Head->getTerminator(); - LLVMContext &C = Head->getContext(); - BasicBlock *ThenBlock = BasicBlock::Create(C, "", Head->getParent(), Tail); - BasicBlock *ElseBlock = BasicBlock::Create(C, "", Head->getParent(), Tail); - *ThenTerm = BranchInst::Create(Tail, ThenBlock); - (*ThenTerm)->setDebugLoc(SplitBefore->getDebugLoc()); - *ElseTerm = BranchInst::Create(Tail, ElseBlock); - (*ElseTerm)->setDebugLoc(SplitBefore->getDebugLoc()); BranchInst *HeadNewTerm = - BranchInst::Create(/*ifTrue*/ThenBlock, /*ifFalse*/ElseBlock, Cond); + BranchInst::Create(/*ifTrue*/ TrueBlock, /*ifFalse*/ FalseBlock, Cond); HeadNewTerm->setMetadata(LLVMContext::MD_prof, BranchWeights); ReplaceInstWithInst(HeadOldTerm, HeadNewTerm); + if (DTU) { - SmallVector<DominatorTree::UpdateType, 8> Updates; - Updates.reserve(4 + 2 * UniqueOrigSuccessors.size()); - for (BasicBlock *Succ : successors(Head)) { - Updates.push_back({DominatorTree::Insert, Head, Succ}); - Updates.push_back({DominatorTree::Insert, Succ, Tail}); - } + Updates.emplace_back(DominatorTree::Insert, Head, TrueBlock); + Updates.emplace_back(DominatorTree::Insert, Head, FalseBlock); + if (ThenToTailEdge) + Updates.emplace_back(DominatorTree::Insert, TrueBlock, Tail); + if (ElseToTailEdge) + Updates.emplace_back(DominatorTree::Insert, FalseBlock, Tail); for (BasicBlock *UniqueOrigSuccessor : UniqueOrigSuccessors) - Updates.push_back({DominatorTree::Insert, Tail, UniqueOrigSuccessor}); + Updates.emplace_back(DominatorTree::Insert, Tail, UniqueOrigSuccessor); for (BasicBlock *UniqueOrigSuccessor : UniqueOrigSuccessors) - Updates.push_back({DominatorTree::Delete, Head, UniqueOrigSuccessor}); + Updates.emplace_back(DominatorTree::Delete, Head, UniqueOrigSuccessor); DTU->applyUpdates(Updates); } + + if (LI) { + if (Loop *L = LI->getLoopFor(Head); L) { + if (ThenToTailEdge) + L->addBasicBlockToLoop(TrueBlock, *LI); + if (ElseToTailEdge) + L->addBasicBlockToLoop(FalseBlock, *LI); + L->addBasicBlockToLoop(Tail, *LI); + } + } +} + +std::pair<Instruction*, Value*> +llvm::SplitBlockAndInsertSimpleForLoop(Value *End, Instruction *SplitBefore) { + BasicBlock *LoopPred = SplitBefore->getParent(); + BasicBlock *LoopBody = SplitBlock(SplitBefore->getParent(), SplitBefore); + BasicBlock *LoopExit = SplitBlock(SplitBefore->getParent(), SplitBefore); + + auto *Ty = End->getType(); + auto &DL = SplitBefore->getModule()->getDataLayout(); + const unsigned Bitwidth = DL.getTypeSizeInBits(Ty); + + IRBuilder<> Builder(LoopBody->getTerminator()); + auto *IV = Builder.CreatePHI(Ty, 2, "iv"); + auto *IVNext = + Builder.CreateAdd(IV, ConstantInt::get(Ty, 1), IV->getName() + ".next", + /*HasNUW=*/true, /*HasNSW=*/Bitwidth != 2); + auto *IVCheck = Builder.CreateICmpEQ(IVNext, End, + IV->getName() + ".check"); + Builder.CreateCondBr(IVCheck, LoopExit, LoopBody); + LoopBody->getTerminator()->eraseFromParent(); + + // Populate the IV PHI. + IV->addIncoming(ConstantInt::get(Ty, 0), LoopPred); + IV->addIncoming(IVNext, LoopBody); + + return std::make_pair(LoopBody->getFirstNonPHI(), IV); +} + +void llvm::SplitBlockAndInsertForEachLane(ElementCount EC, + Type *IndexTy, Instruction *InsertBefore, + std::function<void(IRBuilderBase&, Value*)> Func) { + + IRBuilder<> IRB(InsertBefore); + + if (EC.isScalable()) { + Value *NumElements = IRB.CreateElementCount(IndexTy, EC); + + auto [BodyIP, Index] = + SplitBlockAndInsertSimpleForLoop(NumElements, InsertBefore); + + IRB.SetInsertPoint(BodyIP); + Func(IRB, Index); + return; + } + + unsigned Num = EC.getFixedValue(); + for (unsigned Idx = 0; Idx < Num; ++Idx) { + IRB.SetInsertPoint(InsertBefore); + Func(IRB, ConstantInt::get(IndexTy, Idx)); + } +} + +void llvm::SplitBlockAndInsertForEachLane( + Value *EVL, Instruction *InsertBefore, + std::function<void(IRBuilderBase &, Value *)> Func) { + + IRBuilder<> IRB(InsertBefore); + Type *Ty = EVL->getType(); + + if (!isa<ConstantInt>(EVL)) { + auto [BodyIP, Index] = SplitBlockAndInsertSimpleForLoop(EVL, InsertBefore); + IRB.SetInsertPoint(BodyIP); + Func(IRB, Index); + return; + } + + unsigned Num = cast<ConstantInt>(EVL)->getZExtValue(); + for (unsigned Idx = 0; Idx < Num; ++Idx) { + IRB.SetInsertPoint(InsertBefore); + Func(IRB, ConstantInt::get(Ty, Idx)); + } } BranchInst *llvm::GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue, @@ -1997,3 +2063,17 @@ BasicBlock *llvm::CreateControlFlowHub( return FirstGuardBlock; } + +void llvm::InvertBranch(BranchInst *PBI, IRBuilderBase &Builder) { + Value *NewCond = PBI->getCondition(); + // If this is a "cmp" instruction, only used for branching (and nowhere + // else), then we can simply invert the predicate. + if (NewCond->hasOneUse() && isa<CmpInst>(NewCond)) { + CmpInst *CI = cast<CmpInst>(NewCond); + CI->setPredicate(CI->getInversePredicate()); + } else + NewCond = Builder.CreateNot(NewCond, NewCond->getName() + ".not"); + + PBI->setCondition(NewCond); + PBI->swapSuccessors(); +} |