[llvm-dev] Loop Unroll

legend xx via llvm-dev llvm-dev at lists.llvm.org
Sat May 23 09:15:14 PDT 2020


This is my example (for.c):

#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int main() {
   int a, b, c, d;
   a = 5;
   b = 15;
   c = add(a, b);
   d = 0;
   for(int i=0;i<16;i++)
       d = add(c, d);
}

I run:
$ clang -O0 -Xclang -disable-O0-optnone -emit-llvm for.c -S -o forO0.ll
$ opt -O0 -S --loop-unroll --unroll-count=4 -view-cfg forO0.ll -o
for-opt00-unroll4.ll

And this is the LLVM IR code that I get:

; ModuleID = 'forO0.ll'
source_filename = "for.c"
target datalayout =
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: noinline nounwind uwtable
define dso_local i32 @add(i32 %a, i32 %b) #0 {
entry:
  %a.addr = alloca i32, align 4
  %b.addr = alloca i32, align 4
  store i32 %a, i32* %a.addr, align 4
  store i32 %b, i32* %b.addr, align 4
  %0 = load i32, i32* %a.addr, align 4
  %1 = load i32, i32* %b.addr, align 4
  %add = add nsw i32 %0, %1
  ret i32 %add
}

; Function Attrs: noinline nounwind uwtable
define dso_local i32 @main() #0 {
entry:
  %retval = alloca i32, align 4
  %a = alloca i32, align 4
  %b = alloca i32, align 4
  %c = alloca i32, align 4
  %d = alloca i32, align 4
  %i = alloca i32, align 4
  store i32 0, i32* %retval, align 4
  store i32 5, i32* %a, align 4
  store i32 15, i32* %b, align 4
  %0 = load i32, i32* %a, align 4
  %1 = load i32, i32* %b, align 4
  %call = call i32 @add(i32 %0, i32 %1)
  store i32 %call, i32* %c, align 4
  store i32 0, i32* %d, align 4
  store i32 0, i32* %i, align 4
  br label %for.cond

for.cond:                                         ; preds = %for.inc.3,
%entry
  %2 = load i32, i32* %i, align 4
  %cmp = icmp slt i32 %2, 16
  br i1 %cmp, label %for.body, label %for.end

for.body:                                         ; preds = %for.cond
  %3 = load i32, i32* %c, align 4
  %4 = load i32, i32* %d, align 4
  %call1 = call i32 @add(i32 %3, i32 %4)
  store i32 %call1, i32* %d, align 4
  br label %for.inc

for.inc:                                          ; preds = %for.body
  %5 = load i32, i32* %i, align 4
  %inc = add nsw i32 %5, 1
  store i32 %inc, i32* %i, align 4
  %6 = load i32, i32* %i, align 4
  %cmp.1 = icmp slt i32 %6, 16
  br i1 %cmp.1, label %for.body.1, label %for.end

for.end:                                          ; preds = %for.inc.2,
%for.inc.1, %for.inc, %for.cond
  %7 = load i32, i32* %d, align 4
  %call2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([20 x
i8], [20 x i8]* @.str, i64 0, i64 0), i32 %7)
  %8 = load i32, i32* %retval, align 4
  ret i32 %8

for.body.1:                                       ; preds = %for.inc
  %9 = load i32, i32* %c, align 4
  %10 = load i32, i32* %d, align 4
  %call1.1 = call i32 @add(i32 %9, i32 %10)
  store i32 %call1.1, i32* %d, align 4
  br label %for.inc.1

for.inc.1:                                        ; preds = %for.body.1
  %11 = load i32, i32* %i, align 4
  %inc.1 = add nsw i32 %11, 1
  store i32 %inc.1, i32* %i, align 4
  %12 = load i32, i32* %i, align 4
  %cmp.2 = icmp slt i32 %12, 16
  br i1 %cmp.2, label %for.body.2, label %for.end

for.body.2:                                       ; preds = %for.inc.1
  %13 = load i32, i32* %c, align 4
  %14 = load i32, i32* %d, align 4
  %call1.2 = call i32 @add(i32 %13, i32 %14)
  store i32 %call1.2, i32* %d, align 4
  br label %for.inc.2

for.inc.2:                                        ; preds = %for.body.2
  %15 = load i32, i32* %i, align 4
  %inc.2 = add nsw i32 %15, 1
  store i32 %inc.2, i32* %i, align 4
  %16 = load i32, i32* %i, align 4
  %cmp.3 = icmp slt i32 %16, 16
  br i1 %cmp.3, label %for.body.3, label %for.end

for.body.3:                                       ; preds = %for.inc.2
  %17 = load i32, i32* %c, align 4
  %18 = load i32, i32* %d, align 4
  %call1.3 = call i32 @add(i32 %17, i32 %18)
  store i32 %call1.3, i32* %d, align 4
  br label %for.inc.3

for.inc.3:                                        ; preds = %for.body.3
  %19 = load i32, i32* %i, align 4
  %inc.3 = add nsw i32 %19, 1
  store i32 %inc.3, i32* %i, align 4
  br label %for.cond, !llvm.loop !2
}

declare dso_local i32 @printf(i8*, ...) #1

attributes #0 = { noinline nounwind uwtable
"correctly-rounded-divide-sqrt-fp-math"="false"
"disable-tail-calls"="false" "frame-pointer"="all"
"less-precise-fpmad"="false" "min-legal-vector-width"="0"
"no-infs-fp-math"="false" "no-jump-tables"="false"
"no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false"
"no-trapping-math"="false" "stack-protector-buffer-size"="8"
"target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
"unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false"
"disable-tail-calls"="false" "frame-pointer"="all"
"less-precise-fpmad"="false" "no-infs-fp-math"="false"
"no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false"
"no-trapping-math"="false" "stack-protector-buffer-size"="8"
"target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
"unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project.git
a3485301d4870f57590d7b69eed7959134a694ab)"}
!2 = distinct !{!2, !3}
!3 = !{!"llvm.loop.unroll.disable"}


So my problem is:
With unroll 4 on the loop with 16 bounds I should see one single block for
the incrementation i=i+4, then 4 instructions for each previous one
instruction, and the condition should check if i<16. This is the intuitive
code. However, the incrementation that I get is i=i+1 and there are only 4
blocks.

Do you know why this happen?

Thanks.

El vie., 22 may. 2020 a las 19:49, Florian Hahn (<florian_hahn at apple.com>)
escribió:

>
>
> > On May 22, 2020, at 09:55, legend xx via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
> >
> > Hi,
> >
> > I'm interesting in find a pass for loop unrolling in LLVM compiler. I
> tried opt --loop-unroll --unroll-count=4, but it don't work well.
> >
> > What pass I can used and how?
> >
>
> -loop-unroll should be the right pass. There are multiple possible reasons
> why the loop is not unrolled and the pass has a bunch of options to
> enable/force unrolling for more cases (see
> https://github.com/llvm/llvm-project/blob/master/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp#L81).
>
>
> Passing `-debug` should give you a better idea why the loop is not
> unrolled. If you would share the IR, someone might be able to provide
> additional insight.
>
> > I would also like to know if there is any way to mark the loops that I
> want them to be unroll
>
> Yes it is possible to explicitly mark loops for unrolling using metadata
> in LLVM IR: https://llvm.org/docs/LangRef.html#llvm-loop-unroll. But the
> metadata might not help, if the loop contains code the unroller does not
> support.
>
> Cheers,
> Florian
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200523/e1e2bd42/attachment-0001.html>


More information about the llvm-dev mailing list