[llvm] 47215e1 - [LV] Fix crash when target instruction for sinking is dead.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 29 05:35:23 PDT 2021
Author: Florian Hahn
Date: 2021-06-29T13:31:22+01:00
New Revision: 47215e1c6250298aa9db59b3b06f832fcd23be01
URL: https://github.com/llvm/llvm-project/commit/47215e1c6250298aa9db59b3b06f832fcd23be01
DIFF: https://github.com/llvm/llvm-project/commit/47215e1c6250298aa9db59b3b06f832fcd23be01.diff
LOG: [LV] Fix crash when target instruction for sinking is dead.
This patch fixes a crash when the target instruction for sinking is
dead. In that case, no recipe is created and trying to get the recipe
for it results in a crash. To ensure all sink targets are alive, find &
use the first previous alive instruction.
Note that the case where the sink source is dead is already handled.
Found by
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35320
Reviewed By: Ayal
Differential Revision: https://reviews.llvm.org/D104603
Added:
Modified:
llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
llvm/test/Transforms/LoopVectorize/first-order-recurrence.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index f22e73719a99..bb0cb5e6ba6d 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -9040,6 +9040,24 @@ void LoopVectorizationPlanner::buildVPlansWithVPRecipes(ElementCount MinVF,
for (Instruction *I : DeadInstructions)
SinkAfter.erase(I);
+ // Cannot sink instructions after dead instructions (there won't be any
+ // recipes for them). Instead, find the first non-dead previous instruction.
+ for (auto &P : Legal->getSinkAfter()) {
+ Instruction *SinkTarget = P.second;
+ Instruction *FirstInst = &*SinkTarget->getParent()->begin();
+ (void)FirstInst;
+ while (DeadInstructions.contains(SinkTarget)) {
+ assert(
+ SinkTarget != FirstInst &&
+ "Must find a live instruction (at least the one feeding the "
+ "first-order recurrence PHI) before reaching beginning of the block");
+ SinkTarget = SinkTarget->getPrevNode();
+ assert(SinkTarget != P.first &&
+ "sink source equals target, no sinking required");
+ }
+ P.second = SinkTarget;
+ }
+
auto MaxVFPlusOne = MaxVF.getWithIncrement(1);
for (ElementCount VF = MinVF; ElementCount::isKnownLT(VF, MaxVFPlusOne);) {
VFRange SubRange = {VF, MaxVFPlusOne};
diff --git a/llvm/test/Transforms/LoopVectorize/first-order-recurrence.ll b/llvm/test/Transforms/LoopVectorize/first-order-recurrence.ll
index 1389d28d382e..dac449440069 100644
--- a/llvm/test/Transforms/LoopVectorize/first-order-recurrence.ll
+++ b/llvm/test/Transforms/LoopVectorize/first-order-recurrence.ll
@@ -895,4 +895,43 @@ bb:
br i1 %tmp9, label %bb1, label %bb2, !prof !2
}
+; %vec.dead will be marked as dead instruction in the vector loop and no recipe
+; will be created for it. Make sure a valid sink target is used.
+define void @sink_after_dead_inst(i32* %A.ptr) {
+; CHECK-LABEL: @sink_after_dead_inst
+; CHECK-LABEL: vector.body:
+; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %vector.ph ], [ [[INDEX_NEXT]], %vector.body ]
+; CHECK-NEXT: [[OFFSET_IDX:%.*]] = zext i32 [[INDEX]] to i64
+; CHECK-NEXT: [[SEXT:%.*]] = shl i64 [[OFFSET_IDX]], 48
+; CHECK-NEXT: [[SHIFT:%.*]] = ashr exact i64 [[SEXT]], 48
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, i32* %A.ptr, i64 [[SHIFT]]
+; CHECK-NEXT: [[CAST:%.*]] = bitcast i32* [[GEP]] to <4 x i32>*
+; CHECK-NEXT: store <4 x i32> zeroinitializer, <4 x i32>* [[CAST]], align 4
+; CHECK-NEXT: [[INDEX_NEXT:%.*]] = add nuw i32 [[INDEX]], 4
+; CHECK-NEXT: [[EC:%.*]] = icmp eq i32 [[INDEX_NEXT]], 16
+; CHECK-NEXT: br i1 [[EC]], label %middle.block, label %vector.body
+
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i16 [ 0, %entry ], [ %iv.next, %loop ]
+ %for = phi i32 [ 0, %entry ], [ %for.prev, %loop ]
+ %cmp = icmp eq i32 %for, 15
+ %C = icmp eq i1 %cmp, true
+ %vec.dead = and i1 %C, 1
+ %iv.next = add i16 %iv, 1
+ %B1 = or i16 %iv.next, %iv.next
+ %B3 = and i1 %cmp, %C
+ %for.prev = zext i16 %B1 to i32
+
+ %ext = zext i1 %B3 to i32
+ %A.gep = getelementptr i32, i32* %A.ptr, i16 %iv
+ store i32 0, i32* %A.gep
+ br i1 %vec.dead, label %for.end, label %loop
+
+for.end:
+ ret void
+}
+
!2 = !{!"branch_weights", i32 1, i32 1}
More information about the llvm-commits
mailing list