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 34*5f757f3fSDimitry 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 5506c3fb27SDimitry Andric #define DEBUG_TYPE "callbrprepare" 5606c3fb27SDimitry Andric 57*5f757f3fSDimitry Andric static bool SplitCriticalEdges(ArrayRef<CallBrInst *> CBRs, DominatorTree &DT); 58*5f757f3fSDimitry Andric static bool InsertIntrinsicCalls(ArrayRef<CallBrInst *> CBRs, 59*5f757f3fSDimitry Andric DominatorTree &DT); 60*5f757f3fSDimitry Andric static void UpdateSSA(DominatorTree &DT, CallBrInst *CBR, CallInst *Intrinsic, 61*5f757f3fSDimitry Andric SSAUpdater &SSAUpdate); 62*5f757f3fSDimitry Andric static SmallVector<CallBrInst *, 2> FindCallBrs(Function &Fn); 63*5f757f3fSDimitry 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 76*5f757f3fSDimitry Andric PreservedAnalyses CallBrPreparePass::run(Function &Fn, 77*5f757f3fSDimitry Andric FunctionAnalysisManager &FAM) { 78*5f757f3fSDimitry Andric bool Changed = false; 79*5f757f3fSDimitry Andric SmallVector<CallBrInst *, 2> CBRs = FindCallBrs(Fn); 80*5f757f3fSDimitry Andric 81*5f757f3fSDimitry Andric if (CBRs.empty()) 82*5f757f3fSDimitry Andric return PreservedAnalyses::all(); 83*5f757f3fSDimitry Andric 84*5f757f3fSDimitry Andric auto &DT = FAM.getResult<DominatorTreeAnalysis>(Fn); 85*5f757f3fSDimitry Andric 86*5f757f3fSDimitry Andric Changed |= SplitCriticalEdges(CBRs, DT); 87*5f757f3fSDimitry Andric Changed |= InsertIntrinsicCalls(CBRs, DT); 88*5f757f3fSDimitry Andric 89*5f757f3fSDimitry Andric if (!Changed) 90*5f757f3fSDimitry Andric return PreservedAnalyses::all(); 91*5f757f3fSDimitry Andric PreservedAnalyses PA; 92*5f757f3fSDimitry Andric PA.preserve<DominatorTreeAnalysis>(); 93*5f757f3fSDimitry Andric return PA; 94*5f757f3fSDimitry Andric } 95*5f757f3fSDimitry Andric 9606c3fb27SDimitry Andric char CallBrPrepare::ID = 0; 9706c3fb27SDimitry Andric INITIALIZE_PASS_BEGIN(CallBrPrepare, DEBUG_TYPE, "Prepare callbr", false, false) 9806c3fb27SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 9906c3fb27SDimitry Andric INITIALIZE_PASS_END(CallBrPrepare, DEBUG_TYPE, "Prepare callbr", false, false) 10006c3fb27SDimitry Andric 10106c3fb27SDimitry Andric FunctionPass *llvm::createCallBrPass() { return new CallBrPrepare(); } 10206c3fb27SDimitry Andric 10306c3fb27SDimitry Andric void CallBrPrepare::getAnalysisUsage(AnalysisUsage &AU) const { 10406c3fb27SDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>(); 10506c3fb27SDimitry Andric } 10606c3fb27SDimitry Andric 107*5f757f3fSDimitry Andric SmallVector<CallBrInst *, 2> FindCallBrs(Function &Fn) { 10806c3fb27SDimitry Andric SmallVector<CallBrInst *, 2> CBRs; 10906c3fb27SDimitry Andric for (BasicBlock &BB : Fn) 11006c3fb27SDimitry Andric if (auto *CBR = dyn_cast<CallBrInst>(BB.getTerminator())) 11106c3fb27SDimitry Andric if (!CBR->getType()->isVoidTy() && !CBR->use_empty()) 11206c3fb27SDimitry Andric CBRs.push_back(CBR); 11306c3fb27SDimitry Andric return CBRs; 11406c3fb27SDimitry Andric } 11506c3fb27SDimitry Andric 116*5f757f3fSDimitry Andric bool SplitCriticalEdges(ArrayRef<CallBrInst *> CBRs, DominatorTree &DT) { 11706c3fb27SDimitry Andric bool Changed = false; 11806c3fb27SDimitry Andric CriticalEdgeSplittingOptions Options(&DT); 11906c3fb27SDimitry Andric Options.setMergeIdenticalEdges(); 12006c3fb27SDimitry Andric 12106c3fb27SDimitry Andric // The indirect destination might be duplicated between another parameter... 12206c3fb27SDimitry Andric // %0 = callbr ... [label %x, label %x] 12306c3fb27SDimitry Andric // ...hence MergeIdenticalEdges and AllowIndentical edges, but we don't need 12406c3fb27SDimitry Andric // to split the default destination if it's duplicated between an indirect 12506c3fb27SDimitry Andric // destination... 12606c3fb27SDimitry Andric // %1 = callbr ... to label %x [label %x] 12706c3fb27SDimitry Andric // ...hence starting at 1 and checking against successor 0 (aka the default 12806c3fb27SDimitry Andric // destination). 12906c3fb27SDimitry Andric for (CallBrInst *CBR : CBRs) 13006c3fb27SDimitry Andric for (unsigned i = 1, e = CBR->getNumSuccessors(); i != e; ++i) 13106c3fb27SDimitry Andric if (CBR->getSuccessor(i) == CBR->getSuccessor(0) || 13206c3fb27SDimitry Andric isCriticalEdge(CBR, i, /*AllowIdenticalEdges*/ true)) 13306c3fb27SDimitry Andric if (SplitKnownCriticalEdge(CBR, i, Options)) 13406c3fb27SDimitry Andric Changed = true; 13506c3fb27SDimitry Andric return Changed; 13606c3fb27SDimitry Andric } 13706c3fb27SDimitry Andric 138*5f757f3fSDimitry Andric bool InsertIntrinsicCalls(ArrayRef<CallBrInst *> CBRs, DominatorTree &DT) { 13906c3fb27SDimitry Andric bool Changed = false; 14006c3fb27SDimitry Andric SmallPtrSet<const BasicBlock *, 4> Visited; 14106c3fb27SDimitry Andric IRBuilder<> Builder(CBRs[0]->getContext()); 14206c3fb27SDimitry Andric for (CallBrInst *CBR : CBRs) { 14306c3fb27SDimitry Andric if (!CBR->getNumIndirectDests()) 14406c3fb27SDimitry Andric continue; 14506c3fb27SDimitry Andric 14606c3fb27SDimitry Andric SSAUpdater SSAUpdate; 14706c3fb27SDimitry Andric SSAUpdate.Initialize(CBR->getType(), CBR->getName()); 14806c3fb27SDimitry Andric SSAUpdate.AddAvailableValue(CBR->getParent(), CBR); 14906c3fb27SDimitry Andric SSAUpdate.AddAvailableValue(CBR->getDefaultDest(), CBR); 15006c3fb27SDimitry Andric 15106c3fb27SDimitry Andric for (BasicBlock *IndDest : CBR->getIndirectDests()) { 15206c3fb27SDimitry Andric if (!Visited.insert(IndDest).second) 15306c3fb27SDimitry Andric continue; 15406c3fb27SDimitry Andric Builder.SetInsertPoint(&*IndDest->begin()); 15506c3fb27SDimitry Andric CallInst *Intrinsic = Builder.CreateIntrinsic( 15606c3fb27SDimitry Andric CBR->getType(), Intrinsic::callbr_landingpad, {CBR}); 15706c3fb27SDimitry Andric SSAUpdate.AddAvailableValue(IndDest, Intrinsic); 15806c3fb27SDimitry Andric UpdateSSA(DT, CBR, Intrinsic, SSAUpdate); 15906c3fb27SDimitry Andric Changed = true; 16006c3fb27SDimitry Andric } 16106c3fb27SDimitry Andric } 16206c3fb27SDimitry Andric return Changed; 16306c3fb27SDimitry Andric } 16406c3fb27SDimitry Andric 16506c3fb27SDimitry Andric static bool IsInSameBasicBlock(const Use &U, const BasicBlock *BB) { 16606c3fb27SDimitry Andric const auto *I = dyn_cast<Instruction>(U.getUser()); 16706c3fb27SDimitry Andric return I && I->getParent() == BB; 16806c3fb27SDimitry Andric } 16906c3fb27SDimitry Andric 17006c3fb27SDimitry Andric #ifndef NDEBUG 17106c3fb27SDimitry Andric static void PrintDebugDomInfo(const DominatorTree &DT, const Use &U, 17206c3fb27SDimitry Andric const BasicBlock *BB, bool IsDefaultDest) { 17306c3fb27SDimitry Andric if (!isa<Instruction>(U.getUser())) 17406c3fb27SDimitry Andric return; 17506c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Use: " << *U.getUser() << ", in block " 17606c3fb27SDimitry Andric << cast<Instruction>(U.getUser())->getParent()->getName() 17706c3fb27SDimitry Andric << ", is " << (DT.dominates(BB, U) ? "" : "NOT ") 17806c3fb27SDimitry Andric << "dominated by " << BB->getName() << " (" 17906c3fb27SDimitry Andric << (IsDefaultDest ? "in" : "") << "direct)\n"); 18006c3fb27SDimitry Andric } 18106c3fb27SDimitry Andric #endif 18206c3fb27SDimitry Andric 183*5f757f3fSDimitry Andric void UpdateSSA(DominatorTree &DT, CallBrInst *CBR, CallInst *Intrinsic, 184*5f757f3fSDimitry Andric SSAUpdater &SSAUpdate) { 18506c3fb27SDimitry Andric 18606c3fb27SDimitry Andric SmallPtrSet<Use *, 4> Visited; 18706c3fb27SDimitry Andric BasicBlock *DefaultDest = CBR->getDefaultDest(); 18806c3fb27SDimitry Andric BasicBlock *LandingPad = Intrinsic->getParent(); 18906c3fb27SDimitry Andric 19006c3fb27SDimitry Andric SmallVector<Use *, 4> Uses(make_pointer_range(CBR->uses())); 19106c3fb27SDimitry Andric for (Use *U : Uses) { 19206c3fb27SDimitry Andric if (!Visited.insert(U).second) 19306c3fb27SDimitry Andric continue; 19406c3fb27SDimitry Andric 19506c3fb27SDimitry Andric #ifndef NDEBUG 19606c3fb27SDimitry Andric PrintDebugDomInfo(DT, *U, LandingPad, /*IsDefaultDest*/ false); 19706c3fb27SDimitry Andric PrintDebugDomInfo(DT, *U, DefaultDest, /*IsDefaultDest*/ true); 19806c3fb27SDimitry Andric #endif 19906c3fb27SDimitry Andric 20006c3fb27SDimitry Andric // Don't rewrite the use in the newly inserted intrinsic. 20106c3fb27SDimitry Andric if (const auto *II = dyn_cast<IntrinsicInst>(U->getUser())) 20206c3fb27SDimitry Andric if (II->getIntrinsicID() == Intrinsic::callbr_landingpad) 20306c3fb27SDimitry Andric continue; 20406c3fb27SDimitry Andric 20506c3fb27SDimitry Andric // If the Use is in the same BasicBlock as the Intrinsic call, replace 20606c3fb27SDimitry Andric // the Use with the value of the Intrinsic call. 20706c3fb27SDimitry Andric if (IsInSameBasicBlock(*U, LandingPad)) { 20806c3fb27SDimitry Andric U->set(Intrinsic); 20906c3fb27SDimitry Andric continue; 21006c3fb27SDimitry Andric } 21106c3fb27SDimitry Andric 21206c3fb27SDimitry Andric // If the Use is dominated by the default dest, do not touch it. 21306c3fb27SDimitry Andric if (DT.dominates(DefaultDest, *U)) 21406c3fb27SDimitry Andric continue; 21506c3fb27SDimitry Andric 21606c3fb27SDimitry Andric SSAUpdate.RewriteUse(*U); 21706c3fb27SDimitry Andric } 21806c3fb27SDimitry Andric } 21906c3fb27SDimitry Andric 22006c3fb27SDimitry Andric bool CallBrPrepare::runOnFunction(Function &Fn) { 22106c3fb27SDimitry Andric bool Changed = false; 22206c3fb27SDimitry Andric SmallVector<CallBrInst *, 2> CBRs = FindCallBrs(Fn); 22306c3fb27SDimitry Andric 22406c3fb27SDimitry Andric if (CBRs.empty()) 22506c3fb27SDimitry Andric return Changed; 22606c3fb27SDimitry Andric 22706c3fb27SDimitry Andric // It's highly likely that most programs do not contain CallBrInsts. Follow a 22806c3fb27SDimitry Andric // similar pattern from SafeStackLegacyPass::runOnFunction to reuse previous 22906c3fb27SDimitry Andric // domtree analysis if available, otherwise compute it lazily. This avoids 23006c3fb27SDimitry Andric // forcing Dominator Tree Construction at -O0 for programs that likely do not 23106c3fb27SDimitry Andric // contain CallBrInsts. It does pessimize programs with callbr at higher 23206c3fb27SDimitry Andric // optimization levels, as the DominatorTree created here is not reused by 23306c3fb27SDimitry Andric // subsequent passes. 23406c3fb27SDimitry Andric DominatorTree *DT; 23506c3fb27SDimitry Andric std::optional<DominatorTree> LazilyComputedDomTree; 23606c3fb27SDimitry Andric if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>()) 23706c3fb27SDimitry Andric DT = &DTWP->getDomTree(); 23806c3fb27SDimitry Andric else { 23906c3fb27SDimitry Andric LazilyComputedDomTree.emplace(Fn); 24006c3fb27SDimitry Andric DT = &*LazilyComputedDomTree; 24106c3fb27SDimitry Andric } 24206c3fb27SDimitry Andric 24306c3fb27SDimitry Andric if (SplitCriticalEdges(CBRs, *DT)) 24406c3fb27SDimitry Andric Changed = true; 24506c3fb27SDimitry Andric 24606c3fb27SDimitry Andric if (InsertIntrinsicCalls(CBRs, *DT)) 24706c3fb27SDimitry Andric Changed = true; 24806c3fb27SDimitry Andric 24906c3fb27SDimitry Andric return Changed; 25006c3fb27SDimitry Andric } 251