1//===-- FuncletLayout.cpp - Contiguously lay out funclets -----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements basic block placement transformations which result in
10// funclets being contiguous.
11//
12//===----------------------------------------------------------------------===//
13#include "llvm/CodeGen/FuncletLayout.h"
14#include "llvm/CodeGen/Analysis.h"
15#include "llvm/CodeGen/MachineFunction.h"
16#include "llvm/CodeGen/MachineFunctionPass.h"
17#include "llvm/CodeGen/Passes.h"
18#include "llvm/InitializePasses.h"
19using namespace llvm;
20
21#define DEBUG_TYPE "funclet-layout"
22
23static bool runFuncletLayout(MachineFunction &F) {
24 // Even though this gets information from getEHScopeMembership(), this pass is
25 // only necessary for funclet-based EH personalities, in which these EH scopes
26 // are outlined at the end.
27 DenseMap<const MachineBasicBlock *, int> FuncletMembership =
28 getEHScopeMembership(MF: F);
29 if (FuncletMembership.empty())
30 return false;
31
32 F.sort(comp: [&](MachineBasicBlock &X, MachineBasicBlock &Y) {
33 auto FuncletX = FuncletMembership.find(Val: &X);
34 auto FuncletY = FuncletMembership.find(Val: &Y);
35 assert(FuncletX != FuncletMembership.end());
36 assert(FuncletY != FuncletMembership.end());
37 return FuncletX->second < FuncletY->second;
38 });
39
40 // Conservatively assume we changed something.
41 return true;
42}
43
44namespace {
45class FuncletLayoutLegacy : public MachineFunctionPass {
46public:
47 static char ID; // Pass identification, replacement for typeid
48 FuncletLayoutLegacy() : MachineFunctionPass(ID) {}
49
50 bool runOnMachineFunction(MachineFunction &F) override {
51 return runFuncletLayout(F);
52 }
53 MachineFunctionProperties getRequiredProperties() const override {
54 return MachineFunctionProperties().setNoVRegs();
55 }
56};
57} // namespace
58
59char FuncletLayoutLegacy::ID = 0;
60char &llvm::FuncletLayoutID = FuncletLayoutLegacy::ID;
61INITIALIZE_PASS(FuncletLayoutLegacy, DEBUG_TYPE,
62 "Contiguously Lay Out Funclets", false, false)
63
64PreservedAnalyses FuncletLayoutPass::run(MachineFunction &MF,
65 MachineFunctionAnalysisManager &MFAM) {
66 MFPropsModifier _(*this, MF);
67 if (!runFuncletLayout(F&: MF))
68 return PreservedAnalyses::all();
69
70 return getMachineFunctionPassPreservedAnalyses();
71}
72