├── mem-tracing ├── macpo │ ├── source-me │ ├── macpo │ ├── Makefile │ ├── bar.c │ └── rose_bar.c └── valgrind │ ├── Makefile │ ├── bar.c │ └── code.c ├── spring2014-compilers ├── assignment1 │ ├── prog1.pdf │ ├── Makefile │ ├── loop.c │ ├── README.md │ └── ModuleInfo.cpp ├── assignment2 │ ├── FunctionInfo │ │ ├── stack.bc │ │ ├── Makefile │ │ ├── test-files │ │ │ └── stack.c │ │ └── FunctionInfo.cpp │ └── LocalOpts │ │ ├── Makefile │ │ ├── inputFiles │ │ ├── constfold.c │ │ ├── strength.c │ │ └── algebraic.c │ │ ├── run │ │ ├── generic_methods.h │ │ ├── constfold-out.ll │ │ ├── algebraic-out.ll │ │ ├── test-files │ │ └── stack.c │ │ ├── strength-out.ll │ │ ├── notes.md │ │ └── LocalOpts.cpp ├── assignment3 │ ├── sum.c │ ├── Makefile │ ├── run │ ├── liveness_results_sum │ ├── reaching_results_sum │ ├── liveness_results_sum_loop │ ├── dataflow.h │ ├── reach.cpp │ └── live.cpp ├── llvm-stuff │ ├── Makefile │ ├── loop.c │ └── FunctionInfo.cpp ├── assignment4 │ ├── benchmarks │ │ ├── test1.cpp │ │ ├── li_test_2.cpp │ │ ├── dce_test1.cpp │ │ ├── li_test_1.cpp │ │ └── benchmarks.txt │ ├── run │ ├── Makefile │ ├── dataflow.h │ ├── sum.c │ ├── sum-huge.c │ ├── dce-pass.cpp │ ├── licm-backout.cpp │ └── licm.cpp └── notes │ ├── notes.md │ └── compiler_notes.md ├── basic-compiler-notes ├── compiler_notes_8.md ├── compiler_notes_4.md ├── compiler_notes_5.md ├── compiler_notes_0.md ├── compiler_notes_7.md ├── compiler_notes_6.md ├── compiler_notes_3.md └── compiler_notes_1.md ├── .gitignore ├── x64_assembly.md ├── c ├── vectorization ├── vectorization_0.md ├── vectorization_1.md └── vectorization_2.md └── README.md /mem-tracing/macpo/source-me: -------------------------------------------------------------------------------- 1 | source /work/01174/ashay/apps/macpo-setup.sh 2 | -------------------------------------------------------------------------------- /mem-tracing/macpo/macpo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goyalankit/compilers-and-llvm/HEAD/mem-tracing/macpo/macpo -------------------------------------------------------------------------------- /spring2014-compilers/assignment1/prog1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goyalankit/compilers-and-llvm/HEAD/spring2014-compilers/assignment1/prog1.pdf -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/FunctionInfo/stack.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goyalankit/compilers-and-llvm/HEAD/spring2014-compilers/assignment2/FunctionInfo/stack.bc -------------------------------------------------------------------------------- /spring2014-compilers/assignment3/sum.c: -------------------------------------------------------------------------------- 1 | int sum (int a, int b) 2 | { 3 | int i; 4 | int res = 1; 5 | for (i = a; i < b; i++) 6 | { 7 | res *= i; 8 | } 9 | return res; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment1/Makefile: -------------------------------------------------------------------------------- 1 | all: ModuleInfo.so 2 | 3 | CXXFLAGS = -rdynamic $(shell llvm-config --cxxflags) -g -O0 4 | 5 | %.so: %.o 6 | $(CXX) -dylib -flat_namespace -shared $^ -o $@ 7 | clean: 8 | rm -f *.o *~ *.so 9 | -------------------------------------------------------------------------------- /spring2014-compilers/llvm-stuff/Makefile: -------------------------------------------------------------------------------- 1 | all: ModuleInfo.so 2 | 3 | CXXFLAGS = -rdynamic $(shell llvm-config --cxxflags) -g -O0 4 | 5 | %.so: %.o 6 | $(CXX) -dylib -flat_namespace -shared $^ -o $@ 7 | clean: 8 | rm -f *.o *~ *.so 9 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment3/Makefile: -------------------------------------------------------------------------------- 1 | all: live.so reach.so 2 | 3 | CXXFLAGS = -rdynamic $(shell llvm-config --cxxflags) -g -O0 4 | 5 | %.so: %.o 6 | $(CXX) -dylib -flat_namespace -shared $^ -o $@ 7 | clean: 8 | rm -f *.o *~ *.so 9 | -------------------------------------------------------------------------------- /mem-tracing/macpo/Makefile: -------------------------------------------------------------------------------- 1 | M=foo 2 | F=bar.c 3 | O=macpo 4 | 5 | all: macpo.out 6 | 7 | macpo: 8 | macpo.sh --macpo:gen-trace=$(M) $(F) -o $(O) 9 | 10 | macpo.out: macpo 11 | ./$(O) 12 | 13 | 14 | clean: 15 | rm -f rose_* *.o *.out $(O) 16 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/LocalOpts/Makefile: -------------------------------------------------------------------------------- 1 | all: LocalOpts.so 2 | 3 | CXXFLAGS = -rdynamic $(shell llvm-config --cxxflags) -g -O0 4 | 5 | %.so: %.o 6 | $(CXX) -dylib -flat_namespace -shared $^ -o $@ 7 | clean: 8 | rm -f *.o *~ *.so 9 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/FunctionInfo/Makefile: -------------------------------------------------------------------------------- 1 | all: FunctionInfo.so 2 | 3 | CXXFLAGS = -rdynamic $(shell llvm-config --cxxflags) -g -O0 4 | 5 | %.so: %.o 6 | $(CXX) -dylib -flat_namespace -shared $^ -o $@ 7 | clean: 8 | rm -f *.o *~ *.so 9 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment1/loop.c: -------------------------------------------------------------------------------- 1 | int g; 2 | int g_incr (int c) 3 | { 4 | g += c; 5 | } 6 | int loop (int a, int b, int c) 7 | { 8 | int i; 9 | int ret = 0; 10 | for (i = a; i < b; i++) { 11 | g_incr (c); 12 | } 13 | return ret + g; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /spring2014-compilers/llvm-stuff/loop.c: -------------------------------------------------------------------------------- 1 | int g; 2 | int g_incr (int c) 3 | { 4 | g += c; 5 | } 6 | int loop (int a, int b, int c) 7 | { 8 | int i; 9 | int ret = 0; 10 | for (i = a; i < b; i++) { 11 | g_incr (c); 12 | } 13 | return ret + g; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /mem-tracing/valgrind/Makefile: -------------------------------------------------------------------------------- 1 | S=code.c 2 | 3 | all: gleipnir 4 | 5 | code.out: 6 | gcc -g $(S) -o code.out 7 | 8 | gleipnir: code.out 9 | /work/02681/ankitg/workspace/valgrind/bin/valgrind --read-var-info=yes --tool=gleipnir ./code.out; 10 | 11 | clean: 12 | rm -f gleipnir* *.out 13 | -------------------------------------------------------------------------------- /basic-compiler-notes/compiler_notes_8.md: -------------------------------------------------------------------------------- 1 | ## Machine independent optimizations 2 | 3 | * Loop unrolling 4 | * Function inlining 5 | * Tail recursion removal 6 | * Vectorization 7 | * Loop interchange for parallelization 8 | * Loop blocking -> cache misses 9 | 10 | ## Data flow analysis 11 | 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | 15 | #llvm specific 16 | *.bc 17 | 18 | # Binaries 19 | *.out 20 | 21 | 22 | #temp 23 | mem-tracing/instrumentation/ 24 | 25 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/LocalOpts/inputFiles/constfold.c: -------------------------------------------------------------------------------- 1 | int compute () 2 | { 3 | int result = 0; 4 | int a = 2; 5 | int b = 3; 6 | int c = 4 + a + b; //c=9 7 | 8 | result += a; //res = 0 + 2 9 | result += b; //2 + 3 10 | result *= c; //5*9 11 | result /= 2; //45/2=22 12 | return result; 13 | } 14 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/LocalOpts/inputFiles/strength.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int compute (int a, int b) 4 | { 5 | int result = 0; 6 | 7 | result += a * 2; 8 | result += a * 3; 9 | result += a * 8; 10 | result -= b / 2; 11 | result -= b / 4; 12 | result -= b / 8; 13 | return result; 14 | } 15 | 16 | void main(){ 17 | printf("%d",compute(2,20)); 18 | } 19 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/LocalOpts/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | filename=$(basename "$1") 5 | extension="${filename##*.}" 6 | filename="${filename%.*}" 7 | 8 | clang -O0 -emit-llvm -c inputFiles/$1 9 | opt -mem2reg $filename.bc -o $filename-simp.bc 10 | opt -stats -load ./LocalOpts.so -my-local-opts $filename-simp.bc -o $filename-out.bc 11 | 12 | llvm-dis $filename-simp.bc 13 | llvm-dis $filename-out.bc 14 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment4/benchmarks/test1.cpp: -------------------------------------------------------------------------------- 1 | 2 | #define N 10000 3 | 4 | int loop(int a, int b){ 5 | int i; 6 | int inv; 7 | int c[N][N]; 8 | for(i=0; i historical reasons 11 | R8-R15 12 | ``` 13 | 14 | * Instruction pointer: RIP points to the next instruction to be executed 15 | * RSP points to the last item pushed onto the stack, which grows toward lower addresses. 16 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment3/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | filename=$(basename "$1") 4 | extension="${filename##*.}" 5 | filename="${filename%.*}" 6 | 7 | 8 | clang -O0 -emit-llvm -c $1 9 | opt -mem2reg $filename.bc -o $filename-simp.bc 10 | #opt -load ./live.so -live $filename.bc -o $filename-simp.bc 11 | opt -stats -load $2 -$3 $filename-simp.bc -o $filename-out.bc 12 | 13 | llvm-dis $filename-simp.bc 14 | llvm-dis $filename-out.bc 15 | -------------------------------------------------------------------------------- /mem-tracing/valgrind/bar.c: -------------------------------------------------------------------------------- 1 | #include "/work/02681/ankitg/workspace/valgrind/gleipnir/gleipnir.h" 2 | #include 3 | 4 | void foo(int b[10]){ 5 | int i; 6 | for(i=0; i< 10; i++) b[i] = 12; 7 | b[3] = 23; 8 | printf("hello %d",b[2]); 9 | } 10 | 11 | int main(void){ 12 | GL_START_INSTR; 13 | int a[10]; 14 | a[2] = 23; 15 | printf("%d", a[2]); 16 | foo(a); 17 | GL_STOP_INSTR; 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /mem-tracing/macpo/bar.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void foo(int b[100], int a[100]){ 4 | int i; 5 | for(i=99; i > 0; i--){ 6 | b[i] = 12; 7 | if(i-1 > 1) 8 | a[i] = 21 + b[i-1]; 9 | } 10 | b[3] = 23; 11 | printf("hello %d",b[2]); 12 | } 13 | 14 | int main(void){ 15 | int a[100]; 16 | int b[100]; 17 | a[2] = 23; 18 | printf("%d", a[2]); 19 | foo(a, b); 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment4/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | filename=$(basename "$1") 4 | extension="${filename##*.}" 5 | filename="${filename%.*}" 6 | 7 | 8 | clang -O0 -emit-llvm -c $1 9 | opt -mem2reg $filename.bc -o $filename-simp.bc 10 | #opt -load ./live.so -live $filename.bc -o $filename-simp.bc 11 | opt -stats -load ./dce-pass.so -dce-pass $filename-simp.bc -o $filename-out.bc 12 | 13 | llvm-dis $filename-simp.bc 14 | llvm-dis $filename-out.bc 15 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/LocalOpts/inputFiles/algebraic.c: -------------------------------------------------------------------------------- 1 | int compute (int a, int b) 2 | { 3 | int result = (a/a); //algebraic identity result = 1 4 | 5 | result *= (b/b); //algebraic identity result = 1 * 1 6 | result += (b-b); //algebraic identity result = 1 + 0 7 | result /= result; //algebraic identity result = 1 / 1 8 | result -= result; //algebraic identity result = 1 - 1 9 | result += 23; //constant folding 10 | return result; 11 | } 12 | -------------------------------------------------------------------------------- /c: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | 4 | VBM=VBoxManage 5 | VMID=8f8d7a7e-7aba-466f-a28f-3cf87100a58e 6 | start(){ 7 | $VBM startvm $VMID --type headless 8 | } 9 | 10 | stop() { 11 | $VBM controlvm $VMID poweroff 12 | } 13 | 14 | do_ssh(){ 15 | ssh -p 2022 user@localhost $1 16 | } 17 | 18 | case $1 in 19 | start | up) start;; 20 | pause | suspend) pause;; 21 | stop | halt | down) stop;; 22 | ssh) shift; do_ssh "$@";; 23 | *) echo "Usage $0 {start|up|stop|halt|ssh}"; exit 1 24 | esac 25 | -------------------------------------------------------------------------------- /basic-compiler-notes/compiler_notes_4.md: -------------------------------------------------------------------------------- 1 | **COOL**: Classroom Object Oriented Language 2 | 3 | Designed to be implementable in a short time. 4 | 5 | `COOL compilers >> COOL programs.` 6 | 7 | Sample cool program: 8 | ``` 9 | class Main { 10 | 11 | i : IO <- new IO; 12 | main():Int { { i.out_string("Hello World!"); 1; } }; 13 | 14 | }; 15 | 16 | 17 | ``` 18 | 19 | 20 |
← PreviousNext →
21 | -------------------------------------------------------------------------------- /basic-compiler-notes/compiler_notes_5.md: -------------------------------------------------------------------------------- 1 | ####Lexical Analysis#### 2 | 3 | * Partition the input string into **lexemes** 4 | * Identify the token of each lexeme. 5 | * Left to Right scan => Lookahead required sometimes. Languages try to minimize the amount of lookahead required. 6 | 7 | Example: 8 | 9 | C++ Template Syntax: `Foo` 10 | 11 | C++ Stream Syntax: `cin >> var;` 12 | 13 | Nested Templates: `Foo< Bar>` -> here compiler gets confused with `>>`. 14 | 15 | Solution: Insert a blank. `> >` 16 | 17 |
← PreviousNext →
18 | -------------------------------------------------------------------------------- /basic-compiler-notes/compiler_notes_0.md: -------------------------------------------------------------------------------- 1 | ####Lecture 1#### 2 | 3 | `Compiler`: Pre-processes the code -> executable + data -> run 4 | 5 | `Interpreter`: data + code -> run 6 | 7 | **Fortran** => *Formula Translation* -> First high level successful language 8 | 9 | Modern compilers still preserve the outline of Fortran. 10 | 11 | **Structure of Fortran:** 12 | 13 | 1. **Lexical Analysis** - *Syntactic* 14 | 2. **Parsing** - *Syntactic* 15 | 3. **Semantic Analysis** - *Typescope* 16 | 4. **Optimization** 17 | 5. **Code Generation** - *Translation* 18 | 19 |
← PreviousNext →
20 | -------------------------------------------------------------------------------- /basic-compiler-notes/compiler_notes_7.md: -------------------------------------------------------------------------------- 1 | ####Example of Regular Language#### 2 | 3 | ∑ = {0,1} 4 | 5 | `1* = "" + 1 + 11 + 111 + 1111` = all strings of 1 6 | 7 | `(1+0)1 = {ab | a E 1+0 ^ b E 1} = {11, 01}` 8 | 9 | `0* + 1* = {0^i | i ≥ 0} U {1^i | i≥0}` 10 | 11 | `(0+1)* = U_{i≥0} (0+1)^i = "", (0+1), (0+1)(0+1)` => all strings of 0s and 1s => ∑* 12 | 13 | 14 | * Regular Expressions specify regular languages 15 | * Five Constructs: 16 | * Two base cases: `empty and 1-character strings` 17 | * Three compound expressions: union, concatenation, iteration. 18 | 19 | 20 |
← PreviousNext →
-------------------------------------------------------------------------------- /spring2014-compilers/assignment2/LocalOpts/generic_methods.h: -------------------------------------------------------------------------------- 1 | using namespace llvm; 2 | 3 | namespace { 4 | /* Arbitrary precision constant values. To take care of both 32 bit and 64 bit numbers. */ 5 | template APType getZeroOne(unsigned num_bits, int zeroOne); 6 | template <> APInt getZeroOne(unsigned num_bits, int zeroOne) { return APInt(num_bits,zeroOne); } 7 | 8 | /* Compare value based on the type values to identify algebraic identities */ 9 | /* generalize compare method based on type */ 10 | template bool id_compare(ConstantType& cint, APType zero); 11 | template <> bool id_compare(ConstantInt& cint, APInt zero) { return cint.getValue().eq(zero); } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/LocalOpts/constfold-out.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'constfold-out.bc' 2 | target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" 3 | target triple = "i386-pc-linux-gnu" 4 | 5 | ; Function Attrs: nounwind 6 | define i32 @compute() #0 { 7 | entry: 8 | ret i32 22 9 | } 10 | 11 | attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 12 | 13 | !llvm.ident = !{!0} 14 | 15 | !0 = metadata !{metadata !"clang version 3.4 (tags/RELEASE_34/final)"} 16 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/LocalOpts/algebraic-out.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'algebraic-out.bc' 2 | target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" 3 | target triple = "i386-pc-linux-gnu" 4 | 5 | ; Function Attrs: nounwind 6 | define i32 @compute(i32 %a, i32 %b) #0 { 7 | entry: 8 | ret i32 23 9 | } 10 | 11 | attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 12 | 13 | !llvm.ident = !{!0} 14 | 15 | !0 = metadata !{metadata !"clang version 3.4 (tags/RELEASE_34/final)"} 16 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment4/Makefile: -------------------------------------------------------------------------------- 1 | all: licm.so dce-pass.so 2 | 3 | CXXFLAGS = -rdynamic $(shell llvm-config --cxxflags) -g -O0 4 | 5 | %.so: %.o 6 | $(CXX) -dylib -flat_namespace -shared $^ -o $@ 7 | 8 | clean: 9 | rm -f *.o *~ *.so 10 | 11 | run: sum-out.bc 12 | 13 | sum-simp.bc: sum.bc 14 | opt -mem2reg sum.bc -o sum-simp.bc 15 | 16 | sum.bc: sum.c 17 | clang -O0 -emit-llvm -c sum.c 18 | 19 | sum-out.bc: sum-simp.bc 20 | opt -stats -load ./licm.so -licm-pass sum-simp.bc -o sum-out.bc 21 | 22 | ll: sum-simp.ll sum-out.ll 23 | 24 | sum-simp.ll: sum-simp.bc 25 | llvm-dis sum-simp.bc 26 | 27 | sum-out.ll: sum-out.bc 28 | llvm-dis sum-out.bc 29 | 30 | 31 | clear: 32 | rm -f sum-out.bc sum-simp.bc sum-simp.ll sum-out.ll sum.bc 33 | 34 | nice: clean clear all run 35 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment4/benchmarks/li_test_2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main (int argc, char **argv) 5 | { 6 | clock_t begin, end; 7 | double time_spent; 8 | begin = clock(); 9 | int i, j; 10 | int result = 0; 11 | int e,a; 12 | a = 123; 13 | for (i = 0; ;i++) { 14 | for(j = 0; ; ++j) { 15 | int b =3; 16 | int c =767676; 17 | int d = 22525; 18 | e = (a << 12) * (b << 9) * (c << 10) * (d >> 6); 19 | 20 | if(j>200000) break; 21 | } 22 | 23 | result += e; 24 | if(i>100000) break; 25 | } 26 | end = clock(); 27 | time_spent = (double)(end - begin) / CLOCKS_PER_SEC; 28 | printf("Time taken: %f\n",time_spent); 29 | return result; 30 | } 31 | -------------------------------------------------------------------------------- /mem-tracing/valgrind/code.c: -------------------------------------------------------------------------------- 1 | #include "/work/02681/ankitg/workspace/valgrind/gleipnir/gleipnir.h" 2 | 3 | struct typeA{ 4 | double var1; 5 | int myArray[10]; 6 | }; 7 | 8 | struct typeA GlStrc; 9 | struct typeA glStrcArray[10]; 10 | 11 | int glScalar; 12 | int glArray[10]; 13 | 14 | void func(struct typeA StrcParam[]) 15 | { 16 | int i; 17 | 18 | for(i=0; i<3; i++){ 19 | glStrcArray[i].var1 = glScalar; 20 | glStrcArray[i].myArray[0] = glArray[0]; 21 | StrcParam[i].var1 = glArray[i]; 22 | } 23 | return; 24 | } 25 | 26 | int main(void) 27 | { 28 | GL_START_INSTR; 29 | 30 | struct typeA lcStrcArray[5]; 31 | int i, lcScalar, lcArray[10]; 32 | 33 | glScalar = 10; 34 | lcScalar = 20; 35 | 36 | for(i=0; i<2; i++) 37 | lcArray[i] = glScalar; 38 | 39 | func(lcStrcArray); 40 | 41 | GL_STOP_INSTR; 42 | 43 | return 0; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /mem-tracing/macpo/rose_bar.c: -------------------------------------------------------------------------------- 1 | void indigo__create_map(); 2 | #include 3 | #include "mrt.h" 4 | 5 | void foo(int b[100UL],int a[100UL]) 6 | { 7 | int i; 8 | for (i = 99; i > 0; i--) { 9 | indigo__gen_trace_c(2,6,b,((void *)(&b[i])),0); 10 | b[i] = 12; 11 | if ((i - 1) > 1) { 12 | indigo__gen_trace_c(2,8,a,((void *)(&a[i])),1); 13 | indigo__gen_trace_c(1,8,b,((void *)(&b[i - 1])),0); 14 | a[i] = (21 + b[i - 1]); 15 | } 16 | } 17 | indigo__gen_trace_c(2,10,b,((void *)(&b[3])),0); 18 | b[3] = 23; 19 | printf("hello %d",b[2]); 20 | } 21 | 22 | int main() 23 | { 24 | int a[100UL]; 25 | int b[100UL]; 26 | indigo__init_(1); 27 | indigo__create_map(); 28 | a[2] = 23; 29 | printf("%d",a[2]); 30 | foo(a,b); 31 | return 0; 32 | } 33 | 34 | void indigo__create_map() 35 | { 36 | indigo__write_idx_c("b",1); 37 | indigo__write_idx_c("a",1); 38 | } 39 | -------------------------------------------------------------------------------- /basic-compiler-notes/compiler_notes_6.md: -------------------------------------------------------------------------------- 1 | Regular Languages 2 | ================= 3 | 4 | set of strings belongs to token use regular languages. 5 | 6 | Use regular expressions to define regular languages. 7 | 8 | * Single character 9 | 10 | ` 'c' = {"c"} ` 11 | 12 | * Epsilon 13 | 14 | `E = { "" }` ≠ Empty 15 | 16 | * Union 17 | 18 | `A + B = {a| a E A} U {b| b E B}` 19 | 20 | * Concatenation 21 | 22 | `AB = {ab | a E A ^ b E B}` 23 | 24 | * Iteration 25 | 26 | `A* = U_{i>o} Ai` where Ai = A...A; A0 = "" 27 | 28 | **Definition:** The Regular Expressions over ∑ are the smallest set of expressions including 29 | 30 | Known as grammar. 31 | 32 | ``` 33 | R = E 34 | | 'c' where c E ∑ 35 | | 'R + R' 36 | | RR 37 | | R* 38 | ``` 39 | 40 | 41 |
← PreviousNext →
42 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment1/README.md: -------------------------------------------------------------------------------- 1 | ### Assignment 1 2 | 3 | The goal of this assignment is to familiarize you with the LLVM compiler by implementing a simple LLVM pass that outputs IR instructions followed by the source line number. 4 | 5 | Useful Links: 6 | * http://llvm.org/releases/3.4/docs/WritingAnLLVMPass.html 7 | * http://llvm.org/releases/3.4/docs/SourceLevelDebugging.html#c-c-front-end-specific-debug-information 8 | * http://llvm.org/doxygen/AssemblyAnnotationWriter_8h_source.html 9 | * http://llvm.org/doxygen/classllvm_1_1Module.html#aa711d8571cb8212a7693fd4465719c31 10 | 11 | 12 | Instructions to run the code: 13 | 14 | ``` 15 | make 16 | clang -c -g -emit-llvm loop.c 17 | opt -load ./ModuleInfo.so -module-info loop.bc > /dev/null 18 | ``` 19 | 20 | ``` 21 | Format Produced: 22 | < INSTRUCTION > ; source code line #: 1 23 | < INSTRUCTION > ; source code line #: 2 24 | < INSTRUCTION > ; source code line #: 6 25 | ``` 26 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment4/benchmarks/dce_test1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SIZE_ARRAY 200 5 | 6 | int faint (int x) 7 | { 8 | clock_t begin, end; 9 | double time_spent; 10 | begin = clock(); 11 | int i; 12 | int arr[SIZE_ARRAY]; 13 | int err[SIZE_ARRAY][SIZE_ARRAY]; 14 | int a = x + 1; 15 | 16 | for(i = 0; i < SIZE_ARRAY; ++i) { 17 | int b = a + 2; 18 | int c = b - 3; 19 | int d = b + c; 20 | int e = d * x; 21 | 22 | arr[i] = e; 23 | err[i][i] = b; 24 | 25 | } 26 | return x + a; 27 | } 28 | 29 | #define LOOP_COUNT 1000000 30 | 31 | int main (int argc, char **argv) 32 | { 33 | clock_t begin, end; 34 | double time_spent; 35 | begin = clock(); 36 | 37 | int i, j; 38 | int result = 0; 39 | printf ("Multiple Program \n"); 40 | for (i = 0; i < LOOP_COUNT; i++) { 41 | result += faint (2); 42 | } 43 | end = clock(); 44 | time_spent = (double)(end - begin) / CLOCKS_PER_SEC; 45 | printf("Time taken: %f\n",time_spent); 46 | return result; 47 | } 48 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment3/liveness_results_sum: -------------------------------------------------------------------------------- 1 | 2 | ; Function Attrs: nounwind 3 | define i32 @sum(i32 %a, i32 %b) #0 { 4 | entry: 5 | ; %a, %b, 6 | ; %a, %b, 7 | br label %for.cond 8 | 9 | for.cond: ; preds = %for.inc, %entry 10 | ; %a, %b, %mul, %inc, 11 | ; 12 | %i.0 = phi i32 [ %a, %entry ], [ %inc, %for.inc ] 13 | ; 14 | %res.0 = phi i32 [ 1, %entry ], [ %mul, %for.inc ] 15 | ; %b, %i.0, %res.0, 16 | %cmp = icmp slt i32 %i.0, %b 17 | ; %b, %i.0, %res.0, %cmp, 18 | br i1 %cmp, label %for.body, label %for.end 19 | 20 | for.body: ; preds = %for.cond 21 | ; %b, %i.0, %res.0, 22 | ; %b, %i.0, %res.0, 23 | %mul = mul nsw i32 %res.0, %i.0 24 | ; %b, %i.0, %mul, 25 | br label %for.inc 26 | 27 | for.inc: ; preds = %for.body 28 | ; %b, %i.0, %mul, 29 | ; %b, %i.0, %mul, 30 | %inc = add nsw i32 %i.0, 1 31 | ; %b, %mul, %inc, 32 | br label %for.cond 33 | 34 | for.end: ; preds = %for.cond 35 | ; %res.0, 36 | ; %res.0, 37 | ret i32 %res.0 38 | } 39 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment4/benchmarks/li_test_1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define n 900 6 | double a[n][n], b[n][n], c[n][n]; 7 | 8 | void compute(int p1, int p2) 9 | { 10 | 11 | int i, j, k; 12 | int inv; 13 | for (i = 0;; i++) { 14 | for (k = 0;; k++) { 15 | for (j = 0;; j++) { 16 | inv = p1 * p2 * p1; 17 | c[i][j] += a[i][k] * b[k][j] + inv; 18 | if(j>=n-1) break; 19 | } 20 | if(k>=n-1) break; 21 | } 22 | if(i>=n-1) break; 23 | } 24 | } 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | int i, j, k; 29 | clock_t begin, end; 30 | double time_spent; 31 | 32 | int n_cross_n = n * n; 33 | 34 | for (i = 0; i < n; i++) { 35 | for (j = 0; j < n; j++) { 36 | a[i][j] = i+j; 37 | b[i][j] = i-j; 38 | c[i][j] = 0; 39 | } 40 | } 41 | 42 | begin = clock(); 43 | compute(123,1233); 44 | end = clock(); 45 | time_spent = (double)(end - begin) / CLOCKS_PER_SEC; 46 | printf("Time taken: %f\n",time_spent); 47 | 48 | printf("%.1lf\n", c[3][3]); 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /vectorization/vectorization_0.md: -------------------------------------------------------------------------------- 1 | ### Vectorization Intel Webinar notes 2 | 3 | **Problem Statement:** Vector widths are increasing and extenstions to languages are needed to give best performance on new architectures. 4 | 5 | Different vendors are creating processors with multiple cores and within the cores vector width is increasing. Registers can bring in data in larger quantities and perform simultaneous operations on these quantitities. 6 | 7 | **Solutions:** Multiple methods are avaialable to developers to program explicit vector programming. 8 | 9 | Provide language extensions to simplify vector parallelism. Enable developers to extract more performane from SIMD processors. 10 | 11 | --- 12 | ``` 13 | -------------------- 14 | | Auto-vectorization | 15 | -------------------- 16 | 17 | | 18 | | 19 | 20 | ------------------------------ 21 | | Explicit vector programming | 22 | ------------------------------ 23 | 24 | ``` 25 | **Three ways to do explicit vectorization** 26 | 27 | * Array Notation 28 | * Elemental Function 29 | * SIMD pragma 30 | 31 | Auto-vectorization is limited due to serial nature of the code. 32 | 33 | 2-4x speedup by applying explicit vectorization on Xeon-phi 34 | 35 |
← PreviousNext →
36 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment3/reaching_results_sum: -------------------------------------------------------------------------------- 1 | Entring Block entry 2 | Entring Block for.cond 3 | Entring Block for.body 4 | Entring Block for.end 5 | Entring Block for.inc 6 | Entring Block for.cond 7 | 8 | ; Function Attrs: nounwind 9 | define i32 @sum(i32 %a, i32 %b) #0 { 10 | entry: 11 | ; %a, %b, 12 | ; %a, %b, 13 | br label %for.cond 14 | 15 | for.cond: ; preds = %for.inc, %entry 16 | ; %a, %b, %i.0, %res.0, %cmp, %mul, %inc, 17 | ; 18 | %i.0 = phi i32 [ %a, %entry ], [ %inc, %for.inc ] 19 | ; 20 | %res.0 = phi i32 [ 1, %entry ], [ %mul, %for.inc ] 21 | ; %b, %i.0, %res.0, %cmp, 22 | %cmp = icmp slt i32 %i.0, %b 23 | ; %b, %i.0, %res.0, %cmp, 24 | br i1 %cmp, label %for.body, label %for.end 25 | 26 | for.body: ; preds = %for.cond 27 | ; %b, %i.0, %res.0, %cmp, 28 | ; %b, %i.0, %res.0, %cmp, %mul, 29 | %mul = mul nsw i32 %res.0, %i.0 30 | ; %b, %i.0, %res.0, %cmp, %mul, 31 | br label %for.inc 32 | 33 | for.inc: ; preds = %for.body 34 | ; %b, %i.0, %res.0, %cmp, %mul, 35 | ; %b, %i.0, %res.0, %cmp, %mul, %inc, 36 | %inc = add nsw i32 %i.0, 1 37 | ; %b, %i.0, %res.0, %cmp, %mul, %inc, 38 | br label %for.cond 39 | 40 | for.end: ; preds = %for.cond 41 | ; %b, %i.0, %res.0, %cmp, 42 | ; %b, %i.0, %res.0, %cmp, 43 | ret i32 %res.0 44 | } 45 | -------------------------------------------------------------------------------- /vectorization/vectorization_1.md: -------------------------------------------------------------------------------- 1 | ### What is SIMD and vectorization 2 | 3 | **S**ingle **I**nstruction **M**ultiple **D**ata (SIMD) 4 | 5 | ``` 6 | 7 | | | | | | | 8 | | | | | | | 9 | --- ------- 10 | | | | | | | 11 | 12 | scalar vector 13 | 14 | ``` 15 | 16 | Explicit vector programming allows you to write more portable code. 17 | 18 | **Example:** 19 | 20 | ```c++ 21 | 22 | for(int i=0; i← PreviousNext → 71 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/LocalOpts/test-files/stack.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Following file implements stack in C. 4 | 5 | Author: Ankit Goyal 6 | 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | struct stack{ 13 | int value; 14 | struct stack * next; 15 | }; 16 | 17 | //defining a global head pointer to the stack queue 18 | struct stack *head; 19 | 20 | //push function for stack. 21 | void push(int a){ 22 | struct stack *node = (struct stack *)malloc(sizeof(struct stack)); 23 | if(node==NULL){ 24 | printf("failed to assign memory"); 25 | } 26 | node -> next = head; 27 | node -> value = a; 28 | head = node; 29 | } 30 | 31 | int pop(){ 32 | struct stack *poped; 33 | int popedValue; 34 | poped = head; 35 | popedValue = poped -> value; 36 | head = head -> next; 37 | free(poped); 38 | return popedValue; 39 | } 40 | 41 | void printLinkList(){ 42 | struct stack *temp = head; 43 | while(temp!=NULL){ 44 | printf("hello from list number %d\n", temp->value); 45 | temp = temp -> next; 46 | } 47 | } 48 | 49 | int main(void){ 50 | head = (struct stack *)malloc(sizeof(struct stack)); 51 | 52 | if(head==NULL){ 53 | printf("failed to assign memory"); 54 | } 55 | head -> value = 2; 56 | head -> next = NULL; 57 | 58 | 59 | push(3); 60 | printLinkList(); 61 | 62 | printf("poping value from the stack\n"); 63 | printf("popped the value - %d\n",pop()); 64 | printf("stack after poping the value\n"); 65 | 66 | printLinkList(); 67 | return 0; 68 | } 69 | 70 | 71 | -------------------------------------------------------------------------------- /spring2014-compilers/notes/notes.md: -------------------------------------------------------------------------------- 1 | Notes 2 | --- 3 | 4 | 1. **Loop**: A strongly connected component in CFG. 5 | 6 | 2. **Natural Loop**: Loop with only a single loop header. i.e., NOT able to 7 | enter in the middle of the loop (may be using branch instruction) 8 | 9 | 3. **Reducible Flow Graph**: CFG whose loops are all natural loops. 10 | 11 | --- 12 | 13 | ### Dataflow Analysis 14 | 15 | 1. Liveness flows backwards through the CFG, **because the behavior at future nodes determines liveness at a given node** 16 | 2. Imprecise conservative solutions ⇒ sub-optimal but correct programs 17 | 18 | --- 19 | 20 | ### Lattice theory 21 | 22 | 1. Inferior solutions are lower on the lattice 23 | 2. More conservative solutions are lower on the lattice 24 | 25 | --- 26 | 27 | 28 | – d dom i if all paths from **entry** to node i include d 29 | 30 | 1. The dominance frontier of a node d is the set of nodes that are “just 31 | barely” not dominated by d; i.e., the set of nodes n, such that 32 | 33 | – d dominates a predecessor p of n, and 34 | – d does not strictly dominate n 35 | 36 | 37 | --- 38 | 39 | ### Loop Invariant code motion 40 | 41 | – Constant 42 | – Have all reaching definitions outside of L 43 | – Have exactly one reaching definition and that definition is in the set marked “invariant” 44 | 45 | 1. The block containing s dominates all loop exits 46 | 2. No other statement in the loop assigns to x 47 | 3. The block containing s dominates all uses of x in the loop 48 | 49 | 50 | TODO: 51 | handout 07: slide 30: variable renaming algorithm. 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /basic-compiler-notes/compiler_notes_3.md: -------------------------------------------------------------------------------- 1 | ####Lecture 2#### 2 | --- 3 | 4 | ##Economy of programming languages.## 5 | 6 | **Q. Why are there so many programming lanuages?** 7 | 8 | Applications domains have distinctive/conflicting needs. 9 | 10 | * Scientific Computing: `good FP, good Arrays, Parallelism.` -> FORTRAN is a good example. 11 | * Bussiness Applications: `persistence, report generation, data anlysis` -> SQL 12 | * Systems Programming: `low level control of resources, real time contraints` -> C/C++ 13 | 14 | **Q. Why are there new programming languages?** 15 | 16 | Claim: Programmer training is the dominant cost for a programming language. [Time] 17 | 18 | Predictions: 19 | 20 | 1. Widely used languages will be slow to change. [Need to educate everyone.] 21 | 2. Easy to start a new language. [Start with 0 users.] 22 | 1. Productivity > training cost. => Switch. 23 | 3. Languages adopted to fill a void. [Mobile computing] 24 | 25 | **Q. What is a good programming languages?** 26 | 27 | There is **no** *universally accepted* metric for language design. 28 | 29 | * A good language is one people use? 30 | * Measures the popularity of language. 31 | * Conclusion: Visual Basic is the best language! But not quite true. 32 | 33 | --- 34 | ####Conclusion#### 35 | 36 | * Application domains have conflicting needs. Difficult to design one system to get all features. 37 | * Programmer training is the dominant cost for a programming language. 38 | 39 | 40 |
← PreviousNext →
41 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/LocalOpts/strength-out.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'strength-out.bc' 2 | target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" 3 | target triple = "i386-pc-linux-gnu" 4 | 5 | @.str = private unnamed_addr constant [3 x i8] c"%d\00", align 1 6 | 7 | ; Function Attrs: nounwind 8 | define i32 @compute(i32 %a, i32 %b) #0 { 9 | entry: 10 | %0 = shl i32 %a, 1 11 | %mul1 = mul nsw i32 %a, 3 12 | %add2 = add nsw i32 %0, %mul1 13 | %1 = shl i32 %a, 3 14 | %add4 = add nsw i32 %add2, %1 15 | %2 = ashr i32 %b, 1 16 | %sub = sub nsw i32 %add4, %2 17 | %3 = ashr i32 %b, 2 18 | %sub6 = sub nsw i32 %sub, %3 19 | %4 = ashr i32 %b, 3 20 | %sub8 = sub nsw i32 %sub6, %4 21 | ret i32 %sub8 22 | } 23 | 24 | ; Function Attrs: nounwind 25 | define void @main() #0 { 26 | entry: 27 | %call = call i32 @compute(i32 2, i32 20) 28 | %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([3 x i8]* @.str, i32 0, i32 0), i32 %call) 29 | ret void 30 | } 31 | 32 | declare i32 @printf(i8*, ...) #1 33 | 34 | attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 35 | attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 36 | 37 | !llvm.ident = !{!0} 38 | 39 | !0 = metadata !{metadata !"clang version 3.4 (tags/RELEASE_34/final)"} 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Compilers and LLVM 2 | 3 | --- 4 | 5 | * **basic-compiler-notes** contains course notes from first few lectures from coursera's course on compilers 6 | * **vectorization** contains notes on vectorization. 7 | * **mem-tracing** this has been moved to its own repository. ignore this dir. 8 | 9 | * **spring-2014-compilers/assignment1:** 10 | * **Module pass** to print source code line number as comments in LLVM IR using `AssemblyAnnotationWriter` class. 11 | 12 | * **spring-2014-compilers/assignment2:** 13 | * **Function Info pass**: that prints function name, argument size, number of call sites, number of basic blocks, number of instructions for a given function. 14 | * **LocalOpts Pass**: is an transform optimization pass (changes IR). It applies optimizations such as constant folding, strength reduction and algebraic identity. 15 | 16 | * **spring-2014-compilers/assignment3:** 17 | * **dataflow.h:** implements a dataflow framework with virtual methods that can be implemented to forward (reaching definitions) and backward (liveness) analysis. 18 | * **Live**: pass uses dataflow framework to print live variables above each instruction in IR (SSA form) 19 | * **Reach**: pass uses dataflow framework to print reaching variables above each instruction in IR (SSA form) 20 | 21 | * **spring-2014-compilers/assignment4:** 22 | * **DCE**: pass performs dead code elimination. It uses dataflow frameword developed in the previous assignment. 23 | * **licm**: pass that performs loop invariant code motion. It also uses above dataflow framework. 24 | 25 | 26 | 27 | #### Lessons: 28 | 29 | It would be better to implement dataflow framework using function pointers for `meet` and `transfer` functions, otherwise you can only use them once if implemented using virtual methods. 30 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment3/liveness_results_sum_loop: -------------------------------------------------------------------------------- 1 | 2 | ; Function Attrs: nounwind 3 | define i32 @sum(i32 %a, i32 %b) #0 { 4 | entry: 5 | ; %a, %b, 6 | ; %a, %b, 7 | %cmp = icmp sgt i32 %a, 0 8 | ; %a, %b, %cmp, 9 | br i1 %cmp, label %if.then, label %if.else 10 | 11 | if.then: ; preds = %entry 12 | ; %b, 13 | ; %b, 14 | br label %if.end 15 | 16 | if.else: ; preds = %entry 17 | ; %a, 18 | ; %a, 19 | br label %if.end 20 | 21 | if.end: ; preds = %if.else, %if.then 22 | ; %a, %b, 23 | ; 24 | %b.addr.0 = phi i32 [ %b, %if.then ], [ 12, %if.else ] 25 | ; 26 | %a.addr.0 = phi i32 [ 23, %if.then ], [ %a, %if.else ] 27 | ; %b.addr.0, %a.addr.0, 28 | br label %for.cond 29 | 30 | for.cond: ; preds = %for.inc, %if.end 31 | ; %b.addr.0, %a.addr.0, %mul, %inc, 32 | ; 33 | %i.0 = phi i32 [ %a.addr.0, %if.end ], [ %inc, %for.inc ] 34 | ; 35 | %res.0 = phi i32 [ 1, %if.end ], [ %mul, %for.inc ] 36 | ; %b.addr.0, %i.0, %res.0, 37 | %cmp1 = icmp slt i32 %i.0, %b.addr.0 38 | ; %b.addr.0, %i.0, %res.0, %cmp1, 39 | br i1 %cmp1, label %for.body, label %for.end 40 | 41 | for.body: ; preds = %for.cond 42 | ; %b.addr.0, %i.0, %res.0, 43 | ; %b.addr.0, %i.0, %res.0, 44 | %mul = mul nsw i32 %res.0, %i.0 45 | ; %b.addr.0, %i.0, %mul, 46 | br label %for.inc 47 | 48 | for.inc: ; preds = %for.body 49 | ; %b.addr.0, %i.0, %mul, 50 | ; %b.addr.0, %i.0, %mul, 51 | %inc = add nsw i32 %i.0, 1 52 | ; %b.addr.0, %mul, %inc, 53 | br label %for.cond 54 | 55 | for.end: ; preds = %for.cond 56 | ; %res.0, 57 | ; %res.0, 58 | ret i32 %res.0 59 | } 60 | -------------------------------------------------------------------------------- /vectorization/vectorization_2.md: -------------------------------------------------------------------------------- 1 | ### Example 2 | 3 | ``` 4 | for(i=0; i < *p; i++){ 5 | A[i] = B[i] + C[i]; 6 | sum = sum + A[i] 7 | } 8 | 9 | ``` 10 | 11 | Compiler cannot vectorize above code because it doesn't know: 12 | 13 | * if `*p` loop invariant. `*p` may be pointed to by some code that is running in some other thread. 14 | * if B and C are independent or independent of A. 15 | * if there is a dependency in sum. Sum used as Write-after-read and read-after-write. 16 | * may be sum is aliased to A, B / C 17 | 18 | 19 | **Reduction can be used to explicitly tell compiler** 20 | 21 | ``` 22 | #pragma simd reduction(+:sum) 23 | for(i=0; i < *p; i++){ 24 | A[i] = B[i] + C[i]; 25 | sum = sum + A[i] 26 | } 27 | 28 | ``` 29 | 30 | Above pragma directive allows vectorization of above code. 31 | 32 | ##### reduction 33 | 34 | ``` 35 | reduction(operator:v1, v2, ...) 36 | ``` 37 | Reduces a vector of values to a single value. 38 | Operator should be assosiative accross iterations. 39 | 40 | ##### private 41 | ``` 42 | private(v1, v2, ...) 43 | ``` 44 | Causes each variable to be private to each iteration of a loop. 45 | 46 | ##### vectorlength 47 | ``` 48 | vectorlength(n1, [,n2]) 49 | ``` 50 | Explicitly tell compiler what vector width to use. Must be 2,4,8,or 16. 51 | 52 | ##### linear 53 | ``` 54 | linear(v1:step1, v2:step2, ...) 55 | ```` 56 | 57 | Indicate the presence of a induction variable like `count = count + 2` inside the loop. Here the step size is 2 and thus the count is updated by step1 * (vector length) where step1 is 2 in this case. 58 | 59 | ##### [no]assert 60 | When assert is given it treats vectorization failure as an error and stop compilation. 61 | 62 | Default is no assert where only the warning is printed. 63 | 64 | 65 |
← PreviousNext →
-------------------------------------------------------------------------------- /basic-compiler-notes/compiler_notes_1.md: -------------------------------------------------------------------------------- 1 | ####Lecture 2#### 2 | 3 | Structure of a Compiler 4 | 5 | 1. **Lexical Analysis** 6 | 2. **Parsing** 7 | 3. **Semantic Analysis** 8 | 4. **Optimization** 9 | 5. **Code Generation** 10 | 11 | --- 12 | 13 | **First Step**: Recognize words 14 | 15 | * **Lexical Analysis** : *divides program text into "words" or "tokens".* 16 | 17 | `if x==y then z=1; else z=2` contains *Keywords, operators, variable names, tokens* 18 | 19 | Parsing: 20 | 21 | 22 | ![Lexical Analysis](https://gist.github.com/goyalankit/8074196/raw/85664326f4931a96082d62b55b95bc306bafc044/compilers1.png) 23 | 24 | 25 | * **Semantical Analysis** : compilers perform limited semantical analysis. This is too hard. 26 | 27 | `Jack said Jack left his assignment at home?` : How many people? Worse case 3 different people. 28 | 29 | Programming languages define strict rules to prevent such ambiguities. Analogy: 30 | 31 | ``` 32 | { 33 | int Jack = 2; 34 | { 35 | int Jack = 4; 36 | cout << Jack; 37 | } 38 | } 39 | 40 | ``` 41 | 42 | * **Optimization** is a little like editing. 43 | 44 | Automatically modify program so that they: 45 | * Run Faster 46 | * Use less memory 47 | * less power use 48 | * number of network messages 49 | * number of database calls 50 | 51 | `X = Y * 0 is the same as X = 0` => **INCORRECT RULE** 52 | 53 | Above rule is valid only for integers. Invalid for floating points. 54 | because of the rule `NAN * 0 = NAN` 55 | 56 | * **Code Generation** 57 | 58 | Translation to another language. High level code -> Assembly Code. 59 | 60 | --- 61 | 62 | Proportions of each phase hass changed over time. 63 | 64 | Then: `[....L....] [....P.....] [.S.] [....O....] [....CG....]` 65 | 66 | Now: `[.L.][.P.][.......S......][...........O............][.CG.]` 67 | 68 |
← PreviousNext →
69 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/FunctionInfo/test-files/stack.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | Following file implements stack in C. 5 | ------------------------------------- 6 | 7 | Output on running module pass: 8 | 9 | push: arguments=1 call sites=1 basic blocks=3 instructions=24 10 | 11 | llvm.dbg.declare: arguments=2 call sites=5 basic blocks=0 instructions=0 12 | 13 | malloc: arguments=1 call sites=2 basic blocks=0 instructions=0 14 | 15 | printf: arguments=1 call sites=6 basic blocks=0 instructions=0 16 | 17 | pop: arguments=0 call sites=1 basic blocks=1 instructions=19 18 | 19 | free: arguments=1 call sites=1 basic blocks=0 instructions=0 20 | 21 | printLinkList: arguments=0 call sites=2 basic blocks=4 instructions=18 22 | 23 | main: arguments=0 call sites=0 basic blocks=3 instructions=24 24 | -------------------------------------------------------- 25 | 26 | Author: Ankit Goyal 27 | 28 | */ 29 | 30 | #include 31 | #include 32 | 33 | struct stack{ 34 | int value; 35 | struct stack * next; 36 | }; 37 | 38 | //defining a global head pointer to the stack queue 39 | struct stack *head; 40 | 41 | //push function for stack. 42 | void push(int a){ 43 | struct stack *node = (struct stack *)malloc(sizeof(struct stack)); 44 | if(node==NULL){ 45 | printf("failed to assign memory"); 46 | } 47 | node -> next = head; 48 | node -> value = a; 49 | head = node; 50 | } 51 | 52 | int pop(){ 53 | struct stack *poped; 54 | int popedValue; 55 | poped = head; 56 | popedValue = poped -> value; 57 | head = head -> next; 58 | free(poped); 59 | return popedValue; 60 | } 61 | 62 | void printLinkList(){ 63 | struct stack *temp = head; 64 | while(temp!=NULL){ 65 | printf("hello from list number %d\n", temp->value); 66 | temp = temp -> next; 67 | } 68 | } 69 | 70 | int main(void){ 71 | head = (struct stack *)malloc(sizeof(struct stack)); 72 | 73 | if(head==NULL){ 74 | printf("failed to assign memory"); 75 | } 76 | head -> value = 2; 77 | head -> next = NULL; 78 | 79 | 80 | push(3); 81 | printLinkList(); 82 | 83 | printf("poping value from the stack\n"); 84 | printf("popped the value - %d\n",pop()); 85 | printf("stack after poping the value\n"); 86 | 87 | printLinkList(); 88 | return 0; 89 | } 90 | 91 | 92 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment4/benchmarks/benchmarks.txt: -------------------------------------------------------------------------------- 1 | Source code used for benchmarking is included in the benchmarks folder. 2 | 3 | ### Loop Invariant benchmarks 4 | --- 5 | 6 | 1. Matrix-matrix multiplication.(900 * 900) [ li_test_1.cpp ] 7 | invariant instruction of the form `inv = p1 * p2 * p1;` present inside the loop. 8 | 9 | Execution Results: 10 | 11 | After running licm pass: 12 | ./lli sum-out.bc 13 | Time taken: 0.950000 14 | Result: 17031238350.0 15 | 16 | --- 17 | 18 | Without running licm pass: 19 | ./lli sum-simp.bc 20 | Time taken: 1.240000 21 | Result: 17031238350.0 22 | 23 | --- 24 | 25 | After running LLVM provided licm pass: 26 | Using: opt -stats -debug -licm sum-simp.c -o sum-ll.bc 27 | 28 | ./lli sum-ll.bc 29 | Time taken: 1.200000 30 | Result: 17031238350.0 31 | 32 | --- 33 | 34 | Compiled with gcc 35 | Using: gcc li_test_1.cpp 36 | 37 | ./a.out 38 | Time taken: 3.250000 //I Don't know why this is so bad! 39 | Result: 17031238350.0 40 | 41 | --- 42 | Compiled with intel icc compiler 43 | Using: icc li_test_1.cpp 44 | 45 | ./a.out 46 | Time taken: 0.370000 47 | 17031238350.0 48 | 49 | 50 | 51 | Note that the result is same in both the cases which varifies the correctness. 52 | Improvement by 23% in execution time from unoptimized version 53 | 54 | My pass produced a better version than llvm's pass. LLVM was able to move load and store instructions for heap 55 | related to array indexing. I think my program had less cache misses. 56 | 57 | 58 | 2. General Nested For Loops. [ li_test_2.cpp ] 59 | 60 | After running my licm pass: 61 | lli sum-out.bc 62 | Time taken: 13.300000 63 | 64 | Without licm pass: 65 | lli sum-simp.bc 66 | Time taken: 13.500000 67 | 68 | After running LLVM licm pass: 69 | Time taken: 13.280000 70 | 71 | 72 | This is a generic nested loop program where the nested loops contain some computation. 73 | After running licm computation is moved outside the loop. 74 | LLVM's licm pass is folding the instructions and removing them altogether hence it is faster. 75 | 76 | 77 | ### Dead Code Elimination 78 | --- 79 | 80 | 1. Test Program (dce_test1.cpp) 81 | 82 | Without running dce pass: 83 | Time taken: 0.970000 84 | 85 | After running my dce pass: 86 | Time taken: 0.770000 87 | 88 | After running llvm's dce pass: 89 | Time taken: 0.920000 90 | 91 | 2. 92 | 93 | 94 | -------------------------------------------------------------------------------- /spring2014-compilers/notes/compiler_notes.md: -------------------------------------------------------------------------------- 1 | Data flow: 2 | Flow of data values from one statement to another. 3 | 4 | **Control flow:** 5 | Sequencing of operations. Evaluation of then or else code depends on the if condition. 6 | 7 | **Control flow analysis:** 8 | - Discover the control flow within a __procedure__ 9 | - Build a representation of control flow(loops,etc). 10 | 11 | *** 12 | High level: Control flow is implicit in AST 13 | Low level: Use of a **control flow graph**(CFG). 14 | -- Nodes represent statements 15 | -- Edges represent explicit flow of control. 16 | 17 | Source code 18 | ``` 19 | 1 a := 0 ;start of block 20 | 2 b := a * b ;end of block 21 | 3 L1: c := b/d ;Entry point, start of block 22 | 4 if c < x goto ;Exit point, end of block 23 | 5 e := b / c ;start of block 24 | 6 f := e + 1 ;end of block 25 | 7 L2: g := f ;Entry point; start of block 26 | 8 h := t - g 27 | 9 if e > 0 goto L3 ;Exit Point, end of block 28 | 10 goto L1 ;Exit point, end of block 29 | 11 L3: return ;Entry point, start and end of block 30 | ``` 31 | **Basic Blocks**: A sequence of straight line code that can be entered only at the beginning and exited only at the end. 32 | 33 | **Extended basic blocks**: A maximal sequence of instructions that has no merge points in it.(except perhaps in the leader) 34 | - Single entry multiple exits. 35 | - Increases the scope of any local analysis or transformation that "flow forwards" 36 | 37 | **Reverse Extended basic block** 38 | 39 | --- 40 | #### Paper Review: 41 | 42 | **Overcoming the challenges to Feedback-Directed Optimization** 43 | 44 | Paper presents quite an interesting view on feedback based optimizations. 45 | 46 | Branch-based phase behavior is very similar to the problem of predicting best rate for transmission in networks. The main problem is what amount of interval you need to consider to predict the best rate. In one of the papers, authors show that the mutual information decreases between subsequent dropped packets over a long interval. This seems to be the behavior of phased behavior. If one considers a short enough interval to predict the branch, I think a good performance can be achieved. 47 | 48 | I am not convinced mutable executables are a very good idea due to very reason that a correct code could turn buggy and I am not sure how would one go about debugging an executable that was changed based on the usage pattern. 49 | 50 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/FunctionInfo/FunctionInfo.cpp: -------------------------------------------------------------------------------- 1 | // 15-745 S13 Assignment 1: FunctionInfo.cpp 2 | // 3 | // Based on code from Todd C. Mowry 4 | // Modified by Arthur Peters 5 | // Modified by Ankit Goyal 6 | //////////////////////////////////////////////////////////////////////////////// 7 | 8 | #include "llvm/Pass.h" 9 | #include "llvm/PassManager.h" 10 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 11 | #include "llvm/DebugInfo.h" 12 | #include "llvm/IR/Function.h" 13 | #include "llvm/IR/Module.h" 14 | #include "llvm/Support/raw_ostream.h" 15 | #include "llvm/Support/FormattedStream.h" 16 | #include "llvm/Support/InstIterator.h" 17 | #include "llvm/IR/Instruction.h" 18 | #include "llvm/DebugInfo.h" 19 | #include "llvm/Assembly/AssemblyAnnotationWriter.h" 20 | 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | using namespace llvm; 29 | 30 | namespace { 31 | 32 | class FunctionInfo : public ModulePass{ 33 | 34 | public: 35 | static char ID; 36 | FunctionInfo() : ModulePass(ID) { errs() << "\n"; } //default constructor 37 | ~FunctionInfo() { errs() << "\n"; } 38 | 39 | void printFunctionDetails(Function &F) { 40 | int arg_size = F.arg_size(); 41 | int num_call_sites = F.getNumUses(); 42 | int num_basic_blocks = F.size(); //defined in value class. 43 | //count the number of instructions. 44 | int number_of_instructions = 0; 45 | for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) 46 | number_of_instructions += 1; 47 | 48 | errs() << F.getName() <<": arguments=" << arg_size << " call sites=" << num_call_sites << " basic blocks=" << num_basic_blocks << " instructions=" << number_of_instructions << "\n\n"; 49 | } 50 | 51 | virtual bool runOnModule(Module &M){ 52 | for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) 53 | { 54 | printFunctionDetails(*MI); 55 | } 56 | return false; 57 | } 58 | 59 | 60 | // We don't modify the program, so we preserve all analyses 61 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { 62 | AU.setPreservesAll(); 63 | } 64 | }; 65 | 66 | // LLVM uses the address of this static member to identify the pass, so the 67 | // initialization value is unimportant. 68 | char FunctionInfo::ID = 0; 69 | 70 | // Register this pass to be used by language front ends. 71 | // This allows this pass to be called using the command: 72 | // clang -c -Xclang -load -Xclang ./FunctionInfo.so loop.c 73 | static void registerMyPass(const PassManagerBuilder &, 74 | PassManagerBase &PM) { 75 | PM.add(new FunctionInfo()); 76 | } 77 | RegisterStandardPasses 78 | RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, 79 | registerMyPass); 80 | 81 | // Register the pass name to allow it to be called with opt: 82 | // clang -c -emit-llvm loop.c 83 | // opt -load ./FunctionInfo.so -function-info loop.bc > /dev/null 84 | // See http://llvm.org/releases/3.4/docs/WritingAnLLVMPass.html#running-a-pass-with-opt for more info. 85 | RegisterPass X("function-info", "Function Information"); 86 | 87 | } 88 | -------------------------------------------------------------------------------- /spring2014-compilers/llvm-stuff/FunctionInfo.cpp: -------------------------------------------------------------------------------- 1 | // 15-745 S13 Assignment 1: FunctionInfo.cpp 2 | // 3 | // Based on code from Todd C. Mowry 4 | // Modified by Arthur Peters 5 | //////////////////////////////////////////////////////////////////////////////// 6 | 7 | #include "llvm/Pass.h" 8 | #include "llvm/PassManager.h" 9 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 10 | #include "llvm/DebugInfo.h" 11 | #include "llvm/IR/Function.h" 12 | #include "llvm/IR/Module.h" 13 | #include "llvm/Support/raw_ostream.h" 14 | #include "llvm/Support/FormattedStream.h" 15 | #include "llvm/Support/InstIterator.h" 16 | #include "llvm/IR/Instruction.h" 17 | #include "llvm/DebugInfo.h" 18 | #include "llvm/Assembly/AssemblyAnnotationWriter.h" 19 | 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | using namespace llvm; 27 | 28 | namespace { 29 | 30 | 31 | class CommentWriter : public AssemblyAnnotationWriter { 32 | public: 33 | virtual void emitFunctionAnnot(const Function *F, 34 | formatted_raw_ostream &OS) { 35 | OS << "; [#uses=" << F->getNumUses() << ']'; // Output # uses 36 | OS << '\n'; 37 | } 38 | 39 | }; 40 | 41 | class FunctionInfo : public FunctionPass, public AssemblyAnnotationWriter{ 42 | 43 | public: 44 | static char ID; 45 | FunctionInfo() : FunctionPass(ID) {} 46 | 47 | void emitFunctionAnnot(const Function *F, formatted_raw_ostream &OS) { 48 | errs() << "CALLED"; 49 | OS << "; [#uses=" << F->getNumUses() << ']'; // Output # uses 50 | OS << '\n'; 51 | } 52 | 53 | 54 | virtual bool runOnFunction(Function &F) { 55 | for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I){ 56 | Instruction &II = *I; 57 | // printInfoComment((Value)&I, ferrs()); 58 | errs() << *I; 59 | errs() << " source_line: " << lineNum(&II) << "\n"; 60 | // errs().write_escaped(itoa(lineNum(&II))); 61 | 62 | } 63 | return false; 64 | } 65 | 66 | 67 | unsigned lineNum(Instruction* I){ 68 | if (MDNode *N = I->getMetadata("dbg")) { // Here I is an LLVM instruction 69 | DILocation Loc(N); // DILocation is in DebugInfo.h 70 | unsigned Line = Loc.getLineNumber(); 71 | return Line; 72 | } 73 | } 74 | 75 | 76 | // We don't modify the program, so we preserve all analyses 77 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { 78 | // AU.setPreservesAll(); 79 | } 80 | }; 81 | 82 | // LLVM uses the address of this static member to identify the pass, so the 83 | // initialization value is unimportant. 84 | char FunctionInfo::ID = 0; 85 | 86 | // Register this pass to be used by language front ends. 87 | // This allows this pass to be called using the command: 88 | // clang -c -Xclang -load -Xclang ./FunctionInfo.so loop.c 89 | static void registerMyPass(const PassManagerBuilder &, 90 | PassManagerBase &PM) { 91 | PM.add(new FunctionInfo()); 92 | } 93 | RegisterStandardPasses 94 | RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, 95 | registerMyPass); 96 | 97 | // Register the pass name to allow it to be called with opt: 98 | // clang -c -emit-llvm loop.c 99 | // opt -load ./FunctionInfo.so -function-info loop.bc > /dev/null 100 | // See http://llvm.org/releases/3.4/docs/WritingAnLLVMPass.html#running-a-pass-with-opt for more info. 101 | RegisterPass X("function-info", "Function Information"); 102 | 103 | } 104 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment1/ModuleInfo.cpp: -------------------------------------------------------------------------------- 1 | // 15-745 S13 Assignment 1: FunctionInfo.cpp 2 | // 3 | // Based on code from Todd C. Mowry 4 | // Modified by Arthur Peters 5 | // Modified by Ankit Goyal 6 | // 7 | //////////////////////////////////////////////////////////////////////////////// 8 | 9 | #include "llvm/Pass.h" 10 | #include "llvm/PassManager.h" 11 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 12 | #include "llvm/IR/Function.h" 13 | #include "llvm/IR/Module.h" 14 | #include "llvm/Support/raw_ostream.h" 15 | #include "llvm/Support/InstIterator.h" 16 | #include "llvm/IR/Instruction.h" 17 | #include "llvm/DebugInfo.h" 18 | #include "llvm/Assembly/AssemblyAnnotationWriter.h" 19 | #include "llvm/Support/FormattedStream.h" 20 | #include "llvm/IR/Constants.h" 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | using namespace llvm; 28 | 29 | namespace { 30 | 31 | class CommentWriter : public AssemblyAnnotationWriter { 32 | public: 33 | //Get the line number from metadata of instruction 34 | unsigned lineNum(const Instruction* I){ 35 | if (MDNode *N = I->getMetadata("dbg")) { // Here I is an LLVM instruction 36 | DILocation Loc(N); // DILocation is in DebugInfo.h 37 | unsigned Line = Loc.getLineNumber(); 38 | return Line; 39 | } 40 | // errs() << "Debug Option Not Turned On. Make sure you are using -g option to compile"; 41 | } 42 | 43 | //override to print comment before the instruction 44 | virtual void emitInstructionAnnot(const Instruction *I, formatted_raw_ostream &OS) { 45 | //OS << "Source Line #: " << lineNum(I); 46 | } 47 | 48 | //override to print comment after the instruction 49 | virtual void printInfoComment(const Value &V, formatted_raw_ostream &OS) { 50 | if(const Instruction *I = dyn_cast(&V)){ 51 | OS << " ; source code line #: " << lineNum(I); 52 | } 53 | } 54 | }; 55 | 56 | 57 | class ModuleInfo : public ModulePass { 58 | public: 59 | static char ID; 60 | ModuleInfo() : ModulePass(ID) {} 61 | CommentWriter aaw ; 62 | virtual bool runOnModule(Module &M) { 63 | M.print(errs(), &aaw); 64 | return false; 65 | } 66 | 67 | // We don't modify the program, so we preserve all analyses 68 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { 69 | AU.setPreservesAll(); 70 | } 71 | }; 72 | 73 | // LLVM uses the address of this static member to identify the pass, so the 74 | // initialization value is unimportant. 75 | char ModuleInfo::ID = 0; 76 | 77 | // Register this pass to be used by language front ends. 78 | // This allows this pass to be called using the command: 79 | // clang -c -Xclang -load -Xclang ./FunctionInfo.so loop.c 80 | static void registerMyPass(const PassManagerBuilder &, 81 | PassManagerBase &PM) { 82 | PM.add(new ModuleInfo()); 83 | } 84 | RegisterStandardPasses 85 | RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, 86 | registerMyPass); 87 | 88 | // Register the pass name to allow it to be called with opt: 89 | // clang -c -g -emit-llvm loop.c 90 | // opt -load ./ModuleInfo.so -module-info loop.bc > /dev/null 91 | // See http://llvm.org/releases/3.4/docs/WritingAnLLVMPass.html#running-a-pass-with-opt for more info. 92 | RegisterPass X("module-info", "module Information"); 93 | 94 | } 95 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment2/LocalOpts/notes.md: -------------------------------------------------------------------------------- 1 | All three needs to be done at instruction level. 2 | 3 | 4 | #### Algebraic identities on : e.g, x + 0 = 0 + x = x and x/x = 1 5 | 6 | ```c++ 7 | int compute (int a, int b) 8 | { 9 | int result = (a/a); 10 | unsigned int t = (b/b); 11 | result *= (b/b); 12 | result += (b-b); 13 | result /= result; 14 | result -= result; 15 | return result; 16 | } 17 | 18 | ``` 19 | 20 | The .ll produced by above code: 21 | 22 | ```llvm 23 | 24 | ; Function Attrs: nounwind 25 | define i32 @compute(i32 %a, i32 %b) #0 { 26 | entry: 27 | %a.addr = alloca i32, align 4 28 | %b.addr = alloca i32, align 4 29 | %result = alloca i32, align 4 30 | %t = alloca i32, align 4 31 | store i32 %a, i32* %a.addr, align 4 32 | store i32 %b, i32* %b.addr, align 4 33 | %0 = load i32* %a.addr, align 4 34 | %1 = load i32* %a.addr, align 4 35 | %div = sdiv i32 %0, %1 36 | store i32 %div, i32* %result, align 4 37 | %2 = load i32* %b.addr, align 4 38 | %3 = load i32* %b.addr, align 4 39 | %div1 = sdiv i32 %2, %3 40 | store i32 %div1, i32* %t, align 4 41 | %4 = load i32* %b.addr, align 4 42 | %5 = load i32* %b.addr, align 4 43 | %div2 = sdiv i32 %4, %5 44 | %6 = load i32* %result, align 4 45 | %mul = mul nsw i32 %6, %div2 46 | store i32 %mul, i32* %result, align 4 47 | %7 = load i32* %b.addr, align 4 48 | %8 = load i32* %b.addr, align 4 49 | %sub = sub nsw i32 %7, %8 50 | %9 = load i32* %result, align 4 51 | %add = add nsw i32 %9, %sub 52 | store i32 %add, i32* %result, align 4 53 | %10 = load i32* %result, align 4 54 | %11 = load i32* %result, align 4 55 | %div3 = sdiv i32 %11, %10 56 | store i32 %div3, i32* %result, align 4 57 | %12 = load i32* %result, align 4 58 | %13 = load i32* %result, align 4 59 | %sub4 = sub nsw i32 %13, %12 60 | store i32 %sub4, i32* %result, align 4 61 | %14 = load i32* %result, align 4 62 | ret i32 %14 63 | } 64 | 65 | 66 | ``` 67 | 68 | Look at the short version of the above code. 69 | 70 | ```c++ 71 | int foo(int a){ 72 | int result = (a/a); 73 | return 0; 74 | } 75 | ``` 76 | 77 | ```llvm 78 | %a.addr = alloca i32, align 4 ;allocating memory for a 79 | %result = alloca i32, align 4 ;allocating memory for result 80 | store i32 %a, i32* %a.addr, align 4 ;initializing memory for a 81 | %0 = load i32* %a.addr, align 4 ;loading a to register 0 82 | %1 = load i32* %a.addr, align 4 ;loading a to register 2 83 | %div = sdiv i32 %0, %1 ;dividing register 0 and register 1. Note the s in sdiv for "signed" 84 | store i32 %div, i32* %result, align 4 ;storing the result in result variable 85 | ret i32 0 ;returning 0 86 | ``` 87 | 88 | `%div = sdiv i32 %0, %1` needs to be checked for identity. 89 | 90 | `a/a = 1 => a/1 = a` applying the identity yields the same result. 91 | 92 | **Similarly for substraction:** 93 | 94 | ```c++ 95 | result += (b - b) 96 | ``` 97 | 98 | ```llvm 99 | %7 = load i32* %b.addr, align 4 ; loading b 100 | %8 = load i32* %b.addr, align 4 ; loading b again 101 | %sub = sub nsw i32 %7, %8 ; subtracting b from b 102 | %9 = load i32* %result, align 4 ; loading result 103 | %add = add nsw i32 %9, %sub ; add ing result and result from subtraction 104 | store i32 %add, i32* %result, align 4 ; storing the above result in result 105 | ``` 106 | 107 | Again look at the instruction level: 108 | 109 | `%sub = sub nsw i32 %7, %8` needs to be checked for identity. 110 | 111 | `b - b = 0 => b - 0 = b` ;apply the operator and the result should be variable itself. 112 | 113 | At the instruction level: 114 | 115 | 116 | 117 | #### Constant folding: e.g, 2 ∗ 4 = 8 118 | 119 | #### Strength reductions: e.g, 2 ∗ x = (x + x) or (x << 1) 120 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment3/dataflow.h: -------------------------------------------------------------------------------- 1 | // Assignment 3: FunctionInfo.cpp 2 | // 3 | // Based on code from Todd C. Mowry 4 | // Modified by Arthur Peters 5 | // Modified by Ankit Goyal 6 | //////////////////////////////////////////////////////////////////////////////// 7 | 8 | #include "llvm/Pass.h" 9 | #include "llvm/IR/BasicBlock.h" 10 | #include "llvm/Support/raw_ostream.h" 11 | #include "llvm/IR/Instruction.h" 12 | #include "llvm/IR/Instructions.h" 13 | #include "llvm/IR/Constants.h" 14 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" 15 | #include "llvm/ADT/BitVector.h" 16 | #include "llvm/ADT/ValueMap.h" 17 | #include "llvm/Support/CFG.h" 18 | #include "llvm/ADT/DenseMap.h" 19 | 20 | #include 21 | #include 22 | 23 | using namespace llvm; 24 | 25 | #ifndef __DATAFLOW_H__ 26 | #define __DATAFLOW_H__ 27 | 28 | namespace { 29 | //forward indicates the flow direction. FlowValueType indicates the type of flow value. Ex: BitVector used for liveness and reachness. 30 | 31 | typedef std::list Worklist; 32 | 33 | template 34 | class DataFlow{ 35 | bool forward; 36 | public: 37 | enum SetType { 38 | IN, 39 | OUT 40 | }; 41 | 42 | DataFlow(bool forward) { 43 | this->forward = forward; 44 | in = new BlockInOutMap(); 45 | out = new BlockInOutMap(); 46 | neighbourSpecificValues = new BlockInOutMap(); 47 | visited = new ValueMap(); 48 | } 49 | 50 | //TODO: Destruct stuff 51 | ~DataFlow(){ 52 | delete in; 53 | delete out; 54 | delete neighbourSpecificValues; 55 | delete visited; 56 | } 57 | //mapping from basicblock to lattice 58 | typedef ValueMap BlockInOutMap; 59 | //In out sets for a basic block 60 | BlockInOutMap *in; 61 | BlockInOutMap *out; 62 | BlockInOutMap *neighbourSpecificValues; 63 | ValueMap *visited; 64 | 65 | 66 | //TODO: Merge forward and backward analysis methods. They are very similar. 67 | void performForwardAnalysis(Worklist &w){ 68 | BasicBlock *hotBlock = *w.begin(); 69 | w.pop_front(); 70 | (*visited)[hotBlock] = true; 71 | //DEBUG:: 72 | errs() << "Entring Block " << hotBlock->getName() << "\n"; 73 | int numPred = 0; 74 | for (pred_iterator PI = pred_begin(hotBlock), E = pred_end(hotBlock); PI != E; ++PI){ 75 | ++numPred; 76 | if(PI == pred_begin(hotBlock)){ 77 | *(*in)[hotBlock] = *(*out)[*PI]; 78 | }else{ 79 | meetOp((*in)[hotBlock], (*out)[*PI]); 80 | } 81 | } 82 | 83 | if(numPred == 0) setBoundaryCondition((*in)[hotBlock]); 84 | 85 | 86 | FlowValueType *newOut = transferFn(*hotBlock); 87 | bool changed = false; 88 | changed = (*newOut != *(*out)[hotBlock]); 89 | 90 | if(changed) 91 | *(*out)[hotBlock] = *newOut; 92 | 93 | for (succ_iterator SI = succ_begin(hotBlock), E = succ_end(hotBlock); SI != E; ++SI) { 94 | //TODO: Don't add to worklist if the block is already present 95 | if(changed || !(*visited)[*SI]){ 96 | w.push_back(*SI); 97 | } 98 | } 99 | } 100 | 101 | void performBackwardAnalysis(Worklist &w){ 102 | BasicBlock *hotBlock = *w.begin(); 103 | w.pop_front(); 104 | (*visited)[hotBlock] = true; 105 | errs() << "Entring Block " << hotBlock->getName() << "\n"; 106 | //out of this basic block is equivalent to in of it's successor 107 | //OUT = Union IN 108 | int numSucc = 0; //to check for the exit node 109 | 110 | for (succ_iterator SI = succ_begin(hotBlock), E = succ_end(hotBlock); SI != E; ++SI) { 111 | numSucc++; 112 | if(SI == succ_begin(hotBlock)){ 113 | *(*out)[hotBlock] = *(*in)[*SI]; //copy the first IN set values 114 | }else{ 115 | meetOp((*out)[hotBlock], (*in)[*SI]); //call the meet operator 116 | } 117 | } 118 | 119 | if((*neighbourSpecificValues).find(hotBlock) != (*neighbourSpecificValues).end() ){ 120 | //for phi node. meet the variables that are live from this specific block 121 | meetOp((*out)[hotBlock], (*neighbourSpecificValues)[hotBlock]); 122 | } 123 | 124 | if(numSucc == 0) setBoundaryCondition((*out)[hotBlock]); //set boundary condition for the exit node. 125 | 126 | FlowValueType *newIn = transferFn(*hotBlock); 127 | 128 | bool changed = false; 129 | changed = ((*newIn) != (*(*in)[hotBlock])); 130 | 131 | if(changed) 132 | *(*in)[hotBlock] = *newIn; 133 | 134 | for (pred_iterator PI = pred_begin(hotBlock), E = pred_end(hotBlock); PI != E; ++PI) { 135 | //make sure that each block is traversed at least one. 136 | if(changed || !(*visited)[*PI]){ 137 | w.push_back(*PI); 138 | } 139 | } 140 | } 141 | 142 | void finalizeBackwardAnalysis(Function &func){ 143 | for (Function::iterator i = func.begin(), e = func.end(); i != e; ++i){ 144 | int numSucc = 0; 145 | BasicBlock *hotBlock = &*i; 146 | if((*neighbourSpecificValues).find(hotBlock) != (*neighbourSpecificValues).end()){ 147 | for (succ_iterator SI = succ_begin(&*i), SE = succ_end(&*i); SI != SE; SI++){ 148 | meetOp((*in)[*SI], (*neighbourSpecificValues)[hotBlock]); 149 | } 150 | } 151 | } 152 | } 153 | 154 | //add just the last block in case of backward analysis 155 | void initializeWorklist(Function &func, Worklist &worklist){ 156 | if(forward){ 157 | BasicBlock& entry = func.getEntryBlock(); 158 | worklist.push_back(&entry); 159 | return; 160 | } 161 | 162 | for (Function::iterator i = func.begin(), e = func.end(); i != e; ++i){ 163 | int numSucc = 0; 164 | 165 | for (succ_iterator SI = succ_begin(&*i), SE = succ_end(&*i); SI != SE; SI++) 166 | numSucc++; 167 | 168 | if(numSucc==0) worklist.push_back(&*i); 169 | } 170 | } 171 | 172 | bool runOnFunction(Function &F){ 173 | visited = new ValueMap(); 174 | for (Function::iterator bi = F.begin(), be = F.end(); bi != be; bi++) { 175 | BasicBlock * bb = &*bi; 176 | 177 | //set the appropriate values for forward and backward flow 178 | //(*in)[bb] -> bit vector::lattice for that block 179 | (*in)[bb] = initializeFlowValue(*bi, IN); 180 | (*out)[bb] = initializeFlowValue(*bi, OUT); 181 | } 182 | 183 | Worklist *worklist = new Worklist(); 184 | initializeWorklist(F,*worklist); 185 | while(!worklist->empty()){ 186 | if(forward) 187 | performForwardAnalysis(*worklist); 188 | else 189 | performBackwardAnalysis(*worklist); 190 | } 191 | finalizeBackwardAnalysis(F); 192 | } 193 | 194 | protected: 195 | //get the boundary conditions for entry nodes 196 | virtual void setBoundaryCondition(FlowValueType*) = 0; 197 | //meet operator. could be union or intersection based on the FlowValueType 198 | virtual void meetOp(FlowValueType* lhs, const FlowValueType* rhs) = 0; 199 | //initial flow values for IN and OUT sets. SetType: IN or OUT 200 | virtual FlowValueType* initializeFlowValue(BasicBlock& b, SetType setType) = 0; 201 | //transer function 202 | virtual FlowValueType* transferFn(BasicBlock& b) = 0; 203 | }; 204 | } 205 | 206 | #endif 207 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment4/dataflow.h: -------------------------------------------------------------------------------- 1 | // Assignment 3: FunctionInfo.cpp 2 | // 3 | // Based on code from Todd C. Mowry 4 | // Modified by Arthur Peters 5 | // Modified by Ankit Goyal 6 | //////////////////////////////////////////////////////////////////////////////// 7 | 8 | #include "llvm/Pass.h" 9 | #include "llvm/IR/BasicBlock.h" 10 | #include "llvm/Support/raw_ostream.h" 11 | #include "llvm/IR/Instruction.h" 12 | #include "llvm/IR/Instructions.h" 13 | #include "llvm/IR/Constants.h" 14 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" 15 | #include "llvm/ADT/BitVector.h" 16 | #include "llvm/ADT/ValueMap.h" 17 | #include "llvm/Support/CFG.h" 18 | #include "llvm/ADT/DenseMap.h" 19 | 20 | #include 21 | #include 22 | 23 | using namespace llvm; 24 | 25 | #ifndef __DATAFLOW_H__ 26 | #define __DATAFLOW_H__ 27 | 28 | namespace { 29 | //forward indicates the flow direction. FlowValueType indicates the type of flow value. Ex: BitVector used for liveness and reachness. 30 | 31 | typedef std::list Worklist; 32 | 33 | template 34 | class DataFlow{ 35 | bool forward; 36 | public: 37 | enum SetType { 38 | IN, 39 | OUT 40 | }; 41 | 42 | DataFlow(bool forward) { 43 | this->forward = forward; 44 | in = new BlockInOutMap(); 45 | out = new BlockInOutMap(); 46 | neighbourSpecificValues = new BlockInOutMap(); 47 | visited = new ValueMap(); 48 | } 49 | 50 | //TODO: Destruct stuff 51 | ~DataFlow(){ 52 | delete in; 53 | delete out; 54 | delete neighbourSpecificValues; 55 | delete visited; 56 | } 57 | //mapping from basicblock to lattice 58 | typedef ValueMap BlockInOutMap; 59 | //In out sets for a basic block 60 | BlockInOutMap *in; 61 | BlockInOutMap *out; 62 | BlockInOutMap *neighbourSpecificValues; 63 | ValueMap *visited; 64 | 65 | 66 | //TODO: Merge forward and backward analysis methods. They are very similar. 67 | void performForwardAnalysis(Worklist &w){ 68 | BasicBlock *hotBlock = *w.begin(); 69 | w.pop_front(); 70 | (*visited)[hotBlock] = true; 71 | //DEBUG:: 72 | //errs() << "Entring Block " << hotBlock->getName() << "\n"; 73 | int numPred = 0; 74 | for (pred_iterator PI = pred_begin(hotBlock), E = pred_end(hotBlock); PI != E; ++PI){ 75 | ++numPred; 76 | if(PI == pred_begin(hotBlock)){ 77 | *(*in)[hotBlock] = *(*out)[*PI]; 78 | }else{ 79 | meetOp((*in)[hotBlock], (*out)[*PI]); 80 | } 81 | } 82 | 83 | if(numPred == 0) setBoundaryCondition((*in)[hotBlock]); 84 | 85 | 86 | FlowValueType *newOut = transferFn(*hotBlock); 87 | bool changed = false; 88 | changed = (*newOut != *(*out)[hotBlock]); 89 | 90 | if(changed) 91 | *(*out)[hotBlock] = *newOut; 92 | 93 | for (succ_iterator SI = succ_begin(hotBlock), E = succ_end(hotBlock); SI != E; ++SI) { 94 | //TODO: Don't add to worklist if the block is already present 95 | if(changed || !(*visited)[*SI]){ 96 | w.push_back(*SI); 97 | } 98 | } 99 | } 100 | 101 | void performBackwardAnalysis(Worklist &w){ 102 | BasicBlock *hotBlock = *w.begin(); 103 | w.pop_front(); 104 | (*visited)[hotBlock] = true; 105 | //errs() << "Entring Block " << hotBlock->getName() << "\n"; 106 | //out of this basic block is equivalent to in of it's successor 107 | //OUT = Union IN 108 | int numSucc = 0; //to check for the exit node 109 | 110 | for (succ_iterator SI = succ_begin(hotBlock), E = succ_end(hotBlock); SI != E; ++SI) { 111 | numSucc++; 112 | if(SI == succ_begin(hotBlock)){ 113 | *(*out)[hotBlock] = *(*in)[*SI]; //copy the first IN set values 114 | }else{ 115 | meetOp((*out)[hotBlock], (*in)[*SI]); //call the meet operator 116 | } 117 | } 118 | 119 | if((*neighbourSpecificValues).find(hotBlock) != (*neighbourSpecificValues).end() ){ 120 | //for phi node. meet the variables that are live from this specific block 121 | meetOp((*out)[hotBlock], (*neighbourSpecificValues)[hotBlock]); 122 | } 123 | 124 | if(numSucc == 0) setBoundaryCondition((*out)[hotBlock]); //set boundary condition for the exit node. 125 | 126 | FlowValueType *newIn = transferFn(*hotBlock); 127 | 128 | bool changed = false; 129 | changed = ((*newIn) != (*(*in)[hotBlock])); 130 | 131 | if(changed) 132 | *(*in)[hotBlock] = *newIn; 133 | 134 | for (pred_iterator PI = pred_begin(hotBlock), E = pred_end(hotBlock); PI != E; ++PI) { 135 | //make sure that each block is traversed at least one. 136 | if(changed || !(*visited)[*PI]){ 137 | w.push_back(*PI); 138 | } 139 | } 140 | } 141 | 142 | void finalizeBackwardAnalysis(Function &func){ 143 | for (Function::iterator i = func.begin(), e = func.end(); i != e; ++i){ 144 | int numSucc = 0; 145 | BasicBlock *hotBlock = &*i; 146 | if((*neighbourSpecificValues).find(hotBlock) != (*neighbourSpecificValues).end()){ 147 | for (succ_iterator SI = succ_begin(&*i), SE = succ_end(&*i); SI != SE; SI++){ 148 | meetOp((*in)[*SI], (*neighbourSpecificValues)[hotBlock]); 149 | } 150 | } 151 | } 152 | } 153 | 154 | //add just the last block in case of backward analysis 155 | void initializeWorklist(Function &func, Worklist &worklist){ 156 | if(forward){ 157 | BasicBlock& entry = func.getEntryBlock(); 158 | worklist.push_back(&entry); 159 | return; 160 | } 161 | 162 | for (Function::iterator i = func.begin(), e = func.end(); i != e; ++i){ 163 | int numSucc = 0; 164 | 165 | for (succ_iterator SI = succ_begin(&*i), SE = succ_end(&*i); SI != SE; SI++) 166 | numSucc++; 167 | 168 | if(numSucc==0) worklist.push_back(&*i); 169 | } 170 | } 171 | 172 | bool runOnFunction(Function &F){ 173 | visited = new ValueMap(); 174 | for (Function::iterator bi = F.begin(), be = F.end(); bi != be; bi++) { 175 | BasicBlock * bb = &*bi; 176 | 177 | //set the appropriate values for forward and backward flow 178 | //(*in)[bb] -> bit vector::lattice for that block 179 | (*in)[bb] = initializeFlowValue(*bi, IN); 180 | (*out)[bb] = initializeFlowValue(*bi, OUT); 181 | } 182 | 183 | Worklist *worklist = new Worklist(); 184 | initializeWorklist(F,*worklist); 185 | while(!worklist->empty()){ 186 | if(forward) 187 | performForwardAnalysis(*worklist); 188 | else 189 | performBackwardAnalysis(*worklist); 190 | } 191 | finalizeBackwardAnalysis(F); 192 | } 193 | 194 | protected: 195 | //get the boundary conditions for entry nodes 196 | virtual void setBoundaryCondition(FlowValueType*) = 0; 197 | //meet operator. could be union or intersection based on the FlowValueType 198 | virtual void meetOp(FlowValueType* lhs, const FlowValueType* rhs) = 0; 199 | //initial flow values for IN and OUT sets. SetType: IN or OUT 200 | virtual FlowValueType* initializeFlowValue(BasicBlock& b, SetType setType) = 0; 201 | //transer function 202 | virtual FlowValueType* transferFn(BasicBlock& b) = 0; 203 | }; 204 | } 205 | 206 | #endif 207 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment4/sum.c: -------------------------------------------------------------------------------- 1 | #if(0) 2 | void doIt(int a, int b){ 3 | int i,j, inv; 4 | for(i=0;;i++){ 5 | for(j=0;;j++){ 6 | inv = a +b; //2 hoist 7 | if(j 0 ) 60 | { 61 | ret = i * ret; 62 | } 63 | else 64 | { 65 | ret = i - c; 66 | } 67 | 68 | print("%i",ret); 69 | 70 | } 71 | 72 | 73 | return ret + c; 74 | } 75 | 76 | 77 | /* 78 | Following loop has same invariant instruction inside nested loops. 79 | Both the instructions should be lifted and inv = b + 7 should be before inv = b + 3 80 | count = 3 81 | */ 82 | 83 | int myloop1(int k){ 84 | 85 | goto l1; 86 | 87 | int a = 0; int b = 12; int c =12; 88 | l1: 89 | if(k<100) 90 | b = 12; 91 | else 92 | b = 123; 93 | for(;;k++){ 94 | int inv; 95 | for(; ; a++) 96 | { 97 | inv = b+7; 98 | if(a 0 ) 60 | { 61 | ret = i * ret; 62 | } 63 | else 64 | { 65 | ret = i - c; 66 | } 67 | 68 | print("%i",ret); 69 | 70 | } 71 | 72 | 73 | return ret + c; 74 | } 75 | 76 | 77 | /* 78 | Following loop has same invariant instruction inside nested loops. 79 | Both the instructions should be lifted and inv = b + 7 should be before inv = b + 3 80 | count = 3 81 | */ 82 | 83 | int myloop1(int k){ 84 | 85 | goto l1; 86 | 87 | int a = 0; int b = 12; int c =12; 88 | l1: 89 | if(k<100) 90 | b = 12; 91 | else 92 | b = 123; 93 | for(;;k++){ 94 | int inv; 95 | for(; ; a++) 96 | { 97 | inv = b+7; 98 | if(a 45 | #include 46 | #include 47 | #include 48 | 49 | using namespace llvm; 50 | 51 | namespace { 52 | 53 | class Live : public FunctionPass, public DataFlow, public AssemblyAnnotationWriter{ 54 | 55 | public: 56 | static char ID; 57 | 58 | /* set forward false in the constructor for liveness */ 59 | Live() : DataFlow(true), FunctionPass(ID) { 60 | bvIndexToInstrArg = new std::vector(); 61 | valueToBitVectorIndex = new ValueMap(); 62 | instrInSet = new ValueMap(); 63 | } 64 | 65 | /* domain variable. [all the definitions and function arguments in case of liveness] */ 66 | std::vector domain; 67 | std::vector *bvIndexToInstrArg; //map values to their bitvector. Each values has it's own bit vector 68 | ValueMap *valueToBitVectorIndex; //map values (args and variables) to their bit vector index 69 | ValueMap *instrInSet; //In set for a instruction inside basic block : lower level of granularity 70 | 71 | int domainSize; 72 | int numArgs; 73 | int numInstr; 74 | 75 | /*----------------------------------------implement display methods--------------------------------*/ 76 | 77 | virtual void emitBasicBlockStartAnnot(const BasicBlock *bb, formatted_raw_ostream &os) { 78 | os << "; "; 79 | if (!isa(*(bb))) { 80 | const BitVector *bv = (*in)[&*bb]; 81 | for (int i=0; i < bv->size(); i++) { 82 | if ( (*bv)[i] ) { 83 | WriteAsOperand(os, (*bvIndexToInstrArg)[i], false); 84 | os << ", "; 85 | } 86 | } 87 | } 88 | os << "\n"; 89 | } 90 | 91 | virtual void emitInstructionAnnot(const Instruction *i, formatted_raw_ostream &os) { 92 | os << "; "; 93 | if (!isa(*(i))) { 94 | const BitVector *bv = (*instrInSet)[&*i]; 95 | for (int i=0; i < bv->size(); i++) { 96 | if ( (*bv)[i] ) { 97 | 98 | WriteAsOperand(os, (*bvIndexToInstrArg)[i], false); 99 | os << ", "; 100 | } 101 | } 102 | } 103 | os << "\n"; 104 | } 105 | 106 | /*-----------------------------------implement framework methods-----------------------------------*/ 107 | 108 | //Entry block. set the reaching set true for all the arguments. 109 | virtual void setBoundaryCondition(BitVector *blockBoundary) { 110 | *blockBoundary = BitVector(domainSize, false); 111 | for(int i=0; i(*ii)){ 149 | // errs() << "Phi instruction says hi, i look like " << *ii << "\n"; 150 | PHINode* phiNode = cast(&*ii); 151 | for (int incomingIdx = 0; incomingIdx < phiNode->getNumIncomingValues(); incomingIdx++) { 152 | Value* val = phiNode->getIncomingValue(incomingIdx); 153 | if (isa(val) || isa(val)) { 154 | // errs() << val->getName() << " gotta go!\n"; 155 | (*immOut)[(*valueToBitVectorIndex)[val]] = false; 156 | } 157 | } 158 | }*/ 159 | 160 | outNowIn = immOut; 161 | } 162 | 163 | //return a new copy 164 | return new BitVector(*immOut); 165 | } 166 | 167 | bool isDefinition(Instruction *ii) { 168 | return !(isa(ii)) ; 169 | } 170 | 171 | 172 | /*-------------------------------------------------------------------------------------------------*/ 173 | 174 | 175 | /*------------------------------------------------------------------------------------------------*/ 176 | 177 | virtual bool runOnFunction(Function &F) { 178 | domain.clear(); 179 | bvIndexToInstrArg = new std::vector(); 180 | valueToBitVectorIndex = new ValueMap(); 181 | instrInSet = new ValueMap(); 182 | 183 | numArgs = 0; 184 | int index = 0; 185 | for (Function::arg_iterator arg = F.arg_begin(); arg != F.arg_end(); ++arg){ 186 | domain.push_back(arg); 187 | bvIndexToInstrArg->push_back(&*arg); 188 | (*valueToBitVectorIndex)[&*arg] = index; 189 | index++; 190 | numArgs++; 191 | } 192 | 193 | for (inst_iterator instruction = inst_begin(F), e = inst_end(F); instruction != e; ++instruction) { 194 | domain.push_back(&*instruction); 195 | bvIndexToInstrArg->push_back(&*instruction); 196 | (*valueToBitVectorIndex)[&*instruction] = index; 197 | index++; 198 | } 199 | 200 | domainSize = domain.size(); 201 | 202 | //initialize the IN set set inside the block for each instruction. 203 | for (inst_iterator instruction = inst_begin(F), e = inst_end(F); instruction != e; ++instruction) { 204 | (*instrInSet)[&*instruction] = new BitVector(domainSize, false); 205 | } 206 | 207 | DataFlow::runOnFunction(F); //call the analysis method in dataflow 208 | F.print(errs(), this); 209 | return false; //not changing anything 210 | } 211 | 212 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { 213 | AU.setPreservesAll(); 214 | } 215 | 216 | }; 217 | 218 | // LLVM uses the address of this static member to identify the pass, so the 219 | // initialization value is unimportant. 220 | char Live::ID = 0; 221 | 222 | // Register this pass to be used by language front ends. 223 | // This allows this pass to be called using the command: 224 | // clang -c -Xclang -load -Xclang ./Live.so loop.c 225 | static void registerMyPass(const PassManagerBuilder &, 226 | PassManagerBase &PM) { 227 | PM.add(new Live()); 228 | } 229 | RegisterStandardPasses 230 | RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, 231 | registerMyPass); 232 | 233 | // Register the pass name to allow it to be called with opt: 234 | // clang -c -emit-llvm loop.c 235 | // opt -load ./Live.so -live loop.bc > /dev/null 236 | // See http://llvm.org/releases/3.4/docs/WritingAnLLVMPass.html#running-a-pass-with-opt for more info. 237 | RegisterPass X("reach", "reaching definitions pass"); 238 | 239 | } 240 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment3/live.cpp: -------------------------------------------------------------------------------- 1 | // Assignment 3: Live.cpp 2 | // 3 | // 4 | // Based on code from Todd C. Mowry 5 | // Modified by Arthur Peters 6 | //////////////////////////////////////////////////////////////////////////////// 7 | 8 | /****************************************************************************** 9 | Implementation details: 10 | 11 | Liveness: OUT[n] = UNION_{s E succ[n]} IN[s] //meet 12 | IN[n] = GEN[n] U (OUT[n] - KILL[n]) //transfer function 13 | 14 | Flow Direction: Backward 15 | A BitVector stored at each node for IN and OUT. Bit vector contains an entry for all the values 16 | 17 | Boundary Conditions: empty set for flow value. identified by no successors. 18 | 19 | *********************************************************************************/ 20 | 21 | 22 | 23 | #include "llvm/Pass.h" 24 | #include "llvm/PassManager.h" 25 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 26 | #include "llvm/DebugInfo.h" 27 | #include "llvm/IR/Function.h" 28 | #include "llvm/IR/Module.h" 29 | #include "llvm/Support/raw_ostream.h" 30 | #include "llvm/Support/FormattedStream.h" 31 | #include "llvm/Support/InstIterator.h" 32 | #include "llvm/IR/Instruction.h" 33 | #include "llvm/DebugInfo.h" 34 | #include "llvm/Assembly/AssemblyAnnotationWriter.h" 35 | #include "llvm/ADT/BitVector.h" 36 | #include "llvm/ADT/ValueMap.h" 37 | #include "llvm/Support/InstIterator.h" 38 | #include "llvm/Assembly/Writer.h" 39 | #include "llvm/ADT/DenseMap.h" 40 | 41 | 42 | #include "dataflow.h" 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | using namespace llvm; 50 | 51 | namespace { 52 | 53 | class Live : public FunctionPass, public DataFlow, public AssemblyAnnotationWriter{ 54 | 55 | public: 56 | static char ID; 57 | 58 | /* set forward false in the constructor for liveness */ 59 | Live() : DataFlow(false), FunctionPass(ID) { 60 | bvIndexToInstrArg = new std::vector(); 61 | valueToBitVectorIndex = new ValueMap(); 62 | instrInSet = new ValueMap(); 63 | } 64 | 65 | /* domain variable. [all the definitions and function arguments in case of liveness] */ 66 | std::vector domain; 67 | std::vector *bvIndexToInstrArg; //map values to their bitvector. Each values has it's own bit vector 68 | ValueMap *valueToBitVectorIndex; //map values (args and variables) to their bit vector index 69 | ValueMap *instrInSet; //In set for a instruction inside basic block : lower level of granularity 70 | 71 | int domainSize; 72 | int numArgs; 73 | int numInstr; 74 | 75 | /*----------------------------------------implement display methods--------------------------------*/ 76 | 77 | virtual void emitBasicBlockStartAnnot(const BasicBlock *bb, formatted_raw_ostream &os) { 78 | os << "; "; 79 | if (!isa(*(bb))) { 80 | const BitVector *bv = (*in)[&*bb]; 81 | for (int i=0; i < bv->size(); i++) { 82 | if ( (*bv)[i] ) { 83 | WriteAsOperand(os, (*bvIndexToInstrArg)[i], false); 84 | os << ", "; 85 | } 86 | } 87 | } 88 | os << "\n"; 89 | } 90 | 91 | virtual void emitInstructionAnnot(const Instruction *i, formatted_raw_ostream &os) { 92 | os << "; "; 93 | if (!isa(*(i))) { 94 | const BitVector *bv = (*instrInSet)[&*i]; 95 | for (int i=0; i < bv->size(); i++) { 96 | if ( (*bv)[i] ) { 97 | 98 | WriteAsOperand(os, (*bvIndexToInstrArg)[i], false); 99 | os << ", "; 100 | } 101 | } 102 | } 103 | os << "\n"; 104 | } 105 | 106 | /*-----------------------------------implement framework methods-----------------------------------*/ 107 | 108 | //set the boundary condition for block. exit block in this case. 109 | //an empty set for all nodes in case of backward analysis. 110 | //TODO check the validity 111 | //call the explicit constructor. Since the bitvector has already been initialized 112 | virtual void setBoundaryCondition(BitVector *blockBoundary) { 113 | *blockBoundary = BitVector(domainSize, false); 114 | } 115 | 116 | //union aka bitwise OR. operator '|=' overriden in BitVector class 117 | virtual void meetOp(BitVector* lhs, const BitVector* rhs){ 118 | *lhs |= *rhs; 119 | } 120 | 121 | //empty set initially. each bit represent a value 122 | virtual BitVector* initializeFlowValue(BasicBlock& b, SetType setType){ 123 | return new BitVector(domainSize, false); 124 | } 125 | 126 | 127 | //transfer function: 128 | //IN[n] = USE[n] U (OUT[n] - DEF[n]) //transfer function 129 | 130 | virtual BitVector* transferFn(BasicBlock& bb) { 131 | BitVector* outNowIn = new BitVector(*((*out)[&bb])); 132 | 133 | BitVector* immIn = outNowIn; // for empty blocks 134 | Instruction* tempInst; 135 | bool breakme=false; 136 | // go through instructions in reverse 137 | BasicBlock::iterator ii = --(bb.end()), ib = bb.begin(); 138 | while (true) { 139 | 140 | // inherit data from next instruction 141 | tempInst = &*ii; 142 | immIn = (*instrInSet)[tempInst]; 143 | *immIn = *outNowIn; 144 | 145 | // if this instruction is a new definition, remove it 146 | if (isDefinition(tempInst)){ 147 | (*immIn)[(*valueToBitVectorIndex)[tempInst]] = false; 148 | } 149 | 150 | // add the arguments, unless it is a phi node 151 | if (!isa(*ii)) { 152 | User::op_iterator OI, OE; 153 | for (OI = tempInst->op_begin(), OE=tempInst->op_end(); OI != OE; ++OI) { 154 | if (isa(*OI) || isa(*OI)) { 155 | (*immIn)[(*valueToBitVectorIndex)[*OI]] = true; 156 | } 157 | } 158 | }else if(isa(*ii)){ 159 | PHINode* phiNode = cast(&*ii); 160 | for (int incomingIdx = 0; incomingIdx < phiNode->getNumIncomingValues(); incomingIdx++) { 161 | Value* val = phiNode->getIncomingValue(incomingIdx); 162 | if (isa(val) || isa(val)) { 163 | int valIdx = (*valueToBitVectorIndex)[val]; 164 | BasicBlock* incomingBlock = phiNode->getIncomingBlock(incomingIdx); 165 | if ((*neighbourSpecificValues).find(incomingBlock) == (*neighbourSpecificValues).end()) 166 | (*neighbourSpecificValues)[incomingBlock] = new BitVector(domainSize); 167 | (*(*neighbourSpecificValues)[incomingBlock]).set(valIdx); 168 | } 169 | } 170 | } 171 | 172 | outNowIn = immIn; 173 | 174 | if (ii == ib) break; 175 | 176 | --ii; 177 | } 178 | 179 | return immIn; 180 | } 181 | 182 | bool isDefinition(Instruction *ii) { 183 | return !(isa(ii)) ; 184 | } 185 | 186 | 187 | /*-------------------------------------------------------------------------------------------------*/ 188 | 189 | 190 | /*------------------------------------------------------------------------------------------------*/ 191 | 192 | virtual bool runOnFunction(Function &F) { 193 | domain.clear(); 194 | bvIndexToInstrArg = new std::vector(); 195 | valueToBitVectorIndex = new ValueMap(); 196 | instrInSet = new ValueMap(); 197 | 198 | int index = 0; 199 | for (Function::arg_iterator arg = F.arg_begin(); arg != F.arg_end(); ++arg){ 200 | domain.push_back(arg); 201 | bvIndexToInstrArg->push_back(&*arg); 202 | (*valueToBitVectorIndex)[&*arg] = index; 203 | index++; 204 | } 205 | 206 | for (inst_iterator instruction = inst_begin(F), e = inst_end(F); instruction != e; ++instruction) { 207 | domain.push_back(&*instruction); 208 | bvIndexToInstrArg->push_back(&*instruction); 209 | (*valueToBitVectorIndex)[&*instruction] = index; 210 | index++; 211 | } 212 | 213 | domainSize = domain.size(); 214 | 215 | //initialize the IN set set inside the block for each instruction. 216 | for (inst_iterator instruction = inst_begin(F), e = inst_end(F); instruction != e; ++instruction) { 217 | (*instrInSet)[&*instruction] = new BitVector(domainSize, false); 218 | } 219 | 220 | DataFlow::runOnFunction(F); //call the analysis method in dataflow 221 | F.print(errs(), this); 222 | return false; //not changing anything 223 | } 224 | 225 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { 226 | AU.setPreservesAll(); 227 | } 228 | 229 | }; 230 | 231 | // LLVM uses the address of this static member to identify the pass, so the 232 | // initialization value is unimportant. 233 | char Live::ID = 0; 234 | 235 | // Register this pass to be used by language front ends. 236 | // This allows this pass to be called using the command: 237 | // clang -c -Xclang -load -Xclang ./Live.so loop.c 238 | static void registerMyPass(const PassManagerBuilder &, 239 | PassManagerBase &PM) { 240 | PM.add(new Live()); 241 | } 242 | RegisterStandardPasses 243 | RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, 244 | registerMyPass); 245 | 246 | // Register the pass name to allow it to be called with opt: 247 | // clang -c -emit-llvm loop.c 248 | // opt -load ./Live.so -live loop.bc > /dev/null 249 | // See http://llvm.org/releases/3.4/docs/WritingAnLLVMPass.html#running-a-pass-with-opt for more info. 250 | RegisterPass X("live", "liveness pass"); 251 | 252 | } 253 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment4/dce-pass.cpp: -------------------------------------------------------------------------------- 1 | // Assignment 3: Live.cpp 2 | // 3 | // 4 | // Based on code from Todd C. Mowry 5 | // Modified by Arthur Peters 6 | //////////////////////////////////////////////////////////////////////////////// 7 | 8 | /****************************************************************************** 9 | Implementation details: 10 | 11 | Liveness: OUT[n] = UNION_{s E succ[n]} IN[s] //meet 12 | IN[n] = GEN[n] U (OUT[n] - KILL[n]) //transfer function 13 | 14 | Flow Direction: Backward 15 | A BitVector stored at each node for IN and OUT. Bit vector contains an entry for all the values 16 | 17 | Boundary Conditions: empty set for flow value. identified by no successors. 18 | 19 | *********************************************************************************/ 20 | 21 | #define DEBUG_TYPE "dce-pass" 22 | 23 | 24 | #include "llvm/Pass.h" 25 | #include "llvm/PassManager.h" 26 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 27 | #include "llvm/DebugInfo.h" 28 | #include "llvm/IR/Function.h" 29 | #include "llvm/IR/Module.h" 30 | #include "llvm/Support/raw_ostream.h" 31 | #include "llvm/Support/FormattedStream.h" 32 | #include "llvm/Support/InstIterator.h" 33 | #include "llvm/IR/Instruction.h" 34 | #include "llvm/DebugInfo.h" 35 | #include "llvm/Assembly/AssemblyAnnotationWriter.h" 36 | #include "llvm/ADT/BitVector.h" 37 | #include "llvm/ADT/ValueMap.h" 38 | #include "llvm/Support/InstIterator.h" 39 | #include "llvm/Assembly/Writer.h" 40 | #include "llvm/ADT/DenseMap.h" 41 | #include "llvm/IR/Constants.h" 42 | #include "llvm/ADT/Statistic.h" 43 | 44 | 45 | #include "dataflow.h" 46 | 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | 54 | STATISTIC(NumElim, "The # of instructions eliminated"); 55 | 56 | using namespace llvm; 57 | 58 | namespace { 59 | 60 | class Live : public FunctionPass, public DataFlow, public AssemblyAnnotationWriter{ 61 | 62 | public: 63 | static char ID; 64 | 65 | /* set forward false in the constructor for liveness */ 66 | Live() : DataFlow(false), FunctionPass(ID) { 67 | bvIndexToInstrArg = new std::vector(); 68 | valueToBitVectorIndex = new ValueMap(); 69 | instrInSet = new ValueMap(); 70 | delete_queue = new std::queue(); 71 | deletedSomething = false; 72 | } 73 | 74 | /* domain variable. [all the definitions and function arguments in case of liveness] */ 75 | std::vector domain; 76 | std::vector *bvIndexToInstrArg; //map values to their bitvector. Each values has it's own bit vector 77 | ValueMap *valueToBitVectorIndex; //map values (args and variables) to their bit vector index 78 | ValueMap *instrInSet; //In set for a instruction inside basic block : lower level of granularity 79 | std::queue * delete_queue; 80 | 81 | int domainSize; 82 | int numArgs; 83 | int numInstr; 84 | bool deletedSomething; 85 | 86 | /*----------------------------------------implement display methods--------------------------------*/ 87 | 88 | virtual void emitBasicBlockStartAnnot(const BasicBlock *bb, formatted_raw_ostream &os) { 89 | os << "; "; 90 | if (!isa(*(bb))) { 91 | const BitVector *bv = (*in)[&*bb]; 92 | for (int i=0; i < bv->size(); i++) { 93 | if ( (*bv)[i] ) { 94 | WriteAsOperand(os, (*bvIndexToInstrArg)[i], false); 95 | os << ", "; 96 | } 97 | } 98 | } 99 | os << "\n"; 100 | } 101 | 102 | virtual void emitInstructionAnnot(const Instruction *i, formatted_raw_ostream &os) { 103 | os << "; "; 104 | 105 | if (!isa(*(i))) { 106 | const BitVector *bv = (*instrInSet)[&*i]; 107 | for (int i=0; i < bv->size(); i++) { 108 | if ( (*bv)[i] ) { 109 | WriteAsOperand(os, (*bvIndexToInstrArg)[i], false); 110 | os << ", "; 111 | } 112 | } 113 | } 114 | os << "\n"; 115 | } 116 | 117 | /*-----------------------------------implement framework methods-----------------------------------*/ 118 | 119 | //at boundary nobody can be alive 120 | virtual void setBoundaryCondition(BitVector *blockBoundary) { 121 | *blockBoundary = BitVector(domainSize, true); 122 | } 123 | 124 | //take the intersection. It's a must analysis. we are removing stuff here, better be double sure. 125 | virtual void meetOp(BitVector* lhs, const BitVector* rhs){ 126 | *lhs &= *rhs; 127 | } 128 | 129 | //be optimistic. Assume variable is dead initially 130 | virtual BitVector* initializeFlowValue(BasicBlock& b, SetType setType){ 131 | return new BitVector(domainSize, true); 132 | } 133 | 134 | 135 | //transfer function: 136 | //IN[n] = USE[n] U (OUT[n] - DEF[n]) //transfer function 137 | 138 | virtual BitVector* transferFn(BasicBlock& bb) { 139 | BitVector* outNowIn = new BitVector(*((*out)[&bb])); 140 | 141 | BitVector* immIn = outNowIn; // for empty blocks 142 | Instruction* tempInst; 143 | bool breakme=false; 144 | // go through instructions in reverse 145 | BasicBlock::iterator ii = --(bb.end()), ib = bb.begin(); 146 | while (true) { 147 | 148 | // inherit data from next instruction 149 | tempInst = &*ii; 150 | immIn = (*instrInSet)[tempInst]; 151 | *immIn = *outNowIn; 152 | 153 | if (!isDefinition(tempInst) || !(*immIn)[(*valueToBitVectorIndex)[tempInst]]) 154 | { 155 | User::op_iterator OI, OE; 156 | for (OI = tempInst->op_begin(), OE=tempInst->op_end(); OI != OE; ++OI) 157 | { 158 | if (isa(*OI) || isa(*OI)) 159 | { 160 | (*immIn)[(*valueToBitVectorIndex)[*OI]] = false; 161 | } 162 | } 163 | } 164 | 165 | outNowIn = immIn; 166 | 167 | if (ii == ib) break; 168 | 169 | --ii; 170 | } 171 | 172 | return immIn; 173 | } 174 | 175 | bool isDefinition(Instruction *ii) { 176 | return !(isa(ii) || isa(ii)) ; 177 | } 178 | 179 | 180 | /*-----------------------------------------Deletion methods----------------------------------------*/ 181 | 182 | //remove the instruction from parent and replace all uses 183 | void processBlockForDeletion(BasicBlock *blk, BitVector& killed) 184 | { 185 | BasicBlock::InstListType &blist = blk->getInstList(); 186 | for(BasicBlock::InstListType::iterator it = blist.begin(), e = blist.end(); it != e;){ 187 | Instruction& i(*it); 188 | 189 | BasicBlock::InstListType::iterator next = it; 190 | ++next; 191 | 192 | if(isDefinition(&i) && (killed)[(*valueToBitVectorIndex)[&i]]){ 193 | (*instrInSet).erase(&i); //value is being used in the map. Needs to be deleted so that it can be removed 194 | errs() << "Removing instruction: " << i << "\n"; 195 | i.replaceAllUsesWith(UndefValue::get(i.getType())); 196 | i.eraseFromParent(); 197 | deletedSomething = true; 198 | ++NumElim; 199 | } 200 | it = next; 201 | } 202 | } 203 | 204 | 205 | bool removeTheDead(Function &fun){ 206 | BitVector *killed = (*in)[&(fun.getEntryBlock())]; 207 | 208 | std::queue work_list; 209 | std::set visited; 210 | 211 | //insert the last block in the worklist 212 | for(Function::iterator i(fun.begin()), e = fun.end(); i != e; ++i) { 213 | int numSucc = 0; 214 | 215 | for (succ_iterator SI = succ_begin(&*i), SE = succ_end(&*i); SI != SE; SI++) 216 | numSucc++; 217 | 218 | if(numSucc==0){ 219 | work_list.push(&*i); 220 | visited.insert(&*i); 221 | } 222 | } 223 | 224 | //process the blocks in backward direction 225 | while (!work_list.empty()) { 226 | BasicBlock *hotBlock = work_list.front(); 227 | work_list.pop(); 228 | 229 | processBlockForDeletion(hotBlock, *killed); 230 | 231 | for (pred_iterator PI = pred_begin(hotBlock), E = pred_end(hotBlock); PI != E; ++PI) { 232 | BasicBlock *tempBlk = *PI; 233 | if(visited.find(tempBlk) == visited.end()){ 234 | work_list.push(tempBlk); 235 | visited.insert(tempBlk); 236 | } 237 | } 238 | } 239 | //now every instruction is freed of its uses and can be deleted. 240 | return deletedSomething; 241 | 242 | } 243 | 244 | /*------------------------------------------Print bitvector for debuggin---------------------------*/ 245 | 246 | void printBv(const BitVector &bv){ 247 | errs() << "\n { "; 248 | for(int i=0;i(); 261 | valueToBitVectorIndex = new ValueMap(); 262 | instrInSet = new ValueMap(); 263 | delete_queue = new std::queue(); 264 | 265 | int index = 0; 266 | for (Function::arg_iterator arg = F.arg_begin(); arg != F.arg_end(); ++arg){ 267 | domain.push_back(arg); 268 | bvIndexToInstrArg->push_back(&*arg); 269 | (*valueToBitVectorIndex)[&*arg] = index; 270 | index++; 271 | } 272 | 273 | for (inst_iterator instruction = inst_begin(F), e = inst_end(F); instruction != e; ++instruction) { 274 | if (isDefinition(&*instruction)) { 275 | domain.push_back(&*instruction); 276 | bvIndexToInstrArg->push_back(&*instruction); 277 | (*valueToBitVectorIndex)[&*instruction] = index; 278 | index++; 279 | } 280 | } 281 | 282 | domainSize = domain.size(); 283 | 284 | //initialize the IN set set inside the block for each instruction. 285 | for (inst_iterator instruction = inst_begin(F), e = inst_end(F); instruction != e; ++instruction) { 286 | (*instrInSet)[&*instruction] = new BitVector(domainSize, true); 287 | } 288 | 289 | //Run the liveness analysis to determine the faint variables. 290 | DataFlow::runOnFunction(F); 291 | F.print(errs(), this); 292 | return removeTheDead(F); 293 | } 294 | 295 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { 296 | AU.setPreservesAll(); 297 | } 298 | 299 | }; 300 | 301 | // LLVM uses the address of this static member to identify the pass, so the 302 | // initialization value is unimportant. 303 | char Live::ID = 0; 304 | 305 | // Register this pass to be used by language front ends. 306 | // This allows this pass to be called using the command: 307 | // clang -c -Xclang -load -Xclang ./Live.so loop.c 308 | static void registerMyPass(const PassManagerBuilder &, 309 | PassManagerBase &PM) { 310 | PM.add(new Live()); 311 | } 312 | RegisterStandardPasses 313 | RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, 314 | registerMyPass); 315 | 316 | // Register the pass name to allow it to be called with opt: 317 | // clang -c -emit-llvm loop.c 318 | // opt -load ./Live.so -live loop.bc > /dev/null 319 | // See http://llvm.org/releases/3.4/docs/WritingAnLLVMPass.html#running-a-pass-with-opt for more info. 320 | RegisterPass X("dce-pass", "liveness pass"); 321 | 322 | } 323 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment4/licm-backout.cpp: -------------------------------------------------------------------------------- 1 | // Assignment 4: LoopICM.cpp 2 | // 3 | // 4 | // Based on code from Todd C. Mowry 5 | // Modified by Arthur Peters 6 | //////////////////////////////////////////////////////////////////////////////// 7 | 8 | /****************************************************************************** 9 | 10 | *********************************************************************************/ 11 | 12 | 13 | 14 | #include "llvm/Pass.h" 15 | #include "llvm/PassManager.h" 16 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 17 | #include "llvm/DebugInfo.h" 18 | #include "llvm/IR/Function.h" 19 | #include "llvm/IR/Module.h" 20 | #include "llvm/Support/raw_ostream.h" 21 | #include "llvm/Support/FormattedStream.h" 22 | #include "llvm/Support/InstIterator.h" 23 | #include "llvm/IR/Instruction.h" 24 | #include "llvm/DebugInfo.h" 25 | #include "llvm/Assembly/AssemblyAnnotationWriter.h" 26 | #include "llvm/ADT/BitVector.h" 27 | #include "llvm/ADT/ValueMap.h" 28 | #include "llvm/Support/InstIterator.h" 29 | #include "llvm/Assembly/Writer.h" 30 | #include "llvm/ADT/DenseMap.h" 31 | #include "llvm/Analysis/LoopInfo.h" 32 | 33 | 34 | #include "dataflow.h" 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | using namespace llvm; 42 | 43 | namespace { 44 | 45 | class LoopICM : public FunctionPass, public AssemblyAnnotationWriter{ 46 | 47 | public: 48 | static char ID; 49 | 50 | /* set forward false in the constructor for liveness */ 51 | LoopICM() : FunctionPass(ID) { 52 | bvIndexToInstrArg = new std::vector(); 53 | valueToBitVectorIndex = new ValueMap(); 54 | instrInSet = new ValueMap(); 55 | } 56 | 57 | /* domain variable. [all the definitions and function arguments in case of liveness] */ 58 | std::vector domain; 59 | std::vector *bvIndexToInstrArg; //map values to their bitvector. Each values has it's own bit vector 60 | ValueMap *valueToBitVectorIndex; //map values (args and variables) to their bit vector index 61 | ValueMap *instrInSet; //In set for a instruction inside basic block : lower level of granularity 62 | 63 | typedef ValueMap BlockInOutMap; 64 | BlockInOutMap *rdIn; 65 | BlockInOutMap *rdOut; 66 | 67 | class ReachingDef : public DataFlow{ 68 | public: 69 | ReachingDef(int doSize, int nArgs, ValueMap& insInSet, 70 | std::vector& bvIndex, ValueMap& vToBv, BlockInOutMap *rdin, BlockInOutMap *rdout) : DataFlow(true) { 71 | domainSize = doSize; 72 | numArgs = nArgs; 73 | instrInSet = &insInSet; 74 | bvIndexToInstrArg = &bvIndex; 75 | valueToBitVectorIndex = &vToBv; 76 | localrdin = rdin; 77 | locardout = rdout; 78 | } 79 | typedef ValueMap BlockInOutMap; 80 | BlockInOutMap *localrdin; 81 | BlockInOutMap *locardout; 82 | int domainSize; 83 | int numArgs; 84 | ValueMap *instrInSet; 85 | std::vector *bvIndexToInstrArg; //map values to their bitvector. Each values has it's own bit vector 86 | ValueMap *valueToBitVectorIndex; //map values (args and variables) to their bit vector index 87 | 88 | void run(Function &F){ 89 | DataFlow::runOnFunction(F); 90 | localrdin = in; 91 | locardout = out; 92 | } 93 | 94 | //Entry block. set the reaching set true for all the arguments. 95 | virtual void setBoundaryCondition(BitVector *blockBoundary) { 96 | *blockBoundary = BitVector(domainSize, false); 97 | for(int i=0; i(*cint, generalZeroOne)) 90 | return ConstantType::get(cint->getContext(), generalZeroOne); 91 | } 92 | else if(cint = dyn_cast(operand1)){ //operand 1 is 0 and it's multiplication 93 | if(id_compare(*cint, generalZeroOne)) 94 | return ConstantType::get(cint->getContext(), generalZeroOne); 95 | } 96 | }else if(identity == 1){ 97 | if(cint = dyn_cast(operand2)){ //operand 2 is 1 and it's multiplication 98 | if(id_compare(*cint, generalZeroOne)) 99 | return cint; 100 | } 101 | else if(cint = dyn_cast(operand1)){ //operand 1 is 0 and it's multiplication 102 | if(id_compare(*cint, generalZeroOne)) 103 | return cint; 104 | } 105 | 106 | } 107 | break; 108 | } 109 | case 1:{ //division 110 | 111 | if(identity == 0){ 112 | if(cint = dyn_cast(operand1)){ //operand 1 is 0 and it's division 0 / X = 0 113 | if(id_compare(*cint, generalZeroOne)) 114 | return ConstantType::get(cint->getContext(), generalZeroOne); 115 | } 116 | }else if(identity == 1){ 117 | if(cint = dyn_cast(operand2)){ //operand 2 is 1 and it's division X / 1 = X 118 | if(id_compare(*cint, generalZeroOne)) 119 | return cint; //if operand 2 is 1 return X 120 | } 121 | } 122 | break; 123 | } 124 | } 125 | 126 | return NULL; 127 | } 128 | 129 | 130 | void makeTheChanges(BasicBlock::iterator &ib, Value* val){ 131 | ib->replaceAllUsesWith(val); 132 | BasicBlock::iterator j = ib; 133 | ++ib; 134 | j->eraseFromParent(); 135 | if(ib != ib->getParent()->begin()){ 136 | --ib; 137 | }else{ 138 | replay = true; 139 | } 140 | } 141 | 142 | void reduce_strength(BasicBlock::iterator &ib, ConstantInt &cint, Value &other, unsigned opcode){ 143 | ++NumStrReductions; 144 | APInt apint = cint.getValue(); 145 | unsigned reduction_factor = apint.logBase2(); 146 | BinaryOperator* shift_instruction ; 147 | if(opcode == Instruction::Mul) 148 | shift_instruction = BinaryOperator::Create( Instruction::Shl, &other, ConstantInt::get(cint.getType(), reduction_factor, false)); 149 | else 150 | shift_instruction = BinaryOperator::Create( Instruction::AShr, &other, ConstantInt::get(cint.getType(), reduction_factor, false)); 151 | ib->getParent()->getInstList().insertAfter(ib, shift_instruction); 152 | makeTheChanges(ib, shift_instruction); 153 | ib++; 154 | } 155 | bool can_reduce_strength(ConstantInt& tcint){ 156 | APInt op1 = tcint.getValue(); 157 | if(op1.isPowerOf2()) return true; 158 | return false; 159 | } 160 | 161 | ConstantInt* fold_constants(unsigned operation, ConstantInt *op1, ConstantInt *op2){ 162 | switch(operation){ 163 | case Instruction::Add: 164 | return ConstantInt::get(op1->getContext(), op1->getValue() + op2->getValue()); 165 | case Instruction::Sub: 166 | return ConstantInt::get(op1->getContext(), op1->getValue() + op2->getValue()); 167 | case Instruction::Mul: 168 | return ConstantInt::get(op1->getContext(), op1->getValue() * op2->getValue()); 169 | case Instruction::UDiv: 170 | return ConstantInt::get(op1->getContext(), op1->getValue().udiv(op2->getValue())); 171 | case Instruction::SDiv: 172 | return ConstantInt::get(op1->getContext(), op1->getValue().sdiv(op2->getValue())); 173 | 174 | } 175 | return NULL; 176 | errs() << "An opportunity to fold constants here.." ; 177 | 178 | } 179 | 180 | 181 | class LocalOpts : public FunctionPass{ 182 | 183 | public: 184 | static char ID; 185 | LocalOpts() : FunctionPass(ID) { } //default constructor 186 | ~LocalOpts() { } 187 | 188 | /* Method to print details for a all the functions in a module */ 189 | void printFunctionDetails(Function &F) { 190 | int arg_size = F.arg_size(); 191 | int num_call_sites = F.getNumUses(); 192 | int num_basic_blocks = F.size(); //defined in value class. 193 | /*count the number of instructions.*/ 194 | int number_of_instructions = 0; 195 | for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) 196 | number_of_instructions += 1; 197 | 198 | errs() << F.getName() <<": arguments=" << arg_size << " call sites=" << num_call_sites << " basic blocks=" << num_basic_blocks << " instructions=" << number_of_instructions << "\n\n"; 199 | } 200 | 201 | 202 | 203 | void runOnBasicBlock(BasicBlock &blk){ 204 | for (BasicBlock::iterator i = blk.begin(), e = blk.end(); i != e; ++i){ 205 | if(replay){ 206 | i = blk.begin(); 207 | replay = false; 208 | } 209 | 210 | Instruction *ii= dyn_cast(i); 211 | 212 | Value *v; 213 | IntegerType *intype; 214 | intype = dyn_cast(i->getType()); 215 | 216 | switch(ii->getOpcode()){ 217 | case Instruction::Add: 218 | v = algIdentityAS(*ii, getZeroOne(intype->getBitWidth(),0),0); 219 | if(v) { 220 | makeTheChanges(i, v); 221 | ++NumXForms; 222 | continue; 223 | } 224 | 225 | break; //X+0 = 0+X = X 226 | case Instruction::Sub: { 227 | //check for x-x thing 228 | ConstantInt * zero = ConstantInt::get(intype->getContext(), getZeroOne(intype->getBitWidth(),0)); 229 | if(v = varConVar(*ii, zero)) { 230 | makeTheChanges(i, v); 231 | ++NumXForms; 232 | continue; 233 | } 234 | 235 | else if(v = algIdentityAS(*ii, getZeroOne(intype->getBitWidth(),0), 1)) { 236 | makeTheChanges(i, v); 237 | ++NumXForms; 238 | continue; 239 | } 240 | break; //X-0 = X; 241 | } 242 | case Instruction::Mul:{ 243 | //X * 1 = X , 1 * X = X; operation = 0 identity = 1 244 | if(v = algIdentityMD(*ii, getZeroOne(intype->getBitWidth(),1), 0, 1)) { 245 | makeTheChanges(i, v); 246 | ++NumXForms; 247 | continue; 248 | 249 | } 250 | else if (v = algIdentityMD(*ii, getZeroOne(intype->getBitWidth(),0), 0, 0)){ //X * 0 = 0, 0 * X = 0 OP=0 ID = 0 251 | makeTheChanges(i, v); 252 | ++NumXForms; 253 | continue; 254 | } 255 | break; //X*1 = X; 1*X=X 256 | } 257 | 258 | case Instruction::UDiv: 259 | case Instruction::SDiv:{ 260 | 261 | ConstantInt * one = ConstantInt::get(intype->getContext(), getZeroOne(intype->getBitWidth(),1)); 262 | 263 | if(v = varConVar(*ii, one)) { 264 | makeTheChanges(i, v); 265 | ++NumXForms; 266 | continue; 267 | } 268 | 269 | else if(v = algIdentityMD(*ii, getZeroOne(intype->getBitWidth(),1),1,1))// X / 1 = X; OP=1 ID=1 270 | { 271 | makeTheChanges(i, v); 272 | ++NumXForms; 273 | continue; 274 | } 275 | else if(v = algIdentityMD(*ii, getZeroOne(intype->getBitWidth(),0),1,0)) // X / 1 = X OP=1 ID=0 276 | { 277 | makeTheChanges(i,v); 278 | ++NumXForms; 279 | continue; 280 | } 281 | break; 282 | } 283 | default: break; 284 | } 285 | 286 | //Constant Folding 287 | if((ii->getNumOperands() == 2) && isa(ii->getOperand(0)) && isa(ii->getOperand(1))){ 288 | Value *v1 = fold_constants(ii->getOpcode(), dyn_cast(ii->getOperand(0)), dyn_cast(ii->getOperand(1))); 289 | if(v1) { 290 | makeTheChanges(i,v1); 291 | ++NumConstFolds; 292 | continue; 293 | } 294 | } 295 | 296 | //strength reduction 297 | switch(ii->getOpcode()){ 298 | case Instruction::UDiv: 299 | case Instruction::SDiv: 300 | case Instruction::Mul:{ 301 | ConstantInt *tcint; 302 | Value *other; 303 | if((tcint = dyn_cast(ii->getOperand(0))) && can_reduce_strength(*tcint)){ 304 | other = ii->getOperand(0); 305 | reduce_strength(i, *tcint, *other,ii->getOpcode()); 306 | continue; 307 | } 308 | else if((tcint = dyn_cast(ii->getOperand(1))) && can_reduce_strength(*tcint)){ 309 | other = ii->getOperand(0); 310 | reduce_strength(i, *tcint, *other,ii->getOpcode()); 311 | continue; 312 | } 313 | break; 314 | } 315 | default: break; 316 | } 317 | 318 | 319 | } 320 | } 321 | 322 | virtual bool runOnFunction(Function &func){ 323 | //errs() << "Function: " << func.getName() << "\n"; 324 | for (Function::iterator i = func.begin(), e = func.end(); i != e; ++i){ //iterating over the basic blocks 325 | runOnBasicBlock(*i); 326 | //print_basic_block_info(*i); 327 | } 328 | return true; 329 | } 330 | 331 | 332 | // We don't modify the program, so we preserve all analyses 333 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { 334 | AU.setPreservesAll(); 335 | } 336 | 337 | private: 338 | //helper functions 339 | void print_basic_block_info(BasicBlock &b){ 340 | errs() << "Basic block (name=" << b.getName() << ") has " << b.size() << " instructions.\n"; 341 | 342 | } 343 | }; 344 | 345 | char LocalOpts::ID = 0; 346 | 347 | static void registerMyPass(const PassManagerBuilder &, 348 | PassManagerBase &PM) { 349 | PM.add(new LocalOpts()); 350 | } 351 | RegisterStandardPasses 352 | RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, 353 | registerMyPass); 354 | 355 | RegisterPass X("my-local-opts", "Local Optimizations"); 356 | 357 | } 358 | -------------------------------------------------------------------------------- /spring2014-compilers/assignment4/licm.cpp: -------------------------------------------------------------------------------- 1 | // Assignment 4: LoopICM.cpp 2 | // 3 | // 4 | // Based on code from Todd C. Mowry 5 | // Modified by Arthur Peters 6 | //////////////////////////////////////////////////////////////////////////////// 7 | 8 | /****************************************************************************** 9 | 10 | *********************************************************************************/ 11 | 12 | 13 | #define DEBUG_TYPE "licm-pass" 14 | 15 | #include "llvm/Pass.h" 16 | #include "llvm/PassManager.h" 17 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 18 | #include "llvm/DebugInfo.h" 19 | #include "llvm/IR/Function.h" 20 | #include "llvm/IR/Module.h" 21 | #include "llvm/Support/raw_ostream.h" 22 | #include "llvm/Support/FormattedStream.h" 23 | #include "llvm/Support/InstIterator.h" 24 | #include "llvm/IR/Instruction.h" 25 | #include "llvm/DebugInfo.h" 26 | #include "llvm/Assembly/AssemblyAnnotationWriter.h" 27 | #include "llvm/ADT/BitVector.h" 28 | #include "llvm/ADT/ValueMap.h" 29 | #include "llvm/Support/InstIterator.h" 30 | #include "llvm/Assembly/Writer.h" 31 | #include "llvm/ADT/DenseMap.h" 32 | #include "llvm/Analysis/LoopInfo.h" 33 | #include "llvm/ADT/Statistic.h" 34 | 35 | 36 | #include "dataflow.h" 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | STATISTIC(NumHoisted, "The # of hoists. increaments by 1 for each level hoist."); 44 | 45 | using namespace llvm; 46 | 47 | namespace { 48 | 49 | class LoopICM : public FunctionPass, public DataFlow{ 50 | 51 | public: 52 | static char ID; 53 | 54 | /* set forward false in the constructor for liveness */ 55 | LoopICM() : DataFlow(true), FunctionPass(ID) { 56 | bvIndexToInstrArg = new std::vector(); 57 | valueToBitVectorIndex = new ValueMap(); 58 | instrInSet = new ValueMap(); 59 | modifed = false; 60 | } 61 | 62 | /* domain variable. [all the definitions and function arguments in case of liveness] */ 63 | std::vector domain; 64 | std::vector *bvIndexToInstrArg; //map values to their bitvector. Each values has it's own bit vector 65 | ValueMap *valueToBitVectorIndex; //map values (args and variables) to their bit vector index 66 | ValueMap *instrInSet; //In set for a instruction inside basic block : lower level of granularity 67 | 68 | int domainSize; 69 | int numArgs; 70 | int numInstr; 71 | bool modifed; 72 | 73 | /*------------------ implement framework methods for reaching definitions---------------------------*/ 74 | 75 | //Entry block. set the reaching set true for all the arguments. 76 | virtual void setBoundaryCondition(BitVector *blockBoundary) { 77 | *blockBoundary = BitVector(domainSize, false); 78 | for(int i=0; i