diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h --- a/llvm/include/llvm/CodeGen/Passes.h +++ b/llvm/include/llvm/CodeGen/Passes.h @@ -47,6 +47,8 @@ /// the entry block. FunctionPass *createUnreachableBlockEliminationPass(); + MachineFunctionPass *createRemoveEmptyBasicBlocksPass(); + /// createBasicBlockSections Pass - This pass assigns sections to machine /// basic blocks and is enabled with -fbasic-block-sections. Buf is a memory /// buffer that contains the list of functions and basic block ids to diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -82,6 +82,7 @@ void initializeAttributorLegacyPassPass(PassRegistry&); void initializeAttributorCGSCCLegacyPassPass(PassRegistry &); void initializeBasicBlockSectionsPass(PassRegistry &); +void initializeRemoveEmptyBasicBlocksPass(PassRegistry &); void initializeBDCELegacyPassPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAAWrapperPassPass(PassRegistry&); diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -142,6 +142,7 @@ RegisterCoalescer.cpp RegisterPressure.cpp RegisterScavenging.cpp + RemoveEmptyBasicBlocks.cpp RemoveRedundantDebugValues.cpp RenameIndependentSubregs.cpp MachineStableHash.cpp diff --git a/llvm/lib/CodeGen/RemoveEmptyBasicBlocks.cpp b/llvm/lib/CodeGen/RemoveEmptyBasicBlocks.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/CodeGen/RemoveEmptyBasicBlocks.cpp @@ -0,0 +1,76 @@ +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/InitializePasses.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineBasicBlock.h" + +using llvm::SmallVector; +using llvm::MachineJumpTableInfo; +using namespace llvm; + +class RemoveEmptyBasicBlocks : public MachineFunctionPass { +public: + static char ID; + + RemoveEmptyBasicBlocks() : MachineFunctionPass(ID) { + initializeRemoveEmptyBasicBlocksPass(*PassRegistry::getPassRegistry()); + } + + StringRef getPassName() const override { + return "Remove Basic Blocks."; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool runOnMachineFunction(MachineFunction &MF) override; +}; + +bool RemoveEmptyBasicBlocks::runOnMachineFunction(MachineFunction &MF) { + SmallVector EmptyBlocks; + MachineJumpTableInfo * JTI = MF.getJumpTableInfo(); + for(auto &MBB: MF) { + bool HasAnyRealCode = false; + for (auto &MI: MBB) { + if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() && + !MI.isDebugInstr()) { + HasAnyRealCode = true; + } + } + if (!HasAnyRealCode) { + if (!MBB.isEHPad() && !MBB.hasAddressTaken()) + EmptyBlocks.push_back(&MBB); + } + } + for (MachineBasicBlock *EMBB: EmptyBlocks){ + auto NextMBBI = std::next(MachineFunction::iterator(EMBB)); + if (NextMBBI != MF.end()) { + for(auto &MBB: MF) { + if (MBB.isSuccessor(EMBB)) + MBB.ReplaceUsesOfBlockWith(EMBB, &*NextMBBI); + } + if(JTI) + JTI->ReplaceMBBInJumpTables(EMBB, &*NextMBBI); + MF.remove(EMBB); + errs() << "Removed empty basic block from: " << MF.getName() << "\n"; + } + } + return true; +} + +char RemoveEmptyBasicBlocks::ID = 0; +INITIALIZE_PASS(RemoveEmptyBasicBlocks, "remove-empty-blocks", + "Removes empty basic blocks.", + false, false) + +void RemoveEmptyBasicBlocks::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +MachineFunctionPass * +llvm::createRemoveEmptyBasicBlocksPass() { + return new RemoveEmptyBasicBlocks(); +} diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -1210,11 +1210,15 @@ addPass(createMachineOutlinerPass(RunOnAllFunctions)); } + // Machine function splitter uses the basic block sections feature. Both // cannot be enabled at the same time. Basic block sections takes precedence. // FIXME: In principle, BasicBlockSection::Labels and splitting can used // together. Update this check once we have addressed any issues. if (TM->getBBSectionsType() != llvm::BasicBlockSection::None) { + // Empty basic blocks (without real code) convolute profile attribution. So + // we garbage-collect them here. + addPass(llvm::createRemoveEmptyBasicBlocksPass()); addPass(llvm::createBasicBlockSectionsPass(TM->getBBSectionsFuncListBuf())); } else if (TM->Options.EnableMachineFunctionSplitter || EnableMachineFunctionSplitter) {