Search code examples
c++ccompiler-constructionllvmcompiler-optimization

Does the -loop-unroll pass force LLVM to unroll loops?


I have a piece of code and I want LLVM to unroll all loops in it by a certain factor. I'm using the following command:

opt -mem2reg -simplifycfg -loops -lcssa -loop-simplify -loop-rotate -loop-unroll -unroll-count=3 -unroll-allow-partial -debug TrainingCode/trainingCode.ll -o TrainingCode/unrolledTrainingCode.bc

Specifically, the -loop-unroll and -unroll-count=3 handle the loop unrolling stuff - the rest just transforms the code so that LLVM can unroll the code.

Does this command guarantee that all loops will be unrolled by a factor of 3? Or is it more like using pragma statements with GCC, which the compiler can choose to ignore if it deems non-optimal? In other words, do the -loop-unroll and -unroll-count=3 passes force the compiler to use an unroll factor of 3 or is it more of a "hint" the compiler can choose to ignore?


Solution

  • Does this command guarantee that all loops will be unrolled by a factor of 3?

    The short answer is no.

    First of all, it depends on the loop. For example, if it is a pointer-chasing loop, that is a major inhibiting factor. A determining factor for the unroll is to be able to calculate the trip count at compile time. Thus, a major help to loop unrolling is performing the indvars pass.

    Snooping around LoopUnroll.cpp and LoopUnrollPass.cpp can be illuminating. Among other things, there are statistics kept like NumCompletelyUnrolled and NumUnrolled that can give a rough-cut overall status. Next, there are metadata that can be taken into account as a hint (search for GetLoopUnrollMetadata which complements what @schaiba wrote). One more thing to follow in the pass source file is the TripCount and how that is used in order to determine the exact policy for unrolling the loop.

    PS: My notes are based on the LLVM 3.7 source tree, so that's why I was not very definite in the descriptions. YMMV depending on the version you're working on, but those things are mostly there in the latest trunk (6.0.0).