| ; 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) |