Loop parallelization (Term project) Part 1. Finding loops

In the previous LLVM assignment, you have used the interface LLVM provided. From this assignment on, we are starting to do a loop parallelization term project which is divided into 3 assignments: (1) Loop detection. (2) Dependence analysis and induction variable analysis. (3) Parallelization.

RUST may also be used if there are enough interests.  Email Jacob Bisnett if you are interested.

IMPORTANT NOTES: As we are doing term project from this assignment on, the problem we are going to solve is more close to the real-world compiler development.   The assignment may have missing information and you may encounter problems not covered by the textbooks or the lectures, part of the project experience is to take initiative, formulate these problems, seek help from others (teaching staff, classmates, and online resources), and solve these problems .

The deadline is 11:59pm Friday March 10th. 

For this assignment, you need to use data flow analysis to find loops in the LLVM IR code.

The definition for a loop in the flow graph can be find in the dragon book Chapter 8.4.5 P531. The loop identification approach can be found in these slides from CMU .

For implementation, three steps described in the slides are needed as follows.  Each step generates an output which will be used for grading.

(1) Calculate Dominance relation for basic blocks by data flow analysis.  Provide a function named dump to output the dominance relation.  (Do NOT use the dominator analysis in the LLVM compiler.)

  • To calculate Dominance, you need to traverse CFG.  Take a look at the class reference for functions and basic blocks to see how to find the entry block and how to find the successors or predecessors for a given basic block;
  • You also need to know about some C++ data structures, such as vectors, map, pair, stack, queue. That will simply your implementation.
  • To find the name of basic blocks, look at the APIs such as hasName(), getValueName(), setValueName() provided in value class.

(2) Find back edges; Provide a dump function to output all back edges.

(3) Find natural Loops. Provide a dump function to dump the set of basic blocks in the loop.

The output should first give the number of loops, the dominance relation and all back edges. For each loop, output a set of basic blocks in the loop. For example:


Number of loops: 1

Dominance relation: BB1 -> BB2, BB1->BB3, BB2->BB3

Back edge: BB3 -> BB1

Basic blocks in the loop 1: BB1, BB2, BB3


Write at least two test programs with at least one loop in each program. Provide detailed README file to describe the design and limitations, including what types of loops can be detected and what types of loops can not.

Extra credit (10%):

LLVM built-in analysis may be useful for loop detection, for example the dominator analysis in the LLVM compiler?  Implement a second loop detection pass which you can use any LLVM API for loop detection. Compare different implementations and write down the detection coverage for different loop structures.

Assignment 2 (LLVM/RUST)

Hope you are doing well in the first assignment and ready for the next one.
In this assignment, you will implement and test a compiler pass that instruments a program to report the number of intermediate-level executed instructions. The idea is to insert appropriate calls in the program (instrumentation). You can choose to implement this pass either in LLVM or RUST. For your convenience, these two compilers are already installed on the csug network. (For grads, please ask Marty Guenther <marty@cs.rochester.edu> for an undergrad account to access csug network)

Deadline is 11.59pm Friday, Feb 10th, 2017.

*********************************Instructions on RUST****************************************——————————————————————————————–

Instructions for Writing an Instruction Counting Pass for Rust’s MIR

Environment setup:

In order to write an MIR transformation pass easily you need three things:

  1. A Rust nightly compiler
  2. Cargo: the Rust build system
  3. The source code for the Rust compiler.

Thankfully there is an easy way to get all three: rustup.

Rustup is the system most Rust hackers use to manage their Rust environment. It’s very easy to install:

  1. SSH into the cycle machines
  2. Copy paste the following into your command line, it will run the install script and set your default rust compiler to nightly

$ curl https://sh.rustup.rs -sSf | sh -s — –default-toolchain nightly

  1. Follow the instructions to add rustc and cargo to your PATH
  2. Ensure your rust compiler is on the correct version by making sure the output of the following command contains the word “nightly”:

$ rustc -V

  1. Make sure the same is true of the next command

$ cargo -V

  1. Type the following command to download the rust source code into “~/.multirust/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/” or something similar

$ rustup component add rust-src

Once you have done the above, you are ready to start writing your first MIR pass.

Start your pass:

This git repository is a rust project that contains everything you need to start writing your own compiler pass. You need to finish the compiler pass in the “src/lib.rs” file so that it insert dynamic instruction counting tooling into the compiled “src/main.rs” program. You can use “cargo build” in order to compile the project, and “cargo run” to run it. Your goal is to make the X static variable equal to the number of dynamically executed MIR statements, including Storage, Descriminant, and NOOPs.

Some sample code is in lib.rs to get your started.

If you have any questions, please email jbisnett@u.rochester.edu

*********************************Instructions on LLVM**************************************

Environment setup:

Log in to your csug account.
$ cp -r /u/cs255/cs255-llvm YOURUSERNAME-cs255-llvm
$ cd YOURUSERNAME-cs255-llvm

Start your pass:

Included files:
* lib/InstCounter.cpp
You must implement your compiler pass here.
This file already provides the skeleton and a related example.

* runtime/InstCounting.c
This file implements the runtime functions that you need for the instrumentation. init() is to initialize the counter to ZERO before counting, increase() is to increase the counter by 1 and print_stmt_cnt() is to print the value of the counter.

* test/test.c
This is a simple program to test your pass.

After implementing your pass, compile it by running “make” in your top-level directory. Then cd into the “test” directory and run “make check” to test your pass. This gives you the instrumented program “test”. Run it on the string “cs255” and report your output. Make sure to explain your implementation and findings in a readme file.

Submission guideline:
Archive your working directory using the following command line, and submit on Blackboard.
tar –exclude=’.svn’ –exclude=’autoconf’ -czvf YOURUSERNAME-cs255-llvm.tar.gz YOURUSERNAME-cs255-llvm/

Helpful documentations:

(1) LLVM Programer’s Manual: highlight some of the important classes and interfaces available in the LLVM source-base (For example, how to iterate over basic blocks, how to iterate over instructions inside a basic block or function).

(2) LLVM Language Reference Manual: reference manual for the LLVM assembly language.

(3) LLVM class references: reference for the interfaces of the classes needed. (For example instructions, basic blockfunctions)

Note: you can use the llvm-dis tool (/u/cs255/build-llvm-38/bin/llvm-dis) to check your instrumentation at IR level. Run this tool on the llvm bitcode file that is generated by your pass:
/u/cs255/dc_llvm/build/bin/llvm-dis test.bc.opt

If you have any questions, please email dchen39@cs.rochester.edu


Continue Reading