1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=loop-unroll -unroll-runtime -unroll-allow-partial -S | FileCheck %s 3 4declare void @f() convergent 5declare void @g() 6 7; Although this loop contains a convergent instruction, it should be 8; fully unrolled. 9define i32 @full_unroll() { 10; CHECK-LABEL: @full_unroll( 11; CHECK-NEXT: entry: 12; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor() 13; CHECK-NEXT: br label [[L3:%.*]] 14; CHECK: l3: 15; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ] 16; CHECK-NEXT: br label [[A:%.*]] 17; CHECK: a: 18; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 19; CHECK-NEXT: br label [[A_1:%.*]] 20; CHECK: a.1: 21; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 22; CHECK-NEXT: br label [[A_2:%.*]] 23; CHECK: a.2: 24; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 25; CHECK-NEXT: ret i32 0 26; 27entry: 28 %anchor = call token @llvm.experimental.convergence.anchor() 29 br label %l3 30 31l3: 32 %x.0 = phi i32 [ 0, %entry ], [ %inc, %a ] 33 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ] 34 %inc = add nsw i32 %x.0, 1 35 %exitcond = icmp eq i32 %inc, 3 36 br label %a 37 38a: 39 call void @f() [ "convergencectrl"(token %tok.loop) ] 40 br i1 %exitcond, label %exit, label %l3 41 42exit: 43 ret i32 0 44} 45 46; This loop contains a convergent instruction, but it should be partially 47; unrolled. The unroll count is the largest power of 2 that divides the 48; multiple -- 4, in this case. 49define i32 @runtime_unroll(i32 %n) { 50; CHECK-LABEL: @runtime_unroll( 51; CHECK-NEXT: entry: 52; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor() 53; CHECK-NEXT: [[LOOP_CTL:%.*]] = mul nsw i32 [[N:%.*]], 12 54; CHECK-NEXT: br label [[L3:%.*]] 55; CHECK: l3: 56; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_3:%.*]], [[A_3:%.*]] ] 57; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ] 58; CHECK-NEXT: br label [[A:%.*]] 59; CHECK: a: 60; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 61; CHECK-NEXT: br label [[A_1:%.*]] 62; CHECK: a.1: 63; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 64; CHECK-NEXT: br label [[A_2:%.*]] 65; CHECK: a.2: 66; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 67; CHECK-NEXT: br label [[A_3]] 68; CHECK: a.3: 69; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 70; CHECK-NEXT: [[INC_3]] = add nsw i32 [[X_0]], 4 71; CHECK-NEXT: [[EXITCOND_3:%.*]] = icmp eq i32 [[INC_3]], [[LOOP_CTL]] 72; CHECK-NEXT: br i1 [[EXITCOND_3]], label [[EXIT:%.*]], label [[L3]] 73; CHECK: exit: 74; CHECK-NEXT: ret i32 0 75; 76entry: 77 %anchor = call token @llvm.experimental.convergence.anchor() 78 %loop_ctl = mul nsw i32 %n, 12 79 br label %l3 80 81l3: 82 %x.0 = phi i32 [ 0, %entry ], [ %inc, %a ] 83 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ] 84 br label %a 85 86a: 87 call void @f() [ "convergencectrl"(token %tok.loop) ] 88 %inc = add nsw i32 %x.0, 1 89 %exitcond = icmp eq i32 %inc, %loop_ctl 90 br i1 %exitcond, label %exit, label %l3 91 92exit: 93 ret i32 0 94} 95 96; This loop contains a convergent instruction, so its partial unroll 97; count must divide its trip multiple. This overrides its unroll 98; pragma -- we unroll exactly 8 times, even though 16 is requested. 99define i32 @pragma_unroll(i32 %n) { 100; CHECK-LABEL: @pragma_unroll( 101; CHECK-NEXT: entry: 102; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor() 103; CHECK-NEXT: [[LOOP_CTL:%.*]] = mul nsw i32 [[N:%.*]], 24 104; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP0:![0-9]+]] 105; CHECK: l3: 106; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_7:%.*]], [[A_7:%.*]] ] 107; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ] 108; CHECK-NEXT: br label [[A:%.*]] 109; CHECK: a: 110; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 111; CHECK-NEXT: br label [[A_1:%.*]] 112; CHECK: a.1: 113; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 114; CHECK-NEXT: br label [[A_2:%.*]] 115; CHECK: a.2: 116; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 117; CHECK-NEXT: br label [[A_3:%.*]] 118; CHECK: a.3: 119; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 120; CHECK-NEXT: br label [[A_4:%.*]] 121; CHECK: a.4: 122; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 123; CHECK-NEXT: br label [[A_5:%.*]] 124; CHECK: a.5: 125; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 126; CHECK-NEXT: br label [[A_6:%.*]] 127; CHECK: a.6: 128; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 129; CHECK-NEXT: br label [[A_7]] 130; CHECK: a.7: 131; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 132; CHECK-NEXT: [[INC_7]] = add nsw i32 [[X_0]], 8 133; CHECK-NEXT: [[EXITCOND_7:%.*]] = icmp eq i32 [[INC_7]], [[LOOP_CTL]] 134; CHECK-NEXT: br i1 [[EXITCOND_7]], label [[EXIT:%.*]], label [[L3]], !llvm.loop [[LOOP2:![0-9]+]] 135; CHECK: exit: 136; CHECK-NEXT: ret i32 0 137; 138entry: 139 %anchor = call token @llvm.experimental.convergence.anchor() 140 %loop_ctl = mul nsw i32 %n, 24 141 br label %l3, !llvm.loop !0 142 143l3: 144 %x.0 = phi i32 [ 0, %entry ], [ %inc, %a ] 145 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ] 146 br label %a 147 148a: 149 call void @f() [ "convergencectrl"(token %tok.loop) ] 150 %inc = add nsw i32 %x.0, 1 151 %exitcond = icmp eq i32 %inc, %loop_ctl 152 br i1 %exitcond, label %exit, label %l3, !llvm.loop !0 153 154exit: 155 ret i32 0 156} 157 158; This loop contains a convergent instruction. Since the pragma loop unroll 159; count 2 divides trip count 4. The loop unroll should respect the pragma. 160define void @pragma_unroll_divisible_trip_count() { 161; CHECK-LABEL: @pragma_unroll_divisible_trip_count( 162; CHECK-NEXT: entry: 163; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor() 164; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP4:![0-9]+]] 165; CHECK: l3: 166; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_1:%.*]], [[L3]] ] 167; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ] 168; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 169; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 170; CHECK-NEXT: [[INC_1]] = add nuw nsw i32 [[X_0]], 2 171; CHECK-NEXT: [[EXITCOND_1:%.*]] = icmp eq i32 [[INC_1]], 4 172; CHECK-NEXT: br i1 [[EXITCOND_1]], label [[EXIT:%.*]], label [[L3]], !llvm.loop [[LOOP6:![0-9]+]] 173; CHECK: exit: 174; CHECK-NEXT: ret void 175; 176entry: 177 %anchor = call token @llvm.experimental.convergence.anchor() 178 br label %l3, !llvm.loop !1 179 180l3: 181 %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ] 182 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ] 183 call void @f() [ "convergencectrl"(token %tok.loop) ] 184 %inc = add nsw i32 %x.0, 1 185 %exitcond = icmp eq i32 %inc, 4 186 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1 187 188exit: 189 ret void 190} 191 192; This loop contains a convergent instruction. Since the pragma loop unroll 193; count 2 divides trip multiple 2. The loop unroll should respect the pragma. 194define i32 @pragma_unroll_divisible_trip_multiple(i32 %n) { 195; CHECK-LABEL: @pragma_unroll_divisible_trip_multiple( 196; CHECK-NEXT: entry: 197; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor() 198; CHECK-NEXT: [[LOOP_CTL:%.*]] = mul nsw i32 [[N:%.*]], 2 199; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP4]] 200; CHECK: l3: 201; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_1:%.*]], [[L3]] ] 202; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ] 203; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 204; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 205; CHECK-NEXT: [[INC_1]] = add nsw i32 [[X_0]], 2 206; CHECK-NEXT: [[EXITCOND_1:%.*]] = icmp eq i32 [[INC_1]], [[LOOP_CTL]] 207; CHECK-NEXT: br i1 [[EXITCOND_1]], label [[EXIT:%.*]], label [[L3]], !llvm.loop [[LOOP7:![0-9]+]] 208; CHECK: exit: 209; CHECK-NEXT: ret i32 0 210; 211entry: 212 %anchor = call token @llvm.experimental.convergence.anchor() 213 %loop_ctl = mul nsw i32 %n, 2 214 br label %l3, !llvm.loop !1 215 216l3: 217 %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ] 218 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ] 219 call void @f() [ "convergencectrl"(token %tok.loop) ] 220 %inc = add nsw i32 %x.0, 1 221 %exitcond = icmp eq i32 %inc, %loop_ctl 222 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1 223 224exit: 225 ret i32 0 226} 227 228; This loop contains a convergent instruction. Since the pragma loop unroll 229; count 2 is unknown to divide runtime trip count, the loop is not unrolled 230; since remainder is forbidden for unrolling convergent loop. 231define i32 @pragma_unroll_indivisible_runtime_trip_count(i32 %n) { 232; CHECK-LABEL: @pragma_unroll_indivisible_runtime_trip_count( 233; CHECK-NEXT: entry: 234; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor() 235; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP4]] 236; CHECK: l3: 237; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[L3]] ] 238; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ] 239; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 240; CHECK-NEXT: [[INC]] = add nsw i32 [[X_0]], 1 241; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N:%.*]] 242; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[L3]], !llvm.loop [[LOOP4]] 243; CHECK: exit: 244; CHECK-NEXT: ret i32 0 245; 246entry: 247 %anchor = call token @llvm.experimental.convergence.anchor() 248 br label %l3, !llvm.loop !1 249 250l3: 251 %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ] 252 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ] 253 call void @f() [ "convergencectrl"(token %tok.loop) ] 254 %inc = add nsw i32 %x.0, 1 255 %exitcond = icmp eq i32 %inc, %n 256 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1 257 258exit: 259 ret i32 0 260} 261 262; This loop contains a convergent instruction. Since the pragma loop unroll 263; count 2 does not divide trip count 5, the loop is not unrolled by 2 264; since remainder is forbidden for unrolling convergent loop. Instead, the 265; loop gets fully unrolled. 266define i32 @pragma_unroll_indivisible_trip_count() { 267; CHECK-LABEL: @pragma_unroll_indivisible_trip_count( 268; CHECK-NEXT: entry: 269; CHECK-NEXT: [[ANCHOR:%.*]] = call token @llvm.experimental.convergence.anchor() 270; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP4]] 271; CHECK: l3: 272; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[ANCHOR]]) ] 273; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 274; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 275; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 276; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 277; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 278; CHECK-NEXT: ret i32 0 279; 280entry: 281 %anchor = call token @llvm.experimental.convergence.anchor() 282 br label %l3, !llvm.loop !1 283 284l3: 285 %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ] 286 %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %anchor) ] 287 call void @f() [ "convergencectrl"(token %tok.loop) ] 288 %inc = add nsw i32 %x.0, 1 289 %exitcond = icmp eq i32 %inc, 5 290 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1 291 292exit: 293 ret i32 0 294} 295 296; This loop contains a convergent instruction that is anchored inside the loop 297; itself. It is unrolled by 2 with remainder, as requested by the loop metadata. 298define i32 @pragma_unroll_with_remainder(i32 %n) { 299; CHECK-LABEL: @pragma_unroll_with_remainder( 300; CHECK-NEXT: entry: 301; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[N:%.*]] 302; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], -1 303; CHECK-NEXT: [[XTRAITER:%.*]] = and i32 [[TMP0]], 1 304; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[TMP1]], 1 305; CHECK-NEXT: br i1 [[TMP2]], label [[EXIT_UNR_LCSSA:%.*]], label [[ENTRY_NEW:%.*]] 306; CHECK: entry.new: 307; CHECK-NEXT: [[UNROLL_ITER:%.*]] = sub i32 [[TMP0]], [[XTRAITER]] 308; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP4]] 309; CHECK: l3: 310; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY_NEW]] ], [ [[INC_1:%.*]], [[L3]] ] 311; CHECK-NEXT: [[NITER:%.*]] = phi i32 [ 0, [[ENTRY_NEW]] ], [ [[NITER_NEXT_1:%.*]], [[L3]] ] 312; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.anchor() 313; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 314; CHECK-NEXT: [[TOK_LOOP_1:%.*]] = call token @llvm.experimental.convergence.anchor() 315; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP_1]]) ] 316; CHECK-NEXT: [[INC_1]] = add nsw i32 [[X_0]], 2 317; CHECK-NEXT: [[NITER_NEXT_1]] = add i32 [[NITER]], 2 318; CHECK-NEXT: [[NITER_NCMP_1:%.*]] = icmp eq i32 [[NITER_NEXT_1]], [[UNROLL_ITER]] 319; CHECK-NEXT: br i1 [[NITER_NCMP_1]], label [[EXIT_UNR_LCSSA_LOOPEXIT:%.*]], label [[L3]], !llvm.loop [[LOOP8:![0-9]+]] 320; CHECK: exit.unr-lcssa.loopexit: 321; CHECK-NEXT: br label [[EXIT_UNR_LCSSA]] 322; CHECK: exit.unr-lcssa: 323; CHECK-NEXT: [[LCMP_MOD:%.*]] = icmp ne i32 [[XTRAITER]], 0 324; CHECK-NEXT: br i1 [[LCMP_MOD]], label [[L3_EPIL_PREHEADER:%.*]], label [[EXIT:%.*]] 325; CHECK: l3.epil.preheader: 326; CHECK-NEXT: br label [[L3_EPIL:%.*]] 327; CHECK: l3.epil: 328; CHECK-NEXT: [[TOK_LOOP_EPIL:%.*]] = call token @llvm.experimental.convergence.anchor() 329; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP_EPIL]]) ] 330; CHECK-NEXT: br label [[EXIT]] 331; CHECK: exit: 332; CHECK-NEXT: ret i32 0 333; 334entry: 335 br label %l3, !llvm.loop !1 336 337l3: 338 %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ] 339 %tok.loop = call token @llvm.experimental.convergence.anchor() 340 call void @f() [ "convergencectrl"(token %tok.loop) ] 341 %inc = add nsw i32 %x.0, 1 342 %exitcond = icmp eq i32 %inc, %n 343 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1 344 345exit: 346 ret i32 0 347} 348 349; Don't unroll a loop that is extended by convergence controls. 350; 351; We could theoretically duplicate the extension part, but this is not 352; implemented. 353define i32 @extended_loop(i32 %n) { 354; CHECK-LABEL: @extended_loop( 355; CHECK-NEXT: entry: 356; CHECK-NEXT: br label [[L3:%.*]], !llvm.loop [[LOOP4]] 357; CHECK: l3: 358; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[L3]] ] 359; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.anchor() 360; CHECK-NEXT: [[INC]] = add nsw i32 [[X_0]], 1 361; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N:%.*]] 362; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[L3]], !llvm.loop [[LOOP4]] 363; CHECK: exit: 364; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_LOOP]]) ] 365; CHECK-NEXT: ret i32 0 366; 367entry: 368 br label %l3, !llvm.loop !1 369 370l3: 371 %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ] 372 %tok.loop = call token @llvm.experimental.convergence.anchor() 373 %inc = add nsw i32 %x.0, 1 374 %exitcond = icmp eq i32 %inc, %n 375 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1 376 377exit: 378 call void @f() [ "convergencectrl"(token %tok.loop) ] 379 ret i32 0 380} 381 382; Inner loop is extended beyond the outer loop. No unrolling possible. 383 384define i32 @extended_inner_loop_1(i32 %n, i1 %cond) { 385; CHECK-LABEL: @extended_inner_loop_1( 386; CHECK-NEXT: entry: 387; CHECK-NEXT: br label [[L3:%.*]] 388; CHECK: l3: 389; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LATCH:%.*]] ] 390; CHECK-NEXT: [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.anchor() 391; CHECK-NEXT: [[INC]] = add nsw i32 [[X_0]], 1 392; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 4 393; CHECK-NEXT: br label [[L2:%.*]], !llvm.loop [[LOOP4]] 394; CHECK: l2: 395; CHECK-NEXT: [[TOK_L2:%.*]] = call token @llvm.experimental.convergence.anchor() 396; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2]]) ] 397; CHECK-NEXT: br i1 [[COND:%.*]], label [[L2]], label [[LATCH]], !llvm.loop [[LOOP4]] 398; CHECK: latch: 399; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[L3]] 400; CHECK: exit: 401; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2]]) ] 402; CHECK-NEXT: ret i32 0 403; 404entry: 405 br label %l3 406 407l3: 408 %x.0 = phi i32 [ 0, %entry ], [ %inc, %latch ] 409 %tok.loop = call token @llvm.experimental.convergence.anchor() 410 %inc = add nsw i32 %x.0, 1 411 %exitcond = icmp eq i32 %inc, 4 412 br label %l2, !llvm.loop !1 413 414l2: 415 %tok.l2 = call token @llvm.experimental.convergence.anchor() 416 call void @f() [ "convergencectrl"(token %tok.l2) ] 417 br i1 %cond, label %l2, label %latch, !llvm.loop !1 418 419latch: 420 br i1 %exitcond, label %exit, label %l3 421 422exit: 423 call void @f() [ "convergencectrl"(token %tok.l2) ] 424 ret i32 0 425} 426 427; Inner loop is extended inside the outer loop. Outer loop is unrolled. 428 429define i32 @extended_inner_loop_2(i32 %n, i1 %cond) { 430; CHECK-LABEL: @extended_inner_loop_2( 431; CHECK-NEXT: entry: 432; CHECK-NEXT: br label [[L3:%.*]] 433; CHECK: l3: 434; CHECK-NEXT: br label [[L2:%.*]], !llvm.loop [[LOOP4]] 435; CHECK: l2: 436; CHECK-NEXT: [[TOK_L2:%.*]] = call token @llvm.experimental.convergence.anchor() 437; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2]]) ] 438; CHECK-NEXT: br i1 [[COND:%.*]], label [[L2]], label [[LATCH:%.*]], !llvm.loop [[LOOP4]] 439; CHECK: latch: 440; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2]]) ] 441; CHECK-NEXT: br label [[L2_1:%.*]], !llvm.loop [[LOOP4]] 442; CHECK: l2.1: 443; CHECK-NEXT: [[TOK_L2_1:%.*]] = call token @llvm.experimental.convergence.anchor() 444; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1]]) ] 445; CHECK-NEXT: br i1 [[COND]], label [[L2_1]], label [[LATCH_1:%.*]], !llvm.loop [[LOOP4]] 446; CHECK: latch.1: 447; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1]]) ] 448; CHECK-NEXT: br label [[L2_2:%.*]], !llvm.loop [[LOOP4]] 449; CHECK: l2.2: 450; CHECK-NEXT: [[TOK_L2_2:%.*]] = call token @llvm.experimental.convergence.anchor() 451; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_2]]) ] 452; CHECK-NEXT: br i1 [[COND]], label [[L2_2]], label [[LATCH_2:%.*]], !llvm.loop [[LOOP4]] 453; CHECK: latch.2: 454; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_2]]) ] 455; CHECK-NEXT: br label [[L2_3:%.*]], !llvm.loop [[LOOP4]] 456; CHECK: l2.3: 457; CHECK-NEXT: [[TOK_L2_3:%.*]] = call token @llvm.experimental.convergence.anchor() 458; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_3]]) ] 459; CHECK-NEXT: br i1 [[COND]], label [[L2_3]], label [[LATCH_3:%.*]], !llvm.loop [[LOOP4]] 460; CHECK: latch.3: 461; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_3]]) ] 462; CHECK-NEXT: ret i32 0 463; 464entry: 465 br label %l3 466 467l3: 468 %x.0 = phi i32 [ 0, %entry ], [ %inc, %latch ] 469 %tok.loop = call token @llvm.experimental.convergence.anchor() 470 %inc = add nsw i32 %x.0, 1 471 %exitcond = icmp eq i32 %inc, 4 472 br label %l2, !llvm.loop !1 473 474l2: 475 %tok.l2 = call token @llvm.experimental.convergence.anchor() 476 call void @f() [ "convergencectrl"(token %tok.l2) ] 477 br i1 %cond, label %l2, label %latch, !llvm.loop !1 478 479latch: 480 call void @f() [ "convergencectrl"(token %tok.l2) ] 481 br i1 %exitcond, label %exit, label %l3 482 483exit: 484 ret i32 0 485} 486 487; No extension. Both loops unrolled. 488 489define i32 @unroll_nest(i32 %n, i1 %cond) { 490; CHECK-LABEL: @unroll_nest( 491; CHECK-NEXT: entry: 492; CHECK-NEXT: br label [[L3:%.*]] 493; CHECK: l3: 494; CHECK-NEXT: br label [[L2:%.*]], !llvm.loop [[LOOP4]] 495; CHECK: l2: 496; CHECK-NEXT: [[TOK_L2:%.*]] = call token @llvm.experimental.convergence.anchor() 497; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2]]) ] 498; CHECK-NEXT: br i1 [[COND:%.*]], label [[L2_1:%.*]], label [[LATCH:%.*]], !llvm.loop [[LOOP4]] 499; CHECK: l2.1: 500; CHECK-NEXT: [[TOK_L2_1:%.*]] = call token @llvm.experimental.convergence.anchor() 501; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1]]) ] 502; CHECK-NEXT: br i1 [[COND]], label [[L2]], label [[LATCH]], !llvm.loop [[LOOP9:![0-9]+]] 503; CHECK: latch: 504; CHECK-NEXT: br label [[L2_12:%.*]], !llvm.loop [[LOOP4]] 505; CHECK: l2.12: 506; CHECK-NEXT: [[TOK_L2_11:%.*]] = call token @llvm.experimental.convergence.anchor() 507; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_11]]) ] 508; CHECK-NEXT: br i1 [[COND]], label [[L2_1_1:%.*]], label [[LATCH_1:%.*]], !llvm.loop [[LOOP4]] 509; CHECK: l2.1.1: 510; CHECK-NEXT: [[TOK_L2_1_1:%.*]] = call token @llvm.experimental.convergence.anchor() 511; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1_1]]) ] 512; CHECK-NEXT: br i1 [[COND]], label [[L2_12]], label [[LATCH_1]], !llvm.loop [[LOOP9]] 513; CHECK: latch.1: 514; CHECK-NEXT: br label [[L2_2:%.*]], !llvm.loop [[LOOP4]] 515; CHECK: l2.2: 516; CHECK-NEXT: [[TOK_L2_2:%.*]] = call token @llvm.experimental.convergence.anchor() 517; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_2]]) ] 518; CHECK-NEXT: br i1 [[COND]], label [[L2_1_2:%.*]], label [[LATCH_2:%.*]], !llvm.loop [[LOOP4]] 519; CHECK: l2.1.2: 520; CHECK-NEXT: [[TOK_L2_1_2:%.*]] = call token @llvm.experimental.convergence.anchor() 521; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1_2]]) ] 522; CHECK-NEXT: br i1 [[COND]], label [[L2_2]], label [[LATCH_2]], !llvm.loop [[LOOP9]] 523; CHECK: latch.2: 524; CHECK-NEXT: br label [[L2_3:%.*]], !llvm.loop [[LOOP4]] 525; CHECK: l2.3: 526; CHECK-NEXT: [[TOK_L2_3:%.*]] = call token @llvm.experimental.convergence.anchor() 527; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_3]]) ] 528; CHECK-NEXT: br i1 [[COND]], label [[L2_1_3:%.*]], label [[LATCH_3:%.*]], !llvm.loop [[LOOP4]] 529; CHECK: l2.1.3: 530; CHECK-NEXT: [[TOK_L2_1_3:%.*]] = call token @llvm.experimental.convergence.anchor() 531; CHECK-NEXT: call void @f() [ "convergencectrl"(token [[TOK_L2_1_3]]) ] 532; CHECK-NEXT: br i1 [[COND]], label [[L2_3]], label [[LATCH_3]], !llvm.loop [[LOOP9]] 533; CHECK: latch.3: 534; CHECK-NEXT: ret i32 0 535; 536entry: 537 br label %l3 538 539l3: 540 %x.0 = phi i32 [ 0, %entry ], [ %inc, %latch ] 541 %tok.loop = call token @llvm.experimental.convergence.anchor() 542 %inc = add nsw i32 %x.0, 1 543 %exitcond = icmp eq i32 %inc, 4 544 br label %l2, !llvm.loop !1 545 546l2: 547 %tok.l2 = call token @llvm.experimental.convergence.anchor() 548 call void @f() [ "convergencectrl"(token %tok.l2) ] 549 br i1 %cond, label %l2, label %latch, !llvm.loop !1 550 551latch: 552 br i1 %exitcond, label %exit, label %l3 553 554exit: 555 ret i32 0 556} 557 558declare token @llvm.experimental.convergence.anchor() 559declare token @llvm.experimental.convergence.loop() 560 561!0 = !{!0, !{!"llvm.loop.unroll.count", i32 16}} 562!1 = !{!1, !{!"llvm.loop.unroll.count", i32 2}} 563