@@ -1468,10 +1468,9 @@ InstructionCost VPWidenCastRecipe::computeCost(ElementCount VF,
14681468 ToVectorTy (Ctx.Types .inferScalarType (getOperand (0 )), VF));
14691469 auto *DestTy = cast<VectorType>(ToVectorTy (getResultType (), VF));
14701470 // Computes the CastContextHint from a VPWidenMemoryRecipe instruction.
1471- auto ComputeCCH = [&](VPWidenMemoryRecipe *R) -> TTI::CastContextHint {
1471+ auto ComputeCCH = [&](const VPWidenMemoryRecipe *R) -> TTI::CastContextHint {
14721472 assert ((isa<VPWidenLoadRecipe>(R) || isa<VPWidenStoreRecipe>(R)) &&
14731473 " Expected a load or a store!" );
1474-
14751474 if (VF.isScalar ())
14761475 return TTI::CastContextHint::Normal;
14771476 if (!R->isConsecutive ())
@@ -1485,19 +1484,31 @@ InstructionCost VPWidenCastRecipe::computeCost(ElementCount VF,
14851484
14861485 TTI::CastContextHint CCH = TTI::CastContextHint::None;
14871486 // For Trunc, the context is the only user, which must be a
1488- // VPWidenStoreRecipe.
1489- if (Opcode == Instruction::Trunc || Opcode == Instruction::FPTrunc) {
1490- if (!cast<VPValue>(this )->hasMoreThanOneUniqueUser ())
1491- if (VPWidenMemoryRecipe *Store =
1492- dyn_cast<VPWidenMemoryRecipe>(*this ->user_begin ()))
1493- CCH = ComputeCCH (Store);
1494- }
1495- // For Z/Sext, the context is the operand, which must be a VPWidenLoadRecipe.
1487+ // VPWidenStoreRecipe, a VPInterleaveRecipe ,a VPReplicateRecipe or a live-out
1488+ // value.
1489+ if ((Opcode == Instruction::Trunc || Opcode == Instruction::FPTrunc) &&
1490+ !hasMoreThanOneUniqueUser () && getNumUsers () > 0 ) {
1491+ auto *StoreRecipe = dyn_cast<VPRecipeBase>(*user_begin ());
1492+ if (isa<VPLiveOut>(*user_begin ()) || isa<VPReplicateRecipe>(StoreRecipe))
1493+ 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;
1499+ }
1500+ // For Z/Sext, the context is the operand, which must be a VPWidenLoadRecipe,
1501+ // a VPInterleaveRecipe, a VPReplicateRecipe or a live-in value.
14961502 else if (Opcode == Instruction::ZExt || Opcode == Instruction::SExt ||
14971503 Opcode == Instruction::FPExt) {
1498- if (VPWidenMemoryRecipe *Load = dyn_cast<VPWidenMemoryRecipe>(
1499- this ->getOperand (0 )->getDefiningRecipe ()))
1500- CCH = ComputeCCH (Load);
1504+ const VPRecipeBase *LoadRecipe = getOperand (0 )->getDefiningRecipe ();
1505+ if (getOperand (0 )->isLiveIn () || isa<VPReplicateRecipe>(LoadRecipe))
1506+ 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;
15011512 }
15021513 // Arm TTI will use the underlying instruction to determine the cost.
15031514 return Ctx.TTI .getCastInstrCost (
0 commit comments