Files
Luke Lau 1a09ed10e5 [VPlan] Insert VPBlendRecipes in post order. NFC (#201782)
#201783 wants to optimize blend masks by peeking through the contents of
other phi nodes. Currently we eagerly convert phis to blends in reverse
post order, so switch it to post order so that phis at the bottom can
see the phis in their uses.
2026-06-10 08:26:01 +00:00

753 lines
24 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
; RUN: opt -disable-output < %s -p loop-vectorize -vplan-print-after=introduceMasksAndLinearize -vplan-print-vector-region-scope 2>&1 | FileCheck %s
define void @diamond_phi(ptr %a) {
; CHECK-LABEL: VPlan for loop in 'diamond_phi'
; CHECK-NEXT: <x1> vector loop: {
; CHECK-NEXT: vp<[[VP3:%[0-9]+]]> = CANONICAL-IV
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; CHECK-NEXT: EMIT ir<%gep> = getelementptr ir<%a>, ir<%iv>
; CHECK-NEXT: EMIT ir<%c0> = icmp sle ir<%iv>, ir<0>
; CHECK-NEXT: Successor(s): bb2
; CHECK-EMPTY:
; CHECK-NEXT: bb2:
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = not ir<%c0>
; CHECK-NEXT: EMIT ir<%add2> = add ir<%iv>, ir<2>, vp<[[VP4]]>
; CHECK-NEXT: Successor(s): bb1
; CHECK-EMPTY:
; CHECK-NEXT: bb1:
; CHECK-NEXT: EMIT ir<%add1> = add ir<%iv>, ir<1>, ir<%c0>
; CHECK-NEXT: Successor(s): bb4
; CHECK-EMPTY:
; CHECK-NEXT: bb4:
; CHECK-NEXT: BLEND ir<%phi4> = ir<%add2>/vp<[[VP4]]> ir<%add1>/ir<%c0>
; CHECK-NEXT: EMIT store ir<%phi4>, ir<%gep>
; CHECK-NEXT: EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
; CHECK-NEXT: EMIT ir<%ec> = icmp eq ir<%iv.next>, ir<128>
; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<[[VP3]]>, vp<[[VP1:%[0-9]+]]>
; CHECK-NEXT: EMIT branch-on-count vp<%index.next>, vp<[[VP2:%[0-9]+]]>
; CHECK-NEXT: No successors
; CHECK-NEXT: }
; CHECK-NEXT: Successor(s): middle.block
;
entry:
br label %bb0
bb0:
; bb0
; / \
; bb1 bb2
; \ /
; bb4
; Verify that bb4 is unmasked.
%iv = phi i64 [0, %entry], [%iv.next, %bb4]
%gep = getelementptr i64, ptr %a, i64 %iv
%c0 = icmp sle i64 %iv, 0
br i1 %c0, label %bb1, label %bb2
bb1:
%add1 = add i64 %iv, 1
br label %bb4
bb2:
%add2 = add i64 %iv, 2
br label %bb4
bb4:
%phi4 = phi i64 [%add1, %bb1], [%add2, %bb2]
store i64 %phi4, ptr %gep
%iv.next = add nsw nuw i64 %iv, 1
%ec = icmp eq i64 %iv.next, 128
br i1 %ec, label %exit, label %bb0
exit:
ret void
}
define void @mask_reuse(ptr %a) {
; CHECK-LABEL: VPlan for loop in 'mask_reuse'
; CHECK-NEXT: <x1> vector loop: {
; CHECK-NEXT: vp<[[VP3:%[0-9]+]]> = CANONICAL-IV
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; CHECK-NEXT: EMIT ir<%gep> = getelementptr ir<%a>, ir<%iv>
; CHECK-NEXT: EMIT ir<%c0> = icmp sle ir<%iv>, ir<0>
; CHECK-NEXT: Successor(s): bb1
; CHECK-EMPTY:
; CHECK-NEXT: bb1:
; CHECK-NEXT: EMIT ir<%add1> = add ir<%iv>, ir<1>, ir<%c0>
; CHECK-NEXT: EMIT ir<%c1> = icmp sle ir<%iv>, ir<1>, ir<%c0>
; CHECK-NEXT: Successor(s): bb2
; CHECK-EMPTY:
; CHECK-NEXT: bb2:
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = logical-and ir<%c0>, ir<%c1>
; CHECK-NEXT: EMIT ir<%add2> = add ir<%iv>, ir<2>, vp<[[VP4]]>
; CHECK-NEXT: Successor(s): bb3
; CHECK-EMPTY:
; CHECK-NEXT: bb3:
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = not ir<%c1>
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = logical-and ir<%c0>, vp<[[VP5]]>
; CHECK-NEXT: BLEND ir<%phi3> = ir<%add2>/vp<[[VP4]]> ir<%add1>/vp<[[VP6]]>
; CHECK-NEXT: EMIT ir<%add3> = add ir<%phi3>, ir<3>, ir<%c0>
; CHECK-NEXT: Successor(s): bb4
; CHECK-EMPTY:
; CHECK-NEXT: bb4:
; CHECK-NEXT: EMIT vp<[[VP7:%[0-9]+]]> = not ir<%c0>
; CHECK-NEXT: BLEND ir<%phi4> = ir<%add3>/ir<%c0> ir<%iv>/vp<[[VP7]]>
; CHECK-NEXT: EMIT store ir<%phi4>, ir<%gep>
; CHECK-NEXT: EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
; CHECK-NEXT: EMIT ir<%ec> = icmp eq ir<%iv.next>, ir<128>
; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<[[VP3]]>, vp<[[VP1:%[0-9]+]]>
; CHECK-NEXT: EMIT branch-on-count vp<%index.next>, vp<[[VP2:%[0-9]+]]>
; CHECK-NEXT: No successors
; CHECK-NEXT: }
; CHECK-NEXT: Successor(s): middle.block
;
entry:
br label %bb0
bb0:
; bb0:
; / \
; bb1 \
; /\ \
; bb2 | |
; \ | |
; bb3 /
; \ /
; bb4
; Verify that bb3 reuse bb1's mask and bb4 is unmasked.
%iv = phi i64 [0, %entry], [%iv.next, %bb4]
%gep = getelementptr i64, ptr %a, i64 %iv
%c0 = icmp sle i64 %iv, 0
%add0 = add i64 %iv, 0
br i1 %c0, label %bb1, label %bb4
bb1:
%add1 = add i64 %iv, 1
%c1 = icmp sle i64 %iv, 1
br i1 %c1, label %bb2, label %bb3
bb2:
%add2 = add i64 %iv, 2
br label %bb3
bb3:
%phi3 = phi i64 [%add1, %bb1], [%add2, %bb2]
%add3 = add i64 %phi3, 3
br label %bb4
bb4:
%phi4 = phi i64 [%add3, %bb3], [%add0, %bb0]
store i64 %phi4, ptr %gep
%iv.next = add nsw nuw i64 %iv, 1
%ec = icmp eq i64 %iv.next, 128
br i1 %ec, label %exit, label %bb0
exit:
ret void
}
define void @optimized_mask(ptr %a) {
; CHECK-LABEL: VPlan for loop in 'optimized_mask'
; CHECK-NEXT: <x1> vector loop: {
; CHECK-NEXT: vp<[[VP3:%[0-9]+]]> = CANONICAL-IV
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; CHECK-NEXT: EMIT ir<%gep> = getelementptr ir<%a>, ir<%iv>
; CHECK-NEXT: EMIT ir<%c0> = icmp sle ir<%iv>, ir<0>
; CHECK-NEXT: Successor(s): bb6
; CHECK-EMPTY:
; CHECK-NEXT: bb6:
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = not ir<%c0>
; CHECK-NEXT: EMIT ir<%add6> = add ir<%iv>, ir<6>, vp<[[VP4]]>
; CHECK-NEXT: EMIT ir<%c6> = icmp sle ir<%iv>, ir<6>, vp<[[VP4]]>
; CHECK-NEXT: Successor(s): bb1
; CHECK-EMPTY:
; CHECK-NEXT: bb1:
; CHECK-NEXT: EMIT ir<%c1> = icmp sle ir<%iv>, ir<1>, ir<%c0>
; CHECK-NEXT: Successor(s): bb3
; CHECK-EMPTY:
; CHECK-NEXT: bb3:
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = not ir<%c1>
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = logical-and ir<%c0>, vp<[[VP5]]>
; CHECK-NEXT: EMIT ir<%add3> = add ir<%iv>, ir<3>, vp<[[VP6]]>
; CHECK-NEXT: EMIT ir<%c3> = icmp sle ir<%iv>, ir<3>, vp<[[VP6]]>
; CHECK-NEXT: Successor(s): bb2
; CHECK-EMPTY:
; CHECK-NEXT: bb2:
; CHECK-NEXT: EMIT vp<[[VP7:%[0-9]+]]> = logical-and ir<%c0>, ir<%c1>
; CHECK-NEXT: EMIT ir<%add2> = add ir<%iv>, ir<2>, vp<[[VP7]]>
; CHECK-NEXT: Successor(s): bb4
; CHECK-EMPTY:
; CHECK-NEXT: bb4:
; CHECK-NEXT: EMIT vp<[[VP8:%[0-9]+]]> = logical-and vp<[[VP6]]>, ir<%c3>
; CHECK-NEXT: EMIT vp<[[VP9:%[0-9]+]]> = or vp<[[VP8]]>, vp<[[VP7]]>
; CHECK-NEXT: BLEND ir<%phi4> = ir<%add3>/vp<[[VP8]]> ir<%add2>/vp<[[VP7]]>
; CHECK-NEXT: EMIT ir<%add4> = add ir<%phi4>, ir<4>, vp<[[VP9]]>
; CHECK-NEXT: Successor(s): bb5
; CHECK-EMPTY:
; CHECK-NEXT: bb5:
; CHECK-NEXT: EMIT vp<[[VP10:%[0-9]+]]> = logical-and vp<[[VP4]]>, ir<%c6>
; CHECK-NEXT: EMIT vp<[[VP11:%[0-9]+]]> = or vp<[[VP10]]>, vp<[[VP9]]>
; CHECK-NEXT: EMIT vp<[[VP12:%[0-9]+]]> = not ir<%c3>
; CHECK-NEXT: EMIT vp<[[VP13:%[0-9]+]]> = logical-and vp<[[VP6]]>, vp<[[VP12]]>
; CHECK-NEXT: EMIT vp<[[VP14:%[0-9]+]]> = or vp<[[VP11]]>, vp<[[VP13]]>
; CHECK-NEXT: BLEND ir<%phi5> = ir<%add6>/vp<[[VP10]]> ir<%add4>/vp<[[VP9]]> ir<%add3>/vp<[[VP13]]>
; CHECK-NEXT: EMIT ir<%add5> = add ir<%phi5>, ir<5>, vp<[[VP14]]>
; CHECK-NEXT: Successor(s): bb7
; CHECK-EMPTY:
; CHECK-NEXT: bb7:
; CHECK-NEXT: EMIT vp<[[VP15:%[0-9]+]]> = not ir<%c6>
; CHECK-NEXT: EMIT vp<[[VP16:%[0-9]+]]> = logical-and vp<[[VP4]]>, vp<[[VP15]]>
; CHECK-NEXT: BLEND ir<%phi7> = ir<%add6>/vp<[[VP16]]> ir<%add5>/vp<[[VP14]]>
; CHECK-NEXT: EMIT store ir<%phi7>, ir<%gep>
; CHECK-NEXT: EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
; CHECK-NEXT: EMIT ir<%ec> = icmp eq ir<%iv.next>, ir<128>
; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<[[VP3]]>, vp<[[VP1:%[0-9]+]]>
; CHECK-NEXT: EMIT branch-on-count vp<%index.next>, vp<[[VP2:%[0-9]+]]>
; CHECK-NEXT: No successors
; CHECK-NEXT: }
; CHECK-NEXT: Successor(s): middle.block
;
entry:
br label %bb0
bb0:
; bb0:
; / \
; / \
; bb1 bb6
; / \ / |
; bb2 bb3 / /
; \ /| / /
; bb4| / /
; \ | / /
; bb5 /
; \ /
; bb7
; TODO: bb5's mask shouldn't depend on c1/c3.
%iv = phi i64 [0, %entry], [%iv.next, %bb7]
%gep = getelementptr i64, ptr %a, i64 %iv
%c0 = icmp sle i64 %iv, 0
br i1 %c0, label %bb1, label %bb6
bb1:
%add1 = add i64 %iv, 1
%c1 = icmp sle i64 %iv, 1
br i1 %c1, label %bb2, label %bb3
bb2:
%add2 = add i64 %iv, 2
br label %bb4
bb3:
%add3 = add i64 %iv, 3
%c3 = icmp sle i64 %iv, 3
br i1 %c3, label %bb4, label %bb5
bb4:
%phi4 = phi i64 [%add2, %bb2], [%add3, %bb3]
%add4 = add i64 %phi4, 4
br label %bb5
bb5:
%phi5 = phi i64 [%add4, %bb4], [%add3, %bb3], [%add6, %bb6]
%add5 = add i64 %phi5, 5
br label %bb7
bb6:
%add6 = add i64 %iv, 6
%c6 = icmp sle i64 %iv, 6
br i1 %c6, label %bb5, label %bb7
bb7:
%phi7 = phi i64 [%add5, %bb5], [%add6, %bb6]
store i64 %phi7, ptr %gep
%iv.next = add nsw nuw i64 %iv, 1
%ec = icmp eq i64 %iv.next, 128
br i1 %ec, label %exit, label %bb0
exit:
ret void
}
define void @switch(ptr %a) {
; CHECK-LABEL: VPlan for loop in 'switch'
; CHECK-NEXT: <x1> vector loop: {
; CHECK-NEXT: vp<[[VP3:%[0-9]+]]> = CANONICAL-IV
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; CHECK-NEXT: EMIT ir<%gep> = getelementptr ir<%a>, ir<%iv>
; CHECK-NEXT: EMIT ir<%c0> = icmp sle ir<%iv>, ir<0>
; CHECK-NEXT: Successor(s): bb2
; CHECK-EMPTY:
; CHECK-NEXT: bb2:
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = not ir<%c0>
; CHECK-NEXT: EMIT ir<%add2> = add ir<%iv>, ir<2>, vp<[[VP4]]>
; CHECK-NEXT: EMIT ir<%c2> = icmp sle ir<%iv>, ir<2>, vp<[[VP4]]>
; CHECK-NEXT: Successor(s): bb1
; CHECK-EMPTY:
; CHECK-NEXT: bb1:
; CHECK-NEXT: EMIT ir<%add1> = add ir<%iv>, ir<1>, ir<%c0>
; CHECK-NEXT: Successor(s): bb3
; CHECK-EMPTY:
; CHECK-NEXT: bb3:
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = logical-and vp<[[VP4]]>, ir<%c2>
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = icmp eq ir<%iv>, ir<1>
; CHECK-NEXT: EMIT vp<[[VP7:%[0-9]+]]> = icmp eq ir<%iv>, ir<2>
; CHECK-NEXT: EMIT vp<[[VP8:%[0-9]+]]> = icmp eq ir<%iv>, ir<3>
; CHECK-NEXT: EMIT vp<[[VP9:%[0-9]+]]> = logical-and ir<%c0>, vp<[[VP6]]>
; CHECK-NEXT: EMIT vp<[[VP10:%[0-9]+]]> = or vp<[[VP7]]>, vp<[[VP8]]>
; CHECK-NEXT: EMIT vp<[[VP11:%[0-9]+]]> = logical-and ir<%c0>, vp<[[VP10]]>
; CHECK-NEXT: EMIT vp<[[VP12:%[0-9]+]]> = or vp<[[VP9]]>, vp<[[VP11]]>
; CHECK-NEXT: EMIT vp<[[VP13:%[0-9]+]]> = not vp<[[VP12]]>
; CHECK-NEXT: EMIT vp<[[VP14:%[0-9]+]]> = logical-and ir<%c0>, vp<[[VP13]]>
; CHECK-NEXT: EMIT vp<[[VP15:%[0-9]+]]> = or vp<[[VP5]]>, vp<[[VP11]]>
; CHECK-NEXT: BLEND ir<%phi3> = ir<%add2>/vp<[[VP5]]> ir<%add1>/vp<[[VP11]]> ir<%add1>/vp<[[VP11]]>
; CHECK-NEXT: EMIT ir<%add3> = add ir<%phi3>, ir<3>, vp<[[VP15]]>
; CHECK-NEXT: Successor(s): bb4
; CHECK-EMPTY:
; CHECK-NEXT: bb4:
; CHECK-NEXT: EMIT ir<%add4> = add ir<%iv>, ir<4>, vp<[[VP9]]>
; CHECK-NEXT: Successor(s): bb5
; CHECK-EMPTY:
; CHECK-NEXT: bb5:
; CHECK-NEXT: EMIT vp<[[VP16:%[0-9]+]]> = not ir<%c2>
; CHECK-NEXT: EMIT vp<[[VP17:%[0-9]+]]> = logical-and vp<[[VP4]]>, vp<[[VP16]]>
; CHECK-NEXT: BLEND ir<%phi5> = ir<%add4>/vp<[[VP9]]> ir<%add3>/vp<[[VP15]]> ir<%add2>/vp<[[VP17]]> ir<%add1>/vp<[[VP14]]>
; CHECK-NEXT: EMIT store ir<%phi5>, ir<%gep>
; CHECK-NEXT: EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
; CHECK-NEXT: EMIT ir<%ec> = icmp eq ir<%iv.next>, ir<128>
; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<[[VP3]]>, vp<[[VP1:%[0-9]+]]>
; CHECK-NEXT: EMIT branch-on-count vp<%index.next>, vp<[[VP2:%[0-9]+]]>
; CHECK-NEXT: No successors
; CHECK-NEXT: }
; CHECK-NEXT: Successor(s): middle.block
;
entry:
br label %bb0
bb0:
; bb0:
; / \
; bb1-+ bb2
; / | \| /\
; \bb4 bb3|
; \ \ | /
; +>bb5
; Test for blends at switch destinations, including multiple edges from switch
; to a single block (bb3).
%iv = phi i64 [0, %entry], [%iv.next, %bb5]
%gep = getelementptr i64, ptr %a, i64 %iv
%c0 = icmp sle i64 %iv, 0
%add0 = add i64 %iv, 0
br i1 %c0, label %bb1, label %bb2
bb1:
%add1 = add i64 %iv, 1
switch i64 %iv, label %bb5 [
i64 1, label %bb4
i64 2, label %bb3
i64 3, label %bb3
]
bb2:
%add2 = add i64 %iv, 2
%c2 = icmp sle i64 %iv, 2
br i1 %c2, label %bb3, label %bb5
bb3:
%phi3 = phi i64 [%add1, %bb1], [%add1, %bb1], [%add2, %bb2]
%add3 = add i64 %phi3, 3
br label %bb5
bb4:
%add4 = add i64 %iv, 4
br label %bb5
bb5:
%phi5 = phi i64 [%add1, %bb1], [%add2, %bb2], [%add3, %bb3], [%add4, %bb4]
store i64 %phi5, ptr %gep
%iv.next = add nsw nuw i64 %iv, 1
%ec = icmp eq i64 %iv.next, 128
br i1 %ec, label %exit, label %bb0
exit:
ret void
}
; bb0
; / \
; bb1 bb2
; | \ / |
; | bb4 |
; \ | /
; bb5
;
; The blend masks for %phi in bb4 should be:
; bb1 := bb0->bb1 := c0
; bb2 := bb0->bb2 := !c0
define void @diamond_phi2(ptr %a, i1 %c1, i1 %c2) {
; CHECK-LABEL: VPlan for loop in 'diamond_phi2'
; CHECK-NEXT: <x1> vector loop: {
; CHECK-NEXT: vp<[[VP3:%[0-9]+]]> = CANONICAL-IV
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; CHECK-NEXT: EMIT ir<%c0> = icmp sle ir<%iv>, ir<0>
; CHECK-NEXT: Successor(s): bb2
; CHECK-EMPTY:
; CHECK-NEXT: bb2:
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = not ir<%c0>
; CHECK-NEXT: EMIT ir<%add2> = add ir<%iv>, ir<2>, vp<[[VP4]]>
; CHECK-NEXT: Successor(s): bb1
; CHECK-EMPTY:
; CHECK-NEXT: bb1:
; CHECK-NEXT: EMIT ir<%add1> = add ir<%iv>, ir<1>, ir<%c0>
; CHECK-NEXT: Successor(s): bb4
; CHECK-EMPTY:
; CHECK-NEXT: bb4:
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = logical-and vp<[[VP4]]>, ir<%c2>
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = logical-and ir<%c0>, ir<%c1>
; CHECK-NEXT: EMIT vp<[[VP7:%[0-9]+]]> = or vp<[[VP5]]>, vp<[[VP6]]>
; CHECK-NEXT: BLEND ir<%phi> = ir<%add2>/vp<[[VP5]]> ir<%add1>/vp<[[VP6]]>
; CHECK-NEXT: EMIT ir<%gep> = getelementptr ir<%a>, ir<%iv>
; CHECK-NEXT: EMIT store ir<%phi>, ir<%gep>, vp<[[VP7]]>
; CHECK-NEXT: Successor(s): bb5
; CHECK-EMPTY:
; CHECK-NEXT: bb5:
; CHECK-NEXT: EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
; CHECK-NEXT: EMIT ir<%ec> = icmp eq ir<%iv.next>, ir<128>
; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<[[VP3]]>, vp<[[VP1:%[0-9]+]]>
; CHECK-NEXT: EMIT branch-on-count vp<%index.next>, vp<[[VP2:%[0-9]+]]>
; CHECK-NEXT: No successors
; CHECK-NEXT: }
; CHECK-NEXT: Successor(s): middle.block
;
entry:
br label %bb0
bb0:
%iv = phi i64 [0, %entry], [%iv.next, %bb5]
%c0 = icmp sle i64 %iv, 0
br i1 %c0, label %bb1, label %bb2
bb1:
%add1 = add i64 %iv, 1
br i1 %c1, label %bb4, label %bb5
bb2:
%add2 = add i64 %iv, 2
br i1 %c2, label %bb4, label %bb5
bb4:
%phi = phi i64 [%add1, %bb1], [%add2, %bb2]
%gep = getelementptr i64, ptr %a, i64 %iv
store i64 %phi, ptr %gep
br label %bb5
bb5:
%iv.next = add nsw nuw i64 %iv, 1
%ec = icmp eq i64 %iv.next, 128
br i1 %ec, label %exit, label %bb0
exit:
ret void
}
; bb0
; / \
; bb1 bb2
; / \ |
; bb3 bb4 |
; / \ / \ /
; \ bb5 bb6
; \ \ / /
; \ bb7 /
; \ | /
; bb8
;
; The blend masks for %phi in bb7 should be:
; bb5 := bb1->bb3 v bb4->bb5 := (c0 && c1) || (c0 && !c1 && c3)
; bb6 := bb4->bb6 v bb0->bb2 := (c0 && !c1 && !c3) || !c1
define void @blend_masks(ptr noalias %p, i1 %c0, i1 %c1, i1 %c2, i1 %c3, i1 %c4) {
; CHECK-LABEL: VPlan for loop in 'blend_masks'
; CHECK-NEXT: <x1> vector loop: {
; CHECK-NEXT: vp<[[VP3:%[0-9]+]]> = CANONICAL-IV
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; CHECK-NEXT: Successor(s): bb2
; CHECK-EMPTY:
; CHECK-NEXT: bb2:
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = not ir<%c0>
; CHECK-NEXT: Successor(s): bb1
; CHECK-EMPTY:
; CHECK-NEXT: bb1:
; CHECK-NEXT: Successor(s): bb4
; CHECK-EMPTY:
; CHECK-NEXT: bb4:
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = not ir<%c1>
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = logical-and ir<%c0>, vp<[[VP5]]>
; CHECK-NEXT: Successor(s): bb6
; CHECK-EMPTY:
; CHECK-NEXT: bb6:
; CHECK-NEXT: EMIT vp<[[VP7:%[0-9]+]]> = not ir<%c3>
; CHECK-NEXT: EMIT vp<[[VP8:%[0-9]+]]> = logical-and vp<[[VP6]]>, vp<[[VP7]]>
; CHECK-NEXT: EMIT vp<[[VP9:%[0-9]+]]> = or vp<[[VP8]]>, vp<[[VP4]]>
; CHECK-NEXT: Successor(s): bb3
; CHECK-EMPTY:
; CHECK-NEXT: bb3:
; CHECK-NEXT: EMIT vp<[[VP10:%[0-9]+]]> = logical-and ir<%c0>, ir<%c1>
; CHECK-NEXT: Successor(s): bb5
; CHECK-EMPTY:
; CHECK-NEXT: bb5:
; CHECK-NEXT: EMIT vp<[[VP11:%[0-9]+]]> = logical-and vp<[[VP6]]>, ir<%c3>
; CHECK-NEXT: EMIT vp<[[VP12:%[0-9]+]]> = not ir<%c2>
; CHECK-NEXT: EMIT vp<[[VP13:%[0-9]+]]> = logical-and vp<[[VP10]]>, vp<[[VP12]]>
; CHECK-NEXT: EMIT vp<[[VP14:%[0-9]+]]> = or vp<[[VP11]]>, vp<[[VP13]]>
; CHECK-NEXT: Successor(s): bb7
; CHECK-EMPTY:
; CHECK-NEXT: bb7:
; CHECK-NEXT: EMIT vp<[[VP15:%[0-9]+]]> = logical-and vp<[[VP9]]>, ir<%c4>
; CHECK-NEXT: EMIT vp<[[VP16:%[0-9]+]]> = or vp<[[VP15]]>, vp<[[VP14]]>
; CHECK-NEXT: BLEND ir<%phi> = ir<1>/vp<[[VP15]]> ir<0>/vp<[[VP14]]>
; CHECK-NEXT: EMIT ir<%gep> = getelementptr ir<%p>, ir<%iv>
; CHECK-NEXT: EMIT store ir<%phi>, ir<%gep>, vp<[[VP16]]>
; CHECK-NEXT: Successor(s): bb8
; CHECK-EMPTY:
; CHECK-NEXT: bb8:
; CHECK-NEXT: EMIT ir<%iv.next> = add ir<%iv>, ir<1>
; CHECK-NEXT: EMIT ir<%ec> = icmp eq ir<%iv.next>, ir<128>
; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<[[VP3]]>, vp<[[VP1:%[0-9]+]]>
; CHECK-NEXT: EMIT branch-on-count vp<%index.next>, vp<[[VP2:%[0-9]+]]>
; CHECK-NEXT: No successors
; CHECK-NEXT: }
; CHECK-NEXT: Successor(s): middle.block
;
entry:
br label %bb0
bb0:
%iv = phi i32 [0, %entry], [%iv.next, %bb8]
br i1 %c0, label %bb1, label %bb2
bb1:
br i1 %c1, label %bb3, label %bb4
bb2:
br label %bb6
bb3:
br i1 %c2, label %bb8, label %bb5
bb4:
br i1 %c3, label %bb5, label %bb6
bb5:
br label %bb7
bb6:
br i1 %c4, label %bb7, label %bb8
bb7:
%phi = phi i32 [0, %bb5], [1, %bb6]
%gep = getelementptr i32, ptr %p, i32 %iv
store i32 %phi, ptr %gep
br label %bb8
bb8:
%iv.next = add i32 %iv, 1
%ec = icmp eq i32 %iv.next, 128
br i1 %ec, label %exit, label %bb0
exit:
ret void
}
; bb0
; / |
; bb1 |
; | \ |
; | bb2
; | /
; bb3
;
; The blend masks for %phi in bb3 should be:
; bb0 := bb1->bb2 v bb0->bb2 := c0 && !c1 || !c0
; bb1 := bb1->bb3 := c0 && c1
define void @blend_masks_triangle_phi(ptr noalias %p, i1 %c0, i1 %c1) {
; CHECK-LABEL: VPlan for loop in 'blend_masks_triangle_phi'
; CHECK-NEXT: <x1> vector loop: {
; CHECK-NEXT: vp<[[VP3:%[0-9]+]]> = CANONICAL-IV
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; CHECK-NEXT: Successor(s): bb1
; CHECK-EMPTY:
; CHECK-NEXT: bb1:
; CHECK-NEXT: Successor(s): bb2
; CHECK-EMPTY:
; CHECK-NEXT: bb2:
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = not ir<%c1>
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = logical-and ir<%c0>, vp<[[VP4]]>
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = not ir<%c0>
; CHECK-NEXT: EMIT vp<[[VP7:%[0-9]+]]> = or vp<[[VP5]]>, vp<[[VP6]]>
; CHECK-NEXT: Successor(s): bb3
; CHECK-EMPTY:
; CHECK-NEXT: bb3:
; CHECK-NEXT: EMIT vp<[[VP8:%[0-9]+]]> = logical-and ir<%c0>, ir<%c1>
; CHECK-NEXT: BLEND ir<%phi> = ir<1>/vp<[[VP7]]> ir<0>/vp<[[VP8]]>
; CHECK-NEXT: EMIT ir<%gep> = getelementptr ir<%p>, ir<%iv>
; CHECK-NEXT: EMIT store ir<%phi>, ir<%gep>
; CHECK-NEXT: EMIT ir<%iv.next> = add ir<%iv>, ir<1>
; CHECK-NEXT: EMIT ir<%ec> = icmp eq ir<%iv.next>, ir<128>
; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<[[VP3]]>, vp<[[VP1:%[0-9]+]]>
; CHECK-NEXT: EMIT branch-on-count vp<%index.next>, vp<[[VP2:%[0-9]+]]>
; CHECK-NEXT: No successors
; CHECK-NEXT: }
; CHECK-NEXT: Successor(s): middle.block
;
entry:
br label %bb0
bb0:
%iv = phi i32 [0, %entry], [%iv.next, %bb3]
br i1 %c0, label %bb1, label %bb2
bb1:
br i1 %c1, label %bb3, label %bb2
bb2:
br label %bb3
bb3:
%phi = phi i32 [0, %bb1], [1, %bb2]
%gep = getelementptr i32, ptr %p, i32 %iv
store i32 %phi, ptr %gep
%iv.next = add i32 %iv, 1
%ec = icmp eq i32 %iv.next, 128
br i1 %ec, label %exit, label %bb0
exit:
ret void
}
define void @blend_chain_non_trivial(ptr noalias %a, ptr noalias %b) {
; CHECK-LABEL: VPlan for loop in 'blend_chain_non_trivial'
; CHECK-NEXT: <x1> vector loop: {
; CHECK-NEXT: vp<[[VP3:%[0-9]+]]> = CANONICAL-IV
; CHECK-EMPTY:
; CHECK-NEXT: vector.body:
; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; CHECK-NEXT: EMIT-SCALAR ir<%lb> = load ir<%b>
; CHECK-NEXT: EMIT ir<%v1> = add ir<%iv>, ir<%lb>
; CHECK-NEXT: EMIT ir<%v2> = mul ir<%iv>, ir<3>
; CHECK-NEXT: EMIT ir<%gep> = getelementptr ir<%a>, ir<%iv>
; CHECK-NEXT: EMIT ir<%c0> = icmp sle ir<%iv>, ir<0>
; CHECK-NEXT: Successor(s): if.a
; CHECK-EMPTY:
; CHECK-NEXT: if.a:
; CHECK-NEXT: EMIT ir<%ca> = icmp sle ir<%iv>, ir<8>, ir<%c0>
; CHECK-NEXT: Successor(s): if.a.inner
; CHECK-EMPTY:
; CHECK-NEXT: if.a.inner:
; CHECK-NEXT: EMIT vp<[[VP4:%[0-9]+]]> = logical-and ir<%c0>, ir<%ca>
; CHECK-NEXT: Successor(s): merge.a.inner
; CHECK-EMPTY:
; CHECK-NEXT: merge.a.inner:
; CHECK-NEXT: Successor(s): merge.a
; CHECK-EMPTY:
; CHECK-NEXT: merge.a:
; CHECK-NEXT: EMIT vp<[[VP5:%[0-9]+]]> = not ir<%c0>
; CHECK-NEXT: BLEND ir<%blend.a> = ir<%v1>/ir<%c0> ir<%v1>/vp<[[VP5]]>
; CHECK-NEXT: EMIT ir<%d0> = icmp sgt ir<%iv>, ir<0>
; CHECK-NEXT: Successor(s): if.b
; CHECK-EMPTY:
; CHECK-NEXT: if.b:
; CHECK-NEXT: EMIT ir<%cb> = icmp sle ir<%iv>, ir<16>, ir<%d0>
; CHECK-NEXT: Successor(s): if.b.inner
; CHECK-EMPTY:
; CHECK-NEXT: if.b.inner:
; CHECK-NEXT: EMIT vp<[[VP6:%[0-9]+]]> = logical-and ir<%d0>, ir<%cb>
; CHECK-NEXT: Successor(s): merge.b.inner
; CHECK-EMPTY:
; CHECK-NEXT: merge.b.inner:
; CHECK-NEXT: Successor(s): merge.b
; CHECK-EMPTY:
; CHECK-NEXT: merge.b:
; CHECK-NEXT: EMIT vp<[[VP7:%[0-9]+]]> = not ir<%d0>
; CHECK-NEXT: BLEND ir<%blend.b> = ir<%v2>/ir<%d0> ir<%v2>/vp<[[VP7]]>
; CHECK-NEXT: EMIT ir<%sum> = add ir<%blend.a>, ir<%blend.b>
; CHECK-NEXT: EMIT store ir<%sum>, ir<%gep>
; CHECK-NEXT: Successor(s): loop.latch
; CHECK-EMPTY:
; CHECK-NEXT: loop.latch:
; CHECK-NEXT: EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
; CHECK-NEXT: EMIT ir<%ec> = icmp eq ir<%iv.next>, ir<128>
; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<[[VP3]]>, vp<[[VP1:%[0-9]+]]>
; CHECK-NEXT: EMIT branch-on-count vp<%index.next>, vp<[[VP2:%[0-9]+]]>
; CHECK-NEXT: No successors
; CHECK-NEXT: }
; CHECK-NEXT: Successor(s): middle.block
;
entry:
br label %loop.header
loop.header:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
%lb = load i64, ptr %b
%v1 = add i64 %iv, %lb
%v2 = mul i64 %iv, 3
%gep = getelementptr i64, ptr %a, i64 %iv
%c0 = icmp sle i64 %iv, 0
br i1 %c0, label %if.a, label %merge.a
if.a:
%ca = icmp sle i64 %iv, 8
br i1 %ca, label %if.a.inner, label %merge.a.inner
if.a.inner:
br label %merge.a.inner
merge.a.inner:
%blend.a.inner = phi i64 [ %v1, %if.a ], [ %v1, %if.a.inner ]
br label %merge.a
merge.a:
%blend.a = phi i64 [ %v1, %loop.header ], [ %blend.a.inner, %merge.a.inner ]
%d0 = icmp sgt i64 %iv, 0
br i1 %d0, label %if.b, label %merge.b
if.b:
%cb = icmp sle i64 %iv, 16
br i1 %cb, label %if.b.inner, label %merge.b.inner
if.b.inner:
br label %merge.b.inner
merge.b.inner:
%blend.b.inner = phi i64 [ %v2, %if.b ], [ %v2, %if.b.inner ]
br label %merge.b
merge.b:
%blend.b = phi i64 [ %v2, %merge.a ], [ %blend.b.inner, %merge.b.inner ]
%sum = add i64 %blend.a, %blend.b
store i64 %sum, ptr %gep
br label %loop.latch
loop.latch:
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, 128
br i1 %ec, label %exit, label %loop.header
exit:
ret void
}