xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/GCEmptyBasicBlocks.cpp (revision ef80df0a71912500ad84060334a24e903869f00b)
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