LLVM 24.0.0git
SLPTypeUtils.cpp
Go to the documentation of this file.
1//===- SLPTypeUtils.cpp - SLP Vectorizer type/width helpers ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "SLPTypeUtils.h"
10#include "SLPUtils.h"
11
12#include "llvm/ADT/STLExtras.h"
14#include "llvm/ADT/bit.h"
18#include "llvm/IR/Instruction.h"
20#include "llvm/IR/Type.h"
21#include "llvm/IR/Value.h"
25
26#include <cassert>
27
28using namespace llvm;
29
30namespace llvm::slpvectorizer {
31
32bool isValidElementType(Type *Ty, bool ReVec) {
33 // TODO: Support ScalableVectorType.
34 if (ReVec && isVectorizedTy(Ty) && !getVectorizedTypeVF(Ty).isScalable())
35 Ty = toScalarizedTy(Ty);
36 return canVectorizeTy(Ty) && !Ty->isX86_FP80Ty() && !Ty->isPPC_FP128Ty() &&
37 !Ty->isVoidTy();
38}
39
40Type *getValueType(Value *V, bool ReVec, bool LookThroughCmp) {
41 if (auto *SI = dyn_cast<StoreInst>(V))
42 return SI->getValueOperand()->getType();
43 if (LookThroughCmp)
44 if (auto *CI = dyn_cast<CmpInst>(V))
45 return CI->getOperand(0)->getType();
46 if (!ReVec)
47 if (auto *IE = dyn_cast<InsertElementInst>(V))
48 return IE->getOperand(1)->getType();
49 if (auto *IV = dyn_cast<InsertValueInst>(V))
50 return IV->getOperand(1)->getType();
51 return V->getType();
52}
53
54Type *getWidenedType(Type *ScalarTy, unsigned VF) {
55 if (VF == 1 && !isVectorizedTy(ScalarTy)) {
56 // Workaround for 1 x vector types: toVectorizedTy returns the type
57 // unchanged when EC is scalar, but BoUpSLP relies on widening to
58 // <1 x ScalarTy> (or struct of <1 x ElTy>) to keep the rest of the
59 // pipeline operating on vector types.
60 if (auto *StructTy = dyn_cast<StructType>(ScalarTy)) {
62 "expected unpacked struct literal");
63 assert(all_of(StructTy->elements(), VectorType::isValidElementType) &&
64 "expected all element types to be valid vector element types");
65 return StructType::get(
66 StructTy->getContext(),
67 map_to_vector(StructTy->elements(), [&](Type *ElTy) -> Type * {
68 return FixedVectorType::get(ElTy, 1);
69 }));
70 }
71 return FixedVectorType::get(ScalarTy, 1);
72 }
73 return toVectorizedTy(toScalarizedTy(ScalarTy),
75}
76
78 unsigned Sz, bool ReVec) {
79 if (!isValidElementType(Ty, ReVec) || isa<StructType>(Ty))
80 return bit_ceil(Sz);
81 // Find the number of elements, which forms full vectors.
82 const unsigned NumParts = TTI.getNumberOfParts(getWidenedType(Ty, Sz));
83 if (NumParts == 0 || NumParts >= Sz)
84 return bit_ceil(Sz);
85 return bit_ceil(divideCeil(Sz, NumParts)) * NumParts;
86}
87
89 Type *Ty, unsigned Sz, bool ReVec) {
90 if (!isValidElementType(Ty, ReVec) || isa<StructType>(Ty))
91 return bit_floor(Sz);
92 // Find the number of elements, which forms full vectors.
93 unsigned NumParts = TTI.getNumberOfParts(getWidenedType(Ty, Sz));
94 if (NumParts == 0 || NumParts >= Sz)
95 return bit_floor(Sz);
96 unsigned RegVF = bit_ceil(divideCeil(Sz, NumParts));
97 if (RegVF > Sz)
98 return bit_floor(Sz);
99 return (Sz / RegVF) * RegVF;
100}
101
103 unsigned Opcode, Type *ScalarTy,
104 unsigned NumElts, bool ReVec) {
105 if (!Instruction::isIntDivRem(Opcode) || has_single_bit(NumElts))
106 return nullptr;
107 unsigned PaddedNumElts =
108 getFullVectorNumberOfElements(TTI, ScalarTy, NumElts, ReVec);
109 if (PaddedNumElts == NumElts)
110 return nullptr;
111 return cast<FixedVectorType>(getWidenedType(ScalarTy, PaddedNumElts));
112}
113
115 unsigned Sz, bool ReVec) {
116 if (Sz <= 1)
117 return false;
118 if (!isValidElementType(Ty, ReVec) && !isa<FixedVectorType>(Ty))
119 return false;
120 if (has_single_bit(Sz))
121 return true;
122 if (isa<StructType>(Ty))
123 return false;
124 const unsigned NumParts = TTI.getNumberOfParts(getWidenedType(Ty, Sz));
125 return NumParts > 0 && NumParts < Sz && has_single_bit(Sz / NumParts) &&
126 Sz % NumParts == 0;
127}
128
129bool isAllowedNonPowerOf2VF(unsigned NumElts, bool AllowNonPowerOf2) {
130 return AllowNonPowerOf2 && has_single_bit(NumElts + 1);
131}
132
133unsigned getNumberOfPartsOrRegs(bool QueryNumParts,
134 const TargetTransformInfo &TTI, Type *VecTy,
135 Type *ScalarTy, bool ReVec, unsigned Limit) {
136 if (isa<StructType>(VecTy))
137 return 1;
138 unsigned NumParts = QueryNumParts ? TTI.getNumberOfParts(VecTy)
139 : TTI.getRegUsageForType(VecTy);
140 if (NumParts == 0 || NumParts >= Limit)
141 return 1;
142 unsigned Sz = getNumElements(VecTy);
143 unsigned ScalarSz = getNumElements(ScalarTy);
144 Type *ElementTy = toScalarizedTy(VecTy);
145 unsigned PWSz = getFullVectorNumberOfElements(TTI, ElementTy, Sz, ReVec);
146 if (NumParts >= Sz || PWSz % NumParts != 0 ||
147 (PWSz / NumParts) % ScalarSz != 0 ||
148 !hasFullVectorsOrPowerOf2(TTI, ElementTy, PWSz / NumParts, ReVec))
149 return 1;
150 const unsigned NumElts = PWSz / NumParts;
151 if (divideCeil(Sz, NumElts) != NumParts)
152 return 1;
153 return NumParts;
154}
155
156bool isTypeLimitNeutral(const Value *V, bool IsMax, const DataLayout &DL) {
157 SimplifyQuery SQ(DL);
158 return IsMax ? isKnownNonNegative(V, SQ) : isKnownNegative(V, SQ);
159}
160
161} // namespace llvm::slpvectorizer
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains some templates that are useful if you are working with the STL at all.
This file defines less commonly used SmallVector utilities.
This pass exposes codegen information to IR-level passes.
This file implements the C++20 <bit> header.
static const uint32_t IV[8]
Definition blake3_impl.h:83
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:305
Class to represent fixed width SIMD vectors.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:843
bool isIntDivRem() const
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:467
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM Value Representation.
Definition Value.h:75
static LLVM_ABI bool isValidElementType(Type *ElemTy)
Return true if the specified type is valid as a element type.
A private "module" namespace for types and utilities used by this pass.
unsigned getNumberOfPartsOrRegs(bool QueryNumParts, const TargetTransformInfo &TTI, Type *VecTy, Type *ScalarTy, bool ReVec, unsigned Limit)
Returns number of parts, the type VecTy will be split at the codegen phase.
unsigned getFloorFullVectorNumberOfElements(const TargetTransformInfo &TTI, Type *Ty, unsigned Sz, bool ReVec)
Returns the number of elements of the given type Ty, not greater than Sz, which forms type,...
unsigned getNumElements(Type *Ty)
Definition SLPUtils.cpp:103
Type * getWidenedType(Type *ScalarTy, unsigned VF)
bool hasFullVectorsOrPowerOf2(const TargetTransformInfo &TTI, Type *Ty, unsigned Sz, bool ReVec)
Returns true if widened type of Ty elements with size Sz represents full vector type,...
bool isAllowedNonPowerOf2VF(unsigned NumElts, bool AllowNonPowerOf2)
True when AllowNonPowerOf2 is set and NumElts is a supported non-power-of-2 width: NumElts + 1 must b...
FixedVectorType * getMaskedDivRemType(const TargetTransformInfo &TTI, unsigned Opcode, Type *ScalarTy, unsigned NumElts, bool ReVec)
For a non-power-of-2 NumElts-wide integer div/rem Opcode, returns the padded full-register vector typ...
bool isValidElementType(Type *Ty, bool ReVec)
Predicate for the element types that the SLP vectorizer supports.
Type * getValueType(Value *V, bool ReVec, bool LookThroughCmp)
Returns the "element type" of the given value/instruction V.
bool isTypeLimitNeutral(const Value *V, bool IsMax, const DataLayout &DL)
Returns true if the type limit of the smax (IsMax) or smin lane V stays neutral after narrowing.
unsigned getFullVectorNumberOfElements(const TargetTransformInfo &TTI, Type *Ty, unsigned Sz, bool ReVec)
Returns the number of elements of the given type Ty, not less than Sz, which forms type,...
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
Type * toScalarizedTy(Type *Ty)
A helper for converting vectorized types to scalarized (non-vector) types.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool isUnpackedStructLiteral(StructType *StructTy)
auto map_to_vector(ContainerTy &&C, FuncTy &&F)
Map a range to a SmallVector with element types deduced from the mapping.
bool isVectorizedTy(Type *Ty)
Returns true if Ty is a vector type or a struct of vector types where all vector types share the same...
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
Definition bit.h:362
constexpr bool has_single_bit(T Value) noexcept
Definition bit.h:149
LLVM_ABI bool isKnownNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the given value is known be negative (i.e.
ElementCount getVectorizedTypeVF(Type *Ty)
Returns the number of vector elements for a vectorized type.
Type * toVectorizedTy(Type *Ty, ElementCount EC)
A helper for converting to vectorized types.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
bool canVectorizeTy(Type *Ty)
Returns true if Ty is a valid vector element type, void, or an unpacked literal struct where all elem...
TargetTransformInfo TTI
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
Definition bit.h:347
LLVM_ABI bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.