Home | History | Annotate | Download | only in LoopUnroll
      1 ; RUN: opt < %s -loop-unroll -unroll-runtime -unroll-allow-partial -S | FileCheck %s
      2 
      3 declare void @f() convergent
      4 
      5 ; Although this loop contains a convergent instruction, it should be
      6 ; fully unrolled.
      7 ;
      8 ; CHECK-LABEL: @full_unroll(
      9 define i32 @full_unroll() {
     10 entry:
     11   br label %l3
     12 
     13 l3:
     14   %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
     15 ; CHECK: call void @f()
     16 ; CHECK: call void @f()
     17 ; CHECK: call void @f()
     18 ; CHECK-NOT: call void @f()
     19   call void @f() ;convergent
     20   %inc = add nsw i32 %x.0, 1
     21   %exitcond = icmp eq i32 %inc, 3
     22   br i1 %exitcond, label %exit, label %l3
     23 
     24 exit:
     25   ret i32 0
     26 }
     27 
     28 ; This loop contains a convergent instruction, but it should be partially
     29 ; unrolled.  The unroll count is the largest power of 2 that divides the
     30 ; multiple -- 4, in this case.
     31 ;
     32 ; CHECK-LABEL: @runtime_unroll(
     33 define i32 @runtime_unroll(i32 %n) {
     34 entry:
     35   %loop_ctl = mul nsw i32 %n, 12
     36   br label %l3
     37 
     38 l3:
     39   %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
     40 ; CHECK: call void @f()
     41 ; CHECK: call void @f()
     42 ; CHECK: call void @f()
     43 ; CHECK: call void @f()
     44 ; CHECK-NOT: call void @f()
     45   call void @f() convergent
     46   %inc = add nsw i32 %x.0, 1
     47   %exitcond = icmp eq i32 %inc, %loop_ctl
     48   br i1 %exitcond, label %exit, label %l3
     49 
     50 exit:
     51   ret i32 0
     52 }
     53 
     54 ; This loop contains a convergent instruction, so its partial unroll
     55 ; count must divide its trip multiple.  This overrides its unroll
     56 ; pragma -- we unroll exactly 8 times, even though 16 is requested.
     57 ; CHECK-LABEL: @pragma_unroll
     58 define i32 @pragma_unroll(i32 %n) {
     59 entry:
     60   %loop_ctl = mul nsw i32 %n, 24
     61   br label %l3, !llvm.loop !0
     62 
     63 l3:
     64   %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
     65 ; CHECK: call void @f()
     66 ; CHECK: call void @f()
     67 ; CHECK: call void @f()
     68 ; CHECK: call void @f()
     69 ; CHECK: call void @f()
     70 ; CHECK: call void @f()
     71 ; CHECK: call void @f()
     72 ; CHECK: call void @f()
     73 ; CHECK-NOT: call void @f()
     74   call void @f() convergent
     75   %inc = add nsw i32 %x.0, 1
     76   %exitcond = icmp eq i32 %inc, %loop_ctl
     77   br i1 %exitcond, label %exit, label %l3, !llvm.loop !0
     78 
     79 exit:
     80   ret i32 0
     81 }
     82 
     83 ; This loop contains a convergent instruction. Since the pragma loop unroll
     84 ; count 2 divides trip count 4. The loop unroll should respect the pragma.
     85 ; CHECK-LABEL: @pragma_unroll_divisible_trip_count
     86 define void @pragma_unroll_divisible_trip_count() {
     87 entry:
     88   br label %l3, !llvm.loop !1
     89 
     90 l3:
     91   %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
     92 ; CHECK: call void @f()
     93 ; CHECK: call void @f()
     94 ; CHECK-NOT: call void @f()
     95   call void @f() convergent
     96   %inc = add nsw i32 %x.0, 1
     97   %exitcond = icmp eq i32 %inc, 4
     98   br i1 %exitcond, label %exit, label %l3, !llvm.loop !1
     99 
    100 exit:
    101   ret void
    102 }
    103 
    104 ; This loop contains a convergent instruction. Since the pragma loop unroll
    105 ; count 2 divides trip multiple 2. The loop unroll should respect the pragma.
    106 ; CHECK-LABEL: @pragma_unroll_divisible_trip_multiple
    107 define i32 @pragma_unroll_divisible_trip_multiple(i32 %n) {
    108 entry:
    109   %loop_ctl = mul nsw i32 %n, 2
    110   br label %l3, !llvm.loop !1
    111 
    112 l3:
    113   %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
    114 ; CHECK: call void @f()
    115 ; CHECK: call void @f()
    116 ; CHECK-NOT: call void @f()
    117   call void @f() convergent
    118   %inc = add nsw i32 %x.0, 1
    119   %exitcond = icmp eq i32 %inc, %loop_ctl
    120   br i1 %exitcond, label %exit, label %l3, !llvm.loop !1
    121 
    122 exit:
    123   ret i32 0
    124 }
    125 
    126 ; This loop contains a convergent instruction. Since the pragma loop unroll
    127 ; count 2 is unknown to divide runtime trip count, the loop is not unrolled
    128 ; since remainder is forbidden for unrolling convergent loop.
    129 ; ToDo: Forbidding remainder for unrolling convergent loop may be relaxed
    130 ; in the future.
    131 ; CHECK-LABEL: @pragma_unroll_indivisible_runtime_trip_count
    132 define i32 @pragma_unroll_indivisible_runtime_trip_count(i32 %n) {
    133 entry:
    134   br label %l3, !llvm.loop !1
    135 
    136 l3:
    137   %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
    138 ; CHECK: call void @f()
    139 ; CHECK-NOT: call void @f()
    140   call void @f() convergent
    141   %inc = add nsw i32 %x.0, 1
    142   %exitcond = icmp eq i32 %inc, %n
    143   br i1 %exitcond, label %exit, label %l3, !llvm.loop !1
    144 
    145 exit:
    146   ret i32 0
    147 }
    148 
    149 ; This loop contains a convergent instruction. Since the pragma loop unroll
    150 ; count 2 does not divide trip count 5, the loop is not unrolled by 2
    151 ; since remainder is forbidden for unrolling convergent loop. Instead, the
    152 ; loop gets fully unrolled.
    153 ; ToDo: Forbidding remainder for unrolling convergent loop may be relaxed
    154 ; in the future.
    155 ; CHECK-LABEL: @pragma_unroll_indivisible_trip_count
    156 define i32 @pragma_unroll_indivisible_trip_count() {
    157 entry:
    158   br label %l3, !llvm.loop !1
    159 
    160 l3:
    161   %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
    162 ; CHECK: call void @f()
    163 ; CHECK: call void @f()
    164 ; CHECK: call void @f()
    165 ; CHECK: call void @f()
    166 ; CHECK: call void @f()
    167 ; CHECK-NOT: call void @f()
    168   call void @f() convergent
    169   %inc = add nsw i32 %x.0, 1
    170   %exitcond = icmp eq i32 %inc, 5
    171   br i1 %exitcond, label %exit, label %l3, !llvm.loop !1
    172 
    173 exit:
    174   ret i32 0
    175 }
    176 
    177 !0 = !{!0, !{!"llvm.loop.unroll.count", i32 16}}
    178 !1 = !{!1, !{!"llvm.loop.unroll.count", i32 2}}
    179 
    180