Skip to content

Commit

Permalink
[LV] Set SCEVCheckCond to nullptr whenever it was used.
Browse files Browse the repository at this point in the history
Under some circumstances, SCEVExpander will insert new instructions when
expanding a predicate, but the final result of the expansion can be a
false constant.

In those cases, the expanded instructions may later be used by other
expansions, e.g. the trip count. This may trigger an assertion during
SCEVExpander cleanup. To avoid this, always mark the result as used.

Fixes #55100.
  • Loading branch information
fhahn committed May 15, 2022
1 parent 896557e commit 8b7c3d2
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 6 deletions.
13 changes: 7 additions & 6 deletions llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
Expand Up @@ -2072,7 +2072,11 @@ class GeneratedRTChecks {
BasicBlock *LoopExitBlock) {
if (!SCEVCheckCond)
return nullptr;
if (auto *C = dyn_cast<ConstantInt>(SCEVCheckCond))

Value *Cond = SCEVCheckCond;
// Mark the check as used, to prevent it from being removed during cleanup.
SCEVCheckCond = nullptr;
if (auto *C = dyn_cast<ConstantInt>(Cond))
if (C->isZero())
return nullptr;

Expand All @@ -2091,11 +2095,8 @@ class GeneratedRTChecks {
DT->addNewBlock(SCEVCheckBlock, Pred);
DT->changeImmediateDominator(LoopVectorPreHeader, SCEVCheckBlock);

ReplaceInstWithInst(
SCEVCheckBlock->getTerminator(),
BranchInst::Create(Bypass, LoopVectorPreHeader, SCEVCheckCond));
// Mark the check as used, to prevent it from being removed during cleanup.
SCEVCheckCond = nullptr;
ReplaceInstWithInst(SCEVCheckBlock->getTerminator(),
BranchInst::Create(Bypass, LoopVectorPreHeader, Cond));
return SCEVCheckBlock;
}

Expand Down
@@ -0,0 +1,96 @@
; 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

define void @test_pr55100(i32 %N) {
; CHECK-LABEL: @test_pr55100(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = sub i32 0, [[N:%.*]]
; CHECK-NEXT: br label [[LOOP_1_HEADER:%.*]]
; CHECK: loop.1.header:
; CHECK-NEXT: [[IV_1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_1_NEXT:%.*]], [[LOOP_1_LATCH:%.*]] ]
; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i32 [[IV_1]], -1
; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP0]], [[TMP1]]
; CHECK-NEXT: [[UMIN2:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP2]], i32 18)
; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i32 [[UMIN2]], 1
; CHECK-NEXT: [[TMP4:%.*]] = mul nuw nsw i32 [[IV_1]], -1
; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[TMP0]], [[TMP4]]
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP5]], i32 18)
; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[IV_1]], 10
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2_HEADER_PREHEADER:%.*]], label [[EXIT_LOOPEXIT1:%.*]]
; CHECK: loop.2.header.preheader:
; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i32 [[TMP3]], 2
; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
; CHECK: vector.ph:
; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP3]], 2
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[N_MOD_VF]], 0
; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP6]], i32 2, i32 [[N_MOD_VF]]
; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP3]], [[TMP7]]
; CHECK-NEXT: [[IND_END:%.*]] = trunc i32 [[N_VEC]] to i16
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
; CHECK: vector.body:
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
; CHECK-NEXT: [[OFFSET_IDX:%.*]] = trunc i32 [[INDEX]] to i16
; CHECK-NEXT: [[TMP8:%.*]] = add i16 [[OFFSET_IDX]], 0
; CHECK-NEXT: [[TMP9:%.*]] = add i32 [[N]], [[IV_1]]
; CHECK-NEXT: [[TMP10:%.*]] = sext i16 [[TMP8]] to i32
; CHECK-NEXT: [[TMP11:%.*]] = add i32 [[TMP9]], [[TMP10]]
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
; CHECK: middle.block:
; CHECK-NEXT: br label [[SCALAR_PH]]
; CHECK: scalar.ph:
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i16 [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ 0, [[LOOP_2_HEADER_PREHEADER]] ]
; CHECK-NEXT: br label [[LOOP_2_HEADER:%.*]]
; CHECK: vector.scevcheck:
; CHECK-NEXT: [[TMP13:%.*]] = trunc i32 [[UMIN]] to i16
; CHECK-NEXT: unreachable
; CHECK: loop.2.header:
; CHECK-NEXT: [[IV_2:%.*]] = phi i16 [ [[IV_2_NEXT:%.*]], [[LOOP_2_LATCH:%.*]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ]
; CHECK-NEXT: [[C_3:%.*]] = icmp slt i16 [[IV_2]], 18
; CHECK-NEXT: br i1 [[C_3]], label [[LOOP_2_LATCH]], label [[LOOP_1_LATCH]]
; CHECK: loop.2.latch:
; CHECK-NEXT: [[ADD_1:%.*]] = add i32 [[N]], [[IV_1]]
; CHECK-NEXT: [[IV_2_EXT:%.*]] = sext i16 [[IV_2]] to i32
; CHECK-NEXT: [[ADD_2:%.*]] = add i32 [[ADD_1]], [[IV_2_EXT]]
; CHECK-NEXT: [[C_4:%.*]] = icmp ult i32 [[ADD_2]], 1
; CHECK-NEXT: [[IV_2_NEXT]] = add i16 [[IV_2]], 1
; CHECK-NEXT: br i1 [[C_4]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_2_HEADER]], !llvm.loop [[LOOP2:![0-9]+]]
; CHECK: loop.1.latch:
; CHECK-NEXT: [[IV_1_NEXT]] = add i32 [[IV_1]], 1
; CHECK-NEXT: br label [[LOOP_1_HEADER]]
; CHECK: exit.loopexit:
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: exit.loopexit1:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
br label %loop.1.header

loop.1.header:
%iv.1 = phi i32 [ 0, %entry ], [ %iv.1.next, %loop.1.latch ]
%c.2 = icmp ugt i32 %iv.1, 10
br i1 %c.2, label %loop.2.header, label %exit

loop.2.header:
%iv.2 = phi i16 [ 0, %loop.1.header ], [ %iv.2.next, %loop.2.latch ]
%c.3 = icmp slt i16 %iv.2, 18
br i1 %c.3, label %loop.2.latch, label %loop.1.latch

loop.2.latch:
%add.1 = add i32 %N, %iv.1
%iv.2.ext = sext i16 %iv.2 to i32
%add.2 = add i32 %add.1, %iv.2.ext
%c.4 = icmp ult i32 %add.2, 1
%iv.2.next = add i16 %iv.2, 1
br i1 %c.4, label %exit, label %loop.2.header

loop.1.latch:
%iv.1.next = add i32 %iv.1, 1
br label %loop.1.header

exit:
ret void
}

0 comments on commit 8b7c3d2

Please sign in to comment.