├── Guides ├── HOW_TO_COMPILE_LLVM_PASS.txt ├── HOW_TO_IR.txt └── HOW_TO_RUN_LLVM_PASS.txt ├── Output ├── README └── test_pass_output.txt ├── Passes ├── .DS_Store ├── CMakeLists.txt ├── DFA │ ├── .DS_Store │ ├── 231DFA.h │ ├── CMakeLists.txt │ ├── LivenessAnalysis.cpp │ ├── MayPointToAnalysis.cpp │ └── ReachingDefinitionAnalysis.cpp ├── part1 │ ├── BranchBias.cpp │ ├── CMakeLists.txt │ ├── CountDynamicInstructions.cpp │ └── CountStaticInstructions.cpp └── testPass │ ├── .DS_Store │ ├── CMakeLists.txt │ └── TestPass.cpp ├── README.md ├── Tests ├── .DS_Store ├── HelloWorld │ └── HelloWorld.cpp ├── run.sh ├── test-dataflow │ ├── fib.bc │ ├── fib.c │ ├── fib.ll │ ├── matrix_mul.bc │ ├── matrix_mul.cpp │ ├── matrix_mul.ll │ ├── test.bc │ ├── test.c │ └── test.ll └── test-example │ ├── run.sh │ ├── test1-main.cpp │ ├── test1.bc │ ├── test1.c │ ├── test1.cpp │ └── test1.ll ├── mount_and_launch.sh └── windows_docker_command.txt /Guides/HOW_TO_COMPILE_LLVM_PASS.txt: -------------------------------------------------------------------------------- 1 | Instructions on compiling your own LLVM pass 2 | 3 | - Start the provided docker image by running "sudo ./mount_and_launch.sh" 4 | - Your "src" folder should be mounted at /LLVM_ROOT/llvm/lib/Transforms/CSE231_Project 5 | - You only need to compile your new pass(es) so we'll move directly into the CSE231_Project build folder. To do that type "cd /LLVM_ROOT/build/lib/Transforms/CSE231_Project" 6 | - Everything is pre-configures. You only need to run "make" 7 | - If everything went well, you should be able to find your pass under /LLVM_ROOT/build/lib/ 8 | - Done! 9 | -------------------------------------------------------------------------------- /Guides/HOW_TO_IR.txt: -------------------------------------------------------------------------------- 1 | Instructions on generating LLVM IR code from source code (for test programs) 2 | 3 | - Start the provided docker image by running "sudo ./mount_and_launch.sh" 4 | - Your "tests" folder should be mounted at /tests within the container. Verify. 5 | - Move into the tests folder: "cd /tests" 6 | - cd into the folder with the test case you want to compile. For example: "cd HelloWorld" 7 | - Compile IR code: "clang -S -emit-llvm HelloWorld.cpp" 8 | - Done! You should be able to see a "HelloWorld.ll" file. 9 | - The file should be immediately available on your local (host) machine as well. You can exit the docker image without losing it. 10 | -------------------------------------------------------------------------------- /Guides/HOW_TO_RUN_LLVM_PASS.txt: -------------------------------------------------------------------------------- 1 | Instructions on running the provided LLVM pass (TestPass): 2 | 3 | - Start the provided docker image by running "sudo ./mount_and_launch.sh" 4 | - Follow the steps in "HOW_TO_COMPILE_LLVM_PASS.txt". DO NOT exit the running container. 5 | - The environment is pre-configured so you can run the pass from any directory in the filesystem. 6 | - To run your pass: "opt -load LLVMTestPass.so -TestPass < /tests/HelloWorld/HelloWorld.ll > /dev/null" 7 | - Our pass sends output to the "errs()" device (standard error). We can redirect the output by appending "2> in the previous command. 8 | - Done! 9 | -------------------------------------------------------------------------------- /Output/README: -------------------------------------------------------------------------------- 1 | This folder will be mounted under /output in the running docker container. Everything you write in that folder will immediately be available on your local (host) machine. 2 | 3 | -------------------------------------------------------------------------------- /Output/test_pass_output.txt: -------------------------------------------------------------------------------- 1 | Hello: __cxx_global_var_init 2 | Hello: main 3 | Hello: _GLOBAL__sub_I_HelloWorld.cpp 4 | -------------------------------------------------------------------------------- /Passes/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenbinZhu/CSE231-LLVM-Project/2d78bcbba6fad743661227dac0acce57fa1a6af2/Passes/.DS_Store -------------------------------------------------------------------------------- /Passes/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(testPass) 2 | add_subdirectory(part1) 3 | add_subdirectory(DFA) 4 | 5 | 6 | add_llvm_loadable_module( CSE231 7 | part1/CountStaticInstructions.cpp 8 | part1/CountDynamicInstructions.cpp 9 | part1/BranchBias.cpp 10 | DFA/231DFA.h 11 | DFA/ReachingDefinitionAnalysis.cpp 12 | DFA/LivenessAnalysis.cpp 13 | DFA/MayPointToAnalysis.cpp 14 | 15 | PLUGIN_TOOL 16 | opt 17 | ) 18 | -------------------------------------------------------------------------------- /Passes/DFA/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenbinZhu/CSE231-LLVM-Project/2d78bcbba6fad743661227dac0acce57fa1a6af2/Passes/DFA/.DS_Store -------------------------------------------------------------------------------- /Passes/DFA/231DFA.h: -------------------------------------------------------------------------------- 1 | //===- CSE231.h - Header for CSE 231 projects ----------------------------*- C++ -*-===// 2 | // 3 | // The LLVM Compiler Infrastructure 4 | // 5 | // This file is distributed under the University of Illinois Open Source 6 | // License. See LICENSE.TXT for details. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This file provides the interface for the passes of CSE 231 projects 11 | // 12 | //===----------------------------------------------------------------------===// 13 | 14 | #ifndef LLVM_TRANSFORMS_231DFA_H 15 | #define LLVM_TRANSFORMS_231DFA_H 16 | 17 | #include "llvm/InitializePasses.h" 18 | #include "llvm/IR/CFG.h" 19 | #include "llvm/IR/InstIterator.h" 20 | #include "llvm/IR/Instructions.h" 21 | #include "llvm/IR/Function.h" 22 | #include "llvm/Support/raw_ostream.h" 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | namespace llvm { 30 | 31 | 32 | /* 33 | * This is the base class to represent information in a dataflow analysis. 34 | * For a specific analysis, you need to create a sublcass of it. 35 | */ 36 | class Info { 37 | public: 38 | Info() {} 39 | Info(const Info& other) {} 40 | virtual ~Info() {}; 41 | 42 | /* 43 | * Print out the information 44 | * 45 | * Direction: 46 | * In your subclass you should implement this function according to the project specifications. 47 | */ 48 | virtual void print() = 0; 49 | 50 | /* 51 | * Compare two pieces of information 52 | * 53 | * Direction: 54 | * In your subclass you need to implement this function. 55 | */ 56 | static bool equals(Info * info1, Info * info2); 57 | /* 58 | * Join two pieces of information. 59 | * The third parameter points to the result. 60 | * 61 | * Direction: 62 | * In your subclass you need to implement this function. 63 | */ 64 | static Info* join(Info * info1, Info * info2, Info * result); 65 | }; 66 | 67 | /* 68 | * This is the base template class to represent the generic dataflow analysis framework 69 | * For a specific analysis, you need to create a sublcass of it. 70 | */ 71 | template 72 | class DataFlowAnalysis { 73 | 74 | private: 75 | typedef std::pair Edge; 76 | // Index to instruction map 77 | std::map IndexToInstr; 78 | // Instruction to index map 79 | std::map InstrToIndex; 80 | // Edge to information map 81 | std::map EdgeToInfo; 82 | // The bottom of the lattice 83 | Info Bottom; 84 | // The initial state of the analysis 85 | Info InitialState; 86 | // EntryInstr points to the first instruction to be processed in the analysis 87 | Instruction * EntryInstr; 88 | 89 | 90 | /* 91 | * Assign an index to each instruction. 92 | * The results are stored in InstrToIndex and IndexToInstr. 93 | * A dummy node (nullptr) is added. It has index 0. This node has only one outgoing edge to EntryInstr. 94 | * The information of this edge is InitialState. 95 | * Any real instruction has an index > 0. 96 | * 97 | * Direction: 98 | * Do *NOT* change this function. 99 | * Both forward and backward analyses must use it to assign 100 | * indices to the instructions of a function. 101 | */ 102 | void assignIndiceToInstrs(Function * F) { 103 | 104 | // Dummy instruction null has index 0; 105 | // Any real instruction's index > 0. 106 | InstrToIndex[nullptr] = 0; 107 | IndexToInstr[0] = nullptr; 108 | 109 | unsigned counter = 1; 110 | for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { 111 | Instruction * instr = &*I; 112 | InstrToIndex[instr] = counter; 113 | IndexToInstr[counter] = instr; 114 | counter++; 115 | } 116 | 117 | return; 118 | } 119 | 120 | /* 121 | * Utility function: 122 | * Get incoming edges of the instruction identified by index. 123 | * IncomingEdges stores the indices of the source instructions of the incoming edges. 124 | */ 125 | void getIncomingEdges(unsigned index, std::vector * IncomingEdges) { 126 | assert(IncomingEdges->size() == 0 && "IncomingEdges should be empty."); 127 | 128 | for (auto const &it : EdgeToInfo) { 129 | if (it.first.second == index) 130 | IncomingEdges->push_back(it.first.first); 131 | } 132 | 133 | return; 134 | } 135 | 136 | /* 137 | * Utility function: 138 | * Get incoming edges of the instruction identified by index. 139 | * OutgoingEdges stores the indices of the destination instructions of the outgoing edges. 140 | */ 141 | void getOutgoingEdges(unsigned index, std::vector * OutgoingEdges) { 142 | assert(OutgoingEdges->size() == 0 && "OutgoingEdges should be empty."); 143 | 144 | for (auto const &it : EdgeToInfo) { 145 | if (it.first.first == index) 146 | OutgoingEdges->push_back(it.first.second); 147 | } 148 | 149 | return; 150 | } 151 | 152 | /* 153 | * Utility function: 154 | * Insert an edge to EdgeToInfo. 155 | * The default initial value for each edge is bottom. 156 | */ 157 | void addEdge(Instruction * src, Instruction * dst, Info * content) { 158 | Edge edge = std::make_pair(InstrToIndex[src], InstrToIndex[dst]); 159 | if (EdgeToInfo.count(edge) == 0) 160 | EdgeToInfo[edge] = content; 161 | return; 162 | } 163 | 164 | /* 165 | * Initialize EdgeToInfo and EntryInstr for a forward analysis. 166 | */ 167 | void initializeForwardMap(Function * func) { 168 | assignIndiceToInstrs(func); 169 | 170 | for (Function::iterator bi = func->begin(), e = func->end(); bi != e; ++bi) { 171 | BasicBlock * block = &*bi; 172 | 173 | Instruction * firstInstr = &(block->front()); 174 | 175 | // Initialize incoming edges to the basic block 176 | for (auto pi = pred_begin(block), pe = pred_end(block); pi != pe; ++pi) { 177 | BasicBlock * prev = *pi; 178 | Instruction * src = (Instruction *)prev->getTerminator(); 179 | Instruction * dst = firstInstr; 180 | addEdge(src, dst, &Bottom); 181 | } 182 | 183 | // If there is at least one phi node, add an edge from the first phi node 184 | // to the first non-phi node instruction in the basic block. 185 | if (isa(firstInstr)) { 186 | addEdge(firstInstr, block->getFirstNonPHI(), &Bottom); 187 | } 188 | 189 | // Initialize edges within the basic block 190 | for (auto ii = block->begin(), ie = block->end(); ii != ie; ++ii) { 191 | Instruction * instr = &*ii; 192 | if (isa(instr)) 193 | continue; 194 | if (instr == (Instruction *)block->getTerminator()) 195 | break; 196 | Instruction * next = instr->getNextNode(); 197 | addEdge(instr, next, &Bottom); 198 | } 199 | 200 | // Initialize outgoing edges of the basic block 201 | Instruction * term = (Instruction *)block->getTerminator(); 202 | for (auto si = succ_begin(block), se = succ_end(block); si != se; ++si) { 203 | BasicBlock * succ = *si; 204 | Instruction * next = &(succ->front()); 205 | addEdge(term, next, &Bottom); 206 | } 207 | 208 | } 209 | 210 | EntryInstr = (Instruction *) &((func->front()).front()); 211 | addEdge(nullptr, EntryInstr, &InitialState); 212 | 213 | return; 214 | } 215 | 216 | /* 217 | * Direction: 218 | * Implement the following function in part 3 for backward analyses 219 | */ 220 | void initializeBackwardMap(Function * func) { 221 | } 222 | 223 | /* 224 | * The flow function. 225 | * Instruction I: the IR instruction to be processed. 226 | * std::vector & IncomingEdges: the vector of the indices of the source instructions of the incoming edges. 227 | * std::vector & IncomingEdges: the vector of indices of the source instructions of the outgoing edges. 228 | * std::vector & Infos: the vector of the newly computed information for each outgoing eages. 229 | * 230 | * Direction: 231 | * Implement this function in subclasses. 232 | */ 233 | virtual void flowfunction(Instruction * I, 234 | std::vector & IncomingEdges, 235 | std::vector & OutgoingEdges, 236 | std::vector & Infos) = 0; 237 | 238 | public: 239 | DataFlowAnalysis(Info & bottom, Info & initialState) : 240 | Bottom(bottom), InitialState(initialState),EntryInstr(nullptr) {} 241 | 242 | virtual ~DataFlowAnalysis() {} 243 | 244 | std::map getEdgeToInfo() { 245 | return EdgeToInfo; 246 | } 247 | 248 | std::map getInstrToIndex() { 249 | return InstrToIndex; 250 | } 251 | 252 | std::map getIndexToInstr() { 253 | return IndexToInstr; 254 | } 255 | 256 | /* 257 | * Print out the analysis results. 258 | * 259 | * Direction: 260 | * Do not change this funciton. 261 | * The autograder will check the output of this function. 262 | */ 263 | void print() { 264 | for (auto const &it : EdgeToInfo) { 265 | errs() << "Edge " << it.first.first << "->" "Edge " << it.first.second << ":"; 266 | (it.second)->print(); 267 | } 268 | } 269 | 270 | /* 271 | * This function implements the work list algorithm in the following steps: 272 | * (1) Initialize info of each edge to bottom 273 | * (2) Initialize the worklist 274 | * (3) Compute until the worklist is empty 275 | * 276 | * Direction: 277 | * Implement the rest of the function. 278 | * You may not change anything before "// (2) Initialize the worklist". 279 | */ 280 | void runWorklistAlgorithm(Function * func) { 281 | std::deque worklist; 282 | 283 | // (1) Initialize info of each edge to bottom 284 | if (Direction) 285 | initializeForwardMap(func); 286 | else 287 | initializeBackwardMap(func); 288 | 289 | assert(EntryInstr != nullptr && "Entry instruction is null."); 290 | 291 | // (2) Initialize the work list 292 | std::set nodeSet; 293 | 294 | for (auto it = EdgeToInfo.begin(); it != EdgeToInfo.end(); ++it) { 295 | Edge edge = it->first; 296 | 297 | if (edge.first == 0) 298 | continue; 299 | 300 | // Add all instructions nodes to worklist 301 | if (nodeSet.count(edge.first) == 0) { 302 | worklist.push_back(edge.first); 303 | nodeSet.insert(edge.first); 304 | } 305 | 306 | if (nodeSet.count(edge.second) == 0) { 307 | worklist.push_back(edge.second); 308 | nodeSet.insert(edge.second); 309 | } 310 | } 311 | 312 | // (3) Compute until the work list is empty 313 | while (worklist.size() > 0) { 314 | std::vector incomingEdges; 315 | std::vector outgoingEdges; 316 | std::vector infos; 317 | 318 | unsigned instrIdx = worklist.front(); 319 | worklist.pop_front(); 320 | Instruction * instr = IndexToInstr[instrIdx]; 321 | 322 | getIncomingEdges(instrIdx, &incomingEdges); 323 | getOutgoingEdges(instrIdx, &outgoingEdges); 324 | 325 | flowfunction(instr, incomingEdges, outgoingEdges, infos); 326 | 327 | for (size_t i = 0; i < infos.size(); ++i) { 328 | Info * newInfo = new Info(); 329 | Edge outEdge = std::make_pair(instrIdx, outgoingEdges[i]); 330 | 331 | Info::join(infos[i], EdgeToInfo[outEdge], newInfo); 332 | 333 | if (!Info::equals(EdgeToInfo[outEdge], newInfo)) { 334 | EdgeToInfo[outEdge] = newInfo; 335 | worklist.push_back(outEdge.second); 336 | } 337 | } 338 | } 339 | } 340 | }; 341 | 342 | 343 | 344 | } 345 | #endif // End LLVM_231DFA_H 346 | -------------------------------------------------------------------------------- /Passes/DFA/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Just leave this file empty 2 | -------------------------------------------------------------------------------- /Passes/DFA/LivenessAnalysis.cpp: -------------------------------------------------------------------------------- 1 | //Wenbin Zhu A53211044 2 | #include "231DFA.h" 3 | #include "llvm/Pass.h" 4 | #include "llvm/IR/Function.h" 5 | #include "llvm/Support/raw_ostream.h" 6 | 7 | using namespace llvm; 8 | using namespace std; 9 | 10 | class LivenessInfo : public Info { 11 | private: 12 | set infoSet; 13 | 14 | public: 15 | LivenessInfo() {} 16 | 17 | LivenessInfo(set s) { 18 | infoSet = s; 19 | } 20 | 21 | // getter and setter 22 | set & getInfoSet() { 23 | return infoSet; 24 | } 25 | 26 | void setInfoSet(set s) { 27 | infoSet = s; 28 | } 29 | 30 | void print() { 31 | for (auto it = infoSet.begin(); it != infoSet.end(); ++it) { 32 | errs() << *it << '|'; 33 | } 34 | 35 | errs() << '\n'; 36 | } 37 | 38 | static bool equals(LivenessInfo * info1, LivenessInfo * info2) { 39 | return info1->getInfoSet() == info2->getInfoSet(); 40 | } 41 | 42 | static LivenessInfo* join(LivenessInfo * info1, LivenessInfo * info2, LivenessInfo * result) { 43 | set retSet = info1->getInfoSet(); 44 | set info2Set = info2->getInfoSet(); 45 | 46 | for (auto it = info2Set.begin(); it != info2Set.end(); ++it) { 47 | retSet.insert(*it); 48 | } 49 | 50 | result->setInfoSet(retSet); 51 | 52 | return nullptr; 53 | } 54 | 55 | // Remove info2 from info1 56 | static LivenessInfo* remove(LivenessInfo * info1, LivenessInfo * info2, LivenessInfo * result) { 57 | set retSet = info1->getInfoSet(); 58 | set info2Set = info2->getInfoSet(); 59 | 60 | for (auto it = info2Set.begin(); it != info2Set.end(); ++it) { 61 | retSet.erase(*it); 62 | } 63 | 64 | result->setInfoSet(retSet); 65 | 66 | return nullptr; 67 | } 68 | }; 69 | 70 | 71 | class LivenessAnalysis : public DataFlowAnalysis { 72 | private: 73 | typedef pair Edge; 74 | map opToCategory = {{"alloca", 1}, {"load", 1}, {"select", 1}, 75 | {"icmp", 1}, {"fcmp", 1}, {"getelementptr", 1}, 76 | {"br", 2}, {"switch", 2}, {"store", 2}, {"phi", 3}}; 77 | 78 | public: 79 | LivenessAnalysis(LivenessInfo & bottom, LivenessInfo & initialState) : 80 | DataFlowAnalysis(bottom, initialState) {} 81 | 82 | void flowfunction(Instruction * I, std::vector & IncomingEdges, 83 | std::vector & OutgoingEdges, 84 | std::vector & Infos) { 85 | string opName = I->getOpcodeName(); 86 | 87 | // Get category of this instruction 88 | int category = opToCategory.count(opName) ? opToCategory[opName] : 2; 89 | category = I->isBinaryOp() ? 1 : category; 90 | 91 | std::map edgeToInfo = getEdgeToInfo(); 92 | map instrToIndex = getInstrToIndex(); 93 | map indexToInstr = getIndexToInstr(); 94 | 95 | set operands; 96 | unsigned instrIdx = instrToIndex[I]; 97 | LivenessInfo * outInfo = new LivenessInfo(); 98 | 99 | for (unsigned i = 0; i < I->getNumOperands(); ++i) { 100 | Instruction *instr = (Instruction *) I->getOperand(i); 101 | 102 | if (instrToIndex.count(instr) != 0) 103 | operands.insert(instrToIndex[instr]); 104 | } 105 | 106 | // Join all incoming infos 107 | for (size_t i = 0; i < IncomingEdges.size(); ++i) { 108 | Edge inEdge = make_pair(IncomingEdges[i], instrIdx); 109 | LivenessInfo::join(outInfo, edgeToInfo[inEdge], outInfo); 110 | } 111 | 112 | if (category == 1) { 113 | set index = {instrIdx}; 114 | 115 | LivenessInfo::join(outInfo, new LivenessInfo(operands), outInfo); 116 | LivenessInfo::remove(outInfo, new LivenessInfo(index), outInfo); 117 | 118 | // Distribute result to outgoing edges 119 | for (size_t i = 0; i < OutgoingEdges.size(); ++i) 120 | Infos.push_back(outInfo); 121 | } 122 | 123 | else if (category == 2) { 124 | LivenessInfo::join(outInfo, new LivenessInfo(operands), outInfo); 125 | 126 | // Distribute result to outgoing edges 127 | for (size_t i = 0; i < OutgoingEdges.size(); ++i) 128 | Infos.push_back(outInfo); 129 | } 130 | 131 | else { 132 | set index; 133 | Instruction * firstNonPhi = I->getParent()->getFirstNonPHI(); 134 | unsigned firstNonPhiIdx = instrToIndex[firstNonPhi]; 135 | 136 | for (unsigned i = instrIdx; i < firstNonPhiIdx; ++i) 137 | index.insert(i); 138 | 139 | LivenessInfo::remove(outInfo, new LivenessInfo(index), outInfo); 140 | 141 | // Handle each output respectively 142 | for (unsigned k = 0; k < OutgoingEdges.size(); ++k) { 143 | set operand; 144 | LivenessInfo *out_k = new LivenessInfo(); 145 | 146 | for (unsigned i = instrIdx; i < firstNonPhiIdx; ++i) { 147 | Instruction *instr = indexToInstr[i]; 148 | 149 | for (unsigned j = 0; j < instr->getNumOperands(); ++j) { 150 | Instruction *opInstr = (Instruction *) instr->getOperand(j); 151 | 152 | if (instrToIndex.count(opInstr) == 0) 153 | continue; 154 | 155 | // When label_k == label_ij, update out[k] 156 | if (opInstr->getParent() == indexToInstr[OutgoingEdges[k]]->getParent()) { 157 | operand.insert(instrToIndex[opInstr]); 158 | break; 159 | } 160 | } 161 | } 162 | LivenessInfo::join(outInfo, new LivenessInfo(operand), out_k); 163 | Infos.push_back(out_k); 164 | } 165 | } 166 | } 167 | }; 168 | 169 | 170 | namespace { 171 | struct LivenessAnalysisPass : public FunctionPass { 172 | static char ID; 173 | LivenessAnalysisPass() : FunctionPass(ID) {} 174 | 175 | bool runOnFunction(Function &F) override { 176 | LivenessInfo bottom; 177 | LivenessInfo initialState; 178 | LivenessAnalysis * rda = new LivenessAnalysis(bottom, initialState); 179 | 180 | rda->runWorklistAlgorithm(&F); 181 | rda->print(); 182 | 183 | return false; 184 | } 185 | }; // end of struct LivenessAnalysisPass 186 | } // end of anonymous namespace 187 | 188 | char LivenessAnalysisPass::ID = 0; 189 | static RegisterPass X("cse231-liveness", "Do liveness analysis on DFA CFG", 190 | false /* Only looks at CFG */, 191 | false /* Analysis Pass */); 192 | -------------------------------------------------------------------------------- /Passes/DFA/MayPointToAnalysis.cpp: -------------------------------------------------------------------------------- 1 | //Wenbin Zhu A53211044 2 | #include "231DFA.h" 3 | #include "llvm/Pass.h" 4 | #include "llvm/IR/Function.h" 5 | #include "llvm/Support/raw_ostream.h" 6 | 7 | using namespace llvm; 8 | using namespace std; 9 | 10 | class MayPointToInfo : public Info { 11 | private: 12 | map, set> infoMap; 13 | 14 | public: 15 | MayPointToInfo() {} 16 | 17 | MayPointToInfo(map, set> m) { 18 | infoMap = m; 19 | } 20 | 21 | // getter and setter 22 | map, set> getInfoMap() { 23 | return infoMap; 24 | } 25 | 26 | set getMemSet(pair key) { 27 | return infoMap[key]; 28 | } 29 | 30 | void setInfoMap(map, set> m) { 31 | infoMap = m; 32 | } 33 | 34 | void print() { 35 | for (auto ri = infoMap.begin(); ri != infoMap.end(); ++ri) { 36 | if (ri->second.size() == 0) 37 | continue; 38 | 39 | errs() << (char) toupper(ri->first.first) << ri->first.second << "->("; 40 | 41 | for (auto mi = ri->second.begin(); mi != ri->second.end(); ++mi) { 42 | errs() << "M" << *mi << "/"; 43 | } 44 | errs() << ")|"; 45 | } 46 | errs() << "\n"; 47 | } 48 | 49 | static bool equals(MayPointToInfo * info1, MayPointToInfo * info2) { 50 | return info1->getInfoMap() == info2->getInfoMap(); 51 | } 52 | 53 | static MayPointToInfo* join(MayPointToInfo * info1, MayPointToInfo * info2, MayPointToInfo * result) { 54 | map, set> retMap = info1->getInfoMap(); 55 | map, set> info2Map = info2->getInfoMap(); 56 | 57 | for (auto it = info2Map.begin(); it != info2Map.end(); ++it) { 58 | retMap[make_pair(it->first.first, it->first.second)].insert(it->second.begin(), it->second.end()); 59 | } 60 | 61 | result->setInfoMap(retMap); 62 | 63 | return nullptr; 64 | } 65 | }; 66 | 67 | 68 | class MayPointToAnalysis : public DataFlowAnalysis { 69 | private: 70 | typedef pair Edge; 71 | const char R = 'R'; 72 | const char M = 'm'; 73 | 74 | public: 75 | MayPointToAnalysis(MayPointToInfo & bottom, MayPointToInfo & initialState) : 76 | DataFlowAnalysis(bottom, initialState) {} 77 | 78 | void flowfunction(Instruction * I, std::vector & IncomingEdges, 79 | std::vector & OutgoingEdges, 80 | std::vector & Infos) { 81 | 82 | string opName = I->getOpcodeName(); 83 | map edgeToInfo = getEdgeToInfo(); 84 | map instrToIndex = getInstrToIndex(); 85 | map indexToInstr = getIndexToInstr(); 86 | 87 | unsigned instrIdx = instrToIndex[I]; 88 | MayPointToInfo * inInfo = new MayPointToInfo(); 89 | MayPointToInfo * outInfo = new MayPointToInfo(); 90 | map, set> rmMap; 91 | 92 | // Join all incoming infos 93 | for (size_t i = 0; i < IncomingEdges.size(); ++i) { 94 | Edge inEdge = make_pair(IncomingEdges[i], instrIdx); 95 | MayPointToInfo::join(inInfo, edgeToInfo[inEdge], inInfo); 96 | MayPointToInfo::join(outInfo, edgeToInfo[inEdge], outInfo); 97 | } 98 | 99 | if (isa(I)) { 100 | rmMap[make_pair(R, instrIdx)].insert(instrIdx); 101 | MayPointToInfo::join(outInfo, new MayPointToInfo(rmMap), outInfo); 102 | } 103 | 104 | else if (isa(I)) { 105 | unsigned rv = instrToIndex[(Instruction *) I->getOperand(0)]; 106 | set X = inInfo->getMemSet(make_pair(R, rv)); 107 | 108 | rmMap[make_pair(R, instrIdx)].insert(X.begin(), X.end()); 109 | MayPointToInfo::join(outInfo, new MayPointToInfo(rmMap), outInfo); 110 | } 111 | 112 | else if (isa(I)) { 113 | GetElementPtrInst * instr = cast (I); 114 | unsigned rp = instrToIndex[(Instruction *) instr->getPointerOperand()]; 115 | set X = inInfo->getMemSet(make_pair(R, rp)); 116 | 117 | rmMap[make_pair(R, instrIdx)].insert(X.begin(), X.end()); 118 | MayPointToInfo::join(outInfo, new MayPointToInfo(rmMap), outInfo); 119 | } 120 | 121 | else if (isa(I)) { 122 | if (I->getType()->isPointerTy()) { 123 | LoadInst * instr = cast (I); 124 | unsigned rp = instrToIndex[(Instruction *) instr->getPointerOperand()]; 125 | set X = inInfo->getMemSet(make_pair(R, rp)); 126 | set Y; 127 | 128 | for (auto it = X.begin(); it != X.end(); ++it) { 129 | set s = inInfo->getMemSet(make_pair(M, *it)); 130 | Y.insert(s.begin(), s.end()); 131 | } 132 | 133 | rmMap[make_pair(R, instrIdx)].insert(Y.begin(), Y.end()); 134 | MayPointToInfo::join(outInfo, new MayPointToInfo(rmMap), outInfo); 135 | } 136 | } 137 | 138 | else if (isa(I)) { 139 | StoreInst * instr = cast (I); 140 | unsigned rv = instrToIndex[(Instruction *) instr->getValueOperand()]; 141 | unsigned rp = instrToIndex[(Instruction *) instr->getPointerOperand()]; 142 | set X = inInfo->getMemSet(make_pair(R, rv)); 143 | set Y = inInfo->getMemSet(make_pair(R, rp)); 144 | 145 | for (auto xi = X.begin(); xi != X.end(); ++xi) { 146 | for (auto yi = Y.begin(); yi != Y.end(); ++yi) { 147 | rmMap[make_pair(M, *yi)].insert(*xi); 148 | } 149 | } 150 | 151 | MayPointToInfo::join(outInfo, new MayPointToInfo(rmMap), outInfo); 152 | } 153 | 154 | else if (isa(I)) { 155 | SelectInst * instr = cast (I); 156 | unsigned r1 = instrToIndex[(Instruction *) instr->getTrueValue()]; 157 | unsigned r2 = instrToIndex[(Instruction *) instr->getFalseValue()]; 158 | set X = inInfo->getMemSet(make_pair(R, r1)); 159 | set Y = inInfo->getMemSet(make_pair(R, r2)); 160 | 161 | rmMap[make_pair(R, instrIdx)].insert(X.begin(), X.end()); 162 | rmMap[make_pair(R, instrIdx)].insert(Y.begin(), Y.end()); 163 | MayPointToInfo::join(outInfo, new MayPointToInfo(rmMap), outInfo); 164 | } 165 | 166 | else if (isa(I)) { 167 | Instruction * firstNonPhi = I->getParent()->getFirstNonPHI(); 168 | unsigned firstNonPhiIdx = instrToIndex[firstNonPhi]; 169 | 170 | for (unsigned i = instrIdx; i < firstNonPhiIdx; ++i) { 171 | Instruction *instr = indexToInstr[i]; 172 | 173 | for (unsigned j = 0; j < instr->getNumOperands(); ++j) { 174 | unsigned rv = instrToIndex[(Instruction *) instr->getOperand(j)]; 175 | set X = inInfo->getMemSet(make_pair(R, rv)); 176 | rmMap[make_pair(R, i)].insert(X.begin(), X.end()); 177 | } 178 | } 179 | 180 | MayPointToInfo::join(outInfo, new MayPointToInfo(rmMap), outInfo); 181 | } 182 | 183 | // Distribute result to outgoing edges 184 | for (size_t i = 0; i < OutgoingEdges.size(); ++i) 185 | Infos.push_back(outInfo); 186 | } 187 | }; 188 | 189 | 190 | namespace { 191 | struct MayPointToAnalysisPass : public FunctionPass { 192 | static char ID; 193 | MayPointToAnalysisPass() : FunctionPass(ID) {} 194 | 195 | bool runOnFunction(Function &F) override { 196 | MayPointToInfo bottom; 197 | MayPointToInfo initialState; 198 | MayPointToAnalysis * rda = new MayPointToAnalysis(bottom, initialState); 199 | 200 | rda->runWorklistAlgorithm(&F); 201 | rda->print(); 202 | 203 | return false; 204 | } 205 | }; // end of struct MayPointToAnalysisPass 206 | } // end of anonymous namespace 207 | 208 | char MayPointToAnalysisPass::ID = 0; 209 | static RegisterPass X("cse231-maypointto", "Do maypointto analysis on DFA CFG", 210 | false /* Only looks at CFG */, 211 | false /* Analysis Pass */); 212 | -------------------------------------------------------------------------------- /Passes/DFA/ReachingDefinitionAnalysis.cpp: -------------------------------------------------------------------------------- 1 | //Wenbin Zhu A53211044 2 | #include "231DFA.h" 3 | #include "llvm/Pass.h" 4 | #include "llvm/IR/Function.h" 5 | #include "llvm/Support/raw_ostream.h" 6 | 7 | using namespace llvm; 8 | using namespace std; 9 | 10 | class ReachingInfo : public Info { 11 | private: 12 | set infoSet; 13 | 14 | public: 15 | ReachingInfo() {} 16 | 17 | ReachingInfo(set s) { 18 | infoSet = s; 19 | } 20 | 21 | // getter and setter 22 | set & getInfoSet() { 23 | return infoSet; 24 | } 25 | 26 | void setInfoSet(set s) { 27 | infoSet = s; 28 | } 29 | 30 | void print() { 31 | for (auto it = infoSet.begin(); it != infoSet.end(); ++it) { 32 | errs() << *it << '|'; 33 | } 34 | 35 | errs() << '\n'; 36 | } 37 | 38 | static bool equals(ReachingInfo * info1, ReachingInfo * info2) { 39 | return info1->getInfoSet() == info2->getInfoSet(); 40 | } 41 | 42 | static ReachingInfo* join(ReachingInfo * info1, ReachingInfo * info2, ReachingInfo * result) { 43 | set retSet = info1->getInfoSet(); 44 | set info2Set = info2->getInfoSet(); 45 | 46 | for (auto it = info2Set.begin(); it != info2Set.end(); ++it) { 47 | retSet.insert(*it); 48 | } 49 | 50 | result->setInfoSet(retSet); 51 | 52 | return nullptr; 53 | } 54 | }; 55 | 56 | 57 | class ReachingDefinitionAnalysis : public DataFlowAnalysis { 58 | private: 59 | typedef pair Edge; 60 | map EdgeToInfo; 61 | map opToCategory = {{"alloca", 1}, {"load", 1}, {"select", 1}, 62 | {"icmp", 1}, {"fcmp", 1}, {"getelementptr", 1}, 63 | {"br", 2}, {"switch", 2}, {"store", 2}, {"phi", 3}}; 64 | 65 | public: 66 | ReachingDefinitionAnalysis(ReachingInfo & bottom, ReachingInfo & initialState) : 67 | DataFlowAnalysis(bottom, initialState) {} 68 | 69 | void flowfunction(Instruction * I, std::vector & IncomingEdges, 70 | std::vector & OutgoingEdges, 71 | std::vector & Infos) { 72 | 73 | string opName = I->getOpcodeName(); 74 | 75 | // Get category of this instruction 76 | int category = opToCategory.count(opName) ? opToCategory[opName] : 2; 77 | category = I->isBinaryOp() ? 1 : category; 78 | unsigned instrIdx = getInstrToIndex()[I]; 79 | 80 | std::map edgeToInfo = getEdgeToInfo(); 81 | ReachingInfo * outInfo = new ReachingInfo(); 82 | 83 | // Join all incoming infos 84 | for (size_t i = 0; i < IncomingEdges.size(); ++i) { 85 | Edge inEdge = make_pair(IncomingEdges[i], instrIdx); 86 | ReachingInfo::join(outInfo, edgeToInfo[inEdge], outInfo); 87 | } 88 | 89 | // Join index/indices for category 1 and 3 90 | if (category == 1) { 91 | set current = {instrIdx}; 92 | ReachingInfo::join(outInfo, new ReachingInfo(current), outInfo); 93 | } 94 | 95 | else if (category == 3) { 96 | Instruction * firstNonPhi = I->getParent()->getFirstNonPHI(); 97 | unsigned firstNonPhiIdx = getInstrToIndex()[firstNonPhi]; 98 | set current; 99 | 100 | for (unsigned i = instrIdx; i < firstNonPhiIdx; ++i) { 101 | current.insert(i); 102 | } 103 | 104 | ReachingInfo::join(outInfo, new ReachingInfo(current), outInfo); 105 | } 106 | 107 | // Distribute result to outgoing edges 108 | for (size_t i = 0; i < OutgoingEdges.size(); ++i) 109 | Infos.push_back(outInfo); 110 | } 111 | }; 112 | 113 | 114 | namespace { 115 | struct ReachingDefinitionAnalysisPass : public FunctionPass { 116 | static char ID; 117 | ReachingDefinitionAnalysisPass() : FunctionPass(ID) {} 118 | 119 | bool runOnFunction(Function &F) override { 120 | ReachingInfo bottom; 121 | ReachingInfo initialState; 122 | ReachingDefinitionAnalysis * rda = new ReachingDefinitionAnalysis(bottom, initialState); 123 | 124 | rda->runWorklistAlgorithm(&F); 125 | rda->print(); 126 | 127 | return false; 128 | } 129 | }; // end of struct ReachingDefinitionAnalysisPass 130 | } // end of anonymous namespace 131 | 132 | char ReachingDefinitionAnalysisPass::ID = 0; 133 | static RegisterPass X("cse231-reaching", "Do reaching definition on CFG", 134 | false /* Only looks at CFG */, 135 | false /* Analysis Pass */); 136 | -------------------------------------------------------------------------------- /Passes/part1/BranchBias.cpp: -------------------------------------------------------------------------------- 1 | // Wenbin Zhu A53211044 2 | #include "llvm/Pass.h" 3 | #include "llvm/IR/Type.h" 4 | #include "llvm/IR/Value.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/Function.h" 7 | #include "llvm/IR/IRBuilder.h" 8 | #include "llvm/IR/BasicBlock.h" 9 | #include "llvm/IR/Instruction.h" 10 | #include "llvm/IR/LLVMContext.h" 11 | #include "llvm/Support/raw_ostream.h" 12 | 13 | using namespace llvm; 14 | using namespace std; 15 | 16 | namespace { 17 | struct BranchBias : public FunctionPass { 18 | static char ID; 19 | BranchBias() : FunctionPass(ID) {} 20 | 21 | bool runOnFunction(Function &F) override { 22 | Module *M = F.getParent(); 23 | LLVMContext &Context = M->getContext(); 24 | 25 | Function *update_func = dyn_cast(M->getOrInsertFunction("updateBranchInfo", Type::getVoidTy(Context), Type::getInt1Ty(Context), NULL)); 26 | Function *print_func = dyn_cast(M->getOrInsertFunction("printOutBranchInfo", Type::getVoidTy(Context), NULL)); 27 | 28 | // Iterate over all basic blocks 29 | for (Function::iterator blk = F.begin(), blk_end = F.end(); blk != blk_end; ++blk) { 30 | IRBuilder<> Builder(&*blk); 31 | Builder.SetInsertPoint(blk->getTerminator()); 32 | 33 | // Branch must be at the end of a basic block 34 | BranchInst *branch_inst = dyn_cast(blk->getTerminator()); 35 | 36 | if (branch_inst != NULL && branch_inst->isConditional()) { 37 | vector args; 38 | args.push_back(branch_inst->getCondition()); 39 | 40 | Builder.CreateCall(update_func, args); 41 | } 42 | 43 | for (BasicBlock::iterator ist = blk->begin(), end = blk->end(); ist != end; ++ist) { 44 | if ((string) ist->getOpcodeName() == "ret") { 45 | Builder.SetInsertPoint(&*ist); 46 | Builder.CreateCall(print_func); 47 | } 48 | } 49 | } 50 | 51 | return false; 52 | } 53 | }; // end of struct TestPass 54 | } // end of anonymous namespace 55 | 56 | char BranchBias::ID = 0; 57 | static RegisterPass X("cse231-bb", "Compute Branch Bias", 58 | false /* Only looks at CFG */, 59 | false /* Analysis Pass */); 60 | -------------------------------------------------------------------------------- /Passes/part1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Just leave this file empty 2 | -------------------------------------------------------------------------------- /Passes/part1/CountDynamicInstructions.cpp: -------------------------------------------------------------------------------- 1 | // Wenbin Zhu A53211044 2 | #include "llvm/Pass.h" 3 | #include "llvm/IR/Type.h" 4 | #include "llvm/IR/Value.h" 5 | #include "llvm/IR/Module.h" 6 | #include "llvm/IR/Function.h" 7 | #include "llvm/IR/Constants.h" 8 | #include "llvm/IR/IRBuilder.h" 9 | #include "llvm/IR/BasicBlock.h" 10 | #include "llvm/IR/Instruction.h" 11 | #include "llvm/IR/LLVMContext.h" 12 | #include "llvm/Support/raw_ostream.h" 13 | 14 | #include 15 | #include 16 | 17 | using namespace llvm; 18 | using namespace std; 19 | 20 | namespace { 21 | struct CountDynamicInstructions : public FunctionPass { 22 | static char ID; 23 | CountDynamicInstructions() : FunctionPass(ID) {} 24 | 25 | bool runOnFunction(Function &F) override { 26 | Module *M = F.getParent(); 27 | LLVMContext &Context = M->getContext(); 28 | 29 | Function *update_func = dyn_cast(M->getOrInsertFunction("updateInstrInfo", Type::getVoidTy(Context), 30 | Type::getInt32Ty(Context), Type::getInt32PtrTy(Context), Type::getInt32PtrTy(Context), NULL)); 31 | Function *print_func = dyn_cast(M->getOrInsertFunction("printOutInstrInfo", Type::getVoidTy(Context), NULL)); 32 | 33 | // Iterate over all basic blocks 34 | for (Function::iterator blk = F.begin(), blk_end = F.end(); blk != blk_end; ++blk) { 35 | // errs() << "Block " << blk->size() << "\n"; 36 | map op_counter; 37 | 38 | // Iterate over all instructions in a basic block 39 | for (BasicBlock::iterator ist = blk->begin(), end = blk->end(); ist != end; ++ist) { 40 | ++op_counter[ist->getOpcode()]; 41 | } 42 | 43 | // Insert updateInstrInfo at the end of each basic block 44 | IRBuilder<> Builder(&*blk); 45 | Builder.SetInsertPoint(blk->getTerminator()); 46 | 47 | int num = op_counter.size(); 48 | vector args; 49 | vector keys; 50 | vector values; 51 | 52 | for (map::iterator it = op_counter.begin(), end = op_counter.end(); it != end; ++it) { 53 | keys.push_back(ConstantInt::get(Type::getInt32Ty(Context), it->first)); 54 | values.push_back(ConstantInt::get(Type::getInt32Ty(Context), it->second)); 55 | } 56 | 57 | ArrayType *array_type = ArrayType::get(Type::getInt32Ty(Context), num); 58 | Value* idx_list[2] = {ConstantInt::get(Type::getInt32Ty(Context), 0), ConstantInt::get(Type::getInt32Ty(Context), 0)}; 59 | 60 | GlobalVariable *keys_global = new GlobalVariable(*M, array_type, true, 61 | GlobalVariable::InternalLinkage, ConstantArray::get(array_type, keys), "key_global"); 62 | GlobalVariable *values_global = new GlobalVariable(*M, ArrayType::get(Type::getInt32Ty(Context), num), true, 63 | GlobalVariable::InternalLinkage, ConstantArray::get(array_type, values), "value_global"); 64 | 65 | 66 | args.push_back(ConstantInt::get(Type::getInt32Ty(Context), num)); 67 | args.push_back(Builder.CreateInBoundsGEP(keys_global, idx_list)); 68 | args.push_back(Builder.CreateInBoundsGEP(values_global, idx_list)); 69 | 70 | Builder.CreateCall(update_func, args); 71 | 72 | for (BasicBlock::iterator ist = blk->begin(), end = blk->end(); ist != end; ++ist) { 73 | if ((string) ist->getOpcodeName() == "ret") { 74 | Builder.SetInsertPoint(&*ist); 75 | Builder.CreateCall(print_func); 76 | } 77 | } 78 | } 79 | 80 | return false; 81 | } 82 | }; // end of struct TestPass 83 | } // end of anonymous namespace 84 | 85 | char CountDynamicInstructions::ID = 0; 86 | static RegisterPass X("cse231-cdi", "Count Dynamic Instructions", 87 | false /* Only looks at CFG */, 88 | false /* Analysis Pass */); 89 | -------------------------------------------------------------------------------- /Passes/part1/CountStaticInstructions.cpp: -------------------------------------------------------------------------------- 1 | // Wenbin Zhu A53211044 2 | #include "llvm/Pass.h" 3 | #include "llvm/IR/Function.h" 4 | #include "llvm/IR/InstIterator.h" 5 | #include "llvm/Support/raw_ostream.h" 6 | 7 | #include 8 | 9 | using namespace llvm; 10 | using namespace std; 11 | 12 | namespace { 13 | struct CountStaticInstructions : public FunctionPass { 14 | static char ID; 15 | CountStaticInstructions() : FunctionPass(ID) {} 16 | 17 | bool runOnFunction(Function &F) override { 18 | map op_counter; 19 | 20 | // errs() << "Function: " << F.getName() << '\n'; 21 | 22 | for (inst_iterator it = inst_begin(F), end = inst_end(F); it != end; ++it) { 23 | ++op_counter[it->getOpcodeName()]; 24 | } 25 | 26 | for (map::iterator it = op_counter.begin(), end = op_counter.end(); it != end; ++it) { 27 | errs() << it->first << '\t' << it->second << '\n'; 28 | } 29 | 30 | return false; 31 | } 32 | }; // end of struct TestPass 33 | } // end of anonymous namespace 34 | 35 | char CountStaticInstructions::ID = 0; 36 | static RegisterPass X("cse231-csi", "Count Static Instructions", 37 | false /* Only looks at CFG */, 38 | false /* Analysis Pass */); 39 | -------------------------------------------------------------------------------- /Passes/testPass/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenbinZhu/CSE231-LLVM-Project/2d78bcbba6fad743661227dac0acce57fa1a6af2/Passes/testPass/.DS_Store -------------------------------------------------------------------------------- /Passes/testPass/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_llvm_loadable_module( LLVMTestPass 2 | TestPass.cpp 3 | 4 | PLUGIN_TOOL 5 | opt 6 | ) 7 | -------------------------------------------------------------------------------- /Passes/testPass/TestPass.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/Pass.h" 2 | #include "llvm/IR/Function.h" 3 | #include "llvm/Support/raw_ostream.h" 4 | 5 | using namespace llvm; 6 | 7 | namespace { 8 | struct TestPass : public FunctionPass { 9 | static char ID; 10 | TestPass() : FunctionPass(ID) {} 11 | 12 | bool runOnFunction(Function &F) override { 13 | errs() << "Hello: "; 14 | errs().write_escaped(F.getName()) << '\n'; 15 | return false; 16 | } 17 | }; // end of struct TestPass 18 | } // end of anonymous namespace 19 | 20 | char TestPass::ID = 0; 21 | static RegisterPass X("TestPass", "Developed to test LLVM and docker", 22 | false /* Only looks at CFG */, 23 | false /* Analysis Pass */); 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSE231-LLVM-Project 2 | UCSD CSE231 Advanced Compiler - LLVM project 3 | -------------------------------------------------------------------------------- /Tests/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenbinZhu/CSE231-LLVM-Project/2d78bcbba6fad743661227dac0acce57fa1a6af2/Tests/.DS_Store -------------------------------------------------------------------------------- /Tests/HelloWorld/HelloWorld.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main () { 6 | int var = 1; 7 | 8 | for (int i = 0; i < 5; i++) { 9 | if (var % 2 == 0) 10 | var++; 11 | } 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /Tests/run.sh: -------------------------------------------------------------------------------- 1 | cd /tests/ 2 | clang++ -c -O0 -emit-llvm test.cpp -o test.bc 3 | clang++ -c -O0 -emit-llvm lib231.cpp -o lib231.bc 4 | cd /LLVM_ROOT/build/lib/Transforms/CSE231_Project/ 5 | make 6 | opt -load /LLVM_ROOT/build/lib/CSE231.so -cse231-cdi < /tests/test.bc -o /tests/test_instrument.bc 7 | cd /tests/ 8 | llvm-link lib231.bc test_instrument.bc -o final.bc 9 | llc -filetype=obj final.bc -o final.o 10 | clang++ final.o -o final 11 | ./final 12 | -------------------------------------------------------------------------------- /Tests/test-dataflow/fib.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenbinZhu/CSE231-LLVM-Project/2d78bcbba6fad743661227dac0acce57fa1a6af2/Tests/test-dataflow/fib.bc -------------------------------------------------------------------------------- /Tests/test-dataflow/fib.c: -------------------------------------------------------------------------------- 1 | int calc_fib(int f) { 2 | if (f==0) return 1; 3 | if (f==1) return 1; 4 | 5 | int fibo = 1; 6 | int prevFibo = 1; 7 | for (int i=2; i<=f; i++) { 8 | int temp = fibo; 9 | fibo += prevFibo; 10 | prevFibo = temp; 11 | 12 | } 13 | 14 | return fibo; 15 | } -------------------------------------------------------------------------------- /Tests/test-dataflow/fib.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'fib.bc' 2 | source_filename = "fib.c" 3 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 4 | target triple = "x86_64-unknown-linux-gnu" 5 | 6 | ; Function Attrs: norecurse nounwind readnone uwtable 7 | define i32 @calc_fib(i32) local_unnamed_addr #0 { 8 | %2 = icmp ult i32 %0, 2 9 | %3 = icmp slt i32 %0, 2 10 | %4 = or i1 %2, %3 11 | br i1 %4, label %12, label %5 12 | 13 | ;