[llvm] [LV] Factor out VF-independent code from cost model (NFC). (PR #192426)

David Sherwood via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 20 06:15:50 PDT 2026


================
@@ -490,6 +515,125 @@ struct FixedScalableVFPair {
   bool hasVector() const { return FixedVF.isVector() || ScalableVF.isVector(); }
 };
 
+/// Holds state needed to make cost decisions before computing costs per-VF,
+/// including the maximum VFs.
+class VFSelectionContext {
+  /// \return True if maximizing vector bandwidth is enabled by the target or
+  /// user options, for the given register kind.
+  bool useMaxBandwidth(TargetTransformInfo::RegisterKind RegKind) const;
+
+  /// \return the maximized element count based on the targets vector
+  /// registers and the loop trip-count, but limited to a maximum safe VF.
+  ElementCount getMaximizedVFForTarget(unsigned MaxTripCount,
+                                       unsigned SmallestType,
+                                       unsigned WidestType,
+                                       ElementCount MaxSafeVF, unsigned UserIC,
+                                       bool FoldTailByMasking,
+                                       bool RequiresScalarEpilogue);
+
+  /// If \p VF * \p UserIC > MaxTripcount, clamps VF to the next lower VF
+  /// that results in VF * UserIC <= MaxTripCount.
+  ElementCount clampVFByMaxTripCount(ElementCount VF, unsigned MaxTripCount,
+                                     unsigned UserIC, bool FoldTailByMasking,
+                                     bool RequiresScalarEpilogue) const;
+
+  /// \return True if scalable vectorization is supported and enabled.
+  bool isScalableVectorizationAllowed();
+
+  /// \return The maximum legal scalable VF, based on the safe dependence
+  /// distance.
+  ElementCount getMaxLegalScalableVF(unsigned MaxSafeElements);
+
+  /// Initialize the vscale value used for cost tuning.
+  void initializeVScaleForTuning();
+
+  const TargetTransformInfo &TTI;
+  const LoopVectorizationLegality *Legal;
+  const Loop *TheLoop;
+  const Function &F;
+  OptimizationRemarkEmitter *ORE;
+  const LoopVectorizeHints *Hints;
+
+  /// Cached result of isScalableVectorizationAllowed.
+  std::optional<bool> IsScalableVectorizationAllowed;
+
+  /// The vscale value to tune the cost model for.
+  std::optional<unsigned> VScaleForTuning;
+
+  /// The highest VF possible for this loop, without using MaxBandwidth.
+  FixedScalableVFPair MaxPermissibleVFWithoutMaxBW;
+
+  /// All element types found in the loop.
+  SmallPtrSet<Type *, 16> ElementTypesInLoop;
+
+  /// Ephemeral values collected before cost modeling, reused by the cost
+  /// model's collectValuesToIgnore to avoid recomputation.
+  SmallPtrSet<const Value *, 16> EphemeralValues;
+
+  /// Maximum safe number of elements to be processed per vector iteration,
+  /// which do not prevent store-load forwarding and are safe with regard to the
+  /// memory dependencies. Set by computeFeasibleMaxVF.
+  std::optional<unsigned> MaxSafeElements;
+
+public:
+  const TTI::TargetCostKind CostKind;
+  const bool OptForSize;
+
+  VFSelectionContext(const TargetTransformInfo &TTI,
+                     const LoopVectorizationLegality *Legal,
+                     const Loop *TheLoop, const Function &F,
+                     OptimizationRemarkEmitter *ORE,
+                     const LoopVectorizeHints *Hints, bool OptForSize)
+      : TTI(TTI), Legal(Legal), TheLoop(TheLoop), F(F), ORE(ORE), Hints(Hints),
+        CostKind(F.hasMinSize() ? TTI::TCK_CodeSize : TTI::TCK_RecipThroughput),
+        OptForSize(OptForSize) {
+    initializeVScaleForTuning();
+  }
+
+  /// \return The vscale value to tune the cost model for.
+  std::optional<unsigned> getVScaleForTuning() const { return VScaleForTuning; }
+
+  /// \return True if register pressure should be considered for the given VF.
+  bool shouldConsiderRegPressureForVF(ElementCount VF) const;
+
+  /// \return True if scalable vectors are supported by the target or forced.
+  bool supportsScalableVectors() const;
+
+  /// Collect ephemeral values in the loop.
+  void collectEphemeralValues(AssumptionCache *AC);
+
+  /// Collect element types in the loop that need widening.
+  void collectElementTypesForWidening(
+      const SmallPtrSetImpl<const Value *> *ValuesToIgnore = nullptr);
+
+  /// \return The size (in bits) of the smallest and widest types in the code
+  /// that needs to be vectorized. We ignore values that remain scalar such as
+  /// 64 bit loop indices.
+  std::pair<unsigned, unsigned> getSmallestAndWidestTypes() const;
+
+  /// Compute the maximum feasible VF for both fixed and scalable
----------------
david-arm wrote:

A number of comments from the original version seem to have been dropped. Is there a reason for that?

https://github.com/llvm/llvm-project/pull/192426


More information about the llvm-commits mailing list