1 ; Test the the loop nest depth is correctly calculated for basic blocks. 2 3 ; REQUIRES: allow_dump 4 5 ; Single threaded so that the dumps used for checking happen in order. 6 ; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 --verbose=loop \ 7 ; RUN: -log=%t --threads=0 && FileCheck %s < %t 8 9 define internal void @test_single_loop(i32 %a32) { 10 entry: 11 %a = trunc i32 %a32 to i1 12 br label %loop0 13 14 loop0: ; <-+ 15 br label %loop1 ; | 16 loop1: ; | 17 br i1 %a, label %loop0, label %out ; --+ 18 19 out: 20 ret void 21 } 22 23 ; CHECK-LABEL: After loop analysis 24 ; CHECK-NEXT: entry: 25 ; CHECK-NEXT: LoopNestDepth = 0 26 ; CHECK-NEXT: loop0: 27 ; CHECK-NEXT: LoopNestDepth = 1 28 ; CHECK-NEXT: loop1: 29 ; CHECK-NEXT: LoopNestDepth = 1 30 ; CHECK-NEXT: out: 31 ; CHECK-NEXT: LoopNestDepth = 0 32 ; CHECK-LABEL: Before RMW 33 34 define internal void @test_single_loop_with_continue(i32 %a32, i32 %b32) { 35 entry: 36 %a = trunc i32 %a32 to i1 37 %b = trunc i32 %b32 to i1 38 br label %loop0 39 40 loop0: ; <-+ 41 br label %loop1 ; | 42 loop1: ; | 43 br i1 %a, label %loop0, label %loop2 ; --+ 44 loop2: ; | 45 br i1 %b, label %loop0, label %out ; --+ 46 47 out: 48 ret void 49 } 50 51 ; CHECK-LABEL: After loop analysis 52 ; CHECK-NEXT: entry: 53 ; CHECK-NEXT: LoopNestDepth = 0 54 ; CHECK-NEXT: loop0: 55 ; CHECK-NEXT: LoopNestDepth = 1 56 ; CHECK-NEXT: loop1: 57 ; CHECK-NEXT: LoopNestDepth = 1 58 ; CHECK-NEXT: loop2: 59 ; CHECK-NEXT: LoopNestDepth = 1 60 ; CHECK-NEXT: out: 61 ; CHECK-NEXT: LoopNestDepth = 0 62 ; CHECK-LABEL: Before RMW 63 64 define internal void @test_multiple_exits(i32 %a32, i32 %b32) { 65 entry: 66 %a = trunc i32 %a32 to i1 67 %b = trunc i32 %b32 to i1 68 br label %loop0 69 70 loop0: ; <-+ 71 br label %loop1 ; | 72 loop1: ; | 73 br i1 %a, label %loop2, label %out ; --+-+ 74 loop2: ; | | 75 br i1 %b, label %loop0, label %out ; --+ | 76 ; | 77 out: ; <---+ 78 ret void 79 } 80 81 ; CHECK-LABEL: After loop analysis 82 ; CHECK-NEXT: entry: 83 ; CHECK-NEXT: LoopNestDepth = 0 84 ; CHECK-NEXT: loop0: 85 ; CHECK-NEXT: LoopNestDepth = 1 86 ; CHECK-NEXT: loop1: 87 ; CHECK-NEXT: LoopNestDepth = 1 88 ; CHECK-NEXT: loop2: 89 ; CHECK-NEXT: LoopNestDepth = 1 90 ; CHECK-NEXT: out: 91 ; CHECK-NEXT: LoopNestDepth = 0 92 ; CHECK-LABEL: Before RMW 93 94 define internal void @test_two_nested_loops(i32 %a32, i32 %b32) { 95 entry: 96 %a = trunc i32 %a32 to i1 97 %b = trunc i32 %b32 to i1 98 br label %loop0_0 99 100 loop0_0: ; <---+ 101 br label %loop1_0 ; | 102 loop1_0: ; <-+ | 103 br label %loop1_1 ; | | 104 loop1_1: ; | | 105 br i1 %a, label %loop1_0, label %loop0_1 ; --+ | 106 loop0_1: ; | 107 br i1 %b, label %loop0_0, label %out ; ----+ 108 109 out: 110 ret void 111 } 112 113 ; CHECK-LABEL: After loop analysis 114 ; CHECK-NEXT: entry: 115 ; CHECK-NEXT: LoopNestDepth = 0 116 ; CHECK-NEXT: loop0_0: 117 ; CHECK-NEXT: LoopNestDepth = 1 118 ; CHECK-NEXT: loop1_0: 119 ; CHECK-NEXT: LoopNestDepth = 2 120 ; CHECK-NEXT: loop1_1: 121 ; CHECK-NEXT: LoopNestDepth = 2 122 ; CHECK-NEXT: loop0_1: 123 ; CHECK-NEXT: LoopNestDepth = 1 124 ; CHECK-NEXT: out: 125 ; CHECK-NEXT: LoopNestDepth = 0 126 ; CHECK-LABEL: Before RMW 127 128 define internal void @test_two_nested_loops_with_continue(i32 %a32, i32 %b32, 129 i32 %c32) { 130 entry: 131 %a = trunc i32 %a32 to i1 132 %b = trunc i32 %b32 to i1 133 %c = trunc i32 %c32 to i1 134 br label %loop0_0 135 136 loop0_0: ; <---+ 137 br label %loop1_0 ; | 138 loop1_0: ; <-+ | 139 br label %loop1_1 ; | | 140 loop1_1: ; | | 141 br i1 %a, label %loop1_0, label %loop1_2 ; --+ | 142 loop1_2: ; | | 143 br i1 %a, label %loop1_0, label %loop0_1 ; --+ | 144 loop0_1: ; | 145 br i1 %b, label %loop0_0, label %out ; ----+ 146 147 out: 148 ret void 149 } 150 151 ; CHECK-LABEL: After loop analysis 152 ; CHECK-NEXT: entry: 153 ; CHECK-NEXT: LoopNestDepth = 0 154 ; CHECK-NEXT: loop0_0: 155 ; CHECK-NEXT: LoopNestDepth = 1 156 ; CHECK-NEXT: loop1_0: 157 ; CHECK-NEXT: LoopNestDepth = 2 158 ; CHECK-NEXT: loop1_1: 159 ; CHECK-NEXT: LoopNestDepth = 2 160 ; CHECK-NEXT: loop1_2: 161 ; CHECK-NEXT: LoopNestDepth = 2 162 ; CHECK-NEXT: loop0_1: 163 ; CHECK-NEXT: LoopNestDepth = 1 164 ; CHECK-NEXT: out: 165 ; CHECK-NEXT: LoopNestDepth = 0 166 ; CHECK-LABEL: Before RMW 167 168 define internal void @test_multiple_nested_loops(i32 %a32, i32 %b32) { 169 entry: 170 %a = trunc i32 %a32 to i1 171 %b = trunc i32 %b32 to i1 172 br label %loop0_0 173 174 loop0_0: ; <---+ 175 br label %loop1_0 ; | 176 loop1_0: ; <-+ | 177 br label %loop1_1 ; | | 178 loop1_1: ; | | 179 br i1 %a, label %loop1_0, label %loop0_1 ; --+ | 180 loop0_1: ; | 181 br label %loop2_0 ; | 182 loop2_0: ; <-+ | 183 br label %loop2_1 ; | | 184 loop2_1: ; | | 185 br i1 %a, label %loop2_0, label %loop0_2 ; --+ | 186 loop0_2: ; | 187 br i1 %b, label %loop0_0, label %out ; ----+ 188 189 out: 190 ret void 191 } 192 193 ; CHECK-LABEL: After loop analysis 194 ; CHECK-NEXT: entry: 195 ; CHECK-NEXT: LoopNestDepth = 0 196 ; CHECK-NEXT: loop0_0: 197 ; CHECK-NEXT: LoopNestDepth = 1 198 ; CHECK-NEXT: loop1_0: 199 ; CHECK-NEXT: LoopNestDepth = 2 200 ; CHECK-NEXT: loop1_1: 201 ; CHECK-NEXT: LoopNestDepth = 2 202 ; CHECK-NEXT: loop0_1: 203 ; CHECK-NEXT: LoopNestDepth = 1 204 ; CHECK-NEXT: loop2_0: 205 ; CHECK-NEXT: LoopNestDepth = 2 206 ; CHECK-NEXT: loop2_1: 207 ; CHECK-NEXT: LoopNestDepth = 2 208 ; CHECK-NEXT: loop0_2: 209 ; CHECK-NEXT: LoopNestDepth = 1 210 ; CHECK-NEXT: out: 211 ; CHECK-NEXT: LoopNestDepth = 0 212 ; CHECK-LABEL: Before RMW 213 214 define internal void @test_three_nested_loops(i32 %a32, i32 %b32, i32 %c32) { 215 entry: 216 %a = trunc i32 %a32 to i1 217 %b = trunc i32 %b32 to i1 218 %c = trunc i32 %c32 to i1 219 br label %loop0_0 220 221 loop0_0: ; <-----+ 222 br label %loop1_0 ; | 223 loop1_0: ; <---+ | 224 br label %loop2_0 ; | | 225 loop2_0: ; <-+ | | 226 br label %loop2_1 ; | | | 227 loop2_1: ; | | | 228 br i1 %a, label %loop2_0, label %loop1_1 ; --+ | | 229 loop1_1: ; | | 230 br i1 %b, label %loop1_0, label %loop0_1 ; ----+ | 231 loop0_1: ; | 232 br i1 %c, label %loop0_0, label %out ; ------+ 233 234 out: 235 ret void 236 } 237 238 ; CHECK-LABEL: After loop analysis 239 ; CHECK-NEXT: entry: 240 ; CHECK-NEXT: LoopNestDepth = 0 241 ; CHECK-NEXT: loop0_0: 242 ; CHECK-NEXT: LoopNestDepth = 1 243 ; CHECK-NEXT: loop1_0: 244 ; CHECK-NEXT: LoopNestDepth = 2 245 ; CHECK-NEXT: loop2_0: 246 ; CHECK-NEXT: LoopNestDepth = 3 247 ; CHECK-NEXT: loop2_1: 248 ; CHECK-NEXT: LoopNestDepth = 3 249 ; CHECK-NEXT: loop1_1: 250 ; CHECK-NEXT: LoopNestDepth = 2 251 ; CHECK-NEXT: loop0_1: 252 ; CHECK-NEXT: LoopNestDepth = 1 253 ; CHECK-NEXT: out: 254 ; CHECK-NEXT: LoopNestDepth = 0 255 ; CHECK-LABEL: Before RMW 256 257 define internal void @test_diamond(i32 %a32) { 258 entry: 259 %a = trunc i32 %a32 to i1 260 br i1 %a, label %left, label %right 261 262 left: 263 br label %out 264 265 right: 266 br label %out 267 268 out: 269 ret void 270 } 271 272 ; CHECK-LABEL: After loop analysis 273 ; CHECK-NEXT: entry: 274 ; CHECK-NEXT: LoopNestDepth = 0 275 ; CHECK-NEXT: left: 276 ; CHECK-NEXT: LoopNestDepth = 0 277 ; CHECK-NEXT: right: 278 ; CHECK-NEXT: LoopNestDepth = 0 279 ; CHECK-NEXT: out: 280 ; CHECK-NEXT: LoopNestDepth = 0 281 ; CHECK-LABEL: Before RMW 282 283 define internal void @test_single_block_loop(i32 %count) { 284 entry: 285 br label %body 286 body: 287 ; %i = phi i32 [ 0, %entry ], [ %inc, %body ] 288 ; A normal loop would have a phi instruction like above for the induction 289 ; variable, but that may introduce new basic blocks due to phi edge splitting, 290 ; so we use an alternative definition for %i to make the test more clear. 291 %i = add i32 %count, 1 292 %inc = add i32 %i, 1 293 %cmp = icmp slt i32 %inc, %count 294 br i1 %cmp, label %body, label %exit 295 exit: 296 ret void 297 } 298 299 ; CHECK-LABEL: After loop analysis 300 ; CHECK-NEXT: entry: 301 ; CHECK-NEXT: LoopNestDepth = 0 302 ; CHECK-NEXT: body: 303 ; CHECK-NEXT: LoopNestDepth = 1 304 ; CHECK-NEXT: exit: 305 ; CHECK-NEXT: LoopNestDepth = 0 306 ; CHECK-LABEL: Before RMW 307