LLVM 24.0.0git
Legality.cpp
Go to the documentation of this file.
1//===- Legality.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
15#include "llvm/Support/Debug.h"
18
19namespace llvm::sandboxir {
20
21#ifndef NDEBUG
22void ShuffleMask::dump() const {
23 print(dbgs());
24 dbgs() << "\n";
25}
26
28 print(dbgs());
29 dbgs() << "\n";
30}
31#endif // NDEBUG
32
33std::optional<ResultReason>
34LegalityAnalysis::notVectorizableBasedOnOpcodesAndTypes(BndlRef<Value *> Bndl) {
35 auto *I0 = cast<Instruction>(Bndl[0]);
36 auto Opcode = I0->getOpcode();
37 // If they have different opcodes, then we cannot form a vector (for now).
38 if (any_of(drop_begin(Bndl), [Opcode](Value *V) {
39 return cast<Instruction>(V)->getOpcode() != Opcode;
40 }))
42
43 // If not the same scalar type, Pack. This will accept scalars and vectors as
44 // long as the element type is the same.
46 if (any_of(drop_begin(Bndl), [ElmTy0](Value *V) {
48 }))
50
51 // TODO: Allow vectorization of instrs with different flags as long as we
52 // change them to the least common one.
53 // For now pack if differnt FastMathFlags.
54 if (isa<FPMathOperator>(I0)) {
55 FastMathFlags FMF0 = cast<Instruction>(Bndl[0])->getFastMathFlags();
56 if (any_of(drop_begin(Bndl), [FMF0](auto *V) {
57 return cast<Instruction>(V)->getFastMathFlags() != FMF0;
58 }))
60 }
61
62 // TODO: Allow vectorization by using common flags.
63 // For now Pack if they don't have the same wrap flags.
64 bool CanHaveWrapFlags =
66 if (CanHaveWrapFlags) {
67 bool NUW0 = I0->hasNoUnsignedWrap();
68 bool NSW0 = I0->hasNoSignedWrap();
69 if (any_of(drop_begin(Bndl), [NUW0, NSW0](auto *V) {
70 return cast<Instruction>(V)->hasNoUnsignedWrap() != NUW0 ||
71 cast<Instruction>(V)->hasNoSignedWrap() != NSW0;
72 })) {
74 }
75 }
76
77 // Now we need to do further checks for specific opcodes.
78 switch (Opcode) {
79 case Instruction::Opcode::ZExt:
80 case Instruction::Opcode::SExt:
81 case Instruction::Opcode::FPToUI:
82 case Instruction::Opcode::FPToSI:
83 case Instruction::Opcode::FPExt:
84 case Instruction::Opcode::PtrToAddr:
85 case Instruction::Opcode::PtrToInt:
86 case Instruction::Opcode::IntToPtr:
87 case Instruction::Opcode::SIToFP:
88 case Instruction::Opcode::UIToFP:
89 case Instruction::Opcode::Trunc:
90 case Instruction::Opcode::FPTrunc:
91 case Instruction::Opcode::BitCast: {
92 // We have already checked that they are of the same opcode.
93 assert(all_of(Bndl,
94 [Opcode](Value *V) {
95 return cast<Instruction>(V)->getOpcode() == Opcode;
96 }) &&
97 "Different opcodes, should have early returned!");
98 // But for these opcodes we should also check the operand type.
99 Type *FromTy0 = Utils::getExpectedType(I0->getOperand(0));
100 if (any_of(drop_begin(Bndl), [FromTy0](Value *V) {
102 FromTy0;
103 }))
105 return std::nullopt;
106 }
107 case Instruction::Opcode::FCmp:
108 case Instruction::Opcode::ICmp: {
109 // We need the same predicate and the same operand type.
110 auto Pred0 = cast<CmpInst>(I0)->getPredicate();
111 Type *Ty0 = cast<CmpInst>(I0)->getOperand(0)->getType();
112 bool Same = all_of(Bndl, [Pred0, Ty0](Value *V) {
113 auto *CmpI = cast<CmpInst>(V);
114 return CmpI->getPredicate() == Pred0 &&
115 CmpI->getOperand(0)->getType() == Ty0;
116 });
117 if (Same)
118 return std::nullopt;
120 }
121 case Instruction::Opcode::Select: {
122 auto *Sel0 = cast<SelectInst>(Bndl[0]);
123 auto *Cond0 = Sel0->getCondition();
125 // TODO: For now we don't vectorize if the lanes in the condition don't
126 // match those of the select instruction.
128 return std::nullopt;
129 }
130 case Instruction::Opcode::FNeg:
131 case Instruction::Opcode::Add:
132 case Instruction::Opcode::FAdd:
133 case Instruction::Opcode::Sub:
134 case Instruction::Opcode::FSub:
135 case Instruction::Opcode::Mul:
136 case Instruction::Opcode::FMul:
137 case Instruction::Opcode::FRem:
138 case Instruction::Opcode::UDiv:
139 case Instruction::Opcode::SDiv:
140 case Instruction::Opcode::FDiv:
141 case Instruction::Opcode::URem:
142 case Instruction::Opcode::SRem:
143 case Instruction::Opcode::Shl:
144 case Instruction::Opcode::LShr:
145 case Instruction::Opcode::AShr:
146 case Instruction::Opcode::And:
147 case Instruction::Opcode::Or:
148 case Instruction::Opcode::Xor:
149 return std::nullopt;
150 case Instruction::Opcode::Load:
151 if (VecUtils::areConsecutive<LoadInst>(Bndl, SE, DL))
152 return std::nullopt;
154 case Instruction::Opcode::Store:
155 if (VecUtils::areConsecutive<StoreInst>(Bndl, SE, DL))
156 return std::nullopt;
158 case Instruction::Opcode::PHI:
160 case Instruction::Opcode::Opaque:
162 case Instruction::Opcode::UncondBr:
163 case Instruction::Opcode::CondBr:
164 case Instruction::Opcode::Ret:
165 case Instruction::Opcode::AddrSpaceCast:
166 case Instruction::Opcode::InsertElement:
167 case Instruction::Opcode::InsertValue:
168 case Instruction::Opcode::ExtractElement:
169 case Instruction::Opcode::ExtractValue:
170 case Instruction::Opcode::ShuffleVector:
171 case Instruction::Opcode::Call:
172 case Instruction::Opcode::GetElementPtr:
173 case Instruction::Opcode::Switch:
174 case Instruction::Opcode::Pack:
176 case Instruction::Opcode::VAArg:
177 case Instruction::Opcode::Freeze:
178 case Instruction::Opcode::Fence:
179 case Instruction::Opcode::Invoke:
180 case Instruction::Opcode::CallBr:
181 case Instruction::Opcode::LandingPad:
182 case Instruction::Opcode::CatchPad:
183 case Instruction::Opcode::CleanupPad:
184 case Instruction::Opcode::CatchRet:
185 case Instruction::Opcode::CleanupRet:
186 case Instruction::Opcode::Resume:
187 case Instruction::Opcode::CatchSwitch:
188 case Instruction::Opcode::AtomicRMW:
189 case Instruction::Opcode::AtomicCmpXchg:
190 case Instruction::Opcode::Alloca:
191 case Instruction::Opcode::Unreachable:
193 }
194
195 return std::nullopt;
196}
197
199LegalityAnalysis::getHowToCollectValues(BndlRef<Value *> Bndl) const {
201 Vec.reserve(Bndl.size());
202 for (auto [Elm, V] : enumerate(Bndl)) {
203 if (auto *VecOp = IMaps.getVectorForOrig(V)) {
204 // If there is a vector containing `V`, then get the lane it came from.
205 std::optional<int> ExtractIdxOpt = IMaps.getOrigLane(VecOp, V);
206 // This could be a vector, like <2 x float> in which case the mask needs
207 // to enumerate all lanes.
208 for (unsigned Ln = 0, Lanes = VecUtils::getNumLanes(V); Ln != Lanes; ++Ln)
209 Vec.emplace_back(VecOp, ExtractIdxOpt ? *ExtractIdxOpt + Ln : -1);
210 } else {
211 Vec.emplace_back(V);
212 }
213 }
214 return CollectDescr(std::move(Vec));
215}
216
218 Value *V0 = Values[0];
219 if (!isa<LoadInst>(V0) && !isa<StoreInst>(V0))
220 return true;
222 // If the target is not set, just return true. This helps simplify
223 // target-independent lit tests.
225 return true;
226 Align Alignment = getLoadStoreAlignment(I0);
227 unsigned VecSizeBits =
229 unsigned AS = getLoadStoreAddressSpace(I0);
230 unsigned Fast = 0;
232 TTI, I0->getContext(), VecSizeBits, AS, Alignment, &Fast);
233 return Supported;
234}
235
237 bool SkipScheduling) {
238 // If Bndl contains values other than instructions, we need to Pack.
239 if (any_of(Bndl, [](auto *V) { return !isa<Instruction>(V); }))
241 // Pack if not in the same BB.
244 // Pack if instructions repeat, i.e., require some sort of broadcast.
247 // Check if the target supports the alignment of the generated vector.
248 if (!isAlignmentSupported(Bndl))
250
251 auto CollectDescrs = getHowToCollectValues(Bndl);
252 if (CollectDescrs.hasVectorInputs()) {
253 if (auto ValueShuffleOpt = CollectDescrs.getSingleInput()) {
254 auto [Vec, Mask] = *ValueShuffleOpt;
255 if (Mask.isIdentity())
258 }
260 std::move(CollectDescrs));
261 }
262
263 if (auto ReasonOpt = notVectorizableBasedOnOpcodesAndTypes(Bndl))
264 return createLegalityResult<Pack>(*ReasonOpt);
265
266 if (!SkipScheduling) {
267 // TODO: Try to remove the IBndl vector.
269 IBndl.reserve(Bndl.size());
270 for (auto *V : Bndl)
272 if (!Sched.trySchedule(IBndl))
274 }
275
277}
278
280 Sched.clear();
281 IMaps.clear();
282}
283} // namespace llvm::sandboxir
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
Module * getParent()
Get the module that this global value is contained inside of...
const Triple & getTargetTriple() const
Get the target triple which is a string describing the target host.
Definition Module.h:328
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool empty() const
Whether the triple is empty / default constructed.
Definition Triple.h:584
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
An ArrayRef of Values or Instructions that we can print/dump for debugging.
Definition VecUtils.h:39
Describes how to collect the values needed by each lane.
Definition Legality.h:256
A sandboxir::User with operands, opcode and linked with previous/next instructions in an instruction ...
Definition Instruction.h:43
LLVM_ABI BasicBlock * getParent() const
\Returns the BasicBlock containing this Instruction, or null if it is detached.
LLVM_ABI const LegalityResult & canVectorize(BndlRef< Value * > Bndl, bool SkipScheduling=false)
Checks if it's legal to vectorize the instructions in Bndl.
Definition Legality.cpp:236
LLVM_ABI bool isAlignmentSupported(ArrayRef< Value * > Values) const
Definition Legality.cpp:217
static bool areUnique(BndlRef< ValueT * > Values)
Definition Legality.h:364
static bool differentBlock(BndlRef< ValueT * > Instrs)
Definition Legality.h:356
ResultT & createLegalityResult(ArgsT &&...Args)
A LegalityResult factory.
Definition Legality.h:348
The legality outcome is represented by a class rather than an enum class because in some cases the le...
Definition Legality.h:162
LLVM_DUMP_METHOD void dump() const
Definition Legality.cpp:27
virtual void print(raw_ostream &OS) const
Definition Legality.h:177
void print(raw_ostream &OS) const
Definition Legality.h:74
LLVM_DUMP_METHOD void dump() const
Definition Legality.cpp:22
static bool TTIAllowsMisalignedMemoryAccesses(TargetTransformInfo &TTI, Context &Ctx, unsigned BitWidth, unsigned AddressSpace=0, Align Alignment=Align(1), unsigned *Fast=nullptr)
Definition Utils.h:137
static unsigned getNumBits(Type *Ty, const DataLayout &DL)
\Returns the number of bits of Ty.
Definition Utils.h:67
static Type * getExpectedType(const Value *V)
\Returns the expected type of Value V.
Definition Utils.h:33
A SandboxIR Value has users. This is the base class.
Definition Value.h:72
Context & getContext() const
Definition Value.h:285
static unsigned getNumLanes(Type *Ty)
\Returns the number of vector lanes of Ty or 1 if not a vector.
Definition VecUtils.h:134
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:101
static Type * getElementType(Type *Ty)
Returns Ty if scalar or its element type if vector.
Definition VecUtils.h:94
static BundleTy getOperand(BndlRef< Value * > Bndl, unsigned OpIdx)
Definition BundleVec.cpp:44
unsigned getLoadStoreAddressSpace(const Instruction *I)
A helper function that returns the address space of the pointer operand of load or store instruction.
Align getLoadStoreAlignment(const Value *I)
A helper function that returns the alignment of load or store instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
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
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
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
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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
@ Fast
Assign the register banks as fast as possible (default).
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39