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