1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=loop-unroll -unroll-count=2 -S | FileCheck %s 3 4; LoopUnroll should unroll this loop into one big basic block. 5define void @latch_exit(ptr nocapture %p, i64 %n) nounwind { 6; CHECK-LABEL: @latch_exit( 7; CHECK-NEXT: entry: 8; CHECK-NEXT: [[MUL10:%.*]] = shl i64 [[N:%.*]], 1 9; CHECK-NEXT: br label [[FOR_BODY:%.*]] 10; CHECK: for.body: 11; CHECK-NEXT: [[I_013:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[TMP16_1:%.*]], [[FOR_BODY]] ] 12; CHECK-NEXT: [[ARRAYIDX7:%.*]] = getelementptr double, ptr [[P:%.*]], i64 [[I_013]] 13; CHECK-NEXT: [[TMP16:%.*]] = add nuw nsw i64 [[I_013]], 1 14; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr double, ptr [[P]], i64 [[TMP16]] 15; CHECK-NEXT: [[TMP4:%.*]] = load double, ptr [[ARRAYIDX]], align 8 16; CHECK-NEXT: [[TMP8:%.*]] = load double, ptr [[ARRAYIDX7]], align 8 17; CHECK-NEXT: [[MUL9:%.*]] = fmul double [[TMP8]], [[TMP4]] 18; CHECK-NEXT: store double [[MUL9]], ptr [[ARRAYIDX7]], align 8 19; CHECK-NEXT: [[ARRAYIDX7_1:%.*]] = getelementptr double, ptr [[P]], i64 [[TMP16]] 20; CHECK-NEXT: [[TMP16_1]] = add i64 [[I_013]], 2 21; CHECK-NEXT: [[ARRAYIDX_1:%.*]] = getelementptr double, ptr [[P]], i64 [[TMP16_1]] 22; CHECK-NEXT: [[TMP4_1:%.*]] = load double, ptr [[ARRAYIDX_1]], align 8 23; CHECK-NEXT: [[MUL9_1:%.*]] = fmul double [[TMP4]], [[TMP4_1]] 24; CHECK-NEXT: store double [[MUL9_1]], ptr [[ARRAYIDX7_1]], align 8 25; CHECK-NEXT: [[EXITCOND_1:%.*]] = icmp eq i64 [[TMP16_1]], [[MUL10]] 26; CHECK-NEXT: br i1 [[EXITCOND_1]], label [[FOR_END:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] 27; CHECK: for.end: 28; CHECK-NEXT: ret void 29; 30entry: 31 %mul10 = shl i64 %n, 1 32 br label %for.body 33 34for.body: 35 %i.013 = phi i64 [ %tmp16, %for.body ], [ 0, %entry ] 36 %arrayidx7 = getelementptr double, ptr %p, i64 %i.013 37 %tmp16 = add i64 %i.013, 1 38 %arrayidx = getelementptr double, ptr %p, i64 %tmp16 39 %tmp4 = load double, ptr %arrayidx 40 %tmp8 = load double, ptr %arrayidx7 41 %mul9 = fmul double %tmp8, %tmp4 42 store double %mul9, ptr %arrayidx7 43 %exitcond = icmp eq i64 %tmp16, %mul10 44 br i1 %exitcond, label %for.end, label %for.body 45 46for.end: 47 ret void 48} 49 50; Same as previous test case, but with a non-latch exit. There shouldn't 51; be a conditional branch after the first block. 52define void @non_latch_exit(ptr nocapture %p, i64 %n) nounwind { 53; CHECK-LABEL: @non_latch_exit( 54; CHECK-NEXT: entry: 55; CHECK-NEXT: [[MUL10:%.*]] = shl i64 [[N:%.*]], 1 56; CHECK-NEXT: br label [[FOR_BODY:%.*]] 57; CHECK: for.body: 58; CHECK-NEXT: [[I_013:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[TMP16_1:%.*]], [[LATCH_1:%.*]] ] 59; CHECK-NEXT: [[ARRAYIDX7:%.*]] = getelementptr double, ptr [[P:%.*]], i64 [[I_013]] 60; CHECK-NEXT: [[TMP16:%.*]] = add nuw nsw i64 [[I_013]], 1 61; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr double, ptr [[P]], i64 [[TMP16]] 62; CHECK-NEXT: [[TMP4:%.*]] = load double, ptr [[ARRAYIDX]], align 8 63; CHECK-NEXT: [[TMP8:%.*]] = load double, ptr [[ARRAYIDX7]], align 8 64; CHECK-NEXT: [[MUL9:%.*]] = fmul double [[TMP8]], [[TMP4]] 65; CHECK-NEXT: store double [[MUL9]], ptr [[ARRAYIDX7]], align 8 66; CHECK-NEXT: br label [[LATCH:%.*]] 67; CHECK: latch: 68; CHECK-NEXT: [[ARRAYIDX7_1:%.*]] = getelementptr double, ptr [[P]], i64 [[TMP16]] 69; CHECK-NEXT: [[TMP16_1]] = add i64 [[I_013]], 2 70; CHECK-NEXT: [[ARRAYIDX_1:%.*]] = getelementptr double, ptr [[P]], i64 [[TMP16_1]] 71; CHECK-NEXT: [[TMP4_1:%.*]] = load double, ptr [[ARRAYIDX_1]], align 8 72; CHECK-NEXT: [[MUL9_1:%.*]] = fmul double [[TMP4]], [[TMP4_1]] 73; CHECK-NEXT: store double [[MUL9_1]], ptr [[ARRAYIDX7_1]], align 8 74; CHECK-NEXT: [[EXITCOND_1:%.*]] = icmp eq i64 [[TMP16_1]], [[MUL10]] 75; CHECK-NEXT: br i1 [[EXITCOND_1]], label [[FOR_END:%.*]], label [[LATCH_1]] 76; CHECK: latch.1: 77; CHECK-NEXT: br label [[FOR_BODY]], !llvm.loop [[LOOP2:![0-9]+]] 78; CHECK: for.end: 79; CHECK-NEXT: ret void 80; 81entry: 82 %mul10 = shl i64 %n, 1 83 br label %for.body 84 85for.body: 86 %i.013 = phi i64 [ %tmp16, %latch ], [ 0, %entry ] 87 %arrayidx7 = getelementptr double, ptr %p, i64 %i.013 88 %tmp16 = add i64 %i.013, 1 89 %arrayidx = getelementptr double, ptr %p, i64 %tmp16 90 %tmp4 = load double, ptr %arrayidx 91 %tmp8 = load double, ptr %arrayidx7 92 %mul9 = fmul double %tmp8, %tmp4 93 store double %mul9, ptr %arrayidx7 94 %exitcond = icmp eq i64 %tmp16, %mul10 95 br i1 %exitcond, label %for.end, label %latch 96 97latch: 98 br label %for.body 99 100for.end: 101 ret void 102} 103