blob: e1e185b4752c0c1f7112461efe2f87d165c59c53 [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"
David Majnemerf828a0c2015-10-01 18:44:59 +000019#include "llvm/Target/TargetInstrInfo.h"
20#include "llvm/Target/TargetSubtargetInfo.h"
David Majnemer97890232015-09-17 20:45:18 +000021using namespace llvm;
22
23#define DEBUG_TYPE "funclet-layout"
24
25namespace {
26class FuncletLayout : public MachineFunctionPass {
27public:
28 static char ID; // Pass identification, replacement for typeid
29 FuncletLayout() : MachineFunctionPass(ID) {
30 initializeFuncletLayoutPass(*PassRegistry::getPassRegistry());
31 }
32
33 bool runOnMachineFunction(MachineFunction &F) override;
34};
35}
36
37static void
David Majnemer9966fe82015-09-18 08:18:07 +000038collectFuncletMembers(DenseMap<MachineBasicBlock *, int> &FuncletMembership,
David Majnemer97890232015-09-17 20:45:18 +000039 int Funclet, MachineBasicBlock *MBB) {
40 // Don't revisit blocks.
David Majnemerf828a0c2015-10-01 18:44:59 +000041 if (FuncletMembership.count(MBB) > 0) {
42 // FIXME: This is a hack, we need to assert this unconditionally.
43 bool IsProbablyUnreachableBlock =
44 MBB->empty() ||
45 (MBB->succ_empty() && !MBB->getFirstTerminator()->isReturn() &&
46 MBB->size() == 1);
47
48 if (!IsProbablyUnreachableBlock) {
49 if (FuncletMembership[MBB] != Funclet) {
50 assert(false && "MBB is part of two funclets!");
51 report_fatal_error("MBB is part of two funclets!");
52 }
53 }
David Majnemer97890232015-09-17 20:45:18 +000054 return;
David Majnemerf828a0c2015-10-01 18:44:59 +000055 }
David Majnemer97890232015-09-17 20:45:18 +000056
57 // Add this MBB to our funclet.
58 FuncletMembership[MBB] = Funclet;
59
60 bool IsReturn = false;
61 int NumTerminators = 0;
62 for (MachineInstr &MI : MBB->terminators()) {
63 IsReturn |= MI.isReturn();
64 ++NumTerminators;
65 }
66 assert((!IsReturn || NumTerminators == 1) &&
67 "Expected only one terminator when a return is present!");
68
69 // Returns are boundaries where funclet transfer can occur, don't follow
70 // successors.
71 if (IsReturn)
72 return;
73
74 for (MachineBasicBlock *SMBB : MBB->successors())
75 if (!SMBB->isEHPad())
76 collectFuncletMembers(FuncletMembership, Funclet, SMBB);
77}
78
79char FuncletLayout::ID = 0;
80char &llvm::FuncletLayoutID = FuncletLayout::ID;
81INITIALIZE_PASS(FuncletLayout, "funclet-layout",
82 "Contiguously Lay Out Funclets", false, false)
83
84bool FuncletLayout::runOnMachineFunction(MachineFunction &F) {
85 // We don't have anything to do if there aren't any EH pads.
86 if (!F.getMMI().hasEHFunclets())
87 return false;
88
David Majnemerf828a0c2015-10-01 18:44:59 +000089 const TargetInstrInfo *TII = F.getSubtarget().getInstrInfo();
David Majnemer97890232015-09-17 20:45:18 +000090 SmallVector<MachineBasicBlock *, 16> FuncletBlocks;
David Majnemerf828a0c2015-10-01 18:44:59 +000091 SmallVector<std::pair<MachineBasicBlock *, int>, 16> CatchRetSuccessors;
92 for (MachineBasicBlock &MBB : F) {
David Majnemer97890232015-09-17 20:45:18 +000093 if (MBB.isEHFuncletEntry())
94 FuncletBlocks.push_back(&MBB);
95
David Majnemerf828a0c2015-10-01 18:44:59 +000096 MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
97 if (MBBI->getOpcode() != TII->getCatchReturnOpcode())
98 continue;
99
100 MachineBasicBlock *Successor = MBBI->getOperand(0).getMBB();
101 MachineBasicBlock *SuccessorColor = MBBI->getOperand(1).getMBB();
102 CatchRetSuccessors.push_back({Successor, SuccessorColor->getNumber()});
103 }
104
David Majnemer97890232015-09-17 20:45:18 +0000105 // We don't have anything to do if there aren't any EH pads.
106 if (FuncletBlocks.empty())
107 return false;
108
David Majnemer9966fe82015-09-18 08:18:07 +0000109 DenseMap<MachineBasicBlock *, int> FuncletMembership;
David Majnemerf828a0c2015-10-01 18:44:59 +0000110 // Identify all the basic blocks reachable from the function entry.
111 collectFuncletMembers(FuncletMembership, F.front().getNumber(), F.begin());
112 // Next, identify all the blocks inside the funclets.
David Majnemer97890232015-09-17 20:45:18 +0000113 for (MachineBasicBlock *MBB : FuncletBlocks)
114 collectFuncletMembers(FuncletMembership, MBB->getNumber(), MBB);
David Majnemerf828a0c2015-10-01 18:44:59 +0000115 // Finally, identify all the targets of a catchret.
116 for (std::pair<MachineBasicBlock *, int> CatchRetPair : CatchRetSuccessors)
117 collectFuncletMembers(FuncletMembership, CatchRetPair.second,
118 CatchRetPair.first);
David Majnemer97890232015-09-17 20:45:18 +0000119
David Majnemer9966fe82015-09-18 08:18:07 +0000120 F.sort([&](MachineBasicBlock &x, MachineBasicBlock &y) {
121 return FuncletMembership[&x] < FuncletMembership[&y];
122 });
David Majnemer97890232015-09-17 20:45:18 +0000123
124 // Conservatively assume we changed something.
125 return true;
126}