[LLVMdev] Unrolling loops into constant-time expressions

Duncan Sands baldrick at free.fr
Tue Nov 23 00:51:14 PST 2010


Hi Juliusz,

> I've come across another example:

this looks like a different issue to the previous example.
If you run the output of clang a second time through the
optimizers it gets simplified.

Ciao,

Duncan.

>
> I'm compiling with
> clang -S -emit-llvm -std=gnu99 -O3
> clang version 2.9 (trunk 118238)
> Target: x86_64-unknown-linux-gnu
> Thread model: posix
>
> I take the code:
> int loops(int x) {
>        int ret = 0;
>        for(int i = 0; i<  x; i++) {
>            for(int j = 0; j<  x; j++) {
>                ret += 1;
>            }
>        }
>        return ret;
> }
>
> and the generated code is:
> define i32 @loops(i32 %x) nounwind readnone {
> ;<label>:0
>      %1 = icmp sgt i32 %x, 0
>      br i1 %1, label %2, label %._crit_edge6
>
> ;<label>:2                                       ; preds = %0, %2
>      %i.03.us = phi i32 [ %3, %2 ], [ 0, %0 ]
>      %ret.14.us = phi i32 [ %tmp, %2 ], [ 0, %0 ]
>      %tmp = add i32 %ret.14.us, %x
>      %3 = add nsw i32 %i.03.us, 1
>      %exitcond = icmp eq i32 %3, %x
>      br i1 %exitcond, label %._crit_edge6, label %2
>
> ._crit_edge6:                                     ; preds = %2, %0
>      %ret.1.lcssa = phi i32 [ 0, %0 ], [ %tmp, %2 ]
>      ret i32 %ret.1.lcssa
> }
>
> This code:
> * unrolls the inner loop simplifying the code to sth like:
>      for(int i = 0; i<  x; i++) {
>          ret += x;
> * But it is unable to also unroll the outer loop, even though it is a
> simple expression.
>
> On the other hand it is able to unroll a complicated expression inside
> one loop into a constant-time expression, like here:
> int loop(int x) {
>        int ret = 0;
>        for(int i = 0; i<  x; i++) {
>            ret += 1+i*i + i*(i+2);
>        }
>        return ret;
> }
> generates:
> define i32 @loop(i32 %x) nounwind readnone {
>      %1 = icmp sgt i32 %x, 0
>      br i1 %1, label %bb.nph, label %3
>
> bb.nph:                                           ; preds = %0
>      %tmp4 = add i32 %x, -1
>      %tmp6 = add i32 %x, -2
>      %tmp16 = add i32 %x, -3
>      %tmp7 = zext i32 %tmp6 to i33
>      %tmp5 = zext i32 %tmp4 to i33
>      %tmp17 = zext i32 %tmp16 to i33
>      %tmp15 = mul i33 %tmp5, %tmp7
>      %tmp18 = mul i33 %tmp15, %tmp17
>      %tmp8 = mul i32 %tmp4, %tmp6
>      %tmp19 = lshr i33 %tmp18, 1
>      %2 = shl i32 %tmp8, 2
>      %tmp20 = trunc i33 %tmp19 to i32
>      %tmp12 = mul i32 %x, 5
>      %tmp1125 = and i32 %2, -8
>      %tmp21 = mul i32 %tmp20, 1431655764
>      %tmp13 = add i32 %tmp1125, %tmp12
>      %tmp14 = add i32 %tmp13, -4
>      %tmp22 = sub i32 %tmp14, %tmp21
>      ret i32 %tmp22
>
> ;<label>:3                                       ; preds = %0
>      ret i32 0
> }
> which has no loop, which means that clang -O3 is capable of:
> * unrolling expressions like
>        for(int i = 0; i<  n; i++)
>            ret += i (or i*i, or i*i*i... i checked up to i6 AFAIR)
>      into a constant-time formula
> * unrolling such polynomial-like expressions into a constant time
> formula, and discarding the loop at all.
>
> Even though it can perform such complicated tricks on one loop, it never
> unrolls two nested loop into a constant even in a simple case.
>
> Is there a way to make it do so?
>
> Cheers,
> Juliusz Sompolski
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev




More information about the llvm-dev mailing list