1*c9157d92SDimitry Andric //===-- GCEmptyBasicBlocks.cpp ----------------------------------*- C++ -*-===//
2*c9157d92SDimitry Andric //
3*c9157d92SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*c9157d92SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*c9157d92SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*c9157d92SDimitry Andric //
7*c9157d92SDimitry Andric //===----------------------------------------------------------------------===//
8*c9157d92SDimitry Andric ///
9*c9157d92SDimitry Andric /// \file
10*c9157d92SDimitry Andric /// This file contains the implementation of empty blocks garbage collection
11*c9157d92SDimitry Andric /// pass.
12*c9157d92SDimitry Andric ///
13*c9157d92SDimitry Andric //===----------------------------------------------------------------------===//
14*c9157d92SDimitry Andric #include "llvm/ADT/SmallVector.h"
15*c9157d92SDimitry Andric #include "llvm/ADT/Statistic.h"
16*c9157d92SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
17*c9157d92SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
18*c9157d92SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
19*c9157d92SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h"
20*c9157d92SDimitry Andric #include "llvm/CodeGen/Passes.h"
21*c9157d92SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
22*c9157d92SDimitry Andric #include "llvm/InitializePasses.h"
23*c9157d92SDimitry Andric
24*c9157d92SDimitry Andric using namespace llvm;
25*c9157d92SDimitry Andric
26*c9157d92SDimitry Andric #define DEBUG_TYPE "gc-empty-basic-blocks"
27*c9157d92SDimitry Andric
28*c9157d92SDimitry Andric STATISTIC(NumEmptyBlocksRemoved, "Number of empty blocks removed");
29*c9157d92SDimitry Andric
30*c9157d92SDimitry Andric class GCEmptyBasicBlocks : public MachineFunctionPass {
31*c9157d92SDimitry Andric public:
32*c9157d92SDimitry Andric static char ID;
33*c9157d92SDimitry Andric
GCEmptyBasicBlocks()34*c9157d92SDimitry Andric GCEmptyBasicBlocks() : MachineFunctionPass(ID) {
35*c9157d92SDimitry Andric initializeGCEmptyBasicBlocksPass(*PassRegistry::getPassRegistry());
36*c9157d92SDimitry Andric }
37*c9157d92SDimitry Andric
getPassName() const38*c9157d92SDimitry Andric StringRef getPassName() const override {
39*c9157d92SDimitry Andric return "Remove Empty Basic Blocks.";
40*c9157d92SDimitry Andric }
41*c9157d92SDimitry Andric
42*c9157d92SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
43*c9157d92SDimitry Andric };
44*c9157d92SDimitry Andric
runOnMachineFunction(MachineFunction & MF)45*c9157d92SDimitry Andric bool GCEmptyBasicBlocks::runOnMachineFunction(MachineFunction &MF) {
46*c9157d92SDimitry Andric if (MF.size() < 2)
47*c9157d92SDimitry Andric return false;
48*c9157d92SDimitry Andric MachineJumpTableInfo *JTI = MF.getJumpTableInfo();
49*c9157d92SDimitry Andric int NumRemoved = 0;
50*c9157d92SDimitry Andric
51*c9157d92SDimitry Andric // Iterate over all blocks except the last one. We can't remove the last block
52*c9157d92SDimitry Andric // since it has no fallthrough block to rewire its predecessors to.
53*c9157d92SDimitry Andric for (MachineFunction::iterator MBB = MF.begin(),
54*c9157d92SDimitry Andric LastMBB = MachineFunction::iterator(MF.back()),
55*c9157d92SDimitry Andric NextMBB;
56*c9157d92SDimitry Andric MBB != LastMBB; MBB = NextMBB) {
57*c9157d92SDimitry Andric NextMBB = std::next(MBB);
58*c9157d92SDimitry Andric // TODO If a block is an eh pad, or it has address taken, we don't remove
59*c9157d92SDimitry Andric // it. Removing such blocks is possible, but it probably requires a more
60*c9157d92SDimitry Andric // complex logic.
61*c9157d92SDimitry Andric if (MBB->isEHPad() || MBB->hasAddressTaken())
62*c9157d92SDimitry Andric continue;
63*c9157d92SDimitry Andric // Skip blocks with real code.
64*c9157d92SDimitry Andric bool HasAnyRealCode = llvm::any_of(*MBB, [](const MachineInstr &MI) {
65*c9157d92SDimitry Andric return !MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() &&
66*c9157d92SDimitry Andric !MI.isDebugInstr();
67*c9157d92SDimitry Andric });
68*c9157d92SDimitry Andric if (HasAnyRealCode)
69*c9157d92SDimitry Andric continue;
70*c9157d92SDimitry Andric
71*c9157d92SDimitry Andric LLVM_DEBUG(dbgs() << "Removing basic block " << MBB->getName()
72*c9157d92SDimitry Andric << " in function " << MF.getName() << ":\n"
73*c9157d92SDimitry Andric << *MBB << "\n");
74*c9157d92SDimitry Andric SmallVector<MachineBasicBlock *, 8> Preds(MBB->predecessors());
75*c9157d92SDimitry Andric // Rewire the predecessors of this block to use the next block.
76*c9157d92SDimitry Andric for (auto &Pred : Preds)
77*c9157d92SDimitry Andric Pred->ReplaceUsesOfBlockWith(&*MBB, &*NextMBB);
78*c9157d92SDimitry Andric // Update the jump tables.
79*c9157d92SDimitry Andric if (JTI)
80*c9157d92SDimitry Andric JTI->ReplaceMBBInJumpTables(&*MBB, &*NextMBB);
81*c9157d92SDimitry Andric // Remove this block from predecessors of all its successors.
82*c9157d92SDimitry Andric while (!MBB->succ_empty())
83*c9157d92SDimitry Andric MBB->removeSuccessor(MBB->succ_end() - 1);
84*c9157d92SDimitry Andric // Finally, remove the block from the function.
85*c9157d92SDimitry Andric MBB->eraseFromParent();
86*c9157d92SDimitry Andric ++NumRemoved;
87*c9157d92SDimitry Andric }
88*c9157d92SDimitry Andric NumEmptyBlocksRemoved += NumRemoved;
89*c9157d92SDimitry Andric return NumRemoved != 0;
90*c9157d92SDimitry Andric }
91*c9157d92SDimitry Andric
92*c9157d92SDimitry Andric char GCEmptyBasicBlocks::ID = 0;
93*c9157d92SDimitry Andric INITIALIZE_PASS(GCEmptyBasicBlocks, "gc-empty-basic-blocks",
94*c9157d92SDimitry Andric "Removes empty basic blocks and redirects their uses to their "
95*c9157d92SDimitry Andric "fallthrough blocks.",
96*c9157d92SDimitry Andric false, false)
97*c9157d92SDimitry Andric
createGCEmptyBasicBlocksPass()98*c9157d92SDimitry Andric MachineFunctionPass *llvm::createGCEmptyBasicBlocksPass() {
99*c9157d92SDimitry Andric return new GCEmptyBasicBlocks();
100*c9157d92SDimitry Andric }
101