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