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