563 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=loop-unroll -unroll-runtime -unroll-allow-partial -S | FileCheck %s3 4declare void @f() convergent5declare void @g()6 7; Although this loop contains a convergent instruction, it should be8; 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 026;27entry:28 %anchor = call token @llvm.experimental.convergence.anchor()29 br label %l330 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, 135 %exitcond = icmp eq i32 %inc, 336 br label %a37 38a:39 call void @f() [ "convergencectrl"(token %tok.loop) ]40 br i1 %exitcond, label %exit, label %l341 42exit:43 ret i32 044}45 46; This loop contains a convergent instruction, but it should be partially47; unrolled. The unroll count is the largest power of 2 that divides the48; 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:%.*]], 1254; 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]], 471; 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 075;76entry:77 %anchor = call token @llvm.experimental.convergence.anchor()78 %loop_ctl = mul nsw i32 %n, 1279 br label %l380 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 %a85 86a:87 call void @f() [ "convergencectrl"(token %tok.loop) ]88 %inc = add nsw i32 %x.0, 189 %exitcond = icmp eq i32 %inc, %loop_ctl90 br i1 %exitcond, label %exit, label %l391 92exit:93 ret i32 094}95 96; This loop contains a convergent instruction, so its partial unroll97; count must divide its trip multiple. This overrides its unroll98; 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:%.*]], 24104; 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]], 8133; 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 0137;138entry:139 %anchor = call token @llvm.experimental.convergence.anchor()140 %loop_ctl = mul nsw i32 %n, 24141 br label %l3, !llvm.loop !0142 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 %a147 148a:149 call void @f() [ "convergencectrl"(token %tok.loop) ]150 %inc = add nsw i32 %x.0, 1151 %exitcond = icmp eq i32 %inc, %loop_ctl152 br i1 %exitcond, label %exit, label %l3, !llvm.loop !0153 154exit:155 ret i32 0156}157 158; This loop contains a convergent instruction. Since the pragma loop unroll159; 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]], 2171; CHECK-NEXT: [[EXITCOND_1:%.*]] = icmp eq i32 [[INC_1]], 4172; CHECK-NEXT: br i1 [[EXITCOND_1]], label [[EXIT:%.*]], label [[L3]], !llvm.loop [[LOOP6:![0-9]+]]173; CHECK: exit:174; CHECK-NEXT: ret void175;176entry:177 %anchor = call token @llvm.experimental.convergence.anchor()178 br label %l3, !llvm.loop !1179 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, 1185 %exitcond = icmp eq i32 %inc, 4186 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1187 188exit:189 ret void190}191 192; This loop contains a convergent instruction. Since the pragma loop unroll193; 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:%.*]], 2199; 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]], 2206; 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 0210;211entry:212 %anchor = call token @llvm.experimental.convergence.anchor()213 %loop_ctl = mul nsw i32 %n, 2214 br label %l3, !llvm.loop !1215 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, 1221 %exitcond = icmp eq i32 %inc, %loop_ctl222 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1223 224exit:225 ret i32 0226}227 228; This loop contains a convergent instruction. Since the pragma loop unroll229; count 2 is unknown to divide runtime trip count, the loop is not unrolled230; 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]], 1241; 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 0245;246entry:247 %anchor = call token @llvm.experimental.convergence.anchor()248 br label %l3, !llvm.loop !1249 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, 1255 %exitcond = icmp eq i32 %inc, %n256 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1257 258exit:259 ret i32 0260}261 262; This loop contains a convergent instruction. Since the pragma loop unroll263; count 2 does not divide trip count 5, the loop is not unrolled by 2264; since remainder is forbidden for unrolling convergent loop. Instead, the265; 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 0279;280entry:281 %anchor = call token @llvm.experimental.convergence.anchor()282 br label %l3, !llvm.loop !1283 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, 1289 %exitcond = icmp eq i32 %inc, 5290 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1291 292exit:293 ret i32 0294}295 296; This loop contains a convergent instruction that is anchored inside the loop297; 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]], -1303; CHECK-NEXT: [[XTRAITER:%.*]] = and i32 [[TMP0]], 1304; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[TMP1]], 1305; CHECK-NEXT: br i1 [[TMP2]], label [[L3_EPIL_PREHEADER:%.*]], 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]], 2317; CHECK-NEXT: [[NITER_NEXT_1]] = add i32 [[NITER]], 2318; 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:%.*]], label [[L3]], !llvm.loop [[LOOP8:![0-9]+]]320; CHECK: exit.unr-lcssa:321; CHECK-NEXT: [[LCMP_MOD:%.*]] = icmp ne i32 [[XTRAITER]], 0322; CHECK-NEXT: br i1 [[LCMP_MOD]], label [[L3_EPIL_PREHEADER]], label [[EXIT:%.*]]323; CHECK: l3.epil.preheader:324; CHECK-NEXT: [[LCMP_MOD1:%.*]] = icmp ne i32 [[XTRAITER]], 0325; CHECK-NEXT: call void @llvm.assume(i1 [[LCMP_MOD1]])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 0333;334entry:335 br label %l3, !llvm.loop !1336 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, 1342 %exitcond = icmp eq i32 %inc, %n343 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1344 345exit:346 ret i32 0347}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 not352; 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]], 1361; 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 0366;367entry:368 br label %l3, !llvm.loop !1369 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, 1374 %exitcond = icmp eq i32 %inc, %n375 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1376 377exit:378 call void @f() [ "convergencectrl"(token %tok.loop) ]379 ret i32 0380}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]], 1392; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 4393; 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 0403;404entry:405 br label %l3406 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, 1411 %exitcond = icmp eq i32 %inc, 4412 br label %l2, !llvm.loop !1413 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 !1418 419latch:420 br i1 %exitcond, label %exit, label %l3421 422exit:423 call void @f() [ "convergencectrl"(token %tok.l2) ]424 ret i32 0425}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 0463;464entry:465 br label %l3466 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, 1471 %exitcond = icmp eq i32 %inc, 4472 br label %l2, !llvm.loop !1473 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 !1478 479latch:480 call void @f() [ "convergencectrl"(token %tok.l2) ]481 br i1 %exitcond, label %exit, label %l3482 483exit:484 ret i32 0485}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 0535;536entry:537 br label %l3538 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, 1543 %exitcond = icmp eq i32 %inc, 4544 br label %l2, !llvm.loop !1545 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 !1550 551latch:552 br i1 %exitcond, label %exit, label %l3553 554exit:555 ret i32 0556}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