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