[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