<div dir="ltr"><div>This is my example (for.c):</div><div><br></div><div>#include <stdio.h><br><br>int add(int a, int b) {<br>    return a + b;<br>}<br><br>int main() {<br>   int a, b, c, d;<br>   a = 5;<br>   b = 15;<br>   c = add(a, b);<br>   d = 0;<br>   for(int i=0;i<16;i++)<br>       d = add(c, d);<br>}</div><div><br></div><div>I run:</div><div>$ clang -O0 -Xclang -disable-O0-optnone -emit-llvm for.c -S -o forO0.ll<br>$ opt -O0 -S --loop-unroll --unroll-count=4 -view-cfg forO0.ll -o for-opt00-unroll4.ll</div><div><br></div><div>And this is the LLVM IR code that I get: <br></div><div><br></div><div>; ModuleID = 'forO0.ll'<br>source_filename = "for.c"<br>target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"<br>target triple = "x86_64-unknown-linux-gnu"<br><br>; Function Attrs: noinline nounwind uwtable<br>define dso_local i32 @add(i32 %a, i32 %b) #0 {<br>entry:<br>  %a.addr = alloca i32, align 4<br>  %b.addr = alloca i32, align 4<br>  store i32 %a, i32* %a.addr, align 4<br>  store i32 %b, i32* %b.addr, align 4<br>  %0 = load i32, i32* %a.addr, align 4<br>  %1 = load i32, i32* %b.addr, align 4<br>  %add = add nsw i32 %0, %1<br>  ret i32 %add<br>}<br><br>; Function Attrs: noinline nounwind uwtable<br>define dso_local i32 @main() #0 {<br>entry:<br>  %retval = alloca i32, align 4<br>  %a = alloca i32, align 4<br>  %b = alloca i32, align 4<br>  %c = alloca i32, align 4<br>  %d = alloca i32, align 4<br>  %i = alloca i32, align 4<br>  store i32 0, i32* %retval, align 4<br>  store i32 5, i32* %a, align 4<br>  store i32 15, i32* %b, align 4<br>  %0 = load i32, i32* %a, align 4<br>  %1 = load i32, i32* %b, align 4<br>  %call = call i32 @add(i32 %0, i32 %1)<br>  store i32 %call, i32* %c, align 4<br>  store i32 0, i32* %d, align 4<br>  store i32 0, i32* %i, align 4<br>  br label %for.cond<br><br>for.cond:                                         ; preds = %for.inc.3, %entry<br>  %2 = load i32, i32* %i, align 4<br>  %cmp = icmp slt i32 %2, 16<br>  br i1 %cmp, label %for.body, label %for.end<br><br>for.body:                                         ; preds = %for.cond<br>  %3 = load i32, i32* %c, align 4<br>  %4 = load i32, i32* %d, align 4<br>  %call1 = call i32 @add(i32 %3, i32 %4)<br>  store i32 %call1, i32* %d, align 4<br>  br label %for.inc<br><br>for.inc:                                          ; preds = %for.body<br>  %5 = load i32, i32* %i, align 4<br>  %inc = add nsw i32 %5, 1<br>  store i32 %inc, i32* %i, align 4<br>  %6 = load i32, i32* %i, align 4<br>  %cmp.1 = icmp slt i32 %6, 16<br>  br i1 %cmp.1, label %for.body.1, label %for.end<br><br>for.end:                                          ; preds = %for.inc.2, %for.inc.1, %for.inc, %for.cond<br>  %7 = load i32, i32* %d, align 4<br>  %call2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str, i64 0, i64 0), i32 %7)<br>  %8 = load i32, i32* %retval, align 4<br>  ret i32 %8<br><br>for.body.1:                                       ; preds = %for.inc<br>  %9 = load i32, i32* %c, align 4<br>  %10 = load i32, i32* %d, align 4<br>  %call1.1 = call i32 @add(i32 %9, i32 %10)<br>  store i32 %call1.1, i32* %d, align 4<br>  br label %for.inc.1<br><br>for.inc.1:                                        ; preds = %for.body.1<br>  %11 = load i32, i32* %i, align 4<br>  %inc.1 = add nsw i32 %11, 1<br>  store i32 %inc.1, i32* %i, align 4<br>  %12 = load i32, i32* %i, align 4<br>  %cmp.2 = icmp slt i32 %12, 16<br>  br i1 %cmp.2, label %for.body.2, label %for.end<br><br>for.body.2:                                       ; preds = %for.inc.1<br>  %13 = load i32, i32* %c, align 4<br>  %14 = load i32, i32* %d, align 4<br>  %call1.2 = call i32 @add(i32 %13, i32 %14)<br>  store i32 %call1.2, i32* %d, align 4<br>  br label %for.inc.2<br><br>for.inc.2:                                        ; preds = %for.body.2<br>  %15 = load i32, i32* %i, align 4<br>  %inc.2 = add nsw i32 %15, 1<br>  store i32 %inc.2, i32* %i, align 4<br>  %16 = load i32, i32* %i, align 4<br>  %cmp.3 = icmp slt i32 %16, 16<br>  br i1 %cmp.3, label %for.body.3, label %for.end<br><br>for.body.3:                                       ; preds = %for.inc.2<br>  %17 = load i32, i32* %c, align 4<br>  %18 = load i32, i32* %d, align 4<br>  %call1.3 = call i32 @add(i32 %17, i32 %18)<br>  store i32 %call1.3, i32* %d, align 4<br>  br label %for.inc.3<br><br>for.inc.3:                                        ; preds = %for.body.3<br>  %19 = load i32, i32* %i, align 4<br>  %inc.3 = add nsw i32 %19, 1<br>  store i32 %inc.3, i32* %i, align 4<br>  br label %for.cond, !llvm.loop !2<br>}<br><br>declare dso_local i32 @printf(i8*, ...) #1<br><br>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" }<br>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" }<br><br>!llvm.module.flags = !{!0}<br>!llvm.ident = !{!1}<br><br>!0 = !{i32 1, !"wchar_size", i32 4}<br>!1 = !{!"clang version 11.0.0 (<a href="https://github.com/llvm/llvm-project.git">https://github.com/llvm/llvm-project.git</a> a3485301d4870f57590d7b69eed7959134a694ab)"}<br>!2 = distinct !{!2, !3}<br>!3 = !{!"llvm.loop.unroll.disable"}</div><div><br></div><div><br></div><div>So my problem is:</div><div>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. <br>
</div><div> </div><div><br></div><div>Do you know why this happen?</div><div><br></div><div>Thanks.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">El vie., 22 may. 2020 a las 19:49, Florian Hahn (<<a href="mailto:florian_hahn@apple.com">florian_hahn@apple.com</a>>) escribió:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
<br>
> On May 22, 2020, at 09:55, legend xx via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br>
> <br>
> Hi, <br>
> <br>
> 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. <br>
> <br>
> What pass I can used and how? <br>
> <br>
<br>
-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 <a href="https://github.com/llvm/llvm-project/blob/master/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp#L81" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/blob/master/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp#L81</a>). <br>
<br>
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.<br>
<br>
> I would also like to know if there is any way to mark the loops that I want them to be unroll<br>
<br>
Yes it is possible to explicitly mark loops for unrolling using metadata in LLVM IR: <a href="https://llvm.org/docs/LangRef.html#llvm-loop-unroll" rel="noreferrer" target="_blank">https://llvm.org/docs/LangRef.html#llvm-loop-unroll</a>. But the metadata might not help, if the loop contains code the unroller does not support.<br>
<br>
Cheers,<br>
Florian<br>
<br>
</blockquote></div>