blob: 59abff42fc08946b147c9717a59e13c43a75fb0f [file] [edit]
; 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}