blob: 0cda11f53dbbc58d1340503068121ec8eade873a [file] [log] [blame]
David Majnemer97890232015-09-17 20:45:18 +00001//===-- 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"
David Majnemer97890232015-09-17 20:45:18 +000015#include "llvm/CodeGen/MachineBasicBlock.h"
16#include "llvm/CodeGen/MachineFunction.h"
17#include "llvm/CodeGen/MachineFunctionPass.h"
18#include "llvm/CodeGen/MachineModuleInfo.h"
19using namespace llvm;
20
21#define DEBUG_TYPE "funclet-layout"
22
23namespace {
24class FuncletLayout : public MachineFunctionPass {
25public:
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
35static void
David Majnemer9966fe82015-09-18 08:18:07 +000036collectFuncletMembers(DenseMap<MachineBasicBlock *, int> &FuncletMembership,
David Majnemer97890232015-09-17 20:45:18 +000037 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
64char FuncletLayout::ID = 0;
65char &llvm::FuncletLayoutID = FuncletLayout::ID;
66INITIALIZE_PASS(FuncletLayout, "funclet-layout",
67 "Contiguously Lay Out Funclets", false, false)
68
69bool 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
David Majnemer9966fe82015-09-18 08:18:07 +000083 DenseMap<MachineBasicBlock *, int> FuncletMembership;
David Majnemer97890232015-09-17 20:45:18 +000084 for (MachineBasicBlock *MBB : FuncletBlocks)
85 collectFuncletMembers(FuncletMembership, MBB->getNumber(), MBB);
86
David Majnemer9966fe82015-09-18 08:18:07 +000087 F.sort([&](MachineBasicBlock &x, MachineBasicBlock &y) {
88 return FuncletMembership[&x] < FuncletMembership[&y];
89 });
David Majnemer97890232015-09-17 20:45:18 +000090
91 // Conservatively assume we changed something.
92 return true;
93}