[llvm] [VPlan] Introduce distillation of widening semantics (NFC) (PR #196181)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 13 03:19:31 PDT 2026


================
@@ -361,27 +361,146 @@ bool vputils::isAddressSCEVForCost(const SCEV *Addr, ScalarEvolution &SE,
          match(Addr, m_scev_AffineAddRec(m_SCEV(), m_SCEV()));
 }
 
-/// Returns true if \p Opcode preserves uniformity, i.e., if all operands are
-/// uniform, the result will also be uniform.
-static bool preservesUniformity(unsigned Opcode) {
+/// A class keeping track of widening information of various recipes.
+/// A recipe necessarily produces a single scalar value if only the SingleScalar
+/// bit is set, a wide value if only the Wide bit is set, and scalar values for
+/// all VF lanes only the GenPerAllLanes bit is set. The SingleScalar bit can be
+/// set on Wide or GenPerAllLanes recipes, which indicates that the recipe could
+/// be narrowed to single-scalar if legal and profitable. For instructions not
+/// producing values, like an assume or store, the bits talk about the
+/// appropriate operands. Finally, there is a class of instructions that
+/// necessarily take vector operands and produce a scalar result, like
+/// (Insert|Extract)Element, or necessarily take a scalar values and produce a
+/// vector, like Build(Struct)Vector, or could be interepreted as either a wide
+/// or narrow recipe like Broadcasts and non-constant live-ins: these are marked
+/// with the Agnostic bit.
+class VPWideningInfo {
+  unsigned char Info : 4;
+
+public:
+  using VPWideningTy = enum {
+    SingleScalar = 1 << 0,
+    Wide = 1 << 1,
+    GenPerAllLanes = 1 << 2,
+    Agnostic = 1 << 3
+  };
+
+  VPWideningInfo(unsigned char Info) : Info(Info) {}
+  operator unsigned char() const { return Info; }
+  bool producesSingleScalarResult() const {
+    return Info == SingleScalar || Info == (SingleScalar | Agnostic);
+  }
+  bool couldProduceSingleScalarResult() const { return Info & SingleScalar; }
+};
+
+static VPWideningInfo getNarrowableWideningInfo(unsigned Opcode,
+                                                VPWideningInfo WideOrRep) {
   if (Instruction::isBinaryOp(Opcode) || Instruction::isCast(Opcode))
-    return true;
+    return WideOrRep | VPWideningInfo::SingleScalar;
   switch (Opcode) {
   case Instruction::Freeze:
   case Instruction::GetElementPtr:
   case Instruction::ICmp:
   case Instruction::FCmp:
   case Instruction::Select:
   case VPInstruction::Not:
-  case VPInstruction::Broadcast:
   case VPInstruction::MaskedCond:
   case VPInstruction::PtrAdd:
-    return true;
+    return WideOrRep | VPWideningInfo::SingleScalar;
   default:
-    return false;
+    return WideOrRep;
   }
 }
 
+static VPWideningInfo getWideningInfo(const VPRecipeBase &R) {
+  switch (R.getVPRecipeID()) {
+  case VPRecipeBase::VPVectorPointerSC:
----------------
artagnon wrote:

Yes, would be good to improve independently: I'll put up a PR; thanks for brining it up.

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


More information about the llvm-commits mailing list