26 cl::desc(
"Helps find bugs by verifying the IR whenever we "
27 "emit new instructions (*very* expensive)."));
31 std::numeric_limits<unsigned long>::max();
34 cl::desc(
"Vectorize if the invocation count is < than this. 0 "
35 "disables vectorization."));
38 std::numeric_limits<unsigned long>::max();
41 cl::desc(
"Vectorize up to this many bundles."));
47 for (
Value *BndlV : Bndl) {
65 return std::next(BotI->getIterator());
73 "Expect Instructions!");
74 auto &Ctx = Bndl[0]->getContext();
84 case Instruction::Opcode::ZExt:
85 case Instruction::Opcode::SExt:
86 case Instruction::Opcode::FPToUI:
87 case Instruction::Opcode::FPToSI:
88 case Instruction::Opcode::FPExt:
89 case Instruction::Opcode::PtrToInt:
90 case Instruction::Opcode::IntToPtr:
91 case Instruction::Opcode::SIToFP:
92 case Instruction::Opcode::UIToFP:
93 case Instruction::Opcode::Trunc:
94 case Instruction::Opcode::FPTrunc:
95 case Instruction::Opcode::BitCast: {
96 assert(Operands.
size() == 1u &&
"Casts are unary!");
100 case Instruction::Opcode::FCmp:
101 case Instruction::Opcode::ICmp: {
107 "Expected same predicate across bundle.");
111 case Instruction::Opcode::Select: {
115 case Instruction::Opcode::FNeg: {
117 auto OpC = UOp0->getOpcode();
119 WhereIt, Ctx,
"Vec");
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::UDiv:
128 case Instruction::Opcode::SDiv:
129 case Instruction::Opcode::FDiv:
130 case Instruction::Opcode::URem:
131 case Instruction::Opcode::SRem:
132 case Instruction::Opcode::FRem:
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 auto *
LHS = Operands[0];
141 auto *
RHS = Operands[1];
143 BinOp0->getOpcode(),
LHS,
RHS, BinOp0, WhereIt, Ctx,
"Vec");
145 case Instruction::Opcode::Load: {
147 Value *Ptr = Ld0->getPointerOperand();
151 case Instruction::Opcode::Store: {
153 Value *Val = Operands[0];
154 Value *Ptr = Operands[1];
157 case Instruction::Opcode::UncondBr:
158 case Instruction::Opcode::CondBr:
159 case Instruction::Opcode::Ret:
160 case Instruction::Opcode::PHI:
161 case Instruction::Opcode::AddrSpaceCast:
162 case Instruction::Opcode::Call:
163 case Instruction::Opcode::GetElementPtr:
174 auto *NewI = CreateVectorInstr(Bndl, Operands);
179void BundleVec::tryEraseDeadInstrs() {
180 DenseMap<BasicBlock *, SmallVector<Instruction *>> SortedDeadInstrCandidates;
182 for (
auto *DeadI : DeadInstrCandidates)
183 SortedDeadInstrCandidates[DeadI->getParent()].push_back(DeadI);
184 for (
auto &Pair : SortedDeadInstrCandidates)
187 for (
const auto &Pair : SortedDeadInstrCandidates) {
189 if (
I->hasNUses(0)) {
192 I->eraseFromParent();
196 DeadInstrCandidates.clear();
203 VecOp->getContext(),
"VShuf");
216 Context &Ctx = ToPack[0]->getContext();
218 unsigned InsertIdx = 0;
219 for (
Value *Elm : ToPack) {
222 if (Elm->getType()->isVectorTy()) {
225 for (
auto ExtrLane :
seq<int>(0, NumElms)) {
238 LastInsert, ExtrI, InsertLaneC, WhereIt, Ctx,
"VPack");
239 LastInsert = InsertI;
249 WhereIt, Ctx,
"Pack");
251 WhereIt = std::next(NewI->getIterator());
258 for (
Value *V : Bndl)
263 case Instruction::Opcode::Load: {
267 DeadInstrCandidates.insert(Ptr);
270 case Instruction::Opcode::Store: {
274 DeadInstrCandidates.insert(Ptr);
289 const auto &LegalityRes = StopForDebug ? Legality.getForcedPackForDebugging()
290 : Legality.canVectorize(Bndl);
300 auto ActionPtr = std::make_unique<Action>(&LegalityRes, Bndl,
302 Action *Action = ActionPtr.get();
303 IMaps->registerVector(Bndl, Action);
304 Actions.push_back(std::move(ActionPtr));
309 SmallPtrSet<Instruction *, 4> Claimed;
310 for (
const auto &NextUserBndl :
312 vectorizeRec(NextUserBndl, Bndl,
Depth + 1, Legality);
319 std::make_unique<Action>(&LegalityRes, Bndl, UserBndl,
Depth);
321 switch (LegalityRes.getSubclassID()) {
324 switch (
I->getOpcode()) {
325 case Instruction::Opcode::Load:
327 case Instruction::Opcode::Store: {
331 Operands.push_back(OpA);
339 Operands.push_back(OpA);
344 IMaps->registerVector(Bndl, ActionPtr.get());
354 ActionPtr->Operands = std::move(Operands);
355 auto *Action = ActionPtr.get();
356 Actions.push_back(std::move(ActionPtr));
361void BundleVec::ActionsVector::print(raw_ostream &OS)
const {
362 for (
auto [Idx, Action] :
enumerate(Actions)) {
367void BundleVec::ActionsVector::dump()
const {
print(
dbgs()); }
375 WhereIt = std::next(VecI->getIterator());
382 "A widened Bndl should contain instrs!");
397 auto IsExternal = [
this](
const Use &
U) {
398 return !IMaps->isVectorized(
U.getUser());
401 if (
none_of(Elm->uses(), IsExternal))
404 Elm->replaceUsesWithIf(UnpackV, IsExternal);
408Value *BundleVec::emitVectors() {
409 Value *NewVec =
nullptr;
410 for (
const auto &ActionPtr : Actions) {
413 const LegalityResult &LegalityRes = *ActionPtr->LegalityRes;
414 unsigned Depth = ActionPtr->Depth;
415 auto *UserBB = !UserBndl.empty()
419 switch (LegalityRes.getSubclassID()) {
422 SmallVector<Value *, 2> VecOperands;
424 switch (
I->getOpcode()) {
425 case Instruction::Opcode::Load:
428 case Instruction::Opcode::Store:
429 VecOperands.push_back(ActionPtr->Operands[0]->Vec);
433 for (Action *OpA : ActionPtr->Operands)
434 VecOperands.push_back(OpA->Vec);
438 switch (
I->getOpcode()) {
439 case Instruction::Opcode::Load:
442 case Instruction::Opcode::Store: {
444 if (Action *OpA = IMaps->getVectorForOrig(OpBndl[0]))
445 VecOperands.push_back(OpA->Vec);
447 VecOperands.push_back(createPack(OpBndl, UserBB));
454 if (Action *OpA = IMaps->getVectorForOrig(OpBndl[0]))
455 VecOperands.push_back(OpA->Vec);
457 VecOperands.push_back(createPack(OpBndl, UserBB));
462 NewVec = createVectorInstr(ActionPtr->Bndl, VecOperands);
465 if (NewVec !=
nullptr)
466 collectPotentiallyDeadInstrs(Bndl);
469 emitUnpacksForExternalUses(ActionPtr->Bndl, NewVec);
478 const ShuffleMask &
Mask =
480 NewVec = createShuffle(VecOp, Mask, UserBB);
481 assert(NewVec->getType() == VecOp->getType() &&
482 "Expected same type! Bad mask ?");
491 SmallVector<Value *, 4> DescrInstrs;
492 for (
const auto &ElmDescr : Descr.getDescrs()) {
493 auto *
V = ElmDescr.needsExtract() ? ElmDescr.getValue()->Vec
494 : ElmDescr.getScalar();
496 DescrInstrs.push_back(
I);
502 Context &Ctx = LastV->getContext();
504 for (
const auto &ElmDescr : Descr.getDescrs()) {
505 Value *VecOp =
nullptr;
506 Value *ValueToInsert;
507 if (ElmDescr.needsExtract()) {
508 VecOp = ElmDescr.getValue()->Vec;
512 VecOp, IdxC, WhereIt, VecOp->getContext(),
"VExt");
514 ValueToInsert = ElmDescr.getScalar();
517 if (NumLanesToInsert == 1) {
522 WhereIt, Ctx,
"VIns");
531 for (
unsigned LnCnt = 0; LnCnt != NumLanesToInsert; ++LnCnt) {
534 WhereIt, Ctx,
"VExt");
535 unsigned InsLane = Lane + LnCnt;
541 Lane += NumLanesToInsert;
550 NewVec = createPack(Bndl, UserBB);
554 if (NewVec !=
nullptr) {
556 ActionPtr->Vec = NewVec;
574 LegalityAnalysis &Legality) {
578 DeadInstrCandidates.clear();
582 vectorizeRec(Bndl, {}, 0, Legality);
584 <<
"Vec: Vectorization Actions:\n";
587 tryEraseDeadInstrs();
592 const auto &SeedSlice = Rgn.
getAux();
593 assert(SeedSlice.size() >= 2 &&
"Bad slice!");
594 Function &
F = *SeedSlice[0]->getParent()->getParent();
595 IMaps = std::make_unique<InstrMaps>();
597 F.getParent()->getDataLayout(),
F.getContext(),
605 return tryVectorize(SeedSliceVals, Legality);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_UNLIKELY(EXPR)
MachineInstr unsigned OpIdx
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
iterator begin()
Instruction iterator methods.
InstListType::iterator iterator
Instruction iterators...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM Value Representation.
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 Constant * 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="")
virtual void print(raw_ostream &OS) const
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
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 IntegerType * 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 Value * unpack(Value *FromVec, Type *ExtrTy, unsigned Lane, BasicBlock::iterator WhereIt)
Emits the necessary instruction sequence to extract element of type ExtrTy at Lane from FromVec.
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 auto enumerateLanes(const ValueContainerT &Range)
Helper for creating LaneValueEnumerator ranges.
static Type * getElementType(Type *Ty)
Returns Ty if scalar or its element type if vector.
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.
#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.
initializer< Ty > init(const Ty &Val)
NodeAddr< UseNode * > Use
LLVM_ABI Function * getParent() const
StringLiteral schedDirectionToStr(SchedDirection Dir)
@ DiamondReuseWithShuffle
BasicBlock(llvm::BasicBlock *BB, Context &SBCtx)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
SmallVector< Value *, 4 > BundleTy
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 BundleTy 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.
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,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
static constexpr unsigned long StopBundleDisabled
static cl::opt< unsigned long > StopBundle("sbvec-stop-bndl", cl::init(StopBundleDisabled), cl::Hidden, cl::desc("Vectorize up to this many bundles."))
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
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...
ArrayRef(const T &OneElt) -> ArrayRef< T >
static constexpr unsigned long StopAtDisabled
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
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)."))