106c3fb27SDimitry Andric //===-- CallBrPrepare - Prepare callbr for code generation ----------------===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric // 906c3fb27SDimitry Andric // This pass lowers callbrs in LLVM IR in order to to assist SelectionDAG's 1006c3fb27SDimitry Andric // codegen. 1106c3fb27SDimitry Andric // 1206c3fb27SDimitry Andric // In particular, this pass assists in inserting register copies for the output 1306c3fb27SDimitry Andric // values of a callbr along the edges leading to the indirect target blocks. 1406c3fb27SDimitry Andric // Though the output SSA value is defined by the callbr instruction itself in 1506c3fb27SDimitry Andric // the IR representation, the value cannot be copied to the appropriate virtual 1606c3fb27SDimitry Andric // registers prior to jumping to an indirect label, since the jump occurs 1706c3fb27SDimitry Andric // within the user-provided assembly blob. 1806c3fb27SDimitry Andric // 1906c3fb27SDimitry Andric // Instead, those copies must occur separately at the beginning of each 2006c3fb27SDimitry Andric // indirect target. That requires that we create a separate SSA definition in 2106c3fb27SDimitry Andric // each of them (via llvm.callbr.landingpad), and may require splitting 2206c3fb27SDimitry Andric // critical edges so we have a location to place the intrinsic. Finally, we 2306c3fb27SDimitry Andric // remap users of the original callbr output SSA value to instead point to the 2406c3fb27SDimitry Andric // appropriate llvm.callbr.landingpad value. 2506c3fb27SDimitry Andric // 2606c3fb27SDimitry Andric // Ideally, this could be done inside SelectionDAG, or in the 2706c3fb27SDimitry Andric // MachineInstruction representation, without the use of an IR-level intrinsic. 2806c3fb27SDimitry Andric // But, within the current framework, it’s simpler to implement as an IR pass. 2906c3fb27SDimitry Andric // (If support for callbr in GlobalISel is implemented, it’s worth considering 3006c3fb27SDimitry Andric // whether this is still required.) 3106c3fb27SDimitry Andric // 3206c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 3306c3fb27SDimitry Andric 345f757f3fSDimitry Andric #include "llvm/CodeGen/CallBrPrepare.h" 3506c3fb27SDimitry Andric #include "llvm/ADT/ArrayRef.h" 3606c3fb27SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 3706c3fb27SDimitry Andric #include "llvm/ADT/SmallVector.h" 3806c3fb27SDimitry Andric #include "llvm/ADT/iterator.h" 3906c3fb27SDimitry Andric #include "llvm/Analysis/CFG.h" 4006c3fb27SDimitry Andric #include "llvm/CodeGen/Passes.h" 4106c3fb27SDimitry Andric #include "llvm/IR/BasicBlock.h" 4206c3fb27SDimitry Andric #include "llvm/IR/Dominators.h" 4306c3fb27SDimitry Andric #include "llvm/IR/Function.h" 4406c3fb27SDimitry Andric #include "llvm/IR/IRBuilder.h" 4506c3fb27SDimitry Andric #include "llvm/IR/Instructions.h" 4606c3fb27SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 4706c3fb27SDimitry Andric #include "llvm/IR/Intrinsics.h" 4806c3fb27SDimitry Andric #include "llvm/InitializePasses.h" 4906c3fb27SDimitry Andric #include "llvm/Pass.h" 5006c3fb27SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 5106c3fb27SDimitry Andric #include "llvm/Transforms/Utils/SSAUpdater.h" 5206c3fb27SDimitry Andric 5306c3fb27SDimitry Andric using namespace llvm; 5406c3fb27SDimitry Andric 55*0fca6ea1SDimitry Andric #define DEBUG_TYPE "callbr-prepare" 5606c3fb27SDimitry Andric 575f757f3fSDimitry Andric static bool SplitCriticalEdges(ArrayRef<CallBrInst *> CBRs, DominatorTree &DT); 585f757f3fSDimitry Andric static bool InsertIntrinsicCalls(ArrayRef<CallBrInst *> CBRs, 595f757f3fSDimitry Andric DominatorTree &DT); 605f757f3fSDimitry Andric static void UpdateSSA(DominatorTree &DT, CallBrInst *CBR, CallInst *Intrinsic, 615f757f3fSDimitry Andric SSAUpdater &SSAUpdate); 625f757f3fSDimitry Andric static SmallVector<CallBrInst *, 2> FindCallBrs(Function &Fn); 635f757f3fSDimitry Andric 6406c3fb27SDimitry Andric namespace { 6506c3fb27SDimitry Andric 6606c3fb27SDimitry Andric class CallBrPrepare : public FunctionPass { 6706c3fb27SDimitry Andric public: 6806c3fb27SDimitry Andric CallBrPrepare() : FunctionPass(ID) {} 6906c3fb27SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 7006c3fb27SDimitry Andric bool runOnFunction(Function &Fn) override; 7106c3fb27SDimitry Andric static char ID; 7206c3fb27SDimitry Andric }; 7306c3fb27SDimitry Andric 7406c3fb27SDimitry Andric } // end anonymous namespace 7506c3fb27SDimitry Andric 765f757f3fSDimitry Andric PreservedAnalyses CallBrPreparePass::run(Function &Fn, 775f757f3fSDimitry Andric FunctionAnalysisManager &FAM) { 785f757f3fSDimitry Andric bool Changed = false; 795f757f3fSDimitry Andric SmallVector<CallBrInst *, 2> CBRs = FindCallBrs(Fn); 805f757f3fSDimitry Andric 815f757f3fSDimitry Andric if (CBRs.empty()) 825f757f3fSDimitry Andric return PreservedAnalyses::all(); 835f757f3fSDimitry Andric 845f757f3fSDimitry Andric auto &DT = FAM.getResult<DominatorTreeAnalysis>(Fn); 855f757f3fSDimitry Andric 865f757f3fSDimitry Andric Changed |= SplitCriticalEdges(CBRs, DT); 875f757f3fSDimitry Andric Changed |= InsertIntrinsicCalls(CBRs, DT); 885f757f3fSDimitry Andric 895f757f3fSDimitry Andric if (!Changed) 905f757f3fSDimitry Andric return PreservedAnalyses::all(); 915f757f3fSDimitry Andric PreservedAnalyses PA; 925f757f3fSDimitry Andric PA.preserve<DominatorTreeAnalysis>(); 935f757f3fSDimitry Andric return PA; 945f757f3fSDimitry Andric } 955f757f3fSDimitry Andric 9606c3fb27SDimitry Andric char CallBrPrepare::ID = 0; 97*0fca6ea1SDimitry Andric INITIALIZE_PASS_BEGIN(CallBrPrepare, "callbrprepare", "Prepare callbr", false, 98*0fca6ea1SDimitry Andric false) 9906c3fb27SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 100*0fca6ea1SDimitry Andric INITIALIZE_PASS_END(CallBrPrepare, "callbrprepare", "Prepare callbr", false, 101*0fca6ea1SDimitry Andric false) 10206c3fb27SDimitry Andric 10306c3fb27SDimitry Andric FunctionPass *llvm::createCallBrPass() { return new CallBrPrepare(); } 10406c3fb27SDimitry Andric 10506c3fb27SDimitry Andric void CallBrPrepare::getAnalysisUsage(AnalysisUsage &AU) const { 10606c3fb27SDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>(); 10706c3fb27SDimitry Andric } 10806c3fb27SDimitry Andric 1095f757f3fSDimitry Andric SmallVector<CallBrInst *, 2> FindCallBrs(Function &Fn) { 11006c3fb27SDimitry Andric SmallVector<CallBrInst *, 2> CBRs; 11106c3fb27SDimitry Andric for (BasicBlock &BB : Fn) 11206c3fb27SDimitry Andric if (auto *CBR = dyn_cast<CallBrInst>(BB.getTerminator())) 11306c3fb27SDimitry Andric if (!CBR->getType()->isVoidTy() && !CBR->use_empty()) 11406c3fb27SDimitry Andric CBRs.push_back(CBR); 11506c3fb27SDimitry Andric return CBRs; 11606c3fb27SDimitry Andric } 11706c3fb27SDimitry Andric 1185f757f3fSDimitry Andric bool SplitCriticalEdges(ArrayRef<CallBrInst *> CBRs, DominatorTree &DT) { 11906c3fb27SDimitry Andric bool Changed = false; 12006c3fb27SDimitry Andric CriticalEdgeSplittingOptions Options(&DT); 12106c3fb27SDimitry Andric Options.setMergeIdenticalEdges(); 12206c3fb27SDimitry Andric 12306c3fb27SDimitry Andric // The indirect destination might be duplicated between another parameter... 12406c3fb27SDimitry Andric // %0 = callbr ... [label %x, label %x] 12506c3fb27SDimitry Andric // ...hence MergeIdenticalEdges and AllowIndentical edges, but we don't need 12606c3fb27SDimitry Andric // to split the default destination if it's duplicated between an indirect 12706c3fb27SDimitry Andric // destination... 12806c3fb27SDimitry Andric // %1 = callbr ... to label %x [label %x] 12906c3fb27SDimitry Andric // ...hence starting at 1 and checking against successor 0 (aka the default 13006c3fb27SDimitry Andric // destination). 13106c3fb27SDimitry Andric for (CallBrInst *CBR : CBRs) 13206c3fb27SDimitry Andric for (unsigned i = 1, e = CBR->getNumSuccessors(); i != e; ++i) 13306c3fb27SDimitry Andric if (CBR->getSuccessor(i) == CBR->getSuccessor(0) || 13406c3fb27SDimitry Andric isCriticalEdge(CBR, i, /*AllowIdenticalEdges*/ true)) 13506c3fb27SDimitry Andric if (SplitKnownCriticalEdge(CBR, i, Options)) 13606c3fb27SDimitry Andric Changed = true; 13706c3fb27SDimitry Andric return Changed; 13806c3fb27SDimitry Andric } 13906c3fb27SDimitry Andric 1405f757f3fSDimitry Andric bool InsertIntrinsicCalls(ArrayRef<CallBrInst *> CBRs, DominatorTree &DT) { 14106c3fb27SDimitry Andric bool Changed = false; 14206c3fb27SDimitry Andric SmallPtrSet<const BasicBlock *, 4> Visited; 14306c3fb27SDimitry Andric IRBuilder<> Builder(CBRs[0]->getContext()); 14406c3fb27SDimitry Andric for (CallBrInst *CBR : CBRs) { 14506c3fb27SDimitry Andric if (!CBR->getNumIndirectDests()) 14606c3fb27SDimitry Andric continue; 14706c3fb27SDimitry Andric 14806c3fb27SDimitry Andric SSAUpdater SSAUpdate; 14906c3fb27SDimitry Andric SSAUpdate.Initialize(CBR->getType(), CBR->getName()); 15006c3fb27SDimitry Andric SSAUpdate.AddAvailableValue(CBR->getParent(), CBR); 15106c3fb27SDimitry Andric SSAUpdate.AddAvailableValue(CBR->getDefaultDest(), CBR); 15206c3fb27SDimitry Andric 15306c3fb27SDimitry Andric for (BasicBlock *IndDest : CBR->getIndirectDests()) { 15406c3fb27SDimitry Andric if (!Visited.insert(IndDest).second) 15506c3fb27SDimitry Andric continue; 15606c3fb27SDimitry Andric Builder.SetInsertPoint(&*IndDest->begin()); 15706c3fb27SDimitry Andric CallInst *Intrinsic = Builder.CreateIntrinsic( 15806c3fb27SDimitry Andric CBR->getType(), Intrinsic::callbr_landingpad, {CBR}); 15906c3fb27SDimitry Andric SSAUpdate.AddAvailableValue(IndDest, Intrinsic); 16006c3fb27SDimitry Andric UpdateSSA(DT, CBR, Intrinsic, SSAUpdate); 16106c3fb27SDimitry Andric Changed = true; 16206c3fb27SDimitry Andric } 16306c3fb27SDimitry Andric } 16406c3fb27SDimitry Andric return Changed; 16506c3fb27SDimitry Andric } 16606c3fb27SDimitry Andric 16706c3fb27SDimitry Andric static bool IsInSameBasicBlock(const Use &U, const BasicBlock *BB) { 16806c3fb27SDimitry Andric const auto *I = dyn_cast<Instruction>(U.getUser()); 16906c3fb27SDimitry Andric return I && I->getParent() == BB; 17006c3fb27SDimitry Andric } 17106c3fb27SDimitry Andric 17206c3fb27SDimitry Andric #ifndef NDEBUG 17306c3fb27SDimitry Andric static void PrintDebugDomInfo(const DominatorTree &DT, const Use &U, 17406c3fb27SDimitry Andric const BasicBlock *BB, bool IsDefaultDest) { 17506c3fb27SDimitry Andric if (!isa<Instruction>(U.getUser())) 17606c3fb27SDimitry Andric return; 17706c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Use: " << *U.getUser() << ", in block " 17806c3fb27SDimitry Andric << cast<Instruction>(U.getUser())->getParent()->getName() 17906c3fb27SDimitry Andric << ", is " << (DT.dominates(BB, U) ? "" : "NOT ") 18006c3fb27SDimitry Andric << "dominated by " << BB->getName() << " (" 18106c3fb27SDimitry Andric << (IsDefaultDest ? "in" : "") << "direct)\n"); 18206c3fb27SDimitry Andric } 18306c3fb27SDimitry Andric #endif 18406c3fb27SDimitry Andric 1855f757f3fSDimitry Andric void UpdateSSA(DominatorTree &DT, CallBrInst *CBR, CallInst *Intrinsic, 1865f757f3fSDimitry Andric SSAUpdater &SSAUpdate) { 18706c3fb27SDimitry Andric 18806c3fb27SDimitry Andric SmallPtrSet<Use *, 4> Visited; 18906c3fb27SDimitry Andric BasicBlock *DefaultDest = CBR->getDefaultDest(); 19006c3fb27SDimitry Andric BasicBlock *LandingPad = Intrinsic->getParent(); 19106c3fb27SDimitry Andric 19206c3fb27SDimitry Andric SmallVector<Use *, 4> Uses(make_pointer_range(CBR->uses())); 19306c3fb27SDimitry Andric for (Use *U : Uses) { 19406c3fb27SDimitry Andric if (!Visited.insert(U).second) 19506c3fb27SDimitry Andric continue; 19606c3fb27SDimitry Andric 19706c3fb27SDimitry Andric #ifndef NDEBUG 19806c3fb27SDimitry Andric PrintDebugDomInfo(DT, *U, LandingPad, /*IsDefaultDest*/ false); 19906c3fb27SDimitry Andric PrintDebugDomInfo(DT, *U, DefaultDest, /*IsDefaultDest*/ true); 20006c3fb27SDimitry Andric #endif 20106c3fb27SDimitry Andric 20206c3fb27SDimitry Andric // Don't rewrite the use in the newly inserted intrinsic. 20306c3fb27SDimitry Andric if (const auto *II = dyn_cast<IntrinsicInst>(U->getUser())) 20406c3fb27SDimitry Andric if (II->getIntrinsicID() == Intrinsic::callbr_landingpad) 20506c3fb27SDimitry Andric continue; 20606c3fb27SDimitry Andric 20706c3fb27SDimitry Andric // If the Use is in the same BasicBlock as the Intrinsic call, replace 20806c3fb27SDimitry Andric // the Use with the value of the Intrinsic call. 20906c3fb27SDimitry Andric if (IsInSameBasicBlock(*U, LandingPad)) { 21006c3fb27SDimitry Andric U->set(Intrinsic); 21106c3fb27SDimitry Andric continue; 21206c3fb27SDimitry Andric } 21306c3fb27SDimitry Andric 21406c3fb27SDimitry Andric // If the Use is dominated by the default dest, do not touch it. 21506c3fb27SDimitry Andric if (DT.dominates(DefaultDest, *U)) 21606c3fb27SDimitry Andric continue; 21706c3fb27SDimitry Andric 21806c3fb27SDimitry Andric SSAUpdate.RewriteUse(*U); 21906c3fb27SDimitry Andric } 22006c3fb27SDimitry Andric } 22106c3fb27SDimitry Andric 22206c3fb27SDimitry Andric bool CallBrPrepare::runOnFunction(Function &Fn) { 22306c3fb27SDimitry Andric bool Changed = false; 22406c3fb27SDimitry Andric SmallVector<CallBrInst *, 2> CBRs = FindCallBrs(Fn); 22506c3fb27SDimitry Andric 22606c3fb27SDimitry Andric if (CBRs.empty()) 22706c3fb27SDimitry Andric return Changed; 22806c3fb27SDimitry Andric 22906c3fb27SDimitry Andric // It's highly likely that most programs do not contain CallBrInsts. Follow a 23006c3fb27SDimitry Andric // similar pattern from SafeStackLegacyPass::runOnFunction to reuse previous 23106c3fb27SDimitry Andric // domtree analysis if available, otherwise compute it lazily. This avoids 23206c3fb27SDimitry Andric // forcing Dominator Tree Construction at -O0 for programs that likely do not 23306c3fb27SDimitry Andric // contain CallBrInsts. It does pessimize programs with callbr at higher 23406c3fb27SDimitry Andric // optimization levels, as the DominatorTree created here is not reused by 23506c3fb27SDimitry Andric // subsequent passes. 23606c3fb27SDimitry Andric DominatorTree *DT; 23706c3fb27SDimitry Andric std::optional<DominatorTree> LazilyComputedDomTree; 23806c3fb27SDimitry Andric if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>()) 23906c3fb27SDimitry Andric DT = &DTWP->getDomTree(); 24006c3fb27SDimitry Andric else { 24106c3fb27SDimitry Andric LazilyComputedDomTree.emplace(Fn); 24206c3fb27SDimitry Andric DT = &*LazilyComputedDomTree; 24306c3fb27SDimitry Andric } 24406c3fb27SDimitry Andric 24506c3fb27SDimitry Andric if (SplitCriticalEdges(CBRs, *DT)) 24606c3fb27SDimitry Andric Changed = true; 24706c3fb27SDimitry Andric 24806c3fb27SDimitry Andric if (InsertIntrinsicCalls(CBRs, *DT)) 24906c3fb27SDimitry Andric Changed = true; 25006c3fb27SDimitry Andric 25106c3fb27SDimitry Andric return Changed; 25206c3fb27SDimitry Andric } 253