20#define DEBUG_TYPE "SBVec:Legality"
34std::optional<ResultReason>
35LegalityAnalysis::notVectorizableBasedOnOpcodesAndTypes(
37 auto *I0 = cast<Instruction>(Bndl[0]);
38 auto Opcode = I0->getOpcode();
41 return cast<Instruction>(V)->getOpcode() != Opcode;
56 if (isa<FPMathOperator>(I0)) {
57 FastMathFlags FMF0 = cast<Instruction>(Bndl[0])->getFastMathFlags();
59 return cast<Instruction>(V)->getFastMathFlags() != FMF0;
66 bool CanHaveWrapFlags =
67 isa<OverflowingBinaryOperator>(I0) || isa<TruncInst>(I0);
68 if (CanHaveWrapFlags) {
69 bool NUW0 = I0->hasNoUnsignedWrap();
70 bool NSW0 = I0->hasNoSignedWrap();
72 return cast<Instruction>(V)->hasNoUnsignedWrap() != NUW0 ||
73 cast<Instruction>(V)->hasNoSignedWrap() != NSW0;
81 case Instruction::Opcode::ZExt:
82 case Instruction::Opcode::SExt:
83 case Instruction::Opcode::FPToUI:
84 case Instruction::Opcode::FPToSI:
85 case Instruction::Opcode::FPExt:
86 case Instruction::Opcode::PtrToInt:
87 case Instruction::Opcode::IntToPtr:
88 case Instruction::Opcode::SIToFP:
89 case Instruction::Opcode::UIToFP:
90 case Instruction::Opcode::Trunc:
91 case Instruction::Opcode::FPTrunc:
92 case Instruction::Opcode::BitCast: {
96 return cast<Instruction>(V)->getOpcode() == Opcode;
98 "Different opcodes, should have early returned!");
108 case Instruction::Opcode::FCmp:
109 case Instruction::Opcode::ICmp: {
111 auto Pred0 = cast<CmpInst>(I0)->getPredicate();
113 return cast<CmpInst>(V)->getPredicate() == Pred0;
119 case Instruction::Opcode::Select:
120 case Instruction::Opcode::FNeg:
121 case Instruction::Opcode::Add:
122 case Instruction::Opcode::FAdd:
123 case Instruction::Opcode::Sub:
124 case Instruction::Opcode::FSub:
125 case Instruction::Opcode::Mul:
126 case Instruction::Opcode::FMul:
127 case Instruction::Opcode::FRem:
128 case Instruction::Opcode::UDiv:
129 case Instruction::Opcode::SDiv:
130 case Instruction::Opcode::FDiv:
131 case Instruction::Opcode::URem:
132 case Instruction::Opcode::SRem:
133 case Instruction::Opcode::Shl:
134 case Instruction::Opcode::LShr:
135 case Instruction::Opcode::AShr:
136 case Instruction::Opcode::And:
137 case Instruction::Opcode::Or:
138 case Instruction::Opcode::Xor:
140 case Instruction::Opcode::Load:
141 if (VecUtils::areConsecutive<LoadInst>(Bndl, SE, DL))
144 case Instruction::Opcode::Store:
145 if (VecUtils::areConsecutive<StoreInst>(Bndl, SE, DL))
148 case Instruction::Opcode::PHI:
150 case Instruction::Opcode::Opaque:
152 case Instruction::Opcode::Br:
153 case Instruction::Opcode::Ret:
154 case Instruction::Opcode::AddrSpaceCast:
155 case Instruction::Opcode::InsertElement:
156 case Instruction::Opcode::InsertValue:
157 case Instruction::Opcode::ExtractElement:
158 case Instruction::Opcode::ExtractValue:
159 case Instruction::Opcode::ShuffleVector:
160 case Instruction::Opcode::Call:
161 case Instruction::Opcode::GetElementPtr:
162 case Instruction::Opcode::Switch:
164 case Instruction::Opcode::VAArg:
165 case Instruction::Opcode::Freeze:
166 case Instruction::Opcode::Fence:
167 case Instruction::Opcode::Invoke:
168 case Instruction::Opcode::CallBr:
169 case Instruction::Opcode::LandingPad:
170 case Instruction::Opcode::CatchPad:
171 case Instruction::Opcode::CleanupPad:
172 case Instruction::Opcode::CatchRet:
173 case Instruction::Opcode::CleanupRet:
174 case Instruction::Opcode::Resume:
175 case Instruction::Opcode::CatchSwitch:
176 case Instruction::Opcode::AtomicRMW:
177 case Instruction::Opcode::AtomicCmpXchg:
178 case Instruction::Opcode::Alloca:
179 case Instruction::Opcode::Unreachable:
189 dbgs() << *V <<
"\n";
200 std::optional<int> ExtractIdxOpt = IMaps.
getOrigLane(VecOp, V);
201 Vec.
emplace_back(VecOp, ExtractIdxOpt ? *ExtractIdxOpt : -1);
206 return CollectDescr(std::move(Vec));
210 bool SkipScheduling) {
212 if (
any_of(Bndl, [](
auto *V) {
return !isa<Instruction>(V); })) {
218 auto CollectDescrs = getHowToCollectValues(Bndl);
219 if (CollectDescrs.hasVectorInputs()) {
220 if (
auto ValueShuffleOpt = CollectDescrs.getSingleInput()) {
221 auto [Vec, Mask] = *ValueShuffleOpt;
222 if (Mask.isIdentity())
223 return createLegalityResult<DiamondReuse>(Vec);
224 return createLegalityResult<DiamondReuseWithShuffle>(Vec, Mask);
229 if (
auto ReasonOpt = notVectorizableBasedOnOpcodesAndTypes(Bndl))
230 return createLegalityResult<Pack>(*ReasonOpt);
232 if (!SkipScheduling) {
242 return createLegalityResult<Widen>();
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
reference emplace_back(ArgTypes &&... Args)
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.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
Value * getVectorForOrig(Value *Orig) const
\Returns the vector value that we got from vectorizing Orig, or nullptr if not found.
std::optional< unsigned > getOrigLane(Value *Vec, Value *Orig) const
\Returns the lane of Orig before it got vectorized into Vec, or nullopt if not found.
const LegalityResult & canVectorize(ArrayRef< Value * > Bndl, bool SkipScheduling=false)
Checks if it's legal to vectorize the instructions in Bndl.
The legality outcome is represented by a class rather than an enum class because in some cases the le...
LLVM_DUMP_METHOD void dump() const
virtual void print(raw_ostream &OS) const
bool trySchedule(ArrayRef< Instruction * > Instrs)
Tries to build a schedule that includes all of Instrs scheduled at the same scheduling cycle.
void clear()
Clear the scheduler's state, including the DAG.
void print(raw_ostream &OS) const
LLVM_DUMP_METHOD void dump() const
static Type * getExpectedType(const Value *V)
\Returns the expected type of Value V.
A SandboxIR Value has users. This is the base class.
static Type * getElementType(Type *Ty)
Returns Ty if scalar or its element type if vector.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Type
MessagePack types as defined in the standard, with the exception of Integer being divided into a sign...
static SmallVector< Value *, 4 > getOperand(ArrayRef< Value * > Bndl, unsigned OpIdx)
static void dumpBndl(ArrayRef< Value * > Bndl)
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.