[llvm] [SLP][modularisation][NFC] Move type/width helpers to SLPTypeUtils (1/2) (PR #214672)

Madhur Amilkanthwar via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 30 21:36:30 PDT 2026


https://github.com/madhur13490 updated https://github.com/llvm/llvm-project/pull/214672

>From ca3e4f91efb7b4ec1b26a15c76e03eb96aaeddbd Mon Sep 17 00:00:00 2001
From: Madhur Amilkanthwar <madhura at nvidia.com>
Date: Wed, 5 Aug 2026 10:57:04 -0700
Subject: [PATCH] [SLP][modularisation][NFC] Move type/width helpers to
 SLPTypeUtils (1/2)

Move the following BoUpSLP-independent type/width helpers out of
SLPVectorizer.cpp into a new SLPVectorizer/SLPTypeUtils.{h,cpp}:

  isValidElementType
  getValueType
  getWidenedType

SLPReVec is made non-static and extern-declared in SLPTypeUtils.cpp so
the moved helpers can reference it; behavior is unchanged.

Part of the SLPVectorizer.cpp modularization effort:
https://discourse.llvm.org/t/modularizing-slpvectorizer-cpp/90922
---
 llvm/lib/Transforms/Vectorize/CMakeLists.txt  |  1 +
 .../Transforms/Vectorize/SLPVectorizer.cpp    | 64 +---------------
 .../Vectorize/SLPVectorizer/SLPTypeUtils.cpp  | 76 +++++++++++++++++++
 .../Vectorize/SLPVectorizer/SLPTypeUtils.h    | 46 +++++++++++
 4 files changed, 127 insertions(+), 60 deletions(-)
 create mode 100644 llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPTypeUtils.cpp
 create mode 100644 llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPTypeUtils.h

diff --git a/llvm/lib/Transforms/Vectorize/CMakeLists.txt b/llvm/lib/Transforms/Vectorize/CMakeLists.txt
index 7a134a375309e..11559b481394a 100644
--- a/llvm/lib/Transforms/Vectorize/CMakeLists.txt
+++ b/llvm/lib/Transforms/Vectorize/CMakeLists.txt
@@ -25,6 +25,7 @@ add_llvm_component_library(LLVMVectorize
   SandboxVectorizer/VecUtils.cpp
   SLPVectorizer/SLPCompatibilityAnalysis.cpp
   SLPVectorizer/SLPCostAnalysis.cpp
+  SLPVectorizer/SLPTypeUtils.cpp
   SLPVectorizer/SLPUtils.cpp
   SLPVectorizer.cpp
   Vectorize.cpp
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index f8b168f0327f7..36e0bdbf7ac4a 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -19,6 +19,7 @@
 #include "llvm/Transforms/Vectorize/SLPVectorizer.h"
 #include "SLPVectorizer/SLPCompatibilityAnalysis.h"
 #include "SLPVectorizer/SLPCostAnalysis.h"
+#include "SLPVectorizer/SLPTypeUtils.h"
 #include "SLPVectorizer/SLPUtils.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
@@ -130,7 +131,9 @@ static cl::opt<bool>
     RunSLPVectorization("vectorize-slp", cl::init(true), cl::Hidden,
                         cl::desc("Run the SLP vectorization passes"));
 
-static cl::opt<bool>
+// Non-static so SLPVectorizer/ helper modules can reference it via an extern
+// declaration; see SLPTypeUtils.cpp.
+cl::opt<bool>
     SLPReVec("slp-revec", cl::init(false), cl::Hidden,
              cl::desc("Enable vectorization for wider vector utilization"));
 
@@ -350,65 +353,6 @@ static const int MinScheduleRegionSize = 16;
 /// Maximum allowed number of operands in the PHI nodes.
 static const unsigned MaxPHINumOperands = 128;
 
-/// Predicate for the element types that the SLP vectorizer supports.
-///
-/// The most important thing to filter here are types which are invalid in LLVM
-/// vectors. We also filter target specific types which have absolutely no
-/// meaningful vectorization path such as x86_fp80 and ppc_f128. This just
-/// avoids spending time checking the cost model and realizing that they will
-/// be inevitably scalarized.
-static bool isValidElementType(Type *Ty) {
-  // TODO: Support ScalableVectorType.
-  if (SLPReVec && isVectorizedTy(Ty) && !getVectorizedTypeVF(Ty).isScalable())
-    Ty = toScalarizedTy(Ty);
-  return canVectorizeTy(Ty) && !Ty->isX86_FP80Ty() && !Ty->isPPC_FP128Ty() &&
-         !Ty->isVoidTy();
-}
-
-/// Returns the "element type" of the given value/instruction \p V.
-/// For stores, returns the stored value type; for insertelement (when ReVec is
-/// off), the inserted operand type. For compares, the default is to return the
-/// result type (i1); when \p LookThroughCmp is true, returns the type of the
-/// compared operands instead, which is needed for vector width calculations
-/// (the width is determined by the operand type, not the i1 result).
-static Type *getValueType(Value *V, bool LookThroughCmp = false) {
-  if (auto *SI = dyn_cast<StoreInst>(V))
-    return SI->getValueOperand()->getType();
-  if (LookThroughCmp)
-    if (auto *CI = dyn_cast<CmpInst>(V))
-      return CI->getOperand(0)->getType();
-  if (!SLPReVec)
-    if (auto *IE = dyn_cast<InsertElementInst>(V))
-      return IE->getOperand(1)->getType();
-  if (auto *IV = dyn_cast<InsertValueInst>(V))
-    return IV->getOperand(1)->getType();
-  return V->getType();
-}
-
-/// \returns the vector type of ScalarTy based on vectorization factor.
-static Type *getWidenedType(Type *ScalarTy, unsigned VF) {
-  if (VF == 1 && !isVectorizedTy(ScalarTy)) {
-    // Workaround for 1 x vector types: toVectorizedTy returns the type
-    // unchanged when EC is scalar, but BoUpSLP relies on widening to
-    // <1 x ScalarTy> (or struct of <1 x ElTy>) to keep the rest of the
-    // pipeline operating on vector types.
-    if (auto *StructTy = dyn_cast<StructType>(ScalarTy)) {
-      assert(isUnpackedStructLiteral(StructTy) &&
-             "expected unpacked struct literal");
-      assert(all_of(StructTy->elements(), VectorType::isValidElementType) &&
-             "expected all element types to be valid vector element types");
-      return StructType::get(
-          StructTy->getContext(),
-          map_to_vector(StructTy->elements(), [&](Type *ElTy) -> Type * {
-            return FixedVectorType::get(ElTy, 1);
-          }));
-    }
-    return FixedVectorType::get(ScalarTy, 1);
-  }
-  return toVectorizedTy(toScalarizedTy(ScalarTy),
-                        ElementCount::getFixed(VF * getNumElements(ScalarTy)));
-}
-
 /// Returns the number of elements of the given type \p Ty, not less than \p Sz,
 /// which forms type, which splits by \p TTI into whole vector types during
 /// legalization.
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPTypeUtils.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPTypeUtils.cpp
new file mode 100644
index 0000000000000..dd8f0ac69c735
--- /dev/null
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPTypeUtils.cpp
@@ -0,0 +1,76 @@
+//===- SLPTypeUtils.cpp - SLP Vectorizer type/width helpers ---------------===//
+//
+// 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 "SLPTypeUtils.h"
+#include "SLPUtils.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVectorExtras.h"
+#include "llvm/Analysis/VectorUtils.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
+
+#include <cassert>
+
+using namespace llvm;
+
+// Defined in SLPVectorizer.cpp.
+extern cl::opt<bool> SLPReVec;
+
+namespace llvm::slpvectorizer {
+
+bool isValidElementType(Type *Ty) {
+  // TODO: Support ScalableVectorType.
+  if (SLPReVec && isVectorizedTy(Ty) && !getVectorizedTypeVF(Ty).isScalable())
+    Ty = toScalarizedTy(Ty);
+  return canVectorizeTy(Ty) && !Ty->isX86_FP80Ty() && !Ty->isPPC_FP128Ty() &&
+         !Ty->isVoidTy();
+}
+
+Type *getValueType(Value *V, bool LookThroughCmp) {
+  if (auto *SI = dyn_cast<StoreInst>(V))
+    return SI->getValueOperand()->getType();
+  if (LookThroughCmp)
+    if (auto *CI = dyn_cast<CmpInst>(V))
+      return CI->getOperand(0)->getType();
+  if (!SLPReVec)
+    if (auto *IE = dyn_cast<InsertElementInst>(V))
+      return IE->getOperand(1)->getType();
+  if (auto *IV = dyn_cast<InsertValueInst>(V))
+    return IV->getOperand(1)->getType();
+  return V->getType();
+}
+
+Type *getWidenedType(Type *ScalarTy, unsigned VF) {
+  if (VF == 1 && !isVectorizedTy(ScalarTy)) {
+    // Workaround for 1 x vector types: toVectorizedTy returns the type
+    // unchanged when EC is scalar, but BoUpSLP relies on widening to
+    // <1 x ScalarTy> (or struct of <1 x ElTy>) to keep the rest of the
+    // pipeline operating on vector types.
+    if (auto *StructTy = dyn_cast<StructType>(ScalarTy)) {
+      assert(isUnpackedStructLiteral(StructTy) &&
+             "expected unpacked struct literal");
+      assert(all_of(StructTy->elements(), VectorType::isValidElementType) &&
+             "expected all element types to be valid vector element types");
+      return StructType::get(
+          StructTy->getContext(),
+          map_to_vector(StructTy->elements(), [&](Type *ElTy) -> Type * {
+            return FixedVectorType::get(ElTy, 1);
+          }));
+    }
+    return FixedVectorType::get(ScalarTy, 1);
+  }
+  return toVectorizedTy(toScalarizedTy(ScalarTy),
+                        ElementCount::getFixed(VF * getNumElements(ScalarTy)));
+}
+
+} // namespace llvm::slpvectorizer
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPTypeUtils.h b/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPTypeUtils.h
new file mode 100644
index 0000000000000..f43fd98b6288e
--- /dev/null
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer/SLPTypeUtils.h
@@ -0,0 +1,46 @@
+//===- SLPTypeUtils.h - SLP Vectorizer type/width helpers ------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Internal header used by SLPVectorizer.cpp. It declares free type and vector
+// width helpers that do not depend on BoUpSLP or any other SLP-private type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPTYPEUTILS_H
+#define LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPTYPEUTILS_H
+
+namespace llvm {
+class Type;
+class Value;
+} // namespace llvm
+
+namespace llvm::slpvectorizer {
+
+/// Predicate for the element types that the SLP vectorizer supports.
+///
+/// The most important thing to filter here are types which are invalid in LLVM
+/// vectors. We also filter target specific types which have absolutely no
+/// meaningful vectorization path such as x86_fp80 and ppc_f128. This just
+/// avoids spending time checking the cost model and realizing that they will
+/// be inevitably scalarized.
+bool isValidElementType(Type *Ty);
+
+/// Returns the "element type" of the given value/instruction \p V.
+/// For stores, returns the stored value type; for insertelement (when ReVec is
+/// off), the inserted operand type. For compares, the default is to return the
+/// result type (i1); when \p LookThroughCmp is true, returns the type of the
+/// compared operands instead, which is needed for vector width calculations
+/// (the width is determined by the operand type, not the i1 result).
+Type *getValueType(Value *V, bool LookThroughCmp = false);
+
+/// \returns the vector type of ScalarTy based on vectorization factor.
+Type *getWidenedType(Type *ScalarTy, unsigned VF);
+
+} // namespace llvm::slpvectorizer
+
+#endif // LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPTYPEUTILS_H



More information about the llvm-commits mailing list