1 //===- ReduceArguments.cpp - Specialized Delta Pass -----------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements a function which calls the Generic Delta pass in order
10 // to reduce uninteresting Arguments from defined functions.
12 //===----------------------------------------------------------------------===//
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"
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
);
35 // BB only references Chunk BBs
36 if (ChunkSucessors
.size() == Term
->getNumSuccessors())
39 bool IsBranch
= isa
<BranchInst
>(Term
);
40 Value
*Address
= nullptr;
41 if (auto IndBI
= dyn_cast
<IndirectBrInst
>(Term
))
42 Address
= IndBI
->getAddress();
44 Term
->eraseFromParent();
46 if (ChunkSucessors
.empty()) {
47 ReturnInst::Create(BB
.getContext(), nullptr, &BB
);
52 BranchInst::Create(ChunkSucessors
[0], &BB
);
56 IndirectBrInst::Create(Address
, ChunkSucessors
.size(), &BB
);
57 for (auto Dest
: ChunkSucessors
)
58 NewIndBI
->addDestination(Dest
);
62 /// Removes uninteresting BBs from switch, if the default case ends up being
63 /// uninteresting, the switch is replaced with a void return (since it has to be
64 /// replace with something)
65 static void removeUninterestingBBsFromSwitch(SwitchInst
&SwInst
,
66 std::set
<BasicBlock
*> BBsToKeep
) {
67 if (!BBsToKeep
.count(SwInst
.getDefaultDest())) {
68 ReturnInst::Create(SwInst
.getContext(), nullptr, SwInst
.getParent());
69 SwInst
.eraseFromParent();
71 for (int I
= 0, E
= SwInst
.getNumCases(); I
!= E
; ++I
) {
72 auto Case
= SwInst
.case_begin() + I
;
73 if (!BBsToKeep
.count(Case
->getCaseSuccessor())) {
74 SwInst
.removeCase(Case
);
81 /// Removes out-of-chunk arguments from functions, and modifies their calls
82 /// accordingly. It also removes allocations of out-of-chunk arguments.
83 static void extractBasicBlocksFromModule(std::vector
<Chunk
> ChunksToKeep
,
85 int I
= 0, BBCount
= 0;
86 std::set
<BasicBlock
*> BBsToKeep
;
88 for (auto &F
: *Program
)
90 if (I
< (int)ChunksToKeep
.size()) {
91 if (ChunksToKeep
[I
].contains(++BBCount
))
92 BBsToKeep
.insert(&BB
);
93 if (ChunksToKeep
[I
].end
== BBCount
)
97 std::vector
<BasicBlock
*> BBsToDelete
;
98 for (auto &F
: *Program
)
100 if (!BBsToKeep
.count(&BB
)) {
101 BBsToDelete
.push_back(&BB
);
102 // Remove out-of-chunk BB from successor phi nodes
103 for (auto *Succ
: successors(&BB
))
104 Succ
->removePredecessor(&BB
);
108 // Replace terminators that reference out-of-chunk BBs
109 for (auto &F
: *Program
)
111 if (auto *SwInst
= dyn_cast
<SwitchInst
>(BB
.getTerminator()))
112 removeUninterestingBBsFromSwitch(*SwInst
, BBsToKeep
);
114 replaceBranchTerminator(BB
, BBsToKeep
);
117 // Replace out-of-chunk switch uses
118 for (auto &BB
: BBsToDelete
) {
119 // Instructions might be referenced in other BBs
121 I
.replaceAllUsesWith(UndefValue::get(I
.getType()));
122 BB
->eraseFromParent();
126 /// Counts the amount of basic blocks and prints their name & respective index
127 static int countBasicBlocks(Module
*Program
) {
128 // TODO: Silence index with --quiet flag
129 outs() << "----------------------------\n";
131 for (auto &F
: *Program
)
134 outs() << "\t" << ++BBCount
<< ": " << BB
.getName() << "\n";
136 outs() << "\t" << ++BBCount
<< ": Unnamed\n";
142 void llvm::reduceBasicBlocksDeltaPass(TestRunner
&Test
) {
143 outs() << "*** Reducing Basic Blocks...\n";
144 int BBCount
= countBasicBlocks(Test
.getProgram());
145 runDeltaPass(Test
, BBCount
, extractBasicBlocksFromModule
);