diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index abac45b265d10..8d47ddb53cce4 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -7356,8 +7356,10 @@ static void fixReductionScalarResumeWhenVectorizingEpilog( VPlanPatternMatch::m_Select(VPlanPatternMatch::m_VPValue(), VPlanPatternMatch::m_VPValue(BackedgeVal), VPlanPatternMatch::m_VPValue())); - EpiRedHeaderPhi = cast( + EpiRedHeaderPhi = cast_if_present( vputils::findRecipe(BackedgeVal, IsaPred)); + if (!EpiRedHeaderPhi) + return; } Value *MainResumeValue; @@ -9361,12 +9363,22 @@ static void fixScalarResumeValuesFromBypass(BasicBlock *BypassBlock, Loop *L, // Fix induction resume values from the additional bypass block. IRBuilder<> BypassBuilder(BypassBlock, BypassBlock->getFirstInsertionPt()); for (const auto &[IVPhi, II] : LVL.getInductionVars()) { - auto *Inc = cast(IVPhi->getIncomingValueForBlock(PH)); + Value *IncomingFromPH = IVPhi->getIncomingValueForBlock(PH); Value *V = createInductionAdditionalBypassValues( IVPhi, II, BypassBuilder, ExpandedSCEVs, MainVectorTripCount, LVL.getPrimaryInduction()); - // TODO: Directly add as extra operand to the VPResumePHI recipe. - Inc->setIncomingValueForBlock(BypassBlock, V); + + if (auto *Inc = dyn_cast(IncomingFromPH)) { + // TODO: Directly add as extra operand to the VPResumePHI recipe. + Inc->setIncomingValueForBlock(BypassBlock, V); + } else { + // If the incoming value from preheader is not a PHI node (e.g., a + // constant in functions with GC statepoint), directly add an incoming + // value from BypassBlock to IVPhi. The incoming value from PH remains + // unchanged (IncomingFromPH). + if (IVPhi->getBasicBlockIndex(BypassBlock) == -1) + IVPhi->addIncoming(V, BypassBlock); + } } } diff --git a/llvm/test/Transforms/LoopVectorize/pr179407-gc-statepoint.ll b/llvm/test/Transforms/LoopVectorize/pr179407-gc-statepoint.ll new file mode 100644 index 0000000000000..a2c33b3f1a702 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/pr179407-gc-statepoint.ll @@ -0,0 +1,40 @@ +; RUN: opt -passes=loop-vectorize -enable-epilogue-vectorization -force-vector-width=2 -epilogue-vectorization-force-VF=2 -S < %s | FileCheck %s +; +; Test case for issue #179407: LoopVectorize should not crash when +; vectorizing loops in functions with GC statepoint. +; +; The issue was that fixScalarResumeValuesFromBypass assumed +; IVPhi->getIncomingValueForBlock(PH) always returns a PHINode, but in +; functions with GC statepoint, it could return a constant or other value. +; +; This test verifies that epilogue vectorization works correctly with +; GC statepoint by checking that the loop is vectorized and the +; bypass blocks are properly created. + +; CHECK: define void @wombat +; CHECK-SAME: gc "statepoint-example" +; CHECK: vector.body: +; CHECK: vec.epilog.vector.body: +; CHECK: vec.epilog.scalar.ph: +; CHECK: bb1: + +define void @wombat(i64 %arg) gc "statepoint-example" { +bb: + br label %bb1 + +bb1: ; preds = %bb1, %bb + %phi = phi i64 [ 0, %bb ], [ %add, %bb1 ] + %phi2 = phi i32 [ 0, %bb ], [ %or, %bb1 ] + %phi3 = phi i32 [ 0, %bb ], [ %select, %bb1 ] + %icmp = icmp eq i32 0, 0 + %select = select i1 %icmp, i32 0, i32 %phi3 + %or = or i32 %phi2, 0 + %add = add i64 %phi, 1 + %icmp4 = icmp ult i64 %phi, %arg + br i1 %icmp4, label %bb1, label %bb5 + +bb5: ; preds = %bb1 + %phi6 = phi i32 [ %select, %bb1 ] + %phi7 = phi i32 [ %or, %bb1 ] + ret void +}