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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
; RUN: opt < %s -loop-unroll -S | FileCheck %s
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
; This test shows how unrolling an inner loop could break LCSSA for an outer
; loop, and there is no cheap way to recover it.
;
; In this case the inner loop, L3, is being unrolled. It only runs one
; iteration, so unrolling basically means replacing
; br i1 true, label %exit, label %L3_header
; with
; br label %exit
;
; However, this change messes up the loops structure: for instance, block
; L3_body no longer belongs to L2. It becomes an exit block for L2, so LCSSA
; phis for definitions in L2 should now be placed there. In particular, we need
; to insert such a definition for %y1.
; CHECK-LABEL: @foo1
define void @foo1() {
entry:
br label %L1_header
L1_header:
br label %L2_header
L2_header:
%y1 = phi i64 [ undef, %L1_header ], [ %x.lcssa, %L2_latch ]
br label %L3_header
L3_header:
%y2 = phi i64 [ 0, %L3_latch ], [ %y1, %L2_header ]
%x = add i64 undef, -1
br i1 true, label %L2_latch, label %L3_body
L2_latch:
%x.lcssa = phi i64 [ %x, %L3_header ]
br label %L2_header
; CHECK: L3_body:
; CHECK-NEXT: %y1.lcssa = phi i64 [ %y1, %L3_header ]
L3_body:
store i64 %y1, i64* undef
br i1 false, label %L3_latch, label %L1_latch
L3_latch:
br i1 true, label %exit, label %L3_header
L1_latch:
%y.lcssa = phi i64 [ %y2, %L3_body ]
br label %L1_header
exit:
ret void
}
; Additional tests for some corner cases.
;
; CHECK-LABEL: @foo2
define void @foo2() {
entry:
br label %L1_header
L1_header:
br label %L2_header
L2_header:
%a = phi i64 [ undef, %L1_header ], [ %dec_us, %L3_header ]
br label %L3_header
L3_header:
%b = phi i64 [ 0, %L3_latch ], [ %a, %L2_header ]
%dec_us = add i64 undef, -1
br i1 true, label %L2_header, label %L3_break_to_L1
; CHECK: L3_break_to_L1:
; CHECK-NEXT: %a.lcssa = phi i64 [ %a, %L3_header ]
L3_break_to_L1:
br i1 false, label %L3_latch, label %L1_latch
L1_latch:
%b_lcssa = phi i64 [ %b, %L3_break_to_L1 ]
br label %L1_header
L3_latch:
br i1 true, label %Exit, label %L3_header
Exit:
ret void
}
; CHECK-LABEL: @foo3
define void @foo3() {
entry:
br label %L1_header
L1_header:
%a = phi i8* [ %b, %L1_latch ], [ null, %entry ]
br i1 undef, label %L2_header, label %L1_latch
L2_header:
br i1 undef, label %L2_latch, label %L1_latch
; CHECK: L2_latch:
; CHECK-NEXT: %a.lcssa = phi i8* [ %a, %L2_header ]
L2_latch:
br i1 true, label %L2_exit, label %L2_header
L1_latch:
%b = phi i8* [ undef, %L1_header ], [ null, %L2_header ]
br label %L1_header
L2_exit:
%a_lcssa1 = phi i8* [ %a, %L2_latch ]
br label %Exit
Exit:
%a_lcssa2 = phi i8* [ %a_lcssa1, %L2_exit ]
ret void
}
; PR26688
; CHECK-LABEL: @foo4
define i8 @foo4() {
entry:
br label %L1_header
L1_header:
%x = icmp eq i32 1, 0
br label %L2_header
L2_header:
br label %L3_header
L3_header:
br i1 true, label %L2_header, label %L3_exiting
L3_exiting:
br i1 true, label %L3_body, label %L1_latch
; CHECK: L3_body:
; CHECK-NEXT: %x.lcssa = phi i1
L3_body:
br i1 %x, label %L3_latch, label %L3_latch
L3_latch:
br i1 false, label %L3_header, label %exit
L1_latch:
br label %L1_header
exit:
ret i8 0
}
; CHECK-LABEL: @foo5
define void @foo5() {
entry:
br label %outer
outer:
br label %inner1
; CHECK: inner1:
; CHECK-NOT: br i1 true
; CHECK: br label %inner2_indirect_exit
inner1:
br i1 true, label %inner2_indirect_exit.preheader, label %inner1
inner2_indirect_exit.preheader:
br label %inner2_indirect_exit
inner2_indirect_exit:
%a = phi i32 [ %b, %inner2_latch ], [ undef, %inner2_indirect_exit.preheader ]
indirectbr i8* undef, [label %inner2_latch, label %inner3, label %outer_latch]
inner2_latch:
%b = load i32, i32* undef, align 8
br label %inner2_indirect_exit
inner3:
%a.lcssa = phi i32 [ %a.lcssa, %inner3 ], [ %a, %inner2_indirect_exit ]
br i1 true, label %outer_latch.loopexit, label %inner3
outer_latch.loopexit:
%a.lcssa.lcssa = phi i32 [ %a.lcssa, %inner3 ]
br label %outer_latch
outer_latch:
br label %outer
}
|