blob: 35345d17391f67bebbe259e64d1d3df1702daf1d [file]
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --filter-out-after "vector.body:" --version 6
; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -disable-output -vplan-print-after="printFinalVPlan" %s 2>&1 | FileCheck %s
define void @three_groups_shared_bounds(ptr %a, ptr %b, ptr %c, i64 %n) {
; CHECK-LABEL: VPlan for loop in 'three_groups_shared_bounds'
; CHECK: VPlan 'Final VPlan for VF={4},UF={1}' {
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<entry>:
; CHECK-NEXT: EMIT-SCALAR vp<[[VP2:%[0-9]+]]> = call i64 @llvm.umax(ir<%n>, ir<1>)
; CHECK-NEXT: EMIT vp<%min.iters.check> = icmp ult vp<[[VP2]]>, ir<4>
; CHECK-NEXT: EMIT branch-on-cond vp<%min.iters.check>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, vector.memcheck
; CHECK-EMPTY:
; CHECK-NEXT: vector.memcheck:
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = shl vp<[[VP2]]>, ir<2>
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = ptradd ir<%c>, vp<[[VP4]]>
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = ptradd ir<%a>, vp<[[VP4]]>
; CHECK-NEXT: EMIT vp<[[VP7:%[0-9]+]]> = ptradd ir<%b>, vp<[[VP4]]>
; CHECK-NEXT: EMIT vp<%bound0> = icmp ult ir<%c>, vp<[[VP6]]>
; CHECK-NEXT: EMIT vp<%bound1> = icmp ult ir<%a>, vp<[[VP5]]>
; CHECK-NEXT: EMIT vp<%found.conflict> = and vp<%bound0>, vp<%bound1>
; CHECK-NEXT: EMIT vp<%bound0>.1 = icmp ult ir<%c>, vp<[[VP7]]>
; CHECK-NEXT: EMIT vp<%bound1>.1 = icmp ult ir<%b>, vp<[[VP5]]>
; CHECK-NEXT: EMIT vp<%found.conflict>.1 = and vp<%bound0>.1, vp<%bound1>.1
; CHECK-NEXT: EMIT vp<%conflict.rdx> = or vp<%found.conflict>, vp<%found.conflict>.1
; CHECK-NEXT: EMIT vp<%bound0>.2 = icmp ult ir<%a>, vp<[[VP7]]>
; CHECK-NEXT: EMIT vp<%bound1>.2 = icmp ult ir<%b>, vp<[[VP6]]>
; CHECK-NEXT: EMIT vp<%found.conflict>.2 = and vp<%bound0>.2, vp<%bound1>.2
; CHECK-NEXT: EMIT vp<%conflict.rdx>.1 = or vp<%conflict.rdx>, vp<%found.conflict>.2
; CHECK-NEXT: EMIT branch-on-cond vp<%conflict.rdx>.1
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, vector.ph
; CHECK-EMPTY:
; CHECK-NEXT: vector.ph:
; CHECK-NEXT: EMIT vp<[[VP9:%[0-9]+]]> = and vp<[[VP2]]>, ir<3>
; CHECK-NEXT: EMIT vp<%n.vec> = sub vp<[[VP2]]>, vp<[[VP9]]>
; CHECK-NEXT: Successor(s): vector.body
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%gep.a.read = getelementptr inbounds i32, ptr %a, i64 %iv
%load.a = load i32, ptr %gep.a.read, align 4
%gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
%load.b = load i32, ptr %gep.b, align 4
%sum = add i32 %load.a, %load.b
%gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
store i32 %sum, ptr %gep.c, align 4
store i32 %load.b, ptr %gep.a.read, align 4
%iv.next = add nuw nsw i64 %iv, 1
%cmp = icmp ult i64 %iv.next, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
define void @ptr_minmax_bounds(ptr %a, ptr %b, i64 %n, i64 %s, i64 %t) {
; CHECK-LABEL: VPlan for loop in 'ptr_minmax_bounds'
; CHECK: VPlan 'Final VPlan for VF={4},UF={1}' {
; CHECK-NEXT: Live-in ir<%n> = original trip-count
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<entry>:
; CHECK-NEXT: IR %step = mul i64 %s, %t
; CHECK-NEXT: EMIT vp<%min.iters.check> = icmp ult ir<%n>, ir<4>
; CHECK-NEXT: EMIT branch-on-cond vp<%min.iters.check>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, vector.memcheck
; CHECK-EMPTY:
; CHECK-NEXT: vector.memcheck:
; CHECK-NEXT: EMIT vp<[[VP3:%[0-9]+]]> = shl ir<%n>, ir<2>
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = ptradd ir<%b>, vp<[[VP3]]>
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = add ir<%n>, ir<-1>
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = mul ir<%t>, ir<%s>
; CHECK-NEXT: EMIT vp<[[VP7:%[0-9]+]]> = mul vp<[[VP6]]>, vp<[[VP5]]>
; CHECK-NEXT: EMIT vp<[[VP8:%[0-9]+]]> = shl vp<[[VP7]]>, ir<2>
; CHECK-NEXT: EMIT vp<[[VP9:%[0-9]+]]> = ptradd ir<%a>, vp<[[VP8]]>
; CHECK-NEXT: EMIT vp<[[VP10:%[0-9]+]]> = icmp ult ir<%a>, vp<[[VP9]]>
; CHECK-NEXT: EMIT vp<[[VP11:%[0-9]+]]> = select vp<[[VP10]]>, ir<%a>, vp<[[VP9]]>
; CHECK-NEXT: EMIT vp<[[VP12:%[0-9]+]]> = icmp ugt ir<%a>, vp<[[VP9]]>
; CHECK-NEXT: EMIT vp<[[VP13:%[0-9]+]]> = select vp<[[VP12]]>, ir<%a>, vp<[[VP9]]>
; CHECK-NEXT: EMIT vp<[[VP14:%[0-9]+]]> = ptradd vp<[[VP13]]>, ir<4>
; CHECK-NEXT: EMIT vp<%bound0> = icmp ult ir<%b>, vp<[[VP14]]>
; CHECK-NEXT: EMIT vp<%bound1> = icmp ult vp<[[VP11]]>, vp<[[VP4]]>
; CHECK-NEXT: EMIT vp<%found.conflict> = and vp<%bound0>, vp<%bound1>
; CHECK-NEXT: EMIT branch-on-cond vp<%found.conflict>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, vector.ph
; CHECK-EMPTY:
; CHECK-NEXT: vector.ph:
; CHECK-NEXT: EMIT vp<[[VP16:%[0-9]+]]> = and ir<%n>, ir<3>
; CHECK-NEXT: EMIT vp<%n.vec> = sub ir<%n>, vp<[[VP16]]>
; CHECK-NEXT: EMIT vp<[[VP17:%[0-9]+]]> = broadcast ir<%step>
; CHECK-NEXT: EMIT vp<[[VP18:%[0-9]+]]> = step-vector i64
; CHECK-NEXT: EMIT vp<[[VP19:%[0-9]+]]> = broadcast ir<4>
; CHECK-NEXT: Successor(s): vector.body
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
;
entry:
%step = mul i64 %s, %t
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%idx = mul i64 %iv, %step
%gep.a = getelementptr inbounds i32, ptr %a, i64 %idx
%l = load i32, ptr %gep.a, align 4
%gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
store i32 %l, ptr %gep.b, align 4
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
define void @diff_check(ptr %a, ptr %b, ptr %c, i64 %n) {
; CHECK-LABEL: VPlan for loop in 'diff_check'
; CHECK: VPlan 'Final VPlan for VF={4},UF={1}' {
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<entry>:
; CHECK-NEXT: IR %b7 = ptrtoaddr ptr %b to i64
; CHECK-NEXT: IR %a6 = ptrtoaddr ptr %a to i64
; CHECK-NEXT: IR %c5 = ptrtoaddr ptr %c to i64
; CHECK-NEXT: EMIT-SCALAR vp<[[VP2:%[0-9]+]]> = call i64 @llvm.umax(ir<%n>, ir<1>)
; CHECK-NEXT: EMIT vp<%min.iters.check> = icmp ult vp<[[VP2]]>, ir<4>
; CHECK-NEXT: EMIT branch-on-cond vp<%min.iters.check>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, vector.memcheck
; CHECK-EMPTY:
; CHECK-NEXT: vector.memcheck:
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = sub ir<%c5>, ir<%a6>
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = sub vp<[[VP4]]>, ir<1>
; CHECK-NEXT: EMIT vp<%diff.check> = icmp ult vp<[[VP5]]>, ir<15>
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = sub ir<%c5>, ir<%b7>
; CHECK-NEXT: EMIT vp<[[VP7:%[0-9]+]]> = sub vp<[[VP6]]>, ir<1>
; CHECK-NEXT: EMIT vp<%diff.check>.1 = icmp ult vp<[[VP7]]>, ir<15>
; CHECK-NEXT: EMIT vp<%conflict.rdx> = or vp<%diff.check>, vp<%diff.check>.1
; CHECK-NEXT: EMIT branch-on-cond vp<%conflict.rdx>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, vector.ph
; CHECK-EMPTY:
; CHECK-NEXT: vector.ph:
; CHECK-NEXT: EMIT vp<[[VP9:%[0-9]+]]> = and vp<[[VP2]]>, ir<3>
; CHECK-NEXT: EMIT vp<%n.vec> = sub vp<[[VP2]]>, vp<[[VP9]]>
; CHECK-NEXT: Successor(s): vector.body
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%gep.a = getelementptr inbounds i32, ptr %a, i64 %iv
%load.a = load i32, ptr %gep.a, align 4
%gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
%load.b = load i32, ptr %gep.b, align 4
%sum = add i32 %load.a, %load.b
%gep.c = getelementptr inbounds i32, ptr %c, i64 %iv
store i32 %sum, ptr %gep.c, align 4
%iv.next = add nuw nsw i64 %iv, 1
%cmp = icmp ult i64 %iv.next, %n
br i1 %cmp, label %loop, label %exit
exit:
ret void
}
; One of the bounds of the runtime check is an AddRec of the preceding
; sibling loop.
define void @bound_is_addrec_of_sibling_loop(ptr %a, ptr %b, i64 %n, i64 %d, i1 %cond) {
; CHECK-LABEL: VPlan for loop in 'bound_is_addrec_of_sibling_loop'
; CHECK: VPlan 'Final VPlan for VF={4},UF={1}' {
; CHECK-NEXT: Live-in ir<%n> = original trip-count
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<ph.2>:
; CHECK-NEXT: IR %iv.1.lcssa = phi i64 [ %iv.1, %loop.1 ]
; CHECK-NEXT: EMIT vp<%min.iters.check> = icmp ult ir<%n>, ir<4>
; CHECK-NEXT: EMIT branch-on-cond vp<%min.iters.check>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, ir-bb<vector.scevcheck>
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<vector.scevcheck>:
; CHECK-NEXT: IR %0 = add i64 %n, -1
; CHECK-NEXT: IR %mul = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 8, i64 %0)
; CHECK-NEXT: IR %mul.result = extractvalue { i64, i1 } %mul, 0
; CHECK-NEXT: IR %mul.overflow = extractvalue { i64, i1 } %mul, 1
; CHECK-NEXT: IR %1 = getelementptr i8, ptr %a, i64 %mul.result
; CHECK-NEXT: IR %2 = icmp ult ptr %1, %a
; CHECK-NEXT: IR %3 = or i1 %2, %mul.overflow
; CHECK-NEXT: EMIT branch-on-cond ir<%3>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, ir-bb<vector.memcheck>
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<vector.memcheck>:
; CHECK-NEXT: IR %4 = udiv i64 %n, %d
; CHECK-NEXT: IR %5 = shl i64 %4, 2
; CHECK-NEXT: IR %6 = shl i64 %iv.1, 2
; CHECK-NEXT: IR %7 = add i64 %6, %5
; CHECK-NEXT: IR %scevgep = getelementptr i8, ptr %b, i64 %7
; CHECK-NEXT: IR %8 = shl i64 %n, 2
; CHECK-NEXT: IR %9 = add i64 %8, %5
; CHECK-NEXT: IR %10 = add i64 %6, %9
; CHECK-NEXT: IR %scevgep1 = getelementptr i8, ptr %b, i64 %10
; CHECK-NEXT: IR %11 = shl i64 %n, 3
; CHECK-NEXT: IR %12 = add i64 %11, -4
; CHECK-NEXT: IR %scevgep2 = getelementptr i8, ptr %a, i64 %12
; CHECK-NEXT: IR %bound0 = icmp ult ptr %scevgep, %scevgep2
; CHECK-NEXT: IR %bound1 = icmp ult ptr %a, %scevgep1
; CHECK-NEXT: IR %found.conflict = and i1 %bound0, %bound1
; CHECK-NEXT: EMIT branch-on-cond ir<%found.conflict>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, vector.ph
; CHECK-EMPTY:
; CHECK-NEXT: vector.ph:
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = and ir<%n>, ir<3>
; CHECK-NEXT: EMIT vp<%n.vec> = sub ir<%n>, vp<[[VP5]]>
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = broadcast ir<%d>
; CHECK-NEXT: EMIT vp<[[VP7:%[0-9]+]]> = broadcast ir<%n>
; CHECK-NEXT: EMIT vp<[[VP8:%[0-9]+]]> = broadcast ir<%cond>
; CHECK-NEXT: WIDEN-INTRINSIC vp<[[VP9:%[0-9]+]]> = call llvm.masked.udiv(vp<[[VP7]]>, vp<[[VP6]]>, vp<[[VP8]]>)
; CHECK-NEXT: EMIT vp<[[VP10:%[0-9]+]]> = broadcast ir<%iv.1.lcssa>
; CHECK-NEXT: EMIT vp<[[VP11:%[0-9]+]]> = step-vector i64
; CHECK-NEXT: EMIT vp<[[VP12:%[0-9]+]]> = broadcast ir<4>
; CHECK-NEXT: Successor(s): vector.body
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
;
entry:
br label %loop.1
loop.1:
%iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop.1 ]
call void @use(i64 %iv.1)
%iv.1.next = add nuw nsw i64 %iv.1, 1
%ec.1 = icmp eq i64 %iv.1.next, %n
br i1 %ec.1, label %ph.2, label %loop.1
ph.2:
br label %loop.2
loop.2:
%iv.2 = phi i64 [ 0, %ph.2 ], [ %iv.2.next, %latch ]
br i1 %cond, label %then, label %latch
then:
%q = udiv i64 %n, %d
%idx.a = shl nuw nsw i64 %iv.2, 1
%gep.a = getelementptr inbounds i32, ptr %a, i64 %idx.a
%l = load i32, ptr %gep.a, align 4
%off = add nuw nsw i64 %iv.2, %iv.1
%idx.b = add nuw nsw i64 %off, %q
%gep.b = getelementptr inbounds i32, ptr %b, i64 %idx.b
store i32 %l, ptr %gep.b, align 4
br label %latch
latch:
%iv.2.next = add nuw nsw i64 %iv.2, 1
%ec.2 = icmp eq i64 %iv.2.next, %n
br i1 %ec.2, label %exit, label %loop.2
exit:
ret void
}
define void @bound_is_addrec_of_sibling_loop_non_unit_step(ptr %a, ptr %b, i64 %n, i64 %m) {
; CHECK-LABEL: VPlan for loop in 'bound_is_addrec_of_sibling_loop_non_unit_step'
; CHECK: VPlan 'Final VPlan for VF={4},UF={1}' {
; CHECK-NEXT: Live-in ir<%n> = original trip-count
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<ph.2>:
; CHECK-NEXT: IR %iv.1.lcssa = phi i64 [ %iv.1, %loop.1 ]
; CHECK-NEXT: EMIT vp<%min.iters.check> = icmp ult ir<%n>, ir<4>
; CHECK-NEXT: EMIT branch-on-cond vp<%min.iters.check>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, ir-bb<vector.memcheck>
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<vector.memcheck>:
; CHECK-NEXT: IR %0 = mul i64 %indvar, 12
; CHECK-NEXT: IR %1 = add i64 %0, 20
; CHECK-NEXT: IR %scevgep = getelementptr i8, ptr %b, i64 %1
; CHECK-NEXT: IR %2 = shl i64 %n, 2
; CHECK-NEXT: IR %3 = add i64 %2, 20
; CHECK-NEXT: IR %4 = add i64 %0, %3
; CHECK-NEXT: IR %scevgep1 = getelementptr i8, ptr %b, i64 %4
; CHECK-NEXT: IR %5 = shl i64 %n, 3
; CHECK-NEXT: IR %6 = add i64 %5, -4
; CHECK-NEXT: IR %scevgep2 = getelementptr i8, ptr %a, i64 %6
; CHECK-NEXT: IR %bound0 = icmp ult ptr %scevgep, %scevgep2
; CHECK-NEXT: IR %bound1 = icmp ult ptr %a, %scevgep1
; CHECK-NEXT: IR %found.conflict = and i1 %bound0, %bound1
; CHECK-NEXT: EMIT branch-on-cond ir<%found.conflict>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, vector.ph
; CHECK-EMPTY:
; CHECK-NEXT: vector.ph:
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = and ir<%n>, ir<3>
; CHECK-NEXT: EMIT vp<%n.vec> = sub ir<%n>, vp<[[VP4]]>
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = step-vector i64
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = broadcast ir<4>
; CHECK-NEXT: Successor(s): vector.body
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
;
entry:
br label %loop.1
loop.1:
%iv.1 = phi i64 [ 5, %entry ], [ %iv.1.next, %loop.1 ]
call void @use(i64 %iv.1)
%iv.1.next = add nuw nsw i64 %iv.1, 3
%ec.1 = icmp ugt i64 %iv.1, %m
br i1 %ec.1, label %ph.2, label %loop.1
ph.2:
br label %loop.2
loop.2:
%iv.2 = phi i64 [ 0, %ph.2 ], [ %iv.2.next, %loop.2 ]
%idx.a = shl nuw nsw i64 %iv.2, 1
%gep.a = getelementptr inbounds i32, ptr %a, i64 %idx.a
%l = load i32, ptr %gep.a, align 4
%idx.b = add nuw nsw i64 %iv.2, %iv.1
%gep.b = getelementptr inbounds i32, ptr %b, i64 %idx.b
store i32 %l, ptr %gep.b, align 4
%iv.2.next = add nuw nsw i64 %iv.2, 1
%ec.2 = icmp eq i64 %iv.2.next, %n
br i1 %ec.2, label %exit, label %loop.2
exit:
ret void
}
define void @bound_is_ptr_iv_of_sibling_loop(ptr %a, ptr %b, i64 %n, i64 %m) {
; CHECK-LABEL: VPlan for loop in 'bound_is_ptr_iv_of_sibling_loop'
; CHECK: VPlan 'Final VPlan for VF={4},UF={1}' {
; CHECK-NEXT: Live-in ir<%n> = original trip-count
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<ph.2>:
; CHECK-NEXT: IR %ptr.iv.lcssa = phi ptr [ %ptr.iv, %loop.1 ]
; CHECK-NEXT: EMIT vp<%min.iters.check> = icmp ult ir<%n>, ir<4>
; CHECK-NEXT: EMIT branch-on-cond vp<%min.iters.check>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, ir-bb<vector.memcheck>
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<vector.memcheck>:
; CHECK-NEXT: IR %0 = shl i64 %n, 2
; CHECK-NEXT: IR %1 = sub i64 0, %b1
; CHECK-NEXT: IR %2 = ptrtoaddr ptr %ptr.iv.lcssa to i64
; CHECK-NEXT: IR %3 = add i64 %2, %1
; CHECK-NEXT: IR %4 = add i64 %0, %3
; CHECK-NEXT: IR %scevgep = getelementptr i8, ptr %b, i64 %4
; CHECK-NEXT: IR %5 = shl i64 %n, 3
; CHECK-NEXT: IR %6 = add i64 %5, -4
; CHECK-NEXT: IR %scevgep2 = getelementptr i8, ptr %a, i64 %6
; CHECK-NEXT: IR %bound0 = icmp ult ptr %ptr.iv.lcssa, %scevgep2
; CHECK-NEXT: IR %bound1 = icmp ult ptr %a, %scevgep
; CHECK-NEXT: IR %found.conflict = and i1 %bound0, %bound1
; CHECK-NEXT: EMIT branch-on-cond ir<%found.conflict>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, vector.ph
; CHECK-EMPTY:
; CHECK-NEXT: vector.ph:
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = and ir<%n>, ir<3>
; CHECK-NEXT: EMIT vp<%n.vec> = sub ir<%n>, vp<[[VP4]]>
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = step-vector i64
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = broadcast ir<4>
; CHECK-NEXT: Successor(s): vector.body
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
;
entry:
br label %loop.1
loop.1:
%ptr.iv = phi ptr [ %b, %entry ], [ %ptr.iv.next, %loop.1 ]
%iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop.1 ]
call void @use(i64 %iv.1)
%ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i64 12
%iv.1.next = add nuw i64 %iv.1, 1
%ec.1 = icmp ugt i64 %iv.1, %m
br i1 %ec.1, label %ph.2, label %loop.1
ph.2:
br label %loop.2
loop.2:
%iv.2 = phi i64 [ 0, %ph.2 ], [ %iv.2.next, %loop.2 ]
%idx.a = shl nuw nsw i64 %iv.2, 1
%gep.a = getelementptr inbounds i32, ptr %a, i64 %idx.a
%l = load i32, ptr %gep.a, align 4
%gep.b = getelementptr inbounds i32, ptr %ptr.iv, i64 %iv.2
store i32 %l, ptr %gep.b, align 4
%iv.2.next = add nuw nsw i64 %iv.2, 1
%ec.2 = icmp eq i64 %iv.2.next, %n
br i1 %ec.2, label %exit, label %loop.2
exit:
ret void
}
define void @diff_check_dedup(ptr %dst, i64 %off, i64 %n) {
;
; CHECK-LABEL: VPlan for loop in 'diff_check_dedup'
; CHECK: VPlan 'Final VPlan for VF={4},UF={1}' {
; CHECK-NEXT: Live-in ir<%n> = original trip-count
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<entry>:
; CHECK-NEXT: IR %off.mul.2 = shl i64 %off, 1
; CHECK-NEXT: IR %off.mul.3 = mul i64 %off, 3
; CHECK-NEXT: EMIT vp<%min.iters.check> = icmp ult ir<%n>, ir<4>
; CHECK-NEXT: EMIT branch-on-cond vp<%min.iters.check>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, vector.memcheck
; CHECK-EMPTY:
; CHECK-NEXT: vector.memcheck:
; CHECK-NEXT: EMIT vp<[[VP3:%[0-9]+]]> = shl ir<%off>, ir<3>
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = sub vp<[[VP3]]>, ir<1>
; CHECK-NEXT: EMIT vp<%diff.check> = icmp ult vp<[[VP4]]>, ir<31>
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = shl ir<%off>, ir<4>
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = sub vp<[[VP5]]>, ir<1>
; CHECK-NEXT: EMIT vp<%diff.check>.1 = icmp ult vp<[[VP6]]>, ir<31>
; CHECK-NEXT: EMIT vp<%conflict.rdx> = or vp<%diff.check>, vp<%diff.check>.1
; CHECK-NEXT: EMIT branch-on-cond vp<%conflict.rdx>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, vector.ph
; CHECK-EMPTY:
; CHECK-NEXT: vector.ph:
; CHECK-NEXT: EMIT vp<[[VP8:%[0-9]+]]> = and ir<%n>, ir<3>
; CHECK-NEXT: EMIT vp<%n.vec> = sub ir<%n>, vp<[[VP8]]>
; CHECK-NEXT: Successor(s): vector.body
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
;
entry:
%off.mul.2 = shl i64 %off, 1
%off.mul.3 = mul i64 %off, 3
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%idx.1 = add i64 %iv, %off
%gep.1 = getelementptr i64, ptr %dst, i64 %idx.1
store double 0.000000e+00, ptr %gep.1, align 8
%idx.2 = add i64 %iv, %off.mul.2
%gep.2 = getelementptr i64, ptr %dst, i64 %idx.2
store double 0.000000e+00, ptr %gep.2, align 8
%idx.3 = add i64 %iv, %off.mul.3
%gep.3 = getelementptr i64, ptr %dst, i64 %idx.3
store double 0.000000e+00, ptr %gep.3, align 8
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
define void @diff_check_needs_freeze(ptr %src.1, ptr %src.2, ptr %dst, i1 %c, i64 %n) {
;
; CHECK-LABEL: VPlan for loop in 'diff_check_needs_freeze'
; CHECK: VPlan 'Final VPlan for VF={4},UF={1}' {
; CHECK-NEXT: Live-in ir<%n> = original trip-count
; CHECK-EMPTY:
; CHECK-NEXT: ir-bb<entry>:
; CHECK-NEXT: IR %src.27 = ptrtoaddr ptr %src.2 to i64
; CHECK-NEXT: IR %src.16 = ptrtoaddr ptr %src.1 to i64
; CHECK-NEXT: IR %dst5 = ptrtoaddr ptr %dst to i64
; CHECK-NEXT: EMIT vp<%min.iters.check> = icmp ult ir<%n>, ir<4>
; CHECK-NEXT: EMIT branch-on-cond vp<%min.iters.check>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, vector.memcheck
; CHECK-EMPTY:
; CHECK-NEXT: vector.memcheck:
; CHECK-NEXT: EMIT vp<[[VP3:%[0-9]+]]> = sub ir<%dst5>, ir<%src.16>
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = sub vp<[[VP3]]>, ir<1>
; CHECK-NEXT: EMIT vp<%diff.check> = icmp ult vp<[[VP4]]>, ir<15>
; CHECK-NEXT: EMIT vp<%diff.check.fr> = freeze vp<%diff.check>
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = sub ir<%dst5>, ir<%src.27>
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = sub vp<[[VP5]]>, ir<1>
; CHECK-NEXT: EMIT vp<%diff.check>.1 = icmp ult vp<[[VP6]]>, ir<15>
; CHECK-NEXT: EMIT vp<%diff.check.fr>.1 = freeze vp<%diff.check>.1
; CHECK-NEXT: EMIT vp<%conflict.rdx> = or vp<%diff.check.fr>, vp<%diff.check.fr>.1
; CHECK-NEXT: EMIT branch-on-cond vp<%conflict.rdx>
; CHECK-NEXT: Successor(s): ir-bb<scalar.ph>, vector.ph
; CHECK-EMPTY:
; CHECK-NEXT: vector.ph:
; CHECK-NEXT: EMIT vp<[[VP8:%[0-9]+]]> = and ir<%n>, ir<3>
; CHECK-NEXT: EMIT vp<%n.vec> = sub ir<%n>, vp<[[VP8]]>
; CHECK-NEXT: EMIT vp<[[VP9:%[0-9]+]]> = step-vector i64
; CHECK-NEXT: EMIT vp<[[VP10:%[0-9]+]]> = broadcast ir<4>
; CHECK-NEXT: Successor(s): vector.body
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%gep.src.1 = getelementptr i32, ptr %src.1, i64 %iv
%gep.src.2 = getelementptr i32, ptr %src.2, i64 %iv
%ptr.sel = select i1 %c, ptr %gep.src.1, ptr %gep.src.2
%l = load i32, ptr %ptr.sel, align 4
%gep.dst = getelementptr i32, ptr %dst, i64 %iv
store i32 %l, ptr %gep.dst, align 4
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
declare void @use(i64)