1 //===-- FuncletLayout.cpp - Contiguously lay out funclets -----------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements basic block placement transformations which result in 11 // funclets being contiguous. 12 // 13 //===----------------------------------------------------------------------===// 14 #include "llvm/CodeGen/Passes.h" 15 #include "llvm/ADT/MapVector.h" 16 #include "llvm/CodeGen/MachineBasicBlock.h" 17 #include "llvm/CodeGen/MachineFunction.h" 18 #include "llvm/CodeGen/MachineFunctionPass.h" 19 #include "llvm/CodeGen/MachineModuleInfo.h" 20 using namespace llvm; 21 22 #define DEBUG_TYPE "funclet-layout" 23 24 namespace { 25 class FuncletLayout : public MachineFunctionPass { 26 public: 27 static char ID; // Pass identification, replacement for typeid 28 FuncletLayout() : MachineFunctionPass(ID) { 29 initializeFuncletLayoutPass(*PassRegistry::getPassRegistry()); 30 } 31 32 bool runOnMachineFunction(MachineFunction &F) override; 33 }; 34 } 35 36 static void 37 collectFuncletMembers(MapVector<MachineBasicBlock *, int> &FuncletMembership, 38 int Funclet, MachineBasicBlock *MBB) { 39 // Don't revisit blocks. 40 if (FuncletMembership.count(MBB) > 0) 41 return; 42 43 // Add this MBB to our funclet. 44 FuncletMembership[MBB] = Funclet; 45 46 bool IsReturn = false; 47 int NumTerminators = 0; 48 for (MachineInstr &MI : MBB->terminators()) { 49 IsReturn |= MI.isReturn(); 50 ++NumTerminators; 51 } 52 assert((!IsReturn || NumTerminators == 1) && 53 "Expected only one terminator when a return is present!"); 54 55 // Returns are boundaries where funclet transfer can occur, don't follow 56 // successors. 57 if (IsReturn) 58 return; 59 60 for (MachineBasicBlock *SMBB : MBB->successors()) 61 if (!SMBB->isEHPad()) 62 collectFuncletMembers(FuncletMembership, Funclet, SMBB); 63 } 64 65 char FuncletLayout::ID = 0; 66 char &llvm::FuncletLayoutID = FuncletLayout::ID; 67 INITIALIZE_PASS(FuncletLayout, "funclet-layout", 68 "Contiguously Lay Out Funclets", false, false) 69 70 bool FuncletLayout::runOnMachineFunction(MachineFunction &F) { 71 // We don't have anything to do if there aren't any EH pads. 72 if (!F.getMMI().hasEHFunclets()) 73 return false; 74 75 SmallVector<MachineBasicBlock *, 16> FuncletBlocks; 76 for (MachineBasicBlock &MBB : F) 77 if (MBB.isEHFuncletEntry()) 78 FuncletBlocks.push_back(&MBB); 79 80 // We don't have anything to do if there aren't any EH pads. 81 if (FuncletBlocks.empty()) 82 return false; 83 84 MapVector<MachineBasicBlock *, int> FuncletMembership; 85 for (MachineBasicBlock *MBB : FuncletBlocks) 86 collectFuncletMembers(FuncletMembership, MBB->getNumber(), MBB); 87 88 for (std::pair<llvm::MachineBasicBlock *, int> &FuncletMember : 89 FuncletMembership) { 90 // Move this block to the end of the function. 91 MachineBasicBlock *MBB = FuncletMember.first; 92 MBB->moveAfter(--F.end()); 93 } 94 95 // Conservatively assume we changed something. 96 return true; 97 } 98