17d523365SDimitry Andric //===-- FuncletLayout.cpp - Contiguously lay out funclets -----------------===//
27d523365SDimitry Andric //
37d523365SDimitry Andric //                     The LLVM Compiler Infrastructure
47d523365SDimitry Andric //
57d523365SDimitry Andric // This file is distributed under the University of Illinois Open Source
67d523365SDimitry Andric // License. See LICENSE.TXT for details.
77d523365SDimitry Andric //
87d523365SDimitry Andric //===----------------------------------------------------------------------===//
97d523365SDimitry Andric //
107d523365SDimitry Andric // This file implements basic block placement transformations which result in
117d523365SDimitry Andric // funclets being contiguous.
127d523365SDimitry Andric //
137d523365SDimitry Andric //===----------------------------------------------------------------------===//
147d523365SDimitry Andric #include "llvm/CodeGen/Analysis.h"
157d523365SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
167d523365SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
17db17bf38SDimitry Andric #include "llvm/CodeGen/Passes.h"
187d523365SDimitry Andric using namespace llvm;
197d523365SDimitry Andric 
207d523365SDimitry Andric #define DEBUG_TYPE "funclet-layout"
217d523365SDimitry Andric 
227d523365SDimitry Andric namespace {
237d523365SDimitry Andric class FuncletLayout : public MachineFunctionPass {
247d523365SDimitry Andric public:
257d523365SDimitry Andric   static char ID; // Pass identification, replacement for typeid
FuncletLayout()267d523365SDimitry Andric   FuncletLayout() : MachineFunctionPass(ID) {
277d523365SDimitry Andric     initializeFuncletLayoutPass(*PassRegistry::getPassRegistry());
287d523365SDimitry Andric   }
297d523365SDimitry Andric 
307d523365SDimitry Andric   bool runOnMachineFunction(MachineFunction &F) override;
getRequiredProperties() const313ca95b02SDimitry Andric   MachineFunctionProperties getRequiredProperties() const override {
323ca95b02SDimitry Andric     return MachineFunctionProperties().set(
33d88c1a5aSDimitry Andric         MachineFunctionProperties::Property::NoVRegs);
343ca95b02SDimitry Andric   }
357d523365SDimitry Andric };
367d523365SDimitry Andric }
377d523365SDimitry Andric 
387d523365SDimitry Andric char FuncletLayout::ID = 0;
397d523365SDimitry Andric char &llvm::FuncletLayoutID = FuncletLayout::ID;
40302affcbSDimitry Andric INITIALIZE_PASS(FuncletLayout, DEBUG_TYPE,
417d523365SDimitry Andric                 "Contiguously Lay Out Funclets", false, false)
427d523365SDimitry Andric 
runOnMachineFunction(MachineFunction & F)437d523365SDimitry Andric bool FuncletLayout::runOnMachineFunction(MachineFunction &F) {
44*4ba319b5SDimitry Andric   // Even though this gets information from getEHScopeMembership(), this pass is
45*4ba319b5SDimitry Andric   // only necessary for funclet-based EH personalities, in which these EH scopes
46*4ba319b5SDimitry Andric   // are outlined at the end.
477d523365SDimitry Andric   DenseMap<const MachineBasicBlock *, int> FuncletMembership =
48*4ba319b5SDimitry Andric       getEHScopeMembership(F);
497d523365SDimitry Andric   if (FuncletMembership.empty())
507d523365SDimitry Andric     return false;
517d523365SDimitry Andric 
527d523365SDimitry Andric   F.sort([&](MachineBasicBlock &X, MachineBasicBlock &Y) {
537d523365SDimitry Andric     auto FuncletX = FuncletMembership.find(&X);
547d523365SDimitry Andric     auto FuncletY = FuncletMembership.find(&Y);
557d523365SDimitry Andric     assert(FuncletX != FuncletMembership.end());
567d523365SDimitry Andric     assert(FuncletY != FuncletMembership.end());
577d523365SDimitry Andric     return FuncletX->second < FuncletY->second;
587d523365SDimitry Andric   });
597d523365SDimitry Andric 
607d523365SDimitry Andric   // Conservatively assume we changed something.
617d523365SDimitry Andric   return true;
627d523365SDimitry Andric }
63