3

Are there any options that enable loop inversion? More specifically,can LLVM transform the while form loop into do-while form loop as the following.

Before the transformation, the code is:

void foo(unsigned a, unsigned& ret) {
  bool undone = true;
  #pragma unroll 4
  while((a > 0) && undone) {
    ++ret;
    if(ret > 2)  undone = false;
    if(undone)   --a;
  }
}

After the transformation, the code is:

void foo(unsigned a, unsigned& ret) {
  bool undone = true;
  #pragma unroll 4
  if((a > 0) && undone) {
    do {
      ++ret;
      if(ret > 2)  undone = false;
      if(undone)   --a;
    while((a > 0) && undone);
  }
}

I have use the opt pass and enable the loop-rotate option and loop-simplify option. However, the loop inversion transformation is not implemented.

shu
  • 31
  • 2
  • 1
    That's not now LLVM works. Compilers that use LLVM start by transforming the code to IR, which is a very different language trom C, and then transforms IR to other IR. LLVM never transforms to anything C-like. A function in IR consists of a *set* of blocks, each of which is a *sequence* of instructions, ending with some sort of branch or jump. The two functions you show would not be very different in IR. – arnt Dec 17 '22 at 16:29
  • 1
    The closest LLVM has is `opt -loop-rotate` which I think is a superset of loop inversion. – Nick Lewycky Dec 22 '22 at 21:36

1 Answers1

1

LLVM does exactly the transformation you requested with the standard optimization pipeline used by Clang at -O2 (and most other frontends built on LLVM). So the direct answer to your question is "-O2". It isn't a single pass as you need to enable the complete pipeline of optimizations that work together to accomplish this.

To see all of this in action, let's look at compiler explorer for your example code with Clang v15 (a fixed version so the line numbers are stable): https://cpp.compiler-explorer.com/z/o73nEP6r5

On line 3 of the assembly and line 9 of the LLVM IR you'll see a conditional branch. This branch is outside of the loop, and precisely corresponds to the if((a > 0) && undone) condition in your desired result. At that point, undone is a constant (true) and so folds away and the conditional branch only checks a > 0 prior to entering the loop. Again, this condition is outside of the loop and is never revisited.

Below that, you'll see this line in the assembly output:

.LBB0_2:                                # =>This Inner Loop Header: Depth=1

This label marks a basic block of machine code, and the comment at the end comes from LLVM's loop analysis and shows that this is the "loop header"[1], the top basic block of the actual looping code, and it corresponds to where the do { starts in your desired transformation.

As Nick Lewycky pointed out in the comments, the specific LLVM pass that does the specific transform you describe is 'loop-rotate', and I agree with his comment that it is a superset of what you are describing. However, you can't enable it in isolation. To see how LLVM builds up a set of loop passes that work well, see the pipeline here and the large body of code preceding it that schedules all the other relevant transforms: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Passes/PassBuilderPipelines.cpp#L531,L609

Chandler Carruth
  • 3,011
  • 1
  • 18
  • 26