197890230SDavid Majnemer //===-- FuncletLayout.cpp - Contiguously lay out funclets -----------------===//
297890230SDavid Majnemer //
397890230SDavid Majnemer //                     The LLVM Compiler Infrastructure
497890230SDavid Majnemer //
597890230SDavid Majnemer // This file is distributed under the University of Illinois Open Source
697890230SDavid Majnemer // License. See LICENSE.TXT for details.
797890230SDavid Majnemer //
897890230SDavid Majnemer //===----------------------------------------------------------------------===//
997890230SDavid Majnemer //
1097890230SDavid Majnemer // This file implements basic block placement transformations which result in
1197890230SDavid Majnemer // funclets being contiguous.
1297890230SDavid Majnemer //
1397890230SDavid Majnemer //===----------------------------------------------------------------------===//
1497890230SDavid Majnemer #include "llvm/CodeGen/Passes.h"
1597890230SDavid Majnemer #include "llvm/CodeGen/MachineBasicBlock.h"
1697890230SDavid Majnemer #include "llvm/CodeGen/MachineFunction.h"
1797890230SDavid Majnemer #include "llvm/CodeGen/MachineFunctionPass.h"
1897890230SDavid Majnemer #include "llvm/CodeGen/MachineModuleInfo.h"
1997890230SDavid Majnemer using namespace llvm;
2097890230SDavid Majnemer 
2197890230SDavid Majnemer #define DEBUG_TYPE "funclet-layout"
2297890230SDavid Majnemer 
2397890230SDavid Majnemer namespace {
2497890230SDavid Majnemer class FuncletLayout : public MachineFunctionPass {
2597890230SDavid Majnemer public:
2697890230SDavid Majnemer   static char ID; // Pass identification, replacement for typeid
2797890230SDavid Majnemer   FuncletLayout() : MachineFunctionPass(ID) {
2897890230SDavid Majnemer     initializeFuncletLayoutPass(*PassRegistry::getPassRegistry());
2997890230SDavid Majnemer   }
3097890230SDavid Majnemer 
3197890230SDavid Majnemer   bool runOnMachineFunction(MachineFunction &F) override;
3297890230SDavid Majnemer };
3397890230SDavid Majnemer }
3497890230SDavid Majnemer 
3597890230SDavid Majnemer static void
36*9966fe8fSDavid Majnemer collectFuncletMembers(DenseMap<MachineBasicBlock *, int> &FuncletMembership,
3797890230SDavid Majnemer                       int Funclet, MachineBasicBlock *MBB) {
3897890230SDavid Majnemer   // Don't revisit blocks.
3997890230SDavid Majnemer   if (FuncletMembership.count(MBB) > 0)
4097890230SDavid Majnemer     return;
4197890230SDavid Majnemer 
4297890230SDavid Majnemer   // Add this MBB to our funclet.
4397890230SDavid Majnemer   FuncletMembership[MBB] = Funclet;
4497890230SDavid Majnemer 
4597890230SDavid Majnemer   bool IsReturn = false;
4697890230SDavid Majnemer   int NumTerminators = 0;
4797890230SDavid Majnemer   for (MachineInstr &MI : MBB->terminators()) {
4897890230SDavid Majnemer     IsReturn |= MI.isReturn();
4997890230SDavid Majnemer     ++NumTerminators;
5097890230SDavid Majnemer   }
5197890230SDavid Majnemer   assert((!IsReturn || NumTerminators == 1) &&
5297890230SDavid Majnemer          "Expected only one terminator when a return is present!");
5397890230SDavid Majnemer 
5497890230SDavid Majnemer   // Returns are boundaries where funclet transfer can occur, don't follow
5597890230SDavid Majnemer   // successors.
5697890230SDavid Majnemer   if (IsReturn)
5797890230SDavid Majnemer     return;
5897890230SDavid Majnemer 
5997890230SDavid Majnemer   for (MachineBasicBlock *SMBB : MBB->successors())
6097890230SDavid Majnemer     if (!SMBB->isEHPad())
6197890230SDavid Majnemer       collectFuncletMembers(FuncletMembership, Funclet, SMBB);
6297890230SDavid Majnemer }
6397890230SDavid Majnemer 
6497890230SDavid Majnemer char FuncletLayout::ID = 0;
6597890230SDavid Majnemer char &llvm::FuncletLayoutID = FuncletLayout::ID;
6697890230SDavid Majnemer INITIALIZE_PASS(FuncletLayout, "funclet-layout",
6797890230SDavid Majnemer                 "Contiguously Lay Out Funclets", false, false)
6897890230SDavid Majnemer 
6997890230SDavid Majnemer bool FuncletLayout::runOnMachineFunction(MachineFunction &F) {
7097890230SDavid Majnemer   // We don't have anything to do if there aren't any EH pads.
7197890230SDavid Majnemer   if (!F.getMMI().hasEHFunclets())
7297890230SDavid Majnemer     return false;
7397890230SDavid Majnemer 
7497890230SDavid Majnemer   SmallVector<MachineBasicBlock *, 16> FuncletBlocks;
7597890230SDavid Majnemer   for (MachineBasicBlock &MBB : F)
7697890230SDavid Majnemer     if (MBB.isEHFuncletEntry())
7797890230SDavid Majnemer       FuncletBlocks.push_back(&MBB);
7897890230SDavid Majnemer 
7997890230SDavid Majnemer   // We don't have anything to do if there aren't any EH pads.
8097890230SDavid Majnemer   if (FuncletBlocks.empty())
8197890230SDavid Majnemer     return false;
8297890230SDavid Majnemer 
83*9966fe8fSDavid Majnemer   DenseMap<MachineBasicBlock *, int> FuncletMembership;
8497890230SDavid Majnemer   for (MachineBasicBlock *MBB : FuncletBlocks)
8597890230SDavid Majnemer     collectFuncletMembers(FuncletMembership, MBB->getNumber(), MBB);
8697890230SDavid Majnemer 
87*9966fe8fSDavid Majnemer   F.sort([&](MachineBasicBlock &x, MachineBasicBlock &y) {
88*9966fe8fSDavid Majnemer     return FuncletMembership[&x] < FuncletMembership[&y];
89*9966fe8fSDavid Majnemer   });
9097890230SDavid Majnemer 
9197890230SDavid Majnemer   // Conservatively assume we changed something.
9297890230SDavid Majnemer   return true;
9397890230SDavid Majnemer }
94