reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
; This test checks that nested loops are revisited in various scenarios when
; unrolling. Note that if we ever start doing outer loop peeling a test case
; for that should be added here that will look essentially like a hybrid of the
; current two cases.
;
; RUN: opt < %s -disable-output -debug-pass-manager 2>&1 \
; RUN:     -passes='require<opt-remark-emit>,loop(unroll-full)' \
; RUN:     | FileCheck %s
;
; Also run in a special mode that visits children.
; RUN: opt < %s -disable-output -debug-pass-manager -unroll-revisit-child-loops 2>&1 \
; RUN:     -passes='require<opt-remark-emit>,loop(unroll-full)' \
; RUN:     | FileCheck %s --check-prefixes=CHECK,CHECK-CHILDREN

; Basic test is fully unrolled and we revisit the post-unroll new sibling
; loops, including the ones that used to be child loops.
define void @full_unroll(i1* %ptr) {
; CHECK-LABEL: FunctionToLoopPassAdaptor{{.*}} on full_unroll
; CHECK-NOT: LoopFullUnrollPass

entry:
  br label %l0

l0:
  %cond.0 = load volatile i1, i1* %ptr
  br i1 %cond.0, label %l0.0.ph, label %exit

l0.0.ph:
  br label %l0.0

l0.0:
  %iv = phi i32 [ %iv.next, %l0.0.latch ], [ 0, %l0.0.ph ]
  %iv.next = add i32 %iv, 1
  br label %l0.0.0.ph

l0.0.0.ph:
  br label %l0.0.0

l0.0.0:
  %cond.0.0.0 = load volatile i1, i1* %ptr
  br i1 %cond.0.0.0, label %l0.0.0, label %l0.0.1.ph
; CHECK: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.0<header>
; CHECK-NOT: LoopFullUnrollPass

l0.0.1.ph:
  br label %l0.0.1

l0.0.1:
  %cond.0.0.1 = load volatile i1, i1* %ptr
  br i1 %cond.0.0.1, label %l0.0.1, label %l0.0.latch
; CHECK: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.1<header>
; CHECK-NOT: LoopFullUnrollPass

l0.0.latch:
  %cmp = icmp slt i32 %iv.next, 2
  br i1 %cmp, label %l0.0, label %l0.latch
; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0
; CHECK-NOT: LoopFullUnrollPass
;
; Unrolling occurs, so we visit what were the inner loops twice over. First we
; visit their clones, and then we visit the original loops re-parented.
; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0.1.1<header>
; CHECK-NOT: LoopFullUnrollPass
; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0.0.1<header>
; CHECK-NOT: LoopFullUnrollPass
; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0.1<header>
; CHECK-NOT: LoopFullUnrollPass
; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0.0<header>
; CHECK-NOT: LoopFullUnrollPass

l0.latch:
  br label %l0
; CHECK: LoopFullUnrollPass on Loop at depth 1 containing: %l0<header>
; CHECK-NOT: LoopFullUnrollPass

exit:
  ret void
}

; Now we test forced runtime partial unrolling with metadata. Here we end up
; duplicating child loops without changing their structure and so they aren't by
; default visited, but will be visited with a special parameter.
define void @partial_unroll(i32 %count, i1* %ptr) {
; CHECK-LABEL: FunctionToLoopPassAdaptor{{.*}} on partial_unroll
; CHECK-NOT: LoopFullUnrollPass

entry:
  br label %l0

l0:
  %cond.0 = load volatile i1, i1* %ptr
  br i1 %cond.0, label %l0.0.ph, label %exit

l0.0.ph:
  br label %l0.0

l0.0:
  %iv = phi i32 [ %iv.next, %l0.0.latch ], [ 0, %l0.0.ph ]
  %iv.next = add i32 %iv, 1
  br label %l0.0.0.ph

l0.0.0.ph:
  br label %l0.0.0

l0.0.0:
  %cond.0.0.0 = load volatile i1, i1* %ptr
  br i1 %cond.0.0.0, label %l0.0.0, label %l0.0.1.ph
; CHECK: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.0<header>
; CHECK-NOT: LoopFullUnrollPass

l0.0.1.ph:
  br label %l0.0.1

l0.0.1:
  %cond.0.0.1 = load volatile i1, i1* %ptr
  br i1 %cond.0.0.1, label %l0.0.1, label %l0.0.latch
; CHECK: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.1<header>
; CHECK-NOT: LoopFullUnrollPass

l0.0.latch:
  %cmp = icmp slt i32 %iv.next, %count
  br i1 %cmp, label %l0.0, label %l0.latch, !llvm.loop !1
; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0
; CHECK-NOT: LoopFullUnrollPass
;
; Partial unrolling occurs which introduces both new child loops and new sibling
; loops. We only visit the child loops in a special mode, not by default.
; CHECK-CHILDREN: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.0<header>
; CHECK-CHILDREN-NOT: LoopFullUnrollPass
; CHECK-CHILDREN: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.1<header>
; CHECK-CHILDREN-NOT: LoopFullUnrollPass
; CHECK-CHILDREN: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.0.1<header>
; CHECK-CHILDREN-NOT: LoopFullUnrollPass
; CHECK-CHILDREN: LoopFullUnrollPass on Loop at depth 3 containing: %l0.0.1.1<header>
; CHECK-CHILDREN-NOT: LoopFullUnrollPass
;
; When we revisit children, we also revisit the current loop.
; CHECK-CHILDREN: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0<header>
; CHECK-CHILDREN-NOT: LoopFullUnrollPass
;
; Revisit the children of the outer loop that are part of the epilogue.
; 
; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0.0.epil<header>
; CHECK-NOT: LoopFullUnrollPass
; CHECK: LoopFullUnrollPass on Loop at depth 2 containing: %l0.0.1.epil<header>
; CHECK-NOT: LoopFullUnrollPass
l0.latch:
  br label %l0
; CHECK: LoopFullUnrollPass on Loop at depth 1 containing: %l0<header>
; CHECK-NOT: LoopFullUnrollPass

exit:
  ret void
}
!1 = !{!1, !2}
!2 = !{!"llvm.loop.unroll.count", i32 2}