Update HCFG builder to preserve the original latch block of the initial VPlan, ensuring there is always a latch. It also skips creating the BranchOnCond for the latch of the top-level loop, instead of removing it later. Exiting via the latch is controlled by later recipes. This further unifies HCFG construction and prepares for use to also build an initial VPlan (VPlan0) for inner loops.
100 lines
3.7 KiB
LLVM
100 lines
3.7 KiB
LLVM
; REQUIRES: asserts
|
|
|
|
; RUN: opt -passes=loop-vectorize -pass-remarks=loop-vectorize -enable-vplan-native-path -debug -disable-output %s 2>&1 | FileCheck %s
|
|
|
|
@arr2 = external global [8 x i64], align 16
|
|
@arr = external global [8 x [8 x i64]], align 16
|
|
|
|
define void @foo(i64 %n) {
|
|
; CHECK: VPlan 'HCFGBuilder: Plain CFG
|
|
; CHECK-NEXT: {
|
|
; CHECK-NEXT: Live-in vp<[[VTC:%.+]]> = vector-trip-count
|
|
; CHECK-NEXT: Live-in ir<8> = original 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 loop
|
|
; CHECK-EMPTY:
|
|
; CHECK-NEXT: <x1> vector loop: {
|
|
; CHECK-NEXT: vector.body:
|
|
; CHECK-NEXT: WIDEN-PHI ir<%outer.iv> = phi ir<0>, ir<%outer.iv.next>
|
|
; CHECK-NEXT: EMIT ir<%gep.1> = getelementptr ir<@arr2>, ir<0>, ir<%outer.iv>
|
|
; CHECK-NEXT: EMIT store ir<%outer.iv>, ir<%gep.1>
|
|
; CHECK-NEXT: EMIT ir<%add> = add ir<%outer.iv>, ir<%n>
|
|
; CHECK-NEXT: Successor(s): inner
|
|
; CHECK-EMPTY:
|
|
; CHECK-NEXT: <x1> inner: {
|
|
; CHECK-NEXT: inner:
|
|
; CHECK-NEXT: WIDEN-PHI ir<%inner.iv> = phi ir<0>, ir<%inner.iv.next>
|
|
; CHECK-NEXT: EMIT ir<%gep.2> = getelementptr ir<@arr>, ir<0>, ir<%inner.iv>, ir<%outer.iv>
|
|
; CHECK-NEXT: EMIT store ir<%add>, ir<%gep.2>
|
|
; CHECK-NEXT: EMIT ir<%inner.iv.next> = add ir<%inner.iv>, ir<1>
|
|
; CHECK-NEXT: EMIT ir<%inner.ec> = icmp ir<%inner.iv.next>, ir<8>
|
|
; CHECK-NEXT: EMIT branch-on-cond ir<%inner.ec>
|
|
; CHECK-NEXT: No successors
|
|
; CHECK-NEXT: }
|
|
; CHECK-NEXT: Successor(s): outer.latch
|
|
; CHECK-EMPTY:
|
|
; CHECK-NEXT: outer.latch:
|
|
; CHECK-NEXT: EMIT ir<%outer.iv.next> = add ir<%outer.iv>, ir<1>
|
|
; CHECK-NEXT: EMIT ir<%outer.ec> = icmp ir<%outer.iv.next>, ir<8>
|
|
; CHECK-NEXT: Successor(s): vector.latch
|
|
; CHECK-EMPTY:
|
|
; CHECK-NEXT: vector.latch:
|
|
; CHECK-NEXT: No successors
|
|
; CHECK-NEXT: }
|
|
; CHECK-NEXT: Successor(s): middle.block
|
|
; CHECK-EMPTY:
|
|
; CHECK-NEXT: middle.block:
|
|
; CHECK-NEXT: EMIT vp<[[C:%.+]]> = icmp eq ir<8>, vp<[[VTC]]>
|
|
; CHECK-NEXT: EMIT branch-on-cond vp<[[C]]>
|
|
; CHECK-NEXT: Successor(s): ir-bb<exit>, scalar.ph
|
|
; CHECK-EMPTY:
|
|
; CHECK-NEXT: scalar.ph:
|
|
; CHECK-NEXT: Successor(s): ir-bb<outer.header>
|
|
; CHECK-EMPTY:
|
|
; CHECK-NEXT: ir-bb<outer.header>:
|
|
; CHECK-NEXT: IR %outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %outer.latch ]
|
|
; CHECK-NEXT: IR %gep.1 = getelementptr inbounds [8 x i64], ptr @arr2, i64 0, i64 %outer.iv
|
|
; CHECK-NEXT: IR store i64 %outer.iv, ptr %gep.1, align 4
|
|
; CHECK-NEXT: IR %add = add nsw i64 %outer.iv, %n
|
|
; CHECK-NEXT: No successors
|
|
; CHECK-EMPTY:
|
|
; CHECK-NEXT: ir-bb<exit>:
|
|
; CHECK-NEXT: No successors
|
|
; CHECK-NEXT: }
|
|
entry:
|
|
br label %outer.header
|
|
|
|
outer.header:
|
|
%outer.iv = phi i64 [ 0, %entry ], [ %outer.iv.next, %outer.latch ]
|
|
%gep.1 = getelementptr inbounds [8 x i64], ptr @arr2, i64 0, i64 %outer.iv
|
|
store i64 %outer.iv, ptr %gep.1, align 4
|
|
%add = add nsw i64 %outer.iv, %n
|
|
br label %inner
|
|
|
|
inner:
|
|
%inner.iv = phi i64 [ 0, %outer.header ], [ %inner.iv.next, %inner ]
|
|
%gep.2 = getelementptr inbounds [8 x [8 x i64]], ptr @arr, i64 0, i64 %inner.iv, i64 %outer.iv
|
|
store i64 %add, ptr %gep.2, align 4
|
|
%inner.iv.next = add nuw nsw i64 %inner.iv, 1
|
|
%inner.ec = icmp eq i64 %inner.iv.next, 8
|
|
br i1 %inner.ec, label %outer.latch, label %inner
|
|
|
|
outer.latch:
|
|
%outer.iv.next = add nuw nsw i64 %outer.iv, 1
|
|
%outer.ec = icmp eq i64 %outer.iv.next, 8
|
|
br i1 %outer.ec, label %exit, label %outer.header, !llvm.loop !1
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; CHECK: remark: <unknown>:0:0: vectorized outer loop (vectorization width: 4, interleaved count: 1)
|
|
|
|
!1 = distinct !{!1, !2, !3}
|
|
!2 = !{!"llvm.loop.vectorize.width", i32 4}
|
|
!3 = !{!"llvm.loop.vectorize.enable", i1 true}
|