diff options
Diffstat (limited to 'llvm/lib/CodeGen/GCEmptyBasicBlocks.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/GCEmptyBasicBlocks.cpp | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/GCEmptyBasicBlocks.cpp b/llvm/lib/CodeGen/GCEmptyBasicBlocks.cpp new file mode 100644 index 000000000000..598be26e40c8 --- /dev/null +++ b/llvm/lib/CodeGen/GCEmptyBasicBlocks.cpp @@ -0,0 +1,100 @@ +//===-- GCEmptyBasicBlocks.cpp ----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the implementation of empty blocks garbage collection +/// pass. +/// +//===----------------------------------------------------------------------===// +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/InitializePasses.h" + +using namespace llvm; + +#define DEBUG_TYPE "gc-empty-basic-blocks" + +STATISTIC(NumEmptyBlocksRemoved, "Number of empty blocks removed"); + +class GCEmptyBasicBlocks : public MachineFunctionPass { +public: + static char ID; + + GCEmptyBasicBlocks() : MachineFunctionPass(ID) { + initializeGCEmptyBasicBlocksPass(*PassRegistry::getPassRegistry()); + } + + StringRef getPassName() const override { + return "Remove Empty Basic Blocks."; + } + + bool runOnMachineFunction(MachineFunction &MF) override; +}; + +bool GCEmptyBasicBlocks::runOnMachineFunction(MachineFunction &MF) { + if (MF.size() < 2) + return false; + MachineJumpTableInfo *JTI = MF.getJumpTableInfo(); + int NumRemoved = 0; + + // Iterate over all blocks except the last one. We can't remove the last block + // since it has no fallthrough block to rewire its predecessors to. + for (MachineFunction::iterator MBB = MF.begin(), + LastMBB = MachineFunction::iterator(MF.back()), + NextMBB; + MBB != LastMBB; MBB = NextMBB) { + NextMBB = std::next(MBB); + // TODO If a block is an eh pad, or it has address taken, we don't remove + // it. Removing such blocks is possible, but it probably requires a more + // complex logic. + if (MBB->isEHPad() || MBB->hasAddressTaken()) + continue; + // Skip blocks with real code. + bool HasAnyRealCode = llvm::any_of(*MBB, [](const MachineInstr &MI) { + return !MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() && + !MI.isDebugInstr(); + }); + if (HasAnyRealCode) + continue; + + LLVM_DEBUG(dbgs() << "Removing basic block " << MBB->getName() + << " in function " << MF.getName() << ":\n" + << *MBB << "\n"); + SmallVector<MachineBasicBlock *, 8> Preds(MBB->predecessors()); + // Rewire the predecessors of this block to use the next block. + for (auto &Pred : Preds) + Pred->ReplaceUsesOfBlockWith(&*MBB, &*NextMBB); + // Update the jump tables. + if (JTI) + JTI->ReplaceMBBInJumpTables(&*MBB, &*NextMBB); + // Remove this block from predecessors of all its successors. + while (!MBB->succ_empty()) + MBB->removeSuccessor(MBB->succ_end() - 1); + // Finally, remove the block from the function. + MBB->eraseFromParent(); + ++NumRemoved; + } + NumEmptyBlocksRemoved += NumRemoved; + return NumRemoved != 0; +} + +char GCEmptyBasicBlocks::ID = 0; +INITIALIZE_PASS(GCEmptyBasicBlocks, "gc-empty-basic-blocks", + "Removes empty basic blocks and redirects their uses to their " + "fallthrough blocks.", + false, false) + +MachineFunctionPass *llvm::createGCEmptyBasicBlocksPass() { + return new GCEmptyBasicBlocks(); +} |
