David Blaikie | 070598b | 2019-09-18 21:45:05 +0000 | [diff] [blame] | 1 | //===- ReduceArguments.cpp - Specialized Delta Pass -----------------------===// |
| 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 | // This file implements a function which calls the Generic Delta pass in order |
| 10 | // to reduce uninteresting Arguments from defined functions. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #include "ReduceBasicBlocks.h" |
| 15 | #include "llvm/IR/BasicBlock.h" |
| 16 | #include "llvm/IR/Instruction.h" |
| 17 | #include "llvm/IR/Instructions.h" |
| 18 | #include "llvm/IR/LLVMContext.h" |
| 19 | #include "llvm/IR/Value.h" |
| 20 | #include "llvm/Support/Casting.h" |
| 21 | #include "llvm/Support/raw_ostream.h" |
| 22 | #include <vector> |
| 23 | |
| 24 | using namespace llvm; |
| 25 | |
| 26 | /// Replaces BB Terminator with one that only contains Chunk BBs |
| 27 | static void replaceBranchTerminator(BasicBlock &BB, |
| 28 | std::set<BasicBlock *> BBsToKeep) { |
| 29 | auto Term = BB.getTerminator(); |
| 30 | std::vector<BasicBlock *> ChunkSucessors; |
| 31 | for (auto Succ : successors(&BB)) |
| 32 | if (BBsToKeep.count(Succ)) |
| 33 | ChunkSucessors.push_back(Succ); |
| 34 | |
| 35 | // BB only references Chunk BBs |
| 36 | if (ChunkSucessors.size() == Term->getNumSuccessors()) |
| 37 | return; |
| 38 | |
| 39 | Term->eraseFromParent(); |
| 40 | |
| 41 | if (ChunkSucessors.empty()) { |
| 42 | ReturnInst::Create(BB.getContext(), nullptr, &BB); |
| 43 | return; |
| 44 | } |
| 45 | |
| 46 | if (isa<BranchInst>(Term)) |
| 47 | BranchInst::Create(ChunkSucessors[0], &BB); |
| 48 | |
| 49 | if (auto IndBI = dyn_cast<IndirectBrInst>(Term)) { |
| 50 | auto NewIndBI = |
| 51 | IndirectBrInst::Create(IndBI->getAddress(), ChunkSucessors.size(), &BB); |
| 52 | for (auto Dest : ChunkSucessors) |
| 53 | NewIndBI->addDestination(Dest); |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | /// Removes uninteresting BBs from switch, if the default case ends up being |
| 58 | /// uninteresting, the switch is replaced with a void return (since it has to be |
| 59 | /// replace with something) |
| 60 | static void removeUninterestingBBsFromSwitch(SwitchInst &SwInst, |
| 61 | std::set<BasicBlock *> BBsToKeep) { |
| 62 | if (!BBsToKeep.count(SwInst.getDefaultDest())) { |
| 63 | ReturnInst::Create(SwInst.getContext(), nullptr, SwInst.getParent()); |
| 64 | SwInst.eraseFromParent(); |
| 65 | } else |
| 66 | for (int I = 0, E = SwInst.getNumCases(); I != E; ++I) { |
| 67 | auto Case = SwInst.case_begin() + I; |
| 68 | if (!BBsToKeep.count(Case->getCaseSuccessor())) { |
| 69 | SwInst.removeCase(Case); |
| 70 | --I; |
| 71 | --E; |
| 72 | } |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | /// Removes out-of-chunk arguments from functions, and modifies their calls |
| 77 | /// accordingly. It also removes allocations of out-of-chunk arguments. |
| 78 | /// @returns the Module stripped of out-of-chunk functions |
| 79 | static void extractBasicBlocksFromModule(std::vector<Chunk> ChunksToKeep, |
| 80 | Module *Program) { |
David Blaikie | c4da7ee | 2019-09-18 22:30:25 +0000 | [diff] [blame^] | 81 | int I = 0, BBCount = 0; |
David Blaikie | 070598b | 2019-09-18 21:45:05 +0000 | [diff] [blame] | 82 | std::set<BasicBlock *> BBsToKeep; |
| 83 | |
| 84 | for (auto &F : *Program) |
| 85 | for (auto &BB : F) |
David Blaikie | c4da7ee | 2019-09-18 22:30:25 +0000 | [diff] [blame^] | 86 | if (I < (int)ChunksToKeep.size()) { |
David Blaikie | 070598b | 2019-09-18 21:45:05 +0000 | [diff] [blame] | 87 | if (ChunksToKeep[I].contains(++BBCount)) |
| 88 | BBsToKeep.insert(&BB); |
| 89 | if (ChunksToKeep[I].end == BBCount) |
| 90 | ++I; |
| 91 | } |
| 92 | |
| 93 | std::vector<BasicBlock *> BBsToDelete; |
| 94 | for (auto &F : *Program) |
| 95 | for (auto &BB : F) { |
| 96 | if (!BBsToKeep.count(&BB)) { |
| 97 | BBsToDelete.push_back(&BB); |
| 98 | // Remove out-of-chunk BB from successor phi nodes |
| 99 | for (auto *Succ : successors(&BB)) |
| 100 | Succ->removePredecessor(&BB); |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | // Replace terminators that reference out-of-chunk BBs |
| 105 | for (auto &F : *Program) |
| 106 | for (auto &BB : F) { |
| 107 | if (auto *SwInst = dyn_cast<SwitchInst>(BB.getTerminator())) |
| 108 | removeUninterestingBBsFromSwitch(*SwInst, BBsToKeep); |
| 109 | else |
| 110 | replaceBranchTerminator(BB, BBsToKeep); |
| 111 | } |
| 112 | |
| 113 | // Replace out-of-chunk switch uses |
| 114 | for (auto &BB : BBsToDelete) { |
| 115 | // Instructions might be referenced in other BBs |
| 116 | for (auto &I : *BB) |
| 117 | I.replaceAllUsesWith(UndefValue::get(I.getType())); |
| 118 | BB->eraseFromParent(); |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | /// Counts the amount of basic blocks and prints their name & respective index |
David Blaikie | c4da7ee | 2019-09-18 22:30:25 +0000 | [diff] [blame^] | 123 | static int countBasicBlocks(Module *Program) { |
David Blaikie | 070598b | 2019-09-18 21:45:05 +0000 | [diff] [blame] | 124 | // TODO: Silence index with --quiet flag |
| 125 | outs() << "----------------------------\n"; |
| 126 | int BBCount = 0; |
| 127 | for (auto &F : *Program) |
| 128 | for (auto &BB : F) { |
| 129 | if (BB.hasName()) |
| 130 | outs() << "\t" << ++BBCount << ": " << BB.getName() << "\n"; |
| 131 | else |
| 132 | outs() << "\t" << ++BBCount << ": Unnamed\n"; |
| 133 | } |
| 134 | |
| 135 | return BBCount; |
| 136 | } |
| 137 | |
| 138 | void llvm::reduceBasicBlocksDeltaPass(TestRunner &Test) { |
| 139 | outs() << "*** Reducing Basic Blocks...\n"; |
David Blaikie | c4da7ee | 2019-09-18 22:30:25 +0000 | [diff] [blame^] | 140 | int BBCount = countBasicBlocks(Test.getProgram()); |
David Blaikie | 070598b | 2019-09-18 21:45:05 +0000 | [diff] [blame] | 141 | runDeltaPass(Test, BBCount, extractBasicBlocksFromModule); |
| 142 | } |