1e8d8bef9SDimitry Andric //===-- BasicBlockSections.cpp ---=========--------------------------------===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric // 9e8d8bef9SDimitry Andric // BasicBlockSections implementation. 10e8d8bef9SDimitry Andric // 11e8d8bef9SDimitry Andric // The purpose of this pass is to assign sections to basic blocks when 12e8d8bef9SDimitry Andric // -fbasic-block-sections= option is used. Further, with profile information 13e8d8bef9SDimitry Andric // only the subset of basic blocks with profiles are placed in separate sections 14e8d8bef9SDimitry Andric // and the rest are grouped in a cold section. The exception handling blocks are 15e8d8bef9SDimitry Andric // treated specially to ensure they are all in one seciton. 16e8d8bef9SDimitry Andric // 17e8d8bef9SDimitry Andric // Basic Block Sections 18e8d8bef9SDimitry Andric // ==================== 19e8d8bef9SDimitry Andric // 20e8d8bef9SDimitry Andric // With option, -fbasic-block-sections=list, every function may be split into 21e8d8bef9SDimitry Andric // clusters of basic blocks. Every cluster will be emitted into a separate 22e8d8bef9SDimitry Andric // section with its basic blocks sequenced in the given order. To get the 23e8d8bef9SDimitry Andric // optimized performance, the clusters must form an optimal BB layout for the 24349cc55cSDimitry Andric // function. We insert a symbol at the beginning of every cluster's section to 25349cc55cSDimitry Andric // allow the linker to reorder the sections in any arbitrary sequence. A global 26349cc55cSDimitry Andric // order of these sections would encapsulate the function layout. 27349cc55cSDimitry Andric // For example, consider the following clusters for a function foo (consisting 28349cc55cSDimitry Andric // of 6 basic blocks 0, 1, ..., 5). 29349cc55cSDimitry Andric // 30349cc55cSDimitry Andric // 0 2 31349cc55cSDimitry Andric // 1 3 5 32349cc55cSDimitry Andric // 33349cc55cSDimitry Andric // * Basic blocks 0 and 2 are placed in one section with symbol `foo` 34349cc55cSDimitry Andric // referencing the beginning of this section. 35349cc55cSDimitry Andric // * Basic blocks 1, 3, 5 are placed in a separate section. A new symbol 36349cc55cSDimitry Andric // `foo.__part.1` will reference the beginning of this section. 37349cc55cSDimitry Andric // * Basic block 4 (note that it is not referenced in the list) is placed in 38349cc55cSDimitry Andric // one section, and a new symbol `foo.cold` will point to it. 39e8d8bef9SDimitry Andric // 40e8d8bef9SDimitry Andric // There are a couple of challenges to be addressed: 41e8d8bef9SDimitry Andric // 42e8d8bef9SDimitry Andric // 1. The last basic block of every cluster should not have any implicit 43e8d8bef9SDimitry Andric // fallthrough to its next basic block, as it can be reordered by the linker. 44e8d8bef9SDimitry Andric // The compiler should make these fallthroughs explicit by adding 45e8d8bef9SDimitry Andric // unconditional jumps.. 46e8d8bef9SDimitry Andric // 47e8d8bef9SDimitry Andric // 2. All inter-cluster branch targets would now need to be resolved by the 48e8d8bef9SDimitry Andric // linker as they cannot be calculated during compile time. This is done 49e8d8bef9SDimitry Andric // using static relocations. Further, the compiler tries to use short branch 50e8d8bef9SDimitry Andric // instructions on some ISAs for small branch offsets. This is not possible 51e8d8bef9SDimitry Andric // for inter-cluster branches as the offset is not determined at compile 52e8d8bef9SDimitry Andric // time, and therefore, long branch instructions have to be used for those. 53e8d8bef9SDimitry Andric // 54e8d8bef9SDimitry Andric // 3. Debug Information (DebugInfo) and Call Frame Information (CFI) emission 55e8d8bef9SDimitry Andric // needs special handling with basic block sections. DebugInfo needs to be 56e8d8bef9SDimitry Andric // emitted with more relocations as basic block sections can break a 57e8d8bef9SDimitry Andric // function into potentially several disjoint pieces, and CFI needs to be 58e8d8bef9SDimitry Andric // emitted per cluster. This also bloats the object file and binary sizes. 59e8d8bef9SDimitry Andric // 60*0fca6ea1SDimitry Andric // Basic Block Address Map 61e8d8bef9SDimitry Andric // ================== 62e8d8bef9SDimitry Andric // 63*0fca6ea1SDimitry Andric // With -fbasic-block-address-map, we emit the offsets of BB addresses of 64e8d8bef9SDimitry Andric // every function into the .llvm_bb_addr_map section. Along with the function 65e8d8bef9SDimitry Andric // symbols, this allows for mapping of virtual addresses in PMU profiles back to 66e8d8bef9SDimitry Andric // the corresponding basic blocks. This logic is implemented in AsmPrinter. This 67e8d8bef9SDimitry Andric // pass only assigns the BBSectionType of every function to ``labels``. 68e8d8bef9SDimitry Andric // 69e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 70e8d8bef9SDimitry Andric 71e8d8bef9SDimitry Andric #include "llvm/ADT/SmallVector.h" 72e8d8bef9SDimitry Andric #include "llvm/ADT/StringRef.h" 73e8d8bef9SDimitry Andric #include "llvm/CodeGen/BasicBlockSectionUtils.h" 74bdd1243dSDimitry Andric #include "llvm/CodeGen/BasicBlockSectionsProfileReader.h" 75e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 76e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 77e8d8bef9SDimitry Andric #include "llvm/CodeGen/Passes.h" 78e8d8bef9SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 79e8d8bef9SDimitry Andric #include "llvm/InitializePasses.h" 80e8d8bef9SDimitry Andric #include "llvm/Target/TargetMachine.h" 81bdd1243dSDimitry Andric #include <optional> 82e8d8bef9SDimitry Andric 83e8d8bef9SDimitry Andric using namespace llvm; 84e8d8bef9SDimitry Andric 85e8d8bef9SDimitry Andric // Placing the cold clusters in a separate section mitigates against poor 86e8d8bef9SDimitry Andric // profiles and allows optimizations such as hugepage mapping to be applied at a 87e8d8bef9SDimitry Andric // section granularity. Defaults to ".text.split." which is recognized by lld 88e8d8bef9SDimitry Andric // via the `-z keep-text-section-prefix` flag. 89e8d8bef9SDimitry Andric cl::opt<std::string> llvm::BBSectionsColdTextPrefix( 90e8d8bef9SDimitry Andric "bbsections-cold-text-prefix", 91e8d8bef9SDimitry Andric cl::desc("The text prefix to use for cold basic block clusters"), 92e8d8bef9SDimitry Andric cl::init(".text.split."), cl::Hidden); 93e8d8bef9SDimitry Andric 9406c3fb27SDimitry Andric static cl::opt<bool> BBSectionsDetectSourceDrift( 95fe6060f1SDimitry Andric "bbsections-detect-source-drift", 96fe6060f1SDimitry Andric cl::desc("This checks if there is a fdo instr. profile hash " 97fe6060f1SDimitry Andric "mismatch for this function"), 98fe6060f1SDimitry Andric cl::init(true), cl::Hidden); 99fe6060f1SDimitry Andric 100e8d8bef9SDimitry Andric namespace { 101e8d8bef9SDimitry Andric 102e8d8bef9SDimitry Andric class BasicBlockSections : public MachineFunctionPass { 103e8d8bef9SDimitry Andric public: 104e8d8bef9SDimitry Andric static char ID; 105e8d8bef9SDimitry Andric 1061db9f3b2SDimitry Andric BasicBlockSectionsProfileReaderWrapperPass *BBSectionsProfileReader = nullptr; 107e8d8bef9SDimitry Andric 108e8d8bef9SDimitry Andric BasicBlockSections() : MachineFunctionPass(ID) { 109e8d8bef9SDimitry Andric initializeBasicBlockSectionsPass(*PassRegistry::getPassRegistry()); 110e8d8bef9SDimitry Andric } 111e8d8bef9SDimitry Andric 112e8d8bef9SDimitry Andric StringRef getPassName() const override { 113e8d8bef9SDimitry Andric return "Basic Block Sections Analysis"; 114e8d8bef9SDimitry Andric } 115e8d8bef9SDimitry Andric 116e8d8bef9SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 117e8d8bef9SDimitry Andric 118e8d8bef9SDimitry Andric /// Identify basic blocks that need separate sections and prepare to emit them 119e8d8bef9SDimitry Andric /// accordingly. 120e8d8bef9SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 121*0fca6ea1SDimitry Andric 122*0fca6ea1SDimitry Andric private: 123*0fca6ea1SDimitry Andric bool handleBBSections(MachineFunction &MF); 124*0fca6ea1SDimitry Andric bool handleBBAddrMap(MachineFunction &MF); 125e8d8bef9SDimitry Andric }; 126e8d8bef9SDimitry Andric 127e8d8bef9SDimitry Andric } // end anonymous namespace 128e8d8bef9SDimitry Andric 129e8d8bef9SDimitry Andric char BasicBlockSections::ID = 0; 13006c3fb27SDimitry Andric INITIALIZE_PASS_BEGIN( 13106c3fb27SDimitry Andric BasicBlockSections, "bbsections-prepare", 13206c3fb27SDimitry Andric "Prepares for basic block sections, by splitting functions " 13306c3fb27SDimitry Andric "into clusters of basic blocks.", 13406c3fb27SDimitry Andric false, false) 1351db9f3b2SDimitry Andric INITIALIZE_PASS_DEPENDENCY(BasicBlockSectionsProfileReaderWrapperPass) 13606c3fb27SDimitry Andric INITIALIZE_PASS_END(BasicBlockSections, "bbsections-prepare", 137e8d8bef9SDimitry Andric "Prepares for basic block sections, by splitting functions " 138e8d8bef9SDimitry Andric "into clusters of basic blocks.", 139e8d8bef9SDimitry Andric false, false) 140e8d8bef9SDimitry Andric 141e8d8bef9SDimitry Andric // This function updates and optimizes the branching instructions of every basic 142e8d8bef9SDimitry Andric // block in a given function to account for changes in the layout. 143bdd1243dSDimitry Andric static void 144bdd1243dSDimitry Andric updateBranches(MachineFunction &MF, 145bdd1243dSDimitry Andric const SmallVector<MachineBasicBlock *> &PreLayoutFallThroughs) { 146e8d8bef9SDimitry Andric const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 147e8d8bef9SDimitry Andric SmallVector<MachineOperand, 4> Cond; 148e8d8bef9SDimitry Andric for (auto &MBB : MF) { 149e8d8bef9SDimitry Andric auto NextMBBI = std::next(MBB.getIterator()); 150e8d8bef9SDimitry Andric auto *FTMBB = PreLayoutFallThroughs[MBB.getNumber()]; 151e8d8bef9SDimitry Andric // If this block had a fallthrough before we need an explicit unconditional 152e8d8bef9SDimitry Andric // branch to that block if either 153e8d8bef9SDimitry Andric // 1- the block ends a section, which means its next block may be 154e8d8bef9SDimitry Andric // reorderd by the linker, or 155e8d8bef9SDimitry Andric // 2- the fallthrough block is not adjacent to the block in the new 156e8d8bef9SDimitry Andric // order. 157e8d8bef9SDimitry Andric if (FTMBB && (MBB.isEndSection() || &*NextMBBI != FTMBB)) 158e8d8bef9SDimitry Andric TII->insertUnconditionalBranch(MBB, FTMBB, MBB.findBranchDebugLoc()); 159e8d8bef9SDimitry Andric 160e8d8bef9SDimitry Andric // We do not optimize branches for machine basic blocks ending sections, as 161e8d8bef9SDimitry Andric // their adjacent block might be reordered by the linker. 162e8d8bef9SDimitry Andric if (MBB.isEndSection()) 163e8d8bef9SDimitry Andric continue; 164e8d8bef9SDimitry Andric 165e8d8bef9SDimitry Andric // It might be possible to optimize branches by flipping the branch 166e8d8bef9SDimitry Andric // condition. 167e8d8bef9SDimitry Andric Cond.clear(); 168e8d8bef9SDimitry Andric MachineBasicBlock *TBB = nullptr, *FBB = nullptr; // For analyzeBranch. 169e8d8bef9SDimitry Andric if (TII->analyzeBranch(MBB, TBB, FBB, Cond)) 170e8d8bef9SDimitry Andric continue; 171e8d8bef9SDimitry Andric MBB.updateTerminator(FTMBB); 172e8d8bef9SDimitry Andric } 173e8d8bef9SDimitry Andric } 174e8d8bef9SDimitry Andric 175e8d8bef9SDimitry Andric // This function sorts basic blocks according to the cluster's information. 176e8d8bef9SDimitry Andric // All explicitly specified clusters of basic blocks will be ordered 177e8d8bef9SDimitry Andric // accordingly. All non-specified BBs go into a separate "Cold" section. 178e8d8bef9SDimitry Andric // Additionally, if exception handling landing pads end up in more than one 179e8d8bef9SDimitry Andric // clusters, they are moved into a single "Exception" section. Eventually, 180e8d8bef9SDimitry Andric // clusters are ordered in increasing order of their IDs, with the "Exception" 181e8d8bef9SDimitry Andric // and "Cold" succeeding all other clusters. 1825f757f3fSDimitry Andric // FuncClusterInfo represents the cluster information for basic blocks. It 183bdd1243dSDimitry Andric // maps from BBID of basic blocks to their cluster information. If this is 184bdd1243dSDimitry Andric // empty, it means unique sections for all basic blocks in the function. 185e8d8bef9SDimitry Andric static void 186e8d8bef9SDimitry Andric assignSections(MachineFunction &MF, 1875f757f3fSDimitry Andric const DenseMap<UniqueBBID, BBClusterInfo> &FuncClusterInfo) { 188e8d8bef9SDimitry Andric assert(MF.hasBBSections() && "BB Sections is not set for function."); 189e8d8bef9SDimitry Andric // This variable stores the section ID of the cluster containing eh_pads (if 190e8d8bef9SDimitry Andric // all eh_pads are one cluster). If more than one cluster contain eh_pads, we 191e8d8bef9SDimitry Andric // set it equal to ExceptionSectionID. 192bdd1243dSDimitry Andric std::optional<MBBSectionID> EHPadsSectionID; 193e8d8bef9SDimitry Andric 194e8d8bef9SDimitry Andric for (auto &MBB : MF) { 195e8d8bef9SDimitry Andric // With the 'all' option, every basic block is placed in a unique section. 196e8d8bef9SDimitry Andric // With the 'list' option, every basic block is placed in a section 197e8d8bef9SDimitry Andric // associated with its cluster, unless we want individual unique sections 1985f757f3fSDimitry Andric // for every basic block in this function (if FuncClusterInfo is empty). 199e8d8bef9SDimitry Andric if (MF.getTarget().getBBSectionsType() == llvm::BasicBlockSection::All || 2005f757f3fSDimitry Andric FuncClusterInfo.empty()) { 201e8d8bef9SDimitry Andric // If unique sections are desired for all basic blocks of the function, we 202bdd1243dSDimitry Andric // set every basic block's section ID equal to its original position in 203bdd1243dSDimitry Andric // the layout (which is equal to its number). This ensures that basic 204bdd1243dSDimitry Andric // blocks are ordered canonically. 205bdd1243dSDimitry Andric MBB.setSectionID(MBB.getNumber()); 206bdd1243dSDimitry Andric } else { 2075f757f3fSDimitry Andric auto I = FuncClusterInfo.find(*MBB.getBBID()); 2085f757f3fSDimitry Andric if (I != FuncClusterInfo.end()) { 209bdd1243dSDimitry Andric MBB.setSectionID(I->second.ClusterID); 210bdd1243dSDimitry Andric } else { 211*0fca6ea1SDimitry Andric const TargetInstrInfo &TII = 212*0fca6ea1SDimitry Andric *MBB.getParent()->getSubtarget().getInstrInfo(); 213*0fca6ea1SDimitry Andric 214*0fca6ea1SDimitry Andric if (TII.isMBBSafeToSplitToCold(MBB)) { 215e8d8bef9SDimitry Andric // BB goes into the special cold section if it is not specified in the 216e8d8bef9SDimitry Andric // cluster info map. 217e8d8bef9SDimitry Andric MBB.setSectionID(MBBSectionID::ColdSectionID); 218e8d8bef9SDimitry Andric } 219bdd1243dSDimitry Andric } 220*0fca6ea1SDimitry Andric } 221e8d8bef9SDimitry Andric 222e8d8bef9SDimitry Andric if (MBB.isEHPad() && EHPadsSectionID != MBB.getSectionID() && 223e8d8bef9SDimitry Andric EHPadsSectionID != MBBSectionID::ExceptionSectionID) { 224e8d8bef9SDimitry Andric // If we already have one cluster containing eh_pads, this must be updated 225e8d8bef9SDimitry Andric // to ExceptionSectionID. Otherwise, we set it equal to the current 226e8d8bef9SDimitry Andric // section ID. 22781ad6265SDimitry Andric EHPadsSectionID = EHPadsSectionID ? MBBSectionID::ExceptionSectionID 228e8d8bef9SDimitry Andric : MBB.getSectionID(); 229e8d8bef9SDimitry Andric } 230e8d8bef9SDimitry Andric } 231e8d8bef9SDimitry Andric 232e8d8bef9SDimitry Andric // If EHPads are in more than one section, this places all of them in the 233e8d8bef9SDimitry Andric // special exception section. 234e8d8bef9SDimitry Andric if (EHPadsSectionID == MBBSectionID::ExceptionSectionID) 235e8d8bef9SDimitry Andric for (auto &MBB : MF) 236e8d8bef9SDimitry Andric if (MBB.isEHPad()) 23781ad6265SDimitry Andric MBB.setSectionID(*EHPadsSectionID); 238e8d8bef9SDimitry Andric } 239e8d8bef9SDimitry Andric 240e8d8bef9SDimitry Andric void llvm::sortBasicBlocksAndUpdateBranches( 241e8d8bef9SDimitry Andric MachineFunction &MF, MachineBasicBlockComparator MBBCmp) { 242bdd1243dSDimitry Andric [[maybe_unused]] const MachineBasicBlock *EntryBlock = &MF.front(); 243bdd1243dSDimitry Andric SmallVector<MachineBasicBlock *> PreLayoutFallThroughs(MF.getNumBlockIDs()); 244e8d8bef9SDimitry Andric for (auto &MBB : MF) 2455f757f3fSDimitry Andric PreLayoutFallThroughs[MBB.getNumber()] = 2465f757f3fSDimitry Andric MBB.getFallThrough(/*JumpToFallThrough=*/false); 247e8d8bef9SDimitry Andric 248e8d8bef9SDimitry Andric MF.sort(MBBCmp); 249bdd1243dSDimitry Andric assert(&MF.front() == EntryBlock && 250bdd1243dSDimitry Andric "Entry block should not be displaced by basic block sections"); 251e8d8bef9SDimitry Andric 252e8d8bef9SDimitry Andric // Set IsBeginSection and IsEndSection according to the assigned section IDs. 253e8d8bef9SDimitry Andric MF.assignBeginEndSections(); 254e8d8bef9SDimitry Andric 255e8d8bef9SDimitry Andric // After reordering basic blocks, we must update basic block branches to 256e8d8bef9SDimitry Andric // insert explicit fallthrough branches when required and optimize branches 257e8d8bef9SDimitry Andric // when possible. 258e8d8bef9SDimitry Andric updateBranches(MF, PreLayoutFallThroughs); 259e8d8bef9SDimitry Andric } 260e8d8bef9SDimitry Andric 261e8d8bef9SDimitry Andric // If the exception section begins with a landing pad, that landing pad will 262e8d8bef9SDimitry Andric // assume a zero offset (relative to @LPStart) in the LSDA. However, a value of 263e8d8bef9SDimitry Andric // zero implies "no landing pad." This function inserts a NOP just before the EH 264fcaf7f86SDimitry Andric // pad label to ensure a nonzero offset. 265fcaf7f86SDimitry Andric void llvm::avoidZeroOffsetLandingPad(MachineFunction &MF) { 266e8d8bef9SDimitry Andric for (auto &MBB : MF) { 267e8d8bef9SDimitry Andric if (MBB.isBeginSection() && MBB.isEHPad()) { 268e8d8bef9SDimitry Andric MachineBasicBlock::iterator MI = MBB.begin(); 269e8d8bef9SDimitry Andric while (!MI->isEHLabel()) 270e8d8bef9SDimitry Andric ++MI; 2715f757f3fSDimitry Andric MF.getSubtarget().getInstrInfo()->insertNoop(MBB, MI); 272e8d8bef9SDimitry Andric } 273e8d8bef9SDimitry Andric } 274e8d8bef9SDimitry Andric } 275e8d8bef9SDimitry Andric 2765f757f3fSDimitry Andric bool llvm::hasInstrProfHashMismatch(MachineFunction &MF) { 277fe6060f1SDimitry Andric if (!BBSectionsDetectSourceDrift) 278fe6060f1SDimitry Andric return false; 279fe6060f1SDimitry Andric 280fe6060f1SDimitry Andric const char MetadataName[] = "instr_prof_hash_mismatch"; 281fe6060f1SDimitry Andric auto *Existing = MF.getFunction().getMetadata(LLVMContext::MD_annotation); 282fe6060f1SDimitry Andric if (Existing) { 283fe6060f1SDimitry Andric MDTuple *Tuple = cast<MDTuple>(Existing); 284fcaf7f86SDimitry Andric for (const auto &N : Tuple->operands()) 28506c3fb27SDimitry Andric if (N.equalsStr(MetadataName)) 286fe6060f1SDimitry Andric return true; 287fe6060f1SDimitry Andric } 288fe6060f1SDimitry Andric 289fe6060f1SDimitry Andric return false; 290fe6060f1SDimitry Andric } 291fe6060f1SDimitry Andric 292*0fca6ea1SDimitry Andric // Identify, arrange, and modify basic blocks which need separate sections 293*0fca6ea1SDimitry Andric // according to the specification provided by the -fbasic-block-sections flag. 294*0fca6ea1SDimitry Andric bool BasicBlockSections::handleBBSections(MachineFunction &MF) { 295e8d8bef9SDimitry Andric auto BBSectionsType = MF.getTarget().getBBSectionsType(); 296*0fca6ea1SDimitry Andric if (BBSectionsType == BasicBlockSection::None) 297*0fca6ea1SDimitry Andric return false; 298fe6060f1SDimitry Andric 299fe6060f1SDimitry Andric // Check for source drift. If the source has changed since the profiles 300fe6060f1SDimitry Andric // were obtained, optimizing basic blocks might be sub-optimal. 301fe6060f1SDimitry Andric // This only applies to BasicBlockSection::List as it creates 302fe6060f1SDimitry Andric // clusters of basic blocks using basic block ids. Source drift can 303fe6060f1SDimitry Andric // invalidate these groupings leading to sub-optimal code generation with 304fe6060f1SDimitry Andric // regards to performance. 305fe6060f1SDimitry Andric if (BBSectionsType == BasicBlockSection::List && 306fe6060f1SDimitry Andric hasInstrProfHashMismatch(MF)) 3075f757f3fSDimitry Andric return false; 3085f757f3fSDimitry Andric // Renumber blocks before sorting them. This is useful for accessing the 3095f757f3fSDimitry Andric // original layout positions and finding the original fallthroughs. 310e8d8bef9SDimitry Andric MF.RenumberBlocks(); 311e8d8bef9SDimitry Andric 312e8d8bef9SDimitry Andric if (BBSectionsType == BasicBlockSection::Labels) { 313e8d8bef9SDimitry Andric MF.setBBSectionsType(BBSectionsType); 314*0fca6ea1SDimitry Andric return true; 315e8d8bef9SDimitry Andric } 316e8d8bef9SDimitry Andric 3175f757f3fSDimitry Andric DenseMap<UniqueBBID, BBClusterInfo> FuncClusterInfo; 3185f757f3fSDimitry Andric if (BBSectionsType == BasicBlockSection::List) { 3195f757f3fSDimitry Andric auto [HasProfile, ClusterInfo] = 3201db9f3b2SDimitry Andric getAnalysis<BasicBlockSectionsProfileReaderWrapperPass>() 3215f757f3fSDimitry Andric .getClusterInfoForFunction(MF.getName()); 3225f757f3fSDimitry Andric if (!HasProfile) 3235f757f3fSDimitry Andric return false; 3245f757f3fSDimitry Andric for (auto &BBClusterInfo : ClusterInfo) { 3255f757f3fSDimitry Andric FuncClusterInfo.try_emplace(BBClusterInfo.BBID, BBClusterInfo); 3265f757f3fSDimitry Andric } 3275f757f3fSDimitry Andric } 32881ad6265SDimitry Andric 329e8d8bef9SDimitry Andric MF.setBBSectionsType(BBSectionsType); 3305f757f3fSDimitry Andric assignSections(MF, FuncClusterInfo); 331e8d8bef9SDimitry Andric 3327a6dacacSDimitry Andric const MachineBasicBlock &EntryBB = MF.front(); 3337a6dacacSDimitry Andric auto EntryBBSectionID = EntryBB.getSectionID(); 334e8d8bef9SDimitry Andric 335e8d8bef9SDimitry Andric // Helper function for ordering BB sections as follows: 336e8d8bef9SDimitry Andric // * Entry section (section including the entry block). 337e8d8bef9SDimitry Andric // * Regular sections (in increasing order of their Number). 338e8d8bef9SDimitry Andric // ... 339e8d8bef9SDimitry Andric // * Exception section 340e8d8bef9SDimitry Andric // * Cold section 341e8d8bef9SDimitry Andric auto MBBSectionOrder = [EntryBBSectionID](const MBBSectionID &LHS, 342e8d8bef9SDimitry Andric const MBBSectionID &RHS) { 343e8d8bef9SDimitry Andric // We make sure that the section containing the entry block precedes all the 344e8d8bef9SDimitry Andric // other sections. 345e8d8bef9SDimitry Andric if (LHS == EntryBBSectionID || RHS == EntryBBSectionID) 346e8d8bef9SDimitry Andric return LHS == EntryBBSectionID; 347e8d8bef9SDimitry Andric return LHS.Type == RHS.Type ? LHS.Number < RHS.Number : LHS.Type < RHS.Type; 348e8d8bef9SDimitry Andric }; 349e8d8bef9SDimitry Andric 350e8d8bef9SDimitry Andric // We sort all basic blocks to make sure the basic blocks of every cluster are 351e8d8bef9SDimitry Andric // contiguous and ordered accordingly. Furthermore, clusters are ordered in 352e8d8bef9SDimitry Andric // increasing order of their section IDs, with the exception and the 353e8d8bef9SDimitry Andric // cold section placed at the end of the function. 3547a6dacacSDimitry Andric // Also, we force the entry block of the function to be placed at the 3557a6dacacSDimitry Andric // beginning of the function, regardless of the requested order. 356e8d8bef9SDimitry Andric auto Comparator = [&](const MachineBasicBlock &X, 357e8d8bef9SDimitry Andric const MachineBasicBlock &Y) { 358e8d8bef9SDimitry Andric auto XSectionID = X.getSectionID(); 359e8d8bef9SDimitry Andric auto YSectionID = Y.getSectionID(); 360e8d8bef9SDimitry Andric if (XSectionID != YSectionID) 361e8d8bef9SDimitry Andric return MBBSectionOrder(XSectionID, YSectionID); 3627a6dacacSDimitry Andric // Make sure that the entry block is placed at the beginning. 3637a6dacacSDimitry Andric if (&X == &EntryBB || &Y == &EntryBB) 3647a6dacacSDimitry Andric return &X == &EntryBB; 365e8d8bef9SDimitry Andric // If the two basic block are in the same section, the order is decided by 366e8d8bef9SDimitry Andric // their position within the section. 367e8d8bef9SDimitry Andric if (XSectionID.Type == MBBSectionID::SectionType::Default) 3685f757f3fSDimitry Andric return FuncClusterInfo.lookup(*X.getBBID()).PositionInCluster < 3695f757f3fSDimitry Andric FuncClusterInfo.lookup(*Y.getBBID()).PositionInCluster; 370e8d8bef9SDimitry Andric return X.getNumber() < Y.getNumber(); 371e8d8bef9SDimitry Andric }; 372e8d8bef9SDimitry Andric 373e8d8bef9SDimitry Andric sortBasicBlocksAndUpdateBranches(MF, Comparator); 374e8d8bef9SDimitry Andric avoidZeroOffsetLandingPad(MF); 375e8d8bef9SDimitry Andric return true; 376e8d8bef9SDimitry Andric } 377e8d8bef9SDimitry Andric 378*0fca6ea1SDimitry Andric // When the BB address map needs to be generated, this renumbers basic blocks to 379*0fca6ea1SDimitry Andric // make them appear in increasing order of their IDs in the function. This 380*0fca6ea1SDimitry Andric // avoids the need to store basic block IDs in the BB address map section, since 381*0fca6ea1SDimitry Andric // they can be determined implicitly. 382*0fca6ea1SDimitry Andric bool BasicBlockSections::handleBBAddrMap(MachineFunction &MF) { 383*0fca6ea1SDimitry Andric if (MF.getTarget().getBBSectionsType() == BasicBlockSection::Labels) 384*0fca6ea1SDimitry Andric return false; 385*0fca6ea1SDimitry Andric if (!MF.getTarget().Options.BBAddrMap) 386*0fca6ea1SDimitry Andric return false; 387*0fca6ea1SDimitry Andric MF.RenumberBlocks(); 388*0fca6ea1SDimitry Andric return true; 389*0fca6ea1SDimitry Andric } 390*0fca6ea1SDimitry Andric 391*0fca6ea1SDimitry Andric bool BasicBlockSections::runOnMachineFunction(MachineFunction &MF) { 392*0fca6ea1SDimitry Andric // First handle the basic block sections. 393*0fca6ea1SDimitry Andric auto R1 = handleBBSections(MF); 394*0fca6ea1SDimitry Andric // Handle basic block address map after basic block sections are finalized. 395*0fca6ea1SDimitry Andric auto R2 = handleBBAddrMap(MF); 396*0fca6ea1SDimitry Andric return R1 || R2; 397*0fca6ea1SDimitry Andric } 398*0fca6ea1SDimitry Andric 399e8d8bef9SDimitry Andric void BasicBlockSections::getAnalysisUsage(AnalysisUsage &AU) const { 400e8d8bef9SDimitry Andric AU.setPreservesAll(); 4011db9f3b2SDimitry Andric AU.addRequired<BasicBlockSectionsProfileReaderWrapperPass>(); 402e8d8bef9SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 403e8d8bef9SDimitry Andric } 404e8d8bef9SDimitry Andric 40581ad6265SDimitry Andric MachineFunctionPass *llvm::createBasicBlockSectionsPass() { 40681ad6265SDimitry Andric return new BasicBlockSections(); 407e8d8bef9SDimitry Andric } 408