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