blob: fbb21329dbaa5b027e219f2f47fa4e2f1768ea5f [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --filter-out-after "middle.block" --version 6
; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 \
; RUN: -force-target-supports-masked-memory-ops -disable-output \
; RUN: -vplan-print-after="printFinalVPlan$" %s 2>&1 | FileCheck %s
; REQUIRES: asserts
; Tests CSE of masked widened loads and mixed masked/regular loads.
; Two masked loads from the same address under the same condition are CSE'd.
define void @two_masked_same_mask(ptr noalias %a, ptr noalias %b, ptr noalias %cond) {
; CHECK-LABEL: VPlan for loop in 'two_masked_same_mask'
; CHECK: VPlan 'Final VPlan for VF={4},UF={1}' {
; CHECK-NEXT: Live-in ir<1024> = vector-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.body
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
; CHECK-NEXT: EMIT-SCALAR vp<%index> = phi [ ir<0>, vector.ph ], [ vp<%index.next>, vector.body ]
; CHECK-NEXT: CLONE ir<%gep.c> = getelementptr inbounds ir<%cond>, vp<%index>
; CHECK-NEXT: WIDEN ir<%c> = load ir<%gep.c>
; CHECK-NEXT: WIDEN ir<%cmp> = icmp ne ir<%c>, ir<0>
; CHECK-NEXT: CLONE ir<%gep.a> = getelementptr ir<%a>, vp<%index>
; CHECK-NEXT: WIDEN ir<%x> = load ir<%gep.a>, ir<%cmp>
; CHECK-NEXT: WIDEN ir<%s> = add ir<%x>, ir<%x>
; CHECK-NEXT: EMIT vp<%predphi> = select ir<%cmp>, ir<%s>, ir<0>
; CHECK-NEXT: CLONE ir<%gep.b> = getelementptr inbounds ir<%b>, vp<%index>
; CHECK-NEXT: WIDEN store ir<%gep.b>, vp<%predphi>
; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<%index>, ir<4>
; CHECK-NEXT: EMIT vp<[[VP1:%[0-9]+]]> = icmp eq vp<%index.next>, ir<1024>
; CHECK-NEXT: EMIT branch-on-cond vp<[[VP1]]>
; CHECK-NEXT: Successor(s): middle.block, vector.body
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
%gep.c = getelementptr inbounds i32, ptr %cond, i64 %iv
%c = load i32, ptr %gep.c, align 4
%cmp = icmp ne i32 %c, 0
br i1 %cmp, label %if, label %latch
if:
%gep.a = getelementptr inbounds i32, ptr %a, i64 %iv
%x = load i32, ptr %gep.a, align 4
%y = load i32, ptr %gep.a, align 4
%s = add i32 %x, %y
br label %latch
latch:
%m = phi i32 [ 0, %loop ], [ %s, %if ]
%gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
store i32 %m, ptr %gep.b, align 4
%iv.next = add i64 %iv, 1
%ec = icmp eq i64 %iv.next, 1024
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; Masked loads from the same address under different conditions are not CSE'd.
define void @two_masked_diff_mask(ptr noalias %a, ptr noalias %b, ptr noalias %c1, ptr noalias %c2) {
; CHECK-LABEL: VPlan for loop in 'two_masked_diff_mask'
; CHECK: VPlan 'Final VPlan for VF={4},UF={1}' {
; CHECK-NEXT: Live-in ir<1024> = vector-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.body
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
; CHECK-NEXT: EMIT-SCALAR vp<%index> = phi [ ir<0>, vector.ph ], [ vp<%index.next>, vector.body ]
; CHECK-NEXT: CLONE ir<%gep.a> = getelementptr ir<%a>, vp<%index>
; CHECK-NEXT: CLONE ir<%gp1> = getelementptr inbounds ir<%c1>, vp<%index>
; CHECK-NEXT: WIDEN ir<%v1> = load ir<%gp1>
; CHECK-NEXT: WIDEN ir<%cmp1> = icmp ne ir<%v1>, ir<0>
; CHECK-NEXT: WIDEN ir<%x> = load ir<%gep.a>, ir<%cmp1>
; CHECK-NEXT: EMIT vp<%predphi> = select ir<%cmp1>, ir<%x>, ir<0>
; CHECK-NEXT: CLONE ir<%gp2> = getelementptr inbounds ir<%c2>, vp<%index>
; CHECK-NEXT: WIDEN ir<%v2> = load ir<%gp2>
; CHECK-NEXT: WIDEN ir<%cmp2> = icmp ne ir<%v2>, ir<0>
; CHECK-NEXT: WIDEN ir<%y> = load ir<%gep.a>, ir<%cmp2>
; CHECK-NEXT: EMIT vp<%predphi>.1 = select ir<%cmp2>, ir<%y>, ir<0>
; CHECK-NEXT: WIDEN ir<%sum> = add vp<%predphi>, vp<%predphi>.1
; CHECK-NEXT: CLONE ir<%gep.b> = getelementptr inbounds ir<%b>, vp<%index>
; CHECK-NEXT: WIDEN store ir<%gep.b>, ir<%sum>
; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<%index>, ir<4>
; CHECK-NEXT: EMIT vp<[[VP1:%[0-9]+]]> = icmp eq vp<%index.next>, ir<1024>
; CHECK-NEXT: EMIT branch-on-cond vp<[[VP1]]>
; CHECK-NEXT: Successor(s): middle.block, vector.body
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %latch2 ]
%gep.a = getelementptr inbounds i32, ptr %a, i64 %iv
%gp1 = getelementptr inbounds i32, ptr %c1, i64 %iv
%v1 = load i32, ptr %gp1, align 4
%cmp1 = icmp ne i32 %v1, 0
br i1 %cmp1, label %if1, label %latch1
if1:
%x = load i32, ptr %gep.a, align 4
br label %latch1
latch1:
%mx = phi i32 [ 0, %loop ], [ %x, %if1 ]
%gp2 = getelementptr inbounds i32, ptr %c2, i64 %iv
%v2 = load i32, ptr %gp2, align 4
%cmp2 = icmp ne i32 %v2, 0
br i1 %cmp2, label %if2, label %latch2
if2:
%y = load i32, ptr %gep.a, align 4
br label %latch2
latch2:
%my = phi i32 [ 0, %latch1 ], [ %y, %if2 ]
%sum = add i32 %mx, %my
%gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
store i32 %sum, ptr %gep.b, align 4
%iv.next = add i64 %iv, 1
%ec = icmp eq i64 %iv.next, 1024
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; A duplicated regular load and a duplicated masked load are each CSE'd
; independently.
define void @masked_and_regular_mix(ptr noalias %a, ptr noalias %b, ptr noalias %cond, ptr noalias %out) {
; CHECK-LABEL: VPlan for loop in 'masked_and_regular_mix'
; CHECK: VPlan 'Final VPlan for VF={4},UF={1}' {
; CHECK-NEXT: Live-in ir<1024> = vector-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.body
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
; CHECK-NEXT: EMIT-SCALAR vp<%index> = phi [ ir<0>, vector.ph ], [ vp<%index.next>, vector.body ]
; CHECK-NEXT: CLONE ir<%gep.a> = getelementptr inbounds ir<%a>, vp<%index>
; CHECK-NEXT: WIDEN ir<%r1> = load ir<%gep.a>
; CHECK-NEXT: CLONE ir<%gep.c> = getelementptr inbounds ir<%cond>, vp<%index>
; CHECK-NEXT: WIDEN ir<%c> = load ir<%gep.c>
; CHECK-NEXT: WIDEN ir<%cmp> = icmp ne ir<%c>, ir<0>
; CHECK-NEXT: CLONE ir<%gep.b> = getelementptr ir<%b>, vp<%index>
; CHECK-NEXT: WIDEN ir<%m1> = load ir<%gep.b>, ir<%cmp>
; CHECK-NEXT: WIDEN ir<%ms> = add ir<%m1>, ir<%m1>
; CHECK-NEXT: EMIT vp<%predphi> = select ir<%cmp>, ir<%ms>, ir<0>
; CHECK-NEXT: WIDEN ir<%rr> = add ir<%r1>, ir<%r1>
; CHECK-NEXT: WIDEN ir<%sum> = add ir<%rr>, vp<%predphi>
; CHECK-NEXT: CLONE ir<%gep.o> = getelementptr inbounds ir<%out>, vp<%index>
; CHECK-NEXT: WIDEN store ir<%gep.o>, ir<%sum>
; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<%index>, ir<4>
; CHECK-NEXT: EMIT vp<[[VP1:%[0-9]+]]> = icmp eq vp<%index.next>, ir<1024>
; CHECK-NEXT: EMIT branch-on-cond vp<[[VP1]]>
; CHECK-NEXT: Successor(s): middle.block, vector.body
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
%gep.a = getelementptr inbounds i32, ptr %a, i64 %iv
%r1 = load i32, ptr %gep.a, align 4
%r2 = load i32, ptr %gep.a, align 4
%gep.c = getelementptr inbounds i32, ptr %cond, i64 %iv
%c = load i32, ptr %gep.c, align 4
%cmp = icmp ne i32 %c, 0
br i1 %cmp, label %if, label %latch
if:
%gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
%m1 = load i32, ptr %gep.b, align 4
%m2 = load i32, ptr %gep.b, align 4
%ms = add i32 %m1, %m2
br label %latch
latch:
%mm = phi i32 [ 0, %loop ], [ %ms, %if ]
%rr = add i32 %r1, %r2
%sum = add i32 %rr, %mm
%gep.o = getelementptr inbounds i32, ptr %out, i64 %iv
store i32 %sum, ptr %gep.o, align 4
%iv.next = add i64 %iv, 1
%ec = icmp eq i64 %iv.next, 1024
br i1 %ec, label %exit, label %loop
exit:
ret void
}