| ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --filter "getelementptr" --filter "A,\+,|B,\+,|A\),\+," --version 6 |
| ; RUN: opt -passes='print<scalar-evolution>' -disable-output %s 2>&1 | FileCheck %s --check-prefix=BEFORE |
| ; RUN: opt -passes='loop-vectorize,print<scalar-evolution>' -enable-vplan-native-path -disable-output %s 2>&1 | FileCheck %s --check-prefix=AFTER |
| |
| ; Make sure VPlan-based SCEV analysis does not leak any wrap flags, that are |
| ; not valid in the scalar loop. |
| define void @cond_inbounds(ptr noalias %A, i64 %N, i64 %M, i1 %cond) { |
| ; BEFORE-LABEL: 'cond_inbounds' |
| ; BEFORE: %A.ptr = getelementptr float, ptr %A, i64 %outer.iv |
| ; BEFORE: --> {%A,+,4}<%outer.header> U: full-set S: full-set Exits: (-4 + (4 * %N) + %A) LoopDispositions: { %outer.header: Computable, %inner.body: Invariant } |
| ; BEFORE: %A.cond.ptr = getelementptr inbounds float, ptr %A, i64 %outer.iv |
| ; BEFORE: --> {%A,+,4}<%outer.header> U: full-set S: full-set Exits: (-4 + (4 * %N) + %A) LoopDispositions: { %outer.header: Computable, %inner.body: Invariant } |
| ; |
| ; AFTER-LABEL: 'cond_inbounds' |
| ; AFTER: %1 = getelementptr float, ptr %A, i64 %index |
| ; AFTER: --> {%A,+,16}<%vector.body> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (%N /u 4))<nuw>) /u 4)) + %A) LoopDispositions: { %vector.body: Computable, %inner.body3: Invariant } |
| ; AFTER: %A.ptr = getelementptr float, ptr %A, i64 %outer.iv |
| ; AFTER: --> {((4 * %bc.resume.val) + %A),+,4}<%outer.header> U: full-set S: full-set Exits: (-4 + (4 * %N) + %A) LoopDispositions: { %outer.header: Computable, %inner.body: Invariant } |
| ; AFTER: %A.cond.ptr = getelementptr inbounds float, ptr %A, i64 %outer.iv |
| ; AFTER: --> {((4 * %bc.resume.val) + %A),+,4}<%outer.header> U: full-set S: full-set Exits: (-4 + (4 * %N) + %A) LoopDispositions: { %outer.header: Computable, %inner.body: Invariant } |
| ; |
| entry: |
| br label %outer.header |
| |
| outer.header: |
| %outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %outer.latch ] |
| %A.ptr = getelementptr float, ptr %A, i64 %outer.iv |
| store float 3.000000e+00, ptr %A.ptr, align 4, !llvm.access.group !3 |
| br i1 %cond, label %outer.then, label %inner.ph |
| |
| outer.then: |
| %A.cond.ptr = getelementptr inbounds float, ptr %A, i64 %outer.iv |
| %A.val = load float, ptr %A.cond.ptr, align 4, !llvm.access.group !3 |
| store float %A.val, ptr %A.ptr, align 4, !llvm.access.group !3 |
| br label %inner.ph |
| |
| inner.ph: |
| br label %inner.body |
| |
| inner.body: |
| %inner.iv = phi i64 [ 0, %inner.ph ], [ %inner.iv.next, %inner.body ] |
| %inner.iv.next = add nuw nsw i64 %inner.iv, 1 |
| %inner.iv.cmp = icmp eq i64 %inner.iv.next, %M |
| br i1 %inner.iv.cmp, label %outer.latch, label %inner.body |
| |
| outer.latch: |
| %outer.iv.next = add nuw nsw i64 %outer.iv, 1 |
| %outer.iv.cmp = icmp eq i64 %outer.iv.next, %N |
| br i1 %outer.iv.cmp, label %exit, label %outer.header, !llvm.loop !0 |
| |
| exit: |
| ret void |
| } |
| |
| ; Same as @cond_inbounds, but the inbounds GEP is executed unconditionally. |
| define void @uncond_inbounds(ptr noalias %A, ptr noalias %B, i64 %N, i64 %M) { |
| ; BEFORE-LABEL: 'uncond_inbounds' |
| ; BEFORE: %A.ptr = getelementptr inbounds float, ptr %A, i64 %outer.iv |
| ; BEFORE: --> {%A,+,4}<nuw><%outer.header> U: full-set S: full-set Exits: (-4 + (4 * %N) + %A) LoopDispositions: { %outer.header: Computable, %inner.body: Invariant } |
| ; BEFORE: %B.ptr = getelementptr inbounds float, ptr %B, i64 %inner.iv |
| ; BEFORE: --> {%B,+,4}<nuw><%inner.body> U: full-set S: full-set Exits: (-4 + (4 * %M) + %B) LoopDispositions: { %inner.body: Computable, %outer.header: Uniform } |
| ; |
| ; AFTER-LABEL: 'uncond_inbounds' |
| ; AFTER: %1 = getelementptr inbounds float, ptr %A, i64 %index |
| ; AFTER: --> {%A,+,16}<%vector.body> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (%N /u 4))<nuw>) /u 4)) + %A) LoopDispositions: { %vector.body: Computable, %inner.body1: Invariant } |
| ; AFTER: %A.ptr = getelementptr inbounds float, ptr %A, i64 %outer.iv |
| ; AFTER: --> {((4 * %bc.resume.val) + %A),+,4}<%outer.header> U: full-set S: full-set Exits: (-4 + (4 * %N) + %A) LoopDispositions: { %outer.header: Computable, %inner.body: Invariant } |
| ; AFTER: %B.ptr = getelementptr inbounds float, ptr %B, i64 %inner.iv |
| ; AFTER: --> {%B,+,4}<nuw><%inner.body> U: full-set S: full-set Exits: (-4 + (4 * %M) + %B) LoopDispositions: { %inner.body: Computable, %outer.header: Uniform } |
| ; |
| entry: |
| br label %outer.header |
| |
| outer.header: |
| %outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %outer.latch ] |
| %A.ptr = getelementptr inbounds float, ptr %A, i64 %outer.iv |
| store float 0.000000e+00, ptr %A.ptr, align 4, !llvm.access.group !3 |
| br label %inner.body |
| |
| inner.body: |
| %inner.iv = phi i64 [ 0, %outer.header ], [ %inner.iv.next, %inner.body ] |
| %B.ptr = getelementptr inbounds float, ptr %B, i64 %inner.iv |
| %B.val = load float, ptr %B.ptr, align 4, !llvm.access.group !3 |
| %A.val = load float, ptr %A.ptr, align 4, !llvm.access.group !3 |
| %add = fadd float %A.val, %B.val |
| store float %add, ptr %A.ptr, align 4, !llvm.access.group !3 |
| %inner.iv.next = add nuw nsw i64 %inner.iv, 1 |
| %inner.iv.cmp = icmp eq i64 %inner.iv.next, %M |
| br i1 %inner.iv.cmp, label %outer.latch, label %inner.body |
| |
| outer.latch: |
| %outer.iv.next = add nuw nsw i64 %outer.iv, 1 |
| %outer.iv.cmp = icmp eq i64 %outer.iv.next, %N |
| br i1 %outer.iv.cmp, label %exit, label %outer.header, !llvm.loop !0 |
| |
| exit: |
| ret void |
| } |
| |
| ; The store address is a zero-offset GEP based on an inbounds GEP. |
| define void @propagate_through_gep(ptr noalias %A, i64 %N, i64 %M) { |
| ; BEFORE-LABEL: 'propagate_through_gep' |
| ; BEFORE: %A.ptr = getelementptr inbounds float, ptr %A, i64 %outer.iv |
| ; BEFORE: --> {%A,+,4}<nuw><%outer.header> U: full-set S: full-set Exits: (-4 + (4 * %N) + %A) LoopDispositions: { %outer.header: Computable, %inner.body: Invariant } |
| ; BEFORE: %A.ptr.0 = getelementptr i8, ptr %A.ptr, i64 0 |
| ; BEFORE: --> {%A,+,4}<nuw><%outer.header> U: full-set S: full-set Exits: (-4 + (4 * %N) + %A) LoopDispositions: { %outer.header: Computable, %inner.body: Invariant } |
| ; |
| ; AFTER-LABEL: 'propagate_through_gep' |
| ; AFTER: %1 = getelementptr inbounds float, ptr %A, i64 %index |
| ; AFTER: --> {%A,+,16}<%vector.body> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (%N /u 4))<nuw>) /u 4)) + %A) LoopDispositions: { %vector.body: Computable, %inner.body1: Invariant } |
| ; AFTER: %2 = getelementptr i8, ptr %1, i64 0 |
| ; AFTER: --> {%A,+,16}<%vector.body> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (%N /u 4))<nuw>) /u 4)) + %A) LoopDispositions: { %vector.body: Computable, %inner.body1: Invariant } |
| ; AFTER: %A.ptr = getelementptr inbounds float, ptr %A, i64 %outer.iv |
| ; AFTER: --> {((4 * %bc.resume.val) + %A),+,4}<%outer.header> U: full-set S: full-set Exits: (-4 + (4 * %N) + %A) LoopDispositions: { %outer.header: Computable, %inner.body: Invariant } |
| ; AFTER: %A.ptr.0 = getelementptr i8, ptr %A.ptr, i64 0 |
| ; AFTER: --> {((4 * %bc.resume.val) + %A),+,4}<%outer.header> U: full-set S: full-set Exits: (-4 + (4 * %N) + %A) LoopDispositions: { %outer.header: Computable, %inner.body: Invariant } |
| ; |
| entry: |
| br label %outer.header |
| |
| outer.header: |
| %outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %outer.latch ] |
| %A.ptr = getelementptr inbounds float, ptr %A, i64 %outer.iv |
| %A.ptr.0 = getelementptr i8, ptr %A.ptr, i64 0 |
| store float 0.000000e+00, ptr %A.ptr.0, align 4, !llvm.access.group !3 |
| br label %inner.body |
| |
| inner.body: |
| %inner.iv = phi i64 [ 0, %outer.header ], [ %inner.iv.next, %inner.body ] |
| %inner.iv.next = add nuw nsw i64 %inner.iv, 1 |
| %inner.iv.cmp = icmp eq i64 %inner.iv.next, %M |
| br i1 %inner.iv.cmp, label %outer.latch, label %inner.body |
| |
| outer.latch: |
| %outer.iv.next = add nuw nsw i64 %outer.iv, 1 |
| %outer.iv.cmp = icmp eq i64 %outer.iv.next, %N |
| br i1 %outer.iv.cmp, label %exit, label %outer.header, !llvm.loop !0 |
| |
| exit: |
| ret void |
| } |
| |
| !0 = distinct !{!0, !1, !2, !4} |
| !1 = !{!"llvm.loop.vectorize.width", i32 4} |
| !2 = !{!"llvm.loop.vectorize.enable"} |
| !3 = distinct !{} |
| !4 = !{!"llvm.loop.parallel_accesses", !3} |