LLVM 24.0.0git
VecUtils.cpp
Go to the documentation of this file.
1//===- VecUtils.cpp -------------------------------------------------------===//
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
10#include "../VectorizeOptions.h"
11
12#include "llvm/ADT/DenseMap.h"
13#include "llvm/ADT/Sequence.h"
18
19namespace llvm::sandboxir {
20
23 for (unsigned Idx : seq<unsigned>(U->getNumOperands()))
24 if (U->getOperand(Idx) == Op)
25 OpIdxVec.push_back(Idx);
26 return OpIdxVec;
27}
28
29static std::optional<BundleTy>
31 Instruction *SeedUserInst,
33 SmallVector<unsigned, 2> OpIdxVec0 =
34 getOperandIndicesInUser(SeedUserInst, Seed);
35 assert(!OpIdxVec0.empty() && "U0 does not use Seed!");
36 BundleTy NextUserBndl;
37 NextUserBndl.push_back(SeedUserInst);
38 Claimed.insert(SeedUserInst);
39 for (Value *V : drop_begin(Bndl)) {
40 Instruction *Match = nullptr;
41 for (User *U : V->users()) {
42 auto *UI = dyn_cast<Instruction>(U);
43 if (!UI || IMaps.isVectorized(UI) || Claimed.contains(UI) ||
44 UI->getOpcode() != SeedUserInst->getOpcode() ||
45 UI->getType() != SeedUserInst->getType() ||
46 UI->getParent() != SeedUserInst->getParent() ||
47 getOperandIndicesInUser(UI, V) != OpIdxVec0)
48 continue;
49
50 Match = UI;
51 break;
52 }
53 if (!Match)
54 return std::nullopt;
55 NextUserBndl.push_back(Match);
56 }
57
58 for (auto *I : NextUserBndl)
59 Claimed.insert(cast<Instruction>(I));
60 return NextUserBndl;
61}
62
67 if (Bndl.empty())
68 return Bundles;
69
70 Value *V0 = Bndl[0];
71 DenseSet<User *> SeenUsers;
72 const VectorizeOptions &Opts = getVectorizeOptions(V0->getContext());
73 // For each user U0 of lane 0, try to form a bundle of matching users across
74 // all lanes. Cap the number of users considered to bound compilation time,
75 // since each one may trigger an O(Bndl.size()) search across the other
76 // lanes' users.
77 for (User *U0 : V0->users()) {
78 if (SeenUsers.size() >= Opts.sbvec_max_users_to_consider)
79 break;
80 if (!SeenUsers.insert(U0).second)
81 continue;
82 auto *UI0 = dyn_cast<Instruction>(U0);
83 if (!UI0 || IMaps.isVectorized(UI0) || Claimed.contains(UI0))
84 continue;
85 std::optional<BundleTy> NextUserBndl =
86 getMatchingBundle(Bndl, IMaps, V0, UI0, Claimed);
87 if (NextUserBndl)
88 Bundles.emplace_back(std::move(*NextUserBndl));
89 }
90 return Bundles;
91}
92
93unsigned VecUtils::getFloorPowerOf2(unsigned Num) {
94 if (Num == 0)
95 return Num;
96 unsigned Mask = Num;
97 Mask >>= 1;
98 for (unsigned ShiftBy = 1; ShiftBy < sizeof(Num) * 8; ShiftBy <<= 1)
99 Mask |= Mask >> ShiftBy;
100 return Num & ~Mask;
101}
102
103template <typename T>
105 BndlRef<T *> Bndl) {
106 for (T *V : Bndl) {
107 assert(isa<Instruction>(V) && "Only works with instructions");
108 DeadInstrCandidates.insert(cast<Instruction>(V));
109 }
110 // Also collect the GEPs of vectorized loads and stores.
111 auto Opcode = cast<Instruction>(Bndl[0])->getOpcode();
112 switch (Opcode) {
113 case Instruction::Opcode::Load: {
114 for (T *V : drop_begin(Bndl))
115 if (auto *Ptr =
117 DeadInstrCandidates.insert(Ptr);
118 break;
119 }
120 case Instruction::Opcode::Store: {
121 for (T *V : drop_begin(Bndl))
122 if (auto *Ptr =
124 DeadInstrCandidates.insert(Ptr);
125 break;
126 }
127 default:
128 break;
129 }
130}
131
132template void
135template LLVM_EXPORT_TEMPLATE void
138
140 DenseMap<BasicBlock *, SmallVector<Instruction *>> SortedDeadInstrCandidates;
141 // The dead instrs could span BBs, so we need to collect and sort them per BB.
142 for (auto *V : DeadInstrCandidates) {
143 auto *DeadI = cast<Instruction>(V);
144 SortedDeadInstrCandidates[DeadI->getParent()].push_back(DeadI);
145 }
146 for (auto &Pair : SortedDeadInstrCandidates)
147 sort(Pair.second,
148 [](Instruction *I1, Instruction *I2) { return I1->comesBefore(I2); });
149 for (const auto &Pair : SortedDeadInstrCandidates) {
150 for (Instruction *I : reverse(Pair.second)) {
151 if (I->hasNUses(0)) {
152 // Erase the dead instructions bottom-to-top.
153 LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Erase dead: " << *I << "\n");
154 I->eraseFromParent();
155 }
156 }
157 }
158 DeadInstrCandidates.clear();
159}
160
161#ifndef NDEBUG
162template <typename T> static void dumpImpl(ArrayRef<T *> Bndl) {
163 for (auto [Idx, V] : enumerate(Bndl))
164 dbgs() << Idx << "." << *V << "\n";
165}
168
169template <typename T> void BndlRef<T>::dump() const {
170 print(dbgs());
171 dbgs() << "\n";
172}
173// Explicit instantiation for commonly used types.
174template class BndlRef<Instruction *>;
175template class BndlRef<Value *>;
176
177#endif // NDEBUG
178
179} // namespace llvm::sandboxir
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_EXPORT_TEMPLATE
Definition Compiler.h:213
This file defines the DenseMap class.
#define I(x, y, z)
Definition MD5.cpp:57
#define T
static ManagedStatic< cl::opt< uint64_t >, CreateSeed > Seed
Provides some synthesis utilities to produce sequences of values.
This file defines the SmallPtrSet class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
#define DEBUG_PREFIX
Definition Debug.h:19
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
size_type size() const
Definition DenseSet.h:84
An ArrayRef of Values or Instructions that we can print/dump for debugging.
Definition VecUtils.h:39
LLVM_DUMP_METHOD void dump() const
Definition VecUtils.cpp:169
Maps the original instructions to the vectorized instrs and the reverse.
Definition InstrMaps.h:50
bool isVectorized(Value *Orig) const
\Returns true if Orig was vectorized
Definition InstrMaps.h:65
A sandboxir::User with operands, opcode and linked with previous/next instructions in an instruction ...
Definition Instruction.h:43
Opcode getOpcode() const
\Returns this Instruction's opcode.
LLVM_ABI BasicBlock * getParent() const
\Returns the BasicBlock containing this Instruction, or null if it is detached.
A sandboxir::User has operands.
Definition User.h:59
A SandboxIR Value has users. This is the base class.
Definition Value.h:72
LLVM_ABI Type * getType() const
Definition Value.cpp:46
iterator_range< user_iterator > users()
Definition Value.h:252
LLVM_ABI void tryEraseDeadInstrs()
Erase candidates recorded by collectPotentiallyDeadInstrs() that now have no uses,...
Definition VecUtils.cpp:139
void collectPotentiallyDeadInstrs(BndlRef< T * > Bndl)
Record instructions in Bndl that may be dead after vectorization.
Definition VecUtils.cpp:104
static LLVM_DUMP_METHOD void dump(ArrayRef< Value * > Bndl)
Helper dump function for debugging.
Definition VecUtils.cpp:166
static LLVM_ABI unsigned getFloorPowerOf2(unsigned Num)
\Returns the first integer power of 2 that is <= Num.
Definition VecUtils.cpp:93
static LLVM_ABI SmallVector< BundleTy > getNextUserBundles(ArrayRef< Value * > Bndl, const InstrMaps &IMaps, SmallPtrSet< Instruction *, 4 > &Claimed)
For each user of lane 0 in Bndl, try to form a bundle of matching users for all lanes.
Definition VecUtils.cpp:64
static SmallVector< unsigned, 2 > getOperandIndicesInUser(User *U, Value *Op)
Definition VecUtils.cpp:21
static void dumpImpl(ArrayRef< T * > Bndl)
Definition VecUtils.cpp:162
SmallVector< Value *, 4 > BundleTy
Definition VecUtils.h:82
static std::optional< BundleTy > getMatchingBundle(ArrayRef< Value * > Bndl, const InstrMaps &IMaps, Value *Seed, Instruction *SeedUserInst, SmallPtrSet< Instruction *, 4 > &Claimed)
Definition VecUtils.cpp:30
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
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
DWARFExpression::Operation Op
const VectorizeOptions & getVectorizeOptions(const LLVMContext &C)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341