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 9define internal void @test_single_loop(i32 %a32) { 10entry: 11 %a = trunc i32 %a32 to i1 12 br label %loop0 13 14loop0: ; <-+ 15 br label %loop1 ; | 16loop1: ; | 17 br i1 %a, label %loop0, label %out ; --+ 18 19out: 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 34define internal void @test_single_loop_with_continue(i32 %a32, i32 %b32) { 35entry: 36 %a = trunc i32 %a32 to i1 37 %b = trunc i32 %b32 to i1 38 br label %loop0 39 40loop0: ; <-+ 41 br label %loop1 ; | 42loop1: ; | 43 br i1 %a, label %loop0, label %loop2 ; --+ 44loop2: ; | 45 br i1 %b, label %loop0, label %out ; --+ 46 47out: 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 64define internal void @test_multiple_exits(i32 %a32, i32 %b32) { 65entry: 66 %a = trunc i32 %a32 to i1 67 %b = trunc i32 %b32 to i1 68 br label %loop0 69 70loop0: ; <-+ 71 br label %loop1 ; | 72loop1: ; | 73 br i1 %a, label %loop2, label %out ; --+-+ 74loop2: ; | | 75 br i1 %b, label %loop0, label %out ; --+ | 76 ; | 77out: ; <---+ 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 94define internal void @test_two_nested_loops(i32 %a32, i32 %b32) { 95entry: 96 %a = trunc i32 %a32 to i1 97 %b = trunc i32 %b32 to i1 98 br label %loop0_0 99 100loop0_0: ; <---+ 101 br label %loop1_0 ; | 102loop1_0: ; <-+ | 103 br label %loop1_1 ; | | 104loop1_1: ; | | 105 br i1 %a, label %loop1_0, label %loop0_1 ; --+ | 106loop0_1: ; | 107 br i1 %b, label %loop0_0, label %out ; ----+ 108 109out: 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 128define internal void @test_two_nested_loops_with_continue(i32 %a32, i32 %b32, 129 i32 %c32) { 130entry: 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 136loop0_0: ; <---+ 137 br label %loop1_0 ; | 138loop1_0: ; <-+ | 139 br label %loop1_1 ; | | 140loop1_1: ; | | 141 br i1 %a, label %loop1_0, label %loop1_2 ; --+ | 142loop1_2: ; | | 143 br i1 %a, label %loop1_0, label %loop0_1 ; --+ | 144loop0_1: ; | 145 br i1 %b, label %loop0_0, label %out ; ----+ 146 147out: 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 168define internal void @test_multiple_nested_loops(i32 %a32, i32 %b32) { 169entry: 170 %a = trunc i32 %a32 to i1 171 %b = trunc i32 %b32 to i1 172 br label %loop0_0 173 174loop0_0: ; <---+ 175 br label %loop1_0 ; | 176loop1_0: ; <-+ | 177 br label %loop1_1 ; | | 178loop1_1: ; | | 179 br i1 %a, label %loop1_0, label %loop0_1 ; --+ | 180loop0_1: ; | 181 br label %loop2_0 ; | 182loop2_0: ; <-+ | 183 br label %loop2_1 ; | | 184loop2_1: ; | | 185 br i1 %a, label %loop2_0, label %loop0_2 ; --+ | 186loop0_2: ; | 187 br i1 %b, label %loop0_0, label %out ; ----+ 188 189out: 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 214define internal void @test_three_nested_loops(i32 %a32, i32 %b32, i32 %c32) { 215entry: 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 221loop0_0: ; <-----+ 222 br label %loop1_0 ; | 223loop1_0: ; <---+ | 224 br label %loop2_0 ; | | 225loop2_0: ; <-+ | | 226 br label %loop2_1 ; | | | 227loop2_1: ; | | | 228 br i1 %a, label %loop2_0, label %loop1_1 ; --+ | | 229loop1_1: ; | | 230 br i1 %b, label %loop1_0, label %loop0_1 ; ----+ | 231loop0_1: ; | 232 br i1 %c, label %loop0_0, label %out ; ------+ 233 234out: 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 257define internal void @test_diamond(i32 %a32) { 258entry: 259 %a = trunc i32 %a32 to i1 260 br i1 %a, label %left, label %right 261 262left: 263 br label %out 264 265right: 266 br label %out 267 268out: 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 283define internal void @test_single_block_loop(i32 %count) { 284entry: 285 br label %body 286body: 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 295exit: 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