| ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: opt -passes=loop-vectorize -mtriple=riscv64 -mattr=+v \ |
| ; RUN: -disable-output -vplan-print-after="printFinalVPlan$" %s 2>&1 | FileCheck %s |
| |
| ; The pointer add (%a + 4) has NUW, make sure it is preserved during SCEV expansion. |
| define void @scev_ptradd_strided(ptr noalias %a, ptr noalias %dst, i64 %n) { |
| ; CHECK-LABEL: VPlan for loop in 'scev_ptradd_strided' |
| ; CHECK: VPlan 'Final VPlan for VF={vscale x 1,vscale x 2,vscale x 4},UF={1}' { |
| ; 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: EMIT vp<[[VP2:%[0-9]+]]> = ptradd nuw ir<%a>, ir<4> |
| ; CHECK-NEXT: Successor(s): vector.body |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT-SCALAR vp<%index> = phi [ ir<0>, vector.ph ], [ vp<%current.iteration.next>, vector.body ] |
| ; CHECK-NEXT: EMIT-SCALAR vp<%avl> = phi [ ir<%n>, vector.ph ], [ vp<%avl.next>, vector.body ] |
| ; CHECK-NEXT: EMIT-SCALAR vp<%evl> = EXPLICIT-VECTOR-LENGTH vp<%avl> |
| ; CHECK-NEXT: EMIT vp<[[VP3:%[0-9]+]]> = shl nuw vp<%index>, ir<4> |
| ; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = ptradd nuw vp<[[VP2]]>, vp<[[VP3]]> |
| ; CHECK-NEXT: WIDEN-INTRINSIC vp<[[VP5:%[0-9]+]]> = call llvm.experimental.vp.strided.load(vp<[[VP4]]>, ir<16>, ir<true>, vp<%evl>) |
| ; CHECK-NEXT: CLONE ir<%gd> = getelementptr inbounds ir<%dst>, vp<%index> |
| ; CHECK-NEXT: WIDEN vp.store ir<%gd>, vp<[[VP5]]>, vp<%evl> |
| ; CHECK-NEXT: EMIT-SCALAR vp<[[VP6:%[0-9]+]]> = zext vp<%evl> to i64 |
| ; CHECK-NEXT: EMIT vp<%current.iteration.next> = add vp<[[VP6]]>, vp<%index> |
| ; CHECK-NEXT: EMIT vp<%avl.next> = sub nuw vp<%avl>, vp<[[VP6]]> |
| ; CHECK-NEXT: EMIT vp<[[VP7:%[0-9]+]]> = icmp eq vp<%avl.next>, ir<0> |
| ; CHECK-NEXT: EMIT branch-on-cond vp<[[VP7]]> |
| ; CHECK-NEXT: Successor(s): middle.block, vector.body |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: middle.block: |
| ; CHECK-NEXT: Successor(s): ir-bb<exit> |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<exit>: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] |
| %gep = getelementptr inbounds [4 x i32], ptr %a, i64 %iv, i32 1 |
| %l = load i32, ptr %gep, align 4 |
| %gd = getelementptr inbounds i32, ptr %dst, i64 %iv |
| store i32 %l, ptr %gd |
| %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 @scev_ptradd_strided_var_offset(ptr noalias %a, ptr noalias %dst, i64 %n, i64 %m) { |
| ; CHECK-LABEL: VPlan for loop in 'scev_ptradd_strided_var_offset' |
| ; CHECK: VPlan 'Final VPlan for VF={vscale x 1,vscale x 2,vscale x 4},UF={1}' { |
| ; 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: EMIT vp<[[VP2:%[0-9]+]]> = shl ir<%m>, ir<4> |
| ; CHECK-NEXT: EMIT vp<[[VP3:%[0-9]+]]> = add nuw nsw vp<[[VP2]]>, ir<4> |
| ; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = ptradd ir<%a>, vp<[[VP3]]> |
| ; CHECK-NEXT: Successor(s): vector.body |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: vector.body: |
| ; CHECK-NEXT: EMIT-SCALAR vp<%index> = phi [ ir<0>, vector.ph ], [ vp<%current.iteration.next>, vector.body ] |
| ; CHECK-NEXT: EMIT-SCALAR vp<%avl> = phi [ ir<%n>, vector.ph ], [ vp<%avl.next>, vector.body ] |
| ; CHECK-NEXT: EMIT-SCALAR vp<%evl> = EXPLICIT-VECTOR-LENGTH vp<%avl> |
| ; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = shl vp<%index>, ir<4> |
| ; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = ptradd vp<[[VP4]]>, vp<[[VP5]]> |
| ; CHECK-NEXT: WIDEN-INTRINSIC vp<[[VP7:%[0-9]+]]> = call llvm.experimental.vp.strided.load(vp<[[VP6]]>, ir<16>, ir<true>, vp<%evl>) |
| ; CHECK-NEXT: CLONE ir<%gd> = getelementptr inbounds ir<%dst>, vp<%index> |
| ; CHECK-NEXT: WIDEN vp.store ir<%gd>, vp<[[VP7]]>, vp<%evl> |
| ; CHECK-NEXT: EMIT-SCALAR vp<[[VP8:%[0-9]+]]> = zext vp<%evl> to i64 |
| ; CHECK-NEXT: EMIT vp<%current.iteration.next> = add vp<[[VP8]]>, vp<%index> |
| ; CHECK-NEXT: EMIT vp<%avl.next> = sub nuw vp<%avl>, vp<[[VP8]]> |
| ; CHECK-NEXT: EMIT vp<[[VP9:%[0-9]+]]> = icmp eq vp<%avl.next>, ir<0> |
| ; CHECK-NEXT: EMIT branch-on-cond vp<[[VP9]]> |
| ; CHECK-NEXT: Successor(s): middle.block, vector.body |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: middle.block: |
| ; CHECK-NEXT: Successor(s): ir-bb<exit> |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: ir-bb<exit>: |
| ; CHECK-NEXT: No successors |
| ; CHECK-NEXT: } |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] |
| %idx = add i64 %iv, %m |
| %gep = getelementptr inbounds [4 x i32], ptr %a, i64 %idx, i32 1 |
| %l = load i32, ptr %gep, align 4 |
| %gd = getelementptr inbounds i32, ptr %dst, i64 %iv |
| store i32 %l, ptr %gd |
| %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 |
| } |