brintos

brintos / llvm-project-archived public Read only

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