Home | History | Annotate | Download | only in LoopUnroll
      1 ; This test checks that nested loops are revisited in various scenarios when
      2 ; unrolling. Note that if we ever start doing outer loop peeling a test case
      3 ; for that should be added here that will look essentially like a hybrid of the
      4 ; current two cases.
      5 ;
      6 ; RUN: opt < %s -disable-output -debug-pass-manager 2>&1 \
      7 ; RUN:     -passes='require<opt-remark-emit>,loop(unroll-full)' \
      8 ; RUN:     | FileCheck %s
      9 ;
     10 ; Also run in a special mode that visits children.
     11 ; RUN: opt < %s -disable-output -debug-pass-manager -unroll-revisit-child-loops 2>&1 \
     12 ; RUN:     -passes='require<opt-remark-emit>,loop(unroll-full)' \
     13 ; RUN:     | FileCheck %s --check-prefixes=CHECK,CHECK-CHILDREN
     14 
     15 ; Basic test is fully unrolled and we revisit the post-unroll new sibling
     16 ; loops, including the ones that used to be child loops.
     17 define void @full_unroll(i1* %ptr) {
     18 ; CHECK-LABEL: FunctionToLoopPassAdaptor{{.*}} on full_unroll
     19 ; CHECK-NOT: LoopFullUnrollPass
     20 
     21 entry:
     22   br label %l0
     23 
     24 l0:
     25   %cond.0 = load volatile i1, i1* %ptr
     26   br i1 %cond.0, label %l0.0.ph, label %exit
     27 
     28 l0.0.ph:
     29   br label %l0.0
     30 
     31 l0.0:
     32   %iv = phi i32 [ %iv.next, %l0.0.latch ], [ 0, %l0.0.ph ]
     33   %iv.next = add i32 %iv, 1
     34   br label %l0.0.0.ph
     35 
     36 l0.0.0.ph:
     37   br label %l0.0.0
     38 
     39 l0.0.0:
     40   %cond.0.0.0 = load volatile i1, i1* %ptr
     41   br i1 %cond.0.0.0, label %l0.0.0, label %l0.0.1.ph
     42 ; CHECK: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.0<header>
     43 ; CHECK-NOT: LoopFullUnrollPass
     44 
     45 l0.0.1.ph:
     46   br label %l0.0.1
     47 
     48 l0.0.1:
     49   %cond.0.0.1 = load volatile i1, i1* %ptr
     50   br i1 %cond.0.0.1, label %l0.0.1, label %l0.0.latch
     51 ; CHECK: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.1<header>
     52 ; CHECK-NOT: LoopFullUnrollPass
     53 
     54 l0.0.latch:
     55   %cmp = icmp slt i32 %iv.next, 2
     56   br i1 %cmp, label %l0.0, label %l0.latch
     57 ; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0
     58 ; CHECK-NOT: LoopFullUnrollPass
     59 ;
     60 ; Unrolling occurs, so we visit what were the inner loops twice over. First we
     61 ; visit their clones, and then we visit the original loops re-parented.
     62 ; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0.1.1<header>
     63 ; CHECK-NOT: LoopFullUnrollPass
     64 ; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0.0.1<header>
     65 ; CHECK-NOT: LoopFullUnrollPass
     66 ; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0.1<header>
     67 ; CHECK-NOT: LoopFullUnrollPass
     68 ; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0.0<header>
     69 ; CHECK-NOT: LoopFullUnrollPass
     70 
     71 l0.latch:
     72   br label %l0
     73 ; CHECK: LoopFullUnrollPass on Loop at depth 1 containing: %l0<header>
     74 ; CHECK-NOT: LoopFullUnrollPass
     75 
     76 exit:
     77   ret void
     78 }
     79 
     80 ; Now we test forced runtime partial unrolling with metadata. Here we end up
     81 ; duplicating child loops without changing their structure and so they aren't by
     82 ; default visited, but will be visited with a special parameter.
     83 define void @partial_unroll(i32 %count, i1* %ptr) {
     84 ; CHECK-LABEL: FunctionToLoopPassAdaptor{{.*}} on partial_unroll
     85 ; CHECK-NOT: LoopFullUnrollPass
     86 
     87 entry:
     88   br label %l0
     89 
     90 l0:
     91   %cond.0 = load volatile i1, i1* %ptr
     92   br i1 %cond.0, label %l0.0.ph, label %exit
     93 
     94 l0.0.ph:
     95   br label %l0.0
     96 
     97 l0.0:
     98   %iv = phi i32 [ %iv.next, %l0.0.latch ], [ 0, %l0.0.ph ]
     99   %iv.next = add i32 %iv, 1
    100   br label %l0.0.0.ph
    101 
    102 l0.0.0.ph:
    103   br label %l0.0.0
    104 
    105 l0.0.0:
    106   %cond.0.0.0 = load volatile i1, i1* %ptr
    107   br i1 %cond.0.0.0, label %l0.0.0, label %l0.0.1.ph
    108 ; CHECK: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.0<header>
    109 ; CHECK-NOT: LoopFullUnrollPass
    110 
    111 l0.0.1.ph:
    112   br label %l0.0.1
    113 
    114 l0.0.1:
    115   %cond.0.0.1 = load volatile i1, i1* %ptr
    116   br i1 %cond.0.0.1, label %l0.0.1, label %l0.0.latch
    117 ; CHECK: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.1<header>
    118 ; CHECK-NOT: LoopFullUnrollPass
    119 
    120 l0.0.latch:
    121   %cmp = icmp slt i32 %iv.next, %count
    122   br i1 %cmp, label %l0.0, label %l0.latch, !llvm.loop !1
    123 ; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0
    124 ; CHECK-NOT: LoopFullUnrollPass
    125 ;
    126 ; Partial unrolling occurs which introduces both new child loops and new sibling
    127 ; loops. We only visit the child loops in a special mode, not by default.
    128 ; CHECK-CHILDREN: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.0<header>
    129 ; CHECK-CHILDREN-NOT: LoopFullUnrollPass
    130 ; CHECK-CHILDREN: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.1<header>
    131 ; CHECK-CHILDREN-NOT: LoopFullUnrollPass
    132 ; CHECK-CHILDREN: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.0.1<header>
    133 ; CHECK-CHILDREN-NOT: LoopFullUnrollPass
    134 ; CHECK-CHILDREN: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.1.1<header>
    135 ; CHECK-CHILDREN-NOT: LoopFullUnrollPass
    136 ;
    137 ; When we revisit children, we also revisit the current loop.
    138 ; CHECK-CHILDREN: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0<header>
    139 ; CHECK-CHILDREN-NOT: LoopFullUnrollPass
    140 ;
    141 ; Revisit the children of the outer loop that are part of the epilogue.
    142 ; 
    143 ; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0.0.epil<header>
    144 ; CHECK-NOT: LoopFullUnrollPass
    145 ; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0.1.epil<header>
    146 ; CHECK-NOT: LoopFullUnrollPass
    147 l0.latch:
    148   br label %l0
    149 ; CHECK: LoopFullUnrollPass on Loop at depth 1 containing: %l0<header>
    150 ; CHECK-NOT: LoopFullUnrollPass
    151 
    152 exit:
    153   ret void
    154 }
    155 !1 = !{!1, !2}
    156 !2 = !{!"llvm.loop.unroll.count", i32 2}
    157