LLVM 21.0.0git
VecUtils.h
Go to the documentation of this file.
1//===- VecUtils.h -----------------------------------------------*- C++ -*-===//
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// Collector for SandboxVectorizer related convenience functions that don't
10// belong in other classes.
11
12#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_VECUTILS_H
13#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_VECUTILS_H
14
16#include "llvm/IR/DataLayout.h"
17#include "llvm/SandboxIR/Type.h"
19
20namespace llvm::sandboxir {
21
22class VecUtils {
23public:
24 /// \Returns the number of elements in \p Ty. That is the number of lanes if a
25 /// fixed vector or 1 if scalar. ScalableVectors have unknown size and
26 /// therefore are unsupported.
27 static int getNumElements(Type *Ty) {
28 assert(!isa<ScalableVectorType>(Ty));
29 return Ty->isVectorTy() ? cast<FixedVectorType>(Ty)->getNumElements() : 1;
30 }
31 /// Returns \p Ty if scalar or its element type if vector.
32 static Type *getElementType(Type *Ty) {
33 return Ty->isVectorTy() ? cast<FixedVectorType>(Ty)->getElementType() : Ty;
34 }
35
36 /// \Returns true if \p I1 and \p I2 are load/stores accessing consecutive
37 /// memory addresses.
38 template <typename LoadOrStoreT>
39 static bool areConsecutive(LoadOrStoreT *I1, LoadOrStoreT *I2,
40 ScalarEvolution &SE, const DataLayout &DL) {
41 static_assert(std::is_same<LoadOrStoreT, LoadInst>::value ||
42 std::is_same<LoadOrStoreT, StoreInst>::value,
43 "Expected Load or Store!");
44 auto Diff = Utils::getPointerDiffInBytes(I1, I2, SE);
45 if (!Diff)
46 return false;
47 int ElmBytes = Utils::getNumBits(I1) / 8;
48 return *Diff == ElmBytes;
49 }
50
51 template <typename LoadOrStoreT>
53 const DataLayout &DL) {
54 static_assert(std::is_same<LoadOrStoreT, LoadInst>::value ||
55 std::is_same<LoadOrStoreT, StoreInst>::value,
56 "Expected Load or Store!");
57 assert(isa<LoadOrStoreT>(Bndl[0]) && "Expected Load or Store!");
58 auto *LastLS = cast<LoadOrStoreT>(Bndl[0]);
59 for (Value *V : drop_begin(Bndl)) {
60 assert(isa<LoadOrStoreT>(V) &&
61 "Unimplemented: we only support StoreInst!");
62 auto *LS = cast<LoadOrStoreT>(V);
63 if (!VecUtils::areConsecutive(LastLS, LS, SE, DL))
64 return false;
65 LastLS = LS;
66 }
67 return true;
68 }
69
70 /// \Returns the number of vector lanes of \p Ty or 1 if not a vector.
71 /// NOTE: It asserts that \p Ty is a fixed vector type.
72 static unsigned getNumLanes(Type *Ty) {
73 assert(!isa<ScalableVectorType>(Ty) && "Expect scalar or fixed vector");
74 if (auto *FixedVecTy = dyn_cast<FixedVectorType>(Ty))
75 return FixedVecTy->getNumElements();
76 return 1u;
77 }
78
79 /// \Returns the expected vector lanes of \p V or 1 if not a vector.
80 /// NOTE: It asserts that \p V is a fixed vector.
81 static unsigned getNumLanes(Value *V) {
83 }
84
85 /// \Returns the total number of lanes across all values in \p Bndl.
86 static unsigned getNumLanes(ArrayRef<Value *> Bndl) {
87 unsigned Lanes = 0;
88 for (Value *V : Bndl)
89 Lanes += getNumLanes(V);
90 return Lanes;
91 }
92
93 /// \Returns <NumElts x ElemTy>.
94 /// It works for both scalar and vector \p ElemTy.
95 static Type *getWideType(Type *ElemTy, unsigned NumElts) {
96 if (ElemTy->isVectorTy()) {
97 auto *VecTy = cast<FixedVectorType>(ElemTy);
98 ElemTy = VecTy->getElementType();
99 NumElts = VecTy->getNumElements() * NumElts;
100 }
101 return FixedVectorType::get(ElemTy, NumElts);
102 }
103 /// \Returns the instruction in \p Instrs that is lowest in the BB. Expects
104 /// that all instructions are in the same BB.
106 Instruction *LowestI = Instrs.front();
107 for (auto *I : drop_begin(Instrs)) {
108 if (LowestI->comesBefore(I))
109 LowestI = I;
110 }
111 return LowestI;
112 }
113 /// \Returns the lowest instruction in \p Vals, or nullptr if no instructions
114 /// are found. Skips instructions not in \p BB.
116 // Find the first Instruction in Vals that is also in `BB`.
117 auto It = find_if(Vals, [BB](Value *V) {
118 return isa<Instruction>(V) && cast<Instruction>(V)->getParent() == BB;
119 });
120 // If we couldn't find an instruction return nullptr.
121 if (It == Vals.end())
122 return nullptr;
123 Instruction *FirstI = cast<Instruction>(*It);
124 // Now look for the lowest instruction in Vals starting from one position
125 // after FirstI.
126 Instruction *LowestI = FirstI;
127 for (auto *V : make_range(std::next(It), Vals.end())) {
128 auto *I = dyn_cast<Instruction>(V);
129 // Skip non-instructions.
130 if (I == nullptr)
131 continue;
132 // Skips instructions not in \p BB.
133 if (I->getParent() != BB)
134 continue;
135 // If `LowestI` comes before `I` then `I` is the new lowest.
136 if (LowestI->comesBefore(I))
137 LowestI = I;
138 }
139 return LowestI;
140 }
141
142 /// If \p I is not a PHI it returns it. Else it walks down the instruction
143 /// chain looking for the last PHI and returns it. \Returns nullptr if \p I is
144 /// nullptr.
146 Instruction *LastI = I;
147 while (I != nullptr && isa<PHINode>(I)) {
148 LastI = I;
149 I = I->getNextNode();
150 }
151 return LastI;
152 }
153
154 /// If all values in \p Bndl are of the same scalar type then return it,
155 /// otherwise return nullptr.
157 Value *V0 = Bndl[0];
158 Type *Ty0 = Utils::getExpectedType(V0);
159 Type *ScalarTy = VecUtils::getElementType(Ty0);
160 for (auto *V : drop_begin(Bndl)) {
162 Type *NScalarTy = VecUtils::getElementType(NTy);
163 if (NScalarTy != ScalarTy)
164 return nullptr;
165 }
166 return ScalarTy;
167 }
168
169 /// Similar to tryGetCommonScalarType() but will assert that there is a common
170 /// type. So this is faster in release builds as it won't iterate through the
171 /// values.
173 Value *V0 = Bndl[0];
174 Type *Ty0 = Utils::getExpectedType(V0);
175 Type *ScalarTy = VecUtils::getElementType(Ty0);
176 assert(tryGetCommonScalarType(Bndl) && "Expected common scalar type!");
177 return ScalarTy;
178 }
179 /// \Returns the first integer power of 2 that is <= Num.
180 static unsigned getFloorPowerOf2(unsigned Num);
181
182#ifndef NDEBUG
183 /// Helper dump function for debugging.
184 LLVM_DUMP_METHOD static void dump(ArrayRef<Value *> Bndl);
186#endif // NDEBUG
187};
188
189} // namespace llvm::sandboxir
190
191#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_VECUTILS_H
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:622
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
const T & front() const
front - Get the first element.
Definition: ArrayRef.h:171
iterator end() const
Definition: ArrayRef.h:157
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
The main scalar evolution driver.
Contains a list of sandboxir::Instruction's.
Definition: BasicBlock.h:67
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
A sandboxir::User with operands, opcode and linked with previous/next instructions in an instruction ...
Definition: Instruction.h:42
bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
Definition: Instruction.h:214
Just like llvm::Type these are immutable, unique, never get freed and can only be created via static ...
Definition: Type.h:43
bool isVectorTy() const
True if this is an instance of VectorType.
Definition: Type.h:196
static std::optional< int > getPointerDiffInBytes(LoadOrStoreT *I0, LoadOrStoreT *I1, ScalarEvolution &SE)
\Returns the gap between the memory locations accessed by I0 and I1 in bytes.
Definition: Utils.h:92
static unsigned getNumBits(Type *Ty, const DataLayout &DL)
\Returns the number of bits of Ty.
Definition: Utils.h:66
static Type * getExpectedType(const Value *V)
\Returns the expected type of Value V.
Definition: Utils.h:32
A SandboxIR Value has users. This is the base class.
Definition: Value.h:63
static Type * tryGetCommonScalarType(ArrayRef< Value * > Bndl)
If all values in Bndl are of the same scalar type then return it, otherwise return nullptr.
Definition: VecUtils.h:156
static Instruction * getLowest(ArrayRef< Instruction * > Instrs)
\Returns the instruction in Instrs that is lowest in the BB.
Definition: VecUtils.h:105
static Type * getCommonScalarType(ArrayRef< Value * > Bndl)
Similar to tryGetCommonScalarType() but will assert that there is a common type.
Definition: VecUtils.h:172
static int getNumElements(Type *Ty)
\Returns the number of elements in Ty.
Definition: VecUtils.h:27
static Instruction * getLastPHIOrSelf(Instruction *I)
If I is not a PHI it returns it.
Definition: VecUtils.h:145
static unsigned getNumLanes(Type *Ty)
\Returns the number of vector lanes of Ty or 1 if not a vector.
Definition: VecUtils.h:72
static Instruction * getLowest(ArrayRef< Value * > Vals, BasicBlock *BB)
\Returns the lowest instruction in Vals, or nullptr if no instructions are found.
Definition: VecUtils.h:115
static LLVM_DUMP_METHOD void dump(ArrayRef< Value * > Bndl)
Helper dump function for debugging.
Definition: VecUtils.cpp:28
static Type * getWideType(Type *ElemTy, unsigned NumElts)
\Returns <NumElts x ElemTy>.
Definition: VecUtils.h:95
static bool areConsecutive(LoadOrStoreT *I1, LoadOrStoreT *I2, ScalarEvolution &SE, const DataLayout &DL)
\Returns true if I1 and I2 are load/stores accessing consecutive memory addresses.
Definition: VecUtils.h:39
static Type * getElementType(Type *Ty)
Returns Ty if scalar or its element type if vector.
Definition: VecUtils.h:32
static bool areConsecutive(ArrayRef< Value * > &Bndl, ScalarEvolution &SE, const DataLayout &DL)
Definition: VecUtils.h:52
static unsigned getNumLanes(Value *V)
\Returns the expected vector lanes of V or 1 if not a vector.
Definition: VecUtils.h:81
static unsigned getNumLanes(ArrayRef< Value * > Bndl)
\Returns the total number of lanes across all values in Bndl.
Definition: VecUtils.h:86
static unsigned getFloorPowerOf2(unsigned Num)
\Returns the first integer power of 2 that is <= Num.
Definition: VecUtils.cpp:13
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition: STLExtras.h:329
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1766