diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp index 3c367664a0988..fc918c669df12 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -296,24 +296,32 @@ bool VPRecipeBase::isScalarCast() const { InstructionCost VPPartialReductionRecipe::computeCost(ElementCount VF, VPCostContext &Ctx) const { + // ----------------------------------------------------------------------- + // Helpers that treat an ilist *sentinel* exactly like `nullptr`. + // ----------------------------------------------------------------------- + auto safe = [](VPRecipeBase *R) -> VPRecipeBase * { + return isa_and_present(R) ? R : nullptr; + }; + std::optional Opcode; - VPValue *Op = getOperand(0); - VPRecipeBase *OpR = Op->getDefiningRecipe(); + VPValue *Op = getOperand(0); + VPRecipeBase *OpR = safe(Op->getDefiningRecipe()); // If the partial reduction is predicated, a select will be operand 0 using namespace llvm::VPlanPatternMatch; if (match(getOperand(1), m_Select(m_VPValue(), m_VPValue(Op), m_VPValue()))) { - OpR = Op->getDefiningRecipe(); + OpR = safe(Op->getDefiningRecipe()); } Type *InputTypeA = nullptr, *InputTypeB = nullptr; TTI::PartialReductionExtendKind ExtAType = TTI::PR_None, ExtBType = TTI::PR_None; - auto GetExtendKind = [](VPRecipeBase *R) { + auto GetExtendKind = [&](VPRecipeBase *R) { + R = safe(R); if (!R) return TTI::PR_None; - auto *WidenCastR = dyn_cast(R); + auto *WidenCastR = dyn_cast_if_present(R); if (!WidenCastR) return TTI::PR_None; if (WidenCastR->getOpcode() == Instruction::CastOps::ZExt) @@ -328,11 +336,11 @@ VPPartialReductionRecipe::computeCost(ElementCount VF, auto HandleWiden = [&](VPWidenRecipe *Widen) { if (match(Widen, m_Binary(m_SpecificInt(0), m_VPValue(Op)))) { - Widen = dyn_cast(Op->getDefiningRecipe()); + Widen = dyn_cast_if_present(safe(Op->getDefiningRecipe())); } Opcode = Widen->getOpcode(); - VPRecipeBase *ExtAR = Widen->getOperand(0)->getDefiningRecipe(); - VPRecipeBase *ExtBR = Widen->getOperand(1)->getDefiningRecipe(); + VPRecipeBase *ExtAR = safe(Widen->getOperand(0)->getDefiningRecipe()); + VPRecipeBase *ExtBR = safe(Widen->getOperand(1)->getDefiningRecipe()); InputTypeA = Ctx.Types.inferScalarType(ExtAR ? ExtAR->getOperand(0) : Widen->getOperand(0)); InputTypeB = Ctx.Types.inferScalarType(ExtBR ? ExtBR->getOperand(0) @@ -341,7 +349,7 @@ VPPartialReductionRecipe::computeCost(ElementCount VF, ExtBType = GetExtendKind(ExtBR); }; - if (isa(OpR)) { + if (isa_and_present(OpR)) { InputTypeA = Ctx.Types.inferScalarType(OpR->getOperand(0)); ExtAType = GetExtendKind(OpR); } else if (isa(OpR)) { @@ -351,9 +359,9 @@ VPPartialReductionRecipe::computeCost(ElementCount VF, ExtAType = GetExtendKind(RedPhiOp1R); } else if (auto Widen = dyn_cast(RedPhiOp1R)) HandleWiden(Widen); - } else if (auto Widen = dyn_cast(OpR)) { + } else if (auto Widen = dyn_cast_if_present(OpR)) { HandleWiden(Widen); - } else if (auto Reduction = dyn_cast(OpR)) { + } else if (auto Reduction = dyn_cast_if_present(OpR)) { return Reduction->computeCost(VF, Ctx); } auto *PhiType = Ctx.Types.inferScalarType(getOperand(1)); diff --git a/llvm/test/Transforms/LoopVectorize/PR148389-sentinel.ll b/llvm/test/Transforms/LoopVectorize/PR148389-sentinel.ll new file mode 100644 index 0000000000000..d0c7392302275 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/PR148389-sentinel.ll @@ -0,0 +1,27 @@ +; RUN: opt -passes=loop-vectorize -mcpu=grace -S %s -o /dev/null +; REQUIRES: aarch64-registered-target + +; Reduced from GitHub issue #148389. +; The test just needs to run – if the pass crashes the test will fail. + +define void @h(ptr %e, ptr %f, i8 %d) { +entry: + br label %body +body: + %i = phi i16 [0, %entry], [%inc, %latch] + %idx = sext i16 %i to i64 + %eelt = getelementptr [1 x i16], ptr %e, i64 %idx, i64 %idx + %eval = load i16, ptr %eelt + %felt = getelementptr [7 x i8], ptr %f, i64 %idx, i64 %idx + %fval = load i8, ptr %felt + %cmp = icmp eq i8 %d, 0 + br i1 %cmp, label %update, label %latch +update: + br label %latch +latch: + %inc = add nuw nsw i16 %i, 1 + %exit = icmp eq i16 %inc, 17 + br i1 %exit, label %exit.block, label %body +exit.block: + ret void +}