1 //===-- FuncletLayout.cpp - Contiguously lay out funclets -----------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements basic block placement transformations which result in
11 // funclets being contiguous.
13 //===----------------------------------------------------------------------===//
14 #include "llvm/CodeGen/Passes.h"
15 #include "llvm/CodeGen/MachineBasicBlock.h"
16 #include "llvm/CodeGen/MachineFunction.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/CodeGen/MachineModuleInfo.h"
21 #define DEBUG_TYPE "funclet-layout"
24 class FuncletLayout : public MachineFunctionPass {
26 static char ID; // Pass identification, replacement for typeid
27 FuncletLayout() : MachineFunctionPass(ID) {
28 initializeFuncletLayoutPass(*PassRegistry::getPassRegistry());
31 bool runOnMachineFunction(MachineFunction &F) override;
36 collectFuncletMembers(DenseMap<MachineBasicBlock *, int> &FuncletMembership,
37 int Funclet, MachineBasicBlock *MBB) {
38 // Don't revisit blocks.
39 if (FuncletMembership.count(MBB) > 0)
42 // Add this MBB to our funclet.
43 FuncletMembership[MBB] = Funclet;
45 bool IsReturn = false;
46 int NumTerminators = 0;
47 for (MachineInstr &MI : MBB->terminators()) {
48 IsReturn |= MI.isReturn();
51 assert((!IsReturn || NumTerminators == 1) &&
52 "Expected only one terminator when a return is present!");
54 // Returns are boundaries where funclet transfer can occur, don't follow
59 for (MachineBasicBlock *SMBB : MBB->successors())
61 collectFuncletMembers(FuncletMembership, Funclet, SMBB);
64 char FuncletLayout::ID = 0;
65 char &llvm::FuncletLayoutID = FuncletLayout::ID;
66 INITIALIZE_PASS(FuncletLayout, "funclet-layout",
67 "Contiguously Lay Out Funclets", false, false)
69 bool FuncletLayout::runOnMachineFunction(MachineFunction &F) {
70 // We don't have anything to do if there aren't any EH pads.
71 if (!F.getMMI().hasEHFunclets())
74 SmallVector<MachineBasicBlock *, 16> FuncletBlocks;
75 for (MachineBasicBlock &MBB : F)
76 if (MBB.isEHFuncletEntry())
77 FuncletBlocks.push_back(&MBB);
79 // We don't have anything to do if there aren't any EH pads.
80 if (FuncletBlocks.empty())
83 DenseMap<MachineBasicBlock *, int> FuncletMembership;
84 for (MachineBasicBlock *MBB : FuncletBlocks)
85 collectFuncletMembers(FuncletMembership, MBB->getNumber(), MBB);
87 F.sort([&](MachineBasicBlock &x, MachineBasicBlock &y) {
88 return FuncletMembership[&x] < FuncletMembership[&y];
91 // Conservatively assume we changed something.