LLVM 24.0.0git
BundleVec.cpp
Go to the documentation of this file.
1//===- BundleVec.cpp - A bundle-forming SLP-style vectorizer pass ---------===//
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
20
21namespace llvm {
22
23#ifndef NDEBUG
24static cl::opt<bool>
25 AlwaysVerify("sbvec-always-verify", cl::init(false), cl::Hidden,
26 cl::desc("Helps find bugs by verifying the IR whenever we "
27 "emit new instructions (*very* expensive)."));
28#endif // NDEBUG
29
30static constexpr unsigned long StopAtDisabled =
31 std::numeric_limits<unsigned long>::max();
34 cl::desc("Vectorize if the invocation count is < than this. 0 "
35 "disables vectorization."));
36
37static constexpr unsigned long StopBundleDisabled =
38 std::numeric_limits<unsigned long>::max();
41 cl::desc("Vectorize up to this many bundles."));
42
43namespace sandboxir {
44
46 BundleTy Operands;
47 for (Value *BndlV : Bndl) {
48 auto *BndlI = cast<Instruction>(BndlV);
49 Operands.push_back(BndlI->getOperand(OpIdx));
50 }
51 return Operands;
52}
53
54/// \Returns the BB iterator after the lowest instruction in \p Vals, or the top
55/// of BB if no instruction found in \p Vals.
57 BasicBlock *BB) {
58 auto *BotI = VecUtils::getLastPHIOrSelf(VecUtils::getLowest(Vals, BB));
59 if (BotI == nullptr)
60 // We are using BB->begin() (or after PHIs) as the fallback insert point.
61 return BB->empty()
62 ? BB->begin()
63 : std::next(
64 VecUtils::getLastPHIOrSelf(&*BB->begin())->getIterator());
65 return std::next(BotI->getIterator());
66}
67
68Value *BundleVec::createVectorInstr(ArrayRef<Value *> Bndl,
69 ArrayRef<Value *> Operands) {
70 auto CreateVectorInstr = [](ArrayRef<Value *> Bndl,
71 ArrayRef<Value *> Operands) -> Value * {
72 assert(all_of(Bndl, [](auto *V) { return isa<Instruction>(V); }) &&
73 "Expect Instructions!");
74 auto &Ctx = Bndl[0]->getContext();
75
76 Type *ScalarTy = VecUtils::getElementType(Utils::getExpectedType(Bndl[0]));
77 auto *VecTy = VecUtils::getWideType(ScalarTy, VecUtils::getNumLanes(Bndl));
78
80 Bndl, cast<Instruction>(Bndl[0])->getParent());
81
82 auto Opcode = cast<Instruction>(Bndl[0])->getOpcode();
83 switch (Opcode) {
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!");
97 return CastInst::create(VecTy, Opcode, Operands[0], WhereIt, Ctx,
98 "VCast");
99 }
100 case Instruction::Opcode::FCmp:
101 case Instruction::Opcode::ICmp: {
102 auto Pred = cast<CmpInst>(Bndl[0])->getPredicate();
104 [Pred](auto *SBV) {
105 return cast<CmpInst>(SBV)->getPredicate() == Pred;
106 }) &&
107 "Expected same predicate across bundle.");
108 return CmpInst::create(Pred, Operands[0], Operands[1], WhereIt, Ctx,
109 "VCmp");
110 }
111 case Instruction::Opcode::Select: {
112 return SelectInst::create(Operands[0], Operands[1], Operands[2], WhereIt,
113 Ctx, "Vec");
114 }
115 case Instruction::Opcode::FNeg: {
116 auto *UOp0 = cast<UnaryOperator>(Bndl[0]);
117 auto OpC = UOp0->getOpcode();
118 return UnaryOperator::createWithCopiedFlags(OpC, Operands[0], UOp0,
119 WhereIt, Ctx, "Vec");
120 }
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: {
139 auto *BinOp0 = cast<BinaryOperator>(Bndl[0]);
140 auto *LHS = Operands[0];
141 auto *RHS = Operands[1];
143 BinOp0->getOpcode(), LHS, RHS, BinOp0, WhereIt, Ctx, "Vec");
144 }
145 case Instruction::Opcode::Load: {
146 auto *Ld0 = cast<LoadInst>(Bndl[0]);
147 Value *Ptr = Ld0->getPointerOperand();
148 return LoadInst::create(VecTy, Ptr, Ld0->getAlign(), WhereIt, Ctx,
149 "VecL");
150 }
151 case Instruction::Opcode::Store: {
152 auto Align = cast<StoreInst>(Bndl[0])->getAlign();
153 Value *Val = Operands[0];
154 Value *Ptr = Operands[1];
155 return StoreInst::create(Val, Ptr, Align, WhereIt, Ctx);
156 }
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:
164 llvm_unreachable("Unimplemented");
165 break;
166 default:
167 llvm_unreachable("Unimplemented");
168 break;
169 }
170 llvm_unreachable("Missing switch case!");
171 // TODO: Propagate debug info.
172 };
173
174 auto *NewI = CreateVectorInstr(Bndl, Operands);
175 LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "New instr: " << *NewI << "\n");
176 return NewI;
177}
178
179void BundleVec::tryEraseDeadInstrs() {
180 DenseMap<BasicBlock *, SmallVector<Instruction *>> SortedDeadInstrCandidates;
181 // The dead instrs could span BBs, so we need to collect and sort them per BB.
182 for (auto *DeadI : DeadInstrCandidates)
183 SortedDeadInstrCandidates[DeadI->getParent()].push_back(DeadI);
184 for (auto &Pair : SortedDeadInstrCandidates)
185 sort(Pair.second,
186 [](Instruction *I1, Instruction *I2) { return I1->comesBefore(I2); });
187 for (const auto &Pair : SortedDeadInstrCandidates) {
188 for (Instruction *I : reverse(Pair.second)) {
189 if (I->hasNUses(0)) {
190 // Erase the dead instructions bottom-to-top.
191 LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Erase dead: " << *I << "\n");
192 I->eraseFromParent();
193 }
194 }
195 }
196 DeadInstrCandidates.clear();
197}
198
199Value *BundleVec::createShuffle(Value *VecOp, const ShuffleMask &Mask,
200 BasicBlock *UserBB) {
201 BasicBlock::iterator WhereIt = getInsertPointAfterInstrs({VecOp}, UserBB);
202 return ShuffleVectorInst::create(VecOp, VecOp, Mask, WhereIt,
203 VecOp->getContext(), "VShuf");
204}
205
206Value *BundleVec::createPack(ArrayRef<Value *> ToPack, BasicBlock *UserBB) {
207 BasicBlock::iterator WhereIt = getInsertPointAfterInstrs(ToPack, UserBB);
208
209 Type *ScalarTy = VecUtils::getCommonScalarType(ToPack);
210 unsigned Lanes = VecUtils::getNumLanes(ToPack);
211 Type *VecTy = VecUtils::getWideType(ScalarTy, Lanes);
212
213 // Create a series of pack instructions.
214 Value *LastInsert = PoisonValue::get(VecTy);
215
216 Context &Ctx = ToPack[0]->getContext();
217
218 unsigned InsertIdx = 0;
219 for (Value *Elm : ToPack) {
220 // An element can be either scalar or vector. We need to generate different
221 // IR for each case.
222 if (Elm->getType()->isVectorTy()) {
223 unsigned NumElms =
224 cast<FixedVectorType>(Elm->getType())->getNumElements();
225 for (auto ExtrLane : seq<int>(0, NumElms)) {
226 // We generate extract-insert pairs, for each lane in `Elm`.
227 Constant *ExtrLaneC =
229 // This may return a Constant if Elm is a Constant.
230 auto *ExtrI =
231 ExtractElementInst::create(Elm, ExtrLaneC, WhereIt, Ctx, "VPack");
232 if (!isa<Constant>(ExtrI))
233 WhereIt = std::next(cast<Instruction>(ExtrI)->getIterator());
234 Constant *InsertLaneC =
235 ConstantInt::getSigned(Type::getInt32Ty(Ctx), InsertIdx++);
236 // This may also return a Constant if ExtrI is a Constant.
237 auto *InsertI = InsertElementInst::create(
238 LastInsert, ExtrI, InsertLaneC, WhereIt, Ctx, "VPack");
239 LastInsert = InsertI;
240 if (!isa<Constant>(InsertI))
241 WhereIt = std::next(cast<Instruction>(LastInsert)->getIterator());
242 }
243 } else {
244 Constant *InsertLaneC =
245 ConstantInt::getSigned(Type::getInt32Ty(Ctx), InsertIdx++);
246 // This may be folded into a Constant if LastInsert is a Constant. In
247 // that case we only collect the last constant.
248 LastInsert = InsertElementInst::create(LastInsert, Elm, InsertLaneC,
249 WhereIt, Ctx, "Pack");
250 if (auto *NewI = dyn_cast<Instruction>(LastInsert))
251 WhereIt = std::next(NewI->getIterator());
252 }
253 }
254 return LastInsert;
255}
256
257void BundleVec::collectPotentiallyDeadInstrs(ArrayRef<Value *> Bndl) {
258 for (Value *V : Bndl)
259 DeadInstrCandidates.insert(cast<Instruction>(V));
260 // Also collect the GEPs of vectorized loads and stores.
261 auto Opcode = cast<Instruction>(Bndl[0])->getOpcode();
262 switch (Opcode) {
263 case Instruction::Opcode::Load: {
264 for (Value *V : drop_begin(Bndl))
265 if (auto *Ptr =
267 DeadInstrCandidates.insert(Ptr);
268 break;
269 }
270 case Instruction::Opcode::Store: {
271 for (Value *V : drop_begin(Bndl))
272 if (auto *Ptr =
274 DeadInstrCandidates.insert(Ptr);
275 break;
276 }
277 default:
278 break;
279 }
280}
281
282Action *BundleVec::vectorizeRec(ArrayRef<Value *> Bndl,
283 ArrayRef<Value *> UserBndl, unsigned Depth,
284 LegalityAnalysis &Legality) {
285 bool StopForDebug =
286 DebugBndlCnt++ >= StopBundle && StopBundle != StopBundleDisabled;
287 LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "canVectorize() Bundle:\n";
288 VecUtils::dump(Bndl));
289 const auto &LegalityRes = StopForDebug ? Legality.getForcedPackForDebugging()
290 : Legality.canVectorize(Bndl);
291 LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Legality: " << LegalityRes << "\n");
292
293 if (Dir == SchedDirection::TopDown) {
294 // A non-Widen result means we can't extend the vectorized region into
295 // this bundle, so leave its instructions scalar and don't record an
296 // action for it.
297 if (LegalityRes.getSubclassID() != LegalityResultID::Widen)
298 return nullptr;
299
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));
305
306 // Walk down the def-use chain. Each lane in \p Bndl may feed several
307 // users, so we form every compatible user bundle and recurse into each
308 // one.
309 SmallPtrSet<Instruction *, 4> Claimed;
310 for (const auto &NextUserBndl :
311 VecUtils::getNextUserBundles(Bndl, *IMaps, Claimed))
312 vectorizeRec(NextUserBndl, Bndl, Depth + 1, Legality);
313
314 return Action;
315 }
316
317 // Bottom up direction
318 auto ActionPtr =
319 std::make_unique<Action>(&LegalityRes, Bndl, UserBndl, Depth);
320 SmallVector<Action *> Operands;
321 switch (LegalityRes.getSubclassID()) {
323 auto *I = cast<Instruction>(Bndl[0]);
324 switch (I->getOpcode()) {
325 case Instruction::Opcode::Load:
326 break;
327 case Instruction::Opcode::Store: {
328 // Don't recurse towards the pointer operand.
329 Action *OpA =
330 vectorizeRec(getOperand(Bndl, 0), Bndl, Depth + 1, Legality);
331 Operands.push_back(OpA);
332 break;
333 }
334 default:
335 // Visit all operands.
336 for (auto OpIdx : seq<unsigned>(I->getNumOperands())) {
337 Action *OpA =
338 vectorizeRec(getOperand(Bndl, OpIdx), Bndl, Depth + 1, Legality);
339 Operands.push_back(OpA);
340 }
341 break;
342 }
343 // Update the maps to mark Bndl as "vectorized".
344 IMaps->registerVector(Bndl, ActionPtr.get());
345 break;
346 }
351 break;
352 }
353 // Create actions in post-order.
354 ActionPtr->Operands = std::move(Operands);
355 auto *Action = ActionPtr.get();
356 Actions.push_back(std::move(ActionPtr));
357 return Action;
358}
359
360#ifndef NDEBUG
361void BundleVec::ActionsVector::print(raw_ostream &OS) const {
362 for (auto [Idx, Action] : enumerate(Actions)) {
363 Action->print(OS);
364 OS << "\n";
365 }
366}
367void BundleVec::ActionsVector::dump() const { print(dbgs()); }
368#endif // NDEBUG
369
370void BundleVec::emitUnpacksForExternalUses(const ArrayRef<Value *> Bndl,
371 Value *Vec) {
372 // Find where we should emit the unpacks.
373 BasicBlock::iterator WhereIt;
374 if (auto *VecI = dyn_cast<Instruction>(Vec)) {
375 WhereIt = std::next(VecI->getIterator());
376 } else {
377 // If Vec is a constant then it should be safe to emit the unpacks at the
378 // top of the block.
379 // Note: Extracts from constants are usually folded to constants.
380 assert(isa<Constant>(Vec) && "Expected constant!");
381 assert(isa<Instruction>(Bndl[0]) &&
382 "A widened Bndl should contain instrs!");
383 BasicBlock *BB = cast<Instruction>(Bndl[0])->getParent();
384 WhereIt =
385 BB->empty()
386 ? BB->begin()
387 : std::next(
388 VecUtils::getLastPHIOrSelf(&*BB->begin())->getIterator());
389 }
390
391 for (auto [Lane, Elm] : VecUtils::enumerateLanes(Bndl)) {
392 // Only redirect the external (non-vectorized) uses to an unpack and leave
393 // the vectorized users untouched. A blanket replaceAllUsesWith() would
394 // also rewrite the operands of users we are going to vectorize but have
395 // not emitted yet (in the top-down direction a user bundle is emitted
396 // after its operand bundle), which would corrupt those operands.
397 auto IsExternal = [this](const Use &U) {
398 return !IMaps->isVectorized(U.getUser());
399 };
400 // Don't emit a dead unpack if all uses are internal to the vector region.
401 if (none_of(Elm->uses(), IsExternal))
402 continue;
403 auto *UnpackV = VecUtils::unpack(Vec, Elm->getType(), Lane, WhereIt);
404 Elm->replaceUsesWithIf(UnpackV, IsExternal);
405 }
406}
407
408Value *BundleVec::emitVectors() {
409 Value *NewVec = nullptr;
410 for (const auto &ActionPtr : Actions) {
411 ArrayRef<Value *> Bndl = ActionPtr->Bndl;
412 ArrayRef<Value *> UserBndl = ActionPtr->UserBndl;
413 const LegalityResult &LegalityRes = *ActionPtr->LegalityRes;
414 unsigned Depth = ActionPtr->Depth;
415 auto *UserBB = !UserBndl.empty()
416 ? cast<Instruction>(UserBndl.front())->getParent()
417 : cast<Instruction>(Bndl[0])->getParent();
418
419 switch (LegalityRes.getSubclassID()) {
421 auto *I = cast<Instruction>(Bndl[0]);
422 SmallVector<Value *, 2> VecOperands;
423 if (Dir == SchedDirection::BottomUp) {
424 switch (I->getOpcode()) {
425 case Instruction::Opcode::Load:
426 VecOperands.push_back(cast<LoadInst>(I)->getPointerOperand());
427 break;
428 case Instruction::Opcode::Store:
429 VecOperands.push_back(ActionPtr->Operands[0]->Vec);
430 VecOperands.push_back(cast<StoreInst>(I)->getPointerOperand());
431 break;
432 default:
433 for (Action *OpA : ActionPtr->Operands)
434 VecOperands.push_back(OpA->Vec);
435 break;
436 }
437 } else {
438 switch (I->getOpcode()) {
439 case Instruction::Opcode::Load:
440 VecOperands.push_back(cast<LoadInst>(I)->getPointerOperand());
441 break;
442 case Instruction::Opcode::Store: {
443 auto OpBndl = getOperand(Bndl, 0);
444 if (Action *OpA = IMaps->getVectorForOrig(OpBndl[0]))
445 VecOperands.push_back(OpA->Vec);
446 else
447 VecOperands.push_back(createPack(OpBndl, UserBB));
448 VecOperands.push_back(cast<StoreInst>(I)->getPointerOperand());
449 break;
450 }
451 default:
452 for (unsigned OpIdx = 0; OpIdx < I->getNumOperands(); ++OpIdx) {
453 BundleTy OpBndl = getOperand(Bndl, OpIdx);
454 if (Action *OpA = IMaps->getVectorForOrig(OpBndl[0]))
455 VecOperands.push_back(OpA->Vec);
456 else
457 VecOperands.push_back(createPack(OpBndl, UserBB));
458 }
459 break;
460 }
461 }
462 NewVec = createVectorInstr(ActionPtr->Bndl, VecOperands);
463 // Collect any potentially dead scalar instructions, including the
464 // original scalars and pointer operands of loads/stores.
465 if (NewVec != nullptr)
466 collectPotentiallyDeadInstrs(Bndl);
467
468 // Emit unpacks for all external uses, if any.
469 emitUnpacksForExternalUses(ActionPtr->Bndl, NewVec);
470 break;
471 }
473 NewVec = cast<DiamondReuse>(LegalityRes).getVector()->Vec;
474 break;
475 }
477 auto *VecOp = cast<DiamondReuseWithShuffle>(LegalityRes).getVector()->Vec;
478 const ShuffleMask &Mask =
479 cast<DiamondReuseWithShuffle>(LegalityRes).getMask();
480 NewVec = createShuffle(VecOp, Mask, UserBB);
481 assert(NewVec->getType() == VecOp->getType() &&
482 "Expected same type! Bad mask ?");
483 break;
484 }
486 const auto &Descr =
487 cast<DiamondReuseMultiInput>(LegalityRes).getCollectDescr();
488 Type *ResTy = VecUtils::getWideType(Bndl[0]->getType(), Bndl.size());
489
490 // TODO: Try to get WhereIt without creating a vector.
491 SmallVector<Value *, 4> DescrInstrs;
492 for (const auto &ElmDescr : Descr.getDescrs()) {
493 auto *V = ElmDescr.needsExtract() ? ElmDescr.getValue()->Vec
494 : ElmDescr.getScalar();
495 if (auto *I = dyn_cast<Instruction>(V))
496 DescrInstrs.push_back(I);
497 }
498 BasicBlock::iterator WhereIt =
499 getInsertPointAfterInstrs(DescrInstrs, UserBB);
500
501 Value *LastV = PoisonValue::get(ResTy);
502 Context &Ctx = LastV->getContext();
503 unsigned Lane = 0;
504 for (const auto &ElmDescr : Descr.getDescrs()) {
505 Value *VecOp = nullptr;
506 Value *ValueToInsert;
507 if (ElmDescr.needsExtract()) {
508 VecOp = ElmDescr.getValue()->Vec;
509 ConstantInt *IdxC =
510 ConstantInt::get(Type::getInt32Ty(Ctx), ElmDescr.getExtractIdx());
511 ValueToInsert = ExtractElementInst::create(
512 VecOp, IdxC, WhereIt, VecOp->getContext(), "VExt");
513 } else {
514 ValueToInsert = ElmDescr.getScalar();
515 }
516 auto NumLanesToInsert = VecUtils::getNumLanes(ValueToInsert);
517 if (NumLanesToInsert == 1) {
518 // If we are inserting a scalar element then we need a single insert.
519 // %VIns = insert %DstVec, %SrcScalar, Lane
520 ConstantInt *LaneC = ConstantInt::get(Type::getInt32Ty(Ctx), Lane);
521 LastV = InsertElementInst::create(LastV, ValueToInsert, LaneC,
522 WhereIt, Ctx, "VIns");
523 } else {
524 // If we are inserting a vector element then we need to extract and
525 // insert each vector element one by one with a chain of extracts and
526 // inserts, for example:
527 // %VExt0 = extract %SrcVec, 0
528 // %VIns0 = insert %DstVec, %Vect0, Lane + 0
529 // %VExt1 = extract %SrcVec, 1
530 // %VIns1 = insert %VIns0, %Vect0, Lane + 1
531 for (unsigned LnCnt = 0; LnCnt != NumLanesToInsert; ++LnCnt) {
532 auto *ExtrIdxC = ConstantInt::get(Type::getInt32Ty(Ctx), LnCnt);
533 auto *ExtrI = ExtractElementInst::create(ValueToInsert, ExtrIdxC,
534 WhereIt, Ctx, "VExt");
535 unsigned InsLane = Lane + LnCnt;
536 auto *InsLaneC = ConstantInt::get(Type::getInt32Ty(Ctx), InsLane);
537 LastV = InsertElementInst::create(LastV, ExtrI, InsLaneC, WhereIt,
538 Ctx, "VIns");
539 }
540 }
541 Lane += NumLanesToInsert;
542 }
543 NewVec = LastV;
544 break;
545 }
547 // If we can't vectorize the seeds then just return.
548 if (Depth == 0)
549 return nullptr;
550 NewVec = createPack(Bndl, UserBB);
551 break;
552 }
553 }
554 if (NewVec != nullptr) {
555 Change = true;
556 ActionPtr->Vec = NewVec;
557 }
558#ifndef NDEBUG
559 if (AlwaysVerify) {
560 // This helps find broken IR by constantly verifying the function. Note
561 // that this is very expensive and should only be used for debugging.
562 Instruction *I0 = isa<Instruction>(Bndl[0])
563 ? cast<Instruction>(Bndl[0])
564 : cast<Instruction>(UserBndl[0]);
565 assert(!Utils::verifyFunction(I0->getParent()->getParent(), dbgs()) &&
566 "Broken function!");
567 }
568#endif // NDEBUG
569 }
570 return NewVec;
571}
572
573bool BundleVec::tryVectorize(ArrayRef<Value *> Bndl,
574 LegalityAnalysis &Legality) {
575 Change = false;
576 if (LLVM_UNLIKELY(InvocationCnt++ >= StopAt && StopAt != StopAtDisabled))
577 return false;
578 DeadInstrCandidates.clear();
579 Legality.clear();
580 Actions.clear();
581 DebugBndlCnt = 0;
582 vectorizeRec(Bndl, {}, /*Depth=*/0, Legality);
584 << "Vec: Vectorization Actions:\n";
585 Actions.dump());
586 emitVectors();
587 tryEraseDeadInstrs();
588 return Change;
589}
590
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>();
596 LegalityAnalysis Legality(A.getAA(), A.getScalarEvolution(),
597 F.getParent()->getDataLayout(), F.getContext(),
598 *IMaps, Dir);
599
600 // TODO: Refactor to remove the unnecessary copy to SeedSliceVals.
601 SmallVector<Value *> SeedSliceVals(SeedSlice.begin(), SeedSlice.end());
602 // Try to vectorize starting from the seed slice. The returned value
603 // is true if we found vectorizable code and generated some vector
604 // code for it. It does not mean that the code is profitable.
605 return tryVectorize(SeedSliceVals, Legality);
606}
607
608} // namespace sandboxir
609} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_UNLIKELY(EXPR)
Definition Compiler.h:344
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
MachineInstr unsigned OpIdx
This file defines the SmallVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
#define DEBUG_PREFIX
Definition Debug.h:19
Value * RHS
Value * LHS
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
iterator begin()
Instruction iterator methods.
Definition BasicBlock.h:461
bool empty() const
Definition BasicBlock.h:483
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
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.
Definition Value.h:75
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.
Definition Constant.cpp:48
static LLVM_ABI ConstantInt * getSigned(IntegerType *Ty, int64_t V)
Return a ConstantInt with the specified value for the specified type.
Definition Constant.cpp:56
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.
Definition Legality.h:318
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
Definition Pass.h:67
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition Constant.cpp:263
const SmallVector< Instruction * > & getAux() const
\Returns the auxiliary vector.
Definition Region.h:177
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)
Definition Type.cpp:21
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.
Definition Utils.h:32
static bool verifyFunction(const Function *F, raw_ostream &OS)
Equivalent to llvm::verifyFunction().
Definition Utils.h:130
A SandboxIR Value has users. This is the base class.
Definition Value.h:72
static Instruction * getLowest(ArrayRef< Instruction * > Instrs)
\Returns the instruction in Instrs that is lowest in the BB.
Definition VecUtils.h:145
static Type * getCommonScalarType(ArrayRef< Value * > Bndl)
Similar to tryGetCommonScalarType() but will assert that there is a common type.
Definition VecUtils.h:222
static Instruction * getLastPHIOrSelf(Instruction *I)
If I is not a PHI it returns it.
Definition VecUtils.h:195
static unsigned getNumLanes(Type *Ty)
\Returns the number of vector lanes of Ty or 1 if not a vector.
Definition VecUtils.h:90
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.
Definition VecUtils.h:309
static LLVM_DUMP_METHOD void dump(ArrayRef< Value * > Bndl)
Helper dump function for debugging.
Definition VecUtils.cpp:111
static Type * getWideType(Type *ElemTy, unsigned NumElts)
\Returns <NumElts x ElemTy>.
Definition VecUtils.h:113
static auto enumerateLanes(const ValueContainerT &Range)
Helper for creating LaneValueEnumerator ranges.
Definition VecUtils.h:395
static Type * getElementType(Type *Ty)
Returns Ty if scalar or its element type if vector.
Definition VecUtils.h:50
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.
Definition VecUtils.cpp:68
#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
Definition RDFGraph.h:385
LLVM_ABI Function * getParent() const
StringLiteral schedDirectionToStr(SchedDirection Dir)
Definition Scheduler.cpp:15
BasicBlock(llvm::BasicBlock *BB, Context &SBCtx)
Definition BasicBlock.h:75
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
SmallVector< Value *, 4 > BundleTy
Definition VecUtils.h:38
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...
Definition BundleVec.cpp:56
static BundleTy getOperand(ArrayRef< Value * > Bndl, unsigned OpIdx)
Definition BundleVec.cpp:45
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.
Definition STLExtras.h:315
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
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,...
Definition STLExtras.h:2554
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
static constexpr unsigned long StopBundleDisabled
Definition BundleVec.cpp:37
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
Definition InstrProf.h:143
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1753
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
ArrayRef(const T &OneElt) -> ArrayRef< T >
static constexpr unsigned long StopAtDisabled
Definition BundleVec.cpp:30
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
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)."))