24 cl::desc(
"Helps find bugs by verifying the IR whenever we "
25 "emit new instructions (*very* expensive)."));
29 std::numeric_limits<unsigned long>::max();
32 cl::desc(
"Vectorize if the invocation count is < than this. 0 "
33 "disables vectorization."));
36 std::numeric_limits<unsigned long>::max();
39 cl::desc(
"Vectorize up to this many bundles."));
46 for (
Value *BndlV : Bndl) {
47 auto *BndlI = cast<Instruction>(BndlV);
64 return std::next(BotI->getIterator());
71 assert(
all_of(Bndl, [](
auto *V) {
return isa<Instruction>(V); }) &&
72 "Expect Instructions!");
73 auto &Ctx = Bndl[0]->getContext();
79 Bndl, cast<Instruction>(Bndl[0])->
getParent());
81 auto Opcode = cast<Instruction>(Bndl[0])->getOpcode();
83 case Instruction::Opcode::ZExt:
84 case Instruction::Opcode::SExt:
85 case Instruction::Opcode::FPToUI:
86 case Instruction::Opcode::FPToSI:
87 case Instruction::Opcode::FPExt:
88 case Instruction::Opcode::PtrToInt:
89 case Instruction::Opcode::IntToPtr:
90 case Instruction::Opcode::SIToFP:
91 case Instruction::Opcode::UIToFP:
92 case Instruction::Opcode::Trunc:
93 case Instruction::Opcode::FPTrunc:
94 case Instruction::Opcode::BitCast: {
99 case Instruction::Opcode::FCmp:
100 case Instruction::Opcode::ICmp: {
101 auto Pred = cast<CmpInst>(Bndl[0])->getPredicate();
104 return cast<CmpInst>(SBV)->getPredicate() == Pred;
106 "Expected same predicate across bundle.");
110 case Instruction::Opcode::Select: {
114 case Instruction::Opcode::FNeg: {
115 auto *UOp0 = cast<UnaryOperator>(Bndl[0]);
116 auto OpC = UOp0->getOpcode();
118 WhereIt, Ctx,
"Vec");
120 case Instruction::Opcode::Add:
121 case Instruction::Opcode::FAdd:
122 case Instruction::Opcode::Sub:
123 case Instruction::Opcode::FSub:
124 case Instruction::Opcode::Mul:
125 case Instruction::Opcode::FMul:
126 case Instruction::Opcode::UDiv:
127 case Instruction::Opcode::SDiv:
128 case Instruction::Opcode::FDiv:
129 case Instruction::Opcode::URem:
130 case Instruction::Opcode::SRem:
131 case Instruction::Opcode::FRem:
132 case Instruction::Opcode::Shl:
133 case Instruction::Opcode::LShr:
134 case Instruction::Opcode::AShr:
135 case Instruction::Opcode::And:
136 case Instruction::Opcode::Or:
137 case Instruction::Opcode::Xor: {
138 auto *BinOp0 = cast<BinaryOperator>(Bndl[0]);
142 BinOp0->getOpcode(),
LHS,
RHS, BinOp0, WhereIt, Ctx,
"Vec");
144 case Instruction::Opcode::Load: {
145 auto *Ld0 = cast<LoadInst>(Bndl[0]);
146 Value *
Ptr = Ld0->getPointerOperand();
150 case Instruction::Opcode::Store: {
151 auto Align = cast<StoreInst>(Bndl[0])->getAlign();
156 case Instruction::Opcode::Br:
157 case Instruction::Opcode::Ret:
158 case Instruction::Opcode::PHI:
159 case Instruction::Opcode::AddrSpaceCast:
160 case Instruction::Opcode::Call:
161 case Instruction::Opcode::GetElementPtr:
172 auto *NewI = CreateVectorInstr(Bndl,
Operands);
177void BottomUpVec::tryEraseDeadInstrs() {
178 DenseMap<BasicBlock *, SmallVector<Instruction *>> SortedDeadInstrCandidates;
180 for (
auto *DeadI : DeadInstrCandidates)
181 SortedDeadInstrCandidates[DeadI->getParent()].push_back(DeadI);
182 for (
auto &Pair : SortedDeadInstrCandidates)
184 [](Instruction *I1, Instruction *I2) { return I1->comesBefore(I2); });
185 for (
const auto &Pair : SortedDeadInstrCandidates) {
186 for (Instruction *
I :
reverse(Pair.second)) {
187 if (
I->hasNUses(0)) {
190 I->eraseFromParent();
194 DeadInstrCandidates.clear();
197Value *BottomUpVec::createShuffle(Value *VecOp,
const ShuffleMask &Mask,
198 BasicBlock *UserBB) {
201 VecOp->getContext(),
"VShuf");
204Value *BottomUpVec::createPack(ArrayRef<Value *> ToPack, BasicBlock *UserBB) {
214 Context &Ctx = ToPack[0]->getContext();
216 unsigned InsertIdx = 0;
217 for (Value *Elm : ToPack) {
220 if (Elm->getType()->isVectorTy()) {
222 cast<FixedVectorType>(Elm->getType())->getNumElements();
223 for (
auto ExtrLane : seq<int>(0, NumElms)) {
230 if (!isa<Constant>(ExtrI))
231 WhereIt = std::next(cast<Instruction>(ExtrI)->getIterator());
236 LastInsert, ExtrI, InsertLaneC, WhereIt, Ctx,
"VPack");
237 LastInsert = InsertI;
238 if (!isa<Constant>(InsertI))
239 WhereIt = std::next(cast<Instruction>(LastInsert)->getIterator());
247 WhereIt, Ctx,
"Pack");
248 if (
auto *NewI = dyn_cast<Instruction>(LastInsert))
249 WhereIt = std::next(NewI->getIterator());
255void BottomUpVec::collectPotentiallyDeadInstrs(ArrayRef<Value *> Bndl) {
256 for (Value *V : Bndl)
257 DeadInstrCandidates.insert(cast<Instruction>(V));
259 auto Opcode = cast<Instruction>(Bndl[0])->getOpcode();
261 case Instruction::Opcode::Load: {
265 DeadInstrCandidates.insert(
Ptr);
268 case Instruction::Opcode::Store: {
272 DeadInstrCandidates.insert(
Ptr);
280Action *BottomUpVec::vectorizeRec(ArrayRef<Value *> Bndl,
281 ArrayRef<Value *> UserBndl,
unsigned Depth,
282 LegalityAnalysis &Legality) {
287 const auto &LegalityRes = StopForDebug ? Legality.getForcedPackForDebugging()
288 : Legality.canVectorize(Bndl);
291 std::make_unique<Action>(&LegalityRes, Bndl, UserBndl,
Depth);
293 switch (LegalityRes.getSubclassID()) {
295 auto *
I = cast<Instruction>(Bndl[0]);
296 switch (
I->getOpcode()) {
297 case Instruction::Opcode::Load:
299 case Instruction::Opcode::Store: {
308 for (
auto OpIdx : seq<unsigned>(
I->getNumOperands())) {
316 IMaps->registerVector(Bndl, ActionPtr.get());
326 ActionPtr->Operands = std::move(
Operands);
327 auto *Action = ActionPtr.get();
328 Actions.push_back(std::move(ActionPtr));
333void BottomUpVec::ActionsVector::print(raw_ostream &
OS)
const {
339void BottomUpVec::ActionsVector::dump()
const {
print(
dbgs()); }
342Value *BottomUpVec::emitVectors() {
343 Value *NewVec =
nullptr;
344 for (
const auto &ActionPtr : Actions) {
345 ArrayRef<Value *> Bndl = ActionPtr->Bndl;
346 ArrayRef<Value *> UserBndl = ActionPtr->UserBndl;
347 const LegalityResult &LegalityRes = *ActionPtr->LegalityRes;
348 unsigned Depth = ActionPtr->Depth;
349 auto *UserBB = !UserBndl.empty()
350 ? cast<Instruction>(UserBndl.front())->getParent()
351 : cast<Instruction>(Bndl[0])->getParent();
353 switch (LegalityRes.getSubclassID()) {
355 auto *
I = cast<Instruction>(Bndl[0]);
356 SmallVector<Value *, 2> VecOperands;
357 switch (
I->getOpcode()) {
358 case Instruction::Opcode::Load:
361 case Instruction::Opcode::Store: {
362 VecOperands.push_back(ActionPtr->Operands[0]->Vec);
368 for (Action *OpA : ActionPtr->Operands) {
369 auto *VecOp = OpA->Vec;
370 VecOperands.push_back(VecOp);
374 NewVec = createVectorInstr(ActionPtr->Bndl, VecOperands);
377 if (NewVec !=
nullptr)
378 collectPotentiallyDeadInstrs(Bndl);
382 NewVec = cast<DiamondReuse>(LegalityRes).getVector()->Vec;
386 auto *VecOp = cast<DiamondReuseWithShuffle>(LegalityRes).getVector()->Vec;
387 const ShuffleMask &
Mask =
388 cast<DiamondReuseWithShuffle>(LegalityRes).getMask();
389 NewVec = createShuffle(VecOp, Mask, UserBB);
390 assert(NewVec->getType() == VecOp->getType() &&
391 "Expected same type! Bad mask ?");
396 cast<DiamondReuseMultiInput>(LegalityRes).getCollectDescr();
400 SmallVector<Value *, 4> DescrInstrs;
401 for (
const auto &ElmDescr : Descr.getDescrs()) {
402 auto *
V = ElmDescr.needsExtract() ? ElmDescr.getValue()->Vec
403 : ElmDescr.getScalar();
404 if (
auto *
I = dyn_cast<Instruction>(V))
405 DescrInstrs.push_back(
I);
411 Context &Ctx = LastV->getContext();
413 for (
const auto &ElmDescr : Descr.getDescrs()) {
414 Value *VecOp =
nullptr;
415 Value *ValueToInsert;
416 if (ElmDescr.needsExtract()) {
417 VecOp = ElmDescr.getValue()->Vec;
421 VecOp, IdxC, WhereIt, VecOp->getContext(),
"VExt");
423 ValueToInsert = ElmDescr.getScalar();
426 if (NumLanesToInsert == 1) {
431 WhereIt, Ctx,
"VIns");
440 for (
unsigned LnCnt = 0; LnCnt != NumLanesToInsert; ++LnCnt) {
443 WhereIt, Ctx,
"VExt");
444 unsigned InsLane = Lane + LnCnt;
450 Lane += NumLanesToInsert;
459 NewVec = createPack(Bndl, UserBB);
463 if (NewVec !=
nullptr) {
465 ActionPtr->Vec = NewVec;
471 Instruction *I0 = isa<Instruction>(Bndl[0])
472 ? cast<Instruction>(Bndl[0])
473 :
cast<Instruction>(UserBndl[0]);
482bool BottomUpVec::tryVectorize(ArrayRef<Value *> Bndl,
483 LegalityAnalysis &Legality) {
488 DeadInstrCandidates.clear();
492 vectorizeRec(Bndl, {}, 0, Legality);
496 tryEraseDeadInstrs();
501 const auto &SeedSlice = Rgn.
getAux();
502 assert(SeedSlice.size() >= 2 &&
"Bad slice!");
503 Function &
F = *SeedSlice[0]->getParent()->getParent();
504 IMaps = std::make_unique<InstrMaps>();
506 F.getParent()->getDataLayout(),
F.getContext(),
514 return tryVectorize(SeedSliceVals, Legality);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_UNLIKELY(EXPR)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
mir Rename Register Operands
MachineInstr unsigned OpIdx
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM Value Representation.
Iterator for Instructions in a `BasicBlock.
Contains a list of sandboxir::Instruction's.
LLVM_ABI iterator begin() const
static LLVM_ABI Value * createWithCopiedFlags(Instruction::Opcode Op, Value *LHS, Value *RHS, Value *CopyFrom, InsertPosition Pos, Context &Ctx, const Twine &Name="")
bool runOnRegion(Region &Rgn, const Analyses &A) final
\Returns true if it modifies R.
static LLVM_ABI Value * create(Type *DestTy, Opcode Op, Value *Operand, InsertPosition Pos, Context &Ctx, const Twine &Name="")
static LLVM_ABI Value * create(Predicate Pred, Value *S1, Value *S2, InsertPosition Pos, Context &Ctx, const Twine &Name="")
static LLVM_ABI ConstantInt * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
static LLVM_ABI ConstantInt * getSigned(IntegerType *Ty, int64_t V)
Return a ConstantInt with the specified value for the specified type.
static LLVM_ABI Value * create(Value *Vec, Value *Idx, InsertPosition Pos, Context &Ctx, const Twine &Name="")
static LLVM_ABI Value * create(Value *Vec, Value *NewElt, Value *Idx, InsertPosition Pos, Context &Ctx, const Twine &Name="")
LLVM_ABI BBIterator getIterator() const
\Returns a BasicBlock::iterator for this Instruction.
Performs the legality analysis and returns a LegalityResult object.
static LLVM_ABI LoadInst * create(Type *Ty, Value *Ptr, MaybeAlign Align, InsertPosition Pos, bool IsVolatile, Context &Ctx, const Twine &Name="")
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
The main job of the Region is to point to new instructions generated by vectorization passes.
const SmallVector< Instruction * > & getAux() const
\Returns the auxiliary vector.
static LLVM_ABI Value * create(Value *Cond, Value *True, Value *False, InsertPosition Pos, Context &Ctx, const Twine &Name="")
static LLVM_ABI Value * create(Value *V1, Value *V2, Value *Mask, InsertPosition Pos, Context &Ctx, const Twine &Name="")
static LLVM_ABI StoreInst * create(Value *V, Value *Ptr, MaybeAlign Align, InsertPosition Pos, bool IsVolatile, Context &Ctx)
static LLVM_ABI Type * getInt32Ty(Context &Ctx)
static LLVM_ABI Value * createWithCopiedFlags(Instruction::Opcode Op, Value *OpV, Value *CopyFrom, InsertPosition Pos, Context &Ctx, const Twine &Name="")
static Type * getExpectedType(const Value *V)
\Returns the expected type of Value V.
static bool verifyFunction(const Function *F, raw_ostream &OS)
Equivalent to llvm::verifyFunction().
A SandboxIR Value has users. This is the base class.
static Instruction * getLowest(ArrayRef< Instruction * > Instrs)
\Returns the instruction in Instrs that is lowest in the BB.
static Type * getCommonScalarType(ArrayRef< Value * > Bndl)
Similar to tryGetCommonScalarType() but will assert that there is a common type.
static Instruction * getLastPHIOrSelf(Instruction *I)
If I is not a PHI it returns it.
static unsigned getNumLanes(Type *Ty)
\Returns the number of vector lanes of Ty or 1 if not a vector.
static LLVM_DUMP_METHOD void dump(ArrayRef< Value * > Bndl)
Helper dump function for debugging.
static Type * getWideType(Type *ElemTy, unsigned NumElts)
\Returns <NumElts x ElemTy>.
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.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
template class LLVM_TEMPLATE_ABI opt< bool >
initializer< Ty > init(const Ty &Val)
Type
MessagePack types as defined in the standard, with the exception of Integer being divided into a sign...
@ DiamondReuse
Vectorize by combining scalars to a vector.
@ DiamondReuseWithShuffle
Don't generate new code, reuse existing vector.
@ Widen
Collect scalar values.
@ DiamondReuseMultiInput
Reuse the existing vector but add a shuffle.
static BasicBlock::iterator getInsertPointAfterInstrs(ArrayRef< Value * > Vals, BasicBlock *BB)
\Returns the BB iterator after the lowest instruction in Vals, or the top of BB if no instruction fou...
static SmallVector< Value *, 4 > getOperand(ArrayRef< Value * > Bndl, unsigned OpIdx)
This is an optimization pass for GlobalISel generic memory operations.
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.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
static cl::opt< unsigned long > StopAt("sbvec-stop-at", cl::init(StopAtDisabled), cl::Hidden, cl::desc("Vectorize if the invocation count is < than this. 0 " "disables vectorization."))
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
static cl::opt< unsigned long > StopBundle("sbvec-stop-bndl", cl::init(StopBundleDisabled), cl::Hidden, cl::desc("Vectorize up to this many bundles."))
static constexpr const unsigned long StopBundleDisabled
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)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static constexpr const unsigned long StopAtDisabled
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
static cl::opt< bool > AlwaysVerify("sbvec-always-verify", cl::init(false), cl::Hidden, cl::desc("Helps find bugs by verifying the IR whenever we " "emit new instructions (*very* expensive)."))