Follow-up as discussed when using VPInstruction::ResumePhi for all resume values (#112147). This patch explicitly adds incoming values for each predecessor in VPlan. This simplifies codegen and allows transformations adjusting the predecessors of blocks with NFC modulo incoming block order in phis.
227 lines
10 KiB
LLVM
227 lines
10 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes=loop-vectorize -force-vector-width=2 -force-vector-interleave=1 -S %s | FileCheck %s
|
|
|
|
; Make sure LV does not crash when creating runtime checks involving values from
|
|
; other loops.
|
|
define i16 @test(ptr %arg, i64 %N) {
|
|
; CHECK-LABEL: @test(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[OUTER:%.*]]
|
|
; CHECK: outer:
|
|
; CHECK-NEXT: [[L_1:%.*]] = load ptr, ptr [[ARG:%.*]], align 8
|
|
; CHECK-NEXT: [[L_2:%.*]] = load ptr, ptr [[ARG]], align 8
|
|
; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
|
|
; CHECK-NEXT: br i1 [[C_1]], label [[OUTER_BACKEDGE:%.*]], label [[INNER_PREHEADER:%.*]]
|
|
; CHECK: outer.backedge:
|
|
; CHECK-NEXT: br label [[OUTER]]
|
|
; CHECK: inner.preheader:
|
|
; CHECK-NEXT: br label [[INNER:%.*]]
|
|
; CHECK: inner:
|
|
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
|
|
; CHECK-NEXT: br i1 [[C_2]], label [[OUTER_LATCH:%.*]], label [[INNER_BB:%.*]]
|
|
; CHECK: inner.bb:
|
|
; CHECK-NEXT: [[C_3:%.*]] = call i1 @cond()
|
|
; CHECK-NEXT: br i1 [[C_3]], label [[LOOP_3_PREHEADER:%.*]], label [[INNER_LATCH:%.*]]
|
|
; CHECK: loop.3.preheader:
|
|
; CHECK-NEXT: [[L_1_LCSSA:%.*]] = phi ptr [ [[L_1]], [[INNER_BB]] ]
|
|
; CHECK-NEXT: [[L_2_LCSSA:%.*]] = phi ptr [ [[L_2]], [[INNER_BB]] ]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N:%.*]], 1
|
|
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 2
|
|
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_MEMCHECK:%.*]]
|
|
; CHECK: vector.memcheck:
|
|
; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[L_2_LCSSA]], i64 2
|
|
; CHECK-NEXT: [[SCEVGEP5:%.*]] = getelementptr i8, ptr [[L_1_LCSSA]], i64 2
|
|
; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[N]], 1
|
|
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], 4
|
|
; CHECK-NEXT: [[SCEVGEP6:%.*]] = getelementptr i8, ptr [[L_1_LCSSA]], i64 [[TMP2]]
|
|
; CHECK-NEXT: [[BOUND0:%.*]] = icmp ult ptr [[L_2_LCSSA]], [[SCEVGEP6]]
|
|
; CHECK-NEXT: [[BOUND1:%.*]] = icmp ult ptr [[SCEVGEP5]], [[SCEVGEP]]
|
|
; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]]
|
|
; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]]
|
|
; CHECK: vector.ph:
|
|
; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP0]], 2
|
|
; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP0]], [[N_MOD_VF]]
|
|
; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i16, ptr [[L_2]], i64 0
|
|
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
|
|
; CHECK: vector.body:
|
|
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[INDEX]], 0
|
|
; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i64 [[TMP3]], 1
|
|
; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i16, ptr [[L_1]], i64 [[TMP4]]
|
|
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, ptr [[TMP5]], i32 0
|
|
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i16>, ptr [[TMP6]], align 2, !alias.scope [[META0:![0-9]+]]
|
|
; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x i16> [[WIDE_LOAD]], i32 1
|
|
; CHECK-NEXT: store i16 [[TMP8]], ptr [[TMP7]], align 2, !alias.scope [[META3:![0-9]+]], !noalias [[META0]]
|
|
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
|
|
; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
|
|
; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]]
|
|
; CHECK: middle.block:
|
|
; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP0]], [[N_VEC]]
|
|
; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT_LOOPEXIT:%.*]], label [[SCALAR_PH]]
|
|
; CHECK: scalar.ph:
|
|
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[LOOP_3_PREHEADER]] ], [ 0, [[VECTOR_MEMCHECK]] ]
|
|
; CHECK-NEXT: br label [[LOOP_3:%.*]]
|
|
; CHECK: inner.latch:
|
|
; CHECK-NEXT: [[C_4:%.*]] = call i1 @cond()
|
|
; CHECK-NEXT: br i1 [[C_4]], label [[EXIT_LOOPEXIT1:%.*]], label [[INNER]]
|
|
; CHECK: outer.latch:
|
|
; CHECK-NEXT: br label [[OUTER_BACKEDGE]]
|
|
; CHECK: loop.3:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP_3]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[C_5:%.*]] = icmp ult i64 [[IV]], [[N]]
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i16, ptr [[L_1_LCSSA]], i64 [[IV_NEXT]]
|
|
; CHECK-NEXT: [[LOOP_L_1:%.*]] = load i16, ptr [[GEP_1]], align 2
|
|
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i16, ptr [[L_2_LCSSA]], i64 0
|
|
; CHECK-NEXT: store i16 [[LOOP_L_1]], ptr [[GEP_2]], align 2
|
|
; CHECK-NEXT: br i1 [[C_5]], label [[LOOP_3]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP8:![0-9]+]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
; CHECK: exit.loopexit1:
|
|
; CHECK-NEXT: [[L_1_LCSSA3:%.*]] = phi ptr [ [[L_1]], [[INNER_LATCH]] ]
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[L_14:%.*]] = phi ptr [ [[L_1_LCSSA3]], [[EXIT_LOOPEXIT1]] ], [ [[L_1_LCSSA]], [[EXIT_LOOPEXIT]] ]
|
|
; CHECK-NEXT: [[L_3:%.*]] = load i16, ptr [[L_14]], align 2
|
|
; CHECK-NEXT: ret i16 [[L_3]]
|
|
;
|
|
entry:
|
|
br label %outer
|
|
|
|
outer:
|
|
%l.1 = load ptr, ptr %arg, align 8
|
|
%l.2 = load ptr, ptr %arg, align 8
|
|
%c.1 = call i1 @cond()
|
|
br i1 %c.1, label %outer, label %inner
|
|
|
|
inner:
|
|
%c.2 = call i1 @cond()
|
|
br i1 %c.2, label %outer.latch, label %inner.bb
|
|
|
|
inner.bb:
|
|
%c.3 = call i1 @cond()
|
|
br i1 %c.3, label %loop.3, label %inner.latch
|
|
|
|
inner.latch:
|
|
%c.4 = call i1 @cond()
|
|
br i1 %c.4, label %exit, label %inner
|
|
|
|
outer.latch:
|
|
br label %outer
|
|
|
|
loop.3:
|
|
%iv = phi i64 [ %iv.next, %loop.3 ], [ 0, %inner.bb ]
|
|
%iv.next = add nsw nuw i64 %iv, 1
|
|
%c.5 = icmp ult i64 %iv, %N
|
|
%gep.1 = getelementptr inbounds i16, ptr %l.1, i64 %iv.next
|
|
%loop.l.1 = load i16, ptr %gep.1, align 2
|
|
%gep.2 = getelementptr inbounds i16, ptr %l.2, i64 0
|
|
store i16 %loop.l.1, ptr %gep.2 , align 2
|
|
br i1 %c.5, label %loop.3, label %exit
|
|
|
|
exit:
|
|
%l.3 = load i16, ptr %l.1, align 2
|
|
ret i16 %l.3
|
|
}
|
|
|
|
define void @test2(ptr %dst) {
|
|
; CHECK-LABEL: @test2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP_1_HEADER:%.*]]
|
|
; CHECK: loop.1.header:
|
|
; CHECK-NEXT: br label [[LOOP_2:%.*]]
|
|
; CHECK: loop.2:
|
|
; CHECK-NEXT: [[INDVAR:%.*]] = phi i32 [ [[INDVAR_NEXT:%.*]], [[LOOP_2]] ], [ 0, [[LOOP_1_HEADER]] ]
|
|
; CHECK-NEXT: [[IV_1:%.*]] = phi i64 [ 1000, [[LOOP_1_HEADER]] ], [ [[IV_1_NEXT:%.*]], [[LOOP_2]] ]
|
|
; CHECK-NEXT: [[IV_1_NEXT]] = add i64 [[IV_1]], -1
|
|
; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
|
|
; CHECK-NEXT: [[INDVAR_NEXT]] = add i32 [[INDVAR]], 1
|
|
; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_2]], label [[LOOP_3_PH:%.*]]
|
|
; CHECK: loop.3.ph:
|
|
; CHECK-NEXT: [[INDVAR_LCSSA:%.*]] = phi i32 [ [[INDVAR]], [[LOOP_2]] ]
|
|
; CHECK-NEXT: [[IV_1_LCSSA:%.*]] = phi i64 [ [[IV_1]], [[LOOP_2]] ]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = and i64 [[IV_1_LCSSA]], 4294967295
|
|
; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[INDVAR_LCSSA]], -1
|
|
; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1000
|
|
; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[TMP2]], i32 1)
|
|
; CHECK-NEXT: [[TMP3:%.*]] = sub i32 [[TMP2]], [[SMIN]]
|
|
; CHECK-NEXT: [[TMP4:%.*]] = zext i32 [[TMP3]] to i64
|
|
; CHECK-NEXT: [[TMP5:%.*]] = add nuw nsw i64 [[TMP4]], 1
|
|
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP5]], 2
|
|
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
|
|
; CHECK: vector.ph:
|
|
; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP5]], 2
|
|
; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP5]], [[N_MOD_VF]]
|
|
; CHECK-NEXT: [[IND_END:%.*]] = sub i64 [[TMP0]], [[N_VEC]]
|
|
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
|
|
; CHECK: vector.body:
|
|
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
|
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = sub i64 [[TMP0]], [[INDEX]]
|
|
; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[OFFSET_IDX]], 0
|
|
; CHECK-NEXT: [[TMP7:%.*]] = add nsw i64 [[TMP6]], -1
|
|
; CHECK-NEXT: [[TMP8:%.*]] = and i64 [[TMP7]], 4294967295
|
|
; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i64 [[TMP8]]
|
|
; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i32, ptr [[TMP9]], i32 0
|
|
; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds i32, ptr [[TMP10]], i32 -1
|
|
; CHECK-NEXT: store <2 x i32> zeroinitializer, ptr [[TMP11]], align 4
|
|
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
|
|
; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
|
|
; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP9:![0-9]+]]
|
|
; CHECK: middle.block:
|
|
; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP5]], [[N_VEC]]
|
|
; CHECK-NEXT: br i1 [[CMP_N]], label [[LOOP_1_LATCH:%.*]], label [[SCALAR_PH]]
|
|
; CHECK: scalar.ph:
|
|
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ [[TMP0]], [[LOOP_3_PH]] ]
|
|
; CHECK-NEXT: br label [[LOOP_3:%.*]]
|
|
; CHECK: loop.3:
|
|
; CHECK-NEXT: [[IV_2:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_2_NEXT:%.*]], [[LOOP_3]] ]
|
|
; CHECK-NEXT: [[IV_2_NEXT]] = add nsw i64 [[IV_2]], -1
|
|
; CHECK-NEXT: [[AND_IV:%.*]] = and i64 [[IV_2_NEXT]], 4294967295
|
|
; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[AND_IV]]
|
|
; CHECK-NEXT: store i32 0, ptr [[GEP_DST]], align 4
|
|
; CHECK-NEXT: [[IV_2_TRUNC:%.*]] = trunc i64 [[IV_2]] to i32
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp sgt i32 [[IV_2_TRUNC]], 1
|
|
; CHECK-NEXT: br i1 [[EC]], label [[LOOP_3]], label [[LOOP_1_LATCH]], !llvm.loop [[LOOP10:![0-9]+]]
|
|
; CHECK: loop.1.latch:
|
|
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
|
|
; CHECK-NEXT: br i1 [[C_2]], label [[EXIT:%.*]], label [[LOOP_1_HEADER]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %loop.1.header
|
|
|
|
loop.1.header:
|
|
br label %loop.2
|
|
|
|
loop.2:
|
|
%iv.1 = phi i64 [ 1000, %loop.1.header ], [ %iv.1.next, %loop.2 ]
|
|
%iv.1.next = add i64 %iv.1, -1
|
|
%c.1 = call i1 @cond()
|
|
br i1 %c.1, label %loop.2, label %loop.3.ph
|
|
|
|
loop.3.ph:
|
|
%iv.1.lcssa = phi i64 [ %iv.1, %loop.2 ]
|
|
%0 = and i64 %iv.1.lcssa, 4294967295
|
|
br label %loop.3
|
|
|
|
loop.3:
|
|
%iv.2 = phi i64 [ %0, %loop.3.ph ], [ %iv.2.next, %loop.3 ]
|
|
%iv.2.next = add nsw i64 %iv.2, -1
|
|
%and.iv = and i64 %iv.2.next, 4294967295
|
|
%gep.dst = getelementptr inbounds i32, ptr %dst, i64 %and.iv
|
|
store i32 0, ptr %gep.dst, align 4
|
|
%iv.2.trunc = trunc i64 %iv.2 to i32
|
|
%ec = icmp sgt i32 %iv.2.trunc, 1
|
|
br i1 %ec, label %loop.3, label %loop.1.latch
|
|
|
|
loop.1.latch:
|
|
%c.2 = call i1 @cond()
|
|
br i1 %c.2, label %exit, label %loop.1.header
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
declare i1 @cond()
|