Replies: 18 comments
-
Summarize what you did.This uses a library within the Transforms/Utils directory to see whether an instruction is trivially dead, would be trivially dead, or would be trivially dead on unused paths. Explain how you know your implementation works—how did you test it? Which test inputs did you use? Do you have any quantitative results to report?
What was the hardest part of the task? How did you solve this problem?
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
SummaryFor this task, I implemented what I call a de-optimization. You might ask yourself, what the point of something like this is, which is a very good question. Please let me know if you think of something. Nevertheless, my de-optimization finds add instructions where one of the operands is a constant (say n). It then replaces that add instruction with n instructions that add 1 to the non constant operand. Implementation and TestingMy implementation is fairly straightforward. I loop through all instructions in the program and for each add instruction, I check if either operands are a constant. If so, I loop through that many times adding new instructions that add 1 to the other operand. The final step is to replace all uses of the original add instruction with my new value that is equivalent, but took a bit more work to get there. I briefly looked online for math functions implemented in C, but had trouble finding something that was changed by my pass, so I defaulted to using my own custom test, where I had an addmitedly contrived example of a function that adds constant values to an argument. However, for such a simple implementation I am confident with this. Anything hard?
|
Beta Was this translation helpful? Give feedback.
-
Summary@emwangs and @he-andy and I worked together for this assignment! Implementation Details
Challenges
TestingWe wrote a relatively simple C program to test on:
We then verified all of the floating point operations got caught here:
We also wanted to verify our program on something more "real". I found a program online that computes a Mandelbrot fractal and saves it as a grayscale PPM:
Here's the output:
So we're pretty convinced it will work - after all we aren't doing anything too crazy :) |
Beta Was this translation helpful? Give feedback.
-
Vivian and I worked on lesson 7 together. Summary
Implementation details
What was the hardest part of the task? How did you solve this problem?
|
Beta Was this translation helpful? Give feedback.
-
SummaryI have implemented a simple pass that checks for binary Mul operations, and switch the left hand side and right hand side in the code. I have saved the output assembly code at foo_original.s and foo_opt.s. After my transformation, the code changed from
to
I was supposing that DifficultiesIt seems that clang will perform some optimizations before I see the llvm IR. For example, if I have a function like
It will directly be transformed to
So I won't see the 5 + 4 instruction. Is this an optimization handled in the front-end of the compiler? |
Beta Was this translation helpful? Give feedback.
-
@xalbt and I worked together on lesson 7. SummaryImplementation
Difficulties
TestingWe ran our LLVM pass on a few C files. We've included a pretty clear example in
our output for the pass itself is
and for our ./a.out:
|
Beta Was this translation helpful? Give feedback.
-
I decided to do something similar to the same task that we had with Bril: I look for The main challenge with this task was finding my way around the LLVM docs. In doing so, you can easily see that LLVM is a beast. No wonder why everyone uses it. Here is a code snippet:
|
Beta Was this translation helpful? Give feedback.
-
Summarylink to my commit TestingI basically inspected the program and see if the results are expected as I print out all the results ChallengeThe most challenging part is actually setting up llvm. My computer always uses Clang comes with xcode instead of the clang comes with llvm. I have to change the PATH variable. Also I messed up the installation and I went through a bunch of messy operations like I reinstalled xcode, command line tools. Another challenging part is to get familiar with the llvm syntax. It has so many functions also I also checked out their tutorials but they seem to be more about building syntax trees and not much about actually changing and optimizing the program during compilation |
Beta Was this translation helpful? Give feedback.
-
Summary
Details
Testing/Evaluation
// foo.c
int addSubMul(int x) {
int a = x + 4;
int b = a - 3;
int c = b * 2;
return c;
}
int main() {
return addSubMul(5);
} ❯ make
[ 50%] Building CXX object skeleton/CMakeFiles/SkeletonPass.dir/Skeleton.cpp.o
[100%] Linking CXX shared module SkeletonPass.dylib
[100%] Built target SkeletonPass
❯ cc -c ../src/rtlib.c
❯ clang -fpass-plugin=skeleton/SkeletonPass.dylib -c ../target/foo.c
❯ cc ../src/rtlib.o foo.o -o exe
❯ ./exe
computed: 9
computed: -2
computed: 6 Difficulties
|
Beta Was this translation helpful? Give feedback.
-
SummaryDetails/Testing
DifficultiesI ended up having a lot of trouble getting the |
Beta Was this translation helpful? Give feedback.
-
I worked with @obhalerao on this project. SummaryWe implemented an LLVM pass that counts the number of times each loop is executed. To do so, we used LLVM's loop analysis to find all the natural loops and inserted a call to a logging utlity to increment the count for that loop. The runtime library is implemented in C++ using a nested TestingWe used two benchmarks to test our implementation. In both cases, the output of the program to The first one was a contrived C program which had six for-loops, each of whose bodies execute for two iterations. We used this to check the correctness of our implementation (the header of the loop actually gets entered three times, since the condition is checked three times). The second one was a C++ implementation of the Ford-Fulkerson algorithm for finding the max flow in a flow network, which has much more interesting control flow. Here is a snippet of the output (note that function 37 is
All the library functions that were included with the implementation of Ford-Fulkerson were also transformed by our pass, which explains why there seem to be far more loops (and functions) in our output than anticipated. DifficultiesThe main difficulty we encountered was getting the LLVM pass to work properly. In our current version of the code, there is a for-loop through the basic blocks of the function whose body only executes once. For future work, we would like to investigate the cause for this, clean up the code to avoid it, and finally restrict the pass to detect and ignore standard library functions in order to make the logs more comprehensible. Initially, we implemented the runtime library as a 2D array in C and declared the dimensions of the array as a constant. After learning about C/C++ interoperability, we wrote it in C++ and got it to work pretty easily. We think it would be fun to re-write the runtime library in other languages like OCaml as well. |
Beta Was this translation helpful? Give feedback.
-
Summary@rcplane , @Enochen , and @zachary-kent collaborated on this project. We were successfully able to modify C programs built with clang to reduce emitted llvm ir instruction count converting unnecessary memory stores to register usage while preserving execution correctness. Implementation
Testing
Difficulties
|
Beta Was this translation helpful? Give feedback.
-
SummaryI implemented a version of local copy/constant propagation in C++. The idea is that we keep track of the values that are stored and loaded into registers and propagate the copies where possible, creating opportunities for dead code elimination. ImplementationThere are two key-value maps for each basic block: one maps pointers to non-pointer operands, and the other maps operands to other operands that have the same value (similar to canonical homes in LVN). I differentiated pointers and non-pointers mostly because I couldn't find a good way to extract the register from the pointer value (e.g. When we store an operand to %p, we add this mapping to the If there is a new store to a pointer, we replace the mapping in There are some caveats to this. I made some assumptions about aliasing, which might not hold. We could imagine a scenario where multiple pointers point to the same location and we are not able to detect the mutation. I rewrote some of the arguments in stores and binary operators, but not all pattern are covered. I also tried to add LLVM's dead code pass to the pass pipeline but I wasn't sure how I could do that. So I have not eliminated the dead code and have not measured the speedup. To see which instructions we can eliminate, I added statements that print "dead code {instruction}", as shown below. TestingI asked ChatGPT to generate a "real-ish C program", and it gave me one that computes the factorial. I verified that the results were the same with or without the pass. I also ran some smaller hand-written programs. Difficulties
ExampleThe "dead code" statements at the bottom of the output tell us which instructions could be eliminated. For example,
|
Beta Was this translation helpful? Give feedback.
-
SummaryFor this task, @JohnDRubio and I implemented the basic task of identifying when we found a floating point division instruction for each instruction in the program. ImplementationAs shown in class, we looped over each function, and through each basic block for that function, and finally through each instruction in that basic block. For each instruction, we first checked if it contained a binary operator. If it didn't, we knew it couldn't be a floating point division instruction. If there was a binary operator, we then extracted the opcode and checked if it was a floating point division operator (by comparing it to the enum Instruction::FDiv). TestingWe ran some basic tests with and without floating point division to make sure that our pass ran correctly. Once confirming that, we picked a real-ish C++ program to run our pass to verify that nothing broke and that it correctly found floating point division instructions. For this test program, we used the Ray - Sphere Intersection algorithm DifficultiesThere were no real difficulties in the assignment, mainly just using LLVM documentation to figure out how to extract the opcode for an instruction and checking that it was a floating point division opcode. |
Beta Was this translation helpful? Give feedback.
-
Summary
Implementation
Testing
ChallengesSince my pass works on the LLVM IR, I have to keep in mind how a C program is parsed and tranformed into that IR. Actually I initially planned to do something with the logical operators in C (i.e., |
Beta Was this translation helpful? Give feedback.
-
SummaryI implemented an LLVM pass which determines if potentially null pointers are loaded from or stored to, and if so, prints an error message and aborts compilation. To do this, I reimplemented my generalized data flow framework, and developed a conditional interval analysis. I originally thought using LLVM's LazyValueInfo pass would suffice, but this pass doesn't seem to support loops, and the ScalarEvolutionPass seems to only support loops. Perhaps I used them wrong, but I couldn't figure out any pass that would provide global interval analysis, therefore I ended up writing my own, which is the more complicated part of this. ImplementationThis ended up being a bit more ambitious than I originally anticipated, and as mentioned, involved also writing an interval analysis pass. For the null pointer check, I currently perform an abstract interpretation of the IR, and flag every use of a pointer as non null, or potentially null. Then, I run through all the instructions, and check to make sure every load and store uses only pointers that are definitely null. To support array indexing, I use an interval analysis to determine a conservative range of every integer via abstract interpretation. Then, in the null pointer abstract interpretation, There were A LOT of cool ideas I got when implementing this that I didn't have time to work on (yet). Some included expanding the interval analysis to support variables. For example, although TestingI developed some tests that cause violations and passes as I was working on this. I wrote tests to try and hit corner cases. However, this is definitely undertested. ChallengesThis ended up being more of an undertaking than I initially anticipated. The interval analysis was also more involved than I anticipated as well. |
Beta Was this translation helpful? Give feedback.
-
SummaryI implemented a pass to flip all predicates of the if-else branch. ImplementationLLVM has CmpInst whose two subclasses are FCmpInst and ICmpInst. So I also created an abstract class for Int and Float condition class to flip the message and print the message correspondingly. I iterate over the functions, blocks, instructions and check if it's a conditional instruction. If it is and is comparing between two integers, I dynamically cast the condition to IntConditionClass; and do the same for float comparisons. Then I will invoke flip and print and let polymorphism to do its job. ChallengesIt is a pretty straightforward and unambitious task :) |
Beta Was this translation helpful? Give feedback.
-
Share your experiences getting started with writing an LLVM pass here!
Beta Was this translation helpful? Give feedback.
All reactions