@@ -1467,17 +1467,23 @@ InstructionCost VPWidenCastRecipe::computeCost(ElementCount VF,
14671467 auto *SrcTy = cast<VectorType>(
14681468 ToVectorTy (Ctx.Types .inferScalarType (getOperand (0 )), VF));
14691469 auto *DestTy = cast<VectorType>(ToVectorTy (getResultType (), VF));
1470- // Computes the CastContextHint from a VPWidenMemoryRecipe instruction.
1471- auto ComputeCCH = [&](const VPWidenMemoryRecipe *R) -> TTI::CastContextHint {
1472- assert ((isa<VPWidenLoadRecipe>(R) || isa<VPWidenStoreRecipe>(R)) &&
1473- " Expected a load or a store!" );
1470+ // Computes the CastContextHint from a recipes that may access memory.
1471+ auto ComputeCCH = [&](const VPRecipeBase *R) -> TTI::CastContextHint {
14741472 if (VF.isScalar ())
14751473 return TTI::CastContextHint::Normal;
1476- if (!R->isConsecutive ())
1474+ if (isa<VPInterleaveRecipe>(R))
1475+ return TTI::CastContextHint::Interleave;
1476+ if (const auto *ReplicateRecipe = dyn_cast<VPReplicateRecipe>(R))
1477+ return ReplicateRecipe->isPredicated () ? TTI::CastContextHint::Masked
1478+ : TTI::CastContextHint::Normal;
1479+ const auto *WidenMemoryRecipe = dyn_cast<VPWidenMemoryRecipe>(R);
1480+ if (WidenMemoryRecipe == nullptr )
1481+ return TTI::CastContextHint::None;
1482+ if (!WidenMemoryRecipe->isConsecutive ())
14771483 return TTI::CastContextHint::GatherScatter;
1478- if (R ->isReverse ())
1484+ if (WidenMemoryRecipe ->isReverse ())
14791485 return TTI::CastContextHint::Reversed;
1480- if (R ->isMasked ())
1486+ if (WidenMemoryRecipe ->isMasked ())
14811487 return TTI::CastContextHint::Masked;
14821488 return TTI::CastContextHint::Normal;
14831489 };
@@ -1489,26 +1495,20 @@ InstructionCost VPWidenCastRecipe::computeCost(ElementCount VF,
14891495 if ((Opcode == Instruction::Trunc || Opcode == Instruction::FPTrunc) &&
14901496 !hasMoreThanOneUniqueUser () && getNumUsers () > 0 ) {
14911497 auto *StoreRecipe = dyn_cast<VPRecipeBase>(*user_begin ());
1492- if (isa<VPLiveOut>(*user_begin ()) || isa<VPReplicateRecipe>(StoreRecipe) )
1498+ if (isa<VPLiveOut>(*user_begin ()))
14931499 CCH = TTI::CastContextHint::Normal;
1494- else if (const VPWidenMemoryRecipe *MemoryStoreRecipe =
1495- dyn_cast<VPWidenMemoryRecipe>(StoreRecipe))
1496- CCH = ComputeCCH (MemoryStoreRecipe);
1497- else if (isa<VPInterleaveRecipe>(StoreRecipe))
1498- CCH = TTI::CastContextHint::Interleave;
1500+ else if (StoreRecipe)
1501+ CCH = ComputeCCH (StoreRecipe);
14991502 }
15001503 // For Z/Sext, the context is the operand, which must be a VPWidenLoadRecipe,
15011504 // a VPInterleaveRecipe, a VPReplicateRecipe or a live-in value.
15021505 else if (Opcode == Instruction::ZExt || Opcode == Instruction::SExt ||
15031506 Opcode == Instruction::FPExt) {
15041507 const VPRecipeBase *LoadRecipe = getOperand (0 )->getDefiningRecipe ();
1505- if (getOperand (0 )->isLiveIn () || isa<VPReplicateRecipe>(LoadRecipe) )
1508+ if (getOperand (0 )->isLiveIn ())
15061509 CCH = TTI::CastContextHint::Normal;
1507- else if (const VPWidenMemoryRecipe *MemoryLoadRecipe =
1508- dyn_cast<VPWidenMemoryRecipe>(LoadRecipe))
1509- CCH = ComputeCCH (MemoryLoadRecipe);
1510- else if (isa<VPInterleaveRecipe>(LoadRecipe))
1511- CCH = TTI::CastContextHint::Interleave;
1510+ else if (LoadRecipe)
1511+ CCH = ComputeCCH (LoadRecipe);
15121512 }
15131513 // Arm TTI will use the underlying instruction to determine the cost.
15141514 return Ctx.TTI .getCastInstrCost (
0 commit comments