[llvm] [SandboxVec] Add barebones Region class. (PR #108899)

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 16 16:12:40 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Jorge Gorbe Moya (slackito)

<details>
<summary>Changes</summary>

A region identifies a set of vector instructions generated by vectorization passes. The vectorizer can then run a series of RegionPasses on the region, evaluate the cost, and commit/reject the transforms on a region-by-region basis, instead of an entire basic block.

This is heavily based ov @<!-- -->vporpo's prototype. In particular, the doc comment for the Region class is all his. The rest of this commit is mostly boilerplate around a SetVector: getters, iterators, and some debug helpers.

---
Full diff: https://github.com/llvm/llvm-project/pull/108899.diff


3 Files Affected:

- (added) llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Region.h (+127) 
- (modified) llvm/lib/Transforms/Vectorize/CMakeLists.txt (+1) 
- (added) llvm/lib/Transforms/Vectorize/SandboxVectorizer/Region.cpp (+52) 


``````````diff
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Region.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Region.h
new file mode 100644
index 00000000000000..06c432c2c7b839
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Region.h
@@ -0,0 +1,127 @@
+//===- Region.h -------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_REGION_H
+#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_REGION_H
+
+#include "llvm/ADT/SetVector.h"
+#include "llvm/SandboxIR/SandboxIR.h"
+#include "llvm/Support/InstructionCost.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace sandboxir {
+
+/// The main job of the Region is to point to new instructions generated by
+/// vectorization passes. It is the unit that RegionPasses operate on with their
+/// runOnRegion() function.
+///
+/// The region allows us to stack transformations horizontally, meaning that
+/// each transformation operates on a single region and the resulting region is
+/// the input to the next transformation, as opposed to vertically, which is the
+/// common way of applying a transformation across the whole BB. This enables us
+/// to check for profitability and decide whether we accept or rollback at a
+/// region granularity, which is much better than doing this at the BB level.
+///
+/// The region keeps track of the costs that correspond to that region. That is
+/// the original "scalar" cost and the new "vector" cost. The cost is updated
+/// automatically via SandboxIR callbacks:
+/// (i) Upon deletion: If the deleted instruction is not in the region, it is an
+/// original scalar, so its cost is added to the "scalar cost", otherwise it is
+/// a "vector" instruction created by the vectorizer so we subtract its cost
+/// from the "vector cost".
+/// (ii) Upon creation: New instructions are always considered "vector" so its
+/// cost is added to the "vector cost".
+/// This cost tracking allows us to start with transformations that may not be
+/// profitable if applied by themselves, but may end up being profitable after a
+/// series of transformations.
+///
+//  Traditional approach: transformations applied vertically for the whole BB
+//    BB
+//  +----+
+//  |    |
+//  |    |
+//  |    | -> Transform1 ->  ... -> TransformN -> Check Cost
+//  |    |
+//  |    |
+//  +----+
+//
+//  Region-based approach: transformations applied horizontally, for each Region
+//    BB
+//  +----+
+//  |Rgn1| -> Transform1 ->  ... -> TransformN -> Check Cost
+//  |    |
+//  |Rgn2| -> Transform1 ->  ... -> TransformN -> Check Cost
+//  |    |
+//  |Rgn3| -> Transform1 ->  ... -> TransformN -> Check Cost
+//  +----+
+
+class Region {
+  /// All the instructions in the Region. Only new instructions generated during
+  /// vectorization are part of the Region.
+  SetVector<sandboxir::Instruction *> Insts;
+
+  /// A unique ID, used for debugging.
+  unsigned RegionID = 0;
+
+  sandboxir::Context &Ctx;
+
+  /// The basic block containing this region.
+  sandboxir::BasicBlock &SBBB;
+
+  // TODO: Add cost modeling.
+
+  /// The cost of the original scalar instructions replaced by vector
+  /// instructions in this region.
+  InstructionCost ScalarCost;
+
+  /// The cost of the vector instructions in the region.
+  InstructionCost VectorCost;
+
+  // TODO: Add a way to encode/decode region info to/from metadata.
+
+public:
+  Region(sandboxir::Context &Ctx, sandboxir::BasicBlock &SBBB);
+  ~Region();
+
+  sandboxir::BasicBlock *getParent() const { return &SBBB; }
+  sandboxir::Context &getContext() const { return Ctx; }
+  /// Returns the region's unique ID.
+  unsigned getID() const { return RegionID; }
+
+  /// Adds SBI to the set.
+  void add(sandboxir::Instruction *SBI);
+  /// Removes SBI from the set.
+  void remove(sandboxir::Instruction *SBI);
+  /// Returns true if SBI is in the Region.
+  bool contains(sandboxir::Instruction *SBI) const {
+    return Insts.contains(SBI);
+  }
+  /// Returns true if the Region has no instructions.
+  bool empty() const { return Insts.empty(); }
+
+  using iterator = decltype(Insts.begin());
+  iterator begin() { return Insts.begin(); }
+  iterator end() { return Insts.end(); }
+
+#ifndef NDEBUG
+  /// This is an expensive check, meant for testing.
+  bool operator==(const sandboxir::Region &Other) const;
+  void dump(raw_ostream &OS) const;
+  void dump() const;
+  friend raw_ostream &operator<<(raw_ostream &OS,
+                                 const sandboxir::Region &Rgn) {
+    Rgn.dump(OS);
+    return OS;
+  }
+#endif
+};
+
+} // namespace sandboxir
+} // namespace llvm
+#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_REGION_H
diff --git a/llvm/lib/Transforms/Vectorize/CMakeLists.txt b/llvm/lib/Transforms/Vectorize/CMakeLists.txt
index b11631350e8b4e..45b5618305de9f 100644
--- a/llvm/lib/Transforms/Vectorize/CMakeLists.txt
+++ b/llvm/lib/Transforms/Vectorize/CMakeLists.txt
@@ -4,6 +4,7 @@ add_llvm_component_library(LLVMVectorize
   LoopVectorizationLegality.cpp
   LoopVectorize.cpp
   SandboxVectorizer/Passes/BottomUpVec.cpp
+  SandboxVectorizer/Region.cpp
   SandboxVectorizer/SandboxVectorizer.cpp
   SLPVectorizer.cpp
   Vectorize.cpp
diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Region.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Region.cpp
new file mode 100644
index 00000000000000..91c0d71becd757
--- /dev/null
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Region.cpp
@@ -0,0 +1,52 @@
+//===- Region.cpp ---------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Vectorize/SandboxVectorizer/Region.h"
+
+using namespace llvm;
+
+sandboxir::Region::Region(sandboxir::Context &Ctx, sandboxir::BasicBlock &SBBB)
+    : Ctx(Ctx), SBBB(SBBB) {
+  static unsigned StaticRegionID;
+  RegionID = StaticRegionID++;
+}
+
+sandboxir::Region::~Region() {}
+
+void sandboxir::Region::add(sandboxir::Instruction *SBI) {
+  Insts.insert(SBI);
+}
+
+void sandboxir::Region::remove(sandboxir::Instruction *SBI) {
+  Insts.remove(SBI);
+}
+
+#ifndef NDEBUG
+bool sandboxir::Region::operator==(const sandboxir::Region &Other) const {
+  if (Insts.size() != Other.Insts.size())
+    return false;
+  if (!std::is_permutation(Insts.begin(), Insts.end(),
+                           Other.Insts.begin()))
+    return false;
+  return true;
+}
+
+void sandboxir::Region::dump(raw_ostream &OS) const {
+  OS << "RegionID: " << getID() << " ScalarCost=" << ScalarCost
+     << " VectorCost=" << VectorCost << "\n";
+  for (auto *I : Insts)
+    OS << *I << "\n";
+}
+
+void sandboxir::Region::dump() const {
+  dump(dbgs());
+  dbgs() << "\n";
+}
+
+#endif // NDEBUG
+

``````````

</details>


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


More information about the llvm-commits mailing list