LLVM 20.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
14#include "llvm/Support/Debug.h"
16
17namespace llvm::sandboxir {
18
19#define DEBUG_TYPE "SBVec:Legality"
20
21#ifndef NDEBUG
23 print(dbgs());
24 dbgs() << "\n";
25}
26#endif // NDEBUG
27
28std::optional<ResultReason>
29LegalityAnalysis::notVectorizableBasedOnOpcodesAndTypes(
30 ArrayRef<Value *> Bndl) {
31 auto *I0 = cast<Instruction>(Bndl[0]);
32 auto Opcode = I0->getOpcode();
33 // If they have different opcodes, then we cannot form a vector (for now).
34 if (any_of(drop_begin(Bndl), [Opcode](Value *V) {
35 return cast<Instruction>(V)->getOpcode() != Opcode;
36 }))
38
39 // If not the same scalar type, Pack. This will accept scalars and vectors as
40 // long as the element type is the same.
42 if (any_of(drop_begin(Bndl), [ElmTy0](Value *V) {
44 }))
46
47 // TODO: Allow vectorization of instrs with different flags as long as we
48 // change them to the least common one.
49 // For now pack if differnt FastMathFlags.
50 if (isa<FPMathOperator>(I0)) {
51 FastMathFlags FMF0 = cast<Instruction>(Bndl[0])->getFastMathFlags();
52 if (any_of(drop_begin(Bndl), [FMF0](auto *V) {
53 return cast<Instruction>(V)->getFastMathFlags() != FMF0;
54 }))
56 }
57
58 // TODO: Allow vectorization by using common flags.
59 // For now Pack if they don't have the same wrap flags.
60 bool CanHaveWrapFlags =
61 isa<OverflowingBinaryOperator>(I0) || isa<TruncInst>(I0);
62 if (CanHaveWrapFlags) {
63 bool NUW0 = I0->hasNoUnsignedWrap();
64 bool NSW0 = I0->hasNoSignedWrap();
65 if (any_of(drop_begin(Bndl), [NUW0, NSW0](auto *V) {
66 return cast<Instruction>(V)->hasNoUnsignedWrap() != NUW0 ||
67 cast<Instruction>(V)->hasNoSignedWrap() != NSW0;
68 })) {
70 }
71 }
72
73 // Now we need to do further checks for specific opcodes.
74 switch (Opcode) {
75 case Instruction::Opcode::ZExt:
76 case Instruction::Opcode::SExt:
77 case Instruction::Opcode::FPToUI:
78 case Instruction::Opcode::FPToSI:
79 case Instruction::Opcode::FPExt:
80 case Instruction::Opcode::PtrToInt:
81 case Instruction::Opcode::IntToPtr:
82 case Instruction::Opcode::SIToFP:
83 case Instruction::Opcode::UIToFP:
84 case Instruction::Opcode::Trunc:
85 case Instruction::Opcode::FPTrunc:
86 case Instruction::Opcode::BitCast: {
87 // We have already checked that they are of the same opcode.
88 assert(all_of(Bndl,
89 [Opcode](Value *V) {
90 return cast<Instruction>(V)->getOpcode() == Opcode;
91 }) &&
92 "Different opcodes, should have early returned!");
93 // But for these opcodes we should also check the operand type.
94 Type *FromTy0 = Utils::getExpectedType(I0->getOperand(0));
95 if (any_of(drop_begin(Bndl), [FromTy0](Value *V) {
96 return Utils::getExpectedType(cast<User>(V)->getOperand(0)) !=
97 FromTy0;
98 }))
100 return std::nullopt;
101 }
102 case Instruction::Opcode::FCmp:
103 case Instruction::Opcode::ICmp: {
104 // We need the same predicate..
105 auto Pred0 = cast<CmpInst>(I0)->getPredicate();
106 bool Same = all_of(Bndl, [Pred0](Value *V) {
107 return cast<CmpInst>(V)->getPredicate() == Pred0;
108 });
109 if (Same)
110 return std::nullopt;
112 }
113 case Instruction::Opcode::Select:
114 case Instruction::Opcode::FNeg:
115 case Instruction::Opcode::Add:
116 case Instruction::Opcode::FAdd:
117 case Instruction::Opcode::Sub:
118 case Instruction::Opcode::FSub:
119 case Instruction::Opcode::Mul:
120 case Instruction::Opcode::FMul:
121 case Instruction::Opcode::FRem:
122 case Instruction::Opcode::UDiv:
123 case Instruction::Opcode::SDiv:
124 case Instruction::Opcode::FDiv:
125 case Instruction::Opcode::URem:
126 case Instruction::Opcode::SRem:
127 case Instruction::Opcode::Shl:
128 case Instruction::Opcode::LShr:
129 case Instruction::Opcode::AShr:
130 case Instruction::Opcode::And:
131 case Instruction::Opcode::Or:
132 case Instruction::Opcode::Xor:
133 return std::nullopt;
134 case Instruction::Opcode::Load:
135 if (VecUtils::areConsecutive<LoadInst>(Bndl, SE, DL))
136 return std::nullopt;
138 case Instruction::Opcode::Store:
139 if (VecUtils::areConsecutive<StoreInst>(Bndl, SE, DL))
140 return std::nullopt;
142 case Instruction::Opcode::PHI:
144 case Instruction::Opcode::Opaque:
146 case Instruction::Opcode::Br:
147 case Instruction::Opcode::Ret:
148 case Instruction::Opcode::AddrSpaceCast:
149 case Instruction::Opcode::InsertElement:
150 case Instruction::Opcode::InsertValue:
151 case Instruction::Opcode::ExtractElement:
152 case Instruction::Opcode::ExtractValue:
153 case Instruction::Opcode::ShuffleVector:
154 case Instruction::Opcode::Call:
155 case Instruction::Opcode::GetElementPtr:
156 case Instruction::Opcode::Switch:
158 case Instruction::Opcode::VAArg:
159 case Instruction::Opcode::Freeze:
160 case Instruction::Opcode::Fence:
161 case Instruction::Opcode::Invoke:
162 case Instruction::Opcode::CallBr:
163 case Instruction::Opcode::LandingPad:
164 case Instruction::Opcode::CatchPad:
165 case Instruction::Opcode::CleanupPad:
166 case Instruction::Opcode::CatchRet:
167 case Instruction::Opcode::CleanupRet:
168 case Instruction::Opcode::Resume:
169 case Instruction::Opcode::CatchSwitch:
170 case Instruction::Opcode::AtomicRMW:
171 case Instruction::Opcode::AtomicCmpXchg:
172 case Instruction::Opcode::Alloca:
173 case Instruction::Opcode::Unreachable:
175 }
176
177 return std::nullopt;
178}
179
180#ifndef NDEBUG
181static void dumpBndl(ArrayRef<Value *> Bndl) {
182 for (auto *V : Bndl)
183 dbgs() << *V << "\n";
184}
185#endif // NDEBUG
186
188 bool SkipScheduling) {
189 // If Bndl contains values other than instructions, we need to Pack.
190 if (any_of(Bndl, [](auto *V) { return !isa<Instruction>(V); })) {
191 LLVM_DEBUG(dbgs() << "Not vectorizing: Not Instructions:\n";
192 dumpBndl(Bndl););
193 return createLegalityResult<Pack>(ResultReason::NotInstructions);
194 }
195
196 if (auto ReasonOpt = notVectorizableBasedOnOpcodesAndTypes(Bndl))
197 return createLegalityResult<Pack>(*ReasonOpt);
198
199 // TODO: Check for existing vectors containing values in Bndl.
200
201 if (!SkipScheduling) {
202 // TODO: Try to remove the IBndl vector.
204 IBndl.reserve(Bndl.size());
205 for (auto *V : Bndl)
206 IBndl.push_back(cast<Instruction>(V));
207 if (!Sched.trySchedule(IBndl))
208 return createLegalityResult<Pack>(ResultReason::CantSchedule);
209 }
210
211 return createLegalityResult<Widen>();
212}
213} // namespace llvm::sandboxir
#define LLVM_DEBUG(...)
Definition: Debug.h:106
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
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:168
void reserve(size_type N)
Definition: SmallVector.h:663
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:74
const LegalityResult & canVectorize(ArrayRef< Value * > Bndl, bool SkipScheduling=false)
Checks if it's legal to vectorize the instructions in Bndl.
Definition: Legality.cpp:187
The legality outcome is represented by a class rather than an enum class because in some cases the le...
Definition: Legality.h:87
LLVM_DUMP_METHOD void dump() const
Definition: Legality.cpp:22
virtual void print(raw_ostream &OS) const
Definition: Legality.h:102
bool trySchedule(ArrayRef< Instruction * > Instrs)
Definition: Scheduler.cpp:187
static Type * getExpectedType(const Value *V)
\Returns the expected type of Value V.
Definition: Utils.h:30
A SandboxIR Value has users. This is the base class.
Definition: Value.h:63
static Type * getElementType(Type *Ty)
Returns Ty if scalar or its element type if vector.
Definition: VecUtils.h:32
Type
MessagePack types as defined in the standard, with the exception of Integer being divided into a sign...
Definition: MsgPackReader.h:53
static SmallVector< Value *, 4 > getOperand(ArrayRef< Value * > Bndl, unsigned OpIdx)
Definition: BottomUpVec.cpp:34
static void dumpBndl(ArrayRef< Value * > Bndl)
Definition: Legality.cpp:181
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition: STLExtras.h:329
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:1739
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:1746
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163