[llvm] [LV][VPlan] Introduce VPScalarStore recipe to handle scalar stores in exit block. (PR #93148)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 16 00:52:57 PDT 2024


================
@@ -2964,6 +2966,60 @@ class VPScalarIVStepsRecipe : public VPRecipeWithIRFlags {
   }
 };
 
+/// A recipe to represent scalar stores that are outside the vector loop region.
+/// Both the stored value and the address must be uniform, and finally, only a
+/// single store instance will be generated.
+class VPScalarStoreRecipe : public VPRecipeBase {
+  /// The alignment information of this store.
+  MaybeAlign Alignment = std::nullopt;
+  /// The ingredient store of this recipe.
+  StoreInst *SI = nullptr;
+
+public:
+  VPScalarStoreRecipe(VPValue *StoredVal, VPValue *Addr,
+                      MaybeAlign Align = std::nullopt, DebugLoc DL = {})
+      : VPRecipeBase(VPDef::VPScalarStoreSC, {StoredVal, Addr}, DL),
+        Alignment(Align) {}
+
+  VPScalarStoreRecipe(StoreInst &SI, VPValue *StoredVal, VPValue *Addr)
+      : VPRecipeBase(VPDef::VPScalarStoreSC, {StoredVal, Addr},
+                     SI.getDebugLoc()),
+        Alignment(getLoadStoreAlignment(&SI)), SI(&SI) {}
+
+  ~VPScalarStoreRecipe() override = default;
+
+  VPScalarStoreRecipe *clone() override {
+    if (SI)
+      return new VPScalarStoreRecipe(*SI, getStoredVal(), getAddress());
+    return new VPScalarStoreRecipe(getStoredVal(), getAddress(), Alignment,
+                                   getDebugLoc());
+  }
+
+  VP_CLASSOF_IMPL(VPDef::VPScalarStoreSC)
+
+  /// Generate the scalar store instruction for intermediate store.
+  void execute(VPTransformState &State) override;
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+  /// Print the recipe.
+  void print(raw_ostream &O, const Twine &Indent,
+             VPSlotTracker &SlotTracker) const override;
+#endif
+
+  /// Return the value stored by this recipe.
+  VPValue *getStoredVal() const { return getOperand(0); }
+
+  /// Return the address accessed by this recipe.
+  VPValue *getAddress() const { return getOperand(1); }
+
+  /// Returns true if the recipe only uses the first lane of operand \p Op.
+  bool onlyFirstLaneUsed(const VPValue *Op) const override {
+    assert(is_contained(operands(), Op) &&
----------------
fhahn wrote:

is this needed? operands at the moment are only operands are ComputeReductionReusult which produces a single scalar anyways?

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


More information about the llvm-commits mailing list