blob: 8975665a9bf8ea9d579bef7ccf2c2f7e3c37047d [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 6
; RUN: opt -passes=loop-vectorize -force-vector-width=4 -S %s | FileCheck %s
declare i32 @cond()
; FIXME: ptrtoaddr(%bound) should only be expanded once; see the two
; ptrtoaddr instructions in the CHECK block below.
define i32 @ptrtoaddr_expanded_twice(ptr %bound, ptr %dst) {
; CHECK-LABEL: define i32 @ptrtoaddr_expanded_twice(
; CHECK-SAME: ptr [[BOUND:%.*]], ptr [[DST:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: [[BOUND1:%.*]] = ptrtoaddr ptr [[BOUND]] to i64
; CHECK-NEXT: br label %[[LOOP1:.*]]
; CHECK: [[LOOP1]]:
; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], %[[LOOP1_LATCH:.*]] ], [ 0, %[[ENTRY]] ]
; CHECK-NEXT: [[READ:%.*]] = phi ptr [ [[BOUND]], %[[ENTRY]] ], [ [[READ_NEXT:%.*]], %[[LOOP1_LATCH]] ]
; CHECK-NEXT: [[COND:%.*]] = call i32 @cond()
; CHECK-NEXT: [[COND_CMP:%.*]] = icmp eq i32 [[COND]], 0
; CHECK-NEXT: br i1 [[COND_CMP]], label %[[LOOP1_LATCH]], label %[[LOOP2_PREHEADER:.*]]
; CHECK: [[LOOP2_PREHEADER]]:
; CHECK-NEXT: [[READ_LCSSA:%.*]] = phi ptr [ [[READ]], %[[LOOP1]] ]
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 3, [[BOUND1]]
; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[INDVAR]], -4
; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[TMP2]], [[TMP1]]
; CHECK-NEXT: [[TMP15:%.*]] = ptrtoaddr ptr [[READ_LCSSA]] to i64
; CHECK-NEXT: [[TMP16:%.*]] = ptrtoaddr ptr [[BOUND]] to i64
; CHECK-NEXT: [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP16]], i64 [[TMP15]])
; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[UMAX]], [[TMP3]]
; CHECK-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP4]], 2
; CHECK-NEXT: [[TMP6:%.*]] = add nuw nsw i64 [[TMP5]], 1
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP6]], 4
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
; CHECK: [[VECTOR_PH]]:
; CHECK-NEXT: [[TMP7:%.*]] = and i64 [[TMP6]], 3
; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 0
; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], i64 4, i64 [[TMP7]]
; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP6]], [[TMP9]]
; CHECK-NEXT: [[TMP10:%.*]] = shl i64 [[N_VEC]], 2
; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i8, ptr [[READ_LCSSA]], i64 [[TMP10]]
; CHECK-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[DST]], i64 [[TMP10]]
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
; CHECK: [[VECTOR_BODY]]:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
; CHECK-NEXT: [[TMP13:%.*]] = shl i64 [[INDEX]], 2
; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[DST]], i64 [[TMP13]]
; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[NEXT_GEP]], align 4
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
; CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
; CHECK-NEXT: br i1 [[TMP14]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
; CHECK: [[MIDDLE_BLOCK]]:
; CHECK-NEXT: br label %[[SCALAR_PH]]
; CHECK: [[SCALAR_PH]]:
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[TMP11]], %[[MIDDLE_BLOCK]] ], [ [[READ_LCSSA]], %[[LOOP2_PREHEADER]] ]
; CHECK-NEXT: [[BC_RESUME_VAL2:%.*]] = phi ptr [ [[TMP12]], %[[MIDDLE_BLOCK]] ], [ [[DST]], %[[LOOP2_PREHEADER]] ]
; CHECK-NEXT: br label %[[LOOP2:.*]]
; CHECK: [[LOOP1_LATCH]]:
; CHECK-NEXT: [[READ_NEXT]] = getelementptr i8, ptr [[READ]], i64 4
; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1
; CHECK-NEXT: br label %[[LOOP1]]
; CHECK: [[LOOP2]]:
; CHECK-NEXT: [[SCAN:%.*]] = phi ptr [ [[SCAN_NEXT:%.*]], %[[LOOP2_LATCH:.*]] ], [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ]
; CHECK-NEXT: [[DST_IV:%.*]] = phi ptr [ [[DST_IV_NEXT:%.*]], %[[LOOP2_LATCH]] ], [ [[BC_RESUME_VAL2]], %[[SCALAR_PH]] ]
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ult ptr [[SCAN]], [[BOUND]]
; CHECK-NEXT: br i1 [[EXITCOND]], label %[[LOOP2_LATCH]], label %[[EXIT:.*]]
; CHECK: [[LOOP2_LATCH]]:
; CHECK-NEXT: [[SCAN_NEXT]] = getelementptr nusw i8, ptr [[SCAN]], i64 4
; CHECK-NEXT: [[DST_IV_NEXT]] = getelementptr i8, ptr [[DST_IV]], i64 4
; CHECK-NEXT: store i32 1, ptr [[DST_IV]], align 4
; CHECK-NEXT: br label %[[LOOP2]], !llvm.loop [[LOOP3:![0-9]+]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret i32 0
;
entry:
br label %loop1
loop1:
%read = phi ptr [ %bound, %entry ], [ %read.next, %loop1.latch ]
%cond = call i32 @cond()
%cond.cmp = icmp eq i32 %cond, 0
br i1 %cond.cmp, label %loop1.latch, label %loop2
loop1.latch:
%read.next = getelementptr i8, ptr %read, i64 4
br label %loop1
loop2:
%scan = phi ptr [ %scan.next, %loop2.latch ], [ %read, %loop1 ]
%dst.iv = phi ptr [ %dst.iv.next, %loop2.latch ], [ %dst, %loop1 ]
%exitcond = icmp ult ptr %scan, %bound
br i1 %exitcond, label %loop2.latch, label %exit
loop2.latch:
%scan.next = getelementptr nusw i8, ptr %scan, i64 4
%dst.iv.next = getelementptr i8, ptr %dst.iv, i64 4
store i32 1, ptr %dst.iv, align 4
br label %loop2
exit:
ret i32 0
}
; FIXME: the second loop's and/sub computing N_VEC should reuse the first
; loop's instead of recomputing it from scratch.
define void @sibling_loops_recompute_min_iters_check(ptr %dst, i64 %n) {
; CHECK-LABEL: define void @sibling_loops_recompute_min_iters_check(
; CHECK-SAME: ptr [[DST:%.*]], i64 [[N:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br label %[[OUTER:.*]]
; CHECK: [[OUTER]]:
; CHECK-NEXT: [[IV_OUTER:%.*]] = phi i64 [ [[IV_OUTER_NEXT:%.*]], %[[OUTER_LATCH:.*]] ], [ 0, %[[ENTRY]] ]
; CHECK-NEXT: [[TMP1:%.*]] = mul nsw i64 [[IV_OUTER]], -1
; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[IV_OUTER]], 1
; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 [[TMP0]])
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[SMAX]], [[TMP1]]
; CHECK-NEXT: [[MIN_ITERS_CHECK2:%.*]] = icmp ult i64 [[TMP2]], 4
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK2]], label %[[SCALAR_PH1:.*]], label %[[VECTOR_PH3:.*]]
; CHECK: [[VECTOR_PH3]]:
; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], 3
; CHECK-NEXT: [[N_VEC4:%.*]] = sub i64 [[TMP2]], [[TMP3]]
; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[IV_OUTER]], [[N_VEC4]]
; CHECK-NEXT: br label %[[VECTOR_BODY5:.*]]
; CHECK: [[VECTOR_BODY5]]:
; CHECK-NEXT: [[INDEX6:%.*]] = phi i64 [ 0, %[[VECTOR_PH3]] ], [ [[INDEX_NEXT7:%.*]], %[[VECTOR_BODY5]] ]
; CHECK-NEXT: [[TMP5:%.*]] = add nuw i64 [[IV_OUTER]], [[INDEX6]]
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr float, ptr [[DST]], i64 [[TMP5]]
; CHECK-NEXT: store <4 x float> splat (float 1.000000e+00), ptr [[TMP6]], align 4
; CHECK-NEXT: [[INDEX_NEXT7]] = add nuw i64 [[INDEX6]], 4
; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT7]], [[N_VEC4]]
; CHECK-NEXT: br i1 [[TMP7]], label %[[MIDDLE_BLOCK8:.*]], label %[[VECTOR_BODY5]], !llvm.loop [[LOOP4:![0-9]+]]
; CHECK: [[MIDDLE_BLOCK8]]:
; CHECK-NEXT: [[CMP_N9:%.*]] = icmp eq i64 [[TMP2]], [[N_VEC4]]
; CHECK-NEXT: br i1 [[CMP_N9]], label %[[INNER1_PREHEADER:.*]], label %[[SCALAR_PH1]]
; CHECK: [[SCALAR_PH1]]:
; CHECK-NEXT: [[BC_RESUME_VAL10:%.*]] = phi i64 [ [[TMP4]], %[[MIDDLE_BLOCK8]] ], [ [[IV_OUTER]], %[[OUTER]] ]
; CHECK-NEXT: br label %[[INNER0:.*]]
; CHECK: [[INNER0]]:
; CHECK-NEXT: [[IV0:%.*]] = phi i64 [ [[IV0_NEXT:%.*]], %[[INNER0]] ], [ [[BC_RESUME_VAL10]], %[[SCALAR_PH1]] ]
; CHECK-NEXT: [[P0:%.*]] = getelementptr float, ptr [[DST]], i64 [[IV0]]
; CHECK-NEXT: store float 1.000000e+00, ptr [[P0]], align 4
; CHECK-NEXT: [[IV0_NEXT]] = add nuw nsw i64 [[IV0]], 1
; CHECK-NEXT: [[CMP0:%.*]] = icmp slt i64 [[IV0_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[CMP0]], label %[[INNER0]], label %[[INNER1_PREHEADER]], !llvm.loop [[LOOP5:![0-9]+]]
; CHECK: [[INNER1_PREHEADER]]:
; CHECK-NEXT: [[TMP13:%.*]] = call i64 @llvm.smax.i64(i64 [[N]], i64 [[TMP0]])
; CHECK-NEXT: [[TMP14:%.*]] = add i64 [[TMP13]], [[TMP1]]
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP14]], 4
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
; CHECK: [[VECTOR_PH]]:
; CHECK-NEXT: [[TMP15:%.*]] = and i64 [[TMP14]], 3
; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP14]], [[TMP15]]
; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[IV_OUTER]], [[N_VEC]]
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
; CHECK: [[VECTOR_BODY]]:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
; CHECK-NEXT: [[TMP10:%.*]] = add nuw i64 [[IV_OUTER]], [[INDEX]]
; CHECK-NEXT: [[TMP11:%.*]] = getelementptr float, ptr [[DST]], i64 [[TMP10]]
; CHECK-NEXT: store <4 x float> splat (float 2.000000e+00), ptr [[TMP11]], align 4
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
; CHECK-NEXT: br i1 [[TMP12]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]
; CHECK: [[MIDDLE_BLOCK]]:
; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP14]], [[N_VEC]]
; CHECK-NEXT: br i1 [[CMP_N]], label %[[OUTER_LATCH]], label %[[SCALAR_PH]]
; CHECK: [[SCALAR_PH]]:
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP9]], %[[MIDDLE_BLOCK]] ], [ [[IV_OUTER]], %[[INNER1_PREHEADER]] ]
; CHECK-NEXT: br label %[[INNER1:.*]]
; CHECK: [[INNER1]]:
; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[IV1_NEXT:%.*]], %[[INNER1]] ], [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ]
; CHECK-NEXT: [[P1:%.*]] = getelementptr float, ptr [[DST]], i64 [[IV1]]
; CHECK-NEXT: store float 2.000000e+00, ptr [[P1]], align 4
; CHECK-NEXT: [[IV1_NEXT]] = add nuw nsw i64 [[IV1]], 1
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[IV1_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[CMP1]], label %[[INNER1]], label %[[OUTER_LATCH]], !llvm.loop [[LOOP7:![0-9]+]]
; CHECK: [[OUTER_LATCH]]:
; CHECK-NEXT: [[IV_OUTER_NEXT]] = add nuw nsw i64 [[IV_OUTER]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_OUTER_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[EXITCOND]], label %[[EXIT:.*]], label %[[OUTER]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %outer
outer:
%iv.outer = phi i64 [ %iv.outer.next, %outer.latch ], [ 0, %entry ]
br label %inner0
inner0:
%iv0 = phi i64 [ %iv0.next, %inner0 ], [ %iv.outer, %outer ]
%p0 = getelementptr float, ptr %dst, i64 %iv0
store float 1.000000e+00, ptr %p0, align 4
%iv0.next = add nuw nsw i64 %iv0, 1
%cmp0 = icmp slt i64 %iv0.next, %n
br i1 %cmp0, label %inner0, label %inner1
inner1:
%iv1 = phi i64 [ %iv1.next, %inner1 ], [ %iv.outer, %inner0 ]
%p1 = getelementptr float, ptr %dst, i64 %iv1
store float 2.000000e+00, ptr %p1, align 4
%iv1.next = add nuw nsw i64 %iv1, 1
%cmp1 = icmp slt i64 %iv1.next, %n
br i1 %cmp1, label %inner1, label %outer.latch
outer.latch:
%iv.outer.next = add nuw nsw i64 %iv.outer, 1
%exitcond = icmp eq i64 %iv.outer.next, %n
br i1 %exitcond, label %exit, label %outer
exit:
ret void
}
; FIXME: the umax/umin/sub expression computing the inner loop's trip count
; (which depends on the outer AddRec %i) is expanded three times over.
@arr = internal global [8193 x i8] zeroinitializer
define i32 @nested_loop_min_iters_check_expanded_repeatedly(i64 %n) {
; CHECK-LABEL: define i32 @nested_loop_min_iters_check_expanded_repeatedly(
; CHECK-SAME: i64 [[N:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br label %[[OUTER:.*]]
; CHECK: [[OUTER]]:
; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], %[[OUTER_LATCH:.*]] ], [ 0, %[[ENTRY]] ]
; CHECK-NEXT: [[COUNT:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[COUNT_NEXT:%.*]], %[[OUTER_LATCH]] ]
; CHECK-NEXT: [[I:%.*]] = phi i64 [ 2, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[OUTER_LATCH]] ]
; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[INDVAR]], -2
; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[TMP2]], -4
; CHECK-NEXT: [[OUTER_COND:%.*]] = icmp ne i64 [[I]], [[N]]
; CHECK-NEXT: br i1 [[OUTER_COND]], label %[[OUTER_BODY:.*]], label %[[EXIT:.*]]
; CHECK: [[OUTER_BODY]]:
; CHECK-NEXT: [[PTR_I:%.*]] = getelementptr inbounds nuw i8, ptr @arr, i64 [[I]]
; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[PTR_I]], align 1
; CHECK-NEXT: [[SKIP:%.*]] = icmp eq i8 [[TMP6]], 0
; CHECK-NEXT: br i1 [[SKIP]], label %[[OUTER_LATCH]], label %[[INNER_PH:.*]]
; CHECK: [[INNER_PH]]:
; CHECK-NEXT: [[K_START:%.*]] = shl nuw i64 [[I]], 1
; CHECK-NEXT: [[TMP28:%.*]] = call i64 @llvm.umax.i64(i64 [[N]], i64 [[K_START]])
; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[TMP28]], [[TMP3]]
; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP4]], i64 1)
; CHECK-NEXT: [[TMP29:%.*]] = add i64 [[TMP28]], [[TMP3]]
; CHECK-NEXT: [[TMP30:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP29]], i64 1)
; CHECK-NEXT: [[TMP31:%.*]] = add i64 [[TMP28]], [[TMP3]]
; CHECK-NEXT: [[TMP5:%.*]] = sub i64 [[TMP31]], [[TMP30]]
; CHECK-NEXT: [[TMP8:%.*]] = udiv i64 [[TMP5]], [[I]]
; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[TMP7]], [[TMP8]]
; CHECK-NEXT: [[TMP32:%.*]] = add i64 [[TMP9]], 1
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP32]], 4
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
; CHECK: [[VECTOR_PH]]:
; CHECK-NEXT: [[TMP10:%.*]] = and i64 [[TMP32]], 3
; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], 0
; CHECK-NEXT: [[TMP12:%.*]] = select i1 [[TMP11]], i64 4, i64 [[TMP10]]
; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP32]], [[TMP12]]
; CHECK-NEXT: [[TMP13:%.*]] = mul i64 [[N_VEC]], [[I]]
; CHECK-NEXT: [[TMP14:%.*]] = add i64 [[K_START]], [[TMP13]]
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
; CHECK: [[VECTOR_BODY]]:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
; CHECK-NEXT: [[TMP15:%.*]] = mul i64 [[INDEX]], [[I]]
; CHECK-NEXT: [[TMP16:%.*]] = add i64 [[K_START]], [[TMP15]]
; CHECK-NEXT: [[TMP17:%.*]] = mul i64 1, [[I]]
; CHECK-NEXT: [[TMP18:%.*]] = add i64 [[TMP16]], [[TMP17]]
; CHECK-NEXT: [[TMP19:%.*]] = mul i64 2, [[I]]
; CHECK-NEXT: [[TMP20:%.*]] = add i64 [[TMP16]], [[TMP19]]
; CHECK-NEXT: [[TMP21:%.*]] = mul i64 3, [[I]]
; CHECK-NEXT: [[TMP22:%.*]] = add i64 [[TMP16]], [[TMP21]]
; CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw i8, ptr @arr, i64 [[TMP16]]
; CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds nuw i8, ptr @arr, i64 [[TMP18]]
; CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds nuw i8, ptr @arr, i64 [[TMP20]]
; CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds nuw i8, ptr @arr, i64 [[TMP22]]
; CHECK-NEXT: store i8 0, ptr [[TMP23]], align 1
; CHECK-NEXT: store i8 0, ptr [[TMP24]], align 1
; CHECK-NEXT: store i8 0, ptr [[TMP25]], align 1
; CHECK-NEXT: store i8 0, ptr [[TMP26]], align 1
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
; CHECK-NEXT: [[TMP27:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
; CHECK-NEXT: br i1 [[TMP27]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]]
; CHECK: [[MIDDLE_BLOCK]]:
; CHECK-NEXT: br label %[[SCALAR_PH]]
; CHECK: [[SCALAR_PH]]:
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP14]], %[[MIDDLE_BLOCK]] ], [ [[K_START]], %[[INNER_PH]] ]
; CHECK-NEXT: br label %[[INNER:.*]]
; CHECK: [[INNER]]:
; CHECK-NEXT: [[K:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[K_NEXT:%.*]], %[[INNER_BODY:.*]] ]
; CHECK-NEXT: [[INNER_COND:%.*]] = icmp samesign ult i64 [[K]], [[N]]
; CHECK-NEXT: br i1 [[INNER_COND]], label %[[INNER_BODY]], label %[[INNER_EXIT:.*]]
; CHECK: [[INNER_BODY]]:
; CHECK-NEXT: [[PTR_K:%.*]] = getelementptr inbounds nuw i8, ptr @arr, i64 [[K]]
; CHECK-NEXT: store i8 0, ptr [[PTR_K]], align 1
; CHECK-NEXT: [[K_NEXT]] = add nuw nsw i64 [[K]], [[I]]
; CHECK-NEXT: br label %[[INNER]], !llvm.loop [[LOOP9:![0-9]+]]
; CHECK: [[INNER_EXIT]]:
; CHECK-NEXT: [[COUNT_INC:%.*]] = add nsw i32 [[COUNT]], 1
; CHECK-NEXT: br label %[[OUTER_LATCH]]
; CHECK: [[OUTER_LATCH]]:
; CHECK-NEXT: [[COUNT_NEXT]] = phi i32 [ [[COUNT_INC]], %[[INNER_EXIT]] ], [ [[COUNT]], %[[OUTER_BODY]] ]
; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i64 [[I]], 1
; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1
; CHECK-NEXT: br label %[[OUTER]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: [[COUNT_LCSSA:%.*]] = phi i32 [ [[COUNT]], %[[OUTER]] ]
; CHECK-NEXT: ret i32 [[COUNT_LCSSA]]
;
entry:
br label %outer
outer:
%count = phi i32 [ 0, %entry ], [ %count.next, %outer.latch ]
%i = phi i64 [ 2, %entry ], [ %i.next, %outer.latch ]
%outer.cond = icmp ne i64 %i, %n
br i1 %outer.cond, label %outer.body, label %exit
outer.body:
%ptr.i = getelementptr inbounds nuw i8, ptr @arr, i64 %i
%0 = load i8, ptr %ptr.i, align 1
%skip = icmp eq i8 %0, 0
br i1 %skip, label %outer.latch, label %inner.ph
inner.ph:
%k.start = shl nuw nsw i64 %i, 1
br label %inner
inner:
%k = phi i64 [ %k.start, %inner.ph ], [ %k.next, %inner.body ]
%inner.cond = icmp samesign ult i64 %k, %n
br i1 %inner.cond, label %inner.body, label %inner.exit
inner.body:
%ptr.k = getelementptr inbounds nuw i8, ptr @arr, i64 %k
store i8 0, ptr %ptr.k, align 1
%k.next = add nuw nsw i64 %k, %i
br label %inner
inner.exit:
%count.inc = add nsw i32 %count, 1
br label %outer.latch
outer.latch:
%count.next = phi i32 [ %count.inc, %inner.exit ], [ %count, %outer.body ]
%i.next = add nuw nsw i64 %i, 1
br label %outer
exit:
%count.lcssa = phi i32 [ %count, %outer ]
ret i32 %count.lcssa
}