[llvm] 969f641 - [VPlan] Replace VPTypeAnalysis with VPValue::getScalarType. (NFC) (#200256)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 2 03:04:36 PDT 2026


Author: Florian Hahn
Date: 2026-06-02T10:04:30Z
New Revision: 969f6415b69cce63e98c19a03e8940b89cd8b285

URL: https://github.com/llvm/llvm-project/commit/969f6415b69cce63e98c19a03e8940b89cd8b285
DIFF: https://github.com/llvm/llvm-project/commit/969f6415b69cce63e98c19a03e8940b89cd8b285.diff

LOG: [VPlan] Replace VPTypeAnalysis with VPValue::getScalarType. (NFC) (#200256)

Now that all VPValues have their scalar type set at construction,
replace calls to VPTypeAnalysis::inferScalarType with direct calls to
VPValue::getScalarType, and remove the no-longer-needed VPTypeAnalysis
members from VPCostContext and VPTransformState. Also remove the
getScalarTypeOrInfer fallback helper.

Depends on https://github.com/llvm/llvm-project/pull/200255 

PR: https://github.com/llvm/llvm-project/pull/200256

Added: 
    

Modified: 
    llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
    llvm/lib/Transforms/Vectorize/VPlan.cpp
    llvm/lib/Transforms/Vectorize/VPlan.h
    llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
    llvm/lib/Transforms/Vectorize/VPlanAnalysis.h
    llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
    llvm/lib/Transforms/Vectorize/VPlanHelpers.h
    llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
    llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
    llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
    llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
    llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
    llvm/test/Transforms/LoopVectorize/RISCV/type-info-cache-evl-crash.ll
    llvm/test/Transforms/LoopVectorize/vplan-incomplete-cases.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 0c022ff47033b..7fad3cd78ad57 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -3262,7 +3262,6 @@ void LoopVectorizationPlanner::emitInvalidCostRemarks(
 static bool willGenerateVectors(VPlan &Plan, ElementCount VF,
                                 const TargetTransformInfo &TTI) {
   assert(VF.isVector() && "Checking a scalar VF?");
-  VPTypeAnalysis TypeInfo(Plan);
   DenseSet<VPRecipeBase *> EphemeralRecipes;
   collectEphemeralRecipesForVPlan(Plan, EphemeralRecipes);
   // Set of already visited types.
@@ -3342,7 +3341,7 @@ static bool willGenerateVectors(VPlan &Plan, ElementCount VF,
       // operand.
       VPValue *ToCheck =
           R.getNumDefinedValues() >= 1 ? R.getVPValue(0) : R.getOperand(1);
-      Type *ScalarTy = TypeInfo.inferScalarType(ToCheck);
+      Type *ScalarTy = ToCheck->getScalarType();
       if (!Visited.insert({ScalarTy}).second)
         continue;
       Type *WideTy = toVectorizedTy(ScalarTy, VF);
@@ -6029,8 +6028,7 @@ DenseMap<const SCEV *, Value *> LoopVectorizationPlanner::executePlan(
 
   // Perform the actual loop transformation.
   VPTransformState State(&TTI, BestVF, LI, DT, ILV.AC, ILV.Builder, &BestVPlan,
-                         OrigLoop->getParentLoop(),
-                         Legal->getWidestInductionType());
+                         OrigLoop->getParentLoop());
 
 #ifdef EXPENSIVE_CHECKS
   assert(DT->verify(DominatorTree::VerificationLevel::Fast));
@@ -6843,8 +6841,6 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlan(VPlanPtr Plan,
   // TODO: Enable following transform when the EVL-version of extended-reduction
   // and mulacc-reduction are implemented.
   if (!CM.foldTailWithEVL()) {
-    VPCostContext CostCtx(CM.TTI, *CM.TLI, *Plan, CM, Config.CostKind, CM.PSE,
-                          OrigLoop);
     RUN_VPLAN_PASS(VPlanTransforms::createPartialReductions, *Plan, CostCtx,
                    Range);
     RUN_VPLAN_PASS(VPlanTransforms::convertToAbstractRecipes, *Plan, CostCtx,
@@ -6858,15 +6854,9 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlan(VPlanPtr Plan,
                  InterleaveGroups, CM.isEpilogueAllowed());
 
   // Convert memory recipes to strided access recipes if the strided access is
-  // legal and profitable. Use a new VPCostContext to ensure type inference
-  // reflects the current plan state.
-  // TODO: Remove this VPCostContext scope once VPTypeAnalysis is removed.
-  {
-    VPCostContext CostCtx(CM.TTI, *CM.TLI, *Plan, CM, Config.CostKind, CM.PSE,
-                          OrigLoop);
-    RUN_VPLAN_PASS(VPlanTransforms::convertToStridedAccesses, *Plan, PSE,
-                   *OrigLoop, CostCtx, Range);
-  }
+  // legal and profitable.
+  RUN_VPLAN_PASS(VPlanTransforms::convertToStridedAccesses, *Plan, PSE,
+                 *OrigLoop, CostCtx, Range);
 
   // Ensure scalar VF plans only contain VF=1, as required by hasScalarVFOnly.
   if (Range.Start.isScalar())
@@ -6895,7 +6885,6 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlan(VPlanPtr Plan,
 void LoopVectorizationPlanner::addReductionResultComputation(
     VPlanPtr &Plan, VPRecipeBuilder &RecipeBuilder, ElementCount MinVF) {
   using namespace VPlanPatternMatch;
-  VPTypeAnalysis TypeInfo(*Plan);
   VPRegionBlock *VectorLoopRegion = Plan->getVectorLoopRegion();
   VPBasicBlock *MiddleVPBB = Plan->getMiddleBlock();
   VPBasicBlock *LatchVPBB = VectorLoopRegion->getExitingBasicBlock();
@@ -6911,7 +6900,7 @@ void LoopVectorizationPlanner::addReductionResultComputation(
     RecurKind RecurrenceKind = PhiR->getRecurrenceKind();
     const RecurrenceDescriptor &RdxDesc = Legal->getRecurrenceDescriptor(
         cast<PHINode>(PhiR->getUnderlyingInstr()));
-    Type *PhiTy = TypeInfo.inferScalarType(PhiR);
+    Type *PhiTy = PhiR->getScalarType();
 
     // Convert a VPBlendRecipe backedge to a select.
     if (auto *Blend = dyn_cast<VPBlendRecipe>(PhiR->getBackedgeValue())) {
@@ -7488,7 +7477,9 @@ preparePlanForMainVectorLoop(VPlan &MainPlan, VPlan &EpiPlan) {
       });
   VPPhi *ResumePhi = nullptr;
   if (ResumePhiIter == MainScalarPH->phis().end()) {
-    Type *Ty = VPTypeAnalysis(MainPlan).inferScalarType(VectorTC);
+    assert(MainPlan.getVectorLoopRegion()->getCanonicalIV() &&
+           "canonical IV must exist");
+    Type *Ty = VectorTC->getScalarType();
     VPBuilder ScalarPHBuilder(MainScalarPH, MainScalarPH->begin());
     ResumePhi = ScalarPHBuilder.createScalarPhi(
         {VectorTC, MainPlan.getZero(Ty)}, {}, "vec.epilog.resume.val");

diff  --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index 8047c1d83ddf3..88a328ac7b27b 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -274,9 +274,9 @@ VPTransformState::VPTransformState(const TargetTransformInfo *TTI,
                                    ElementCount VF, LoopInfo *LI,
                                    DominatorTree *DT, AssumptionCache *AC,
                                    IRBuilderBase &Builder, VPlan *Plan,
-                                   Loop *CurrentParentLoop, Type *CanonicalIVTy)
+                                   Loop *CurrentParentLoop)
     : TTI(TTI), VF(VF), CFG(DT), LI(LI), AC(AC), Builder(Builder), Plan(Plan),
-      CurrentParentLoop(CurrentParentLoop), TypeAnalysis(*Plan), VPDT(*Plan) {}
+      CurrentParentLoop(CurrentParentLoop), VPDT(*Plan) {}
 
 Value *VPTransformState::get(const VPValue *Def, const VPLane &Lane) {
   if (isa<VPIRValue, VPSymbolicValue>(Def))
@@ -1653,9 +1653,7 @@ std::string VPSlotTracker::getOrCreateName(const VPValue *V) const {
 VPInstruction *VPBuilder::createAnyOfReduction(VPValue *ChainOp,
                                                VPValue *TrueVal,
                                                VPValue *FalseVal, DebugLoc DL) {
-  assert(VPTypeAnalysis(*getInsertBlock()->getPlan())
-             .inferScalarType(ChainOp)
-             ->isIntegerTy(1) &&
+  assert(ChainOp->getScalarType()->isIntegerTy(1) &&
          "ChainOp must be i1 for AnyOf reduction");
   VPIRFlags Flags(RecurKind::Or, /*IsOrdered=*/false, /*IsInLoop=*/false,
                   FastMathFlags());
@@ -1899,7 +1897,7 @@ InstructionCost VPCostContext::getScalarizationOverhead(
          cast<VPReplicateRecipe>(Op)->getOpcode() == Instruction::Load) ||
         !UniqueOperands.insert(Op).second)
       continue;
-    Tys.push_back(toVectorizedTy(Types.inferScalarType(Op), VF));
+    Tys.push_back(toVectorizedTy(Op->getScalarType(), VF));
   }
   return ScalarizationCost +
          TTI.getOperandsScalarizationOverhead(Tys, CostKind, VIC);
@@ -1932,7 +1930,7 @@ bool VPCostContext::useEmulatedMaskMemRefHack(const VPReplicateRecipe *R,
           if (!isa<StoreInst>(RepR->getUnderlyingInstr()))
             continue;
           // Check if scatter is legal for this store. If so, don't count it.
-          Type *Ty = Types.inferScalarType(RepR->getOperand(0));
+          Type *Ty = RepR->getOperand(0)->getScalarType();
           auto *VTy = VectorType::get(Ty, VF);
           const Align Alignment =
               getLoadStoreAlignment(RepR->getUnderlyingInstr());

diff  --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index c5f39cbf9cb68..ef64e30ac38e6 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -598,13 +598,6 @@ class LLVM_ABI_FOR_TEST VPRecipeBase
     return R->getVPRecipeID() == VPRecipeID;                                   \
   }
 
-/// Return the scalar type of \p V. If \p V's scalar type has not been set
-/// because the defining recipe was not assigned one yet, fall back to
-/// VPTypeAnalysis using the plan of the defining recipe.
-/// TODO: Remove once all VPRecipeValues have been migrated to carry their
-/// types.
-LLVM_ABI Type *getScalarTypeOrInfer(VPValue *V);
-
 /// Compute the scalar result type for an IR \p Opcode given \p Operands.
 LLVM_ABI Type *computeScalarTypeForInstruction(unsigned Opcode,
                                                ArrayRef<VPValue *> Operands);
@@ -2204,7 +2197,7 @@ class LLVM_ABI_FOR_TEST VPWidenGEPRecipe : public VPRecipeWithIRFlags {
                    DebugLoc DL = DebugLoc::getUnknown(),
                    GetElementPtrInst *UV = nullptr)
       : VPRecipeWithIRFlags(VPRecipeBase::VPWidenGEPSC, Operands,
-                            getScalarTypeOrInfer(Operands[0]), Flags, DL),
+                            Operands[0]->getScalarType(), Flags, DL),
         SourceElementTy(SourceElementTy) {
     if (UV) {
       setUnderlyingValue(UV);
@@ -2266,7 +2259,7 @@ class VPVectorEndPointerRecipe : public VPRecipeWithIRFlags {
   VPVectorEndPointerRecipe(VPValue *Ptr, VPValue *VF, Type *SourceElementTy,
                            int64_t Stride, GEPNoWrapFlags GEPFlags, DebugLoc DL)
       : VPRecipeWithIRFlags(VPRecipeBase::VPVectorEndPointerSC, {Ptr, VF},
-                            getScalarTypeOrInfer(Ptr), GEPFlags, DL),
+                            Ptr->getScalarType(), GEPFlags, DL),
         SourceElementTy(SourceElementTy), Stride(Stride) {
     assert(Stride < 0 && "Stride must be negative");
   }
@@ -2337,7 +2330,7 @@ class VPVectorPointerRecipe : public VPRecipeWithIRFlags {
                         GEPNoWrapFlags GEPFlags, DebugLoc DL)
       : VPRecipeWithIRFlags(VPRecipeBase::VPVectorPointerSC,
                             ArrayRef<VPValue *>({Ptr, Stride}),
-                            getScalarTypeOrInfer(Ptr), GEPFlags, DL),
+                            Ptr->getScalarType(), GEPFlags, DL),
         SourceElementTy(SourceElementTy) {}
 
   VP_CLASSOF_IMPL(VPRecipeBase::VPVectorPointerSC)
@@ -2415,7 +2408,7 @@ class LLVM_ABI_FOR_TEST VPHeaderPHIRecipe : public VPSingleDefRecipe,
   VPHeaderPHIRecipe(unsigned char VPRecipeID, Instruction *UnderlyingInstr,
                     VPValue *Start, DebugLoc DL = DebugLoc::getUnknown())
       : VPHeaderPHIRecipe(VPRecipeID, UnderlyingInstr, Start,
-                          getScalarTypeOrInfer(Start), DL) {}
+                          Start->getScalarType(), DL) {}
 
   VPHeaderPHIRecipe(unsigned char VPRecipeID, Instruction *UnderlyingInstr,
                     VPValue *Start, Type *ResultTy, DebugLoc DL)
@@ -2489,7 +2482,7 @@ class VPWidenInductionRecipe : public VPHeaderPHIRecipe {
                          VPValue *Step, const InductionDescriptor &IndDesc,
                          DebugLoc DL)
       : VPWidenInductionRecipe(Kind, IV, Start, Step, IndDesc,
-                               getScalarTypeOrInfer(Start), DL) {}
+                               Start->getScalarType(), DL) {}
 
   VPWidenInductionRecipe(unsigned char Kind, PHINode *IV, VPValue *Start,
                          VPValue *Step, const InductionDescriptor &IndDesc,
@@ -2715,7 +2708,7 @@ class LLVM_ABI_FOR_TEST VPWidenPHIRecipe : public VPSingleDefRecipe,
   VPWidenPHIRecipe(ArrayRef<VPValue *> IncomingValues,
                    DebugLoc DL = DebugLoc::getUnknown(), const Twine &Name = "")
       : VPSingleDefRecipe(VPRecipeBase::VPWidenPHISC, IncomingValues,
-                          getScalarTypeOrInfer(IncomingValues[0]),
+                          IncomingValues[0]->getScalarType(),
                           /*UV=*/nullptr, DL),
         Name(Name.str()) {
     assert(all_of(IncomingValues,
@@ -3643,7 +3636,7 @@ class LLVM_ABI_FOR_TEST VPPredInstPHIRecipe : public VPSingleDefRecipe {
   /// nodes after merging back from a Branch-on-Mask.
   VPPredInstPHIRecipe(VPValue *PredV, DebugLoc DL)
       : VPSingleDefRecipe(VPRecipeBase::VPPredInstPHISC, PredV,
-                          getScalarTypeOrInfer(PredV), /*UV=*/nullptr, DL) {}
+                          PredV->getScalarType(), /*UV=*/nullptr, DL) {}
   ~VPPredInstPHIRecipe() override = default;
 
   VPPredInstPHIRecipe *clone() override {
@@ -4179,7 +4172,7 @@ class LLVM_ABI_FOR_TEST VPScalarIVStepsRecipe : public VPRecipeWithIRFlags {
                         Instruction::BinaryOps Opcode, FastMathFlags FMFs,
                         DebugLoc DL)
       : VPRecipeWithIRFlags(VPRecipeBase::VPScalarIVStepsSC, {IV, Step, VF},
-                            getScalarTypeOrInfer(IV), FMFs, DL),
+                            IV->getScalarType(), FMFs, DL),
         InductionOpcode(Opcode) {}
 
   VPScalarIVStepsRecipe(const InductionDescriptor &IndDesc, VPValue *IV,

diff  --git a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
index 1687b8ed22685..ef01c1817f79e 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp
@@ -13,21 +13,13 @@
 #include "VPlanHelpers.h"
 #include "VPlanPatternMatch.h"
 #include "llvm/ADT/PostOrderIterator.h"
-#include "llvm/Analysis/ScalarEvolution.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
-#include "llvm/IR/Instruction.h"
 
 using namespace llvm;
 using namespace VPlanPatternMatch;
 
 #define DEBUG_TYPE "vplan"
 
-Type *VPTypeAnalysis::inferScalarType(const VPValue *V) {
-  Type *Ty = V->getScalarType();
-  assert(Ty && "Scalar type must be set by recipe construction");
-  return Ty;
-}
-
 void llvm::collectEphemeralRecipesForVPlan(
     VPlan &Plan, DenseSet<VPRecipeBase *> &EphRecipes) {
   // First, collect seed recipes which are operands of assumes.
@@ -195,8 +187,6 @@ SmallVector<VPRegisterUsage, 8> llvm::calculateRegisterUsageForPlan(
 
   LLVM_DEBUG(dbgs() << "LV(REG): Calculating max register usage:\n");
 
-  VPTypeAnalysis TypeInfo(Plan);
-
   const auto &TTICapture = TTI;
   auto GetRegUsage = [&TTICapture](Type *Ty, ElementCount VF) -> unsigned {
     if (Ty->isTokenTy() || !VectorType::isValidElementType(Ty) ||
@@ -265,7 +255,7 @@ SmallVector<VPRegisterUsage, 8> llvm::calculateRegisterUsageForPlan(
             (isa<VPReductionPHIRecipe>(VPV) &&
              (cast<VPReductionPHIRecipe>(VPV))->isInLoop())) {
           unsigned ClassID =
-              TTI.getRegisterClassForType(false, TypeInfo.inferScalarType(VPV));
+              TTI.getRegisterClassForType(false, VPV->getScalarType());
           // FIXME: The target might use more than one register for the type
           // even in the scalar case.
           RegUsage[ClassID] += 1;
@@ -281,7 +271,7 @@ SmallVector<VPRegisterUsage, 8> llvm::calculateRegisterUsageForPlan(
                               << " to " << VF << " for " << *R << "\n";);
           }
 
-          Type *ScalarTy = TypeInfo.inferScalarType(VPV);
+          Type *ScalarTy = VPV->getScalarType();
           unsigned ClassID = TTI.getRegisterClassForType(true, ScalarTy);
           RegUsage[ClassID] += GetRegUsage(ScalarTy, VF);
         }
@@ -320,9 +310,9 @@ SmallVector<VPRegisterUsage, 8> llvm::calculateRegisterUsageForPlan(
       bool IsScalar = vputils::onlyScalarValuesUsed(In);
 
       ElementCount VF = IsScalar ? ElementCount::getFixed(1) : VFs[Idx];
-      unsigned ClassID = TTI.getRegisterClassForType(
-          VF.isVector(), TypeInfo.inferScalarType(In));
-      Invariant[ClassID] += GetRegUsage(TypeInfo.inferScalarType(In), VF);
+      unsigned ClassID =
+          TTI.getRegisterClassForType(VF.isVector(), In->getScalarType());
+      Invariant[ClassID] += GetRegUsage(In->getScalarType(), VF);
     }
 
     LLVM_DEBUG({

diff  --git a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.h b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.h
index 23feaf5615798..39bacf1fee7c6 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.h
@@ -19,41 +19,13 @@
 
 namespace llvm {
 
-class LLVMContext;
-class VPValue;
 class VPRecipeBase;
 class VPlan;
-class Value;
 class TargetTransformInfo;
-class Type;
 class InstructionCost;
 
 struct VPCostContext;
 
-/// An analysis for type-inference for VPValues.
-/// It infers the scalar type for a given VPValue by bottom-up traversing
-/// through defining recipes until root nodes with known types are reached (e.g.
-/// live-ins or load recipes). The types are then propagated top down through
-/// operations.
-/// Note that the analysis caches the inferred types. A new analysis object must
-/// be constructed once a VPlan has been modified in a way that invalidates any
-/// of the previously inferred types.
-class VPTypeAnalysis {
-  DenseMap<const VPValue *, Type *> CachedTypes;
-  LLVMContext &Ctx;
-  const DataLayout &DL;
-
-public:
-  VPTypeAnalysis(const VPlan &Plan)
-      : Ctx(Plan.getContext()), DL(Plan.getDataLayout()) {}
-
-  /// Infer the type of \p V. Returns the scalar type of \p V.
-  Type *inferScalarType(const VPValue *V);
-
-  /// Return the LLVMContext used by the analysis.
-  LLVMContext &getContext() { return Ctx; }
-};
-
 // Collect a VPlan's ephemeral recipes (those used only by an assume).
 void collectEphemeralRecipesForVPlan(VPlan &Plan,
                                      DenseSet<VPRecipeBase *> &EphRecipes);

diff  --git a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
index 73e81d9746338..e5c546c7fb851 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
@@ -1046,7 +1046,6 @@ bool VPlanTransforms::finalizeSCEVPredicates(VPlan &Plan,
 
 void VPlanTransforms::createInLoopReductionRecipes(VPlan &Plan,
                                                    ElementCount MinVF) {
-  VPTypeAnalysis TypeInfo(Plan);
   VPBasicBlock *Header = Plan.getVectorLoopRegion()->getEntryBasicBlock();
   SmallVector<VPRecipeBase *> ToDelete;
 
@@ -1141,7 +1140,7 @@ void VPlanTransforms::createInLoopReductionRecipes(VPlan &Plan,
         VecOp = FMulRecipe;
       } else if (Kind == RecurKind::AddChainWithSubs &&
                  match(CurrentLink, m_Sub(m_VPValue(), m_VPValue()))) {
-        Type *PhiTy = TypeInfo.inferScalarType(PhiR);
+        Type *PhiTy = PhiR->getScalarType();
         auto *Zero = Plan.getConstantInt(PhiTy, 0);
         VPBuilder Builder(LinkVPBB, CurrentLink->getIterator());
         auto *Sub = Builder.createSub(Zero, CurrentLink->getOperand(1),
@@ -1236,7 +1235,7 @@ static bool areAllLoadsDereferenceable(VPBasicBlock *HeaderVPBB, Loop *TheLoop,
       }
 
       // Check dereferenceability using the SCEV-based version.
-      Type *LoadTy = VPI->getResultType();
+      Type *LoadTy = VPI->getScalarType();
       const SCEV *SizeSCEV =
           SE.getStoreSizeOfExpr(DL.getIndexType(PtrSCEV->getType()), LoadTy);
       auto *Load = cast<LoadInst>(VPI->getUnderlyingValue());
@@ -1403,12 +1402,11 @@ void VPlanTransforms::foldTailByMasking(VPlan &Plan) {
 
   // Insert phis for values coming past the end of the tail.
   Builder.setInsertPoint(Latch, Latch->begin());
-  VPTypeAnalysis TypeInfo(Plan);
   for (const auto &[V, Users] : NeedsPhi) {
     if (isa<VPIRValue>(V))
       continue;
     VPValue *TailVal =
-        Plan.getOrAddLiveIn(PoisonValue::get(TypeInfo.inferScalarType(V)));
+        Plan.getOrAddLiveIn(PoisonValue::get(V->getScalarType()));
     VPIRFlags Flags;
     assert(llvm::count_if(Users, IsaPred<VPReductionPHIRecipe>) <= 1 &&
            "Value used by more than two reduction phis?");
@@ -1938,7 +1936,7 @@ static bool handleFirstArgMinOrMax(
   Type *Ty = Plan.getVectorLoopRegion()->getCanonicalIVType();
   // TODO: Support non (i.e., narrower than) canonical IV types.
   // TODO: Emit remarks for failed transformations.
-  if (Ty != VPTypeAnalysis(Plan).inferScalarType(WideIV))
+  if (Ty != WideIV->getScalarType())
     return false;
 
   auto *FindIVSelectR = cast<VPSingleDefRecipe>(

diff  --git a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
index 0e46b284deb25..9ed27e3899eee 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanHelpers.h
@@ -191,8 +191,8 @@ class VPLane {
 struct VPTransformState {
   VPTransformState(const TargetTransformInfo *TTI, ElementCount VF,
                    LoopInfo *LI, DominatorTree *DT, AssumptionCache *AC,
-                   IRBuilderBase &Builder, VPlan *Plan, Loop *CurrentParentLoop,
-                   Type *CanonicalIVTy);
+                   IRBuilderBase &Builder, VPlan *Plan,
+                   Loop *CurrentParentLoop);
   /// Target Transform Info.
   const TargetTransformInfo *TTI;
 
@@ -314,9 +314,6 @@ struct VPTransformState {
   /// The parent loop object for the current scope, or nullptr.
   Loop *CurrentParentLoop = nullptr;
 
-  /// VPlan-based type analysis.
-  VPTypeAnalysis TypeAnalysis;
-
   /// VPlan-based dominator tree.
   VPDominatorTree VPDT;
 };
@@ -325,7 +322,6 @@ struct VPTransformState {
 struct VPCostContext {
   const TargetTransformInfo &TTI;
   const TargetLibraryInfo &TLI;
-  VPTypeAnalysis Types;
   LLVMContext &LLVMCtx;
   LoopVectorizationCostModel &CM;
   SmallPtrSet<Instruction *, 8> SkipCostComputation;
@@ -340,7 +336,7 @@ struct VPCostContext {
                 const VPlan &Plan, LoopVectorizationCostModel &CM,
                 TargetTransformInfo::TargetCostKind CostKind,
                 PredicatedScalarEvolution &PSE, const Loop *L)
-      : TTI(TTI), TLI(TLI), Types(Plan), LLVMCtx(Plan.getContext()), CM(CM),
+      : TTI(TTI), TLI(TLI), LLVMCtx(Plan.getContext()), CM(CM),
         CostKind(CostKind), PSE(PSE), L(L) {}
 
   /// Return the cost for \p UI with \p VF using the legacy cost model as

diff  --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index d77d82a68876f..941e8e309471e 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -13,7 +13,6 @@
 
 #include "LoopVectorizationPlanner.h"
 #include "VPlan.h"
-#include "VPlanAnalysis.h"
 #include "VPlanHelpers.h"
 #include "VPlanPatternMatch.h"
 #include "VPlanUtils.h"
@@ -423,16 +422,6 @@ void VPRecipeBase::print(raw_ostream &O, const Twine &Indent,
 }
 #endif
 
-Type *llvm::getScalarTypeOrInfer(VPValue *V) {
-  if (Type *Ty = V->getScalarType())
-    return Ty;
-  auto *Recipe = V->getDefiningRecipe();
-  assert(Recipe && Recipe->getParent() &&
-         "operand without scalar type must be a recipe in a plan");
-  VPTypeAnalysis TypeInfo(*Recipe->getParent()->getPlan());
-  return TypeInfo.inferScalarType(V);
-}
-
 VPExpandSCEVRecipe::VPExpandSCEVRecipe(const SCEV *Expr)
     : VPSingleDefRecipe(VPRecipeBase::VPExpandSCEVSC, {}, Expr->getType()),
       Expr(Expr) {}
@@ -465,12 +454,12 @@ Type *llvm::computeScalarTypeForInstruction(unsigned Opcode,
                                                         Type *ExpectedTy) {
     if (!ExpectedTy || Operands.size() <= Idx)
       return;
-    [[maybe_unused]] Type *OpTy = getScalarTypeOrInfer(Operands[Idx]);
+    [[maybe_unused]] Type *OpTy = Operands[Idx]->getScalarType();
     assert((!OpTy || OpTy == ExpectedTy) &&
            "
diff erent types inferred for 
diff erent operands");
   };
 
-  Type *Op0Ty = getScalarTypeOrInfer(Operands[0]);
+  Type *Op0Ty = Operands[0]->getScalarType();
   LLVMContext &Ctx = Op0Ty->getContext();
   switch (Opcode) {
   case VPInstruction::BranchOnCond:
@@ -493,14 +482,14 @@ Type *llvm::computeScalarTypeForInstruction(unsigned Opcode,
   case VPInstruction::ExplicitVectorLength:
     return IntegerType::get(Ctx, 32);
   case Instruction::Select: {
-    Type *Op1Ty = getScalarTypeOrInfer(Operands[1]);
+    Type *Op1Ty = Operands[1]->getScalarType();
     AssertOperandType(2, Op1Ty);
     return Op1Ty;
   }
   case VPInstruction::ExtractLane: {
     assert(Operands.size() >= 2 && "ExtractLane requires a lane operand and "
                                    "at least one source vector operand");
-    Type *Op1Ty = getScalarTypeOrInfer(Operands[1]);
+    Type *Op1Ty = Operands[1]->getScalarType();
     for (unsigned Idx = 2; Idx != Operands.size(); ++Idx)
       AssertOperandType(Idx, Op1Ty);
     return Op1Ty;
@@ -761,7 +750,7 @@ Value *VPInstruction::generate(VPTransformState &State) {
     assert(VecTy->getScalarSizeInBits() == 1 &&
            "NumActiveLanes only implemented for i1 vectors");
 
-    Type *Ty = State.TypeAnalysis.inferScalarType(this);
+    Type *Ty = getScalarType();
     Value *ZExt = Builder.CreateCast(
         Instruction::ZExt, Op, VectorType::get(Ty, VecTy->getElementCount()));
     Value *NumActive =
@@ -836,8 +825,7 @@ Value *VPInstruction::generate(VPTransformState &State) {
   case VPInstruction::BuildStructVector: {
     // For struct types, we need to build a new 'wide' struct type, where each
     // element is widened, i.e., we create a struct of vectors.
-    auto *StructTy =
-        cast<StructType>(State.TypeAnalysis.inferScalarType(getOperand(0)));
+    auto *StructTy = cast<StructType>(getOperand(0)->getScalarType());
     Value *Res = PoisonValue::get(toVectorizedTy(StructTy, State.VF));
     for (const auto &[LaneIndex, Op] : enumerate(operands())) {
       for (unsigned FieldIndex = 0; FieldIndex != StructTy->getNumElements();
@@ -853,7 +841,7 @@ Value *VPInstruction::generate(VPTransformState &State) {
     return Res;
   }
   case VPInstruction::BuildVector: {
-    auto *ScalarTy = State.TypeAnalysis.inferScalarType(getOperand(0));
+    auto *ScalarTy = getOperand(0)->getScalarType();
     auto NumOfElements = ElementCount::getFixed(getNumOperands());
     Value *Res = PoisonValue::get(toVectorizedTy(ScalarTy, NumOfElements));
     for (const auto &[Idx, Op] : enumerate(operands()))
@@ -976,7 +964,7 @@ Value *VPInstruction::generate(VPTransformState &State) {
     assert(getNumOperands() != 2 && "ExtractLane from single source should be "
                                     "simplified to ExtractElement.");
     Value *LaneToExtract = State.get(getOperand(0), true);
-    Type *IdxTy = State.TypeAnalysis.inferScalarType(getOperand(0));
+    Type *IdxTy = getOperand(0)->getScalarType();
     Value *Res = nullptr;
     Value *RuntimeVF = getRuntimeVF(Builder, IdxTy, State.VF);
 
@@ -1000,7 +988,7 @@ Value *VPInstruction::generate(VPTransformState &State) {
     return Res;
   }
   case VPInstruction::FirstActiveLane: {
-    Type *Ty = State.TypeAnalysis.inferScalarType(this);
+    Type *Ty = this->getScalarType();
     if (getNumOperands() == 1) {
       Value *Mask = State.get(getOperand(0));
       return Builder.CreateCountTrailingZeroElems(Ty, Mask,
@@ -1063,7 +1051,7 @@ Value *VPInstruction::generate(VPTransformState &State) {
 
 InstructionCost VPRecipeWithIRFlags::getCostForRecipeWithOpcode(
     unsigned Opcode, ElementCount VF, VPCostContext &Ctx) const {
-  Type *ScalarTy = Ctx.Types.inferScalarType(this);
+  Type *ScalarTy = this->getScalarType();
   Type *ResultTy = VF.isVector() ? toVectorTy(ScalarTy, VF) : ScalarTy;
   switch (Opcode) {
   case Instruction::FNeg:
@@ -1116,7 +1104,7 @@ InstructionCost VPRecipeWithIRFlags::getCostForRecipeWithOpcode(
                                              Ctx.CostKind);
   case Instruction::ICmp:
   case Instruction::FCmp: {
-    Type *ScalarOpTy = Ctx.Types.inferScalarType(getOperand(0));
+    Type *ScalarOpTy = getOperand(0)->getScalarType();
     Type *OpTy = VF.isVector() ? toVectorTy(ScalarOpTy, VF) : ScalarOpTy;
     Instruction *CtxI = dyn_cast_or_null<Instruction>(getUnderlyingValue());
     return Ctx.TTI.getCmpSelInstrCost(
@@ -1125,7 +1113,7 @@ InstructionCost VPRecipeWithIRFlags::getCostForRecipeWithOpcode(
         {TTI::OK_AnyValue, TTI::OP_None}, CtxI);
   }
   case Instruction::BitCast: {
-    Type *ScalarTy = Ctx.Types.inferScalarType(this);
+    Type *ScalarTy = this->getScalarType();
     if (ScalarTy->isPointerTy())
       return 0;
     [[fallthrough]];
@@ -1209,7 +1197,7 @@ InstructionCost VPRecipeWithIRFlags::getCostForRecipeWithOpcode(
     if (IsReverse && CCH != TTI::CastContextHint::None)
       CCH = TTI::CastContextHint::Reversed;
 
-    auto *ScalarSrcTy = Ctx.Types.inferScalarType(Operand);
+    auto *ScalarSrcTy = Operand->getScalarType();
     Type *SrcTy = VF.isVector() ? toVectorTy(ScalarSrcTy, VF) : ScalarSrcTy;
     // Arm TTI will use the underlying instruction to determine the cost.
     return Ctx.TTI.getCastInstrCost(
@@ -1219,7 +1207,7 @@ InstructionCost VPRecipeWithIRFlags::getCostForRecipeWithOpcode(
   case Instruction::Select: {
     SelectInst *SI = cast_or_null<SelectInst>(getUnderlyingValue());
     bool IsScalarCond = getOperand(0)->isDefinedOutsideLoopRegions();
-    Type *ScalarTy = Ctx.Types.inferScalarType(this);
+    Type *ScalarTy = this->getScalarType();
 
     VPValue *Op0, *Op1;
     bool IsLogicalAnd =
@@ -1250,7 +1238,7 @@ InstructionCost VPRecipeWithIRFlags::getCostForRecipeWithOpcode(
           Ctx.CostKind, {Op1VK, Op1VP}, {Op2VK, Op2VP}, Operands, SI);
     }
 
-    Type *CondTy = Ctx.Types.inferScalarType(getOperand(0));
+    Type *CondTy = getOperand(0)->getScalarType();
     if (!IsScalarCond && VF.isVector())
       CondTy = VectorType::get(CondTy, VF);
 
@@ -1259,7 +1247,7 @@ InstructionCost VPRecipeWithIRFlags::getCostForRecipeWithOpcode(
       if (auto *CondIRV = dyn_cast<VPIRValue>(getOperand(0)))
         if (auto *Cmp = dyn_cast<CmpInst>(CondIRV->getValue()))
           Pred = Cmp->getPredicate();
-    Type *VectorTy = toVectorTy(Ctx.Types.inferScalarType(this), VF);
+    Type *VectorTy = toVectorTy(this->getScalarType(), VF);
     return Ctx.TTI.getCmpSelInstrCost(
         Instruction::Select, VectorTy, CondTy, Pred, Ctx.CostKind,
         {TTI::OK_AnyValue, TTI::OP_None}, {TTI::OK_AnyValue, TTI::OP_None}, SI);
@@ -1289,8 +1277,8 @@ InstructionCost VPInstruction::computeCost(ElementCount VF,
   case Instruction::Select: {
     llvm::CmpPredicate Pred = CmpInst::BAD_ICMP_PREDICATE;
     match(getOperand(0), m_Cmp(Pred, m_VPValue(), m_VPValue()));
-    auto *CondTy = Ctx.Types.inferScalarType(getOperand(0));
-    auto *VecTy = Ctx.Types.inferScalarType(getOperand(1));
+    auto *CondTy = getOperand(0)->getScalarType();
+    auto *VecTy = getOperand(1)->getScalarType();
     if (!vputils::onlyFirstLaneUsed(this)) {
       CondTy = toVectorTy(CondTy, VF);
       VecTy = toVectorTy(VecTy, VF);
@@ -1307,18 +1295,18 @@ InstructionCost VPInstruction::computeCost(ElementCount VF,
     }
 
     // Add on the cost of extracting the element.
-    auto *VecTy = toVectorTy(Ctx.Types.inferScalarType(getOperand(0)), VF);
+    auto *VecTy = toVectorTy(getOperand(0)->getScalarType(), VF);
     return Ctx.TTI.getVectorInstrCost(Instruction::ExtractElement, VecTy,
                                       Ctx.CostKind);
   }
   case VPInstruction::AnyOf: {
-    auto *VecTy = toVectorTy(Ctx.Types.inferScalarType(this), VF);
+    auto *VecTy = toVectorTy(this->getScalarType(), VF);
     return Ctx.TTI.getArithmeticReductionCost(
         Instruction::Or, cast<VectorType>(VecTy), std::nullopt, Ctx.CostKind);
   }
   case VPInstruction::FirstActiveLane: {
-    Type *Ty = Ctx.Types.inferScalarType(this);
-    Type *ScalarTy = Ctx.Types.inferScalarType(getOperand(0));
+    Type *Ty = this->getScalarType();
+    Type *ScalarTy = getOperand(0)->getScalarType();
     if (VF.isScalar())
       return Ctx.TTI.getCmpSelInstrCost(Instruction::ICmp, ScalarTy,
                                         CmpInst::makeCmpResultType(ScalarTy),
@@ -1330,8 +1318,8 @@ InstructionCost VPInstruction::computeCost(ElementCount VF,
     return Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
   }
   case VPInstruction::LastActiveLane: {
-    Type *Ty = Ctx.Types.inferScalarType(this);
-    Type *ScalarTy = Ctx.Types.inferScalarType(getOperand(0));
+    Type *Ty = this->getScalarType();
+    Type *ScalarTy = getOperand(0)->getScalarType();
     if (VF.isScalar())
       return Ctx.TTI.getCmpSelInstrCost(Instruction::ICmp, ScalarTy,
                                         CmpInst::makeCmpResultType(ScalarTy),
@@ -1352,7 +1340,7 @@ InstructionCost VPInstruction::computeCost(ElementCount VF,
     return Cost;
   }
   case VPInstruction::ExtractLastActive: {
-    Type *ScalarTy = Ctx.Types.inferScalarType(this);
+    Type *ScalarTy = this->getScalarType();
     Type *VecTy = toVectorTy(ScalarTy, VF);
     Type *MaskTy = toVectorTy(Type::getInt1Ty(Ctx.LLVMCtx), VF);
     IntrinsicCostAttributes ICA(
@@ -1362,13 +1350,13 @@ InstructionCost VPInstruction::computeCost(ElementCount VF,
   }
   case VPInstruction::FirstOrderRecurrenceSplice: {
     assert(VF.isVector() && "Scalar FirstOrderRecurrenceSplice?");
-    Type *VectorTy = toVectorTy(Ctx.Types.inferScalarType(this), VF);
+    Type *VectorTy = toVectorTy(this->getScalarType(), VF);
     return Ctx.TTI.getShuffleCost(
         TargetTransformInfo::SK_Splice, cast<VectorType>(VectorTy),
         cast<VectorType>(VectorTy), {}, Ctx.CostKind, -1);
   }
   case VPInstruction::ActiveLaneMask: {
-    Type *ArgTy = Ctx.Types.inferScalarType(getOperand(0));
+    Type *ArgTy = getOperand(0)->getScalarType();
     unsigned Multiplier = cast<VPConstantInt>(getOperand(2))->getZExtValue();
     Type *RetTy = toVectorTy(Type::getInt1Ty(Ctx.LLVMCtx), VF * Multiplier);
     IntrinsicCostAttributes Attrs(Intrinsic::get_active_lane_mask, RetTy,
@@ -1376,7 +1364,7 @@ InstructionCost VPInstruction::computeCost(ElementCount VF,
     return Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
   }
   case VPInstruction::ExplicitVectorLength: {
-    Type *Arg0Ty = Ctx.Types.inferScalarType(getOperand(0));
+    Type *Arg0Ty = getOperand(0)->getScalarType();
     Type *I32Ty = Type::getInt32Ty(Ctx.LLVMCtx);
     Type *I1Ty = Type::getInt1Ty(Ctx.LLVMCtx);
     IntrinsicCostAttributes Attrs(Intrinsic::experimental_get_vector_length,
@@ -1385,7 +1373,7 @@ InstructionCost VPInstruction::computeCost(ElementCount VF,
   }
   case VPInstruction::Reverse: {
     assert(VF.isVector() && "Reverse operation must be vector type");
-    Type *EltTy = Ctx.Types.inferScalarType(this);
+    Type *EltTy = this->getScalarType();
     // Skip the reverse operation cost for the mask.
     // FIXME: Remove this once redundant mask reverse operations can be
     // eliminated by VPlanTransforms::cse before cost computation.
@@ -1398,7 +1386,7 @@ InstructionCost VPInstruction::computeCost(ElementCount VF,
   }
   case VPInstruction::ExtractLastLane: {
     // Add on the cost of extracting the element.
-    auto *VecTy = toVectorTy(Ctx.Types.inferScalarType(getOperand(0)), VF);
+    auto *VecTy = toVectorTy(getOperand(0)->getScalarType(), VF);
     return Ctx.TTI.getIndexedVectorInstrCostFromEnd(Instruction::ExtractElement,
                                                     VecTy, Ctx.CostKind, 0);
   }
@@ -2123,7 +2111,7 @@ void VPWidenIntrinsicRecipe::execute(VPTransformState &State) {
 InstructionCost VPWidenIntrinsicRecipe::computeCallCost(
     Intrinsic::ID ID, ArrayRef<const VPValue *> Operands,
     const VPRecipeWithIRFlags &R, ElementCount VF, VPCostContext &Ctx) {
-  Type *ScalarRetTy = Ctx.Types.inferScalarType(&R);
+  Type *ScalarRetTy = R.getScalarType();
   // Skip the reverse operation cost for the mask.
   // FIXME: Remove this once redundant mask reverse operations can be eliminated
   // by VPlanTransforms::cse before cost computation.
@@ -2152,7 +2140,7 @@ InstructionCost VPWidenIntrinsicRecipe::computeCallCost(
   Type *RetTy = VF.isVector() ? toVectorizedTy(ScalarRetTy, VF) : ScalarRetTy;
   SmallVector<Type *> ParamTys =
       map_to_vector(Operands, [&](const VPValue *Op) {
-        return toVectorTy(Ctx.Types.inferScalarType(Op), VF);
+        return toVectorTy(Op->getScalarType(), VF);
       });
 
   // TODO: Rework TTI interface to avoid reliance on underlying IntrinsicInst.
@@ -2266,9 +2254,9 @@ InstructionCost VPHistogramRecipe::computeCost(ElementCount VF,
   //        whether we can use base + vec-of-smaller-indices or just
   //        vec-of-pointers.
   assert(VF.isVector() && "Invalid VF for histogram cost");
-  Type *AddressTy = Ctx.Types.inferScalarType(getOperand(0));
+  Type *AddressTy = getOperand(0)->getScalarType();
   VPValue *IncAmt = getOperand(1);
-  Type *IncTy = Ctx.Types.inferScalarType(IncAmt);
+  Type *IncTy = IncAmt->getScalarType();
   VectorType *VTy = VectorType::get(IncTy, VF);
 
   // Assume that a non-constant update value (or a constant != 1) requires
@@ -2673,7 +2661,7 @@ void VPWidenRecipe::execute(VPTransformState &State) {
 #if !defined(NDEBUG)
   // Verify that VPlan type inference results agree with the type of the
   // generated values.
-  assert(VectorType::get(State.TypeAnalysis.inferScalarType(this), State.VF) ==
+  assert(VectorType::get(this->getScalarType(), State.VF) ==
              State.get(this)->getType() &&
          "inferred type and type from generated instructions do not match");
 #endif
@@ -2945,12 +2933,11 @@ void VPVectorEndPointerRecipe::materializeOffset(unsigned Part) {
   VPBuilder Builder(this);
   VPlan &Plan = *getParent()->getPlan();
   VPValue *VFVal = getVFValue();
-  VPTypeAnalysis TypeInfo(Plan);
   const DataLayout &DL = Plan.getDataLayout();
-  Type *IndexTy = DL.getIndexType(TypeInfo.inferScalarType(this));
+  Type *IndexTy = DL.getIndexType(this->getScalarType());
   VPValue *Stride =
       Plan.getConstantInt(IndexTy, getStride(), /*IsSigned=*/true);
-  Type *VFTy = TypeInfo.inferScalarType(VFVal);
+  Type *VFTy = VFVal->getScalarType();
   VPValue *VF = Builder.createScalarZExtOrTrunc(VFVal, IndexTy, VFTy,
                                                 DebugLoc::getUnknown());
 
@@ -3027,8 +3014,8 @@ InstructionCost VPBlendRecipe::computeCost(ElementCount VF,
   if (vputils::onlyFirstLaneUsed(this))
     VF = ElementCount::getFixed(1);
 
-  Type *ResultTy = toVectorTy(Ctx.Types.inferScalarType(this), VF);
-  Type *CmpTy = toVectorTy(Type::getInt1Ty(Ctx.Types.getContext()), VF);
+  Type *ResultTy = toVectorTy(this->getScalarType(), VF);
+  Type *CmpTy = toVectorTy(Type::getInt1Ty(Ctx.LLVMCtx), VF);
   return (getNumIncomingValues() - 1) *
          Ctx.TTI.getCmpSelInstrCost(Instruction::Select, ResultTy, CmpTy,
                                     CmpInst::BAD_ICMP_PREDICATE, Ctx.CostKind);
@@ -3155,7 +3142,7 @@ void VPReductionEVLRecipe::execute(VPTransformState &State) {
 InstructionCost VPReductionRecipe::computeCost(ElementCount VF,
                                                VPCostContext &Ctx) const {
   RecurKind RdxKind = getRecurrenceKind();
-  Type *ElementTy = Ctx.Types.inferScalarType(this);
+  Type *ElementTy = this->getScalarType();
   auto *VectorTy = cast<VectorType>(toVectorTy(ElementTy, VF));
   unsigned Opcode = RecurrenceDescriptor::getOpcode(RdxKind);
   FastMathFlags FMFs = getFastMathFlags();
@@ -3166,8 +3153,8 @@ InstructionCost VPReductionRecipe::computeCost(ElementCount VF,
     InstructionCost CondCost = 0;
     if (isConditional()) {
       CmpInst::Predicate Pred = CmpInst::BAD_ICMP_PREDICATE;
-      auto *CondTy = cast<VectorType>(
-          toVectorTy(Ctx.Types.inferScalarType(getCondOp()), VF));
+      auto *CondTy =
+          cast<VectorType>(toVectorTy(getCondOp()->getScalarType(), VF));
       CondCost = Ctx.TTI.getCmpSelInstrCost(Instruction::Select, VectorTy,
                                             CondTy, Pred, Ctx.CostKind);
     }
@@ -3246,8 +3233,7 @@ VPExpressionRecipe::VPExpressionRecipe(
       if (Def && ExpressionRecipesAsSetOfUsers.contains(Def))
         continue;
       addOperand(Op);
-      LiveInPlaceholders.push_back(
-          new VPSymbolicValue(getScalarTypeOrInfer(Op)));
+      LiveInPlaceholders.push_back(new VPSymbolicValue(Op->getScalarType()));
     }
   }
 
@@ -3274,9 +3260,9 @@ void VPExpressionRecipe::decompose() {
 
 InstructionCost VPExpressionRecipe::computeCost(ElementCount VF,
                                                 VPCostContext &Ctx) const {
-  Type *RedTy = Ctx.Types.inferScalarType(this);
-  auto *SrcVecTy = cast<VectorType>(
-      toVectorTy(Ctx.Types.inferScalarType(getOperand(0)), VF));
+  Type *RedTy = this->getScalarType();
+  auto *SrcVecTy =
+      cast<VectorType>(toVectorTy(getOperand(0)->getScalarType(), VF));
   unsigned Opcode = RecurrenceDescriptor::getOpcode(
       cast<VPReductionRecipe>(ExpressionRecipes.back())->getRecurrenceKind());
   switch (ExpressionType) {
@@ -3288,7 +3274,7 @@ InstructionCost VPExpressionRecipe::computeCost(ElementCount VF,
 
     if (RedR->isPartialReduction())
       return Ctx.TTI.getPartialReductionCost(
-          Opcode, Ctx.Types.inferScalarType(getOperand(0)), nullptr, RedTy, VF,
+          Opcode, getOperand(0)->getScalarType(), nullptr, RedTy, VF,
           TargetTransformInfo::getPartialReductionExtendKind(ExtR->getOpcode()),
           TargetTransformInfo::PR_None, std::nullopt, Ctx.CostKind,
           RedTy->isFloatingPointTy() ? std::optional{RedR->getFastMathFlags()}
@@ -3324,8 +3310,8 @@ InstructionCost VPExpressionRecipe::computeCost(ElementCount VF,
       auto *Ext1R = cast<VPWidenCastRecipe>(ExpressionRecipes[1]);
       auto *Mul = cast<VPWidenRecipe>(ExpressionRecipes[2]);
       return Ctx.TTI.getPartialReductionCost(
-          Opcode, Ctx.Types.inferScalarType(getOperand(0)),
-          Ctx.Types.inferScalarType(getOperand(1)), RedTy, VF,
+          Opcode, getOperand(0)->getScalarType(),
+          getOperand(1)->getScalarType(), RedTy, VF,
           TargetTransformInfo::getPartialReductionExtendKind(
               Ext0R->getOpcode()),
           TargetTransformInfo::getPartialReductionExtendKind(
@@ -3579,8 +3565,8 @@ InstructionCost VPReplicateRecipe::computeCost(ElementCount VF,
   case Instruction::Alloca:
     if (VF.isScalable())
       return InstructionCost::getInvalid();
-    return Ctx.TTI.getArithmeticInstrCost(
-        Instruction::Mul, Ctx.Types.inferScalarType(this), Ctx.CostKind);
+    return Ctx.TTI.getArithmeticInstrCost(Instruction::Mul,
+                                          this->getScalarType(), Ctx.CostKind);
   case Instruction::GetElementPtr:
     // We mark this instruction as zero-cost because the cost of GEPs in
     // vectorized code depends on whether the corresponding memory instruction
@@ -3590,7 +3576,7 @@ InstructionCost VPReplicateRecipe::computeCost(ElementCount VF,
   case Instruction::Call: {
     auto *CalledFn =
         cast<Function>(getOperand(getNumOperands() - 1)->getLiveInIRValue());
-    Type *ResultTy = Ctx.Types.inferScalarType(this);
+    Type *ResultTy = this->getScalarType();
     SmallVector<const VPValue *> ArgOps(drop_end(operands()));
     return computeCallCost(CalledFn, ResultTy, ArgOps, isSingleScalar(), VF,
                            Ctx);
@@ -3638,7 +3624,7 @@ InstructionCost VPReplicateRecipe::computeCost(ElementCount VF,
       break;
 
     ScalarCost = ScalarCost * VF.getFixedValue() +
-                 Ctx.getScalarizationOverhead(Ctx.Types.inferScalarType(this),
+                 Ctx.getScalarizationOverhead(this->getScalarType(),
                                               to_vector(operands()), VF);
     // If the recipe is not predicated (i.e. not in a replicate region), return
     // the scalar cost. Otherwise handle predicated cost.
@@ -3662,8 +3648,8 @@ InstructionCost VPReplicateRecipe::computeCost(ElementCount VF,
     if (isa_and_nonnull<SCEVCouldNotCompute>(PtrSCEV))
       break;
 
-    Type *ValTy = Ctx.Types.inferScalarType(IsLoad ? this : getOperand(0));
-    Type *ScalarPtrTy = Ctx.Types.inferScalarType(PtrOp);
+    Type *ValTy = (IsLoad ? this : getOperand(0))->getScalarType();
+    Type *ScalarPtrTy = PtrOp->getScalarType();
     const Align Alignment = getLoadStoreAlignment(UI);
     unsigned AS = cast<PointerType>(ScalarPtrTy)->getAddressSpace();
     TTI::OperandValueInfo OpInfo = TTI::getOperandInfo(UI->getOperand(0));
@@ -3712,7 +3698,7 @@ InstructionCost VPReplicateRecipe::computeCost(ElementCount VF,
         append_range(OpsToScalarize, operands());
 
       if (!EfficientVectorLoadStore)
-        ResultTy = Ctx.Types.inferScalarType(this);
+        ResultTy = this->getScalarType();
     }
 
     TTI::VectorInstrContext VIC =
@@ -3772,7 +3758,7 @@ InstructionCost VPReplicateRecipe::computeCallCost(
     Function *CalledFn, Type *ResultTy, ArrayRef<const VPValue *> ArgOps,
     bool IsSingleScalar, ElementCount VF, VPCostContext &Ctx) {
   SmallVector<Type *, 4> Tys = map_to_vector<4>(
-      ArgOps, [&](const VPValue *Op) { return Ctx.Types.inferScalarType(Op); });
+      ArgOps, [&](const VPValue *Op) { return Op->getScalarType(); });
 
   Intrinsic::ID IntrinID = CalledFn->getIntrinsicID();
   auto GetIntrinsicCost = [&] {
@@ -3807,8 +3793,7 @@ void VPReplicateRecipe::printRecipe(raw_ostream &O, const Twine &Indent,
                                     VPSlotTracker &SlotTracker) const {
   O << Indent << (IsSingleScalar ? "CLONE " : "REPLICATE ");
 
-  VPTypeAnalysis TypeInfo(*getParent()->getPlan());
-  if (!TypeInfo.inferScalarType(this)->isVoidTy()) {
+  if (!getScalarType()->isVoidTy()) {
     printAsOperand(O, SlotTracker);
     O << " = ";
   }
@@ -3869,10 +3854,10 @@ InstructionCost VPWidenMemoryRecipe::computeCost(ElementCount VF,
   const VPRecipeBase *R = getAsRecipe();
   bool IsLoad = isa<VPWidenLoadRecipe, VPWidenLoadEVLRecipe>(R);
   Type *ScalarTy = IsLoad ? cast<VPSingleDefRecipe>(R)->getScalarType()
-                          : Ctx.Types.inferScalarType(R->getOperand(1));
+                          : R->getOperand(1)->getScalarType();
   Type *Ty = toVectorTy(ScalarTy, VF);
-  unsigned AS = cast<PointerType>(Ctx.Types.inferScalarType(getAddr()))
-                    ->getAddressSpace();
+  unsigned AS =
+      cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
   unsigned Opcode = IsLoad ? Instruction::Load : Instruction::Store;
 
   if (!Consecutive) {
@@ -3891,7 +3876,7 @@ InstructionCost VPWidenMemoryRecipe::computeCost(ElementCount VF,
     };
     assert(!IsReverseMask() &&
            "Inconsecutive memory access should not have reverse order");
-    Type *PtrTy = Ctx.Types.inferScalarType(getAddr());
+    Type *PtrTy = getAddr()->getScalarType();
     const Value *Ptr = getAddr()->getUnderlyingValue();
 
     // If the address value is uniform across all lanes, then the address can be
@@ -4004,8 +3989,8 @@ InstructionCost VPWidenLoadEVLRecipe::computeCost(ElementCount VF,
   // TODO: Using getMemoryOpCost() instead of getMemIntrinsicInstrCost  when we
   // don't need to compare to the legacy cost model.
   Type *Ty = toVectorTy(getScalarType(), VF);
-  unsigned AS = cast<PointerType>(Ctx.Types.inferScalarType(getAddr()))
-                    ->getAddressSpace();
+  unsigned AS =
+      cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
   return Ctx.TTI.getMemIntrinsicInstrCost(
       MemIntrinsicCostAttributes(Intrinsic::vp_load, Ty, Alignment, AS),
       Ctx.CostKind);
@@ -4091,9 +4076,9 @@ InstructionCost VPWidenStoreEVLRecipe::computeCost(ElementCount VF,
   // legacy model, it will always calculate the cost of mask.
   // TODO: Using getMemoryOpCost() instead of getMemIntrinsicInstrCost when we
   // don't need to compare to the legacy cost model.
-  Type *Ty = toVectorTy(Ctx.Types.inferScalarType(getStoredValue()), VF);
-  unsigned AS = cast<PointerType>(Ctx.Types.inferScalarType(getAddr()))
-                    ->getAddressSpace();
+  Type *Ty = toVectorTy(getStoredValue()->getScalarType(), VF);
+  unsigned AS =
+      cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
   return Ctx.TTI.getMemIntrinsicInstrCost(
       MemIntrinsicCostAttributes(Intrinsic::vp_store, Ty, Alignment, AS),
       Ctx.CostKind);
@@ -4544,12 +4529,13 @@ InstructionCost VPInterleaveBase::computeCost(ElementCount VF,
         break;
       InsertPosIdx++;
     }
-  Type *ValTy = Ctx.Types.inferScalarType(
-      getNumDefinedValues() > 0 ? getVPValue(InsertPosIdx)
-                                : getStoredValues()[InsertPosIdx]);
+  const VPValue *ValV = getNumDefinedValues() > 0
+                            ? getVPValue(InsertPosIdx)
+                            : getStoredValues()[InsertPosIdx];
+  Type *ValTy = ValV->getScalarType();
   auto *VectorTy = cast<VectorType>(toVectorTy(ValTy, VF));
-  unsigned AS = cast<PointerType>(Ctx.Types.inferScalarType(getAddr()))
-                    ->getAddressSpace();
+  unsigned AS =
+      cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
 
   unsigned InterleaveFactor = IG->getFactor();
   auto *WideVecTy = VectorType::get(ValTy, VF * InterleaveFactor);

diff  --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 3ed50e27c8534..ee5bb20e0089a 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -157,7 +157,6 @@ class SinkStoreInfo {
   VPReplicateRecipe &GroupLeader;
   PredicatedScalarEvolution &PSE;
   const Loop &L;
-  VPTypeAnalysis &TypeInfo;
 
   // Return true if \p A and \p B are known to not alias for all VFs in the
   // plan, checked via the distance between the accesses
@@ -179,9 +178,9 @@ class SinkStoreInfo {
       return false;
 
     const DataLayout &DL = SE.getDataLayout();
-    Type *TyA = TypeInfo.inferScalarType(A->getOperand(0));
+    Type *TyA = A->getOperand(0)->getScalarType();
     uint64_t SizeA = DL.getTypeStoreSize(TyA);
-    Type *TyB = TypeInfo.inferScalarType(B->getOperand(0));
+    Type *TyB = B->getOperand(0)->getScalarType();
     uint64_t SizeB = DL.getTypeStoreSize(TyB);
 
     // Use the maximum store size to ensure no overlap from either direction.
@@ -200,9 +199,9 @@ class SinkStoreInfo {
 public:
   SinkStoreInfo(const SmallPtrSetImpl<VPRecipeBase *> &ExcludeRecipes,
                 VPReplicateRecipe &GroupLeader, PredicatedScalarEvolution &PSE,
-                const Loop &L, VPTypeAnalysis &TypeInfo)
+                const Loop &L)
       : ExcludeRecipes(ExcludeRecipes), GroupLeader(GroupLeader), PSE(PSE),
-        L(L), TypeInfo(TypeInfo) {}
+        L(L) {}
 
   /// Return true if \p R should be skipped during alias checking, either
   /// because it's in the exclude set or because no-alias can be proven via
@@ -254,8 +253,7 @@ canHoistOrSinkWithNoAliasCheck(const MemoryLocation &MemLoc,
 /// Get the value type of the replicate load or store. \p IsLoad indicates
 /// whether it is a load.
 static Type *getLoadStoreValueType(VPReplicateRecipe *R, bool IsLoad) {
-  VPTypeAnalysis TypeInfo(*R->getParent()->getPlan());
-  return TypeInfo.inferScalarType(IsLoad ? R : R->getOperand(0));
+  return (IsLoad ? R : R->getOperand(0))->getScalarType();
 }
 
 /// Collect either replicated Loads or Stores grouped by their address SCEV and
@@ -682,8 +680,7 @@ createScalarIVSteps(VPlan &Plan, InductionDescriptor::InductionKind Kind,
       Builder.createDerivedIV(Kind, FPBinOp, StartV, CanonicalIV, Step);
 
   // Truncate base induction if needed.
-  VPTypeAnalysis TypeInfo(Plan);
-  Type *ResultTy = TypeInfo.inferScalarType(BaseIV);
+  Type *ResultTy = BaseIV->getScalarType();
   if (TruncI) {
     Type *TruncTy = TruncI->getType();
     assert(ResultTy->getScalarSizeInBits() > TruncTy->getScalarSizeInBits() &&
@@ -694,7 +691,7 @@ createScalarIVSteps(VPlan &Plan, InductionDescriptor::InductionKind Kind,
   }
 
   // Truncate step if needed.
-  Type *StepTy = TypeInfo.inferScalarType(Step);
+  Type *StepTy = Step->getScalarType();
   if (ResultTy != StepTy) {
     assert(StepTy->getScalarSizeInBits() > ResultTy->getScalarSizeInBits() &&
            "Not truncating.");
@@ -1017,9 +1014,7 @@ getOptimizableIVOf(VPValue *VPV, PredicatedScalarEvolution &PSE) {
 
 /// Attempts to optimize the induction variable exit values for users in the
 /// early exit block.
-static VPValue *optimizeEarlyExitInductionUser(VPlan &Plan,
-                                               VPTypeAnalysis &TypeInfo,
-                                               VPValue *Op,
+static VPValue *optimizeEarlyExitInductionUser(VPlan &Plan, VPValue *Op,
                                                PredicatedScalarEvolution &PSE) {
   VPValue *Incoming, *Mask;
   if (!match(Op, m_ExtractLane(m_FirstActiveLane(m_VPValue(Mask)),
@@ -1071,7 +1066,6 @@ static VPValue *optimizeEarlyExitInductionUser(VPlan &Plan,
 /// VPDerivedIVRecipe for non-canonical inductions.
 static VPValue *tryToComputeEndValueForInduction(VPWidenInductionRecipe *WideIV,
                                                  VPBuilder &VectorPHBuilder,
-                                                 VPTypeAnalysis &TypeInfo,
                                                  VPValue *VectorTC) {
   auto *WideIntOrFp = dyn_cast<VPWidenIntOrFpInductionRecipe>(WideIV);
   // Truncated wide inductions resume from the last lane of their vector value
@@ -1091,8 +1085,8 @@ static VPValue *tryToComputeEndValueForInduction(VPWidenInductionRecipe *WideIV,
 
   // EndValue is derived from the vector trip count (which has the same type as
   // the widest induction) and thus may be wider than the induction here.
-  Type *ScalarTypeOfWideIV = TypeInfo.inferScalarType(WideIV);
-  if (ScalarTypeOfWideIV != TypeInfo.inferScalarType(EndValue)) {
+  Type *ScalarTypeOfWideIV = WideIV->getScalarType();
+  if (ScalarTypeOfWideIV != EndValue->getScalarType()) {
     EndValue = VectorPHBuilder.createScalarCast(Instruction::Trunc, EndValue,
                                                 ScalarTypeOfWideIV,
                                                 WideIV->getDebugLoc());
@@ -1103,9 +1097,10 @@ static VPValue *tryToComputeEndValueForInduction(VPWidenInductionRecipe *WideIV,
 
 /// Attempts to optimize the induction variable exit values for users in the
 /// exit block coming from the latch in the original scalar loop.
-static VPValue *optimizeLatchExitInductionUser(
-    VPlan &Plan, VPTypeAnalysis &TypeInfo, VPValue *Op,
-    DenseMap<VPValue *, VPValue *> &EndValues, PredicatedScalarEvolution &PSE) {
+static VPValue *
+optimizeLatchExitInductionUser(VPlan &Plan, VPValue *Op,
+                               DenseMap<VPValue *, VPValue *> &EndValues,
+                               PredicatedScalarEvolution &PSE) {
   VPValue *Incoming;
   if (!match(Op, m_ExtractLastLaneOfLastPart(m_VPValue(Incoming))))
     return nullptr;
@@ -1127,11 +1122,11 @@ static VPValue *optimizeLatchExitInductionUser(
   auto *ExtractR = cast<VPInstruction>(Op);
   VPBuilder B(ExtractR);
   VPValue *Step = WideIV->getStepValue();
-  Type *ScalarTy = TypeInfo.inferScalarType(WideIV);
+  Type *ScalarTy = WideIV->getScalarType();
   if (ScalarTy->isIntegerTy())
     return B.createSub(EndValue, Step, DebugLoc::getUnknown(), "ind.escape");
   if (ScalarTy->isPointerTy()) {
-    Type *StepTy = TypeInfo.inferScalarType(Step);
+    Type *StepTy = Step->getScalarType();
     auto *Zero = Plan.getZero(StepTy);
     return B.createPtrAdd(EndValue, B.createSub(Zero, Step),
                           DebugLoc::getUnknown(), "ind.escape");
@@ -1151,7 +1146,6 @@ static VPValue *optimizeLatchExitInductionUser(
 void VPlanTransforms::optimizeInductionLiveOutUsers(
     VPlan &Plan, PredicatedScalarEvolution &PSE, bool FoldTail) {
   // Compute end values for all inductions.
-  VPTypeAnalysis TypeInfo(Plan);
   VPRegionBlock *VectorRegion = Plan.getVectorLoopRegion();
   auto *VectorPH = cast<VPBasicBlock>(VectorRegion->getSinglePredecessor());
   VPBuilder VectorPHBuilder(VectorPH, VectorPH->begin());
@@ -1162,8 +1156,8 @@ void VPlanTransforms::optimizeInductionLiveOutUsers(
     auto *WideIV = dyn_cast<VPWidenInductionRecipe>(&Phi);
     if (!WideIV)
       continue;
-    if (VPValue *EndValue = tryToComputeEndValueForInduction(
-            WideIV, VectorPHBuilder, TypeInfo, ResumeTC))
+    if (VPValue *EndValue =
+            tryToComputeEndValueForInduction(WideIV, VectorPHBuilder, ResumeTC))
       EndValues[WideIV] = EndValue;
   }
 
@@ -1188,10 +1182,10 @@ void VPlanTransforms::optimizeInductionLiveOutUsers(
         VPValue *Escape = nullptr;
         if (PredVPBB == MiddleVPBB)
           Escape = optimizeLatchExitInductionUser(
-              Plan, TypeInfo, ExitIRI->getOperand(Idx), EndValues, PSE);
+              Plan, ExitIRI->getOperand(Idx), EndValues, PSE);
         else
           Escape = optimizeEarlyExitInductionUser(
-              Plan, TypeInfo, ExitIRI->getOperand(Idx), PSE);
+              Plan, ExitIRI->getOperand(Idx), PSE);
         if (Escape)
           ExitIRI->setOperand(Idx, Escape);
       }
@@ -1270,8 +1264,7 @@ getOpcodeOrIntrinsicID(const VPSingleDefRecipe *R) {
 /// Operands are foldable live-ins.
 static VPIRValue *tryToFoldLiveIns(VPSingleDefRecipe &R,
                                    ArrayRef<VPValue *> Operands,
-                                   const DataLayout &DL,
-                                   VPTypeAnalysis &TypeInfo) {
+                                   const DataLayout &DL, LLVMContext &Ctx) {
   auto OpcodeOrIID = getOpcodeOrIntrinsicID(&R);
   if (!OpcodeOrIID)
     return nullptr;
@@ -1292,8 +1285,7 @@ static VPIRValue *tryToFoldLiveIns(VPSingleDefRecipe &R,
       if (R.getNumOperands() != 2)
         return nullptr;
       unsigned ID = OpcodeOrIID->second;
-      return Folder.FoldBinaryIntrinsic(ID, Ops[0], Ops[1],
-                                        TypeInfo.inferScalarType(&R));
+      return Folder.FoldBinaryIntrinsic(ID, Ops[0], Ops[1], R.getScalarType());
     }
     unsigned Opcode = OpcodeOrIID->second;
     if (Instruction::isBinaryOp(Opcode))
@@ -1301,7 +1293,7 @@ static VPIRValue *tryToFoldLiveIns(VPSingleDefRecipe &R,
                               Ops[0], Ops[1]);
     if (Instruction::isCast(Opcode))
       return Folder.FoldCast(static_cast<Instruction::CastOps>(Opcode), Ops[0],
-                             TypeInfo.inferScalarType(R.getVPSingleValue()));
+                             R.getVPSingleValue()->getScalarType());
     switch (Opcode) {
     case VPInstruction::LogicalAnd:
       return Folder.FoldSelect(Ops[0], Ops[1],
@@ -1323,8 +1315,7 @@ static VPIRValue *tryToFoldLiveIns(VPSingleDefRecipe &R,
     }
     case VPInstruction::PtrAdd:
     case VPInstruction::WidePtrAdd:
-      return Folder.FoldGEP(IntegerType::getInt8Ty(TypeInfo.getContext()),
-                            Ops[0], Ops[1],
+      return Folder.FoldGEP(IntegerType::getInt8Ty(Ctx), Ops[0], Ops[1],
                             cast<VPRecipeWithIRFlags>(R).getGEPNoWrapFlags());
     // An extract of a live-in is an extract of a broadcast, so return the
     // broadcasted element.
@@ -1341,8 +1332,7 @@ static VPIRValue *tryToFoldLiveIns(VPSingleDefRecipe &R,
 }
 
 /// Try to simplify logical and bitwise recipes in \p Def.
-static bool simplifyLogicalRecipe(VPSingleDefRecipe *Def,
-                                  VPTypeAnalysis &TypeInfo, VPBuilder &Builder,
+static bool simplifyLogicalRecipe(VPSingleDefRecipe *Def, VPBuilder &Builder,
                                   bool CanCreateNewRecipe) {
   VPlan *Plan = Def->getParent()->getPlan();
 
@@ -1361,8 +1351,7 @@ static bool simplifyLogicalRecipe(VPSingleDefRecipe *Def,
 
   // x | AllOnes -> AllOnes
   if (match(Def, m_c_BinaryOr(m_VPValue(X), m_AllOnes()))) {
-    Def->replaceAllUsesWith(
-        Plan->getAllOnesValue(TypeInfo.inferScalarType(Def)));
+    Def->replaceAllUsesWith(Plan->getAllOnesValue(Def->getScalarType()));
     return true;
   }
 
@@ -1374,14 +1363,13 @@ static bool simplifyLogicalRecipe(VPSingleDefRecipe *Def,
 
   // x | !x -> AllOnes
   if (match(Def, m_c_BinaryOr(m_VPValue(X), m_Not(m_Deferred(X))))) {
-    Def->replaceAllUsesWith(
-        Plan->getAllOnesValue(TypeInfo.inferScalarType(Def)));
+    Def->replaceAllUsesWith(Plan->getAllOnesValue(Def->getScalarType()));
     return true;
   }
 
   // x & 0 -> 0
   if (match(Def, m_c_BinaryAnd(m_VPValue(X), m_ZeroInt()))) {
-    Def->replaceAllUsesWith(Plan->getZero(TypeInfo.inferScalarType(Def)));
+    Def->replaceAllUsesWith(Plan->getZero(Def->getScalarType()));
     return true;
   }
 
@@ -1462,7 +1450,7 @@ static bool simplifyLogicalRecipe(VPSingleDefRecipe *Def,
       match(Def, m_Select(m_VPValue(X),
                           m_OneUse(m_c_BinaryOr(m_VPValue(Y), m_VPValue(Z))),
                           m_Deferred(Y))) &&
-      TypeInfo.inferScalarType(Y)->isIntegerTy(1)) {
+      Y->getScalarType()->isIntegerTy(1)) {
     Def->replaceAllUsesWith(
         Builder.createOr(Y, Builder.createLogicalAnd(X, Z)));
     return true;
@@ -1472,13 +1460,14 @@ static bool simplifyLogicalRecipe(VPSingleDefRecipe *Def,
 }
 
 /// Try to simplify VPSingleDefRecipe \p Def.
-static void simplifyRecipe(VPSingleDefRecipe *Def, VPTypeAnalysis &TypeInfo) {
+static void simplifyRecipe(VPSingleDefRecipe *Def) {
   VPlan *Plan = Def->getParent()->getPlan();
 
   // Simplification of live-in IR values for SingleDef recipes using
   // InstSimplifyFolder.
   const DataLayout &DL = Plan->getDataLayout();
-  if (VPValue *V = tryToFoldLiveIns(*Def, Def->operands(), DL, TypeInfo))
+  if (VPValue *V =
+          tryToFoldLiveIns(*Def, Def->operands(), DL, Plan->getContext()))
     return Def->replaceAllUsesWith(V);
 
   // Fold PredPHI LiveIn -> LiveIn.
@@ -1503,8 +1492,8 @@ static void simplifyRecipe(VPSingleDefRecipe *Def, VPTypeAnalysis &TypeInfo) {
 
   VPValue *A;
   if (match(Def, m_Trunc(m_ZExtOrSExt(m_VPValue(A))))) {
-    Type *TruncTy = TypeInfo.inferScalarType(Def);
-    Type *ATy = TypeInfo.inferScalarType(A);
+    Type *TruncTy = Def->getScalarType();
+    Type *ATy = A->getScalarType();
     if (TruncTy == ATy) {
       Def->replaceAllUsesWith(A);
     } else {
@@ -1528,20 +1517,9 @@ static void simplifyRecipe(VPSingleDefRecipe *Def, VPTypeAnalysis &TypeInfo) {
         Def->replaceAllUsesWith(Trunc);
       }
     }
-#ifndef NDEBUG
-    // Verify that the cached type info is for both A and its users is still
-    // accurate by comparing it to freshly computed types.
-    VPTypeAnalysis TypeInfo2(*Plan);
-    assert(TypeInfo.inferScalarType(A) == TypeInfo2.inferScalarType(A));
-    for (VPUser *U : A->users()) {
-      auto *R = cast<VPRecipeBase>(U);
-      for (VPValue *VPV : R->definedValues())
-        assert(TypeInfo.inferScalarType(VPV) == TypeInfo2.inferScalarType(VPV));
-    }
-#endif
   }
 
-  if (simplifyLogicalRecipe(Def, TypeInfo, Builder, CanCreateNewRecipe))
+  if (simplifyLogicalRecipe(Def, Builder, CanCreateNewRecipe))
     return;
 
   VPValue *X, *Y, *C;
@@ -1552,16 +1530,14 @@ static void simplifyRecipe(VPSingleDefRecipe *Def, VPTypeAnalysis &TypeInfo) {
     return Def->replaceAllUsesWith(A);
 
   if (match(Def, m_c_Mul(m_VPValue(A), m_ZeroInt())))
-    return Def->replaceAllUsesWith(
-        Plan->getZero(TypeInfo.inferScalarType(Def)));
+    return Def->replaceAllUsesWith(Plan->getZero(Def->getScalarType()));
 
   if (CanCreateNewRecipe && match(Def, m_c_Mul(m_VPValue(A), m_AllOnes()))) {
     // Preserve nsw from the Mul on the new Sub.
     VPIRFlags::WrapFlagsTy NW = {
         false, cast<VPRecipeWithIRFlags>(Def)->hasNoSignedWrap()};
-    return Def->replaceAllUsesWith(
-        Builder.createSub(Plan->getZero(TypeInfo.inferScalarType(A)), A,
-                          Def->getDebugLoc(), "", NW));
+    return Def->replaceAllUsesWith(Builder.createSub(
+        Plan->getZero(A->getScalarType()), A, Def->getDebugLoc(), "", NW));
   }
 
   if (CanCreateNewRecipe &&
@@ -1669,14 +1645,13 @@ static void simplifyRecipe(VPSingleDefRecipe *Def, VPTypeAnalysis &TypeInfo) {
   // Remove redundant DerviedIVs, that is 0 + A * 1 -> A and 0 + 0 * x -> 0.
   if ((match(Def, m_DerivedIV(m_ZeroInt(), m_VPValue(A), m_One())) ||
        match(Def, m_DerivedIV(m_ZeroInt(), m_ZeroInt(), m_VPValue()))) &&
-      TypeInfo.inferScalarType(Def->getOperand(1)) ==
-          TypeInfo.inferScalarType(Def))
+      Def->getOperand(1)->getScalarType() == Def->getScalarType())
     return Def->replaceAllUsesWith(Def->getOperand(1));
 
   if (match(Def, m_VPInstruction<VPInstruction::WideIVStep>(m_VPValue(X),
                                                             m_One()))) {
-    Type *WideStepTy = TypeInfo.inferScalarType(Def);
-    if (TypeInfo.inferScalarType(X) != WideStepTy)
+    Type *WideStepTy = Def->getScalarType();
+    if (X->getScalarType() != WideStepTy)
       X = Builder.createWidenCast(Instruction::Trunc, X, WideStepTy);
     Def->replaceAllUsesWith(X);
     return;
@@ -1687,7 +1662,7 @@ static void simplifyRecipe(VPSingleDefRecipe *Def, VPTypeAnalysis &TypeInfo) {
   if (match(Def, m_Intrinsic<Intrinsic::vp_merge>(m_True(), m_VPValue(A),
                                                   m_VPValue(X), m_VPValue())) &&
       match(A, m_c_BinaryOr(m_Specific(X), m_VPValue(Y))) &&
-      TypeInfo.inferScalarType(Def)->isIntegerTy(1)) {
+      Def->getScalarType()->isIntegerTy(1)) {
     Def->setOperand(1, Def->getOperand(0));
     Def->setOperand(0, Y);
     return;
@@ -1853,11 +1828,10 @@ static void simplifyRecipe(VPSingleDefRecipe *Def, VPTypeAnalysis &TypeInfo) {
 void VPlanTransforms::simplifyRecipes(VPlan &Plan) {
   ReversePostOrderTraversal<VPBlockDeepTraversalWrapper<VPBlockBase *>> RPOT(
       Plan.getEntry());
-  VPTypeAnalysis TypeInfo(Plan);
   for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(RPOT)) {
     for (VPRecipeBase &R : make_early_inc_range(*VPBB))
       if (auto *Def = dyn_cast<VPSingleDefRecipe>(&R))
-        simplifyRecipe(Def, TypeInfo);
+        simplifyRecipe(Def);
   }
 }
 
@@ -2387,9 +2361,8 @@ bool VPlanTransforms::simplifyKnownEVL(VPlan &Plan, ElementCount VF,
       if (Trunc != AVL) {
         auto *TruncR = cast<VPSingleDefRecipe>(Trunc);
         const DataLayout &DL = Plan.getDataLayout();
-        VPTypeAnalysis TypeInfo(Plan);
-        if (VPValue *Folded =
-                tryToFoldLiveIns(*TruncR, TruncR->operands(), DL, TypeInfo))
+        if (VPValue *Folded = tryToFoldLiveIns(*TruncR, TruncR->operands(), DL,
+                                               Plan.getContext()))
           Trunc = Folded;
       }
       R.getVPSingleValue()->replaceAllUsesWith(Trunc);
@@ -2477,11 +2450,9 @@ struct VPCSEDenseMapInfo : public DenseMapInfo<VPSingleDefRecipe *> {
 
   /// Hash the underlying data of \p Def.
   static unsigned getHashValue(const VPSingleDefRecipe *Def) {
-    const VPlan *Plan = Def->getParent()->getPlan();
-    VPTypeAnalysis TypeInfo(*Plan);
     hash_code Result = hash_combine(
         Def->getVPRecipeID(), getOpcodeOrIntrinsicID(Def),
-        getGEPSourceElementType(Def), TypeInfo.inferScalarType(Def),
+        getGEPSourceElementType(Def), Def->getScalarType(),
         vputils::isSingleScalar(Def), hash_combine_range(Def->operands()));
     if (auto *RFlags = dyn_cast<VPRecipeWithIRFlags>(Def))
       if (RFlags->hasPredicate())
@@ -2521,9 +2492,7 @@ struct VPCSEDenseMapInfo : public DenseMapInfo<VPSingleDefRecipe *> {
          (RegionR && RegionR->isReplicator())) &&
         L->getParent() != R->getParent())
       return false;
-    const VPlan *Plan = L->getParent()->getPlan();
-    VPTypeAnalysis TypeInfo(*Plan);
-    return TypeInfo.inferScalarType(L) == TypeInfo.inferScalarType(R);
+    return L->getScalarType() == R->getScalarType();
   }
 };
 } // end anonymous namespace
@@ -2664,7 +2633,6 @@ void VPlanTransforms::truncateToMinimalBitwidths(
   // other uses have 
diff erent types for their operands, making them invalidly
   // typed.
   DenseMap<VPValue *, VPWidenCastRecipe *> ProcessedTruncs;
-  VPTypeAnalysis TypeInfo(Plan);
   VPBasicBlock *PH = Plan.getVectorPreheader();
   for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
            vp_depth_first_deep(Plan.getVectorLoopRegion()))) {
@@ -2686,7 +2654,7 @@ void VPlanTransforms::truncateToMinimalBitwidths(
       if (isa<VPReplicateRecipe, VPWidenCastRecipe>(&R))
         continue;
 
-      Type *OldResTy = TypeInfo.inferScalarType(ResultVPV);
+      Type *OldResTy = ResultVPV->getScalarType();
       unsigned OldResSizeInBits = OldResTy->getScalarSizeInBits();
       assert(OldResTy->isIntegerTy() && "only integer types supported");
       (void)OldResSizeInBits;
@@ -2721,8 +2689,7 @@ void VPlanTransforms::truncateToMinimalBitwidths(
           match(&R, m_Select(m_VPValue(), m_VPValue(), m_VPValue())) ? 1 : 0;
       SmallVector<VPValue *> NewOperands(R.operands());
       for (VPValue *&Op : drop_begin(NewOperands, StartIdx)) {
-        unsigned OpSizeInBits =
-            TypeInfo.inferScalarType(Op)->getScalarSizeInBits();
+        unsigned OpSizeInBits = Op->getScalarType()->getScalarSizeInBits();
         if (OpSizeInBits == NewResSizeInBits)
           continue;
         assert(OpSizeInBits > NewResSizeInBits && "nothing to truncate");
@@ -2997,35 +2964,33 @@ static std::optional<Intrinsic::ID> getVPDivRemIntrinsic(Intrinsic::ID IntrID) {
 /// recipe could be created.
 /// \p HeaderMask  Header Mask.
 /// \p CurRecipe   Recipe to be transform.
-/// \p TypeInfo    VPlan-based type analysis.
 /// \p EVL         The explicit vector length parameter of vector-predication
 /// intrinsics.
 static VPRecipeBase *optimizeMaskToEVL(VPValue *HeaderMask,
-                                       VPRecipeBase &CurRecipe,
-                                       VPTypeAnalysis &TypeInfo, VPValue &EVL) {
+                                       VPRecipeBase &CurRecipe, VPValue &EVL) {
   VPlan *Plan = CurRecipe.getParent()->getPlan();
   DebugLoc DL = CurRecipe.getDebugLoc();
   VPValue *Addr, *Mask, *EndPtr;
 
   /// Adjust any end pointers so that they point to the end of EVL lanes not VF.
-  auto AdjustEndPtr = [&CurRecipe, &EVL, &TypeInfo](VPValue *EndPtr) {
+  auto AdjustEndPtr = [&CurRecipe, &EVL](VPValue *EndPtr) {
     auto *EVLEndPtr = cast<VPVectorEndPointerRecipe>(EndPtr)->clone();
     EVLEndPtr->insertBefore(&CurRecipe);
     // Cast EVL (i32) to match the VF operand's type.
     VPValue *EVLAsVF = VPBuilder(EVLEndPtr).createScalarZExtOrTrunc(
-        &EVL, TypeInfo.inferScalarType(EVLEndPtr->getOperand(1)),
-        TypeInfo.inferScalarType(&EVL), DebugLoc::getUnknown());
+        &EVL, EVLEndPtr->getOperand(1)->getScalarType(), EVL.getScalarType(),
+        DebugLoc::getUnknown());
     EVLEndPtr->setOperand(1, EVLAsVF);
     return EVLEndPtr;
   };
 
-  auto GetVPReverse = [&CurRecipe, &EVL, &TypeInfo, Plan,
+  auto GetVPReverse = [&CurRecipe, &EVL, Plan,
                        DL](VPValue *V) -> VPWidenIntrinsicRecipe * {
     if (!V)
       return nullptr;
     auto *Reverse = new VPWidenIntrinsicRecipe(
         Intrinsic::experimental_vp_reverse, {V, Plan->getTrue(), &EVL},
-        TypeInfo.inferScalarType(V), {}, {}, DL);
+        V->getScalarType(), {}, {}, DL);
     Reverse->insertBefore(&CurRecipe);
     return Reverse;
   };
@@ -3046,9 +3011,9 @@ static VPRecipeBase *optimizeMaskToEVL(VPValue *HeaderMask,
     auto *LoadR = new VPWidenLoadEVLRecipe(
         *cast<VPWidenLoadRecipe>(ReversedVal), Addr, EVL, Mask);
     LoadR->insertBefore(&CurRecipe);
-    return new VPWidenIntrinsicRecipe(
-        Intrinsic::experimental_vp_reverse, {LoadR, Plan->getTrue(), &EVL},
-        TypeInfo.inferScalarType(LoadR), {}, {}, DL);
+    return new VPWidenIntrinsicRecipe(Intrinsic::experimental_vp_reverse,
+                                      {LoadR, Plan->getTrue(), &EVL},
+                                      LoadR->getScalarType(), {}, {}, DL);
   }
 
   VPValue *Stride;
@@ -3096,13 +3061,13 @@ static VPRecipeBase *optimizeMaskToEVL(VPValue *HeaderMask,
                                  m_VPValue(RHS))))
     return new VPWidenIntrinsicRecipe(
         Intrinsic::vp_merge, {Mask ? Mask : Plan->getTrue(), LHS, RHS, &EVL},
-        TypeInfo.inferScalarType(LHS), {}, {}, DL);
+        LHS->getScalarType(), {}, {}, DL);
 
   if (match(&CurRecipe, m_LastActiveLane(m_Specific(HeaderMask)))) {
-    Type *Ty = TypeInfo.inferScalarType(CurRecipe.getVPSingleValue());
-    VPValue *ZExt = VPBuilder(&CurRecipe)
-                        .createScalarZExtOrTrunc(
-                            &EVL, Ty, TypeInfo.inferScalarType(&EVL), DL);
+    Type *Ty = CurRecipe.getVPSingleValue()->getScalarType();
+    VPValue *ZExt =
+        VPBuilder(&CurRecipe)
+            .createScalarZExtOrTrunc(&EVL, Ty, EVL.getScalarType(), DL);
     return new VPInstruction(
         Instruction::Sub, {ZExt, Plan->getConstantInt(Ty, 1)},
         VPIRFlags::getDefaultFlags(Instruction::Sub), {}, DL);
@@ -3112,9 +3077,9 @@ static VPRecipeBase *optimizeMaskToEVL(VPValue *HeaderMask,
   if (match(&CurRecipe,
             m_c_BinaryOr(m_VPValue(LHS),
                          m_LogicalAnd(m_Specific(HeaderMask), m_VPValue(RHS)))))
-    return new VPWidenIntrinsicRecipe(
-        Intrinsic::vp_merge, {RHS, Plan->getTrue(), LHS, &EVL},
-        TypeInfo.inferScalarType(LHS), {}, {}, DL);
+    return new VPWidenIntrinsicRecipe(Intrinsic::vp_merge,
+                                      {RHS, Plan->getTrue(), LHS, &EVL},
+                                      LHS->getScalarType(), {}, {}, DL);
 
   if (auto *IntrR = dyn_cast<VPWidenIntrinsicRecipe>(&CurRecipe))
     if (auto VPID = getVPDivRemIntrinsic(IntrR->getVectorIntrinsicID()))
@@ -3144,11 +3109,10 @@ void VPlanTransforms::optimizeEVLMasks(VPlan &Plan) {
   if (!HeaderMask)
     return;
 
-  VPTypeAnalysis TypeInfo(Plan);
   SmallVector<VPRecipeBase *> OldRecipes;
   for (VPUser *U : collectUsersRecursively(HeaderMask)) {
     VPRecipeBase *R = cast<VPRecipeBase>(U);
-    if (auto *NewR = optimizeMaskToEVL(HeaderMask, *R, TypeInfo, *EVL)) {
+    if (auto *NewR = optimizeMaskToEVL(HeaderMask, *R, *EVL)) {
       NewR->insertBefore(R);
       for (auto [Old, New] :
            zip_equal(R->definedValues(), NewR->definedValues()))
@@ -3165,14 +3129,13 @@ void VPlanTransforms::optimizeEVLMasks(VPlan &Plan) {
       auto *LogicalAnd = cast<VPInstruction>(U);
       auto *Merge = new VPWidenIntrinsicRecipe(
           Intrinsic::vp_merge, {Plan.getTrue(), Mask, Plan.getFalse(), EVL},
-          TypeInfo.inferScalarType(Mask), {}, {}, LogicalAnd->getDebugLoc());
+          Mask->getScalarType(), {}, {}, LogicalAnd->getDebugLoc());
       Merge->insertBefore(LogicalAnd);
       LogicalAnd->replaceAllUsesWith(Merge);
       OldRecipes.push_back(LogicalAnd);
     }
   }
 
-  // Erase old recipes at the end so we don't invalidate TypeInfo.
   for (VPRecipeBase *R : reverse(OldRecipes)) {
     SmallVector<VPValue *> PossiblyDead(R->operands());
     R->eraseFromParent();
@@ -3185,16 +3148,14 @@ void VPlanTransforms::optimizeEVLMasks(VPlan &Plan) {
 /// VF to use the EVL instead to avoid incorrect updates on the penultimate
 /// iteration.
 static void fixupVFUsersForEVL(VPlan &Plan, VPValue &EVL) {
-  VPTypeAnalysis TypeInfo(Plan);
   VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
   VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();
 
   // EVL is i32 but VF/VFxUF are IdxTy. Convert as needed.
   VPValue *EVLAsIdx =
       VPBuilder::getToInsertAfter(EVL.getDefiningRecipe())
-          .createScalarZExtOrTrunc(&EVL, Plan.getVF().getType(),
-                                   TypeInfo.inferScalarType(&EVL),
-                                   DebugLoc::getUnknown());
+          .createScalarZExtOrTrunc(&EVL, Plan.getVF().getScalarType(),
+                                   EVL.getScalarType(), DebugLoc::getUnknown());
 
   assert(all_of(Plan.getVF().users(),
                 [&Plan](VPUser *U) {
@@ -3235,8 +3196,8 @@ static void fixupVFUsersForEVL(VPlan &Plan, VPValue &EVL) {
     // Emit VPScalarCastRecipe in preheader if VF is not a 32 bits integer.
     VPBuilder Builder(LoopRegion->getPreheaderVPBB());
     MaxEVL = Builder.createScalarZExtOrTrunc(
-        MaxEVL, Type::getInt32Ty(Plan.getContext()),
-        TypeInfo.inferScalarType(MaxEVL), DebugLoc::getUnknown());
+        MaxEVL, Type::getInt32Ty(Plan.getContext()), MaxEVL->getScalarType(),
+        DebugLoc::getUnknown());
 
     Builder.setInsertPoint(Header, Header->getFirstNonPhi());
     VPValue *PrevEVL = Builder.createScalarPhi(
@@ -3255,8 +3216,7 @@ static void fixupVFUsersForEVL(VPlan &Plan, VPValue &EVL) {
         VPWidenIntrinsicRecipe *VPSplice = new VPWidenIntrinsicRecipe(
             Intrinsic::experimental_vp_splice,
             {V1, V2, Imm, Plan.getTrue(), PrevEVL, &EVL},
-            TypeInfo.inferScalarType(R.getVPSingleValue()), {}, {},
-            R.getDebugLoc());
+            R.getVPSingleValue()->getScalarType(), {}, {}, R.getDebugLoc());
         VPSplice->insertBefore(&R);
         R.getVPSingleValue()->replaceAllUsesWith(VPSplice);
       }
@@ -3285,7 +3245,7 @@ static void fixupVFUsersForEVL(VPlan &Plan, VPValue &EVL) {
   // icmp ult step-vector, EVL
   VPRecipeBase *EVLR = EVL.getDefiningRecipe();
   VPBuilder Builder(EVLR->getParent(), std::next(EVLR->getIterator()));
-  Type *EVLType = TypeInfo.inferScalarType(&EVL);
+  Type *EVLType = EVL.getScalarType();
   VPValue *EVLMask = Builder.createICmp(
       CmpInst::ICMP_ULT,
       Builder.createNaryOp(VPInstruction::StepVector, {}, EVLType), &EVL);
@@ -3493,7 +3453,7 @@ void VPlanTransforms::convertEVLExitCond(VPlan &Plan) {
          "Expected BranchOnCond with ICmp comparing CanIV + VFxUF with vector "
          "trip count");
 
-  Type *AVLTy = VPTypeAnalysis(Plan).inferScalarType(AVLNext);
+  Type *AVLTy = AVLNext->getScalarType();
   VPBuilder Builder(LatchBr);
   LatchBr->setOperand(
       0, Builder.createICmp(CmpInst::ICMP_EQ, AVLNext, Plan.getZero(AVLTy)));
@@ -3791,8 +3751,7 @@ void VPlanTransforms::createInterleaveGroups(
 ///    No successors
 ///  }
 static void
-expandVPWidenIntOrFpInduction(VPWidenIntOrFpInductionRecipe *WidenIVR,
-                              VPTypeAnalysis &TypeInfo) {
+expandVPWidenIntOrFpInduction(VPWidenIntOrFpInductionRecipe *WidenIVR) {
   VPlan *Plan = WidenIVR->getParent()->getPlan();
   VPValue *Start = WidenIVR->getStartValue();
   VPValue *Step = WidenIVR->getStepValue();
@@ -3863,8 +3822,7 @@ expandVPWidenIntOrFpInduction(VPWidenIntOrFpInductionRecipe *WidenIVR,
       VF = Builder.createScalarCast(Instruction::CastOps::UIToFP, VF, StepTy,
                                     DL);
     else
-      VF = Builder.createScalarZExtOrTrunc(VF, StepTy,
-                                           TypeInfo.inferScalarType(VF), DL);
+      VF = Builder.createScalarZExtOrTrunc(VF, StepTy, VF->getScalarType(), DL);
 
     Inc = Builder.createNaryOp(MulOp, {Step, VF}, Flags);
     Inc = Builder.createNaryOp(VPInstruction::Broadcast, Inc);
@@ -3902,8 +3860,7 @@ expandVPWidenIntOrFpInduction(VPWidenIntOrFpInductionRecipe *WidenIVR,
 ///      EMIT %ptr.ind = ptradd %pointer.phi, %vf
 ///      EMIT branch-on-count ...
 ///  }
-static void expandVPWidenPointerInduction(VPWidenPointerInductionRecipe *R,
-                                          VPTypeAnalysis &TypeInfo) {
+static void expandVPWidenPointerInduction(VPWidenPointerInductionRecipe *R) {
   VPlan *Plan = R->getParent()->getPlan();
   VPValue *Start = R->getStartValue();
   VPValue *Step = R->getStepValue();
@@ -3912,7 +3869,7 @@ static void expandVPWidenPointerInduction(VPWidenPointerInductionRecipe *R,
   assert(R->getInductionDescriptor().getKind() ==
              InductionDescriptor::IK_PtrInduction &&
          "Not a pointer induction according to InductionDescriptor!");
-  assert(TypeInfo.inferScalarType(R)->isPointerTy() && "Unexpected type.");
+  assert(R->getScalarType()->isPointerTy() && "Unexpected type.");
   assert(!R->onlyScalarsGenerated(Plan->hasScalableVF()) &&
          "Recipe should have been replaced");
 
@@ -3925,7 +3882,7 @@ static void expandVPWidenPointerInduction(VPWidenPointerInductionRecipe *R,
   // Create actual address geps that use the pointer phi as base and a
   // vectorized version of the step value (<step*0, ..., step*N>) as offset.
   Builder.setInsertPoint(R->getParent(), R->getParent()->getFirstNonPhi());
-  Type *StepTy = TypeInfo.inferScalarType(Step);
+  Type *StepTy = Step->getScalarType();
   VPValue *Offset = Builder.createNaryOp(VPInstruction::StepVector, {}, StepTy);
   Offset = Builder.createOverflowingOp(Instruction::Mul, {Offset, Step});
   VPValue *PtrAdd =
@@ -3935,8 +3892,7 @@ static void expandVPWidenPointerInduction(VPWidenPointerInductionRecipe *R,
   // Create the backedge value for the scalar pointer phi.
   VPBasicBlock *ExitingBB = Plan->getVectorLoopRegion()->getExitingBasicBlock();
   Builder.setInsertPoint(ExitingBB, ExitingBB->getTerminator()->getIterator());
-  VF = Builder.createScalarZExtOrTrunc(VF, StepTy, TypeInfo.inferScalarType(VF),
-                                       DL);
+  VF = Builder.createScalarZExtOrTrunc(VF, StepTy, VF->getScalarType(), DL);
   VPValue *Inc = Builder.createOverflowingOp(Instruction::Mul, {Step, VF});
 
   VPValue *InductionGEP =
@@ -3945,13 +3901,13 @@ static void expandVPWidenPointerInduction(VPWidenPointerInductionRecipe *R,
 }
 
 /// Expand a VPDerivedIVRecipe into executable recipes.
-static void expandVPDerivedIV(VPDerivedIVRecipe *R, VPTypeAnalysis &TypeInfo) {
+static void expandVPDerivedIV(VPDerivedIVRecipe *R) {
   VPBuilder Builder(R);
   VPIRValue *Start = R->getStartValue();
   VPValue *Step = R->getStepValue();
   VPValue *Index = R->getIndex();
-  Type *StepTy = TypeInfo.inferScalarType(Step);
-  Type *IndexTy = TypeInfo.inferScalarType(Index);
+  Type *StepTy = Step->getScalarType();
+  Type *IndexTy = Index->getScalarType();
   Index = StepTy->isIntegerTy()
               ? Builder.createScalarSExtOrTrunc(
                     Index, StepTy, IndexTy, DebugLoc::getCompilerGenerated())
@@ -3959,7 +3915,7 @@ static void expandVPDerivedIV(VPDerivedIVRecipe *R, VPTypeAnalysis &TypeInfo) {
                                          DebugLoc::getCompilerGenerated());
   switch (R->getInductionKind()) {
   case InductionDescriptor::IK_IntInduction: {
-    assert(TypeInfo.inferScalarType(Index) == TypeInfo.inferScalarType(Start) &&
+    assert(Index->getScalarType() == Start->getScalarType() &&
            "Index type does not match StartValue type");
     return R->replaceAllUsesWith(Builder.createAdd(
         Start, Builder.createOverflowingOp(Instruction::Mul, {Index, Step})));
@@ -4050,15 +4006,13 @@ void VPlanTransforms::expandBranchOnTwoConds(VPlan &Plan) {
 }
 
 void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
-  VPTypeAnalysis TypeInfo(Plan);
-  SmallVector<VPRecipeBase *> ToRemove;
   for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
            vp_depth_first_deep(Plan.getEntry()))) {
     for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
       VPBuilder Builder(&R);
       if (auto *WidenIVR = dyn_cast<VPWidenIntOrFpInductionRecipe>(&R)) {
-        expandVPWidenIntOrFpInduction(WidenIVR, TypeInfo);
-        ToRemove.push_back(WidenIVR);
+        expandVPWidenIntOrFpInduction(WidenIVR);
+        WidenIVR->eraseFromParent();
         continue;
       }
 
@@ -4069,23 +4023,23 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
           VPValue *PtrAdd =
               scalarizeVPWidenPointerInduction(WidenIVR, Plan, Builder);
           WidenIVR->replaceAllUsesWith(PtrAdd);
-          ToRemove.push_back(WidenIVR);
+          WidenIVR->eraseFromParent();
           continue;
         }
-        expandVPWidenPointerInduction(WidenIVR, TypeInfo);
-        ToRemove.push_back(WidenIVR);
+        expandVPWidenPointerInduction(WidenIVR);
+        WidenIVR->eraseFromParent();
         continue;
       }
 
       if (auto *DerivedIVR = dyn_cast<VPDerivedIVRecipe>(&R)) {
-        expandVPDerivedIV(DerivedIVR, TypeInfo);
-        ToRemove.push_back(DerivedIVR);
+        expandVPDerivedIV(DerivedIVR);
+        DerivedIVR->eraseFromParent();
         continue;
       }
 
       if (auto *WideCanIV = dyn_cast<VPWidenCanonicalIVRecipe>(&R)) {
         VPValue *CanIV = WideCanIV->getCanonicalIV();
-        Type *CanIVTy = TypeInfo.inferScalarType(CanIV);
+        Type *CanIVTy = CanIV->getScalarType();
         VPValue *Step = WideCanIV->getStepValue();
         if (!Step) {
           assert(Plan.getConcreteUF() == 1 &&
@@ -4100,7 +4054,7 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
             Builder.createAdd(CanIV, Step, WideCanIV->getDebugLoc(), "vec.iv",
                               WideCanIV->getNoWrapFlags());
         WideCanIV->replaceAllUsesWith(CanVecIV);
-        ToRemove.push_back(WideCanIV);
+        WideCanIV->eraseFromParent();
         continue;
       }
 
@@ -4112,7 +4066,8 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
                                         Blend->getIncomingValue(I), Select,
                                         R.getDebugLoc(), "predphi", *Blend);
         Blend->replaceAllUsesWith(Select);
-        ToRemove.push_back(Blend);
+        Blend->eraseFromParent();
+        continue;
       }
 
       if (auto *VEPR = dyn_cast<VPVectorEndPointerRecipe>(&R)) {
@@ -4121,11 +4076,13 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
                  "Expected unroller to have materialized offset for UF != 1");
           VEPR->materializeOffset();
         }
+        continue;
       }
 
       if (auto *Expr = dyn_cast<VPExpressionRecipe>(&R)) {
         Expr->decompose();
-        ToRemove.push_back(Expr);
+        Expr->eraseFromParent();
+        continue;
       }
 
       // Expand LastActiveLane into Not + FirstActiveLane + Sub.
@@ -4151,7 +4108,7 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
                               LastActiveL->getDebugLoc(), "last.active.lane");
 
         LastActiveL->replaceAllUsesWith(LastLane);
-        ToRemove.push_back(LastActiveL);
+        LastActiveL->eraseFromParent();
         continue;
       }
 
@@ -4162,7 +4119,7 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
                "Unmasked MaskedCond should be simplified earlier");
         VPI->replaceAllUsesWith(Builder.createNaryOp(
             VPInstruction::LogicalAnd, {VPI->getMask(), VPI->getOperand(0)}));
-        ToRemove.push_back(VPI);
+        VPI->eraseFromParent();
         continue;
       }
 
@@ -4175,7 +4132,7 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
             Instruction::Add, VPI->operands(), VPI->getNoWrapFlags(),
             VPI->getDebugLoc());
         VPI->replaceAllUsesWith(Add);
-        ToRemove.push_back(VPI);
+        VPI->eraseFromParent();
         continue;
       }
 
@@ -4186,7 +4143,7 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
         DebugLoc DL = BranchOnCountInst->getDebugLoc();
         VPValue *Cond = Builder.createICmp(CmpInst::ICMP_EQ, IV, TC, DL);
         Builder.createNaryOp(VPInstruction::BranchOnCond, Cond, DL);
-        ToRemove.push_back(BranchOnCountInst);
+        BranchOnCountInst->eraseFromParent();
         continue;
       }
 
@@ -4198,8 +4155,8 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
 
       // Expand WideIVStep.
       auto *VPI = cast<VPInstruction>(&R);
-      Type *IVTy = TypeInfo.inferScalarType(VPI);
-      if (TypeInfo.inferScalarType(VectorStep) != IVTy) {
+      Type *IVTy = VPI->getScalarType();
+      if (VectorStep->getScalarType() != IVTy) {
         Instruction::CastOps CastOp = IVTy->isFloatingPointTy()
                                           ? Instruction::UIToFP
                                           : Instruction::Trunc;
@@ -4207,7 +4164,7 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
       }
 
       assert(!match(ScalarStep, m_One()) && "Expected non-unit scalar-step");
-      if (TypeInfo.inferScalarType(ScalarStep) != IVTy) {
+      if (ScalarStep->getScalarType() != IVTy) {
         ScalarStep =
             Builder.createWidenCast(Instruction::Trunc, ScalarStep, IVTy);
       }
@@ -4226,12 +4183,9 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
           MulOpc, {VectorStep, ScalarStep}, Flags, R.getDebugLoc());
       VectorStep = Mul;
       VPI->replaceAllUsesWith(VectorStep);
-      ToRemove.push_back(VPI);
+      VPI->eraseFromParent();
     }
   }
-
-  for (VPRecipeBase *R : ToRemove)
-    R->eraseFromParent();
 }
 
 void VPlanTransforms::handleUncountableEarlyExits(VPlan &Plan,
@@ -4467,7 +4421,7 @@ void VPlanTransforms::handleUncountableEarlyExits(VPlan &Plan,
 static VPExpressionRecipe *
 tryToMatchAndCreateExtendedReduction(VPReductionRecipe *Red, VPCostContext &Ctx,
                                      VFRange &Range) {
-  Type *RedTy = Ctx.Types.inferScalarType(Red);
+  Type *RedTy = Red->getScalarType();
   VPValue *VecOp = Red->getVecOp();
 
   assert(!Red->isPartialReduction() &&
@@ -4501,8 +4455,7 @@ tryToMatchAndCreateExtendedReduction(VPReductionRecipe *Red, VPCostContext &Ctx,
   if (match(VecOp, m_Isa<VPWidenCastRecipe>(m_ZExtOrSExt(m_VPValue(A)))) &&
       IsExtendedRedValidAndClampRange(
           RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind()),
-          cast<VPWidenCastRecipe>(VecOp)->getOpcode(),
-          Ctx.Types.inferScalarType(A)))
+          cast<VPWidenCastRecipe>(VecOp)->getOpcode(), A->getScalarType()))
     return new VPExpressionRecipe(cast<VPWidenCastRecipe>(VecOp), Red);
 
   return nullptr;
@@ -4527,7 +4480,7 @@ tryToMatchAndCreateMulAccumulateReduction(VPReductionRecipe *Red,
 
   assert(!Red->isPartialReduction() &&
          "This path does not support partial reductions");
-  Type *RedTy = Ctx.Types.inferScalarType(Red);
+  Type *RedTy = Red->getScalarType();
 
   // Clamp the range if using multiply-accumulate-reduction is profitable.
   auto IsMulAccValidAndClampRange =
@@ -4536,8 +4489,7 @@ tryToMatchAndCreateMulAccumulateReduction(VPReductionRecipe *Red,
     return LoopVectorizationPlanner::getDecisionAndClampRange(
         [&](ElementCount VF) {
           TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
-          Type *SrcTy =
-              Ext0 ? Ctx.Types.inferScalarType(Ext0->getOperand(0)) : RedTy;
+          Type *SrcTy = Ext0 ? Ext0->getOperand(0)->getScalarType() : RedTy;
           InstructionCost MulAccCost;
 
           // getMulAccReductionCost for in-loop reductions does not support
@@ -4588,12 +4540,12 @@ tryToMatchAndCreateMulAccumulateReduction(VPReductionRecipe *Red,
   // creates two uniform extends that can more easily be matched by the rest of
   // the bundling code. The ExtB reference, ValB and operand 1 of Mul are all
   // replaced with the new extend of the constant.
-  auto ExtendAndReplaceConstantOp = [&Ctx](VPWidenCastRecipe *ExtA,
-                                           VPWidenCastRecipe *&ExtB,
-                                           VPValue *&ValB, VPWidenRecipe *Mul) {
+  auto ExtendAndReplaceConstantOp = [](VPWidenCastRecipe *ExtA,
+                                       VPWidenCastRecipe *&ExtB, VPValue *&ValB,
+                                       VPWidenRecipe *Mul) {
     if (!ExtA || ExtB || !isa<VPIRValue>(ValB))
       return;
-    Type *NarrowTy = Ctx.Types.inferScalarType(ExtA->getOperand(0));
+    Type *NarrowTy = ExtA->getOperand(0)->getScalarType();
     Instruction::CastOps ExtOpc = ExtA->getOpcode();
     const APInt *Const;
     if (!match(ValB, m_APInt(Const)) ||
@@ -4608,7 +4560,7 @@ tryToMatchAndCreateMulAccumulateReduction(VPReductionRecipe *Red,
     VPBuilder Builder(Mul);
     auto *Trunc =
         Builder.createWidenCast(Instruction::CastOps::Trunc, ValB, NarrowTy);
-    Type *WideTy = Ctx.Types.inferScalarType(ExtA);
+    Type *WideTy = ExtA->getScalarType();
     ValB = ExtB = Builder.createWidenCast(ExtOpc, Trunc, WideTy);
     Mul->setOperand(1, ExtB);
   };
@@ -4891,8 +4843,7 @@ void VPlanTransforms::hoistPredicatedLoads(VPlan &Plan,
 
 static bool
 canSinkStoreWithNoAliasCheck(ArrayRef<VPReplicateRecipe *> StoresToSink,
-                             PredicatedScalarEvolution &PSE, const Loop &L,
-                             VPTypeAnalysis &TypeInfo) {
+                             PredicatedScalarEvolution &PSE, const Loop &L) {
   auto StoreLoc = vputils::getMemoryLocation(*StoresToSink.front());
   if (!StoreLoc || !StoreLoc->AATags.Scope)
     return false;
@@ -4904,7 +4855,7 @@ canSinkStoreWithNoAliasCheck(ArrayRef<VPReplicateRecipe *> StoresToSink,
 
   VPBasicBlock *FirstBB = StoresToSink.front()->getParent();
   VPBasicBlock *LastBB = StoresToSink.back()->getParent();
-  SinkStoreInfo SinkInfo(StoresToSinkSet, *StoresToSink[0], PSE, L, TypeInfo);
+  SinkStoreInfo SinkInfo(StoresToSinkSet, *StoresToSink[0], PSE, L);
   return canHoistOrSinkWithNoAliasCheck(*StoreLoc, FirstBB, LastBB, SinkInfo);
 }
 
@@ -4916,10 +4867,8 @@ void VPlanTransforms::sinkPredicatedStores(VPlan &Plan,
   if (Groups.empty())
     return;
 
-  VPTypeAnalysis TypeInfo(Plan);
-
   for (auto &Group : Groups) {
-    if (!canSinkStoreWithNoAliasCheck(Group, PSE, *L, TypeInfo))
+    if (!canSinkStoreWithNoAliasCheck(Group, PSE, *L))
       continue;
 
     // Use the last (most dominated) store's location for the unconditional
@@ -5000,7 +4949,7 @@ void VPlanTransforms::materializeBackedgeTakenCount(VPlan &Plan,
     return;
 
   VPBuilder Builder(VectorPH, VectorPH->begin());
-  auto *TCTy = VPTypeAnalysis(Plan).inferScalarType(Plan.getTripCount());
+  auto *TCTy = Plan.getTripCount()->getScalarType();
   auto *TCMO =
       Builder.createSub(Plan.getTripCount(), Plan.getConstantInt(TCTy, 1),
                         DebugLoc::getCompilerGenerated(), "trip.count.minus.1");
@@ -5011,7 +4960,6 @@ void VPlanTransforms::materializePacksAndUnpacks(VPlan &Plan) {
   if (Plan.hasScalarVFOnly())
     return;
 
-  VPTypeAnalysis TypeInfo(Plan);
   VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
   auto VPBBsOutsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
       vp_depth_first_shallow(Plan.getEntry()));
@@ -5040,7 +4988,7 @@ void VPlanTransforms::materializePacksAndUnpacks(VPlan &Plan) {
           none_of(DefR->users(), UsesVectorOrInsideReplicateRegion))
         continue;
 
-      Type *ScalarTy = TypeInfo.inferScalarType(DefR);
+      Type *ScalarTy = DefR->getScalarType();
       unsigned Opcode = ScalarTy->isStructTy()
                             ? VPInstruction::BuildStructVector
                             : VPInstruction::BuildVector;
@@ -5110,7 +5058,7 @@ void VPlanTransforms::materializeVectorTripCount(
     return;
 
   VPValue *TC = Plan.getTripCount();
-  Type *TCTy = VPTypeAnalysis(Plan).inferScalarType(TC);
+  Type *TCTy = TC->getScalarType();
   VPBasicBlock::iterator InsertPt = VectorPHVPBB->begin();
   if (auto *StepR = Step->getDefiningRecipe()) {
     assert(VPDominatorTree(Plan).dominates(StepR->getParent(), VectorPHVPBB) &&
@@ -5181,7 +5129,7 @@ void VPlanTransforms::materializeFactors(VPlan &Plan, VPBasicBlock *VectorPH,
   }
 
   VPBuilder Builder(VectorPH, VectorPH->begin());
-  Type *TCTy = VPTypeAnalysis(Plan).inferScalarType(Plan.getTripCount());
+  Type *TCTy = Plan.getTripCount()->getScalarType();
   VPValue &VF = Plan.getVF();
   VPValue &VFxUF = Plan.getVFxUF();
   // If there are no users of the runtime VF, compute VFxUF by constant folding
@@ -5238,7 +5186,6 @@ VPlanTransforms::materializeAliasMask(VPlan &Plan, VPBasicBlock *AliasCheckVPBB,
   VPBuilder Builder(AliasCheckVPBB);
   Type *I1Ty = IntegerType::getInt1Ty(Plan.getContext());
 
-  VPTypeAnalysis TypeInfo(Plan);
   VPValue *IncomingAliasMask = vputils::findIncomingAliasMask(Plan);
   assert(IncomingAliasMask && "Expected an alias mask!");
 
@@ -5247,7 +5194,7 @@ VPlanTransforms::materializeAliasMask(VPlan &Plan, VPBasicBlock *AliasCheckVPBB,
     VPValue *Src = vputils::getOrCreateVPValueForSCEVExpr(Plan, Check.SrcStart);
     VPValue *Sink =
         vputils::getOrCreateVPValueForSCEVExpr(Plan, Check.SinkStart);
-    Type *AddrType = TypeInfo.inferScalarType(Src);
+    Type *AddrType = Src->getScalarType();
 
     // TODO: Only freeze the required pointer (not both src and sink).
     if (Check.NeedsFreeze) {
@@ -5290,7 +5237,7 @@ void VPlanTransforms::materializeAliasMaskCheckBlock(
   VPValue *ClampedVF = materializeAliasMask(Plan, ClampedVFCheck, DiffChecks);
   VPBuilder Builder(ClampedVFCheck);
   DebugLoc DL = DebugLoc::getCompilerGenerated();
-  Type *TCTy = VPTypeAnalysis(Plan).inferScalarType(Plan.getTripCount());
+  Type *TCTy = Plan.getTripCount()->getScalarType();
 
   // Check the "ClampedVF" from the alias mask is larger than one.
   VPValue *IsScalar =
@@ -5448,27 +5395,25 @@ static bool canNarrowOps(ArrayRef<VPValue *> Ops, bool IsScalable) {
 /// Returns VF from \p VFs if \p IR is a full interleave group with factor and
 /// number of members both equal to VF. The interleave group must also access
 /// the full vector width.
-static std::optional<ElementCount> isConsecutiveInterleaveGroup(
-    VPInterleaveRecipe *InterleaveR, ArrayRef<ElementCount> VFs,
-    VPTypeAnalysis &TypeInfo, const TargetTransformInfo &TTI) {
+static std::optional<ElementCount>
+isConsecutiveInterleaveGroup(VPInterleaveRecipe *InterleaveR,
+                             ArrayRef<ElementCount> VFs,
+                             const TargetTransformInfo &TTI) {
   if (!InterleaveR || InterleaveR->getMask())
     return std::nullopt;
 
   Type *GroupElementTy = nullptr;
   if (InterleaveR->getStoredValues().empty()) {
-    GroupElementTy = TypeInfo.inferScalarType(InterleaveR->getVPValue(0));
-    if (!all_of(InterleaveR->definedValues(),
-                [&TypeInfo, GroupElementTy](VPValue *Op) {
-                  return TypeInfo.inferScalarType(Op) == GroupElementTy;
-                }))
+    GroupElementTy = InterleaveR->getVPValue(0)->getScalarType();
+    if (!all_of(InterleaveR->definedValues(), [GroupElementTy](VPValue *Op) {
+          return Op->getScalarType() == GroupElementTy;
+        }))
       return std::nullopt;
   } else {
-    GroupElementTy =
-        TypeInfo.inferScalarType(InterleaveR->getStoredValues()[0]);
-    if (!all_of(InterleaveR->getStoredValues(),
-                [&TypeInfo, GroupElementTy](VPValue *Op) {
-                  return TypeInfo.inferScalarType(Op) == GroupElementTy;
-                }))
+    GroupElementTy = InterleaveR->getStoredValues()[0]->getScalarType();
+    if (!all_of(InterleaveR->getStoredValues(), [GroupElementTy](VPValue *Op) {
+          return Op->getScalarType() == GroupElementTy;
+        }))
       return std::nullopt;
   }
 
@@ -5577,7 +5522,6 @@ VPlanTransforms::narrowInterleaveGroups(VPlan &Plan,
                                m_Specific(&Plan.getVectorTripCount()))) &&
          "unexpected branch-on-count");
 
-  VPTypeAnalysis TypeInfo(Plan);
   SmallVector<VPInterleaveRecipe *> StoreGroups;
   std::optional<ElementCount> VFToOptimize;
   for (auto &R : *VectorLoop->getEntryBasicBlock()) {
@@ -5619,7 +5563,7 @@ VPlanTransforms::narrowInterleaveGroups(VPlan &Plan,
         VFToOptimize ? SmallVector<ElementCount>({*VFToOptimize})
                      : to_vector(Plan.vectorFactors());
     std::optional<ElementCount> NarrowedVF =
-        isConsecutiveInterleaveGroup(InterleaveR, VFs, TypeInfo, TTI);
+        isConsecutiveInterleaveGroup(InterleaveR, VFs, TTI);
     if (!NarrowedVF || (VFToOptimize && NarrowedVF != VFToOptimize))
       return nullptr;
     VFToOptimize = NarrowedVF;
@@ -5758,7 +5702,6 @@ void VPlanTransforms::adjustFirstOrderRecurrenceMiddleUsers(VPlan &Plan,
   VPRegionBlock *VectorRegion = Plan.getVectorLoopRegion();
   auto *MiddleVPBB = Plan.getMiddleBlock();
   VPBuilder MiddleBuilder(MiddleVPBB, MiddleVPBB->getFirstNonPhi());
-  VPTypeAnalysis TypeInfo(Plan);
 
   auto IsScalableOne = [](ElementCount VF) -> bool {
     return VF == ElementCount::getScalable(1);
@@ -5943,7 +5886,7 @@ void VPlanTransforms::optimizeFindIVReductions(VPlan &Plan,
                      PhiR->getRecurrenceKind()))
       continue;
 
-    Type *PhiTy = VPTypeAnalysis(Plan).inferScalarType(PhiR);
+    Type *PhiTy = PhiR->getScalarType();
     if (PhiTy->isPointerTy() || PhiTy->isFloatingPointTy())
       continue;
 
@@ -6161,15 +6104,14 @@ struct VPPartialReductionChain {
 };
 
 static VPSingleDefRecipe *
-optimizeExtendsForPartialReduction(VPSingleDefRecipe *Op,
-                                   VPTypeAnalysis &TypeInfo) {
+optimizeExtendsForPartialReduction(VPSingleDefRecipe *Op) {
   // reduce.add(mul(ext(A), C))
   // -> reduce.add(mul(ext(A), ext(trunc(C))))
   const APInt *Const;
   if (match(Op, m_Mul(m_ZExtOrSExt(m_VPValue()), m_APInt(Const)))) {
     auto *ExtA = cast<VPWidenCastRecipe>(Op->getOperand(0));
     Instruction::CastOps ExtOpc = ExtA->getOpcode();
-    Type *NarrowTy = TypeInfo.inferScalarType(ExtA->getOperand(0));
+    Type *NarrowTy = ExtA->getOperand(0)->getScalarType();
     if (!Op->hasOneUse() ||
         !llvm::canConstantBeExtended(
             Const, NarrowTy, TTI::getPartialReductionExtendKind(ExtOpc)))
@@ -6178,7 +6120,7 @@ optimizeExtendsForPartialReduction(VPSingleDefRecipe *Op,
     VPBuilder Builder(Op);
     auto *Trunc = Builder.createWidenCast(Instruction::CastOps::Trunc,
                                           Op->getOperand(1), NarrowTy);
-    Type *WideTy = TypeInfo.inferScalarType(ExtA);
+    Type *WideTy = ExtA->getScalarType();
     Op->setOperand(1, Builder.createWidenCast(ExtOpc, Trunc, WideTy));
     return Op;
   }
@@ -6195,7 +6137,7 @@ optimizeExtendsForPartialReduction(VPSingleDefRecipe *Op,
            "Expected both the LHS and RHS extends to be the same");
     bool IsSigned = Ext->getOpcode() == Instruction::SExt;
     VPBuilder Builder(Op);
-    Type *SrcTy = TypeInfo.inferScalarType(X);
+    Type *SrcTy = X->getScalarType();
     auto *FreezeX = Builder.insert(new VPWidenRecipe(Instruction::Freeze, {X}));
     auto *FreezeY = Builder.insert(new VPWidenRecipe(Instruction::Freeze, {Y}));
     auto *Max = Builder.insert(
@@ -6207,7 +6149,7 @@ optimizeExtendsForPartialReduction(VPSingleDefRecipe *Op,
     auto *AbsDiff =
         Builder.insert(new VPWidenRecipe(Instruction::Sub, {Max, Min}));
     return Builder.createWidenCast(Instruction::CastOps::ZExt, AbsDiff,
-                                   TypeInfo.inferScalarType(Op));
+                                   Op->getScalarType());
   }
 
   // reduce.add(ext(mul(ext(A), ext(B))))
@@ -6290,7 +6232,7 @@ createPartialReductionExpression(VPReductionRecipe *Red) {
 // Helper to transform a partial reduction chain into a partial reduction
 // recipe. Assumes profitability has been checked.
 static void transformToPartialReduction(const VPPartialReductionChain &Chain,
-                                        VPTypeAnalysis &TypeInfo, VPlan &Plan,
+                                        VPlan &Plan,
                                         VPReductionPHIRecipe *RdxPhi) {
   VPWidenRecipe *WidenRecipe = Chain.ReductionBinOp;
   assert(WidenRecipe->getNumOperands() == 2 && "Expected binary operation");
@@ -6318,7 +6260,7 @@ static void transformToPartialReduction(const VPPartialReductionChain &Chain,
       (WidenRecipe->getOpcode() == Instruction::FSub &&
        Chain.RK != RecurKind::FSub)) {
     VPBuilder Builder(WidenRecipe);
-    Type *ElemTy = TypeInfo.inferScalarType(ExtendedOp);
+    Type *ElemTy = ExtendedOp->getScalarType();
     VPWidenRecipe *NegRecipe;
     if (WidenRecipe->getOpcode() == Instruction::FSub) {
       NegRecipe =
@@ -6335,7 +6277,7 @@ static void transformToPartialReduction(const VPPartialReductionChain &Chain,
   }
 
   // FIXME: Do these transforms before invoking the cost-model.
-  ExtendedOp = optimizeExtendsForPartialReduction(ExtendedOp, TypeInfo);
+  ExtendedOp = optimizeExtendsForPartialReduction(ExtendedOp);
 
   // Check if WidenRecipe is the final result of the reduction. If so look
   // through selects for predicated reductions.
@@ -6348,7 +6290,7 @@ static void transformToPartialReduction(const VPPartialReductionChain &Chain,
   assert((!ExitValue || IsLastInChain) &&
          "if we found ExitValue, it must match RdxPhi's backedge value");
 
-  Type *PhiType = TypeInfo.inferScalarType(RdxPhi);
+  Type *PhiType = RdxPhi->getScalarType();
   RecurKind RdxKind =
       PhiType->isFloatingPointTy() ? RecurKind::FAdd : RecurKind::Add;
   auto *PartialRed = new VPReductionRecipe(
@@ -6411,7 +6353,7 @@ static InstructionCost
 getPartialReductionLinkCost(VPCostContext &CostCtx,
                             const VPPartialReductionChain &Link,
                             ElementCount VF) {
-  Type *RdxType = CostCtx.Types.inferScalarType(Link.ReductionBinOp);
+  Type *RdxType = Link.ReductionBinOp->getScalarType();
   const ExtendedReductionOperand &ExtendedOp = Link.ExtendedOp;
   std::optional<unsigned> BinOpc = std::nullopt;
   // If ExtendB is not none, then the "ExtendsUser" is the binary operation.
@@ -6457,8 +6399,7 @@ static ExtendKind getPartialReductionExtendKind(VPWidenCastRecipe *Cast) {
 ///
 /// Note: The second operand of UpdateR corresponds to \p Op in the examples.
 static std::optional<ExtendedReductionOperand>
-matchExtendedReductionOperand(VPWidenRecipe *UpdateR, VPValue *Op,
-                              VPTypeAnalysis &TypeInfo) {
+matchExtendedReductionOperand(VPWidenRecipe *UpdateR, VPValue *Op) {
   assert(is_contained(UpdateR->operands(), Op) &&
          "Op should be operand of UpdateR");
 
@@ -6476,8 +6417,8 @@ matchExtendedReductionOperand(VPWidenRecipe *UpdateR, VPValue *Op,
     auto *Sub = cast<VPWidenRecipe>(Abs->getOperand(0));
     auto *LHSExt = cast<VPWidenCastRecipe>(Sub->getOperand(0));
     auto *RHSExt = cast<VPWidenCastRecipe>(Sub->getOperand(1));
-    Type *LHSInputType = TypeInfo.inferScalarType(X);
-    Type *RHSInputType = TypeInfo.inferScalarType(Y);
+    Type *LHSInputType = X->getScalarType();
+    Type *RHSInputType = Y->getScalarType();
     if (LHSInputType != RHSInputType ||
         LHSExt->getOpcode() != RHSExt->getOpcode())
       return std::nullopt;
@@ -6512,7 +6453,7 @@ matchExtendedReductionOperand(VPWidenRecipe *UpdateR, VPValue *Op,
       // case for sub reductions too).
       return ExtendedReductionOperand{
           UpdateR,
-          /*ExtendA=*/{TypeInfo.inferScalarType(CastSource), *OuterExtKind},
+          /*ExtendA=*/{CastSource->getScalarType(), *OuterExtKind},
           /*ExtendB=*/{}};
     }
   }
@@ -6536,7 +6477,7 @@ matchExtendedReductionOperand(VPWidenRecipe *UpdateR, VPValue *Op,
     return std::nullopt;
 
   auto *LHSCast = cast<VPWidenCastRecipe>(LHS);
-  Type *LHSInputType = TypeInfo.inferScalarType(LHSCast->getOperand(0));
+  Type *LHSInputType = LHSCast->getOperand(0)->getScalarType();
   ExtendKind LHSExtendKind = getPartialReductionExtendKind(LHSCast);
 
   // The RHS of the operation can be an extend or a constant integer.
@@ -6557,7 +6498,7 @@ matchExtendedReductionOperand(VPWidenRecipe *UpdateR, VPValue *Op,
   Type *RHSInputType = LHSInputType;
   ExtendKind RHSExtendKind = LHSExtendKind;
   if (RHSCast) {
-    RHSInputType = TypeInfo.inferScalarType(RHSCast->getOperand(0));
+    RHSInputType = RHSCast->getOperand(0)->getScalarType();
     RHSExtendKind = getPartialReductionExtendKind(RHSCast);
   }
 
@@ -6581,10 +6522,9 @@ getScaledReductions(VPReductionPHIRecipe *RedPhiR, VPCostContext &CostCtx,
   VPValue *ExitValue = RdxResult->getOperand(0);
   match(ExitValue, m_Select(m_VPValue(), m_VPValue(ExitValue), m_VPValue()));
 
-  VPTypeAnalysis &TypeInfo = CostCtx.Types;
   SmallVector<VPPartialReductionChain> Chain;
   RecurKind RK = RedPhiR->getRecurrenceKind();
-  Type *PhiType = TypeInfo.inferScalarType(RedPhiR);
+  Type *PhiType = RedPhiR->getScalarType();
   TypeSize PHISize = PhiType->getPrimitiveSizeInBits();
 
   // Work backwards from the ExitValue examining each reduction operation.
@@ -6600,9 +6540,9 @@ getScaledReductions(VPReductionPHIRecipe *RedPhiR, VPCostContext &CostCtx,
     // Find the extended operand. The other operand (PrevValue) is the next link
     // in the reduction chain.
     std::optional<ExtendedReductionOperand> ExtendedOp =
-        matchExtendedReductionOperand(UpdateR, Op, TypeInfo);
+        matchExtendedReductionOperand(UpdateR, Op);
     if (!ExtendedOp) {
-      ExtendedOp = matchExtendedReductionOperand(UpdateR, PrevValue, TypeInfo);
+      ExtendedOp = matchExtendedReductionOperand(UpdateR, PrevValue);
       if (!ExtendedOp)
         return std::nullopt;
       std::swap(Op, PrevValue);
@@ -6746,7 +6686,7 @@ void VPlanTransforms::createPartialReductions(VPlan &Plan,
 
   for (auto &[Phi, Chains] : ChainsByPhi)
     for (const VPPartialReductionChain &Chain : Chains)
-      transformToPartialReduction(Chain, CostCtx.Types, Plan, Phi);
+      transformToPartialReduction(Chain, Plan, Phi);
 }
 
 void VPlanTransforms::makeMemOpWideningDecisions(
@@ -6849,8 +6789,7 @@ void VPlanTransforms::makeScalarizationDecisions(VPlan &Plan, VFRange &Range) {
 
 /// Returns true if \p Info's parameter kinds are compatible with \p Args.
 static bool areVFParamsOk(const VFInfo &Info, ArrayRef<VPValue *> Args,
-                          PredicatedScalarEvolution &PSE, const Loop *L,
-                          VPTypeAnalysis &Types) {
+                          PredicatedScalarEvolution &PSE, const Loop *L) {
   ScalarEvolution *SE = PSE.getSE();
   return all_of(Info.Shape.Parameters, [&](VFParameter Param) {
     switch (Param.ParamKind) {
@@ -6858,7 +6797,7 @@ static bool areVFParamsOk(const VFInfo &Info, ArrayRef<VPValue *> Args,
     case VFParamKind::GlobalPredicate:
       return true;
     case VFParamKind::OMP_Uniform:
-      return SE->isSCEVable(Types.inferScalarType(Args[Param.ParamPos])) &&
+      return SE->isSCEVable(Args[Param.ParamPos]->getScalarType()) &&
              SE->isLoopInvariant(
                  vputils::getSCEVExprForVPValue(Args[Param.ParamPos], PSE, L),
                  L);
@@ -6879,13 +6818,13 @@ static bool areVFParamsOk(const VFInfo &Info, ArrayRef<VPValue *> Args,
 static Function *findVectorVariant(CallInst *CI, ArrayRef<VPValue *> Args,
                                    ElementCount VF, bool MaskRequired,
                                    PredicatedScalarEvolution &PSE,
-                                   const Loop *L, VPTypeAnalysis &Types) {
+                                   const Loop *L) {
   if (CI->isNoBuiltin())
     return nullptr;
   auto Mappings = VFDatabase::getMappings(*CI);
   const auto *It = find_if(Mappings, [&](const VFInfo &Info) {
     return Info.Shape.VF == VF && (!MaskRequired || Info.isMasked()) &&
-           areVFParamsOk(Info, Args, PSE, L, Types);
+           areVFParamsOk(Info, Args, PSE, L);
   });
   if (It == Mappings.end())
     return nullptr;
@@ -6923,7 +6862,7 @@ static CallWideningDecision decideCallWidening(VPInstruction &VPI,
 
   auto *CalledFn = cast<Function>(
       VPI.getOperand(VPI.getNumOperandsWithoutMask() - 1)->getLiveInIRValue());
-  Type *ResultTy = CostCtx.Types.inferScalarType(&VPI);
+  Type *ResultTy = VPI.getScalarType();
   Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, &CostCtx.TLI);
   bool MaskRequired = CostCtx.isMaskRequired(CI);
 
@@ -6935,8 +6874,8 @@ static CallWideningDecision decideCallWidening(VPInstruction &VPI,
       VPReplicateRecipe::computeCallCost(CalledFn, ResultTy, Ops,
                                          /*IsSingleScalar=*/false, VF, CostCtx);
 
-  Function *VecFunc = findVectorVariant(CI, Ops, VF, MaskRequired, CostCtx.PSE,
-                                        CostCtx.L, CostCtx.Types);
+  Function *VecFunc =
+      findVectorVariant(CI, Ops, VF, MaskRequired, CostCtx.PSE, CostCtx.L);
   InstructionCost VecCallCost = InstructionCost::getInvalid();
   if (VecFunc)
     VecCallCost = VPWidenCallRecipe::computeCallCost(VecFunc, CostCtx);
@@ -6961,7 +6900,6 @@ static CallWideningDecision decideCallWidening(VPInstruction &VPI,
 void VPlanTransforms::makeCallWideningDecisions(VPlan &Plan, VFRange &Range,
                                                 VPRecipeBuilder &RecipeBuilder,
                                                 VPCostContext &CostCtx) {
-  SmallVector<VPInstruction *, 8> ToErase;
   for (VPBasicBlock *VPBB : VPBlockUtils::blocksAs<VPBasicBlock>(
            vp_depth_first_shallow(Plan.getVectorLoopRegion()->getEntry()))) {
     for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
@@ -6986,7 +6924,7 @@ void VPlanTransforms::makeCallWideningDecisions(VPlan &Plan, VFRange &Range,
       switch (Decision.Kind) {
       case CallWideningDecision::KindTy::Intrinsic: {
         Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, &CostCtx.TLI);
-        Type *ResultTy = CostCtx.Types.inferScalarType(VPI);
+        Type *ResultTy = VPI->getScalarType();
         Replacement = new VPWidenIntrinsicRecipe(*CI, ID, Ops, ResultTy, *VPI,
                                                  *VPI, VPI->getDebugLoc());
         break;
@@ -7010,11 +6948,9 @@ void VPlanTransforms::makeCallWideningDecisions(VPlan &Plan, VFRange &Range,
 
       Replacement->insertBefore(VPI);
       VPI->replaceAllUsesWith(Replacement);
-      ToErase.push_back(VPI);
+      VPI->eraseFromParent();
     }
   }
-  for (VPInstruction *VPI : ToErase)
-    VPI->eraseFromParent();
 }
 
 void VPlanTransforms::convertToStridedAccesses(VPlan &Plan,
@@ -7024,7 +6960,6 @@ void VPlanTransforms::convertToStridedAccesses(VPlan &Plan,
   if (Plan.hasScalarVFOnly())
     return;
 
-  VPTypeAnalysis TypeInfo(Plan);
   VPRegionBlock *VectorLoop = Plan.getVectorLoopRegion();
   VPValue *I32VF = nullptr;
   for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
@@ -7053,7 +6988,7 @@ void VPlanTransforms::convertToStridedAccesses(VPlan &Plan,
                                               m_SpecificLoop(&L))))
         continue;
 
-      Type *LoadTy = TypeInfo.inferScalarType(LoadR);
+      Type *LoadTy = LoadR->getScalarType();
       Align Alignment = LoadR->getAlign();
       auto IsProfitable = [&](ElementCount VF) {
         Type *DataTy = toVectorTy(LoadTy, VF);
@@ -7082,7 +7017,7 @@ void VPlanTransforms::convertToStridedAccesses(VPlan &Plan,
         VPBuilder Builder(Plan.getVectorPreheader());
         I32VF = Builder.createScalarZExtOrTrunc(
             &Plan.getVF(), Type::getInt32Ty(Plan.getContext()),
-            TypeInfo.inferScalarType(&Plan.getVF()), DebugLoc::getUnknown());
+            Plan.getVF().getScalarType(), DebugLoc::getUnknown());
       }
 
       VPBuilder Builder(LoadR);

diff  --git a/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp b/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
index 65ad0feaa71c9..82cc5b05ebfaf 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanUnroll.cpp
@@ -40,8 +40,6 @@ class UnrollState {
   VPlan &Plan;
   /// Unroll factor to unroll by.
   const unsigned UF;
-  /// Analysis for types.
-  VPTypeAnalysis TypeInfo;
 
   /// Unrolling may create recipes that should not be unrolled themselves.
   /// Those are tracked in ToSkip.
@@ -75,7 +73,7 @@ class UnrollState {
   }
 
 public:
-  UnrollState(VPlan &Plan, unsigned UF) : Plan(Plan), UF(UF), TypeInfo(Plan) {}
+  UnrollState(VPlan &Plan, unsigned UF) : Plan(Plan), UF(UF) {}
 
   void unrollBlock(VPBlockBase *VPB);
 
@@ -125,25 +123,22 @@ class UnrollState {
 } // namespace
 
 static void addStartIndexForScalarSteps(VPScalarIVStepsRecipe *Steps,
-                                        unsigned Part, VPlan &Plan,
-                                        VPTypeAnalysis &TypeInfo) {
+                                        unsigned Part, VPlan &Plan) {
   if (Part == 0)
     return;
 
   VPBuilder Builder(Steps);
-  Type *BaseIVTy = TypeInfo.inferScalarType(Steps->getOperand(0));
+  Type *BaseIVTy = Steps->getOperand(0)->getScalarType();
   Type *IntStepTy =
       IntegerType::get(BaseIVTy->getContext(), BaseIVTy->getScalarSizeInBits());
   VPValue *StartIndex = Steps->getVFValue();
   if (Part > 1) {
     StartIndex = Builder.createOverflowingOp(
         Instruction::Mul,
-        {StartIndex,
-         Plan.getConstantInt(TypeInfo.inferScalarType(StartIndex), Part)});
+        {StartIndex, Plan.getConstantInt(StartIndex->getScalarType(), Part)});
   }
   StartIndex = Builder.createScalarSExtOrTrunc(
-      StartIndex, IntStepTy, TypeInfo.inferScalarType(StartIndex),
-      Steps->getDebugLoc());
+      StartIndex, IntStepTy, StartIndex->getScalarType(), Steps->getDebugLoc());
 
   if (BaseIVTy->isFloatingPointTy())
     StartIndex = Builder.createScalarCast(Instruction::SIToFP, StartIndex,
@@ -166,7 +161,7 @@ void UnrollState::unrollReplicateRegionByUF(VPRegionBlock *VPR) {
       for (const auto &[PartIR, Part0R] : zip(*PartIVPBB, *Part0VPBB)) {
         remapOperands(&PartIR, Part);
         if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(&PartIR))
-          addStartIndexForScalarSteps(Steps, Part, Plan, TypeInfo);
+          addStartIndexForScalarSteps(Steps, Part, Plan);
 
         addRecipeForPart(&Part0R, &PartIR, Part);
       }
@@ -178,7 +173,7 @@ void UnrollState::unrollWidenInductionByUF(
     VPWidenInductionRecipe *IV, VPBasicBlock::iterator InsertPtForPhi) {
   VPBasicBlock *PH = cast<VPBasicBlock>(
       IV->getParent()->getEnclosingLoopRegion()->getSinglePredecessor());
-  Type *IVTy = TypeInfo.inferScalarType(IV);
+  Type *IVTy = IV->getScalarType();
   auto &ID = IV->getInductionDescriptor();
   FastMathFlags FMF;
   VPIRFlags::WrapFlagsTy WrapFlags(false, false);
@@ -191,8 +186,7 @@ void UnrollState::unrollWidenInductionByUF(
 
   VPValue *ScalarStep = IV->getStepValue();
   VPBuilder Builder(PH);
-  Type *VectorStepTy =
-      IVTy->isPointerTy() ? TypeInfo.inferScalarType(ScalarStep) : IVTy;
+  Type *VectorStepTy = IVTy->isPointerTy() ? ScalarStep->getScalarType() : IVTy;
   VPInstruction *VectorStep = Builder.createNaryOp(
       VPInstruction::WideIVStep, {&Plan.getVF(), ScalarStep}, VectorStepTy, FMF,
       IV->getDebugLoc());
@@ -347,8 +341,8 @@ void UnrollState::unrollRecipeByUF(VPRecipeBase &R) {
       Type *IndexTy =
           isa<VPWidenCanonicalIVRecipe>(R)
               ? Plan.getVectorLoopRegion()->getCanonicalIVType()
-              : DL.getIndexType(TypeInfo.inferScalarType(R.getVPSingleValue()));
-      Type *VFTy = Plan.getVF().getType();
+              : DL.getIndexType(R.getVPSingleValue()->getScalarType());
+      Type *VFTy = Plan.getVF().getScalarType();
       VPValue *VF = Builder.createScalarZExtOrTrunc(
           &Plan.getVF(), IndexTy, VFTy, DebugLoc::getUnknown());
       // VFxUF does not wrap, so VF * Part also cannot wrap.
@@ -381,7 +375,7 @@ void UnrollState::unrollRecipeByUF(VPRecipeBase &R) {
     remapOperands(Copy, Part);
 
     if (auto *ScalarIVSteps = dyn_cast<VPScalarIVStepsRecipe>(Copy))
-      addStartIndexForScalarSteps(ScalarIVSteps, Part, Plan, TypeInfo);
+      addStartIndexForScalarSteps(ScalarIVSteps, Part, Plan);
 
     if (match(Copy,
               m_VPInstruction<VPInstruction::CanonicalIVIncrementForPart>())) {
@@ -508,7 +502,7 @@ void VPlanTransforms::unrollByUF(VPlan &Plan, unsigned UF) {
       }
     }
 
-    Type *TCTy = VPTypeAnalysis(Plan).inferScalarType(Plan.getTripCount());
+    Type *TCTy = Plan.getTripCount()->getScalarType();
     Plan.getUF().replaceAllUsesWith(Plan.getConstantInt(TCTy, UF));
   });
   if (UF == 1) {
@@ -553,8 +547,7 @@ void VPlanTransforms::unrollByUF(VPlan &Plan, unsigned UF) {
 static void addLaneToStartIndex(VPScalarIVStepsRecipe *Steps, unsigned Lane,
                                 VPlan &Plan, VPRecipeBase *InsertPt) {
   assert(Lane > 0 && "Zero lane adds no offset to start index");
-  VPTypeAnalysis TypeInfo(Plan);
-  Type *BaseIVTy = TypeInfo.inferScalarType(Steps->getOperand(0));
+  Type *BaseIVTy = Steps->getOperand(0)->getScalarType();
 
   VPValue *OldStartIndex = Steps->getStartIndex();
   VPValue *LaneOffset;
@@ -675,7 +668,6 @@ static void convertRecipesInRegionBlocksToSingleScalar(VPlan &Plan, Type *IdxTy,
                                                        VPBlockBase *Entry,
                                                        ElementCount VF) {
   VPValue *Idx0 = Plan.getZero(IdxTy);
-  VPTypeAnalysis TypeInfo(Plan);
   for (VPBlockBase *VPB : vp_depth_first_shallow(Entry)) {
     for (VPRecipeBase &OldR : make_early_inc_range(cast<VPBasicBlock>(*VPB))) {
       assert(
@@ -721,7 +713,7 @@ static void convertRecipesInRegionBlocksToSingleScalar(VPlan &Plan, Type *IdxTy,
         BranchOnMask->eraseFromParent();
       } else if (auto *PredPhi = dyn_cast<VPPredInstPHIRecipe>(&OldR)) {
         VPValue *PredOp = PredPhi->getOperand(0);
-        Type *PredTy = TypeInfo.inferScalarType(PredOp);
+        Type *PredTy = PredOp->getScalarType();
         VPValue *Poison = Plan.getOrAddLiveIn(PoisonValue::get(PredTy));
         VPPhi *NewPhi = Builder.createScalarPhi({Poison, PredOp}, OldDL);
         PredPhi->replaceAllUsesWith(NewPhi);
@@ -820,14 +812,13 @@ static void dissolveReplicateRegion(VPRegionBlock *Region, ElementCount VF,
   // BuildVectors are recorded to be replaced later by chains of insert-element
   // and widen phi's.
   unsigned NumLanes = VF.getFixedValue();
-  VPTypeAnalysis TypeInfo(Plan);
   SmallVector<VPInstruction *> BuildVectors;
   for (auto &R : FirstLaneExiting->phis()) {
     auto *Phi = cast<VPPhi>(&R);
     if (vputils::onlyFirstLaneUsed(Phi))
       continue;
 
-    Type *ScalarTy = TypeInfo.inferScalarType(Phi);
+    Type *ScalarTy = Phi->getScalarType();
     bool IsStruct = isa<StructType>(ScalarTy);
     VPValue *Poison = Plan.getOrAddLiveIn(PoisonValue::get(ScalarTy));
     SmallVector<VPValue *> BVOps(NumLanes, Poison);

diff  --git a/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp b/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
index c4d3619333d85..17a825429d89b 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
@@ -243,22 +243,19 @@ const SCEV *vputils::getSCEVExprForVPValue(const VPValue *V,
       return SE.getURemExpr(Ops[0], SE.getConstant(*Mask + 1));
     });
   if (match(V, m_Trunc(m_VPValue(LHSVal)))) {
-    const VPlan *Plan = V->getDefiningRecipe()->getParent()->getPlan();
-    Type *DestTy = VPTypeAnalysis(*Plan).inferScalarType(V);
+    Type *DestTy = V->getScalarType();
     return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
       return SE.getTruncateExpr(Ops[0], DestTy);
     });
   }
   if (match(V, m_ZExt(m_VPValue(LHSVal)))) {
-    const VPlan *Plan = V->getDefiningRecipe()->getParent()->getPlan();
-    Type *DestTy = VPTypeAnalysis(*Plan).inferScalarType(V);
+    Type *DestTy = V->getScalarType();
     return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
       return SE.getZeroExtendExpr(Ops[0], DestTy);
     });
   }
   if (match(V, m_SExt(m_VPValue(LHSVal)))) {
-    const VPlan *Plan = V->getDefiningRecipe()->getParent()->getPlan();
-    Type *DestTy = VPTypeAnalysis(*Plan).inferScalarType(V);
+    Type *DestTy = V->getScalarType();
 
     // Mirror SCEV's createSCEV handling for sext(sub nsw): push sign extension
     // onto the operands before computing the subtraction.

diff  --git a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
index 276ef819be669..be7f84f3b5a00 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp
@@ -30,7 +30,6 @@ using namespace VPlanPatternMatch;
 namespace {
 class VPlanVerifier {
   const VPDominatorTree &VPDT;
-  VPTypeAnalysis &TypeInfo;
 
   SmallPtrSet<BasicBlock *, 8> WrappedIRBBs;
 
@@ -67,8 +66,7 @@ class VPlanVerifier {
   bool verifyRegionRec(const VPRegionBlock *Region);
 
 public:
-  VPlanVerifier(VPDominatorTree &VPDT, VPTypeAnalysis &TypeInfo)
-      : VPDT(VPDT), TypeInfo(TypeInfo) {}
+  VPlanVerifier(VPDominatorTree &VPDT) : VPDT(VPDT) {}
 
   bool verify(const VPlan &Plan);
 };
@@ -239,8 +237,7 @@ bool VPlanVerifier::verifyRecipeTypes(const VPRecipeBase &R) const {
 
   auto CheckOperandTypes = [&]() -> bool {
     if (all_of(drop_begin(R.operands()), [&R](VPValue *Op) {
-          return getScalarTypeOrInfer(R.getOperand(0)) ==
-                 getScalarTypeOrInfer(Op);
+          return R.getOperand(0)->getScalarType() == Op->getScalarType();
         }))
       return true;
     errs() << "Recipe operand types do not match";
@@ -264,7 +261,7 @@ bool VPlanVerifier::verifyRecipeTypes(const VPRecipeBase &R) const {
   case VPRecipeBase::VPScalarIVStepsSC:
   case VPRecipeBase::VPWidenPointerInductionSC:
   case VPRecipeBase::VPDerivedIVSC:
-    return CheckScalarType(getScalarTypeOrInfer(R.getOperand(0)));
+    return CheckScalarType(R.getOperand(0)->getScalarType());
   case VPRecipeBase::VPWidenPHISC:
   case VPRecipeBase::VPPredInstPHISC:
   case VPRecipeBase::VPReductionPHISC:
@@ -272,7 +269,7 @@ bool VPlanVerifier::verifyRecipeTypes(const VPRecipeBase &R) const {
   case VPRecipeBase::VPCurrentIterationPHISC:
   case VPRecipeBase::VPFirstOrderRecurrencePHISC:
     return CheckOperandTypes() &&
-           CheckScalarType(getScalarTypeOrInfer(R.getOperand(0)));
+           CheckScalarType(R.getOperand(0)->getScalarType());
   case VPRecipeBase::VPInstructionSC: {
     auto *VPI = cast<VPInstruction>(&R);
     if (isa<VPInstructionWithType>(VPI) ||
@@ -334,11 +331,9 @@ bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) {
     if (!verifyRecipeTypes(R))
       return false;
     for (const VPValue *V : R.definedValues()) {
-      // Verify that we can infer a scalar type for each defined value. With
-      // assertions enabled, inferScalarType will perform some consistency
-      // checks during type inference.
-      if (!TypeInfo.inferScalarType(V)) {
-        errs() << "Failed to infer scalar type!\n";
+      // Verify that each defined value has a scalar type.
+      if (!V->getScalarType()) {
+        errs() << "VPValue without scalar type!\n";
         return false;
       }
 
@@ -615,7 +610,6 @@ bool VPlanVerifier::verify(const VPlan &Plan) {
 
 bool llvm::verifyVPlanIsValid(const VPlan &Plan) {
   VPDominatorTree VPDT(const_cast<VPlan &>(Plan));
-  VPTypeAnalysis TypeInfo(Plan);
-  VPlanVerifier Verifier(VPDT, TypeInfo);
+  VPlanVerifier Verifier(VPDT);
   return Verifier.verify(Plan);
 }

diff  --git a/llvm/test/Transforms/LoopVectorize/RISCV/type-info-cache-evl-crash.ll b/llvm/test/Transforms/LoopVectorize/RISCV/type-info-cache-evl-crash.ll
index b9795aee8c032..06d74a77bb0e3 100644
--- a/llvm/test/Transforms/LoopVectorize/RISCV/type-info-cache-evl-crash.ll
+++ b/llvm/test/Transforms/LoopVectorize/RISCV/type-info-cache-evl-crash.ll
@@ -1,9 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -passes=loop-vectorize -tail-folding-policy=prefer-fold-tail -mtriple=riscv64 -mattr=+v -S %s | FileCheck %s
 
-; This test tries to recreate the conditions for a crash that occurred when the
-; VPTypeAnalysis cache wasn't cleared after a recipe was erased and clobbered
-; with a new one.
+; This test tries to recreate the conditions for a crash that occurred when a
+; recipe was erased and replaced with a new one during EVL optimization.
 
 define void @type_info_cache_clobber(ptr %dstv, ptr %src, i64 %wide.trip.count) {
 ; CHECK-LABEL: define void @type_info_cache_clobber(

diff  --git a/llvm/test/Transforms/LoopVectorize/vplan-incomplete-cases.ll b/llvm/test/Transforms/LoopVectorize/vplan-incomplete-cases.ll
index b41ffe57b7058..aed4fb7dd5b85 100644
--- a/llvm/test/Transforms/LoopVectorize/vplan-incomplete-cases.ll
+++ b/llvm/test/Transforms/LoopVectorize/vplan-incomplete-cases.ll
@@ -1,7 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -passes=loop-vectorize -S %s | FileCheck %s
 
-; This test used to crash due to missing Or/Not cases in inferScalarTypeForRecipe.
+; This test used to crash due to missing Or/Not cases in type inference.
 define void @vplan_incomplete_cases_tc2(i8 %x, i8 %y) {
 ; CHECK-LABEL: define void @vplan_incomplete_cases_tc2(
 ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
@@ -44,7 +44,7 @@ exit:
   ret void
 }
 
-; This test used to crash due to missing the LogicalAnd case in inferScalarTypeForRecipe.
+; This test used to crash due to missing the LogicalAnd case in type inference.
 define void @vplan_incomplete_cases_tc3(i8 %x, i8 %y) {
 ; CHECK-LABEL: define void @vplan_incomplete_cases_tc3(
 ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {


        


More information about the llvm-commits mailing list