[FunctionAttrs] Extract a helper function for the core logic used to
[oota-llvm.git] / lib / CodeGen / FuncletLayout.cpp
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/CodeGen/MachineBasicBlock.h"
16 #include "llvm/CodeGen/MachineFunction.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/CodeGen/MachineModuleInfo.h"
19 using namespace llvm;
20
21 #define DEBUG_TYPE "funclet-layout"
22
23 namespace {
24 class FuncletLayout : public MachineFunctionPass {
25 public:
26   static char ID; // Pass identification, replacement for typeid
27   FuncletLayout() : MachineFunctionPass(ID) {
28     initializeFuncletLayoutPass(*PassRegistry::getPassRegistry());
29   }
30
31   bool runOnMachineFunction(MachineFunction &F) override;
32 };
33 }
34
35 static void
36 collectFuncletMembers(DenseMap<MachineBasicBlock *, int> &FuncletMembership,
37                       int Funclet, MachineBasicBlock *MBB) {
38   // Don't revisit blocks.
39   if (FuncletMembership.count(MBB) > 0)
40     return;
41
42   // Add this MBB to our funclet.
43   FuncletMembership[MBB] = Funclet;
44
45   bool IsReturn = false;
46   int NumTerminators = 0;
47   for (MachineInstr &MI : MBB->terminators()) {
48     IsReturn |= MI.isReturn();
49     ++NumTerminators;
50   }
51   assert((!IsReturn || NumTerminators == 1) &&
52          "Expected only one terminator when a return is present!");
53
54   // Returns are boundaries where funclet transfer can occur, don't follow
55   // successors.
56   if (IsReturn)
57     return;
58
59   for (MachineBasicBlock *SMBB : MBB->successors())
60     if (!SMBB->isEHPad())
61       collectFuncletMembers(FuncletMembership, Funclet, SMBB);
62 }
63
64 char FuncletLayout::ID = 0;
65 char &llvm::FuncletLayoutID = FuncletLayout::ID;
66 INITIALIZE_PASS(FuncletLayout, "funclet-layout",
67                 "Contiguously Lay Out Funclets", false, false)
68
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())
72     return false;
73
74   SmallVector<MachineBasicBlock *, 16> FuncletBlocks;
75   for (MachineBasicBlock &MBB : F)
76     if (MBB.isEHFuncletEntry())
77       FuncletBlocks.push_back(&MBB);
78
79   // We don't have anything to do if there aren't any EH pads.
80   if (FuncletBlocks.empty())
81     return false;
82
83   DenseMap<MachineBasicBlock *, int> FuncletMembership;
84   for (MachineBasicBlock *MBB : FuncletBlocks)
85     collectFuncletMembers(FuncletMembership, MBB->getNumber(), MBB);
86
87   F.sort([&](MachineBasicBlock &x, MachineBasicBlock &y) {
88     return FuncletMembership[&x] < FuncletMembership[&y];
89   });
90
91   // Conservatively assume we changed something.
92   return true;
93 }