| ; REQUIRES: asserts |
| |
| ; RUN: opt -passes=loop-vectorize -force-vector-interleave=1 -force-vector-width=2 -debug -disable-output %s 2>&1 | FileCheck %s |
| |
| target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" |
| |
| @a = common global [2048 x i32] zeroinitializer, align 16 |
| @b = common global [2048 x i32] zeroinitializer, align 16 |
| @c = common global [2048 x i32] zeroinitializer, align 16 |
| |
| |
| ; CHECK-LABEL: LV: Checking a loop in 'sink1' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: Live-in vp<[[BTC:%.+]]> = backedge-taken count |
| ; CHECK-NEXT: vp<[[TC:%.+]]> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: EMIT vp<[[TC]]> = EXPAND SCEV (1 + (8 umin %k))<nuw><nsw> |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VF]]> |
| ; CHECK-NEXT: EMIT vp<[[MASK:%.+]]> = icmp ule ir<%iv>, vp<[[BTC]]> |
| ; CHECK-NEXT: Successor(s): pred.store |
| |
| ; CHECK: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| |
| ; CHECK: pred.store.if: |
| ; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1> |
| ; CHECK-NEXT: REPLICATE ir<%gep.b> = getelementptr inbounds ir<@b>, ir<0>, vp<[[STEPS]]> |
| ; CHECK-NEXT: REPLICATE ir<%lv.b> = load ir<%gep.b> |
| ; CHECK-NEXT: REPLICATE ir<%add> = add ir<%lv.b>, ir<10> |
| ; CHECK-NEXT: REPLICATE ir<%gep.a> = getelementptr inbounds ir<@a>, ir<0>, vp<[[STEPS]] |
| ; CHECK-NEXT: REPLICATE ir<%mul> = mul ir<2>, ir<%add> |
| ; CHECK-NEXT: REPLICATE store ir<%mul>, ir<%gep.a> |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| |
| ; CHECK: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| |
| ; CHECK: loop.1: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| define void @sink1(i32 %k) { |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] |
| %gep.b = getelementptr inbounds [2048 x i32], ptr @b, i32 0, i32 %iv |
| %lv.b = load i32, ptr %gep.b, align 4 |
| %add = add i32 %lv.b, 10 |
| %mul = mul i32 2, %add |
| %gep.a = getelementptr inbounds [2048 x i32], ptr @a, i32 0, i32 %iv |
| store i32 %mul, ptr %gep.a, align 4 |
| %iv.next = add i32 %iv, 1 |
| %large = icmp sge i32 %iv, 8 |
| %exitcond = icmp eq i32 %iv, %k |
| %realexit = or i1 %large, %exitcond |
| br i1 %realexit, label %exit, label %loop |
| |
| exit: |
| ret void |
| } |
| |
| ; CHECK-LABEL: LV: Checking a loop in 'sink2' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: Live-in vp<[[BTC:%.+]]> = backedge-taken count |
| ; CHECK-NEXT: vp<[[TC:%.+]]> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: EMIT vp<[[TC]]> = EXPAND SCEV (1 + (8 umin %k))<nuw><nsw> |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VF]]> |
| ; CHECK-NEXT: EMIT vp<[[MASK:%.+]]> = icmp ule ir<%iv>, vp<[[BTC]]> |
| ; CHECK-NEXT: Successor(s): pred.load |
| |
| ; CHECK: <xVFxUF> pred.load: { |
| ; CHECK-NEXT: pred.load.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK]]> |
| ; CHECK-NEXT: Successor(s): pred.load.if, pred.load.continue |
| |
| ; CHECK: pred.load.if: |
| ; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1> |
| ; CHECK-NEXT: REPLICATE ir<%gep.b> = getelementptr inbounds ir<@b>, ir<0>, vp<[[STEPS]]> |
| ; CHECK-NEXT: REPLICATE ir<%lv.b> = load ir<%gep.b> |
| ; CHECK-NEXT: Successor(s): pred.load.continue |
| |
| ; CHECK: pred.load.continue: |
| ; CHECK-NEXT: PHI-PREDICATED-INSTRUCTION vp<[[PRED:%.+]]> = ir<%lv.b> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| |
| ; CHECK: loop.0: |
| ; CHECK-NEXT: WIDEN ir<%mul> = mul ir<%iv>, ir<2> |
| ; CHECK-NEXT: Successor(s): pred.store |
| |
| ; CHECK: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| |
| ; CHECK: pred.store.if: |
| ; CHECK-NEXT: REPLICATE ir<%gep.a> = getelementptr inbounds ir<@a>, ir<0>, ir<%mul> |
| ; CHECK-NEXT: REPLICATE ir<%add> = add vp<[[PRED]]>, ir<10> |
| ; CHECK-NEXT: REPLICATE store ir<%add>, ir<%gep.a> |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| |
| ; CHECK: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| |
| ; CHECK: loop.1: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| define void @sink2(i32 %k) { |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] |
| %gep.b = getelementptr inbounds [2048 x i32], ptr @b, i32 0, i32 %iv |
| %lv.b = load i32, ptr %gep.b, align 4 |
| %add = add i32 %lv.b, 10 |
| %mul = mul i32 %iv, 2 |
| %gep.a = getelementptr inbounds [2048 x i32], ptr @a, i32 0, i32 %mul |
| store i32 %add, ptr %gep.a, align 4 |
| %iv.next = add i32 %iv, 1 |
| %large = icmp sge i32 %iv, 8 |
| %exitcond = icmp eq i32 %iv, %k |
| %realexit = or i1 %large, %exitcond |
| br i1 %realexit, label %exit, label %loop |
| |
| exit: |
| ret void |
| } |
| |
| ; CHECK-LABEL: LV: Checking a loop in 'sink3' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: Live-in vp<[[BTC:%.+]]> = backedge-taken count |
| ; CHECK-NEXT: vp<[[TC:%.+]]> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: EMIT vp<[[TC]]> = EXPAND SCEV (1 + (8 umin %k))<nuw><nsw> |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VF]]> |
| ; CHECK-NEXT: EMIT vp<[[MASK:%.+]]> = icmp ule ir<%iv>, vp<[[BTC]]> |
| ; CHECK-NEXT: Successor(s): pred.load |
| |
| ; CHECK: <xVFxUF> pred.load: { |
| ; CHECK-NEXT: pred.load.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK]]> |
| ; CHECK-NEXT: Successor(s): pred.load.if, pred.load.continue |
| |
| ; CHECK: pred.load.if: |
| ; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1> |
| ; CHECK-NEXT: REPLICATE ir<%gep.b> = getelementptr inbounds ir<@b>, ir<0>, vp<[[STEPS]]> |
| ; CHECK-NEXT: REPLICATE ir<%lv.b> = load ir<%gep.b> (S->V) |
| ; CHECK-NEXT: Successor(s): pred.load.continue |
| |
| ; CHECK: pred.load.continue: |
| ; CHECK-NEXT: PHI-PREDICATED-INSTRUCTION vp<[[PRED:%.+]]> = ir<%lv.b> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| |
| ; CHECK: loop.0: |
| ; CHECK-NEXT: WIDEN ir<%add> = add vp<[[PRED]]>, ir<10> |
| ; CHECK-NEXT: WIDEN ir<%mul> = mul ir<%iv>, ir<%add> |
| ; CHECK-NEXT: Successor(s): pred.store |
| |
| ; CHECK: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| |
| ; CHECK: pred.store.if: |
| ; CHECK-NEXT: REPLICATE ir<%gep.a> = getelementptr inbounds ir<@a>, ir<0>, ir<%mul> |
| ; CHECK-NEXT: REPLICATE store ir<%add>, ir<%gep.a> |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| |
| ; CHECK: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| |
| ; CHECK: loop.1: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| define void @sink3(i32 %k) { |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] |
| %gep.b = getelementptr inbounds [2048 x i32], ptr @b, i32 0, i32 %iv |
| %lv.b = load i32, ptr %gep.b, align 4 |
| %add = add i32 %lv.b, 10 |
| %mul = mul i32 %iv, %add |
| %gep.a = getelementptr inbounds [2048 x i32], ptr @a, i32 0, i32 %mul |
| store i32 %add, ptr %gep.a, align 4 |
| %iv.next = add i32 %iv, 1 |
| %large = icmp sge i32 %iv, 8 |
| %exitcond = icmp eq i32 %iv, %k |
| %realexit = or i1 %large, %exitcond |
| br i1 %realexit, label %exit, label %loop |
| |
| exit: |
| ret void |
| } |
| |
| ; Make sure we do not sink uniform instructions. |
| define void @uniform_gep(i64 %k, ptr noalias %A, ptr noalias %B) { |
| ; CHECK-LABEL: LV: Checking a loop in 'uniform_gep' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: Live-in vp<[[BTC:%.+]]> = backedge-taken count |
| ; CHECK-NEXT: Live-in ir<11> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: vp<[[END:%.+]]> = DERIVED-IV ir<21> + vp<[[VEC_TC]]> * ir<1> |
| ; CHECK-NEXT: CLONE ir<%gep.A.uniform> = getelementptr inbounds ir<%A>, ir<0> |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION ir<21>, ir<1>, vp<[[VF]]> |
| ; CHECK-NEXT: vp<[[DERIVED_IV:%.+]]> = DERIVED-IV ir<21> + vp<[[CAN_IV]]> * ir<1> |
| ; CHECK-NEXT: EMIT vp<[[WIDE_CAN_IV:%.+]]> = WIDEN-CANONICAL-INDUCTION vp<[[CAN_IV]]> |
| ; CHECK-NEXT: EMIT vp<[[MASK:%.+]]> = icmp ule vp<[[WIDE_CAN_IV]]>, vp<[[BTC]]> |
| ; CHECK-NEXT: CLONE ir<%lv> = load ir<%gep.A.uniform> |
| ; CHECK-NEXT: WIDEN ir<%cmp> = icmp ult ir<%iv>, ir<%k> |
| ; CHECK-NEXT: EMIT vp<[[NOT2:%.+]]> = not ir<%cmp> |
| ; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = logical-and vp<[[MASK]]>, vp<[[NOT2]]> |
| ; CHECK-NEXT: Successor(s): pred.store |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK2]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.if: |
| ; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[DERIVED_IV]]>, ir<1> |
| ; CHECK-NEXT: REPLICATE ir<%gep.B> = getelementptr inbounds ir<%B>, vp<[[STEPS]]> |
| ; CHECK-NEXT: REPLICATE store ir<%lv>, ir<%gep.B> |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): loop.then.0 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: loop.then.0: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i64 [ 21, %entry ], [ %iv.next, %loop.latch ] |
| %gep.A.uniform = getelementptr inbounds i16, ptr %A, i64 0 |
| %gep.B = getelementptr inbounds i16, ptr %B, i64 %iv |
| %lv = load i16, ptr %gep.A.uniform, align 1 |
| %cmp = icmp ult i64 %iv, %k |
| br i1 %cmp, label %loop.latch, label %loop.then |
| |
| loop.then: |
| store i16 %lv, ptr %gep.B, align 1 |
| br label %loop.latch |
| |
| loop.latch: |
| %iv.next = add nsw i64 %iv, 1 |
| %cmp179 = icmp slt i64 %iv.next, 32 |
| br i1 %cmp179, label %loop, label %exit |
| exit: |
| ret void |
| } |
| |
| ; Loop with predicated load. |
| define void @pred_cfg1(i32 %k, i32 %j) { |
| ; CHECK-LABEL: LV: Checking a loop in 'pred_cfg1' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: Live-in vp<[[BTC:%.+]]> = backedge-taken count |
| ; CHECK-NEXT: vp<[[TC:%.+]]> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: EMIT vp<[[TC]]> = EXPAND SCEV (1 + (8 umin %k))<nuw><nsw> |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VF]]> |
| ; CHECK-NEXT: EMIT vp<[[MASK1:%.+]]> = icmp ule ir<%iv>, vp<[[BTC]]> |
| ; CHECK-NEXT: WIDEN ir<%c.1> = icmp ult ir<%iv>, ir<%j> |
| ; CHECK-NEXT: WIDEN ir<%mul> = mul ir<%iv>, ir<10> |
| ; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = logical-and vp<[[MASK1]]>, ir<%c.1> |
| ; CHECK-NEXT: Successor(s): pred.load |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.load: { |
| ; CHECK-NEXT: pred.load.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK2]]> |
| ; CHECK-NEXT: Successor(s): pred.load.if, pred.load.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.load.if: |
| ; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1> |
| ; CHECK-NEXT: REPLICATE ir<%gep.b> = getelementptr inbounds ir<@b>, ir<0>, vp<[[STEPS]]> |
| ; CHECK-NEXT: REPLICATE ir<%lv.b> = load ir<%gep.b> (S->V) |
| ; CHECK-NEXT: Successor(s): pred.load.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.load.continue: |
| ; CHECK-NEXT: PHI-PREDICATED-INSTRUCTION vp<[[PRED:%.+]]> = ir<%lv.b> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): then.0.0 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: then.0.0: |
| ; CHECK-NEXT: BLEND ir<%p> = ir<0> vp<[[PRED]]>/vp<[[MASK2]]> |
| ; CHECK-NEXT: Successor(s): pred.store |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK1]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.if: |
| ; CHECK-NEXT: REPLICATE ir<%gep.a> = getelementptr inbounds ir<@a>, ir<0>, ir<%mul> |
| ; CHECK-NEXT: REPLICATE store ir<%p>, ir<%gep.a> |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): next.0.1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: next.0.1: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %next.0 ] |
| %gep.b = getelementptr inbounds [2048 x i32], ptr @b, i32 0, i32 %iv |
| %c.1 = icmp ult i32 %iv, %j |
| %mul = mul i32 %iv, 10 |
| %gep.a = getelementptr inbounds [2048 x i32], ptr @a, i32 0, i32 %mul |
| br i1 %c.1, label %then.0, label %next.0 |
| |
| then.0: |
| %lv.b = load i32, ptr %gep.b, align 4 |
| br label %next.0 |
| |
| next.0: |
| %p = phi i32 [ 0, %loop ], [ %lv.b, %then.0 ] |
| store i32 %p, ptr %gep.a, align 4 |
| %iv.next = add i32 %iv, 1 |
| %large = icmp sge i32 %iv, 8 |
| %exitcond = icmp eq i32 %iv, %k |
| %realexit = or i1 %large, %exitcond |
| br i1 %realexit, label %exit, label %loop |
| |
| exit: |
| ret void |
| } |
| |
| ; Loop with predicated load and store in separate blocks, store depends on |
| ; loaded value. |
| define void @pred_cfg2(i32 %k, i32 %j) { |
| ; CHECK-LABEL: LV: Checking a loop in 'pred_cfg2' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: Live-in vp<[[BTC:%.+]]> = backedge-taken count |
| ; CHECK-NEXT: vp<[[TC:%.+]]> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: EMIT vp<[[TC]]> = EXPAND SCEV (1 + (8 umin %k))<nuw><nsw> |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VF]]> |
| ; CHECK-NEXT: EMIT vp<[[MASK1:%.+]]> = icmp ule ir<%iv>, vp<[[BTC]]> |
| ; CHECK-NEXT: WIDEN ir<%mul> = mul ir<%iv>, ir<10> |
| ; CHECK-NEXT: WIDEN ir<%c.0> = icmp ult ir<%iv>, ir<%j> |
| ; CHECK-NEXT: WIDEN ir<%c.1> = icmp ugt ir<%iv>, ir<%j> |
| ; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = logical-and vp<[[MASK1]]>, ir<%c.0> |
| ; CHECK-NEXT: Successor(s): pred.load |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.load: { |
| ; CHECK-NEXT: pred.load.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK2]]> |
| ; CHECK-NEXT: Successor(s): pred.load.if, pred.load.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.load.if: |
| ; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1> |
| ; CHECK-NEXT: REPLICATE ir<%gep.b> = getelementptr inbounds ir<@b>, ir<0>, vp<[[STEPS]]> |
| ; CHECK-NEXT: REPLICATE ir<%lv.b> = load ir<%gep.b> (S->V) |
| ; CHECK-NEXT: Successor(s): pred.load.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.load.continue: |
| ; CHECK-NEXT: PHI-PREDICATED-INSTRUCTION vp<[[PRED:%.+]]> = ir<%lv.b> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): then.0.0 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: then.0.0: |
| ; CHECK-NEXT: BLEND ir<%p> = ir<0> vp<[[PRED]]>/vp<[[MASK2]]> |
| ; CHECK-NEXT: EMIT vp<[[MASK3:%.+]]> = logical-and vp<[[MASK1]]>, ir<%c.1> |
| ; CHECK-NEXT: Successor(s): pred.store |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK3]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.if: |
| ; CHECK-NEXT: REPLICATE ir<%gep.a> = getelementptr inbounds ir<@a>, ir<0>, ir<%mul> |
| ; CHECK-NEXT: REPLICATE store ir<%p>, ir<%gep.a> |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): then.1.1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: then.1.1: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %next.1 ] |
| %gep.b = getelementptr inbounds [2048 x i32], ptr @b, i32 0, i32 %iv |
| %mul = mul i32 %iv, 10 |
| %gep.a = getelementptr inbounds [2048 x i32], ptr @a, i32 0, i32 %mul |
| %c.0 = icmp ult i32 %iv, %j |
| %c.1 = icmp ugt i32 %iv, %j |
| br i1 %c.0, label %then.0, label %next.0 |
| |
| then.0: |
| %lv.b = load i32, ptr %gep.b, align 4 |
| br label %next.0 |
| |
| next.0: |
| %p = phi i32 [ 0, %loop ], [ %lv.b, %then.0 ] |
| br i1 %c.1, label %then.1, label %next.1 |
| |
| then.1: |
| store i32 %p, ptr %gep.a, align 4 |
| br label %next.1 |
| |
| next.1: |
| %iv.next = add i32 %iv, 1 |
| %large = icmp sge i32 %iv, 8 |
| %exitcond = icmp eq i32 %iv, %k |
| %realexit = or i1 %large, %exitcond |
| br i1 %realexit, label %exit, label %loop |
| |
| exit: |
| ret void |
| } |
| |
| ; Loop with predicated load and store in separate blocks, store does not depend |
| ; on loaded value. |
| define void @pred_cfg3(i32 %k, i32 %j) { |
| ; CHECK-LABEL: LV: Checking a loop in 'pred_cfg3' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: Live-in vp<[[BTC:%.+]]> = backedge-taken count |
| ; CHECK-NEXT: vp<[[TC:%.+]]> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: EMIT vp<[[TC]]> = EXPAND SCEV (1 + (8 umin %k))<nuw><nsw> |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VF]]> |
| ; CHECK-NEXT: EMIT vp<[[MASK1:%.+]]> = icmp ule ir<%iv>, vp<[[BTC]]> |
| ; CHECK-NEXT: WIDEN ir<%mul> = mul ir<%iv>, ir<10> |
| ; CHECK-NEXT: WIDEN ir<%c.0> = icmp ult ir<%iv>, ir<%j> |
| ; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = logical-and vp<[[MASK1:%.+]]>, ir<%c.0> |
| ; CHECK-NEXT: Successor(s): pred.load |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.load: { |
| ; CHECK-NEXT: pred.load.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK2]]> |
| ; CHECK-NEXT: Successor(s): pred.load.if, pred.load.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.load.if: |
| ; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1> |
| ; CHECK-NEXT: REPLICATE ir<%gep.b> = getelementptr inbounds ir<@b>, ir<0>, vp<[[STEPS]]> |
| ; CHECK-NEXT: REPLICATE ir<%lv.b> = load ir<%gep.b> |
| ; CHECK-NEXT: Successor(s): pred.load.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.load.continue: |
| ; CHECK-NEXT: PHI-PREDICATED-INSTRUCTION vp<[[PRED:%.+]]> = ir<%lv.b> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): then.0.0 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: then.0.0: |
| ; CHECK-NEXT: BLEND ir<%p> = ir<0> vp<[[PRED]]>/vp<[[MASK2]]> |
| ; CHECK-NEXT: EMIT vp<[[MASK3:%.+]]> = logical-and vp<[[MASK1]]>, ir<%c.0> |
| ; CHECK-NEXT: Successor(s): pred.store |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK3]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.if: |
| ; CHECK-NEXT: REPLICATE ir<%gep.a> = getelementptr inbounds ir<@a>, ir<0>, ir<%mul> |
| ; CHECK-NEXT: REPLICATE store ir<0>, ir<%gep.a> |
| ; CHECK-NEXT: REPLICATE ir<%gep.c> = getelementptr inbounds ir<@c>, ir<0>, ir<%mul> |
| ; CHECK-NEXT: REPLICATE store ir<%p>, ir<%gep.c> |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): then.1.2 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: then.1.2: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %next.1 ] |
| %gep.b = getelementptr inbounds [2048 x i32], ptr @b, i32 0, i32 %iv |
| %mul = mul i32 %iv, 10 |
| %gep.a = getelementptr inbounds [2048 x i32], ptr @a, i32 0, i32 %mul |
| %gep.c = getelementptr inbounds [2048 x i32], ptr @c, i32 0, i32 %mul |
| %c.0 = icmp ult i32 %iv, %j |
| br i1 %c.0, label %then.0, label %next.0 |
| |
| then.0: |
| %lv.b = load i32, ptr %gep.b, align 4 |
| br label %next.0 |
| |
| next.0: |
| %p = phi i32 [ 0, %loop ], [ %lv.b, %then.0 ] |
| br i1 %c.0, label %then.1, label %next.1 |
| |
| then.1: |
| store i32 0, ptr %gep.a, align 4 |
| store i32 %p, ptr %gep.c, align 4 |
| br label %next.1 |
| |
| next.1: |
| %iv.next = add i32 %iv, 1 |
| %large = icmp sge i32 %iv, 8 |
| %exitcond = icmp eq i32 %iv, %k |
| %realexit = or i1 %large, %exitcond |
| br i1 %realexit, label %exit, label %loop |
| |
| exit: |
| ret void |
| } |
| |
| define void @merge_3_replicate_region(i32 %k, i32 %j) { |
| ; CHECK-LABEL: LV: Checking a loop in 'merge_3_replicate_region' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: Live-in vp<[[BTC:%.+]]> = backedge-taken count |
| ; CHECK-NEXT: vp<[[TC:%.+]]> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: EMIT vp<[[TC]]> = EXPAND SCEV (1 + (8 umin %k))<nuw><nsw> |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VF]]> |
| ; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1> |
| ; CHECK-NEXT: EMIT vp<[[MASK:%.+]]> = icmp ule ir<%iv>, vp<[[BTC]]> |
| ; CHECK-NEXT: Successor(s): pred.store |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.if: |
| ; CHECK-NEXT: REPLICATE ir<%gep.a> = getelementptr inbounds ir<@a>, ir<0>, vp<[[STEPS]]> |
| ; CHECK-NEXT: REPLICATE ir<%lv.a> = load ir<%gep.a> |
| ; CHECK-NEXT: REPLICATE ir<%gep.b> = getelementptr inbounds ir<@b>, ir<0>, vp<[[STEPS]]> |
| ; CHECK-NEXT: REPLICATE ir<%lv.b> = load ir<%gep.b> |
| ; CHECK-NEXT: REPLICATE ir<%gep.c> = getelementptr inbounds ir<@c>, ir<0>, vp<[[STEPS]]> |
| ; CHECK-NEXT: REPLICATE store ir<%lv.a>, ir<%gep.c> |
| ; CHECK-NEXT: REPLICATE store ir<%lv.b>, ir<%gep.a> |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.continue: |
| ; CHECK-NEXT: PHI-PREDICATED-INSTRUCTION vp<[[PRED1:%.+]]> = ir<%lv.a> |
| ; CHECK-NEXT: PHI-PREDICATED-INSTRUCTION vp<[[PRED2:%.+]]> = ir<%lv.b> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): loop.3 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: loop.3: |
| ; CHECK-NEXT: WIDEN ir<%c.0> = icmp ult ir<%iv>, ir<%j> |
| ; CHECK-NEXT: EMIT vp<[[MASK2:%.+]]> = logical-and vp<[[MASK]]>, ir<%c.0> |
| ; CHECK-NEXT: WIDEN ir<%mul> = mul vp<[[PRED1]]>, vp<[[PRED2]]> |
| ; CHECK-NEXT: Successor(s): pred.store |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK2]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.if: |
| ; CHECK-NEXT: REPLICATE ir<%gep.c.1> = getelementptr inbounds ir<@c>, ir<0>, vp<[[STEPS]]> |
| ; CHECK-NEXT: REPLICATE store ir<%mul>, ir<%gep.c.1> |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): then.0.4 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: then.0.4: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %latch ] |
| %gep.a = getelementptr inbounds [2048 x i32], ptr @a, i32 0, i32 %iv |
| %lv.a = load i32, ptr %gep.a, align 4 |
| %gep.b = getelementptr inbounds [2048 x i32], ptr @b, i32 0, i32 %iv |
| %lv.b = load i32, ptr %gep.b, align 4 |
| %gep.c = getelementptr inbounds [2048 x i32], ptr @c, i32 0, i32 %iv |
| store i32 %lv.a, ptr %gep.c, align 4 |
| store i32 %lv.b, ptr %gep.a, align 4 |
| %c.0 = icmp ult i32 %iv, %j |
| br i1 %c.0, label %then.0, label %latch |
| |
| then.0: |
| %mul = mul i32 %lv.a, %lv.b |
| %gep.c.1 = getelementptr inbounds [2048 x i32], ptr @c, i32 0, i32 %iv |
| store i32 %mul, ptr %gep.c.1, align 4 |
| br label %latch |
| |
| latch: |
| %iv.next = add i32 %iv, 1 |
| %large = icmp sge i32 %iv, 8 |
| %exitcond = icmp eq i32 %iv, %k |
| %realexit = or i1 %large, %exitcond |
| br i1 %realexit, label %exit, label %loop |
| |
| exit: |
| ret void |
| } |
| |
| |
| define void @update_2_uses_in_same_recipe_in_merged_block(i32 %k) { |
| ; CHECK-LABEL: LV: Checking a loop in 'update_2_uses_in_same_recipe_in_merged_block' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: Live-in vp<[[BTC:%.+]]> = backedge-taken count |
| ; CHECK-NEXT: vp<[[TC:%.+]]> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: EMIT vp<[[TC]]> = EXPAND SCEV (1 + (8 umin %k))<nuw><nsw> |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VF]]> |
| ; CHECK-NEXT: EMIT vp<[[MASK:%.+]]> = icmp ule ir<%iv>, vp<[[BTC]]> |
| ; CHECK-NEXT: Successor(s): pred.store |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.if: |
| ; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1> |
| ; CHECK-NEXT: REPLICATE ir<%gep.a> = getelementptr inbounds ir<@a>, ir<0>, vp<[[STEPS]]> |
| ; CHECK-NEXT: REPLICATE ir<%lv.a> = load ir<%gep.a> |
| ; CHECK-NEXT: REPLICATE ir<%div> = sdiv ir<%lv.a>, ir<%lv.a> |
| ; CHECK-NEXT: REPLICATE store ir<%div>, ir<%gep.a> |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): loop.2 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: loop.2: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] |
| %gep.a = getelementptr inbounds [2048 x i32], ptr @a, i32 0, i32 %iv |
| %lv.a = load i32, ptr %gep.a, align 4 |
| %div = sdiv i32 %lv.a, %lv.a |
| store i32 %div, ptr %gep.a, align 4 |
| %iv.next = add i32 %iv, 1 |
| %large = icmp sge i32 %iv, 8 |
| %exitcond = icmp eq i32 %iv, %k |
| %realexit = or i1 %large, %exitcond |
| br i1 %realexit, label %exit, label %loop |
| |
| exit: |
| ret void |
| } |
| |
| define void @recipe_in_merge_candidate_used_by_first_order_recurrence(i32 %k) { |
| ; CHECK-LABEL: LV: Checking a loop in 'recipe_in_merge_candidate_used_by_first_order_recurrence' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: Live-in vp<[[BTC:%.+]]> = backedge-taken count |
| ; CHECK-NEXT: vp<[[TC:%.+]]> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: EMIT vp<[[TC]]> = EXPAND SCEV (1 + (8 umin %k))<nuw><nsw> |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VF]]> |
| ; CHECK-NEXT: FIRST-ORDER-RECURRENCE-PHI ir<%for> = phi ir<0>, vp<[[PRED:%.+]]> |
| ; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1> |
| ; CHECK-NEXT: EMIT vp<[[MASK:%.+]]> = icmp ule ir<%iv>, vp<[[BTC]]> |
| ; CHECK-NEXT: REPLICATE ir<%gep.a> = getelementptr inbounds ir<@a>, ir<0>, vp<[[STEPS]]> |
| ; CHECK-NEXT: Successor(s): pred.load |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.load: { |
| ; CHECK-NEXT: pred.load.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK]]> |
| ; CHECK-NEXT: Successor(s): pred.load.if, pred.load.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.load.if: |
| ; CHECK-NEXT: REPLICATE ir<%lv.a> = load ir<%gep.a> |
| ; CHECK-NEXT: Successor(s): pred.load.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.load.continue: |
| ; CHECK-NEXT: PHI-PREDICATED-INSTRUCTION vp<[[PRED]]> = ir<%lv.a> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): loop.0 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: loop.0: |
| ; CHECK-NEXT: EMIT vp<[[SPLICE:%.+]]> = first-order splice ir<%for>, vp<[[PRED]]> |
| ; CHECK-NEXT: Successor(s): pred.store |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.if: |
| ; CHECK-NEXT: REPLICATE ir<%div> = sdiv vp<[[SPLICE]]>, vp<[[PRED]]> |
| ; CHECK-NEXT: REPLICATE store ir<%div>, ir<%gep.a> |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): loop.2 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: loop.2: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] |
| %for = phi i32 [ 0, %entry ], [ %lv.a, %loop ] |
| %gep.a = getelementptr inbounds [2048 x i32], ptr @a, i32 0, i32 %iv |
| %lv.a = load i32, ptr %gep.a, align 4 |
| %div = sdiv i32 %for, %lv.a |
| store i32 %div, ptr %gep.a, align 4 |
| %iv.next = add i32 %iv, 1 |
| %large = icmp sge i32 %iv, 8 |
| %exitcond = icmp eq i32 %iv, %k |
| %realexit = or i1 %large, %exitcond |
| br i1 %realexit, label %exit, label %loop |
| |
| exit: |
| ret void |
| } |
| |
| define void @update_multiple_users(ptr noalias %src, ptr noalias %dst, i1 %c) { |
| ; CHECK-LABEL: LV: Checking a loop in 'update_multiple_users' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: Live-in ir<999> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: Successor(s): pred.store |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK ir<%c> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.if: |
| ; CHECK-NEXT: REPLICATE ir<%l1> = load ir<%src> |
| ; CHECK-NEXT: REPLICATE ir<%l2> = trunc ir<%l1> |
| ; CHECK-NEXT: REPLICATE ir<%cmp> = icmp eq ir<%l1>, ir<0> |
| ; CHECK-NEXT: REPLICATE ir<%sel> = select ir<%cmp>, ir<5>, ir<%l2> |
| ; CHECK-NEXT: REPLICATE store ir<%sel>, ir<%dst> |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): loop.then.1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: loop.then.1: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| entry: |
| br label %loop.header |
| |
| loop.header: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] |
| br i1 %c, label %loop.then, label %loop.latch |
| |
| loop.then: |
| %l1 = load i16, ptr %src, align 2 |
| %l2 = trunc i16 %l1 to i8 |
| %cmp = icmp eq i16 %l1, 0 |
| %sel = select i1 %cmp, i8 5, i8 %l2 |
| store i8 %sel, ptr %dst, align 1 |
| %sext.l1 = sext i16 %l1 to i32 |
| br label %loop.latch |
| |
| loop.latch: |
| %iv.next = add nsw i64 %iv, 1 |
| %ec = icmp eq i64 %iv.next, 999 |
| br i1 %ec, label %exit, label %loop.header |
| |
| exit: |
| ret void |
| } |
| |
| define void @sinking_requires_duplication(ptr %addr) { |
| ; CHECK-LABEL: LV: Checking a loop in 'sinking_requires_duplication' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: Live-in ir<201> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1> |
| ; CHECK-NEXT: CLONE ir<%gep> = getelementptr ir<%addr>, vp<[[STEPS]]> |
| ; CHECK-NEXT: vp<[[VEC_PTR:%.+]]> = vector-pointer ir<%gep> |
| ; CHECK-NEXT: WIDEN ir<%0> = load vp<[[VEC_PTR]]> |
| ; CHECK-NEXT: WIDEN ir<%pred> = fcmp oeq ir<%0>, ir<0.000000e+00> |
| ; CHECK-NEXT: EMIT vp<[[MASK:%.+]]> = not ir<%pred> |
| ; CHECK-NEXT: Successor(s): pred.store |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.if: |
| ; CHECK-NEXT: REPLICATE ir<%gep>.1 = getelementptr ir<%addr>, vp<[[STEPS]]> |
| ; CHECK-NEXT: REPLICATE store ir<1.000000e+01>, ir<%gep>.1 |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): then.0 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: then.0: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| entry: |
| br label %loop.header |
| |
| loop.header: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] |
| %gep = getelementptr float, ptr %addr, i64 %iv |
| %exitcond.not = icmp eq i64 %iv, 200 |
| br i1 %exitcond.not, label %exit, label %loop.body |
| |
| loop.body: |
| %0 = load float, ptr %gep, align 4 |
| %pred = fcmp oeq float %0, 0.0 |
| br i1 %pred, label %loop.latch, label %then |
| |
| then: |
| store float 10.0, ptr %gep, align 4 |
| br label %loop.latch |
| |
| loop.latch: |
| %iv.next = add nuw nsw i64 %iv, 1 |
| br label %loop.header |
| |
| exit: |
| ret void |
| } |
| |
| ; Test case with a dead GEP between the load and store regions. Dead recipes |
| ; need to be removed before merging. |
| define void @merge_with_dead_gep_between_regions(i32 %n, ptr noalias %src, ptr noalias %dst) optsize { |
| ; CHECK-LABEL: LV: Checking a loop in 'merge_with_dead_gep_between_regions' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: Live-in vp<[[BTC:%.+]]> = backedge-taken count |
| ; CHECK-NEXT: Live-in ir<%n> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: vp<[[END:%.+]]> = DERIVED-IV ir<%n> + vp<[[VEC_TC]]> * ir<-1> |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: vp<[[DERIVED_IV:%.+]]> = DERIVED-IV ir<%n> + vp<[[CAN_IV]]> * ir<-1> |
| ; CHECK-NEXT: EMIT vp<[[WIDE_IV:%.+]]> = WIDEN-CANONICAL-INDUCTION vp<[[CAN_IV]]> |
| ; CHECK-NEXT: EMIT vp<[[MASK:%.+]]> = icmp ule vp<[[WIDE_IV]]>, vp<[[BTC]]> |
| ; CHECK-NEXT: Successor(s): pred.store |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[MASK]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.if: |
| ; CHECK-NEXT: vp<[[SCALAR_STEPS:%.+]]> = SCALAR-STEPS vp<[[DERIVED_IV]]>, ir<-1> |
| ; CHECK-NEXT: REPLICATE ir<%gep.src> = getelementptr inbounds ir<%src>, vp<[[SCALAR_STEPS]]> |
| ; CHECK-NEXT: REPLICATE ir<%l> = load ir<%gep.src> |
| ; CHECK-NEXT: REPLICATE ir<%gep.dst> = getelementptr inbounds ir<%dst>, vp<[[SCALAR_STEPS]]> |
| ; CHECK-NEXT: REPLICATE store ir<%l>, ir<%gep.dst> |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): loop.1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: loop.1: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): middle.block |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: middle.block: |
| ; CHECK-NEXT: EMIT branch-on-cond ir<true> |
| ; CHECK-NEXT: Successor(s): ir-bb<exit>, scalar.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: scalar.ph |
| ; CHECK-NEXT: EMIT vp<[[RESUME:%.+]]> = resume-phi vp<[[END]]>, ir<%n> |
| ; CHECK-NEXT: Successor(s): ir-bb<loop> |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<loop>: |
| ; CHECK-NEXT: IR %iv = phi i32 [ %n, %entry ], [ %iv.next, %loop ] (extra operand: vp<[[RESUME]]> from scalar.ph) |
| ; CHECK-NEXT: IR %iv.next = add nsw i32 %iv, -1 |
| ; CHECK-NEXT: IR %gep.src = getelementptr inbounds i32, ptr %src, i32 %iv |
| ; CHECK-NEXT: IR %l = load i32, ptr %gep.src, align 16 |
| ; CHECK-NEXT: IR %dead_gep = getelementptr inbounds i32, ptr %dst, i64 1 |
| ; CHECK-NEXT: IR %gep.dst = getelementptr inbounds i32, ptr %dst, i32 %iv |
| ; CHECK-NEXT: IR store i32 %l, ptr %gep.dst, align 16 |
| ; CHECK-NEXT: IR %ec = icmp eq i32 %iv.next, 0 |
| ; CHECK-NEXT: No successors |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<exit> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i32[ %n, %entry ], [ %iv.next, %loop ] |
| %iv.next = add nsw i32 %iv, -1 |
| %gep.src = getelementptr inbounds i32, ptr %src, i32 %iv |
| %l = load i32, ptr %gep.src, align 16 |
| %dead_gep = getelementptr inbounds i32, ptr %dst, i64 1 |
| %gep.dst = getelementptr inbounds i32, ptr %dst, i32 %iv |
| store i32 %l, ptr %gep.dst, align 16 |
| %ec = icmp eq i32 %iv.next, 0 |
| br i1 %ec, label %exit, label %loop |
| |
| exit: |
| ret void |
| } |
| |
| define void @ptr_induction_remove_dead_recipe(ptr %start, ptr %end) { |
| ; CHECK-LABEL: LV: Checking a loop in 'ptr_induction_remove_dead_recipe' |
| ; CHECK: VPlan 'Initial VPlan for VF={2},UF>=1' { |
| ; CHECK-NEXT: Live-in vp<[[VF:%.+]]> = VF |
| ; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF |
| ; CHECK-NEXT: Live-in vp<[[VEC_TC:%.+]]> = vector-trip-count |
| ; CHECK-NEXT: vp<[[TC:%.+]]> = original trip-count |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<entry>: |
| ; CHECK-NEXT: EMIT vp<[[TC]]> = EXPAND SCEV ((-1 * (ptrtoint ptr %end to i64)) + (ptrtoint ptr %start to i64)) |
| ; CHECK-NEXT: Successor(s): vector.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.ph: |
| ; CHECK-NEXT: vp<[[END:%.+]]> = DERIVED-IV ir<%start> + vp<[[VEC_TC]]> * ir<-1> |
| ; CHECK-NEXT: Successor(s): vector loop |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <x1> vector loop: { |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION |
| ; CHECK-NEXT: vp<[[DEV_IV:%.+]]> = DERIVED-IV ir<0> + vp<[[CAN_IV]]> * ir<-1> |
| ; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[DEV_IV]]>, ir<-1> |
| ; CHECK-NEXT: EMIT vp<[[PTR_IV:%.+]]> = ptradd ir<%start>, vp<[[STEPS]]> |
| ; CHECK-NEXT: CLONE ir<%ptr.iv.next> = getelementptr inbounds vp<[[PTR_IV]]>, ir<-1> |
| ; CHECK-NEXT: vp<[[VEC_PTR:%.+]]> = reverse-vector-pointer inbounds ir<%ptr.iv.next>, vp<[[VF]]> |
| ; CHECK-NEXT: WIDEN ir<%l> = load vp<[[VEC_PTR]]> |
| ; CHECK-NEXT: WIDEN ir<%c.1> = icmp eq ir<%l>, ir<0> |
| ; CHECK-NEXT: EMIT vp<[[NEG:%.+]]> = not ir<%c.1> |
| ; CHECK-NEXT: Successor(s): pred.store |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: <xVFxUF> pred.store: { |
| ; CHECK-NEXT: pred.store.entry: |
| ; CHECK-NEXT: BRANCH-ON-MASK vp<[[NEG]]> |
| ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.if: |
| ; CHECK-NEXT: REPLICATE ir<%ptr.iv.next>.1 = getelementptr inbounds vp<[[PTR_IV]]>, ir<-1> |
| ; CHECK-NEXT: REPLICATE store ir<95>, ir<%ptr.iv.next>.1 |
| ; CHECK-NEXT: Successor(s): pred.store.continue |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: pred.store.continue: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): if.then.0 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: if.then.0: |
| ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]> |
| ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; CHECK-NEXT: Successor(s): middle.block |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: middle.block: |
| ; CHECK-NEXT: EMIT vp<[[CMP:%.+]]> = icmp eq vp<[[TC]]>, vp<[[VEC_TC]]> |
| ; CHECK-NEXT: EMIT branch-on-cond vp<[[CMP]]> |
| ; CHECK-NEXT: Successor(s): ir-bb<exit>, scalar.ph |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: scalar.ph: |
| ; CHECK-NEXT: EMIT vp<[[RESUME:%.+]]> = resume-phi vp<[[END]]>, ir<%start> |
| ; CHECK-NEXT: Successor(s): ir-bb<loop.header> |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<loop.header>: |
| ; CHECK-NEXT: IR %ptr.iv = phi ptr [ %start, %entry ], [ %ptr.iv.next, %loop.latch ] (extra operand: vp<[[RESUME]]> from scalar.ph) |
| ; CHECK-NEXT: IR %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i64 -1 |
| ; CHECK-NEXT: IR %l = load i8, ptr %ptr.iv.next, align 1 |
| ; CHECK-NEXT: IR %c.1 = icmp eq i8 %l, 0 |
| ; CHECK-NEXT: No successors |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<exit>: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| entry: |
| br label %loop.header |
| |
| loop.header: |
| %ptr.iv = phi ptr [ %start, %entry ], [ %ptr.iv.next, %loop.latch ] |
| %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i64 -1 |
| %l = load i8, ptr %ptr.iv.next, align 1 |
| %c.1 = icmp eq i8 %l, 0 |
| br i1 %c.1, label %loop.latch, label %if.then |
| |
| if.then: |
| store i8 95, ptr %ptr.iv.next, align 1 |
| br label %loop.latch |
| |
| loop.latch: |
| %c.2 = icmp eq ptr %ptr.iv.next, %end |
| br i1 %c.2, label %exit, label %loop.header |
| |
| exit: |
| ret void |
| } |