LLVM 24.0.0git
VPlanRecipes.cpp
Go to the documentation of this file.
1//===- VPlanRecipes.cpp - Implementations for VPlan recipes ---------------===//
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///
9/// \file
10/// This file contains implementations for different VPlan recipes.
11///
12//===----------------------------------------------------------------------===//
13
15#include "VPlan.h"
16#include "VPlanHelpers.h"
17#include "VPlanPatternMatch.h"
18#include "VPlanUtils.h"
19#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/Twine.h"
27#include "llvm/IR/BasicBlock.h"
28#include "llvm/IR/IRBuilder.h"
29#include "llvm/IR/Instruction.h"
31#include "llvm/IR/Intrinsics.h"
32#include "llvm/IR/Type.h"
33#include "llvm/IR/Value.h"
36#include "llvm/Support/Debug.h"
40#include <cassert>
41
42using namespace llvm;
43using namespace llvm::VPlanPatternMatch;
44
46
47#define LV_NAME "loop-vectorize"
48#define DEBUG_TYPE LV_NAME
49
50#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
51// It is sometimes necessary to disable printing of metadata in tests in order
52// to avoid non-deterministic behaviour due to metadata introduced by VPlan
53// that wasn't present in the original scalar IR.
55 "vplan-print-metadata", cl::init(true), cl::Hidden,
56 cl::desc("Controls the printing of recipe metadata when debugging."));
57#endif
58
60 switch (getVPRecipeID()) {
61 case VPExpressionSC:
62 return cast<VPExpressionRecipe>(this)->mayReadOrWriteMemory();
63 case VPInstructionSC: {
64 auto *VPI = cast<VPInstruction>(this);
65 // Loads read from memory but don't write to memory.
66 if (VPI->getOpcode() == Instruction::Load)
67 return false;
68 return VPI->opcodeMayReadOrWriteFromMemory();
69 }
70 case VPInterleaveEVLSC:
71 case VPInterleaveSC:
72 return cast<VPInterleaveBase>(this)->getNumStoreOperands() > 0;
73 case VPWidenStoreEVLSC:
74 case VPWidenStoreSC:
75 return true;
76 case VPReplicateSC:
77 return cast<Instruction>(getVPSingleValue()->getUnderlyingValue())
78 ->mayWriteToMemory();
79 case VPWidenCallSC:
80 return !cast<VPWidenCallRecipe>(this)
81 ->getCalledScalarFunction()
82 ->onlyReadsMemory();
83 case VPWidenMemIntrinsicSC:
84 case VPWidenIntrinsicSC:
85 return cast<VPWidenIntrinsicRecipe>(this)->mayWriteToMemory();
86 case VPActiveLaneMaskPHISC:
87 case VPCurrentIterationPHISC:
88 case VPBranchOnMaskSC:
89 case VPDerivedIVSC:
90 case VPFirstOrderRecurrencePHISC:
91 case VPReductionPHISC:
92 case VPScalarIVStepsSC:
93 case VPPredInstPHISC:
94 return false;
95 case VPBlendSC:
96 case VPReductionEVLSC:
97 case VPReductionSC:
98 case VPVectorPointerSC:
99 case VPWidenCanonicalIVSC:
100 case VPWidenCastSC:
101 case VPWidenGEPSC:
102 case VPWidenIntOrFpInductionSC:
103 case VPWidenLoadEVLSC:
104 case VPWidenLoadSC:
105 case VPWidenPHISC:
106 case VPWidenPointerInductionSC:
107 case VPWidenSC: {
108 const Instruction *I =
109 dyn_cast_or_null<Instruction>(getVPSingleValue()->getUnderlyingValue());
110 (void)I;
111 assert((!I || !I->mayWriteToMemory()) &&
112 "underlying instruction may write to memory");
113 return false;
114 }
115 default:
116 return true;
117 }
118}
119
121 switch (getVPRecipeID()) {
122 case VPExpressionSC:
123 return cast<VPExpressionRecipe>(this)->mayReadOrWriteMemory();
124 case VPInstructionSC:
125 return cast<VPInstruction>(this)->opcodeMayReadOrWriteFromMemory();
126 case VPWidenLoadEVLSC:
127 case VPWidenLoadSC:
128 return true;
129 case VPReplicateSC:
130 return cast<Instruction>(getVPSingleValue()->getUnderlyingValue())
131 ->mayReadFromMemory();
132 case VPWidenCallSC:
133 return !cast<VPWidenCallRecipe>(this)
134 ->getCalledScalarFunction()
135 ->onlyWritesMemory();
136 case VPWidenMemIntrinsicSC:
137 case VPWidenIntrinsicSC:
138 return cast<VPWidenIntrinsicRecipe>(this)->mayReadFromMemory();
139 case VPBranchOnMaskSC:
140 case VPDerivedIVSC:
141 case VPCurrentIterationPHISC:
142 case VPFirstOrderRecurrencePHISC:
143 case VPReductionPHISC:
144 case VPPredInstPHISC:
145 case VPScalarIVStepsSC:
146 case VPWidenStoreEVLSC:
147 case VPWidenStoreSC:
148 return false;
149 case VPBlendSC:
150 case VPReductionEVLSC:
151 case VPReductionSC:
152 case VPVectorPointerSC:
153 case VPWidenCanonicalIVSC:
154 case VPWidenCastSC:
155 case VPWidenGEPSC:
156 case VPWidenIntOrFpInductionSC:
157 case VPWidenPHISC:
158 case VPWidenPointerInductionSC:
159 case VPWidenSC: {
160 const Instruction *I =
161 dyn_cast_or_null<Instruction>(getVPSingleValue()->getUnderlyingValue());
162 (void)I;
163 assert((!I || !I->mayReadFromMemory()) &&
164 "underlying instruction may read from memory");
165 return false;
166 }
167 default:
168 // FIXME: Return false if the recipe represents an interleaved store.
169 return true;
170 }
171}
172
174 switch (getVPRecipeID()) {
175 case VPExpressionSC:
176 return cast<VPExpressionRecipe>(this)->mayHaveSideEffects();
177 case VPActiveLaneMaskPHISC:
178 case VPDerivedIVSC:
179 case VPCurrentIterationPHISC:
180 case VPFirstOrderRecurrencePHISC:
181 case VPReductionPHISC:
182 case VPPredInstPHISC:
183 case VPVectorEndPointerSC:
184 return false;
185 case VPInstructionSC: {
186 auto *VPI = cast<VPInstruction>(this);
187 return mayWriteToMemory() ||
188 VPI->getOpcode() == VPInstruction::BranchOnCount ||
189 VPI->getOpcode() == VPInstruction::BranchOnCond ||
190 VPI->getOpcode() == VPInstruction::BranchOnTwoConds;
191 }
192 case VPWidenCallSC: {
193 Function *Fn = cast<VPWidenCallRecipe>(this)->getCalledScalarFunction();
194 return mayWriteToMemory() || !Fn->doesNotThrow() || !Fn->willReturn();
195 }
196 case VPWidenMemIntrinsicSC:
197 case VPWidenIntrinsicSC:
198 return cast<VPWidenIntrinsicRecipe>(this)->mayHaveSideEffects();
199 case VPBlendSC:
200 case VPReductionEVLSC:
201 case VPReductionSC:
202 case VPScalarIVStepsSC:
203 case VPVectorPointerSC:
204 case VPWidenCanonicalIVSC:
205 case VPWidenCastSC:
206 case VPWidenGEPSC:
207 case VPWidenIntOrFpInductionSC:
208 case VPWidenPHISC:
209 case VPWidenPointerInductionSC:
210 case VPWidenSC: {
211 const Instruction *I =
212 dyn_cast_or_null<Instruction>(getVPSingleValue()->getUnderlyingValue());
213 (void)I;
214 assert((!I || !I->mayHaveSideEffects()) &&
215 "underlying instruction has side-effects");
216 return false;
217 }
218 case VPInterleaveEVLSC:
219 case VPInterleaveSC:
220 return mayWriteToMemory();
221 case VPWidenLoadEVLSC:
222 case VPWidenLoadSC:
223 case VPWidenStoreEVLSC:
224 case VPWidenStoreSC:
225 assert(
226 cast<VPWidenMemoryRecipe>(this)->getIngredient().mayHaveSideEffects() ==
228 "mayHaveSideffects result for ingredient differs from this "
229 "implementation");
230 return mayWriteToMemory();
231 case VPReplicateSC: {
232 auto *R = cast<VPReplicateRecipe>(this);
233 return R->getUnderlyingInstr()->mayHaveSideEffects();
234 }
235 default:
236 return true;
237 }
238}
239
241 switch (getVPRecipeID()) {
242 default:
243 return false;
244 case VPInstructionSC: {
245 unsigned Opcode = cast<VPInstruction>(this)->getOpcode();
246 if (Instruction::isCast(Opcode))
247 return true;
248
249 switch (Opcode) {
250 default:
251 return false;
252 case Instruction::Add:
253 case Instruction::Sub:
254 case Instruction::Mul:
255 case Instruction::GetElementPtr:
256 return true;
257 }
258 }
259 }
260}
261
263 assert(!Parent && "Recipe already in some VPBasicBlock");
264 assert(InsertPos->getParent() &&
265 "Insertion position not in any VPBasicBlock");
266 InsertPos->getParent()->insert(this, InsertPos->getIterator());
267}
268
269void VPRecipeBase::insertBefore(VPBasicBlock &BB,
271 assert(!Parent && "Recipe already in some VPBasicBlock");
272 assert(I == BB.end() || I->getParent() == &BB);
273 BB.insert(this, I);
274}
275
277 assert(!Parent && "Recipe already in some VPBasicBlock");
278 assert(InsertPos->getParent() &&
279 "Insertion position not in any VPBasicBlock");
280 InsertPos->getParent()->insert(this, std::next(InsertPos->getIterator()));
281}
282
284 assert(getParent() && "Recipe not in any VPBasicBlock");
286 Parent = nullptr;
287}
288
290 assert(getParent() && "Recipe not in any VPBasicBlock");
292}
293
296 insertAfter(InsertPos);
297}
298
304
306 // Get the underlying instruction for the recipe, if there is one. It is used
307 // to
308 // * decide if cost computation should be skipped for this recipe,
309 // * apply forced target instruction cost.
310 Instruction *UI = nullptr;
311 if (auto *S = dyn_cast<VPSingleDefRecipe>(this))
312 UI = dyn_cast_or_null<Instruction>(S->getUnderlyingValue());
313 else if (auto *IG = dyn_cast<VPInterleaveBase>(this))
314 UI = IG->getInsertPos();
315 else if (auto *WidenMem = dyn_cast<VPWidenMemoryRecipe>(this))
316 UI = &WidenMem->getIngredient();
317
318 InstructionCost RecipeCost;
319 if (UI && Ctx.skipCostComputation(UI, VF.isVector())) {
320 RecipeCost = 0;
321 } else {
322 RecipeCost = computeCost(VF, Ctx);
323 if (ForceTargetInstructionCost.getNumOccurrences() > 0 &&
324 RecipeCost.isValid()) {
325 if (UI)
327 else
328 RecipeCost = InstructionCost(0);
329 }
330 }
331
332 LLVM_DEBUG({
333 dbgs() << "Cost of " << RecipeCost << " for VF " << VF << ": ";
334 if (VPSlotTracker *SlotTracker = Ctx.getSlotTracker()) {
335 print(dbgs(), "", *SlotTracker);
336 dbgs() << "\n";
337 } else {
338 dump();
339 }
340 });
341 return RecipeCost;
342}
343
345 VPCostContext &Ctx) const {
346 llvm_unreachable("subclasses should implement computeCost");
347}
348
350 return (getVPRecipeID() >= VPFirstPHISC && getVPRecipeID() <= VPLastPHISC) ||
352}
353
355 assert(OpType == Other.OpType && "OpType must match");
356 switch (OpType) {
357 case OperationType::OverflowingBinOp:
358 WrapFlags.HasNUW &= Other.WrapFlags.HasNUW;
359 WrapFlags.HasNSW &= Other.WrapFlags.HasNSW;
360 break;
361 case OperationType::Trunc:
362 TruncFlags.HasNUW &= Other.TruncFlags.HasNUW;
363 TruncFlags.HasNSW &= Other.TruncFlags.HasNSW;
364 break;
365 case OperationType::DisjointOp:
366 DisjointFlags.IsDisjoint &= Other.DisjointFlags.IsDisjoint;
367 break;
368 case OperationType::PossiblyExactOp:
369 ExactFlags.IsExact &= Other.ExactFlags.IsExact;
370 break;
371 case OperationType::GEPOp:
372 GEPFlagsStorage &= Other.GEPFlagsStorage;
373 break;
374 case OperationType::FPMathOp:
375 case OperationType::FCmp:
376 assert((OpType != OperationType::FCmp ||
377 FCmpFlags.CmpPredStorage == Other.FCmpFlags.CmpPredStorage) &&
378 "Cannot drop CmpPredicate");
379 getFMFsRef() = getFastMathFlagsOrNone() & Other.getFastMathFlagsOrNone();
380 break;
381 case OperationType::NonNegOp:
382 NonNegFlags.NonNeg &= Other.NonNegFlags.NonNeg;
383 break;
384 case OperationType::Cmp:
385 assert(CmpPredStorage == Other.CmpPredStorage &&
386 "Cannot drop CmpPredicate");
387 break;
388 case OperationType::ReductionOp:
389 assert(ReductionFlags.Kind == Other.ReductionFlags.Kind &&
390 "Cannot change RecurKind");
391 assert(ReductionFlags.IsOrdered == Other.ReductionFlags.IsOrdered &&
392 "Cannot change IsOrdered");
393 assert(ReductionFlags.IsInLoop == Other.ReductionFlags.IsInLoop &&
394 "Cannot change IsInLoop");
395 getFMFsRef() = getFastMathFlagsOrNone() & Other.getFastMathFlagsOrNone();
396 break;
397 case OperationType::Other:
398 break;
399 }
400}
401
403 if (!hasFastMathFlags())
404 return {};
405 const FastMathFlagsTy &F = getFMFsRef();
406 FastMathFlags Res;
407 Res.setAllowReassoc(F.AllowReassoc);
408 Res.setNoNaNs(F.NoNaNs);
409 Res.setNoInfs(F.NoInfs);
410 Res.setNoSignedZeros(F.NoSignedZeros);
411 Res.setAllowReciprocal(F.AllowReciprocal);
412 Res.setAllowContract(F.AllowContract);
413 Res.setApproxFunc(F.ApproxFunc);
414 return Res;
415}
416
417#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
419
420void VPRecipeBase::print(raw_ostream &O, const Twine &Indent,
421 VPSlotTracker &SlotTracker) const {
422 printRecipe(O, Indent, SlotTracker);
423 if (auto DL = getDebugLoc()) {
424 O << ", !dbg ";
425 DL.print(O);
426 }
427
428 if (auto *Metadata = dyn_cast<VPIRMetadata>(this))
430}
431#endif
432
434 : VPSingleDefRecipe(VPRecipeBase::VPExpandSCEVSC, {}, Expr->getType()),
435 Expr(Expr) {}
436
437/// For call VPInstruction operands, return the operand index of the called
438/// function. The function is either the last operand (for unmasked calls) or
439/// the second-to-last operand (for masked calls).
441 unsigned NumOps = Operands.size();
442 auto *LastOp = dyn_cast<VPIRValue>(Operands[NumOps - 1]);
443 if (LastOp && isa<Function>(LastOp->getValue()))
444 return NumOps - 1;
446 "expected function operand");
447 return NumOps - 2;
448}
449
450/// For call VPInstruction operands, return the called function.
455
458 assert(!Operands.empty() &&
459 "zero-operand VPInstruction opcodes must pass explicit ResultTy");
460 // Assert operand \p Idx (if present and typed) has type \p ExpectedTy.
461 [[maybe_unused]] auto AssertOperandType = [&Operands](unsigned Idx,
462 Type *ExpectedTy) {
463 if (!ExpectedTy || Operands.size() <= Idx)
464 return;
465 [[maybe_unused]] Type *OpTy = Operands[Idx]->getScalarType();
466 assert((!OpTy || OpTy == ExpectedTy) &&
467 "different types inferred for different operands");
468 };
469
470 Type *Op0Ty = Operands[0]->getScalarType();
471 LLVMContext &Ctx = Op0Ty->getContext();
472 switch (Opcode) {
474 assert(Op0Ty->isIntegerTy(1) && "expected bool condition");
475 return Type::getVoidTy(Ctx);
477 assert(Op0Ty->isIntegerTy(1) && "expected bool condition");
478 AssertOperandType(1, IntegerType::get(Ctx, 1));
479 return Type::getVoidTy(Ctx);
481 assert(Op0Ty->isIntegerTy() && "expected integer operand");
482 AssertOperandType(1, Op0Ty);
483 return Type::getVoidTy(Ctx);
486 assert(Op0Ty->isIntegerTy() && "expected integer operand");
487 for (unsigned Idx = 1; Idx != Operands.size(); ++Idx)
488 AssertOperandType(Idx, Op0Ty);
489 return Op0Ty;
490 case Instruction::Switch:
491 for (unsigned Idx = 1; Idx != Operands.size(); ++Idx)
492 AssertOperandType(Idx, Op0Ty);
493 return Type::getVoidTy(Ctx);
494 case Instruction::Store:
495 return Type::getVoidTy(Ctx);
496 case Instruction::ICmp:
497 assert(Op0Ty->isIntOrPtrTy() && "expected integer or pointer operand");
498 AssertOperandType(1, Op0Ty);
499 return IntegerType::get(Ctx, 1);
500 case Instruction::FCmp:
501 assert(Op0Ty->isFloatingPointTy() && "expected floating-point operand");
502 AssertOperandType(1, Op0Ty);
503 return IntegerType::get(Ctx, 1);
505 assert(Op0Ty->isIntegerTy() && "expected integer operand");
506 AssertOperandType(1, Op0Ty);
507 return IntegerType::get(Ctx, 1);
509 assert(Op0Ty->isIntegerTy(1) && "expected bool operand");
510 return IntegerType::get(Ctx, 1);
513 assert(Op0Ty->isIntegerTy(1) && "expected bool operand");
514 AssertOperandType(1, Op0Ty);
515 return IntegerType::get(Ctx, 1);
517 assert(Op0Ty->isIntegerTy(1) && "expected bool operand");
518 for (unsigned Idx = 1; Idx != Operands.size(); ++Idx)
519 AssertOperandType(Idx, Op0Ty);
520 return IntegerType::get(Ctx, 1);
522 assert(Op0Ty->isIntegerTy() && "expected integer operand");
523 return IntegerType::get(Ctx, 32);
524 case Instruction::Select: {
525 assert((!Op0Ty || Op0Ty->isIntegerTy(1)) &&
526 "select condition must be bool");
527 Type *Op1Ty = Operands[1]->getScalarType();
528 AssertOperandType(2, Op1Ty);
529 return Op1Ty;
530 }
531 case Instruction::InsertElement:
532 // The inserted scalar (operand 1) must match the vector element type;
533 // operand 2 must be an integer.
534 AssertOperandType(1, Op0Ty);
535 assert(Operands[2]->getScalarType()->isIntegerTy() &&
536 "expected integer operand");
537 return Op0Ty;
539 // The start value and the identity value (operands 0 and 1) fill the same
540 // vector and must match in type; operand 2 is the scaling factor.
541 AssertOperandType(1, Op0Ty);
542 return Op0Ty;
544 assert(Operands.size() >= 2 && "ExtractLane requires a lane operand and "
545 "at least one source vector operand");
546 // Operand 0 is the lane index, used for integer arithmetic.
547 assert(Op0Ty->isIntegerTy() && "expected integer operand");
548 Type *Op1Ty = Operands[1]->getScalarType();
549 for (unsigned Idx = 2; Idx != Operands.size(); ++Idx)
550 AssertOperandType(Idx, Op1Ty);
551 return Op1Ty;
552 }
555 assert(Operands[0]->getScalarType()->isPointerTy() &&
556 "expected pointer operand");
557 assert(Operands[1]->getScalarType()->isIntegerTy() &&
558 "expected integer operand");
559 return Op0Ty;
560 case Instruction::ExtractValue: {
561 assert(Operands.size() == 2 && "expected single level extractvalue");
562 auto *StructTy = cast<StructType>(Op0Ty);
563 return StructTy->getTypeAtIndex(
564 cast<VPConstantInt>(Operands[1])->getZExtValue());
565 }
570 case Instruction::Load:
571 case Instruction::Alloca:
572 llvm_unreachable("type must be passed explicitly");
573 case Instruction::Call:
575 default:
576 break;
577 }
578
579 // Opcodes that require all operands to share the same scalar type as the
580 // result.
581 bool AllOperandsSameType =
582 Instruction::isBinaryOp(Opcode) ||
586 Opcode);
587 if (AllOperandsSameType)
588 for (unsigned Idx = 1; Idx != Operands.size(); ++Idx)
589 AssertOperandType(Idx, Op0Ty);
590
591 return Op0Ty;
592}
593
596 unsigned Opcode = I->getOpcode();
597 if (Instruction::isCast(Opcode) ||
598 is_contained(ArrayRef<unsigned>({Instruction::ExtractValue,
599 Instruction::Load, Instruction::Alloca}),
600 Opcode))
601 return I->getType();
603}
604
606 const VPIRFlags &Flags, const VPIRMetadata &MD,
607 DebugLoc DL, const Twine &Name, Type *ResultTy)
609 VPRecipeBase::VPInstructionSC, Operands,
610 ResultTy ? ResultTy
612 Flags, DL),
613 VPIRMetadata(MD), Opcode(Opcode), Name(Name.str()) {
615 "Set flags not supported for the provided opcode");
617 "Opcode requires specific flags to be set");
621 "number of operands does not match opcode");
622}
623
625 if (Instruction::isUnaryOp(Opcode) || Instruction::isCast(Opcode))
626 return 1;
627
628 if (Instruction::isBinaryOp(Opcode))
629 return 2;
630
631 switch (Opcode) {
634 return 0;
635 case Instruction::Alloca:
636 case Instruction::ExtractValue:
637 case Instruction::Freeze:
638 case Instruction::Load:
651 return 1;
652 case Instruction::ICmp:
653 case Instruction::FCmp:
654 case Instruction::ExtractElement:
655 case Instruction::Store:
666 return 2;
667 case Instruction::InsertElement:
668 case Instruction::Select:
671 return 3;
672 case Instruction::Call:
673 return getCalledFnOperandIndex(operands()) + 1;
674 case Instruction::GetElementPtr:
675 case Instruction::PHI:
676 case Instruction::Switch:
677 case Instruction::AtomicRMW:
678 case Instruction::AtomicCmpXchg:
679 case Instruction::Fence:
690 // Cannot determine the number of operands from the opcode.
691 return -1u;
692 }
693 llvm_unreachable("all cases should be handled above");
694}
695
697 return Opcode == VPInstruction::Unpack ||
699}
700
701bool VPInstruction::canGenerateScalarForFirstLane() const {
703 return true;
705 return true;
706 switch (Opcode) {
707 case Instruction::Freeze:
708 case Instruction::ICmp:
709 case Instruction::PHI:
710 case Instruction::Select:
720 return true;
721 default:
722 return false;
723 }
724}
725
727 if (Kind == RecurKind::Sub)
728 return Instruction::Add;
729 if (Kind == RecurKind::FSub)
730 return Instruction::FAdd;
731 llvm_unreachable("RecurKind should be Sub/FSub.");
732}
733
734Value *VPInstruction::generate(VPTransformState &State) {
735 IRBuilderBase &Builder = State.Builder;
736
738 bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this);
739 Value *A = State.get(getOperand(0), OnlyFirstLaneUsed);
740 Value *B = State.get(getOperand(1), OnlyFirstLaneUsed);
741 auto *Res =
742 Builder.CreateBinOp((Instruction::BinaryOps)getOpcode(), A, B, Name);
743 if (auto *I = dyn_cast<Instruction>(Res))
744 applyFlags(*I);
745 return Res;
746 }
747
748 switch (getOpcode()) {
749 case VPInstruction::Not: {
750 bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this);
751 Value *A = State.get(getOperand(0), OnlyFirstLaneUsed);
752 return Builder.CreateNot(A, Name);
753 }
754 case Instruction::ExtractElement: {
755 assert(State.VF.isVector() && "Only extract elements from vectors");
756 if (auto *Idx = dyn_cast<VPConstantInt>(getOperand(1)))
757 return State.get(getOperand(0), VPLane(Idx->getZExtValue()));
758 Value *Vec = State.get(getOperand(0));
759 Value *Idx = State.get(getOperand(1), /*IsScalar=*/true);
760 return Builder.CreateExtractElement(Vec, Idx, Name);
761 }
762 case Instruction::InsertElement: {
763 assert(State.VF.isVector() && "Can only insert elements into vectors");
764 Value *Vec = State.get(getOperand(0), /*IsScalar=*/false);
765 Value *Elt = State.get(getOperand(1), /*IsScalar=*/true);
766 Value *Idx = State.get(getOperand(2), /*IsScalar=*/true);
767 return Builder.CreateInsertElement(Vec, Elt, Idx, Name);
768 }
769 case Instruction::Freeze: {
771 return Builder.CreateFreeze(Op, Name);
772 }
773 case Instruction::FCmp:
774 case Instruction::ICmp: {
775 bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this);
776 Value *A = State.get(getOperand(0), OnlyFirstLaneUsed);
777 Value *B = State.get(getOperand(1), OnlyFirstLaneUsed);
778 return Builder.CreateCmp(getPredicate(), A, B, Name);
779 }
780 case Instruction::PHI: {
781 llvm_unreachable("should be handled by VPPhi::execute");
782 }
783 case Instruction::Select: {
784 bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this);
785 Value *Cond =
786 State.get(getOperand(0),
787 OnlyFirstLaneUsed || vputils::isSingleScalar(getOperand(0)));
788 Value *Op1 = State.get(getOperand(1), OnlyFirstLaneUsed);
789 Value *Op2 = State.get(getOperand(2), OnlyFirstLaneUsed);
790 return Builder.CreateSelectFMF(Cond, Op1, Op2, getFastMathFlagsOrNone(),
791 Name);
792 }
794 // Get first lane of vector induction variable.
795 Value *VIVElem0 = State.get(getOperand(0), VPLane(0));
796 // Get the original loop tripcount.
797 Value *ScalarTC = State.get(getOperand(1), VPLane(0));
798
799 // If this part of the active lane mask is scalar, generate the CMP directly
800 // to avoid unnecessary extracts.
801 if (State.VF.isScalar())
802 return Builder.CreateCmp(CmpInst::Predicate::ICMP_ULT, VIVElem0, ScalarTC,
803 Name);
804
805 ElementCount EC = State.VF.multiplyCoefficientBy(
806 cast<VPConstantInt>(getOperand(2))->getZExtValue());
807 auto *PredTy = VectorType::get(Builder.getInt1Ty(), EC);
808 return Builder.CreateIntrinsic(Intrinsic::get_active_lane_mask,
809 {PredTy, ScalarTC->getType()},
810 {VIVElem0, ScalarTC}, nullptr, Name);
811 }
813 Value *Op = State.get(getOperand(0));
814 auto *VecTy = cast<VectorType>(Op->getType());
815 assert(VecTy->getScalarSizeInBits() == 1 &&
816 "NumActiveLanes only implemented for i1 vectors");
817
818 Type *Ty = getScalarType();
819 Value *ZExt = Builder.CreateCast(
820 Instruction::ZExt, Op, VectorType::get(Ty, VecTy->getElementCount()));
821 Value *NumActive =
822 Builder.CreateUnaryIntrinsic(Intrinsic::vector_reduce_add, ZExt);
823 return NumActive;
824 }
826 // Generate code to combine the previous and current values in vector v3.
827 //
828 // vector.ph:
829 // v_init = vector(..., ..., ..., a[-1])
830 // br vector.body
831 //
832 // vector.body
833 // i = phi [0, vector.ph], [i+4, vector.body]
834 // v1 = phi [v_init, vector.ph], [v2, vector.body]
835 // v2 = a[i, i+1, i+2, i+3];
836 // v3 = vector(v1(3), v2(0, 1, 2))
837
838 auto *V1 = State.get(getOperand(0));
839 if (!V1->getType()->isVectorTy())
840 return V1;
841 Value *V2 = State.get(getOperand(1));
842 return Builder.CreateVectorSpliceRight(V1, V2, 1, Name);
843 }
845 Value *ScalarTC = State.get(getOperand(0), VPLane(0));
846 Value *VFxUF = State.get(getOperand(1), VPLane(0));
847 Value *Sub = Builder.CreateSub(ScalarTC, VFxUF);
848 Value *Cmp =
849 Builder.CreateICmp(CmpInst::Predicate::ICMP_UGT, ScalarTC, VFxUF);
851 return Builder.CreateSelect(Cmp, Sub, Zero);
852 }
854 // TODO: Restructure this code with an explicit remainder loop, vsetvli can
855 // be outside of the main loop.
856 Value *AVL = State.get(getOperand(0), /*IsScalar*/ true);
857 // Compute EVL
858 assert(AVL->getType()->isIntegerTy() &&
859 "Requested vector length should be an integer.");
860
861 assert(State.VF.isScalable() && "Expected scalable vector factor.");
862 Value *VFArg = Builder.getInt32(State.VF.getKnownMinValue());
863
864 Value *EVL = Builder.CreateIntrinsic(
865 Builder.getInt32Ty(), Intrinsic::experimental_get_vector_length,
866 {AVL, VFArg, Builder.getTrue()});
867 return EVL;
868 }
870 Value *Cond = State.get(getOperand(0), VPLane(0));
871 // Replace the temporary unreachable terminator with a new conditional
872 // branch, hooking it up to backward destination for latch blocks now, and
873 // to forward destination(s) later when they are created.
874 // Second successor may be backwards - iff it is already in VPBB2IRBB.
875 VPBasicBlock *SecondVPSucc =
876 cast<VPBasicBlock>(getParent()->getSuccessors()[1]);
877 BasicBlock *SecondIRSucc = State.CFG.VPBB2IRBB.lookup(SecondVPSucc);
878 BasicBlock *IRBB = State.CFG.VPBB2IRBB[getParent()];
879 auto *Br = Builder.CreateCondBr(Cond, IRBB, SecondIRSucc);
880 // First successor is always forward, reset it to nullptr.
881 Br->setSuccessor(0, nullptr);
883 applyMetadata(*Br);
884 return Br;
885 }
887 return Builder.CreateVectorSplat(
888 State.VF, State.get(getOperand(0), /*IsScalar*/ true), "broadcast");
889 }
891 // For struct types, we need to build a new 'wide' struct type, where each
892 // element is widened, i.e., we create a struct of vectors.
893 auto *StructTy = cast<StructType>(getOperand(0)->getScalarType());
894 Value *Res = PoisonValue::get(toVectorizedTy(StructTy, State.VF));
895 for (const auto &[LaneIndex, Op] : enumerate(operands())) {
896 for (unsigned FieldIndex = 0; FieldIndex != StructTy->getNumElements();
897 FieldIndex++) {
898 Value *ScalarValue =
899 Builder.CreateExtractValue(State.get(Op, true), FieldIndex);
900 Value *VectorValue = Builder.CreateExtractValue(Res, FieldIndex);
901 VectorValue =
902 Builder.CreateInsertElement(VectorValue, ScalarValue, LaneIndex);
903 Res = Builder.CreateInsertValue(Res, VectorValue, FieldIndex);
904 }
905 }
906 return Res;
907 }
909 auto *ScalarTy = getOperand(0)->getScalarType();
910 auto NumOfElements = ElementCount::getFixed(getNumOperands());
911 Value *Res = PoisonValue::get(toVectorizedTy(ScalarTy, NumOfElements));
912 for (const auto &[Idx, Op] : enumerate(operands()))
913 Res = Builder.CreateInsertElement(Res, State.get(Op, true),
914 Builder.getInt64(Idx));
915 return Res;
916 }
918 if (State.VF.isScalar())
919 return State.get(getOperand(0), true);
920 IRBuilderBase::FastMathFlagGuard FMFG(Builder);
922 // If this start vector is scaled then it should produce a vector with fewer
923 // elements than the VF.
924 ElementCount VF = State.VF.divideCoefficientBy(
925 cast<VPConstantInt>(getOperand(2))->getZExtValue());
926 auto *Iden = Builder.CreateVectorSplat(VF, State.get(getOperand(1), true));
927 return Builder.CreateInsertElement(Iden, State.get(getOperand(0), true),
928 Builder.getInt64(0));
929 }
931 RecurKind RK = getRecurKind();
932 bool IsOrdered = isReductionOrdered();
933 bool IsInLoop = isReductionInLoop();
935 "FindIV should use min/max reduction kinds");
936
937 // The recipe may have multiple operands to be reduced together.
938 unsigned NumOperandsToReduce = getNumOperands();
939 VectorParts RdxParts(NumOperandsToReduce);
940 for (unsigned Part = 0; Part < NumOperandsToReduce; ++Part)
941 RdxParts[Part] = State.get(getOperand(Part), IsInLoop);
942
943 IRBuilderBase::FastMathFlagGuard FMFG(Builder);
945
946 // Reduce multiple operands into one.
947 Value *ReducedPartRdx = RdxParts[0];
948 if (IsOrdered) {
949 ReducedPartRdx = RdxParts[NumOperandsToReduce - 1];
950 } else {
951 // Floating-point operations should have some FMF to enable the reduction.
952 for (unsigned Part = 1; Part < NumOperandsToReduce; ++Part) {
953 Value *RdxPart = RdxParts[Part];
955 ReducedPartRdx = createMinMaxOp(Builder, RK, ReducedPartRdx, RdxPart);
956 else {
957 // For sub-recurrences, each part's reduction variable is already
958 // negative, we need to do: reduce.add(-acc_uf0 + -acc_uf1)
962 : (Instruction::BinaryOps)RecurrenceDescriptor::getOpcode(RK);
963 ReducedPartRdx =
964 Builder.CreateBinOp(Opcode, RdxPart, ReducedPartRdx, "bin.rdx");
965 }
966 }
967 }
968
969 // Create the reduction after the loop. Note that inloop reductions create
970 // the target reduction in the loop using a Reduction recipe.
971 if (State.VF.isVector() && !IsInLoop) {
972 // TODO: Support in-order reductions based on the recurrence descriptor.
973 // All ops in the reduction inherit fast-math-flags from the recurrence
974 // descriptor.
975 ReducedPartRdx = createSimpleReduction(Builder, ReducedPartRdx, RK);
976 }
977
978 return ReducedPartRdx;
979 }
982 unsigned Offset =
984 Value *Res;
985 if (State.VF.isVector()) {
986 assert(Offset <= State.VF.getKnownMinValue() &&
987 "invalid offset to extract from");
988 // Extract lane VF - Offset from the operand.
989 Res = State.get(getOperand(0), VPLane::getLaneFromEnd(State.VF, Offset));
990 } else {
991 // TODO: Remove ExtractLastLane for scalar VFs.
992 assert(Offset <= 1 && "invalid offset to extract from");
993 Res = State.get(getOperand(0));
994 }
996 Res->setName(Name);
997 return Res;
998 }
1000 Value *A = State.get(getOperand(0));
1001 Value *B = State.get(getOperand(1));
1002 return Builder.CreateLogicalAnd(A, B, Name);
1003 }
1005 Value *A = State.get(getOperand(0));
1006 Value *B = State.get(getOperand(1));
1007 return Builder.CreateLogicalOr(A, B, Name);
1008 }
1009 case VPInstruction::PtrAdd: {
1010 assert((State.VF.isScalar() || vputils::onlyFirstLaneUsed(this)) &&
1011 "can only generate first lane for PtrAdd");
1012 Value *Ptr = State.get(getOperand(0), VPLane(0));
1013 Value *Addend = State.get(getOperand(1), VPLane(0));
1014 return Builder.CreatePtrAdd(Ptr, Addend, Name, getGEPNoWrapFlags());
1015 }
1017 Value *Ptr =
1019 Value *Addend = State.get(getOperand(1));
1020 return Builder.CreatePtrAdd(Ptr, Addend, Name, getGEPNoWrapFlags());
1021 }
1022 case VPInstruction::AnyOf: {
1023 Value *Res = Builder.CreateFreeze(State.get(getOperand(0)));
1024 for (VPValue *Op : drop_begin(operands()))
1025 Res = Builder.CreateOr(Res, Builder.CreateFreeze(State.get(Op)));
1026 return State.VF.isScalar() ? Res : Builder.CreateOrReduce(Res);
1027 }
1029 assert(getNumOperands() != 2 && "ExtractLane from single source should be "
1030 "simplified to ExtractElement.");
1031 Value *LaneToExtract = State.get(getOperand(0), true);
1032 Type *IdxTy = getOperand(0)->getScalarType();
1033 Value *Res = nullptr;
1034 Value *RuntimeVF = getRuntimeVF(Builder, IdxTy, State.VF);
1035
1036 for (unsigned Idx = 1; Idx != getNumOperands(); ++Idx) {
1037 Value *VectorStart =
1038 Builder.CreateMul(RuntimeVF, ConstantInt::get(IdxTy, Idx - 1));
1039 Value *VectorIdx = Idx == 1
1040 ? LaneToExtract
1041 : Builder.CreateSub(LaneToExtract, VectorStart);
1042 Value *Ext = State.VF.isScalar()
1043 ? State.get(getOperand(Idx))
1044 : Builder.CreateExtractElement(
1045 State.get(getOperand(Idx)), VectorIdx);
1046 if (Res) {
1047 Value *Cmp = Builder.CreateICmpUGE(LaneToExtract, VectorStart);
1048 Res = Builder.CreateSelect(Cmp, Ext, Res);
1049 } else {
1050 Res = Ext;
1051 }
1052 }
1053 return Res;
1054 }
1056 Type *Ty = this->getScalarType();
1057 if (getNumOperands() == 1) {
1058 Value *Mask = State.get(getOperand(0));
1059 return Builder.CreateCountTrailingZeroElems(Ty, Mask,
1060 /*ZeroIsPoison=*/false, Name);
1061 }
1062 // If there are multiple operands, create a chain of selects to pick the
1063 // first operand with an active lane and add the number of lanes of the
1064 // preceding operands.
1065 Value *RuntimeVF = getRuntimeVF(Builder, Ty, State.VF);
1066 unsigned LastOpIdx = getNumOperands() - 1;
1067 Value *Res = nullptr;
1068 for (int Idx = LastOpIdx; Idx >= 0; --Idx) {
1069 Value *TrailingZeros =
1070 State.VF.isScalar()
1071 ? Builder.CreateZExt(
1072 Builder.CreateICmpEQ(State.get(getOperand(Idx)),
1073 Builder.getFalse()),
1074 Ty)
1076 Ty, State.get(getOperand(Idx)),
1077 /*ZeroIsPoison=*/false, Name);
1078 Value *Current = Builder.CreateAdd(
1079 Builder.CreateMul(RuntimeVF, ConstantInt::get(Ty, Idx)),
1080 TrailingZeros);
1081 if (Res) {
1082 Value *Cmp = Builder.CreateICmpNE(TrailingZeros, RuntimeVF);
1083 Res = Builder.CreateSelect(Cmp, Current, Res);
1084 } else {
1085 Res = Current;
1086 }
1087 }
1088
1089 return Res;
1090 }
1092 return State.get(getOperand(0), true);
1094 return Builder.CreateVectorReverse(State.get(getOperand(0)), "reverse");
1096 Value *Result = State.get(getOperand(0), /*IsScalar=*/true);
1097 for (unsigned Idx = 1; Idx < getNumOperands(); Idx += 2) {
1098 Value *Data = State.get(getOperand(Idx));
1099 Value *Mask = State.get(getOperand(Idx + 1));
1100 Type *VTy = Data->getType();
1101
1102 if (State.VF.isScalar())
1103 Result = Builder.CreateSelect(Mask, Data, Result);
1104 else
1105 Result = Builder.CreateIntrinsic(
1106 Intrinsic::experimental_vector_extract_last_active, {VTy},
1107 {Data, Mask, Result});
1108 }
1109
1110 return Result;
1111 }
1112 default:
1113 llvm_unreachable("Unsupported opcode for instruction");
1114 }
1115}
1116
1118 unsigned Opcode, ElementCount VF, VPCostContext &Ctx) const {
1119 Type *ScalarTy = this->getScalarType();
1120 Type *ResultTy = VF.isVector() ? toVectorTy(ScalarTy, VF) : ScalarTy;
1121 switch (Opcode) {
1122 case Instruction::FNeg:
1123 return Ctx.TTI.getArithmeticInstrCost(Opcode, ResultTy, Ctx.CostKind);
1124 case Instruction::UDiv:
1125 case Instruction::SDiv:
1126 case Instruction::SRem:
1127 case Instruction::URem:
1128 case Instruction::Add:
1129 case Instruction::FAdd:
1130 case Instruction::Sub:
1131 case Instruction::FSub:
1132 case Instruction::Mul:
1133 case Instruction::FMul:
1134 case Instruction::FDiv:
1135 case Instruction::FRem:
1136 case Instruction::Shl:
1137 case Instruction::LShr:
1138 case Instruction::AShr:
1139 case Instruction::And:
1140 case Instruction::Or:
1141 case Instruction::Xor: {
1142 // Certain instructions can be cheaper if they have a constant second
1143 // operand. One example of this are shifts on x86.
1144 VPValue *RHS = getOperand(1);
1145 TargetTransformInfo::OperandValueInfo RHSInfo = Ctx.getOperandInfo(RHS);
1146
1147 if (RHSInfo.Kind == TargetTransformInfo::OK_AnyValue &&
1150
1153 if (CtxI)
1154 Operands.append(CtxI->value_op_begin(), CtxI->value_op_end());
1155 return Ctx.TTI.getArithmeticInstrCost(
1156 Opcode, ResultTy, Ctx.CostKind,
1157 {TargetTransformInfo::OK_AnyValue, TargetTransformInfo::OP_None},
1158 RHSInfo, Operands, CtxI, &Ctx.TLI);
1159 }
1160 case Instruction::Freeze:
1161 // NOTE: The only way to ask for the cost is via getInstructionCost, which
1162 // requires the actual vector instruction. Instead, both here and in the
1163 // LoopVectorizationCostModel::getInstructionCost the costs mirror the
1164 // current behaviour in llvm/Analysis/TargetTransformInfoImpl.h to keep
1165 // them in sync.
1166 return TTI::TCC_Free;
1167 case Instruction::ExtractValue:
1168 return Ctx.TTI.getInsertExtractValueCost(Instruction::ExtractValue,
1169 Ctx.CostKind);
1170 case Instruction::ICmp:
1171 case Instruction::FCmp: {
1172 Type *ScalarOpTy = getOperand(0)->getScalarType();
1173 Type *OpTy = VF.isVector() ? toVectorTy(ScalarOpTy, VF) : ScalarOpTy;
1175 return Ctx.TTI.getCmpSelInstrCost(
1177 Ctx.CostKind, {TTI::OK_AnyValue, TTI::OP_None},
1178 {TTI::OK_AnyValue, TTI::OP_None}, CtxI);
1179 }
1180 case Instruction::BitCast: {
1181 Type *ScalarTy = this->getScalarType();
1182 if (ScalarTy->isPointerTy())
1183 return 0;
1184 [[fallthrough]];
1185 }
1186 case Instruction::SExt:
1187 case Instruction::ZExt:
1188 case Instruction::FPToUI:
1189 case Instruction::FPToSI:
1190 case Instruction::FPExt:
1191 case Instruction::PtrToInt:
1192 case Instruction::PtrToAddr:
1193 case Instruction::IntToPtr:
1194 case Instruction::SIToFP:
1195 case Instruction::UIToFP:
1196 case Instruction::Trunc:
1197 case Instruction::FPTrunc:
1198 case Instruction::AddrSpaceCast: {
1199 // Computes the CastContextHint from a recipe that may access memory.
1200 auto ComputeCCH = [&](const VPRecipeBase *R) -> TTI::CastContextHint {
1201 if (isa<VPInterleaveBase>(R))
1203 if (const auto *ReplicateRecipe = dyn_cast<VPReplicateRecipe>(R)) {
1204 // Only compute CCH for memory operations, matching the legacy model
1205 // which only considers loads/stores for cast context hints.
1206 auto *UI = cast<Instruction>(ReplicateRecipe->getUnderlyingValue());
1207 if (!isa<LoadInst, StoreInst>(UI))
1209 return ReplicateRecipe->isPredicated() ? TTI::CastContextHint::Masked
1211 }
1212 const auto *WidenMemoryRecipe = dyn_cast<VPWidenMemoryRecipe>(R);
1213 if (WidenMemoryRecipe == nullptr)
1215 if (VF.isScalar())
1217 if (!WidenMemoryRecipe->isConsecutive())
1219 if (WidenMemoryRecipe->isMasked())
1222 };
1223
1224 VPValue *Operand = getOperand(0);
1226 bool IsReverse = false;
1227 // For Trunc/FPTrunc, get the context from the only user.
1228 if (Opcode == Instruction::Trunc || Opcode == Instruction::FPTrunc) {
1229 if (auto *Recipe = cast_or_null<VPRecipeBase>(getSingleUser())) {
1230 if (match(Recipe,
1234 IsReverse = true;
1236 Recipe->getVPSingleValue()->getSingleUser());
1237 }
1238 if (Recipe)
1239 CCH = ComputeCCH(Recipe);
1240 }
1241 }
1242 // For Z/Sext, get the context from the operand.
1243 else if (Opcode == Instruction::ZExt || Opcode == Instruction::SExt ||
1244 Opcode == Instruction::FPExt) {
1245 if (auto *Recipe = Operand->getDefiningRecipe()) {
1246 VPValue *ReverseOp;
1247 if (match(Recipe,
1248 m_CombineOr(m_Reverse(m_VPValue(ReverseOp)),
1250 m_VPValue(ReverseOp))))) {
1251 Recipe = ReverseOp->getDefiningRecipe();
1252 IsReverse = true;
1253 }
1254 if (Recipe)
1255 CCH = ComputeCCH(Recipe);
1256 }
1257 }
1258 if (IsReverse && CCH != TTI::CastContextHint::None)
1260
1261 auto *ScalarSrcTy = Operand->getScalarType();
1262 Type *SrcTy = VF.isVector() ? toVectorTy(ScalarSrcTy, VF) : ScalarSrcTy;
1263 // Arm TTI will use the underlying instruction to determine the cost.
1264 return Ctx.TTI.getCastInstrCost(
1265 Opcode, ResultTy, SrcTy, CCH, Ctx.CostKind,
1267 }
1268 case Instruction::Select: {
1270 bool IsScalarCond = getOperand(0)->isDefinedOutsideLoopRegions();
1271 Type *ScalarTy = this->getScalarType();
1272
1273 VPValue *Op0, *Op1;
1274 bool IsLogicalAnd =
1275 match(this, m_c_LogicalAnd(m_VPValue(Op0), m_VPValue(Op1)));
1276 bool IsLogicalOr =
1277 match(this, m_c_LogicalOr(m_VPValue(Op0), m_VPValue(Op1)));
1278 // Also match the inverted forms:
1279 // select x, false, y --> !x & y (still AND)
1280 // select x, y, true --> !x | y (still OR)
1281 IsLogicalAnd |=
1282 match(this, m_Select(m_VPValue(Op0), m_False(), m_VPValue(Op1)));
1283 IsLogicalOr |=
1284 match(this, m_Select(m_VPValue(Op0), m_VPValue(Op1), m_True()));
1285
1286 if (!IsScalarCond && ScalarTy->getScalarSizeInBits() == 1 &&
1287 (IsLogicalAnd || IsLogicalOr)) {
1288 // select x, y, false --> x & y
1289 // select x, true, y --> x | y
1290 const auto [Op1VK, Op1VP] = Ctx.getOperandInfo(Op0);
1291 const auto [Op2VK, Op2VP] = Ctx.getOperandInfo(Op1);
1292
1294 if (SI && all_of(operands(),
1295 [](VPValue *Op) { return Op->getUnderlyingValue(); }))
1296 append_range(Operands, SI->operands());
1297 return Ctx.TTI.getArithmeticInstrCost(
1298 IsLogicalOr ? Instruction::Or : Instruction::And, ResultTy,
1299 Ctx.CostKind, {Op1VK, Op1VP}, {Op2VK, Op2VP}, Operands, SI);
1300 }
1301
1302 Type *CondTy = getOperand(0)->getScalarType();
1303 if (!IsScalarCond && VF.isVector())
1304 CondTy = VectorType::get(CondTy, VF);
1305
1306 llvm::CmpPredicate Pred;
1307 if (!match(getOperand(0), m_Cmp(Pred, m_VPValue(), m_VPValue())))
1308 if (auto *CondIRV = dyn_cast<VPIRValue>(getOperand(0)))
1309 if (auto *Cmp = dyn_cast<CmpInst>(CondIRV->getValue()))
1310 Pred = Cmp->getPredicate();
1311 Type *VectorTy = toVectorTy(this->getScalarType(), VF);
1312 return Ctx.TTI.getCmpSelInstrCost(
1313 Instruction::Select, VectorTy, CondTy, Pred, Ctx.CostKind,
1314 {TTI::OK_AnyValue, TTI::OP_None}, {TTI::OK_AnyValue, TTI::OP_None}, SI);
1315 }
1316 }
1317 llvm_unreachable("called for unsupported opcode");
1318}
1319
1321 VPCostContext &Ctx) const {
1323 if (!getUnderlyingValue() && getOpcode() != Instruction::FMul) {
1324 // TODO: Compute cost for VPInstructions without underlying values once
1325 // the legacy cost model has been retired.
1326 return 0;
1327 }
1328
1330 "Should only generate a vector value or single scalar, not scalars "
1331 "for all lanes.");
1333 getOpcode(),
1335 }
1336
1337 switch (getOpcode()) {
1338 case Instruction::Select: {
1340 match(getOperand(0), m_Cmp(Pred, m_VPValue(), m_VPValue()));
1341 auto *CondTy = getOperand(0)->getScalarType();
1342 auto *VecTy = getOperand(1)->getScalarType();
1343 if (!vputils::onlyFirstLaneUsed(this)) {
1344 CondTy = toVectorTy(CondTy, VF);
1345 VecTy = toVectorTy(VecTy, VF);
1346 }
1347 return Ctx.TTI.getCmpSelInstrCost(Instruction::Select, VecTy, CondTy, Pred,
1348 Ctx.CostKind);
1349 }
1350 case Instruction::ExtractElement:
1352 if (VF.isScalar()) {
1353 // ExtractLane with VF=1 takes care of handling extracting across multiple
1354 // parts.
1355 return 0;
1356 }
1357
1358 // Add on the cost of extracting the element.
1359 auto *VecTy = toVectorTy(getOperand(0)->getScalarType(), VF);
1360 return Ctx.TTI.getVectorInstrCost(Instruction::ExtractElement, VecTy,
1361 Ctx.CostKind);
1362 }
1363 case VPInstruction::AnyOf: {
1364 auto *VecTy = toVectorTy(this->getScalarType(), VF);
1365 return Ctx.TTI.getArithmeticReductionCost(
1366 Instruction::Or, cast<VectorType>(VecTy), std::nullopt, Ctx.CostKind);
1367 }
1369 Type *Ty = this->getScalarType();
1370 Type *ScalarTy = getOperand(0)->getScalarType();
1371 if (VF.isScalar())
1372 return Ctx.TTI.getCmpSelInstrCost(Instruction::ICmp, ScalarTy,
1374 CmpInst::ICMP_EQ, Ctx.CostKind);
1375 // Calculate the cost of determining the lane index.
1376 auto *PredTy = toVectorTy(ScalarTy, VF);
1377 IntrinsicCostAttributes Attrs(Intrinsic::experimental_cttz_elts, Ty,
1378 {PredTy, Type::getInt1Ty(Ctx.LLVMCtx)});
1379 return Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
1380 }
1382 Type *Ty = this->getScalarType();
1383 Type *ScalarTy = getOperand(0)->getScalarType();
1384 if (VF.isScalar())
1385 return Ctx.TTI.getCmpSelInstrCost(Instruction::ICmp, ScalarTy,
1387 CmpInst::ICMP_EQ, Ctx.CostKind);
1388 // Calculate the cost of determining the lane index: NOT + cttz_elts + SUB.
1389 auto *PredTy = toVectorTy(ScalarTy, VF);
1390 IntrinsicCostAttributes Attrs(Intrinsic::experimental_cttz_elts, Ty,
1391 {PredTy, Type::getInt1Ty(Ctx.LLVMCtx)});
1392 InstructionCost Cost = Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
1393 // Add cost of NOT operation on the predicate.
1394 Cost += Ctx.TTI.getArithmeticInstrCost(
1395 Instruction::Xor, PredTy, Ctx.CostKind,
1396 {TargetTransformInfo::OK_AnyValue, TargetTransformInfo::OP_None},
1397 {TargetTransformInfo::OK_UniformConstantValue,
1398 TargetTransformInfo::OP_None});
1399 // Add cost of SUB operation on the index.
1400 Cost += Ctx.TTI.getArithmeticInstrCost(Instruction::Sub, Ty, Ctx.CostKind);
1401 return Cost;
1402 }
1404 Type *ScalarTy = this->getScalarType();
1405 Type *VecTy = toVectorTy(ScalarTy, VF);
1406 Type *MaskTy = toVectorTy(Type::getInt1Ty(Ctx.LLVMCtx), VF);
1408 Intrinsic::experimental_vector_extract_last_active, ScalarTy,
1409 {VecTy, MaskTy, ScalarTy});
1410 return Ctx.TTI.getIntrinsicInstrCost(ICA, Ctx.CostKind);
1411 }
1413 assert(VF.isVector() && "Scalar FirstOrderRecurrenceSplice?");
1414 Type *VectorTy = toVectorTy(this->getScalarType(), VF);
1415 return Ctx.TTI.getShuffleCost(
1417 cast<VectorType>(VectorTy), {}, Ctx.CostKind, -1);
1418 }
1420 Type *ArgTy = getOperand(0)->getScalarType();
1421 unsigned Multiplier = cast<VPConstantInt>(getOperand(2))->getZExtValue();
1422 Type *RetTy = toVectorTy(Type::getInt1Ty(Ctx.LLVMCtx), VF * Multiplier);
1423 IntrinsicCostAttributes Attrs(Intrinsic::get_active_lane_mask, RetTy,
1424 {ArgTy, ArgTy});
1425 return Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
1426 }
1428 Type *Arg0Ty = getOperand(0)->getScalarType();
1429 Type *I32Ty = Type::getInt32Ty(Ctx.LLVMCtx);
1430 Type *I1Ty = Type::getInt1Ty(Ctx.LLVMCtx);
1431 IntrinsicCostAttributes Attrs(Intrinsic::experimental_get_vector_length,
1432 I32Ty, {Arg0Ty, I32Ty, I1Ty});
1433 return Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
1434 }
1436 assert(VF.isVector() && "Reverse operation must be vector type");
1437 Type *EltTy = this->getScalarType();
1438 // Skip the reverse operation cost for the mask.
1439 // FIXME: Remove this once redundant mask reverse operations can be
1440 // eliminated by VPlanTransforms::cse before cost computation.
1441 if (EltTy->isIntegerTy(1))
1442 return 0;
1443 auto *VectorTy = cast<VectorType>(toVectorTy(EltTy, VF));
1444 return Ctx.TTI.getShuffleCost(TargetTransformInfo::SK_Reverse, VectorTy,
1445 VectorTy, /*Mask=*/{}, Ctx.CostKind,
1446 /*Index=*/0);
1447 }
1449 // Add on the cost of extracting the element.
1450 auto *VecTy = toVectorTy(getOperand(0)->getScalarType(), VF);
1451 return Ctx.TTI.getIndexedVectorInstrCostFromEnd(Instruction::ExtractElement,
1452 VecTy, Ctx.CostKind, 0);
1453 }
1454 case VPInstruction::Not: {
1455 Type *ValTy = this->getScalarType();
1456 // InstCombine will fold `xor` to the conditional branch.
1457 if (auto *U = const_cast<VPUser *>(getSingleUser()))
1458 if (match(U, m_BranchOnCond(m_VPValue())))
1459 return 0;
1460 if (!vputils::onlyFirstLaneUsed(this))
1461 ValTy = toVectorTy(ValTy, VF);
1462 return Ctx.TTI.getArithmeticInstrCost(Instruction::Xor, ValTy,
1463 Ctx.CostKind);
1464 }
1466 // If TC <= VF then this is just a branch.
1467 // FIXME: Removing the branch happens in simplifyBranchConditionForVFAndUF
1468 // where it checks TC <= VF * UF, but we don't know UF yet. This means in
1469 // some cases we get a cost that's too high due to counting a cmp that
1470 // later gets removed.
1471 // FIXME: The compare could also be removed if TC = M * vscale,
1472 // VF = N * vscale, and M <= N. Detecting that would require having the
1473 // trip count as a SCEV though.
1476 if (TCConst && TCConst->getValue().ule(VF.getKnownMinValue()))
1477 return 0;
1478 // Otherwise BranchOnCount generates ICmpEQ followed by a branch.
1479 Type *ValTy = getOperand(0)->getScalarType();
1480 return Ctx.TTI.getCmpSelInstrCost(Instruction::ICmp, ValTy,
1482 CmpInst::ICMP_EQ, Ctx.CostKind);
1483 }
1484 case Instruction::FCmp:
1485 case Instruction::ICmp:
1487 getOpcode(),
1490 if (VF == ElementCount::getScalable(1))
1492 [[fallthrough]];
1493 default:
1494 // TODO: Compute cost other VPInstructions once the legacy cost model has
1495 // been retired.
1497 "unexpected VPInstruction witht underlying value");
1498 return 0;
1499 }
1500}
1501
1514
1516 switch (getOpcode()) {
1517 case Instruction::Load:
1518 case Instruction::PHI:
1522 return true;
1523 default:
1525 }
1526}
1527
1529#ifndef NDEBUG
1530 Type *Ty = Op->getScalarType();
1531 switch (getOpcode()) {
1535 assert(Ty == getOperand(0)->getScalarType() &&
1536 "types of operand 0 and new operand must match");
1537 break;
1541 assert(Ty == getOperand(0)->getScalarType() &&
1542 "appended operand must match operand 0's scalar type");
1543 break;
1545 assert(Ty == getOperand(1)->getScalarType() &&
1546 "appended operand must match operand 1's scalar type");
1547 break;
1549 // The recipe is constructed with 3 operands (result, data, mask). Extra
1550 // operands beyond that are appended in (data, mask) pairs.
1551 constexpr unsigned NumInitialOperands = 3;
1552 assert(getNumOperands() >= NumInitialOperands &&
1553 "ExtractLastActive must have at least the initial 3 operands");
1554 bool IsMaskSlot = ((getNumOperands() - NumInitialOperands) & 1u) == 1u;
1555 assert((IsMaskSlot ? Ty->isIntegerTy(1)
1556 : Ty == getOperand(1)->getScalarType()) &&
1557 "ExtractLastActive expects alternating data/mask operands "
1558 "matching operand 1's type and i1, respectively");
1559 break;
1560 }
1561 default:
1562 llvm_unreachable("opcode does not support growing the operand list "
1563 "outside of construction");
1564 }
1565#endif
1567}
1568
1570 assert(!isMasked() && "cannot execute masked VPInstruction");
1571 IRBuilderBase::FastMathFlagGuard FMFGuard(State.Builder);
1573 "Set flags not supported for the provided opcode");
1575 "Opcode requires specific flags to be set");
1576 State.Builder.setFastMathFlags(getFastMathFlagsOrNone());
1577 Value *GeneratedValue = generate(State);
1578 if (!hasResult())
1579 return;
1580 assert(GeneratedValue && "generate must produce a value");
1581 bool GeneratesPerFirstLaneOnly = canGenerateScalarForFirstLane() &&
1584 assert((((GeneratedValue->getType()->isVectorTy() ||
1585 GeneratedValue->getType()->isStructTy()) ==
1586 !GeneratesPerFirstLaneOnly) ||
1587 State.VF.isScalar()) &&
1588 "scalar value but not only first lane defined");
1589 State.set(this, GeneratedValue,
1590 /*IsScalar*/ GeneratesPerFirstLaneOnly);
1592 getOpcode() == Instruction::Freeze) {
1593 // FIXME: This is a workaround to enable reliable updates of the scalar loop
1594 // resume phis, and to let epilogue vectorization recover the frozen
1595 // reduction start from the main plan. Must be removed once epilogue
1596 // vectorization explicitly connects VPlans.
1597 setUnderlyingValue(GeneratedValue);
1598 }
1599}
1600
1604 return false;
1605 switch (getOpcode()) {
1606 case Instruction::ExtractValue:
1607 case Instruction::InsertValue:
1608 case Instruction::GetElementPtr:
1609 case Instruction::ExtractElement:
1610 case Instruction::InsertElement:
1611 case Instruction::Freeze:
1612 case Instruction::FCmp:
1613 case Instruction::ICmp:
1614 case Instruction::Select:
1615 case Instruction::PHI:
1641 case VPInstruction::Not:
1649 return false;
1652 AttributeSet Attrs =
1654 return !Attrs.getMemoryEffects().doesNotAccessMemory();
1655 }
1656 case Instruction::Call:
1658 default:
1659 return true;
1660 }
1661}
1662
1664 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
1666 return vputils::onlyFirstLaneUsed(this);
1667
1668 switch (getOpcode()) {
1669 default:
1670 return false;
1671 case Instruction::ExtractElement:
1672 return Op == getOperand(1);
1673 case Instruction::InsertElement:
1674 return Op == getOperand(1) || Op == getOperand(2);
1675 case Instruction::PHI:
1676 return true;
1677 case Instruction::FCmp:
1678 case Instruction::ICmp:
1679 case Instruction::Select:
1680 case Instruction::Or:
1681 case Instruction::Freeze:
1682 case VPInstruction::Not:
1683 // TODO: Cover additional opcodes.
1684 return vputils::onlyFirstLaneUsed(this);
1685 case Instruction::Load:
1697 return true;
1700 // Before replicating by VF, Build(Struct)Vector uses all lanes of the
1701 // operand, after replicating its operands only the first lane is used.
1702 // Before replicating, it will have only a single operand.
1703 return getNumOperands() > 1;
1705 return Op == getOperand(0) || vputils::onlyFirstLaneUsed(this);
1707 // WidePtrAdd supports scalar and vector base addresses.
1708 return false;
1711 return Op == getOperand(0);
1712 };
1713 llvm_unreachable("switch should return");
1714}
1715
1717 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
1719 return vputils::onlyFirstPartUsed(this);
1720
1721 switch (getOpcode()) {
1722 default:
1723 return false;
1724 case Instruction::FCmp:
1725 case Instruction::ICmp:
1726 case Instruction::Select:
1727 return vputils::onlyFirstPartUsed(this);
1732 return true;
1733 };
1734 llvm_unreachable("switch should return");
1735}
1736
1737#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1739 VPSlotTracker SlotTracker(getParent()->getPlan());
1741}
1742
1744 VPSlotTracker &SlotTracker) const {
1745 O << Indent << "EMIT" << (isSingleScalar() ? "-SCALAR" : "") << " ";
1746
1747 if (hasResult()) {
1749 O << " = ";
1750 }
1751
1752 switch (getOpcode()) {
1753 case VPInstruction::Not:
1754 O << "not";
1755 break;
1757 O << "active lane mask";
1758 break;
1760 O << "incoming-alias-mask";
1761 break;
1763 O << "EXPLICIT-VECTOR-LENGTH";
1764 break;
1766 O << "first-order splice";
1767 break;
1769 O << "branch-on-cond";
1770 break;
1772 O << "branch-on-two-conds";
1773 break;
1775 O << "TC > VF ? TC - VF : 0";
1776 break;
1778 O << "VF * Part +";
1779 break;
1781 O << "branch-on-count";
1782 break;
1784 O << "broadcast";
1785 break;
1787 O << "buildstructvector";
1788 break;
1790 O << "buildvector";
1791 break;
1793 O << "exiting-iv-value";
1794 break;
1796 O << "masked-cond";
1797 break;
1799 O << "extract-lane";
1800 break;
1802 O << "extract-last-lane";
1803 break;
1805 O << "extract-last-part";
1806 break;
1808 O << "extract-penultimate-element";
1809 break;
1811 O << "compute-reduction-result";
1812 break;
1814 O << "logical-and";
1815 break;
1817 O << "logical-or";
1818 break;
1820 O << "ptradd";
1821 break;
1823 O << "wide-ptradd";
1824 break;
1826 O << "any-of";
1827 break;
1829 O << "first-active-lane";
1830 break;
1832 O << "last-active-lane";
1833 break;
1835 O << "reduction-start-vector";
1836 break;
1838 O << "resume-for-epilogue";
1839 break;
1841 O << "reverse";
1842 break;
1844 O << "unpack";
1845 break;
1847 O << "extract-last-active";
1848 break;
1850 O << "num-active-lanes";
1851 break;
1852 default:
1854 }
1855
1856 printFlags(O);
1858}
1859#endif
1860
1862 Type *ResultTy = getResultType();
1864 Value *Op = State.get(getOperand(0), VPLane(0));
1865 Value *Cast = State.Builder.CreateCast(Instruction::CastOps(getOpcode()),
1866 Op, ResultTy);
1867 if (auto *CastOp = dyn_cast<Instruction>(Cast)) {
1868 applyFlags(*CastOp);
1869 applyMetadata(*CastOp);
1870 }
1871 State.set(this, Cast, VPLane(0));
1872 return;
1873 }
1874 switch (getOpcode()) {
1876 Value *StepVector =
1877 State.Builder.CreateStepVector(VectorType::get(ResultTy, State.VF));
1878 State.set(this, StepVector);
1879 break;
1880 }
1883 for (VPValue *Op : drop_end(operands()))
1884 Args.push_back(State.get(Op, /*IsSingleScalar=*/true));
1885 Value *Call =
1886 State.Builder.CreateIntrinsic(ResultTy, vputils::getIntrinsicID(this),
1887 Args, /*FMFSource=*/nullptr, getName());
1888 State.set(this, Call, true);
1889 break;
1890 }
1891
1892 default:
1893 llvm_unreachable("opcode not implemented yet");
1894 }
1895}
1896
1898 VPCostContext &Ctx) const {
1899 // NOTE: At the moment it seems only possible to expose this path for
1900 // the trunc, zext and sext opcodes. However, isScalarCast also covers
1901 // int<>fp conversions, bitcasts, ptr<>int conversions, etc.
1904 Ctx);
1905
1906 switch (getOpcode()) {
1908 // TODO: This isn't quite right since even if the step-vector is hoisted
1909 // out of the loop it has a non-zero cost in the middle block, etc.
1910 // Once the stepvector is correctly hoisted out of the vector loop by the
1911 // licm transform we can add the cost here so that it doesn't incorrectly
1912 // affect the choice of VF.
1913 return 0;
1915 Type *Ty = getScalarType();
1917 for (const VPValue *Op : drop_end(operands()))
1918 ArgTys.push_back(Op->getScalarType());
1919 IntrinsicCostAttributes Attrs(vputils::getIntrinsicID(this), Ty, ArgTys);
1920 return Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
1921 }
1922 default:
1923 // Although VPInstructionWithType is also used for
1924 // VPInstruction::WideIVStep it isn't currently possible to expose cases
1925 // where the cost is queried.
1926 llvm_unreachable("Unhandled opcode");
1927 }
1928 return 0;
1929}
1930
1931#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1933 VPSlotTracker &SlotTracker) const {
1934 O << Indent << "EMIT" << (isSingleScalar() ? "-SCALAR" : "") << " ";
1936 O << " = ";
1937
1938 Type *ResultTy = getResultType();
1939 switch (getOpcode()) {
1941 O << "wide-iv-step ";
1943 break;
1945 O << "step-vector " << *ResultTy;
1946 break;
1948 O << "call " << *ResultTy << " @"
1951 Op->printAsOperand(O, SlotTracker);
1952 });
1953 O << ")";
1954 break;
1955 }
1956 case Instruction::Load:
1957 O << "load ";
1959 break;
1960 default:
1961 assert(Instruction::isCast(getOpcode()) && "unhandled opcode");
1963 printFlags(O);
1965 O << " to " << *ResultTy;
1966 }
1967}
1968#endif
1969
1970/// Shared execute logic for VPPhi and VPWidenPHIRecipe. Creates a PHI node,
1971/// adds incoming values, and stores the result in State. For header phis, only
1972/// the preheader incoming value is added; the backedge is fixed up later by
1973/// VPlan::execute().
1975 VPTransformState &State, bool IsScalar,
1976 const Twine &Name) {
1977 unsigned NumIncoming = VPBlockUtils::isHeader(R->getParent(), State.VPDT)
1978 ? 1
1979 : Phi.getNumIncoming();
1980 Value *FirstInc = State.get(Phi.getIncomingValue(0), IsScalar);
1981 PHINode *NewPhi = State.Builder.CreatePHI(FirstInc->getType(), 2, Name);
1982 NewPhi->addIncoming(FirstInc,
1983 State.CFG.VPBB2IRBB.at(Phi.getIncomingBlock(0)));
1984 for (unsigned Idx = 1; Idx != NumIncoming; ++Idx)
1985 NewPhi->addIncoming(State.get(Phi.getIncomingValue(Idx), IsScalar),
1986 State.CFG.VPBB2IRBB.at(Phi.getIncomingBlock(Idx)));
1987 State.set(R, NewPhi, IsScalar);
1988}
1989
1991 executePhiRecipe(this, *this, State, /*IsScalar=*/true, getName());
1992}
1993
1994#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1995void VPPhi::printRecipe(raw_ostream &O, const Twine &Indent,
1996 VPSlotTracker &SlotTracker) const {
1997 O << Indent << "EMIT" << (isSingleScalar() ? "-SCALAR" : "") << " ";
1999 O << " = phi";
2000 printFlags(O);
2002}
2003#endif
2004
2005VPIRInstruction *VPIRInstruction ::create(Instruction &I) {
2006 if (auto *Phi = dyn_cast<PHINode>(&I))
2007 return new VPIRPhi(*Phi);
2008 return new VPIRInstruction(I);
2009}
2010
2012 assert(!isa<VPIRPhi>(this) && getNumOperands() == 0 &&
2013 "PHINodes must be handled by VPIRPhi");
2014 // Advance the insert point after the wrapped IR instruction. This allows
2015 // interleaving VPIRInstructions and other recipes.
2016 State.Builder.SetInsertPoint(I.getParent(), std::next(I.getIterator()));
2017}
2018
2020 VPCostContext &Ctx) const {
2021 // The recipe wraps an existing IR instruction on the border of VPlan's scope,
2022 // hence it does not contribute to the cost-modeling for the VPlan.
2023 return 0;
2024}
2025
2026#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2028 VPSlotTracker &SlotTracker) const {
2029 O << Indent << "IR " << I;
2030}
2031#endif
2032
2034 PHINode *Phi = &getIRPhi();
2035 for (const auto &[Idx, Op] : enumerate(operands())) {
2036 VPValue *ExitValue = Op;
2037 auto Lane = vputils::isSingleScalar(ExitValue)
2039 : VPLane::getLastLaneForVF(State.VF);
2040 VPBlockBase *Pred = getParent()->getPredecessors()[Idx];
2041 auto *PredVPBB = Pred->getExitingBasicBlock();
2042 BasicBlock *PredBB = State.CFG.VPBB2IRBB[PredVPBB];
2043 // Set insertion point in PredBB in case an extract needs to be generated.
2044 // TODO: Model extracts explicitly.
2045 State.Builder.SetInsertPoint(PredBB->getTerminator());
2046 Value *V = State.get(ExitValue, VPLane(Lane));
2047 // If there is no existing block for PredBB in the phi, add a new incoming
2048 // value. Otherwise update the existing incoming value for PredBB.
2049 if (Phi->getBasicBlockIndex(PredBB) == -1)
2050 Phi->addIncoming(V, PredBB);
2051 else
2052 Phi->setIncomingValueForBlock(PredBB, V);
2053 }
2054
2055 // Advance the insert point after the wrapped IR instruction. This allows
2056 // interleaving VPIRInstructions and other recipes.
2057 State.Builder.SetInsertPoint(Phi->getParent(), std::next(Phi->getIterator()));
2058}
2059
2061 VPRecipeBase *R = const_cast<VPRecipeBase *>(getAsRecipe());
2062 assert(R->getNumOperands() == R->getParent()->getNumPredecessors() &&
2063 "Number of phi operands must match number of predecessors");
2064 unsigned Position = R->getParent()->getIndexForPredecessor(IncomingBlock);
2065 R->removeOperand(Position);
2066}
2067
2068VPValue *
2070 VPRecipeBase *R = const_cast<VPRecipeBase *>(getAsRecipe());
2071 return getIncomingValue(R->getParent()->getIndexForPredecessor(VPBB));
2072}
2073
2075 VPValue *V) const {
2076 VPRecipeBase *R = const_cast<VPRecipeBase *>(getAsRecipe());
2077 R->setOperand(R->getParent()->getIndexForPredecessor(VPBB), V);
2078}
2079
2080#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2082 VPSlotTracker &SlotTracker) const {
2084 O << "[ ";
2085 std::get<0>(Op)->printAsOperand(O, SlotTracker);
2086 O << ", ";
2087 std::get<1>(Op)->printAsOperand(O);
2088 O << " ]";
2089 });
2090}
2091#endif
2092
2093#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2095 VPSlotTracker &SlotTracker) const {
2097
2098 if (getNumOperands() != 0) {
2099 O << " (extra operand" << (getNumOperands() > 1 ? "s" : "") << ": ";
2101 [&O, &SlotTracker](auto Op) {
2102 std::get<0>(Op)->printAsOperand(O, SlotTracker);
2103 O << " from ";
2104 std::get<1>(Op)->printAsOperand(O);
2105 });
2106 O << ")";
2107 }
2108}
2109#endif
2110
2112 for (const auto &[Kind, Node] : Metadata)
2113 I.setMetadata(Kind, Node);
2114}
2115
2117 SmallVector<std::pair<unsigned, MDNode *>> MetadataIntersection;
2118 for (const auto &[KindA, MDA] : Metadata) {
2119 for (const auto &[KindB, MDB] : Other.Metadata) {
2120 if (KindA == KindB && MDA == MDB) {
2121 MetadataIntersection.emplace_back(KindA, MDA);
2122 break;
2123 }
2124 }
2125 }
2126 Metadata = std::move(MetadataIntersection);
2127}
2128
2129#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2131 const Module *M = SlotTracker.getModule();
2132 if (Metadata.empty() || !M || !VPlanPrintMetadata)
2133 return;
2134
2135 ArrayRef<StringRef> MDNames = SlotTracker.getMDNames();
2136 O << " (";
2137 interleaveComma(Metadata, O, [&](const auto &KindNodePair) {
2138 auto [Kind, Node] = KindNodePair;
2139 assert(Kind < MDNames.size() && !MDNames[Kind].empty() &&
2140 "Unexpected unnamed metadata kind");
2141 O << "!" << MDNames[Kind] << " ";
2142 Node->printAsOperand(O, M);
2143 });
2144 O << ")";
2145}
2146#endif
2147
2149 assert(State.VF.isVector() && "not widening");
2150 assert(Variant != nullptr && "Can't create vector function.");
2151
2152 FunctionType *VFTy = Variant->getFunctionType();
2153 // Add return type if intrinsic is overloaded on it.
2155 for (const auto &I : enumerate(args())) {
2156 Value *Arg;
2157 // Some vectorized function variants may also take a scalar argument,
2158 // e.g. linear parameters for pointers. This needs to be the scalar value
2159 // from the start of the respective part when interleaving.
2160 if (!VFTy->getParamType(I.index())->isVectorTy())
2161 Arg = State.get(I.value(), VPLane(0));
2162 else
2163 Arg = State.get(I.value(), usesFirstLaneOnly(I.value()));
2164 Args.push_back(Arg);
2165 }
2166
2169 if (CI)
2170 CI->getOperandBundlesAsDefs(OpBundles);
2171
2172 CallInst *V = State.Builder.CreateCall(Variant, Args, OpBundles);
2173 applyFlags(*V);
2174 applyMetadata(*V);
2175 V->setCallingConv(Variant->getCallingConv());
2176
2177 if (!V->getType()->isVoidTy())
2178 State.set(this, V);
2179}
2180
2182 VPCostContext &Ctx) const {
2183 assert(getVectorizedTypeVF(Variant->getReturnType()) == VF &&
2184 "Variant return type must match VF");
2185 return computeCallCost(Variant, Ctx);
2186}
2187
2189 VPCostContext &Ctx) {
2190 return Ctx.TTI.getCallInstrCost(nullptr, Variant->getReturnType(),
2191 Variant->getFunctionType()->params(),
2192 Ctx.CostKind);
2193}
2194
2196 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
2197 assert(Variant && "Variant not set");
2198 FunctionType *VFTy = Variant->getFunctionType();
2199 return all_of(enumerate(args()), [VFTy, &Op](const auto &Arg) {
2200 auto [Idx, V] = Arg;
2201 Type *ArgTy = VFTy->getParamType(Idx);
2202 return V != Op || ArgTy->isIntegerTy() || ArgTy->isFloatingPointTy() ||
2203 ArgTy->isPointerTy() || ArgTy->isByteTy();
2204 });
2205}
2206
2207#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2209 VPSlotTracker &SlotTracker) const {
2210 O << Indent << "WIDEN-CALL ";
2211
2212 Function *CalledFn = getCalledScalarFunction();
2213 if (CalledFn->getReturnType()->isVoidTy())
2214 O << "void ";
2215 else {
2217 O << " = ";
2218 }
2219
2220 O << "call";
2221 printFlags(O);
2222 O << "@" << CalledFn->getName() << "(";
2223 interleaveComma(args(), O, [&O, &SlotTracker](VPValue *Op) {
2224 Op->printAsOperand(O, SlotTracker);
2225 });
2226 O << ")";
2227
2228 O << " (using library function";
2229 if (Variant->hasName())
2230 O << ": " << Variant->getName();
2231 O << ")";
2232}
2233#endif
2234
2236 assert(State.VF.isVector() && "not widening");
2237
2238 SmallVector<Type *, 2> TysForDecl;
2239 // Add return type if intrinsic is overloaded on it.
2240 if (isVectorIntrinsicWithOverloadTypeAtArg(VectorIntrinsicID, -1,
2241 State.TTI)) {
2242 Type *RetTy = toVectorizedTy(getScalarType(), State.VF);
2243 ArrayRef<Type *> ContainedTys = getContainedTypes(RetTy);
2244 for (auto [Idx, Ty] : enumerate(ContainedTys)) {
2246 Idx, State.TTI))
2247 TysForDecl.push_back(Ty);
2248 }
2249 }
2251 for (const auto &I : enumerate(operands())) {
2252 // Some intrinsics have a scalar argument - don't replace it with a
2253 // vector.
2254 Value *Arg;
2255 if (isVectorIntrinsicWithScalarOpAtArg(VectorIntrinsicID, I.index(),
2256 State.TTI))
2257 Arg = State.get(I.value(), VPLane(0));
2258 else
2259 Arg = State.get(I.value(), usesFirstLaneOnly(I.value()));
2260 if (isVectorIntrinsicWithOverloadTypeAtArg(VectorIntrinsicID, I.index(),
2261 State.TTI))
2262 TysForDecl.push_back(Arg->getType());
2263 Args.push_back(Arg);
2264 }
2265
2266 // Use vector version of the intrinsic.
2267 Module *M = State.Builder.GetInsertBlock()->getModule();
2268 Function *VectorF =
2269 Intrinsic::getOrInsertDeclaration(M, VectorIntrinsicID, TysForDecl);
2270 assert(VectorF &&
2271 "Can't retrieve vector intrinsic or vector-predication intrinsics.");
2272
2275 if (CI)
2276 CI->getOperandBundlesAsDefs(OpBundles);
2277
2278 CallInst *V = State.Builder.CreateCall(VectorF, Args, OpBundles);
2279
2280 applyFlags(*V);
2281 applyMetadata(*V);
2282
2283 return V;
2284}
2285
2287 CallInst *V = createVectorCall(State);
2288 if (!V->getType()->isVoidTy())
2289 State.set(this, V);
2290}
2291
2294 const VPRecipeWithIRFlags &R, ElementCount VF, VPCostContext &Ctx) {
2295 Type *ScalarRetTy = R.getScalarType();
2296 // Skip the reverse operation cost for the mask.
2297 // FIXME: Remove this once redundant mask reverse operations can be eliminated
2298 // by VPlanTransforms::cse before cost computation.
2299 if (ID == Intrinsic::experimental_vp_reverse && ScalarRetTy->isIntegerTy(1))
2300 return InstructionCost(0);
2301
2302 // Some backends analyze intrinsic arguments to determine cost. Use the
2303 // underlying value for the operand if it has one. Otherwise try to use the
2304 // operand of the underlying call instruction, if there is one. Otherwise
2305 // clear Arguments.
2306 // TODO: Rework TTI interface to be independent of concrete IR values.
2308 for (const auto &[Idx, Op] : enumerate(Operands)) {
2309 auto *V = Op->getUnderlyingValue();
2310 if (!V) {
2311 if (auto *UI = dyn_cast_or_null<CallBase>(R.getUnderlyingValue())) {
2312 Arguments.push_back(UI->getArgOperand(Idx));
2313 continue;
2314 }
2315 Arguments.clear();
2316 break;
2317 }
2318 Arguments.push_back(V);
2319 }
2320
2321 Type *RetTy = VF.isVector() ? toVectorizedTy(ScalarRetTy, VF) : ScalarRetTy;
2322 SmallVector<Type *> ParamTys =
2323 map_to_vector(Operands, [&](const VPValue *Op) {
2324 return toVectorTy(Op->getScalarType(), VF);
2325 });
2326
2328 for (const VPValue *Op : Operands)
2329 if (isa<VPWidenRecipe>(Op) &&
2332 break;
2333 }
2334
2335 // TODO: Rework TTI interface to avoid reliance on underlying IntrinsicInst.
2336 IntrinsicCostAttributes CostAttrs(
2337 ID, RetTy, Arguments, ParamTys, R.getFastMathFlagsOrNone(),
2338 dyn_cast_or_null<IntrinsicInst>(R.getUnderlyingValue()),
2340 return Ctx.TTI.getIntrinsicInstrCost(CostAttrs, Ctx.CostKind);
2341}
2342
2344 VPCostContext &Ctx) const {
2345 return computeCallCost(VectorIntrinsicID, operands(), *this, VF, Ctx);
2346}
2347
2349 return Intrinsic::getBaseName(VectorIntrinsicID);
2350}
2351
2353 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
2354 return all_of(enumerate(operands()), [this, &Op](const auto &X) {
2355 auto [Idx, V] = X;
2357 Idx, nullptr);
2358 });
2359}
2360
2361#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2363 VPSlotTracker &SlotTracker) const {
2364 O << Indent << "WIDEN-INTRINSIC ";
2365 if (getScalarType()->isVoidTy()) {
2366 O << "void ";
2367 } else {
2369 O << " = ";
2370 }
2371
2372 O << "call";
2373 printFlags(O);
2374 O << getIntrinsicName() << "(";
2376 O << ")";
2377}
2378#endif
2379
2381 CallInst *MemI = createVectorCall(State);
2382 MemI->addParamAttr(
2383 0, Attribute::getWithAlignment(MemI->getContext(), Alignment));
2384 State.set(this, MemI);
2385}
2386
2388 Intrinsic::ID IID, Type *Ty, bool IsMasked, Align Alignment,
2389 VPCostContext &Ctx) {
2390 return Ctx.TTI.getMemIntrinsicInstrCost(
2391 MemIntrinsicCostAttributes(IID, Ty, /*Ptr=*/nullptr, IsMasked, Alignment),
2392 Ctx.CostKind);
2393}
2394
2397 VPCostContext &Ctx) const {
2398 Type *Ty = toVectorTy(getScalarType(), VF);
2400 !match(getOperand(2), m_True()), Alignment,
2401 Ctx);
2402}
2403
2405 IRBuilderBase &Builder = State.Builder;
2406
2407 Value *Address = State.get(getOperand(0));
2408 Value *IncAmt = State.get(getOperand(1), /*IsScalar=*/true);
2409 VectorType *VTy = cast<VectorType>(Address->getType());
2410
2411 // The histogram intrinsic requires a mask even if the recipe doesn't;
2412 // if the mask operand was omitted then all lanes should be executed and
2413 // we just need to synthesize an all-true mask.
2414 Value *Mask = nullptr;
2415 if (VPValue *VPMask = getMask())
2416 Mask = State.get(VPMask);
2417 else
2418 Mask =
2419 Builder.CreateVectorSplat(VTy->getElementCount(), Builder.getInt1(1));
2420
2421 // If this is a subtract, we want to invert the increment amount. We may
2422 // add a separate intrinsic in future, but for now we'll try this.
2423 if (Opcode == Instruction::Sub)
2424 IncAmt = Builder.CreateNeg(IncAmt);
2425 else
2426 assert(Opcode == Instruction::Add && "only add or sub supported for now");
2427
2428 Instruction *HistogramInst = State.Builder.CreateIntrinsicWithoutFolding(
2429 Intrinsic::experimental_vector_histogram_add, {VTy, IncAmt->getType()},
2430 {Address, IncAmt, Mask});
2431 applyMetadata(*HistogramInst);
2432}
2433
2435 VPCostContext &Ctx) const {
2436 // FIXME: Take the gather and scatter into account as well. For now we're
2437 // generating the same cost as the fallback path, but we'll likely
2438 // need to create a new TTI method for determining the cost, including
2439 // whether we can use base + vec-of-smaller-indices or just
2440 // vec-of-pointers.
2441 assert(VF.isVector() && "Invalid VF for histogram cost");
2442 Type *AddressTy = getOperand(0)->getScalarType();
2443 VPValue *IncAmt = getOperand(1);
2444 Type *IncTy = IncAmt->getScalarType();
2445 VectorType *VTy = VectorType::get(IncTy, VF);
2446
2447 // Assume that a non-constant update value (or a constant != 1) requires
2448 // a multiply, and add that into the cost.
2449 InstructionCost MulCost =
2450 Ctx.TTI.getArithmeticInstrCost(Instruction::Mul, VTy, Ctx.CostKind);
2451 if (match(IncAmt, m_One()))
2452 MulCost = TTI::TCC_Free;
2453
2454 // Find the cost of the histogram operation itself.
2455 Type *PtrTy = VectorType::get(AddressTy, VF);
2456 Type *MaskTy = VectorType::get(Type::getInt1Ty(Ctx.LLVMCtx), VF);
2457 IntrinsicCostAttributes ICA(Intrinsic::experimental_vector_histogram_add,
2458 Type::getVoidTy(Ctx.LLVMCtx),
2459 {PtrTy, IncTy, MaskTy});
2460
2461 // Add the costs together with the add/sub operation.
2462 return Ctx.TTI.getIntrinsicInstrCost(ICA, Ctx.CostKind) + MulCost +
2463 Ctx.TTI.getArithmeticInstrCost(Opcode, VTy, Ctx.CostKind);
2464}
2465
2466#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2468 VPSlotTracker &SlotTracker) const {
2469 O << Indent << "WIDEN-HISTOGRAM buckets: ";
2471
2472 if (Opcode == Instruction::Sub)
2473 O << ", dec: ";
2474 else {
2475 assert(Opcode == Instruction::Add);
2476 O << ", inc: ";
2477 }
2479
2480 if (VPValue *Mask = getMask()) {
2481 O << ", mask: ";
2482 Mask->printAsOperand(O, SlotTracker);
2483 }
2484}
2485#endif
2486
2487VPIRFlags::FastMathFlagsTy::FastMathFlagsTy(const FastMathFlags &FMF) {
2488 AllowReassoc = FMF.allowReassoc();
2489 NoNaNs = FMF.noNaNs();
2490 NoInfs = FMF.noInfs();
2491 NoSignedZeros = FMF.noSignedZeros();
2492 AllowReciprocal = FMF.allowReciprocal();
2493 AllowContract = FMF.allowContract();
2494 ApproxFunc = FMF.approxFunc();
2495}
2496
2497VPIRFlags VPIRFlags::getDefaultFlags(unsigned Opcode, Type *ResultTy) {
2498 switch (Opcode) {
2499 case Instruction::Add:
2500 case Instruction::Sub:
2501 case Instruction::Mul:
2502 case Instruction::Shl:
2504 return WrapFlagsTy(false, false);
2505 case Instruction::Trunc:
2506 return TruncFlagsTy(false, false);
2507 case Instruction::Or:
2508 return DisjointFlagsTy(false);
2509 case Instruction::AShr:
2510 case Instruction::LShr:
2511 case Instruction::UDiv:
2512 case Instruction::SDiv:
2513 return ExactFlagsTy(false);
2514 case Instruction::GetElementPtr:
2517 return GEPNoWrapFlags::none();
2518 case Instruction::ZExt:
2519 case Instruction::UIToFP:
2520 return NonNegFlagsTy(false);
2521 case Instruction::FAdd:
2522 case Instruction::FSub:
2523 case Instruction::FMul:
2524 case Instruction::FDiv:
2525 case Instruction::FRem:
2526 case Instruction::FNeg:
2527 case Instruction::FPExt:
2528 case Instruction::FPTrunc:
2529 return FastMathFlags();
2530 case Instruction::Select:
2531 // Selects only have fast-math flags if they produce a floating-point value.
2532 if (ResultTy && FPMathOperator::isSupportedFloatingPointType(ResultTy))
2533 return FastMathFlags();
2534 return VPIRFlags();
2535 case Instruction::ICmp:
2536 case Instruction::FCmp:
2538 llvm_unreachable("opcode requires explicit flags");
2539 default:
2540 return VPIRFlags();
2541 }
2542}
2543
2544#if !defined(NDEBUG)
2545bool VPIRFlags::flagsValidForOpcode(unsigned Opcode) const {
2546 switch (OpType) {
2547 case OperationType::OverflowingBinOp:
2548 return Opcode == Instruction::Add || Opcode == Instruction::Sub ||
2549 Opcode == Instruction::Mul || Opcode == Instruction::Shl ||
2550 Opcode == VPInstruction::VPInstruction::CanonicalIVIncrementForPart;
2551 case OperationType::Trunc:
2552 return Opcode == Instruction::Trunc;
2553 case OperationType::DisjointOp:
2554 return Opcode == Instruction::Or;
2555 case OperationType::PossiblyExactOp:
2556 return Opcode == Instruction::AShr || Opcode == Instruction::LShr ||
2557 Opcode == Instruction::UDiv || Opcode == Instruction::SDiv;
2558 case OperationType::GEPOp:
2559 return Opcode == Instruction::GetElementPtr ||
2560 Opcode == VPInstruction::PtrAdd ||
2561 Opcode == VPInstruction::WidePtrAdd;
2562 case OperationType::FPMathOp:
2563 return Opcode == Instruction::Call || Opcode == Instruction::FAdd ||
2564 Opcode == Instruction::FMul || Opcode == Instruction::FSub ||
2565 Opcode == Instruction::FNeg || Opcode == Instruction::FDiv ||
2566 Opcode == Instruction::FRem || Opcode == Instruction::FPExt ||
2567 Opcode == Instruction::FPTrunc || Opcode == Instruction::PHI ||
2568 Opcode == Instruction::Select || Opcode == Instruction::SIToFP ||
2569 Opcode == Instruction::UIToFP ||
2570 Opcode == VPInstruction::WideIVStep ||
2572 case OperationType::FCmp:
2573 return Opcode == Instruction::FCmp;
2574 case OperationType::NonNegOp:
2575 return Opcode == Instruction::ZExt || Opcode == Instruction::UIToFP;
2576 case OperationType::Cmp:
2577 return Opcode == Instruction::FCmp || Opcode == Instruction::ICmp;
2578 case OperationType::ReductionOp:
2580 case OperationType::Other:
2581 return true;
2582 }
2583 llvm_unreachable("Unknown OperationType enum");
2584}
2585
2586bool VPIRFlags::hasRequiredFlagsForOpcode(unsigned Opcode) const {
2587 // Handle opcodes without default flags.
2588 if (Opcode == Instruction::ICmp)
2589 return OpType == OperationType::Cmp;
2590 if (Opcode == Instruction::FCmp)
2591 return OpType == OperationType::FCmp;
2593 return OpType == OperationType::ReductionOp;
2594
2595 OperationType Required = getDefaultFlags(Opcode).OpType;
2596 return Required == OperationType::Other || Required == OpType;
2597}
2598#endif
2599
2600#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2601static void printRecurrenceKind(raw_ostream &OS, const RecurKind &Kind) {
2602 switch (Kind) {
2603 case RecurKind::None:
2604 OS << "none";
2605 break;
2606 case RecurKind::Add:
2607 OS << "add";
2608 break;
2609 case RecurKind::Sub:
2610 OS << "sub";
2611 break;
2613 OS << "add-chain-with-subs";
2614 break;
2615 case RecurKind::Mul:
2616 OS << "mul";
2617 break;
2618 case RecurKind::Or:
2619 OS << "or";
2620 break;
2621 case RecurKind::And:
2622 OS << "and";
2623 break;
2624 case RecurKind::Xor:
2625 OS << "xor";
2626 break;
2627 case RecurKind::SMin:
2628 OS << "smin";
2629 break;
2630 case RecurKind::SMax:
2631 OS << "smax";
2632 break;
2633 case RecurKind::UMin:
2634 OS << "umin";
2635 break;
2636 case RecurKind::UMax:
2637 OS << "umax";
2638 break;
2639 case RecurKind::FAdd:
2640 OS << "fadd";
2641 break;
2643 OS << "fadd-chain-with-subs";
2644 break;
2645 case RecurKind::FSub:
2646 OS << "fsub";
2647 break;
2648 case RecurKind::FMul:
2649 OS << "fmul";
2650 break;
2651 case RecurKind::FMin:
2652 OS << "fmin";
2653 break;
2654 case RecurKind::FMax:
2655 OS << "fmax";
2656 break;
2657 case RecurKind::FMinNum:
2658 OS << "fminnum";
2659 break;
2660 case RecurKind::FMaxNum:
2661 OS << "fmaxnum";
2662 break;
2664 OS << "fminimum";
2665 break;
2667 OS << "fmaximum";
2668 break;
2670 OS << "fminimumnum";
2671 break;
2673 OS << "fmaximumnum";
2674 break;
2675 case RecurKind::FMulAdd:
2676 OS << "fmuladd";
2677 break;
2678 case RecurKind::AnyOf:
2679 OS << "any-of";
2680 break;
2681 case RecurKind::FindIV:
2682 OS << "find-iv";
2683 break;
2685 OS << "find-last";
2686 break;
2687 }
2688}
2689
2691 switch (OpType) {
2692 case OperationType::Cmp:
2694 break;
2695 case OperationType::FCmp:
2698 break;
2699 case OperationType::DisjointOp:
2700 if (DisjointFlags.IsDisjoint)
2701 O << " disjoint";
2702 break;
2703 case OperationType::PossiblyExactOp:
2704 if (ExactFlags.IsExact)
2705 O << " exact";
2706 break;
2707 case OperationType::OverflowingBinOp:
2708 if (WrapFlags.HasNUW)
2709 O << " nuw";
2710 if (WrapFlags.HasNSW)
2711 O << " nsw";
2712 break;
2713 case OperationType::Trunc:
2714 if (TruncFlags.HasNUW)
2715 O << " nuw";
2716 if (TruncFlags.HasNSW)
2717 O << " nsw";
2718 break;
2719 case OperationType::FPMathOp:
2721 break;
2722 case OperationType::GEPOp: {
2724 if (Flags.isInBounds())
2725 O << " inbounds";
2726 else if (Flags.hasNoUnsignedSignedWrap())
2727 O << " nusw";
2728 if (Flags.hasNoUnsignedWrap())
2729 O << " nuw";
2730 break;
2731 }
2732 case OperationType::NonNegOp:
2733 if (NonNegFlags.NonNeg)
2734 O << " nneg";
2735 break;
2736 case OperationType::ReductionOp: {
2737 O << " (";
2739 if (isReductionInLoop())
2740 O << ", in-loop";
2741 if (isReductionOrdered())
2742 O << ", ordered";
2743 O << ")";
2745 break;
2746 }
2747 case OperationType::Other:
2748 break;
2749 }
2750 O << " ";
2751}
2752#endif
2753
2755 auto &Builder = State.Builder;
2756 switch (Opcode) {
2757 case Instruction::Call:
2758 case Instruction::UncondBr:
2759 case Instruction::CondBr:
2760 case Instruction::PHI:
2761 case Instruction::GetElementPtr:
2762 llvm_unreachable("This instruction is handled by a different recipe.");
2763 case Instruction::UDiv:
2764 case Instruction::SDiv:
2765 case Instruction::SRem:
2766 case Instruction::URem:
2767 case Instruction::Add:
2768 case Instruction::FAdd:
2769 case Instruction::Sub:
2770 case Instruction::FSub:
2771 case Instruction::FNeg:
2772 case Instruction::Mul:
2773 case Instruction::FMul:
2774 case Instruction::FDiv:
2775 case Instruction::FRem:
2776 case Instruction::Shl:
2777 case Instruction::LShr:
2778 case Instruction::AShr:
2779 case Instruction::And:
2780 case Instruction::Or:
2781 case Instruction::Xor: {
2782 // Just widen unops and binops.
2784 for (VPValue *VPOp : operands())
2785 Ops.push_back(State.get(VPOp));
2786
2787 Value *V = Builder.CreateNAryOp(Opcode, Ops);
2788
2789 if (auto *VecOp = dyn_cast<Instruction>(V)) {
2790 applyFlags(*VecOp);
2791 applyMetadata(*VecOp);
2792 }
2793
2794 // Use this vector value for all users of the original instruction.
2795 State.set(this, V);
2796 break;
2797 }
2798 case Instruction::ExtractValue: {
2799 assert(getNumOperands() == 2 && "expected single level extractvalue");
2800 Value *Op = State.get(getOperand(0));
2801 Value *Extract = Builder.CreateExtractValue(
2802 Op, cast<VPConstantInt>(getOperand(1))->getZExtValue());
2803 State.set(this, Extract);
2804 break;
2805 }
2806 case Instruction::Freeze: {
2807 Value *Op = State.get(getOperand(0));
2808 Value *Freeze = Builder.CreateFreeze(Op);
2809 State.set(this, Freeze);
2810 break;
2811 }
2812 case Instruction::ICmp:
2813 case Instruction::FCmp: {
2814 // Widen compares. Generate vector compares.
2815 bool FCmp = Opcode == Instruction::FCmp;
2816 Value *A = State.get(getOperand(0));
2817 Value *B = State.get(getOperand(1));
2818 Value *C = nullptr;
2819 if (FCmp) {
2820 C = Builder.CreateFCmp(getPredicate(), A, B);
2821 } else {
2822 C = Builder.CreateICmp(getPredicate(), A, B);
2823 }
2824 if (auto *I = dyn_cast<Instruction>(C)) {
2825 applyFlags(*I);
2826 applyMetadata(*I);
2827 }
2828 State.set(this, C);
2829 break;
2830 }
2831 case Instruction::Select: {
2832 VPValue *CondOp = getOperand(0);
2833 Value *Cond = State.get(CondOp, vputils::isSingleScalar(CondOp));
2834 Value *Op0 = State.get(getOperand(1));
2835 Value *Op1 = State.get(getOperand(2));
2836 Value *Sel = State.Builder.CreateSelect(Cond, Op0, Op1);
2837 State.set(this, Sel);
2838 if (auto *I = dyn_cast<Instruction>(Sel)) {
2840 applyFlags(*I);
2841 applyMetadata(*I);
2842 }
2843 break;
2844 }
2845 default:
2846 // This instruction is not vectorized by simple widening.
2847 LLVM_DEBUG(dbgs() << "LV: Found an unhandled opcode : "
2848 << Instruction::getOpcodeName(Opcode));
2849 llvm_unreachable("Unhandled instruction!");
2850 } // end of switch.
2851
2852#if !defined(NDEBUG)
2853 // Verify that VPlan type inference results agree with the type of the
2854 // generated values.
2855 assert(VectorType::get(this->getScalarType(), State.VF) ==
2856 State.get(this)->getType() &&
2857 "inferred type and type from generated instructions do not match");
2858#endif
2859}
2860
2862 VPCostContext &Ctx) const {
2863 switch (Opcode) {
2864 case Instruction::UDiv:
2865 case Instruction::SDiv:
2866 case Instruction::SRem:
2867 case Instruction::URem:
2868 // If the div/rem operation isn't safe to speculate and requires
2869 // predication, then the only way we can even create a vplan is to insert
2870 // a select on the second input operand to ensure we use the value of 1
2871 // for the inactive lanes. The select will be costed separately.
2872 case Instruction::FNeg:
2873 case Instruction::Add:
2874 case Instruction::FAdd:
2875 case Instruction::Sub:
2876 case Instruction::FSub:
2877 case Instruction::Mul:
2878 case Instruction::FMul:
2879 case Instruction::FDiv:
2880 case Instruction::FRem:
2881 case Instruction::Shl:
2882 case Instruction::LShr:
2883 case Instruction::AShr:
2884 case Instruction::And:
2885 case Instruction::Or:
2886 case Instruction::Xor:
2887 case Instruction::Freeze:
2888 case Instruction::ExtractValue:
2889 case Instruction::ICmp:
2890 case Instruction::FCmp:
2891 case Instruction::Select:
2892 return getCostForRecipeWithOpcode(getOpcode(), VF, Ctx);
2893 default:
2894 llvm_unreachable("Unsupported opcode for instruction");
2895 }
2896}
2897
2898#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2900 VPSlotTracker &SlotTracker) const {
2901 O << Indent << "WIDEN ";
2903 O << " = " << Instruction::getOpcodeName(Opcode);
2904 printFlags(O);
2906}
2907#endif
2908
2910 auto &Builder = State.Builder;
2911 /// Vectorize casts.
2912 assert(State.VF.isVector() && "Not vectorizing?");
2913 Type *DestTy = VectorType::get(getScalarType(), State.VF);
2914 VPValue *Op = getOperand(0);
2915 Value *A = State.get(Op);
2916 Value *Cast = Builder.CreateCast(Instruction::CastOps(Opcode), A, DestTy);
2917 State.set(this, Cast);
2918 if (auto *CastOp = dyn_cast<Instruction>(Cast)) {
2919 applyFlags(*CastOp);
2920 applyMetadata(*CastOp);
2921 }
2922}
2923
2928
2929#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2931 VPSlotTracker &SlotTracker) const {
2932 O << Indent << "WIDEN-CAST ";
2934 O << " = " << Instruction::getOpcodeName(Opcode);
2935 printFlags(O);
2937 O << " to " << *getScalarType();
2938}
2939#endif
2940
2942 VPCostContext &Ctx) const {
2943 return Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
2944}
2945
2946#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2948 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
2949 O << Indent;
2951 O << " = WIDEN-INDUCTION";
2952 printFlags(O);
2954
2955 if (auto *TI = getTruncInst())
2956 O << " (truncated to " << *TI->getType() << ")";
2957}
2958#endif
2959
2961 // The step may be defined by a recipe in the preheader (e.g. if it requires
2962 // SCEV expansion), but for the canonical induction the step is required to be
2963 // 1, which is represented as live-in.
2964 return match(getStartValue(), m_ZeroInt()) &&
2965 match(getStepValue(), m_One()) &&
2966 getScalarType() == getRegion()->getCanonicalIVType();
2967}
2968
2971 VPCostContext &Ctx) const {
2972 // A widened induction generates a vector phi and increments it by the
2973 // splatted step each iteration.
2975 InstructionCost Cost = Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
2976 Type *StepTy = getScalarType();
2977 unsigned IncOpc = ID.getKind() == InductionDescriptor::IK_IntInduction
2978 ? Instruction::Add
2979 : ID.getInductionOpcode();
2980 assert(IncOpc != Instruction::BinaryOpsEnd &&
2981 "induction must have a valid increment opcode");
2982 return Cost + Ctx.TTI.getArithmeticInstrCost(IncOpc, toVectorTy(StepTy, VF),
2983 Ctx.CostKind);
2984}
2985
2987 VPCostContext &Ctx) const {
2988 // The cost model for this is modelled on expandVPDerivedIV in
2989 // VPlanTransforms.cpp. In order to avoid overly pessimistic costs that can
2990 // negatively affect vectorization it takes into account any expected
2991 // simplifications that happen in simplifyRecipe.
2992 switch (getInductionKind()) {
2993 default:
2994 // TODO: Compute cost for remaining kinds.
2995 break;
2997 // There are currently no tests that expose a path where all lanes are
2998 // used, so it's better to bail out for now.
2999 if (!vputils::onlyFirstLaneUsed(this))
3000 break;
3001
3002 // Start off by assuming we need both mul and add, then refine this.
3003 bool NeedsMul = true, NeedsAdd = true, NeedsShl = false;
3004
3005 // If the start value is zero the add gets folded away.
3006 if (auto *StartC = dyn_cast<VPConstantInt>(getStartValue()))
3007 NeedsAdd = !StartC->isZero();
3008
3009 // For some values of step the arithmetic changes:
3010 // 1. A step of 1 requires no operation.
3011 // 2. A step of -1 requires a negate.
3012 // 3. A power-of-2 step will use a shl, instead of a mul.
3013 Type *StepTy = getStepValue()->getScalarType();
3015 if (auto *StepC = dyn_cast<VPConstantInt>(getStepValue())) {
3016 if (StepC->isOne())
3017 NeedsMul = false;
3018 else if (StepC->getAPInt().isAllOnes()) {
3019 // This will most likely end up as a negate in simplifyRecipe, and
3020 // the negate will be combined with the add to make a sub.
3021 // NOTE: This is perhaps an invalid assumption that the cost of an
3022 // 'add' is the same as a 'sub'.
3023 NeedsMul = false;
3024 NeedsAdd = true;
3025 } else if (StepC->getAPInt().isPowerOf2()) {
3026 // This will most likely end up as a shift-left in simplifyRecipe
3027 NeedsMul = false;
3028 NeedsShl = true;
3029 }
3030 }
3031
3032 // Add the cost of the conversion from index to step type if the index
3033 // will be used.
3034 Type *IndexTy = getIndex()->getScalarType();
3035 unsigned StepTySize = StepTy->getScalarSizeInBits();
3036 unsigned IndexTySize = IndexTy->getScalarSizeInBits();
3037 if ((NeedsAdd || NeedsMul || NeedsShl) && StepTySize != IndexTySize) {
3038 unsigned CastOpc =
3039 StepTySize < IndexTySize ? Instruction::Trunc : Instruction::ZExt;
3040 Cost += Ctx.TTI.getCastInstrCost(
3041 CastOpc, StepTy, IndexTy, TTI::CastContextHint::None, Ctx.CostKind);
3042 }
3043
3044 if (NeedsMul)
3045 Cost += Ctx.TTI.getArithmeticInstrCost(Instruction::Mul, StepTy,
3046 Ctx.CostKind);
3047 if (NeedsShl)
3048 Cost += Ctx.TTI.getArithmeticInstrCost(
3049 Instruction::Shl, StepTy, Ctx.CostKind,
3050 {TargetTransformInfo::OK_AnyValue, TargetTransformInfo::OP_None},
3051 {TargetTransformInfo::OK_UniformConstantValue,
3052 TargetTransformInfo::OP_None});
3053 if (NeedsAdd)
3054 Cost += Ctx.TTI.getArithmeticInstrCost(Instruction::Add, StepTy,
3055 Ctx.CostKind);
3056 return Cost;
3057 }
3058 }
3059
3060 return 0;
3061}
3062
3063#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3065 VPSlotTracker &SlotTracker) const {
3066 O << Indent;
3068 O << " = DERIVED-IV";
3069 printFlags(O);
3070 getStartValue()->printAsOperand(O, SlotTracker);
3071 O << " + ";
3072 getOperand(1)->printAsOperand(O, SlotTracker);
3073 O << " * ";
3074 getStepValue()->printAsOperand(O, SlotTracker);
3075}
3076#endif
3077
3081
3083 VPCostContext &Ctx) const {
3084 // TODO: Add costs for floating point.
3085 Type *BaseIVTy = getOperand(0)->getScalarType();
3086 if (!BaseIVTy->isIntegerTy())
3087 return 0;
3088
3089 // TODO: Add support for predicated regions. Requires scaling the cost by the
3090 // probability of entering the block.
3091 if (getRegion() && getRegion()->isReplicator())
3092 return 0;
3093
3094 // If only the first lane is used, then there won't be any code that remains
3095 // in the loop for the first unrolled part.
3097 return 0;
3098
3099 // Typically the operations are:
3100 // 1. Add the start index to each lane value.
3101 // 2. Multiply the start index by the step.
3102 // 3. Add the scaled start index to base IV.
3103 // Any code generated for 1 and 2 should be loop invariant and therefore
3104 // hoisted out of the loop. We only need to add on the cost of 3.
3105
3106 // Given the users of VPScalarIVStepsRecipe tend to be scalarized GEPs, i.e.
3107 // %add1 = add i32 %iv, 0
3108 // %add2 = add i32 %iv, 1
3109 // %gep1 = getelementptr i8, ptr %p, i32 %add1
3110 // %gep2 = getelementptr i8, ptr %p, i32 %add2
3111 // it's very likely that these GEPs will all be rewritten to have a common
3112 // base such that what's left is just
3113 // %base_gep = getelementptr i8, ptr %p, i32 %iv
3114 // %gep1 = getelementptr i8, ptr %base_gep, i32 0
3115 // %gep2 = getelementptr i8, ptr %base_gep, i32 1
3116 // Therefore, in reality the cost is somewhere betwen 1*AddCost and
3117 // (NumLanes - 1) * AddCost. For now, assume the cost of a single add.
3118 return Ctx.TTI.getArithmeticInstrCost(Instruction::Add, BaseIVTy,
3119 Ctx.CostKind);
3120}
3121
3123 // Fast-math-flags propagate from the original induction instruction.
3124 IRBuilder<>::FastMathFlagGuard FMFG(State.Builder);
3125 State.Builder.setFastMathFlags(getFastMathFlagsOrNone());
3126
3127 /// Compute scalar induction steps. \p ScalarIV is the scalar induction
3128 /// variable on which to base the steps, \p Step is the size of the step.
3129
3130 Value *BaseIV = State.get(getOperand(0), VPLane(0));
3131 Value *Step = State.get(getStepValue(), VPLane(0));
3132 IRBuilderBase &Builder = State.Builder;
3133
3134 // Ensure step has the same type as that of scalar IV.
3135 Type *BaseIVTy = BaseIV->getType()->getScalarType();
3136 assert(BaseIVTy == Step->getType() && "Types of BaseIV and Step must match!");
3137
3138 // We build scalar steps for both integer and floating-point induction
3139 // variables. Here, we determine the kind of arithmetic we will perform.
3142 if (BaseIVTy->isIntegerTy()) {
3143 AddOp = Instruction::Add;
3144 MulOp = Instruction::Mul;
3145 } else {
3146 AddOp = InductionOpcode;
3147 MulOp = Instruction::FMul;
3148 }
3149
3150 // Determine the number of scalars we need to generate.
3151 bool FirstLaneOnly = vputils::onlyFirstLaneUsed(this);
3152 // Compute the scalar steps and save the results in State.
3153
3154 unsigned EndLane = FirstLaneOnly ? 1 : State.VF.getKnownMinValue();
3155 Value *StartIdx0 = getStartIndex() ? State.get(getStartIndex(), true)
3156 : Constant::getNullValue(BaseIVTy);
3157
3158 for (unsigned Lane = 0; Lane < EndLane; ++Lane) {
3159 // It is okay if the induction variable type cannot hold the lane number,
3160 // we expect truncation in this case.
3161 Constant *LaneValue =
3162 BaseIVTy->isIntegerTy()
3163 ? ConstantInt::get(BaseIVTy, Lane, /*IsSigned=*/false,
3164 /*ImplicitTrunc=*/true)
3165 : ConstantFP::get(BaseIVTy, Lane);
3166 Value *StartIdx = Builder.CreateBinOp(AddOp, StartIdx0, LaneValue);
3167 assert((State.VF.isScalable() || isa<Constant>(StartIdx)) &&
3168 "Expected StartIdx to be folded to a constant when VF is not "
3169 "scalable");
3170 auto *Mul = Builder.CreateBinOp(MulOp, StartIdx, Step);
3171 auto *Add = Builder.CreateBinOp(AddOp, BaseIV, Mul);
3172 State.set(this, Add, VPLane(Lane));
3173 }
3174}
3175
3176#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3178 VPSlotTracker &SlotTracker) const {
3179 O << Indent;
3181 O << " = SCALAR-STEPS ";
3183}
3184#endif
3185
3187 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
3189}
3190
3192 assert(State.VF.isVector() && "not widening");
3193 auto Ops = map_to_vector(operands(), [&](VPValue *Op) {
3194 return State.get(Op, vputils::isSingleScalar(Op));
3195 });
3196 auto *GEP =
3197 State.Builder.CreateGEP(getSourceElementType(), Ops.front(),
3198 drop_begin(Ops), "wide.gep", getGEPNoWrapFlags());
3199 State.set(this, GEP, vputils::isSingleScalar(this));
3200}
3201
3202#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3204 VPSlotTracker &SlotTracker) const {
3205 O << Indent << "WIDEN-GEP ";
3207 O << " = getelementptr";
3208 printFlags(O);
3210}
3211#endif
3212
3214 assert(!getOffset() && "Unexpected offset operand");
3215 VPBuilder Builder(this);
3216 VPlan &Plan = *getParent()->getPlan();
3217 VPValue *VFVal = getVFValue();
3218 const DataLayout &DL = Plan.getDataLayout();
3219 Type *IndexTy = DL.getIndexType(this->getScalarType());
3220 VPValue *Stride =
3221 Plan.getConstantInt(IndexTy, getStride(), /*IsSigned=*/true);
3222 VPValue *VF =
3223 Builder.createScalarZExtOrTrunc(VFVal, IndexTy, DebugLoc::getUnknown());
3224
3225 // Offset for Part0 = Offset0 = Stride * (VF - 1).
3226 VPInstruction *VFMinusOne =
3227 Builder.createSub(VF, Plan.getConstantInt(IndexTy, 1u),
3228 DebugLoc::getUnknown(), "", {true, true});
3229 VPInstruction *Offset0 =
3230 Builder.createOverflowingOp(Instruction::Mul, {VFMinusOne, Stride});
3231
3232 // Offset for PartN = Offset0 + Part * Stride * VF.
3233 VPValue *PartxStride =
3234 Plan.getConstantInt(IndexTy, Part * getStride(), /*IsSigned=*/true);
3235 VPValue *Offset = Builder.createAdd(
3236 Offset0,
3237 Builder.createOverflowingOp(Instruction::Mul, {PartxStride, VF}));
3239}
3240
3242 auto &Builder = State.Builder;
3243 assert(getOffset() && "Expected prior materialization of offset");
3244 Value *Ptr = State.get(getPointer(), true);
3245 Value *Offset = State.get(getOffset(), true);
3246 Value *ResultPtr = Builder.CreateGEP(getSourceElementType(), Ptr, Offset, "",
3248 State.set(this, ResultPtr, /*IsScalar*/ true);
3249}
3250
3251#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3253 VPSlotTracker &SlotTracker) const {
3254 O << Indent;
3256 O << " = vector-end-pointer";
3257 printFlags(O);
3258 getSourceElementType()->print(O);
3259 O << ", ";
3261}
3262#endif
3263
3265 assert(getVFxPart() &&
3266 "Expected prior simplification of recipe without VFxPart");
3267
3268 auto &Builder = State.Builder;
3269 Value *Ptr = State.get(getOperand(0), VPLane(0));
3270 Value *Offset = State.get(getVFxPart(), true);
3271 // TODO: Expand to VPInstruction to support constant folding.
3272 if (!match(getStride(), m_One())) {
3273 Value *Stride = Builder.CreateZExtOrTrunc(State.get(getStride(), true),
3274 Offset->getType());
3275 Offset = Builder.CreateMul(Offset, Stride);
3276 }
3277 Value *ResultPtr = Builder.CreateGEP(getSourceElementType(), Ptr, Offset, "",
3279 State.set(this, ResultPtr, /*IsScalar*/ true);
3280}
3281
3282#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3284 VPSlotTracker &SlotTracker) const {
3285 O << Indent;
3287 O << " = vector-pointer";
3288 printFlags(O);
3289 getSourceElementType()->print(O);
3290 O << ", ";
3292}
3293#endif
3294
3296 VPCostContext &Ctx) const {
3297 // A blend will be expanded to a select VPInstruction, which will generate a
3298 // scalar select if only the first lane is used.
3300 VF = ElementCount::getFixed(1);
3301
3302 Type *ResultTy = toVectorTy(this->getScalarType(), VF);
3303 Type *CmpTy = toVectorTy(Type::getInt1Ty(Ctx.LLVMCtx), VF);
3304 return (getNumIncomingValues() - 1) *
3305 Ctx.TTI.getCmpSelInstrCost(Instruction::Select, ResultTy, CmpTy,
3306 CmpInst::BAD_ICMP_PREDICATE, Ctx.CostKind);
3307}
3308
3309#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3311 VPSlotTracker &SlotTracker) const {
3312 O << Indent << "BLEND ";
3314 O << " =";
3315 printFlags(O);
3316 if (getNumIncomingValues() == 1) {
3317 // Not a User of any mask: not really blending, this is a
3318 // single-predecessor phi.
3319 getIncomingValue(0)->printAsOperand(O, SlotTracker);
3320 } else {
3321 for (unsigned I = 0, E = getNumIncomingValues(); I < E; ++I) {
3322 if (I != 0)
3323 O << " ";
3324 getIncomingValue(I)->printAsOperand(O, SlotTracker);
3325 if (I == 0 && isNormalized())
3326 continue;
3327 O << "/";
3328 getMask(I)->printAsOperand(O, SlotTracker);
3329 }
3330 }
3331}
3332#endif
3333
3337 "In-loop AnyOf reductions aren't currently supported");
3338 // Propagate the fast-math flags carried by the underlying instruction.
3339 IRBuilderBase::FastMathFlagGuard FMFGuard(State.Builder);
3340 State.Builder.setFastMathFlags(getFastMathFlagsOrNone());
3341 Value *NewVecOp = State.get(getVecOp());
3342 if (VPValue *Cond = getCondOp()) {
3343 Value *NewCond = State.get(Cond, State.VF.isScalar());
3344 VectorType *VecTy = dyn_cast<VectorType>(NewVecOp->getType());
3345 Type *ElementTy = VecTy ? VecTy->getElementType() : NewVecOp->getType();
3346
3347 Value *Start =
3349 if (State.VF.isVector())
3350 Start = State.Builder.CreateVectorSplat(VecTy->getElementCount(), Start);
3351
3352 Value *Select = State.Builder.CreateSelect(NewCond, NewVecOp, Start);
3353 NewVecOp = Select;
3354 }
3355 Value *NewRed;
3356 Value *NextInChain;
3357 if (isOrdered()) {
3358 Value *PrevInChain = State.get(getChainOp(), /*IsScalar*/ true);
3359 if (State.VF.isVector())
3360 NewRed =
3361 createOrderedReduction(State.Builder, Kind, NewVecOp, PrevInChain);
3362 else
3363 NewRed = State.Builder.CreateBinOp(
3365 PrevInChain, NewVecOp);
3366 PrevInChain = NewRed;
3367 NextInChain = NewRed;
3368 } else if (isPartialReduction()) {
3369 assert((Kind == RecurKind::Add || Kind == RecurKind::FAdd) &&
3370 "Unexpected partial reduction kind");
3371 Value *PrevInChain = State.get(getChainOp(), /*IsScalar*/ false);
3372 NewRed = State.Builder.CreateIntrinsic(
3373 PrevInChain->getType(),
3374 Kind == RecurKind::Add ? Intrinsic::vector_partial_reduce_add
3375 : Intrinsic::vector_partial_reduce_fadd,
3376 {PrevInChain, NewVecOp}, State.Builder.getFastMathFlags(),
3377 "partial.reduce");
3378 PrevInChain = NewRed;
3379 NextInChain = NewRed;
3380 } else {
3381 assert(isInLoop() &&
3382 "The reduction must either be ordered, partial or in-loop");
3383 Value *PrevInChain = State.get(getChainOp(), /*IsScalar*/ true);
3384 NewRed = createSimpleReduction(State.Builder, NewVecOp, Kind);
3386 NextInChain = createMinMaxOp(State.Builder, Kind, NewRed, PrevInChain);
3387 else
3388 NextInChain = State.Builder.CreateBinOp(
3390 PrevInChain, NewRed);
3391 }
3392 State.set(this, NextInChain, /*IsScalar*/ !isPartialReduction());
3393}
3394
3396
3397 auto &Builder = State.Builder;
3398 // Propagate the fast-math flags carried by the underlying instruction.
3399 IRBuilderBase::FastMathFlagGuard FMFGuard(Builder);
3400 Builder.setFastMathFlags(getFastMathFlagsOrNone());
3401
3403 Value *Prev = State.get(getChainOp(), /*IsScalar*/ true);
3404 Value *VecOp = State.get(getVecOp());
3405 Value *EVL = State.get(getEVL(), VPLane(0));
3406
3407 Value *Mask;
3408 if (VPValue *CondOp = getCondOp())
3409 Mask = State.get(CondOp);
3410 else
3411 Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue());
3412
3413 Value *NewRed;
3414 if (isOrdered()) {
3415 NewRed = createOrderedReduction(Builder, Kind, VecOp, Prev, Mask, EVL);
3416 } else {
3417 NewRed = createSimpleReduction(Builder, VecOp, Kind, Mask, EVL);
3419 NewRed = createMinMaxOp(Builder, Kind, NewRed, Prev);
3420 else
3421 NewRed = Builder.CreateBinOp(
3423 Prev);
3424 }
3425 State.set(this, NewRed, /*IsScalar*/ true);
3426}
3427
3429 VPCostContext &Ctx) const {
3430 RecurKind RdxKind = getRecurrenceKind();
3431 Type *ElementTy = this->getScalarType();
3432 auto *VectorTy = cast<VectorType>(toVectorTy(ElementTy, VF));
3433 unsigned Opcode = RecurrenceDescriptor::getOpcode(RdxKind);
3435 std::optional<FastMathFlags> OptionalFMF =
3436 ElementTy->isFloatingPointTy() ? std::make_optional(FMFs) : std::nullopt;
3437
3438 if (isPartialReduction()) {
3439 InstructionCost CondCost = 0;
3440 if (isConditional()) {
3442 auto *CondTy =
3444 CondCost = Ctx.TTI.getCmpSelInstrCost(Instruction::Select, VectorTy,
3445 CondTy, Pred, Ctx.CostKind);
3446 }
3447 return CondCost + Ctx.TTI.getPartialReductionCost(
3448 Opcode, ElementTy, ElementTy, ElementTy, VF,
3449 TTI::PR_None, TTI::PR_None, {}, Ctx.CostKind,
3450 OptionalFMF);
3451 }
3452
3453 // TODO: Support any-of reductions.
3454 assert(
3456 ForceTargetInstructionCost.getNumOccurrences() > 0) &&
3457 "Any-of reduction not implemented in VPlan-based cost model currently.");
3458
3459 // Note that TTI should model the cost of moving result to the scalar register
3460 // and the BinOp cost in the getMinMaxReductionCost().
3463 return Ctx.TTI.getMinMaxReductionCost(Id, VectorTy, FMFs, Ctx.CostKind);
3464 }
3465
3466 // Note that TTI should model the cost of moving result to the scalar register
3467 // and the BinOp cost in the getArithmeticReductionCost().
3468 return Ctx.TTI.getArithmeticReductionCost(Opcode, VectorTy, OptionalFMF,
3469 Ctx.CostKind);
3470}
3471
3472VPExpressionRecipe::VPExpressionRecipe(
3473 ExpressionTypes ExpressionType,
3474 ArrayRef<VPSingleDefRecipe *> ExpressionRecipes)
3475 : VPSingleDefRecipe(VPRecipeBase::VPExpressionSC, {},
3476 cast<VPReductionRecipe>(ExpressionRecipes.back())
3477 ->getChainOp()
3478 ->getScalarType()),
3479 ExpressionRecipes(ExpressionRecipes), ExpressionType(ExpressionType) {
3480 assert(!ExpressionRecipes.empty() && "Nothing to combine?");
3481 assert(
3482 none_of(ExpressionRecipes,
3483 [](VPSingleDefRecipe *R) { return R->mayHaveSideEffects(); }) &&
3484 "expression cannot contain recipes with side-effects");
3485
3486 // Maintain a copy of the expression recipes as a set of users.
3487 SmallPtrSet<VPUser *, 4> ExpressionRecipesAsSetOfUsers;
3488 for (auto *R : ExpressionRecipes)
3489 ExpressionRecipesAsSetOfUsers.insert(R);
3490
3491 // Recipes in the expression, except the last one, must only be used by
3492 // (other) recipes inside the expression. If there are other users, external
3493 // to the expression, use a clone of the recipe for external users.
3494 for (VPSingleDefRecipe *R : reverse(ExpressionRecipes)) {
3495 if (R != ExpressionRecipes.back() &&
3496 any_of(R->users(), [&ExpressionRecipesAsSetOfUsers](VPUser *U) {
3497 return !ExpressionRecipesAsSetOfUsers.contains(U);
3498 })) {
3499 // There are users outside of the expression. Clone the recipe and use the
3500 // clone those external users.
3501 VPSingleDefRecipe *CopyForExtUsers = R->clone();
3502 R->replaceUsesWithIf(CopyForExtUsers, [&ExpressionRecipesAsSetOfUsers](
3503 VPUser &U, unsigned) {
3504 return !ExpressionRecipesAsSetOfUsers.contains(&U);
3505 });
3506 CopyForExtUsers->insertBefore(R);
3507 }
3508 if (R->getParent())
3509 R->removeFromParent();
3510 }
3511
3512 // Internalize all external operands to the expression recipes. To do so,
3513 // create new temporary VPValues for all operands defined by a recipe outside
3514 // the expression. The original operands are added as operands of the
3515 // VPExpressionRecipe itself.
3516 for (auto *R : ExpressionRecipes) {
3517 for (const auto &[Idx, Op] : enumerate(R->operands())) {
3518 auto *Def = Op->getDefiningRecipe();
3519 if (Def && ExpressionRecipesAsSetOfUsers.contains(Def))
3520 continue;
3521 addOperand(Op);
3522 LiveInPlaceholders.push_back(new VPSymbolicValue(Op->getScalarType()));
3523 }
3524 }
3525
3526 // Replace each external operand with the first one created for it in
3527 // LiveInPlaceholders.
3528 for (auto *R : ExpressionRecipes)
3529 for (auto const &[LiveIn, Tmp] : zip(operands(), LiveInPlaceholders))
3530 R->replaceUsesOfWith(LiveIn, Tmp);
3531}
3532
3534 for (auto *R : ExpressionRecipes)
3535 // Since the list could contain duplicates, make sure the recipe hasn't
3536 // already been inserted.
3537 if (!R->getParent())
3538 R->insertBefore(this);
3539
3540 for (const auto &[Idx, Op] : enumerate(operands()))
3541 LiveInPlaceholders[Idx]->replaceAllUsesWith(Op);
3542
3543 replaceAllUsesWith(ExpressionRecipes.back());
3544 ExpressionRecipes.clear();
3545}
3546
3548 VPCostContext &Ctx) const {
3549 Type *RedTy = this->getScalarType();
3550 auto *SrcVecTy =
3552 unsigned Opcode = RecurrenceDescriptor::getOpcode(
3553 cast<VPReductionRecipe>(ExpressionRecipes.back())->getRecurrenceKind());
3554 switch (ExpressionType) {
3555 case ExpressionTypes::NegatedExtendedReduction:
3556 assert((Opcode == Instruction::Add || Opcode == Instruction::FAdd) &&
3557 "Unexpected opcode");
3558 Opcode = Opcode == Instruction::Add ? Instruction::Sub : Instruction::FSub;
3559 [[fallthrough]];
3560 case ExpressionTypes::ExtendedReduction: {
3561 auto *RedR = cast<VPReductionRecipe>(ExpressionRecipes.back());
3562 auto *ExtR = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3563
3564 if (RedR->isPartialReduction())
3565 return Ctx.TTI.getPartialReductionCost(
3566 Opcode, getOperand(0)->getScalarType(), nullptr, RedTy, VF,
3568 TargetTransformInfo::PR_None, std::nullopt, Ctx.CostKind,
3569 RedTy->isFloatingPointTy()
3570 ? std::optional{RedR->getFastMathFlagsOrNone()}
3571 : std::nullopt);
3572 else if (!RedTy->isFloatingPointTy())
3573 // TTI::getExtendedReductionCost only supports integer types.
3574 return Ctx.TTI.getExtendedReductionCost(
3575 Opcode, ExtR->getOpcode() == Instruction::ZExt, RedTy, SrcVecTy,
3576 std::nullopt, Ctx.CostKind);
3577 else
3579 }
3580 case ExpressionTypes::MulAccReduction:
3581 return Ctx.TTI.getMulAccReductionCost(false, Opcode, RedTy, SrcVecTy,
3582 Ctx.CostKind);
3583
3584 case ExpressionTypes::ExtNegatedMulAccReduction:
3585 switch (Opcode) {
3586 case Instruction::Add:
3587 Opcode = Instruction::Sub;
3588 break;
3589 case Instruction::FAdd:
3590 Opcode = Instruction::FSub;
3591 break;
3592 default:
3593 llvm_unreachable("Unsupported opcode for ExtNegatedMulAccReduction");
3594 }
3595 [[fallthrough]];
3596 case ExpressionTypes::ExtMulAccReduction: {
3597 auto *RedR = cast<VPReductionRecipe>(ExpressionRecipes.back());
3598 if (RedR->isPartialReduction()) {
3599 auto *Ext0R = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3600 auto *Ext1R = cast<VPWidenCastRecipe>(ExpressionRecipes[1]);
3601 auto *Mul = cast<VPWidenRecipe>(ExpressionRecipes[2]);
3602 return Ctx.TTI.getPartialReductionCost(
3603 Opcode, getOperand(0)->getScalarType(),
3604 getOperand(1)->getScalarType(), RedTy, VF,
3606 Ext0R->getOpcode()),
3608 Ext1R->getOpcode()),
3609 Mul->getOpcode(), Ctx.CostKind,
3610 RedTy->isFloatingPointTy()
3611 ? std::optional{RedR->getFastMathFlagsOrNone()}
3612 : std::nullopt);
3613 }
3614 assert(Opcode != Instruction::FSub && "Only integer types are supported");
3615 return Ctx.TTI.getMulAccReductionCost(
3616 cast<VPWidenCastRecipe>(ExpressionRecipes.front())->getOpcode() ==
3617 Instruction::ZExt,
3618 Opcode, RedTy, SrcVecTy, Ctx.CostKind);
3619 }
3620 }
3621 llvm_unreachable("Unknown VPExpressionRecipe::ExpressionTypes enum");
3622}
3623
3625 return any_of(ExpressionRecipes, [](VPSingleDefRecipe *R) {
3626 return R->mayReadFromMemory() || R->mayWriteToMemory();
3627 });
3628}
3629
3631 assert(
3632 none_of(ExpressionRecipes,
3633 [](VPSingleDefRecipe *R) { return R->mayHaveSideEffects(); }) &&
3634 "expression cannot contain recipes with side-effects");
3635 return false;
3636}
3637
3639 auto *RR = dyn_cast<VPReductionRecipe>(ExpressionRecipes.back());
3640 return RR && !RR->isPartialReduction();
3641}
3642
3643#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3644
3646 VPSlotTracker &SlotTracker) const {
3647 O << Indent << "EXPRESSION ";
3649 O << " = ";
3650 auto *Red = cast<VPReductionRecipe>(ExpressionRecipes.back());
3651 unsigned Opcode = RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind());
3652 VPValue *RdxStart =
3653 getOperand(getNumOperands() - (Red->isConditional() ? 2 : 1));
3654
3655 switch (ExpressionType) {
3656 case ExpressionTypes::NegatedExtendedReduction:
3657 case ExpressionTypes::ExtendedReduction: {
3658 bool Negated = ExpressionType == ExpressionTypes::NegatedExtendedReduction;
3660 O << " + " << (Red->isPartialReduction() ? "partial." : "") << "reduce.";
3661 O << Instruction::getOpcodeName(Opcode) << " (";
3662 if (Negated)
3663 O << (Opcode == Instruction::Add ? "sub (0, " : "fneg(");
3665 if (Negated)
3666 O << ")";
3667 Red->printFlags(O);
3668
3669 auto *Ext0 = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3670 O << Instruction::getOpcodeName(Ext0->getOpcode()) << " to "
3671 << *Ext0->getScalarType();
3672 if (Red->isConditional()) {
3673 O << ", ";
3675 }
3676 O << ")";
3677 break;
3678 }
3679 case ExpressionTypes::ExtNegatedMulAccReduction: {
3680 RdxStart->printAsOperand(O, SlotTracker);
3681 O << " + " << (Red->isPartialReduction() ? "partial." : "") << "reduce.";
3683 RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind()))
3684 << " (sub (0, mul";
3685 auto *Mul = cast<VPWidenRecipe>(ExpressionRecipes[2]);
3686 Mul->printFlags(O);
3687 O << "(";
3689 auto *Ext0 = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3690 O << " " << Instruction::getOpcodeName(Ext0->getOpcode()) << " to "
3691 << *Ext0->getScalarType() << "), (";
3693 auto *Ext1 = cast<VPWidenCastRecipe>(ExpressionRecipes[1]);
3694 O << " " << Instruction::getOpcodeName(Ext1->getOpcode()) << " to "
3695 << *Ext1->getScalarType() << ")";
3696 if (Red->isConditional()) {
3697 O << ", ";
3699 }
3700 O << "))";
3701 break;
3702 }
3703 case ExpressionTypes::MulAccReduction:
3704 case ExpressionTypes::ExtMulAccReduction: {
3705 RdxStart->printAsOperand(O, SlotTracker);
3706 O << " + " << (Red->isPartialReduction() ? "partial." : "") << "reduce.";
3708 RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind()))
3709 << " (";
3710 O << "mul";
3711 bool IsExtended = ExpressionType == ExpressionTypes::ExtMulAccReduction;
3712 auto *Mul = cast<VPWidenRecipe>(IsExtended ? ExpressionRecipes[2]
3713 : ExpressionRecipes[0]);
3714 Mul->printFlags(O);
3715 if (IsExtended)
3716 O << "(";
3718 if (IsExtended) {
3719 auto *Ext0 = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3720 O << " " << Instruction::getOpcodeName(Ext0->getOpcode()) << " to "
3721 << *Ext0->getScalarType() << "), (";
3722 } else {
3723 O << ", ";
3724 }
3726 if (IsExtended) {
3727 auto *Ext1 = cast<VPWidenCastRecipe>(ExpressionRecipes[1]);
3728 O << " " << Instruction::getOpcodeName(Ext1->getOpcode()) << " to "
3729 << *Ext1->getScalarType() << ")";
3730 }
3731 if (Red->isConditional()) {
3732 O << ", ";
3734 }
3735 O << ")";
3736 break;
3737 }
3738 }
3739}
3740
3742 VPSlotTracker &SlotTracker) const {
3743 if (isPartialReduction())
3744 O << Indent << "PARTIAL-REDUCE ";
3745 else
3746 O << Indent << "REDUCE ";
3748 O << " = ";
3750 O << " +";
3751 printFlags(O);
3752 O << " reduce.";
3754 O << " (";
3756 if (isConditional()) {
3757 O << ", ";
3759 }
3760 O << ")";
3761}
3762
3764 VPSlotTracker &SlotTracker) const {
3765 O << Indent << "REDUCE ";
3767 O << " = ";
3769 O << " +";
3770 printFlags(O);
3771 O << " vp.reduce."
3774 << " (";
3776 O << ", ";
3778 if (isConditional()) {
3779 O << ", ";
3781 }
3782 O << ")";
3783}
3784
3785#endif
3786
3788 assert(IsSingleScalar &&
3789 "VPReplicateRecipes must be unrolled before ::execute");
3790 auto *Instr = getUnderlyingInstr();
3791 Instruction *Cloned = Instr->clone();
3792 Type *ResultTy = getScalarType();
3793 if (!ResultTy->isVoidTy()) {
3794 Cloned->setName(Instr->getName() + ".cloned");
3795 // The operands of the replicate recipe may have been narrowed, resulting in
3796 // a narrower result type. Update the type of the cloned instruction to the
3797 // correct type.
3798 if (ResultTy != Cloned->getType())
3799 Cloned->mutateType(ResultTy);
3800 }
3801
3802 applyFlags(*Cloned);
3803 applyMetadata(*Cloned);
3804
3805 if (hasPredicate())
3806 cast<CmpInst>(Cloned)->setPredicate(getPredicate());
3807
3808 // Replace the operands of the cloned instructions with their scalar
3809 // equivalents in the new loop.
3810 for (const auto &[Idx, V] : enumerate(operands()))
3811 Cloned->setOperand(Idx, State.get(V, true));
3812
3813 // Place the cloned scalar in the new loop.
3814 State.Builder.Insert(Cloned);
3815
3816 State.set(this, Cloned, true);
3817
3818 // If we just cloned a new assumption, add it the assumption cache.
3819 if (auto *II = dyn_cast<AssumeInst>(Cloned))
3820 State.AC->registerAssumption(II);
3821}
3822
3823/// Returns a SCEV expression for \p Ptr if it is a pointer computation for
3824/// which the legacy cost model computes a SCEV expression when computing the
3825/// address cost. Computing SCEVs for VPValues is incomplete and returns
3826/// SCEVCouldNotCompute in cases the legacy cost model can compute SCEVs. In
3827/// those cases we fall back to the legacy cost model. Otherwise return nullptr.
3828static const SCEV *getAddressAccessSCEV(const VPValue *Ptr,
3830 const Loop *L) {
3831 const SCEV *Addr = vputils::getSCEVExprForVPValue(Ptr, PSE, L);
3832 if (isa<SCEVCouldNotCompute>(Addr))
3833 return Addr;
3834
3835 return vputils::isAddressSCEVForCost(Addr, *PSE.getSE(), L) ? Addr : nullptr;
3836}
3837
3839 VPCostContext &Ctx) const {
3841 // VPReplicateRecipe may be cloned as part of an existing VPlan-to-VPlan
3842 // transform, avoid computing their cost multiple times for now.
3843 Ctx.SkipCostComputation.insert(UI);
3844
3845 if (VF.isScalable() && !isSingleScalar())
3847
3848 switch (UI->getOpcode()) {
3849 case Instruction::Alloca:
3850 if (VF.isScalable())
3852 return Ctx.TTI.getArithmeticInstrCost(Instruction::Mul,
3853 this->getScalarType(), Ctx.CostKind);
3854 case Instruction::GetElementPtr:
3855 // We mark this instruction as zero-cost because the cost of GEPs in
3856 // vectorized code depends on whether the corresponding memory instruction
3857 // is scalarized or not. Therefore, we handle GEPs with the memory
3858 // instruction cost.
3859 return 0;
3860 case Instruction::Call: {
3861 auto *CalledFn =
3863 Type *ResultTy = this->getScalarType();
3864 return computeCallCost(CalledFn, ResultTy, drop_end(operands()),
3865 isSingleScalar(), VF, Ctx);
3866 }
3867 case Instruction::Add:
3868 case Instruction::Sub:
3869 case Instruction::FAdd:
3870 case Instruction::FSub:
3871 case Instruction::Mul:
3872 case Instruction::FMul:
3873 case Instruction::FDiv:
3874 case Instruction::FRem:
3875 case Instruction::Shl:
3876 case Instruction::LShr:
3877 case Instruction::AShr:
3878 case Instruction::And:
3879 case Instruction::Or:
3880 case Instruction::Xor:
3881 case Instruction::ICmp:
3882 case Instruction::FCmp:
3884 Ctx) *
3885 (isSingleScalar() ? 1 : VF.getFixedValue());
3886 case Instruction::SDiv:
3887 case Instruction::UDiv:
3888 case Instruction::SRem:
3889 case Instruction::URem: {
3890 InstructionCost ScalarCost =
3892 if (isSingleScalar())
3893 return ScalarCost;
3894
3895 // If any of the operands is from a different replicate region and has its
3896 // cost skipped, it may have been forced to scalar. Fall back to legacy cost
3897 // model to avoid cost mis-match.
3898 if (any_of(operands(), [&Ctx, VF](VPValue *Op) {
3899 auto *PredR = dyn_cast<VPPredInstPHIRecipe>(Op);
3900 if (!PredR)
3901 return false;
3902 return Ctx.skipCostComputation(
3904 PredR->getOperand(0)->getUnderlyingValue()),
3905 VF.isVector());
3906 }))
3907 break;
3908
3909 ScalarCost = ScalarCost * VF.getFixedValue() +
3910 Ctx.getScalarizationOverhead(this->getScalarType(),
3911 to_vector(operands()), VF);
3912 // If the recipe is not predicated (i.e. not in a replicate region), return
3913 // the scalar cost. Otherwise handle predicated cost.
3914 if (!getRegion()->isReplicator())
3915 return ScalarCost;
3916
3917 // Account for the phi nodes that we will create.
3918 ScalarCost += VF.getFixedValue() *
3919 Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
3920 // Scale the cost by the probability of executing the predicated blocks.
3921 // This assumes the predicated block for each vector lane is equally
3922 // likely.
3923 ScalarCost /= Ctx.getPredBlockCostDivisor(UI->getParent());
3924 return ScalarCost;
3925 }
3926 case Instruction::Load:
3927 case Instruction::Store: {
3928 bool IsLoad = UI->getOpcode() == Instruction::Load;
3929 const VPValue *PtrOp = getOperand(!IsLoad);
3930 const SCEV *PtrSCEV = getAddressAccessSCEV(PtrOp, Ctx.PSE, Ctx.L);
3932 break;
3933
3934 Type *ValTy = (IsLoad ? this : getOperand(0))->getScalarType();
3935 Type *ScalarPtrTy = PtrOp->getScalarType();
3936 const Align Alignment = getLoadStoreAlignment(UI);
3937 unsigned AS = cast<PointerType>(ScalarPtrTy)->getAddressSpace();
3939 bool PreferVectorizedAddressing = Ctx.TTI.prefersVectorizedAddressing();
3940 bool UsedByLoadStoreAddress =
3941 !PreferVectorizedAddressing && vputils::isUsedByLoadStoreAddress(this);
3942 InstructionCost ScalarMemOpCost = Ctx.TTI.getMemoryOpCost(
3943 UI->getOpcode(), ValTy, Alignment, AS, Ctx.CostKind, OpInfo,
3944 UsedByLoadStoreAddress ? UI : nullptr);
3945
3946 Type *PtrTy = isSingleScalar() ? ScalarPtrTy : toVectorTy(ScalarPtrTy, VF);
3947 InstructionCost ScalarCost =
3948 ScalarMemOpCost +
3949 Ctx.TTI.getAddressComputationCost(
3950 PtrTy, UsedByLoadStoreAddress ? nullptr : Ctx.PSE.getSE(), PtrSCEV,
3951 Ctx.CostKind);
3952 if (isSingleScalar())
3953 return ScalarCost;
3954
3955 SmallVector<const VPValue *> OpsToScalarize;
3956 Type *ResultTy = Type::getVoidTy(PtrTy->getContext());
3957 // Set ResultTy and OpsToScalarize, if scalarization is needed. Currently we
3958 // don't assign scalarization overhead in general, if the target prefers
3959 // vectorized addressing or the loaded value is used as part of an address
3960 // of another load or store.
3961 if (!UsedByLoadStoreAddress) {
3962 bool EfficientVectorLoadStore =
3963 Ctx.TTI.supportsEfficientVectorElementLoadStore();
3964 if (!(IsLoad && !PreferVectorizedAddressing) &&
3965 !(!IsLoad && EfficientVectorLoadStore))
3966 append_range(OpsToScalarize, operands());
3967
3968 if (!EfficientVectorLoadStore)
3969 ResultTy = this->getScalarType();
3970 }
3971
3973 IsLoad ? TTI::VectorInstrContext::Load : TTI::VectorInstrContext::Store;
3975 (ScalarCost * VF.getFixedValue()) +
3976 Ctx.getScalarizationOverhead(ResultTy, OpsToScalarize, VF, VIC, true);
3977
3978 const VPRegionBlock *ParentRegion = getRegion();
3979 if (ParentRegion && ParentRegion->isReplicator()) {
3980 if (!PtrSCEV)
3981 break;
3982 Cost /= Ctx.getPredBlockCostDivisor(UI->getParent());
3983 Cost += Ctx.TTI.getCFInstrCost(Instruction::CondBr, Ctx.CostKind);
3984
3985 auto *VecI1Ty = VectorType::get(
3986 IntegerType::getInt1Ty(Ctx.L->getHeader()->getContext()), VF);
3987 Cost += Ctx.TTI.getScalarizationOverhead(
3988 VecI1Ty, APInt::getAllOnes(VF.getFixedValue()),
3989 /*Insert=*/false, /*Extract=*/true, Ctx.CostKind);
3990
3991 if (Ctx.useEmulatedMaskMemRefHack(this, VF)) {
3992 // Artificially setting to a high enough value to practically disable
3993 // vectorization with such operations.
3994 return 3000000;
3995 }
3996 }
3997 return Cost;
3998 }
3999 case Instruction::SExt:
4000 case Instruction::ZExt:
4001 case Instruction::FPToUI:
4002 case Instruction::FPToSI:
4003 case Instruction::FPExt:
4004 case Instruction::PtrToInt:
4005 case Instruction::PtrToAddr:
4006 case Instruction::IntToPtr:
4007 case Instruction::SIToFP:
4008 case Instruction::UIToFP:
4009 case Instruction::Trunc:
4010 case Instruction::FPTrunc:
4011 case Instruction::Select:
4012 case Instruction::AddrSpaceCast: {
4014 Ctx) *
4015 (isSingleScalar() ? 1 : VF.getFixedValue());
4016 }
4017 case Instruction::ExtractValue:
4018 case Instruction::InsertValue:
4019 return Ctx.TTI.getInsertExtractValueCost(getOpcode(), Ctx.CostKind);
4020 }
4021
4022 return Ctx.getLegacyCost(UI, VF);
4023}
4024
4026 Function *CalledFn, Type *ResultTy, ArrayRef<const VPValue *> ArgOps,
4027 bool IsSingleScalar, ElementCount VF, VPCostContext &Ctx) {
4029 ArgOps, [&](const VPValue *Op) { return Op->getScalarType(); });
4030
4031 Intrinsic::ID IntrinID = CalledFn->getIntrinsicID();
4032 auto GetIntrinsicCost = [&] {
4033 if (!IntrinID)
4035 return Ctx.TTI.getIntrinsicInstrCost(
4036 IntrinsicCostAttributes(IntrinID, ResultTy, Tys), Ctx.CostKind);
4037 };
4038
4039 if (IntrinID && VPCostContext::isFreeScalarIntrinsic(IntrinID)) {
4040 assert(GetIntrinsicCost() == 0 && "scalarizing intrinsic should be free");
4041 return 0;
4042 }
4043
4044 InstructionCost ScalarCallCost =
4045 Ctx.TTI.getCallInstrCost(CalledFn, ResultTy, Tys, Ctx.CostKind);
4046 if (IsSingleScalar) {
4047 ScalarCallCost = std::min(ScalarCallCost, GetIntrinsicCost());
4048 return ScalarCallCost;
4049 }
4050
4051 // Scalarization overhead is undefined for scalable VFs.
4052 if (VF.isScalable())
4054
4055 return ScalarCallCost * VF.getFixedValue() +
4056 Ctx.getScalarizationOverhead(ResultTy, ArgOps, VF);
4057}
4058
4059#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4061 VPSlotTracker &SlotTracker) const {
4062 O << Indent << (IsSingleScalar ? "CLONE " : "REPLICATE ");
4063
4064 if (!getScalarType()->isVoidTy()) {
4066 O << " = ";
4067 }
4068 if (auto *CB = dyn_cast<CallBase>(getUnderlyingInstr())) {
4069 O << "call";
4070 printFlags(O);
4071 O << "@" << CB->getCalledFunction()->getName() << "(";
4073 Op->printAsOperand(O, SlotTracker);
4074 });
4075 O << ")";
4076 } else {
4078 printFlags(O);
4080 }
4081
4082 // Find if the recipe is used by a widened recipe via an intervening
4083 // VPPredInstPHIRecipe. In this case, also pack the scalar values in a vector.
4084 if (any_of(users(), [](const VPUser *U) {
4085 if (auto *PredR = dyn_cast<VPPredInstPHIRecipe>(U))
4086 return !vputils::onlyScalarValuesUsed(PredR);
4087 return false;
4088 }))
4089 O << " (S->V)";
4090}
4091#endif
4092
4094 llvm_unreachable("recipe must be removed when dissolving replicate region");
4095}
4096
4098 VPCostContext &Ctx) const {
4099 // The legacy cost model doesn't assign costs to branches for individual
4100 // replicate regions. Match the current behavior in the VPlan cost model for
4101 // now.
4102 return 0;
4103}
4104
4106 llvm_unreachable("recipe must be removed when dissolving replicate region");
4107}
4108
4109#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4111 VPSlotTracker &SlotTracker) const {
4112 O << Indent << "PHI-PREDICATED-INSTRUCTION ";
4114 O << " = ";
4116}
4117#endif
4118
4120const VPRecipeBase *VPWidenLoadRecipe::getAsRecipe() const { return this; }
4121
4124
4126const VPRecipeBase *VPWidenStoreRecipe::getAsRecipe() const { return this; }
4127
4130
4132 VPCostContext &Ctx) const {
4133 const VPRecipeBase *R = getAsRecipe();
4135 Type *ScalarTy = IsLoad ? cast<VPSingleDefRecipe>(R)->getScalarType()
4136 : R->getOperand(1)->getScalarType();
4137 Type *Ty = toVectorTy(ScalarTy, VF);
4138 unsigned AS =
4139 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4140 unsigned Opcode = IsLoad ? Instruction::Load : Instruction::Store;
4141
4142 if (!Consecutive) {
4143 // TODO: Using the original IR may not be accurate.
4144 // Currently, ARM will use the underlying IR to calculate gather/scatter
4145 // instruction cost.
4146 Type *PtrTy = getAddr()->getScalarType();
4147 const Value *Ptr = getAddr()->getUnderlyingValue();
4148
4149 // If the address value is uniform across all lanes, then the address can be
4150 // calculated with scalar type and broadcast.
4152 PtrTy = toVectorTy(PtrTy, VF);
4153
4154 unsigned IID = isa<VPWidenLoadRecipe>(R) ? Intrinsic::masked_gather
4155 : isa<VPWidenStoreRecipe>(R) ? Intrinsic::masked_scatter
4156 : isa<VPWidenLoadEVLRecipe>(R) ? Intrinsic::vp_gather
4157 : Intrinsic::vp_scatter;
4158 return Ctx.TTI.getAddressComputationCost(PtrTy, nullptr, nullptr,
4159 Ctx.CostKind) +
4160 Ctx.TTI.getMemIntrinsicInstrCost(
4162 &Ingredient),
4163 Ctx.CostKind);
4164 }
4165
4167 if (IsMasked) {
4168 unsigned IID = isa<VPWidenLoadRecipe>(R) ? Intrinsic::masked_load
4169 : Intrinsic::masked_store;
4170 Cost += Ctx.TTI.getMemIntrinsicInstrCost(
4171 MemIntrinsicCostAttributes(IID, Ty, Alignment, AS), Ctx.CostKind);
4172 } else {
4173 TTI::OperandValueInfo OpInfo = Ctx.getOperandInfo(
4175 : R->getOperand(1));
4176 Cost += Ctx.TTI.getMemoryOpCost(Opcode, Ty, Alignment, AS, Ctx.CostKind,
4177 OpInfo, &Ingredient);
4178 }
4179 return Cost;
4180}
4181
4183 Type *ScalarDataTy = getScalarType();
4184 auto *DataTy = VectorType::get(ScalarDataTy, State.VF);
4185 bool CreateGather = !isConsecutive();
4186
4187 auto &Builder = State.Builder;
4188 Value *Mask = nullptr;
4189 if (auto *VPMask = getMask())
4190 Mask = State.get(VPMask);
4191
4192 Value *Addr = State.get(getAddr(), /*IsScalar*/ !CreateGather);
4193 Value *NewLI;
4194 if (CreateGather) {
4195 NewLI = Builder.CreateMaskedGather(DataTy, Addr, Alignment, Mask, nullptr,
4196 "wide.masked.gather");
4197 } else if (Mask) {
4198 NewLI =
4199 Builder.CreateMaskedLoad(DataTy, Addr, Alignment, Mask,
4200 PoisonValue::get(DataTy), "wide.masked.load");
4201 } else {
4202 NewLI = Builder.CreateAlignedLoad(DataTy, Addr, Alignment, "wide.load");
4203 }
4205 State.set(this, NewLI);
4206}
4207
4208#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4210 VPSlotTracker &SlotTracker) const {
4211 O << Indent << "WIDEN ";
4213 O << " = load ";
4215}
4216#endif
4217
4219 Type *ScalarDataTy = getScalarType();
4220 auto *DataTy = VectorType::get(ScalarDataTy, State.VF);
4221 bool CreateGather = !isConsecutive();
4222
4223 auto &Builder = State.Builder;
4224 CallInst *NewLI;
4225 Value *EVL = State.get(getEVL(), VPLane(0));
4226 Value *Addr = State.get(getAddr(), !CreateGather);
4227 Value *Mask = nullptr;
4228 if (VPValue *VPMask = getMask())
4229 Mask = State.get(VPMask);
4230 else
4231 Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue());
4232
4233 if (CreateGather) {
4234 NewLI = Builder.CreateIntrinsicWithoutFolding(DataTy, Intrinsic::vp_gather,
4235 {Addr, Mask, EVL}, nullptr,
4236 "wide.masked.gather");
4237 } else {
4238 NewLI = Builder.CreateIntrinsicWithoutFolding(
4239 DataTy, Intrinsic::vp_load, {Addr, Mask, EVL}, nullptr, "vp.op.load");
4240 }
4241 NewLI->addParamAttr(
4243 applyMetadata(*NewLI);
4244 State.set(this, NewLI);
4245}
4246
4248 VPCostContext &Ctx) const {
4249 if (!Consecutive || IsMasked)
4250 return VPWidenMemoryRecipe::computeCost(VF, Ctx);
4251
4252 // We need to use the getMemIntrinsicInstrCost() instead of getMemoryOpCost()
4253 // here because the EVL recipes using EVL to replace the tail mask. But in the
4254 // legacy model, it will always calculate the cost of mask.
4255 // TODO: Using getMemoryOpCost() instead of getMemIntrinsicInstrCost when we
4256 // don't need to compare to the legacy cost model.
4257 Type *Ty = toVectorTy(getScalarType(), VF);
4258 unsigned AS =
4259 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4260 return Ctx.TTI.getMemIntrinsicInstrCost(
4261 MemIntrinsicCostAttributes(Intrinsic::vp_load, Ty, Alignment, AS),
4262 Ctx.CostKind);
4263}
4264
4265#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4267 VPSlotTracker &SlotTracker) const {
4268 O << Indent << "WIDEN ";
4270 O << " = vp.load ";
4272}
4273#endif
4274
4276 VPValue *StoredVPValue = getStoredValue();
4277 bool CreateScatter = !isConsecutive();
4278
4279 auto &Builder = State.Builder;
4280
4281 Value *Mask = nullptr;
4282 if (auto *VPMask = getMask())
4283 Mask = State.get(VPMask);
4284
4285 Value *StoredVal = State.get(StoredVPValue);
4286 Value *Addr = State.get(getAddr(), /*IsScalar*/ !CreateScatter);
4287 Instruction *NewSI = nullptr;
4288 if (CreateScatter)
4289 NewSI = Builder.CreateMaskedScatter(StoredVal, Addr, Alignment, Mask);
4290 else if (Mask)
4291 NewSI = Builder.CreateMaskedStore(StoredVal, Addr, Alignment, Mask);
4292 else
4293 NewSI = Builder.CreateAlignedStore(StoredVal, Addr, Alignment);
4294 applyMetadata(*NewSI);
4295}
4296
4297#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4299 VPSlotTracker &SlotTracker) const {
4300 O << Indent << "WIDEN store ";
4302}
4303#endif
4304
4306 VPValue *StoredValue = getStoredValue();
4307 bool CreateScatter = !isConsecutive();
4308
4309 auto &Builder = State.Builder;
4310
4311 CallInst *NewSI = nullptr;
4312 Value *StoredVal = State.get(StoredValue);
4313 Value *EVL = State.get(getEVL(), VPLane(0));
4314 Value *Mask = nullptr;
4315 if (VPValue *VPMask = getMask())
4316 Mask = State.get(VPMask);
4317 else
4318 Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue());
4319
4320 Value *Addr = State.get(getAddr(), !CreateScatter);
4321 if (CreateScatter) {
4322 NewSI = Builder.CreateIntrinsicWithoutFolding(
4323 Type::getVoidTy(EVL->getContext()), Intrinsic::vp_scatter,
4324 {StoredVal, Addr, Mask, EVL});
4325 } else {
4326 NewSI = Builder.CreateIntrinsicWithoutFolding(
4327 Type::getVoidTy(EVL->getContext()), Intrinsic::vp_store,
4328 {StoredVal, Addr, Mask, EVL});
4329 }
4330 NewSI->addParamAttr(
4332 applyMetadata(*NewSI);
4333}
4334
4336 VPCostContext &Ctx) const {
4337 if (!Consecutive || IsMasked)
4338 return VPWidenMemoryRecipe::computeCost(VF, Ctx);
4339
4340 // We need to use the getMemIntrinsicInstrCost() instead of getMemoryOpCost()
4341 // here because the EVL recipes using EVL to replace the tail mask. But in the
4342 // legacy model, it will always calculate the cost of mask.
4343 // TODO: Using getMemoryOpCost() instead of getMemIntrinsicInstrCost when we
4344 // don't need to compare to the legacy cost model.
4345 Type *Ty = toVectorTy(getStoredValue()->getScalarType(), VF);
4346 unsigned AS =
4347 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4348 return Ctx.TTI.getMemIntrinsicInstrCost(
4349 MemIntrinsicCostAttributes(Intrinsic::vp_store, Ty, Alignment, AS),
4350 Ctx.CostKind);
4351}
4352
4353#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4355 VPSlotTracker &SlotTracker) const {
4356 O << Indent << "WIDEN vp.store ";
4358}
4359#endif
4360
4362 VectorType *DstVTy, const DataLayout &DL) {
4363 // Verify that V is a vector type with same number of elements as DstVTy.
4364 auto VF = DstVTy->getElementCount();
4365 auto *SrcVecTy = cast<VectorType>(V->getType());
4366 assert(VF == SrcVecTy->getElementCount() && "Vector dimensions do not match");
4367 Type *SrcElemTy = SrcVecTy->getElementType();
4368 Type *DstElemTy = DstVTy->getElementType();
4369 assert((DL.getTypeSizeInBits(SrcElemTy) == DL.getTypeSizeInBits(DstElemTy)) &&
4370 "Vector elements must have same size");
4371
4372 // Do a direct cast if element types are castable.
4373 if (CastInst::isBitOrNoopPointerCastable(SrcElemTy, DstElemTy, DL)) {
4374 return Builder.CreateBitOrPointerCast(V, DstVTy);
4375 }
4376 // V cannot be directly casted to desired vector type.
4377 // May happen when V is a floating point vector but DstVTy is a vector of
4378 // pointers or vice-versa. Handle this using a two-step bitcast using an
4379 // intermediate Integer type for the bitcast i.e. Ptr <-> Int <-> Float.
4380 assert((DstElemTy->isPointerTy() != SrcElemTy->isPointerTy()) &&
4381 "Only one type should be a pointer type");
4382 assert((DstElemTy->isFloatingPointTy() != SrcElemTy->isFloatingPointTy()) &&
4383 "Only one type should be a floating point type");
4384 Type *IntTy =
4385 IntegerType::getIntNTy(V->getContext(), DL.getTypeSizeInBits(SrcElemTy));
4386 auto *VecIntTy = VectorType::get(IntTy, VF);
4387 Value *CastVal = Builder.CreateBitOrPointerCast(V, VecIntTy);
4388 return Builder.CreateBitOrPointerCast(CastVal, DstVTy);
4389}
4390
4391/// Return a vector containing interleaved elements from multiple
4392/// smaller input vectors.
4394 const Twine &Name) {
4395 unsigned Factor = Vals.size();
4396 assert(Factor > 1 && "Tried to interleave invalid number of vectors");
4397
4398 VectorType *VecTy = cast<VectorType>(Vals[0]->getType());
4399#ifndef NDEBUG
4400 for (Value *Val : Vals)
4401 assert(Val->getType() == VecTy && "Tried to interleave mismatched types");
4402#endif
4403
4404 // Scalable vectors cannot use arbitrary shufflevectors (only splats), so
4405 // must use intrinsics to interleave.
4406 if (VecTy->isScalableTy()) {
4407 assert(Factor <= 8 && "Unsupported interleave factor for scalable vectors");
4408 return Builder.CreateVectorInterleave(Vals, Name);
4409 }
4410
4411 // Fixed length. Start by concatenating all vectors into a wide vector.
4412 Value *WideVec = concatenateVectors(Builder, Vals);
4413
4414 // Interleave the elements into the wide vector.
4415 const unsigned NumElts = VecTy->getElementCount().getFixedValue();
4416 return Builder.CreateShuffleVector(
4417 WideVec, createInterleaveMask(NumElts, Factor), Name);
4418}
4419
4420// Try to vectorize the interleave group that \p Instr belongs to.
4421//
4422// E.g. Translate following interleaved load group (factor = 3):
4423// for (i = 0; i < N; i+=3) {
4424// R = Pic[i]; // Member of index 0
4425// G = Pic[i+1]; // Member of index 1
4426// B = Pic[i+2]; // Member of index 2
4427// ... // do something to R, G, B
4428// }
4429// To:
4430// %wide.vec = load <12 x i32> ; Read 4 tuples of R,G,B
4431// %R.vec = shuffle %wide.vec, poison, <0, 3, 6, 9> ; R elements
4432// %G.vec = shuffle %wide.vec, poison, <1, 4, 7, 10> ; G elements
4433// %B.vec = shuffle %wide.vec, poison, <2, 5, 8, 11> ; B elements
4434//
4435// Or translate following interleaved store group (factor = 3):
4436// for (i = 0; i < N; i+=3) {
4437// ... do something to R, G, B
4438// Pic[i] = R; // Member of index 0
4439// Pic[i+1] = G; // Member of index 1
4440// Pic[i+2] = B; // Member of index 2
4441// }
4442// To:
4443// %R_G.vec = shuffle %R.vec, %G.vec, <0, 1, 2, ..., 7>
4444// %B_U.vec = shuffle %B.vec, poison, <0, 1, 2, 3, u, u, u, u>
4445// %interleaved.vec = shuffle %R_G.vec, %B_U.vec,
4446// <0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11> ; Interleave R,G,B elements
4447// store <12 x i32> %interleaved.vec ; Write 4 tuples of R,G,B
4449 assert((!needsMaskForGaps() || !State.VF.isScalable()) &&
4450 "Masking gaps for scalable vectors is not yet supported.");
4452 Instruction *Instr = Group->getInsertPos();
4453
4454 // Prepare for the vector type of the interleaved load/store.
4455 Type *ScalarTy = getLoadStoreType(Instr);
4456 unsigned InterleaveFactor = Group->getFactor();
4457 auto *VecTy = VectorType::get(ScalarTy, State.VF * InterleaveFactor);
4458
4459 VPValue *BlockInMask = getMask();
4460 VPValue *Addr = getAddr();
4461 Value *ResAddr = State.get(Addr, VPLane(0));
4462
4463 auto CreateGroupMask = [&BlockInMask, &State,
4464 &InterleaveFactor](Value *MaskForGaps) -> Value * {
4465 if (State.VF.isScalable()) {
4466 assert(!MaskForGaps && "Interleaved groups with gaps are not supported.");
4467 assert(InterleaveFactor <= 8 &&
4468 "Unsupported deinterleave factor for scalable vectors");
4469 auto *ResBlockInMask = State.get(BlockInMask);
4470 SmallVector<Value *> Ops(InterleaveFactor, ResBlockInMask);
4471 return interleaveVectors(State.Builder, Ops, "interleaved.mask");
4472 }
4473
4474 if (!BlockInMask)
4475 return MaskForGaps;
4476
4477 Value *ResBlockInMask = State.get(BlockInMask);
4478 Value *ShuffledMask = State.Builder.CreateShuffleVector(
4479 ResBlockInMask,
4480 createReplicatedMask(InterleaveFactor, State.VF.getFixedValue()),
4481 "interleaved.mask");
4482 return MaskForGaps ? State.Builder.CreateBinOp(Instruction::And,
4483 ShuffledMask, MaskForGaps)
4484 : ShuffledMask;
4485 };
4486
4487 const DataLayout &DL = Instr->getDataLayout();
4488 // Vectorize the interleaved load group.
4489 if (isa<LoadInst>(Instr)) {
4490 Value *MaskForGaps = nullptr;
4491 if (needsMaskForGaps()) {
4492 MaskForGaps =
4493 createBitMaskForGaps(State.Builder, State.VF.getFixedValue(), *Group);
4494 assert(MaskForGaps && "Mask for Gaps is required but it is null");
4495 }
4496
4497 Instruction *NewLoad;
4498 if (BlockInMask || MaskForGaps) {
4499 Value *GroupMask = CreateGroupMask(MaskForGaps);
4500 Value *PoisonVec = PoisonValue::get(VecTy);
4501 NewLoad = State.Builder.CreateMaskedLoad(VecTy, ResAddr,
4502 Group->getAlign(), GroupMask,
4503 PoisonVec, "wide.masked.vec");
4504 } else
4505 NewLoad = State.Builder.CreateAlignedLoad(VecTy, ResAddr,
4506 Group->getAlign(), "wide.vec");
4507 applyMetadata(*NewLoad);
4508 // TODO: Also manage existing metadata using VPIRMetadata.
4509 Group->addMetadata(NewLoad);
4510
4512 if (VecTy->isScalableTy()) {
4513 // Scalable vectors cannot use arbitrary shufflevectors (only splats),
4514 // so must use intrinsics to deinterleave.
4515 assert(InterleaveFactor <= 8 &&
4516 "Unsupported deinterleave factor for scalable vectors");
4517 NewLoad = State.Builder.CreateIntrinsicWithoutFolding(
4518 Intrinsic::getDeinterleaveIntrinsicID(InterleaveFactor),
4519 NewLoad->getType(), NewLoad,
4520 /*FMFSource=*/nullptr, "strided.vec");
4521 }
4522
4523 auto CreateStridedVector = [&InterleaveFactor, &State,
4524 &NewLoad](unsigned Index) -> Value * {
4525 assert(Index < InterleaveFactor && "Illegal group index");
4526 if (State.VF.isScalable())
4527 return State.Builder.CreateExtractValue(NewLoad, Index);
4528
4529 // For fixed length VF, use shuffle to extract the sub-vectors from the
4530 // wide load.
4531 auto StrideMask =
4532 createStrideMask(Index, InterleaveFactor, State.VF.getFixedValue());
4533 return State.Builder.CreateShuffleVector(NewLoad, StrideMask,
4534 "strided.vec");
4535 };
4536
4537 for (unsigned I = 0, J = 0; I < InterleaveFactor; ++I) {
4538 Instruction *Member = Group->getMember(I);
4539
4540 // Skip the gaps in the group.
4541 if (!Member)
4542 continue;
4543
4544 Value *StridedVec = CreateStridedVector(I);
4545
4546 // If this member has different type, cast the result type.
4547 if (Member->getType() != ScalarTy) {
4548 VectorType *OtherVTy = VectorType::get(Member->getType(), State.VF);
4549 StridedVec =
4550 createBitOrPointerCast(State.Builder, StridedVec, OtherVTy, DL);
4551 }
4552
4553 if (Group->isReverse())
4554 StridedVec = State.Builder.CreateVectorReverse(StridedVec, "reverse");
4555
4556 State.set(VPDefs[J], StridedVec);
4557 ++J;
4558 }
4559 return;
4560 }
4561
4562 // The sub vector type for current instruction.
4563 auto *SubVT = VectorType::get(ScalarTy, State.VF);
4564
4565 // Vectorize the interleaved store group.
4566 Value *MaskForGaps =
4567 createBitMaskForGaps(State.Builder, State.VF.getKnownMinValue(), *Group);
4568 assert(((MaskForGaps != nullptr) == needsMaskForGaps()) &&
4569 "Mismatch between NeedsMaskForGaps and MaskForGaps");
4570 ArrayRef<VPValue *> StoredValues = getStoredValues();
4571 // Collect the stored vector from each member.
4572 SmallVector<Value *, 4> StoredVecs;
4573 unsigned StoredIdx = 0;
4574 for (unsigned i = 0; i < InterleaveFactor; i++) {
4575 assert((Group->getMember(i) || MaskForGaps) &&
4576 "Fail to get a member from an interleaved store group");
4577 Instruction *Member = Group->getMember(i);
4578
4579 // Skip the gaps in the group.
4580 if (!Member) {
4581 Value *Undef = PoisonValue::get(SubVT);
4582 StoredVecs.push_back(Undef);
4583 continue;
4584 }
4585
4586 Value *StoredVec = State.get(StoredValues[StoredIdx]);
4587 ++StoredIdx;
4588
4589 if (Group->isReverse())
4590 StoredVec = State.Builder.CreateVectorReverse(StoredVec, "reverse");
4591
4592 // If this member has different type, cast it to a unified type.
4593
4594 if (StoredVec->getType() != SubVT)
4595 StoredVec = createBitOrPointerCast(State.Builder, StoredVec, SubVT, DL);
4596
4597 StoredVecs.push_back(StoredVec);
4598 }
4599
4600 // Interleave all the smaller vectors into one wider vector.
4601 Value *IVec = interleaveVectors(State.Builder, StoredVecs, "interleaved.vec");
4602 Instruction *NewStoreInstr;
4603 if (BlockInMask || MaskForGaps) {
4604 Value *GroupMask = CreateGroupMask(MaskForGaps);
4605 NewStoreInstr = State.Builder.CreateMaskedStore(
4606 IVec, ResAddr, Group->getAlign(), GroupMask);
4607 } else
4608 NewStoreInstr =
4609 State.Builder.CreateAlignedStore(IVec, ResAddr, Group->getAlign());
4610
4611 applyMetadata(*NewStoreInstr);
4612 // TODO: Also manage existing metadata using VPIRMetadata.
4613 Group->addMetadata(NewStoreInstr);
4614}
4615
4616#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4618 VPSlotTracker &SlotTracker) const {
4620 O << Indent << "INTERLEAVE-GROUP with factor " << IG->getFactor() << ", ";
4622 VPValue *Mask = getMask();
4623 if (Mask) {
4624 O << ", ";
4625 Mask->printAsOperand(O, SlotTracker);
4626 }
4627
4628 unsigned OpIdx = 0;
4629 for (unsigned i = 0; i < IG->getFactor(); ++i) {
4630 if (!IG->getMember(i))
4631 continue;
4632 if (getNumStoreOperands() > 0) {
4633 O << "\n" << Indent << " store ";
4635 O << " to index " << i;
4636 } else {
4637 O << "\n" << Indent << " ";
4639 O << " = load from index " << i;
4640 }
4641 ++OpIdx;
4642 }
4643}
4644#endif
4645
4647 assert(State.VF.isScalable() &&
4648 "Only support scalable VF for EVL tail-folding.");
4650 "Masking gaps for scalable vectors is not yet supported.");
4652 Instruction *Instr = Group->getInsertPos();
4653
4654 // Prepare for the vector type of the interleaved load/store.
4655 Type *ScalarTy = getLoadStoreType(Instr);
4656 unsigned InterleaveFactor = Group->getFactor();
4657 assert(InterleaveFactor <= 8 &&
4658 "Unsupported deinterleave/interleave factor for scalable vectors");
4659 ElementCount WideVF = State.VF * InterleaveFactor;
4660 auto *VecTy = VectorType::get(ScalarTy, WideVF);
4661
4662 VPValue *Addr = getAddr();
4663 Value *ResAddr = State.get(Addr, VPLane(0));
4664 Value *EVL = State.get(getEVL(), VPLane(0));
4665 Value *InterleaveEVL = State.Builder.CreateMul(
4666 EVL, ConstantInt::get(EVL->getType(), InterleaveFactor), "interleave.evl",
4667 /* NUW= */ true, /* NSW= */ true);
4668 LLVMContext &Ctx = State.Builder.getContext();
4669
4670 Value *GroupMask = nullptr;
4671 if (VPValue *BlockInMask = getMask()) {
4672 SmallVector<Value *> Ops(InterleaveFactor, State.get(BlockInMask));
4673 GroupMask = interleaveVectors(State.Builder, Ops, "interleaved.mask");
4674 } else {
4675 GroupMask =
4676 State.Builder.CreateVectorSplat(WideVF, State.Builder.getTrue());
4677 }
4678
4679 // Vectorize the interleaved load group.
4680 if (isa<LoadInst>(Instr)) {
4681 CallInst *NewLoad = State.Builder.CreateIntrinsicWithoutFolding(
4682 VecTy, Intrinsic::vp_load, {ResAddr, GroupMask, InterleaveEVL}, nullptr,
4683 "wide.vp.load");
4684 NewLoad->addParamAttr(0,
4685 Attribute::getWithAlignment(Ctx, Group->getAlign()));
4686
4687 applyMetadata(*NewLoad);
4688 // TODO: Also manage existing metadata using VPIRMetadata.
4689 Group->addMetadata(NewLoad);
4690
4691 // Scalable vectors cannot use arbitrary shufflevectors (only splats),
4692 // so must use intrinsics to deinterleave.
4693 NewLoad = State.Builder.CreateIntrinsicWithoutFolding(
4694 Intrinsic::getDeinterleaveIntrinsicID(InterleaveFactor),
4695 NewLoad->getType(), NewLoad,
4696 /*FMFSource=*/nullptr, "strided.vec");
4697
4698 const DataLayout &DL = Instr->getDataLayout();
4699 for (unsigned I = 0, J = 0; I < InterleaveFactor; ++I) {
4700 Instruction *Member = Group->getMember(I);
4701 // Skip the gaps in the group.
4702 if (!Member)
4703 continue;
4704
4705 Value *StridedVec = State.Builder.CreateExtractValue(NewLoad, I);
4706 // If this member has different type, cast the result type.
4707 if (Member->getType() != ScalarTy) {
4708 VectorType *OtherVTy = VectorType::get(Member->getType(), State.VF);
4709 StridedVec =
4710 createBitOrPointerCast(State.Builder, StridedVec, OtherVTy, DL);
4711 }
4712
4713 State.set(getVPValue(J), StridedVec);
4714 ++J;
4715 }
4716 return;
4717 } // End for interleaved load.
4718
4719 // The sub vector type for current instruction.
4720 auto *SubVT = VectorType::get(ScalarTy, State.VF);
4721 // Vectorize the interleaved store group.
4722 ArrayRef<VPValue *> StoredValues = getStoredValues();
4723 // Collect the stored vector from each member.
4724 SmallVector<Value *, 4> StoredVecs;
4725 const DataLayout &DL = Instr->getDataLayout();
4726 for (unsigned I = 0, StoredIdx = 0; I < InterleaveFactor; I++) {
4727 Instruction *Member = Group->getMember(I);
4728 // Skip the gaps in the group.
4729 if (!Member) {
4730 StoredVecs.push_back(PoisonValue::get(SubVT));
4731 continue;
4732 }
4733
4734 Value *StoredVec = State.get(StoredValues[StoredIdx]);
4735 // If this member has different type, cast it to a unified type.
4736 if (StoredVec->getType() != SubVT)
4737 StoredVec = createBitOrPointerCast(State.Builder, StoredVec, SubVT, DL);
4738
4739 StoredVecs.push_back(StoredVec);
4740 ++StoredIdx;
4741 }
4742
4743 // Interleave all the smaller vectors into one wider vector.
4744 Value *IVec = interleaveVectors(State.Builder, StoredVecs, "interleaved.vec");
4745 CallInst *NewStore = State.Builder.CreateIntrinsicWithoutFolding(
4746 Type::getVoidTy(Ctx), Intrinsic::vp_store,
4747 {IVec, ResAddr, GroupMask, InterleaveEVL});
4748
4749 NewStore->addParamAttr(1,
4750 Attribute::getWithAlignment(Ctx, Group->getAlign()));
4751
4752 applyMetadata(*NewStore);
4753 // TODO: Also manage existing metadata using VPIRMetadata.
4754 Group->addMetadata(NewStore);
4755}
4756
4757#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4759 VPSlotTracker &SlotTracker) const {
4761 O << Indent << "INTERLEAVE-GROUP with factor " << IG->getFactor() << ", ";
4763 O << ", ";
4765 if (VPValue *Mask = getMask()) {
4766 O << ", ";
4767 Mask->printAsOperand(O, SlotTracker);
4768 }
4769
4770 unsigned OpIdx = 0;
4771 for (unsigned i = 0; i < IG->getFactor(); ++i) {
4772 if (!IG->getMember(i))
4773 continue;
4774 if (getNumStoreOperands() > 0) {
4775 O << "\n" << Indent << " vp.store ";
4777 O << " to index " << i;
4778 } else {
4779 O << "\n" << Indent << " ";
4781 O << " = vp.load from index " << i;
4782 }
4783 ++OpIdx;
4784 }
4785}
4786#endif
4787
4789 VPCostContext &Ctx) const {
4790 Instruction *InsertPos = getInsertPos();
4791 // Find the VPValue index of the interleave group. We need to skip gaps.
4792 unsigned InsertPosIdx = 0;
4793 for (unsigned Idx = 0; IG->getFactor(); ++Idx)
4794 if (auto *Member = IG->getMember(Idx)) {
4795 if (Member == InsertPos)
4796 break;
4797 InsertPosIdx++;
4798 }
4799 const VPValue *ValV = getNumDefinedValues() > 0
4800 ? getVPValue(InsertPosIdx)
4801 : getStoredValues()[InsertPosIdx];
4802 Type *ValTy = ValV->getScalarType();
4803 auto *VectorTy = cast<VectorType>(toVectorTy(ValTy, VF));
4804 unsigned AS =
4805 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4806
4807 unsigned InterleaveFactor = IG->getFactor();
4808 auto *WideVecTy = VectorType::get(ValTy, VF * InterleaveFactor);
4809
4810 // Holds the indices of existing members in the interleaved group.
4812 for (unsigned IF = 0; IF < InterleaveFactor; IF++)
4813 if (IG->getMember(IF))
4814 Indices.push_back(IF);
4815
4816 // Calculate the cost of the whole interleaved group.
4817 InstructionCost Cost = Ctx.TTI.getInterleavedMemoryOpCost(
4818 InsertPos->getOpcode(), WideVecTy, IG->getFactor(), Indices,
4819 IG->getAlign(), AS, Ctx.CostKind, getMask(), NeedsMaskForGaps);
4820
4821 if (!IG->isReverse())
4822 return Cost;
4823
4824 return Cost + IG->getNumMembers() *
4825 Ctx.TTI.getShuffleCost(TargetTransformInfo::SK_Reverse,
4826 VectorTy, VectorTy, {}, Ctx.CostKind,
4827 0);
4828}
4829
4831 return vputils::onlyScalarValuesUsed(this) &&
4832 (!IsScalable || vputils::onlyFirstLaneUsed(this));
4833}
4834
4835#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4837 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
4838 assert((getNumOperands() == 3 || getNumOperands() == 5) &&
4839 "unexpected number of operands");
4840 O << Indent << "EMIT ";
4842 O << " = WIDEN-POINTER-INDUCTION ";
4844 O << ", ";
4846 O << ", ";
4848 if (getNumOperands() == 5) {
4849 O << ", ";
4851 O << ", ";
4853 }
4854}
4855
4857 VPSlotTracker &SlotTracker) const {
4858 O << Indent << "EMIT ";
4860 O << " = EXPAND SCEV " << *Expr;
4861}
4862#endif
4863
4864#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4866 VPSlotTracker &SlotTracker) const {
4867 O << Indent << "EMIT ";
4869 O << " = WIDEN-CANONICAL-INDUCTION";
4870 printFlags(O);
4872}
4873#endif
4874
4876 auto &Builder = State.Builder;
4877 // Create a vector from the initial value.
4878 auto *VectorInit = getStartValue()->getLiveInIRValue();
4879
4880 Type *VecTy = State.VF.isScalar()
4881 ? VectorInit->getType()
4882 : VectorType::get(VectorInit->getType(), State.VF);
4883
4884 BasicBlock *VectorPH =
4885 State.CFG.VPBB2IRBB.at(getParent()->getCFGPredecessor(0));
4886 if (State.VF.isVector()) {
4887 auto *IdxTy = Builder.getInt32Ty();
4888 auto *One = ConstantInt::get(IdxTy, 1);
4889 IRBuilder<>::InsertPointGuard Guard(Builder);
4890 Builder.SetInsertPoint(VectorPH->getTerminator());
4891 auto *RuntimeVF = getRuntimeVF(Builder, IdxTy, State.VF);
4892 auto *LastIdx = Builder.CreateSub(RuntimeVF, One);
4893 VectorInit = Builder.CreateInsertElement(
4894 PoisonValue::get(VecTy), VectorInit, LastIdx, "vector.recur.init");
4895 }
4896
4897 // Create a phi node for the new recurrence.
4898 PHINode *Phi = PHINode::Create(VecTy, 2, "vector.recur");
4899 Phi->insertBefore(State.CFG.PrevBB->getFirstInsertionPt());
4900 Phi->addIncoming(VectorInit, VectorPH);
4901 State.set(this, Phi);
4902}
4903
4906 VPCostContext &Ctx) const {
4907 if (VF.isScalar())
4908 return Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
4909
4910 return 0;
4911}
4912
4913#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4915 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
4916 O << Indent << "FIRST-ORDER-RECURRENCE-PHI ";
4918 O << " = phi ";
4920}
4921#endif
4922
4924 // Reductions do not have to start at zero. They can start with
4925 // any loop invariant values.
4926 VPValue *StartVPV = getStartValue();
4927
4928 // In order to support recurrences we need to be able to vectorize Phi nodes.
4929 // Phi nodes have cycles, so we need to vectorize them in two stages. This is
4930 // stage #1: We create a new vector PHI node with no incoming edges. We'll use
4931 // this value when we vectorize all of the instructions that use the PHI.
4932 BasicBlock *VectorPH =
4933 State.CFG.VPBB2IRBB.at(getParent()->getCFGPredecessor(0));
4934 bool ScalarPHI = State.VF.isScalar() || isInLoop();
4935 Value *StartV = State.get(StartVPV, ScalarPHI);
4936 Type *VecTy = StartV->getType();
4937
4938 BasicBlock *HeaderBB = State.CFG.PrevBB;
4939 assert(State.CurrentParentLoop->getHeader() == HeaderBB &&
4940 "recipe must be in the vector loop header");
4941 auto *Phi = PHINode::Create(VecTy, 2, "vec.phi");
4942 Phi->insertBefore(HeaderBB->getFirstInsertionPt());
4943 State.set(this, Phi, isInLoop());
4944
4945 Phi->addIncoming(StartV, VectorPH);
4946}
4947
4948#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4950 VPSlotTracker &SlotTracker) const {
4951 O << Indent << "WIDEN-REDUCTION-PHI ";
4952
4954 O << " = phi (";
4955 printRecurrenceKind(O, Kind);
4956 O << ")";
4957 printFlags(O);
4959 if (getVFScaleFactor() > 1)
4960 O << " (VF scaled by 1/" << getVFScaleFactor() << ")";
4961}
4962#endif
4963
4965 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
4966 return vputils::onlyFirstLaneUsed(this);
4967}
4968
4970 executePhiRecipe(this, *this, State, /*IsScalar=*/false, Name);
4971}
4972
4974 VPCostContext &Ctx) const {
4975 return Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
4976}
4977
4978#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4980 VPSlotTracker &SlotTracker) const {
4981 O << Indent << "WIDEN-PHI ";
4982
4984 O << " = phi ";
4986}
4987#endif
4988
4990 BasicBlock *VectorPH =
4991 State.CFG.VPBB2IRBB.at(getParent()->getCFGPredecessor(0));
4992 Value *StartMask = State.get(getOperand(0));
4993 PHINode *Phi =
4994 State.Builder.CreatePHI(StartMask->getType(), 2, "active.lane.mask");
4995 Phi->addIncoming(StartMask, VectorPH);
4996 State.set(this, Phi);
4997}
4998
4999#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
5001 VPSlotTracker &SlotTracker) const {
5002 O << Indent << "ACTIVE-LANE-MASK-PHI ";
5003
5005 O << " = phi ";
5007}
5008#endif
5009
5010#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
5012 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
5013 O << Indent << "CURRENT-ITERATION-PHI ";
5014
5016 O << " = phi ";
5018}
5019#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
AMDGPU Lower Kernel Arguments
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const Function * getParent(const Value *V)
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static void replaceAllUsesWith(Value *Old, Value *New, SmallPtrSet< BasicBlock *, 32 > &FreshBBs, bool IsHuge)
Replace all old uses with new ones, and push the updated BBs into FreshBBs.
Hexagon Common GEP
Value * getPointer(Value *Ptr)
iv users
Definition IVUsers.cpp:48
static constexpr Value * getValue(Ty &ValueOrUse)
static std::pair< Value *, APInt > getMask(Value *WideMask, unsigned Factor, ElementCount LeafValueEC)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file provides a LoopVectorizationPlanner class.
static const SCEV * getAddressAccessSCEV(Value *Ptr, PredicatedScalarEvolution &PSE, const Loop *TheLoop)
Gets the address access SCEV for Ptr, if it should be used for cost modeling according to isAddressSC...
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static const Function * getCalledFunction(const Value *V)
static bool isOrdered(const Instruction *I)
MachineInstr unsigned OpIdx
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > & Cond
SI Fold Operands
This file contains some templates that are useful if you are working with the STL at all.
This file defines less commonly used SmallVector utilities.
This file defines the SmallVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
This file contains the declarations of different VPlan-related auxiliary helpers.
static Value * interleaveVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vals, const Twine &Name)
Return a vector containing interleaved elements from multiple smaller input vectors.
static void executePhiRecipe(VPSingleDefRecipe *R, VPPhiAccessors &Phi, VPTransformState &State, bool IsScalar, const Twine &Name)
Shared execute logic for VPPhi and VPWidenPHIRecipe.
static Value * createBitOrPointerCast(IRBuilderBase &Builder, Value *V, VectorType *DstVTy, const DataLayout &DL)
static Instruction::BinaryOps getSubRecurOpcode(RecurKind Kind)
SmallVector< Value *, 2 > VectorParts
static cl::opt< bool > VPlanPrintMetadata("vplan-print-metadata", cl::init(true), cl::Hidden, cl::desc("Controls the printing of recipe metadata when debugging."))
static void printRecurrenceKind(raw_ostream &OS, const RecurKind &Kind)
static unsigned getCalledFnOperandIndex(ArrayRef< VPValue * > Operands)
For call VPInstruction operands, return the operand index of the called function.
This file contains the declarations of the Vectorization Plan base classes:
void printAsOperand(OutputBuffer &OB, Prec P=Prec::Default, bool StrictlyWorse=false) const
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
Definition APInt.h:235
bool ule(const APInt &RHS) const
Unsigned less or equal comparison.
Definition APInt.h:1159
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
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
This class holds the attributes for a particular argument, parameter, function, or return value.
Definition Attributes.h:407
static LLVM_ABI Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI bool isBitOrNoopPointerCastable(Type *SrcTy, Type *DestTy, const DataLayout &DL)
Check whether a bitcast, inttoptr, or ptrtoint cast between these types is valid and a no-op.
static Type * makeCmpResultType(Type *opnd_type)
Create a result type for fcmp/icmp.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:763
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
static LLVM_ABI StringRef getPredicateName(Predicate P)
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
void setSuccessor(unsigned idx, BasicBlock *NewSucc)
This is the shared class of boolean and integer constants.
Definition Constants.h:87
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
A debug info location.
Definition DebugLoc.h:126
static DebugLoc getUnknown()
Definition DebugLoc.h:153
constexpr bool isVector() const
One or more elements.
Definition TypeSize.h:324
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:312
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:309
constexpr bool isScalar() const
Exactly one element.
Definition TypeSize.h:320
static bool isSupportedFloatingPointType(Type *Ty)
Returns true if Ty is a supported floating-point type for phi, select, or call FPMathOperators.
Definition Operator.h:302
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
LLVM_ABI void print(raw_ostream &O) const
Print fast-math flags to O.
Definition Operator.cpp:286
void setAllowContract(bool B=true)
Definition FMF.h:90
bool noSignedZeros() const
Definition FMF.h:67
bool noInfs() const
Definition FMF.h:66
void setAllowReciprocal(bool B=true)
Definition FMF.h:87
bool allowReciprocal() const
Definition FMF.h:68
void setNoSignedZeros(bool B=true)
Definition FMF.h:84
bool allowReassoc() const
Flag queries.
Definition FMF.h:64
bool approxFunc() const
Definition FMF.h:70
void setNoNaNs(bool B=true)
Definition FMF.h:78
void setAllowReassoc(bool B=true)
Flag setters.
Definition FMF.h:75
bool noNaNs() const
Definition FMF.h:65
void setApproxFunc(bool B=true)
Definition FMF.h:93
void setNoInfs(bool B=true)
Definition FMF.h:81
bool allowContract() const
Definition FMF.h:69
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
bool willReturn() const
Determine if the function will return.
Definition Function.h:646
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition Function.h:246
bool doesNotThrow() const
Determine if the function cannot unwind.
Definition Function.h:576
bool doesNotAccessMemory() const
Determine if the function does not access memory.
Definition Function.cpp:866
Type * getReturnType() const
Returns the type of the ret val.
Definition Function.h:216
Represents flags for the getelementptr instruction/expression.
static GEPNoWrapFlags none()
Common base class shared among various IRBuilders.
Definition IRBuilder.h:114
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2662
IntegerType * getInt1Ty()
Fetch the type representing a single bit.
Definition IRBuilder.h:519
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition IRBuilder.h:2716
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2650
LLVM_ABI Value * CreateVectorSpliceRight(Value *V1, Value *V2, Value *Offset, const Twine &Name="")
Create a vector.splice.right intrinsic call, or a shufflevector that produces the same result if the ...
CondBrInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
Definition IRBuilder.h:1216
LLVM_ABI Value * CreateSelectFMF(Value *C, Value *True, Value *False, FMFSource FMFSource, const Twine &Name="", Instruction *MDFrom=nullptr)
LLVM_ABI Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition IRBuilder.h:2709
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateFreeze(Value *V, const Twine &Name="")
Definition IRBuilder.h:2728
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition IRBuilder.h:534
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Definition IRBuilder.h:2092
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
Definition IRBuilder.h:2277
void setFastMathFlags(FastMathFlags NewFMF)
Set the fast-math flags to be used with generated fp-math operators.
Definition IRBuilder.h:300
LLVM_ABI Value * CreateVectorReverse(Value *V, const Twine &Name="")
Return a vector value that contains the vector V reversed.
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2379
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Definition IRBuilder.h:482
Value * CreateLogicalAnd(Value *Cond1, Value *Cond2, const Twine &Name="", Instruction *MDFrom=nullptr)
Definition IRBuilder.h:1770
LLVM_ABI Value * CreateOrReduce(Value *Src)
Create a vector int OR reduction intrinsic of the source vector.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Definition IRBuilder.h:477
Value * CreateCmp(CmpInst::Predicate Pred, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2509
Value * CreateNot(Value *V, const Twine &Name="")
Definition IRBuilder.h:1854
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2375
Value * CreateCountTrailingZeroElems(Type *ResTy, Value *Mask, bool ZeroIsPoison=true, const Twine &Name="")
Create a call to llvm.experimental_cttz_elts.
Definition IRBuilder.h:1154
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1439
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Definition IRBuilder.h:2121
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1422
ConstantInt * getFalse()
Get the constant value for i1 false.
Definition IRBuilder.h:462
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:1731
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2387
Value * CreateLogicalOr(Value *Cond1, Value *Cond2, const Twine &Name="", Instruction *MDFrom=nullptr)
Definition IRBuilder.h:1778
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2485
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Definition IRBuilder.h:1592
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1456
LLVM_ABI Value * CreateUnaryIntrinsic(Intrinsic::ID ID, Value *Op, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with 1 operand which is mangled on its type.
A struct for saving information about induction variables.
@ IK_IntInduction
Integer induction variable. Step = C.
static InstructionCost getInvalid(CostType Val=0)
bool isCast() const
bool isBinaryOp() const
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
const char * getOpcodeName() const
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
bool isUnaryOp() const
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:348
The group of interleaved loads/stores sharing the same stride and close to each other.
uint32_t getFactor() const
InstTy * getMember(uint32_t Index) const
Get the member with the given index Index.
bool isReverse() const
InstTy * getInsertPos() const
void addMetadata(InstTy *NewInst) const
Add metadata (e.g.
Align getAlign() const
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
Information for memory intrinsic cost model.
Root of the metadata hierarchy.
Definition Metadata.h:64
LLVM_ABI void print(raw_ostream &OS, const Module *M=nullptr, bool IsForDebug=false) const
Print.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
ScalarEvolution * getSE() const
Returns the ScalarEvolution analysis used.
static LLVM_ABI unsigned getOpcode(RecurKind Kind)
Returns the opcode corresponding to the RecurrenceKind.
static bool isAnyOfRecurrenceKind(RecurKind Kind)
Returns true if the recurrence kind is of the form select(cmp(),x,y) where one of (x,...
static LLVM_ABI bool isSubRecurrenceKind(RecurKind Kind)
Returns true if the recurrence kind is for a sub operation.
static bool isFindIVRecurrenceKind(RecurKind Kind)
Returns true if the recurrence kind is of the form select(cmp(),x,y) where one of (x,...
static bool isMinMaxRecurrenceKind(RecurKind Kind)
Returns true if the recurrence kind is any min/max kind.
This class represents an analyzed expression in the program.
This class represents the LLVM 'select' instruction.
This class provides computation of slot numbers for LLVM Assembly writing.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
reference emplace_back(ArgTypes &&... Args)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
static LLVM_ABI PartialReductionExtendKind getPartialReductionExtendKind(Instruction *I)
Get the kind of extension that an instruction represents.
static LLVM_ABI OperandValueInfo getOperandInfo(const Value *V)
Collect properties of V used in cost analysis, e.g. OP_PowerOf2.
llvm::VectorInstrContext VectorInstrContext
@ TCC_Free
Expected to fold away in lowering.
@ SK_Splice
Concatenates elements from the first input vector with elements of the second input vector.
@ SK_Reverse
Reverse the order of the vector.
CastContextHint
Represents a hint about the context in which a cast is used.
@ Reversed
The cast is used with a reversed load/store.
@ Masked
The cast is used with a masked load/store.
@ None
The cast is not used with a load/store of any kind.
@ Normal
The cast is used with a normal load/store.
@ Interleave
The cast is used with an interleaved load/store.
@ GatherScatter
The cast is used with a gather/scatter.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isByteTy() const
True if this is an instance of ByteType.
Definition Type.h:242
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:288
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:282
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:282
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:368
bool isStructTy() const
True if this is an instance of StructType.
Definition Type.h:276
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition Type.h:130
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:232
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:306
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
bool isIntOrPtrTy() const
Return true if this is an integer type or a pointer type.
Definition Type.h:270
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:313
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
value_op_iterator value_op_end()
Definition User.h:288
void setOperand(unsigned i, Value *Val)
Definition User.h:212
Value * getOperand(unsigned i) const
Definition User.h:207
value_op_iterator value_op_begin()
Definition User.h:285
void execute(VPTransformState &State) override
Generate the active lane mask phi of the vector loop.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
Definition VPlan.h:4380
RecipeListTy & getRecipeList()
Returns a reference to the list of recipes.
Definition VPlan.h:4433
iterator end()
Definition VPlan.h:4417
void insert(VPRecipeBase *Recipe, iterator InsertPt)
Definition VPlan.h:4446
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPWidenMemoryRecipe.
VPValue * getIncomingValue(unsigned Idx) const
Return incoming value number Idx.
Definition VPlan.h:2994
unsigned getNumIncomingValues() const
Return the number of incoming values, taking into account when normalized the first incoming value wi...
Definition VPlan.h:2989
bool usesFirstLaneOnly(const VPValue *Op) const override
Returns true if the recipe only uses the first lane of operand Op.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
bool isNormalized() const
A normalized blend is one that has an odd number of operands, whereby the first operand does not have...
Definition VPlan.h:2985
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition VPlan.h:94
const VPBlocksTy & getPredecessors() const
Definition VPlan.h:228
VPlan * getPlan()
Definition VPlan.cpp:211
static bool isHeader(const VPBlockBase *VPB, const VPDominatorTree &VPDT)
Returns true if VPB is a loop header, based on regions or VPDT in their absence.
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPBranchOnMaskRecipe.
void execute(VPTransformState &State) override
Generate the extraction of the appropriate bit from the block mask and the conditional branch.
VPlan-based builder utility analogous to IRBuilder.
LLVM_ABI_FOR_TEST void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
unsigned getNumDefinedValues() const
Returns the number of values defined by the VPDef.
Definition VPlanValue.h:578
VPValue * getVPSingleValue()
Returns the only VPValue defined by the VPDef.
Definition VPlanValue.h:551
VPValue * getVPValue(unsigned I)
Returns the VPValue with index I defined by the VPDef.
Definition VPlanValue.h:563
ArrayRef< VPRecipeValue * > definedValues()
Returns an ArrayRef of the values defined by the VPDef.
Definition VPlanValue.h:573
InductionDescriptor::InductionKind getInductionKind() const
Definition VPlan.h:4211
VPValue * getIndex() const
Definition VPlan.h:4208
VPValue * getStepValue() const
Definition VPlan.h:4209
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPDerivedIVRecipe.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
VPValue * getStartValue() const
Definition VPlan.h:4207
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
VPExpandSCEVRecipe(const SCEV *Expr)
bool isVectorToScalar() const
Returns true if this VPExpressionRecipe produces a single scalar.
void decompose()
Insert the recipes of the expression back into the VPlan, directly before the current recipe.
bool mayHaveSideEffects() const
Returns true if this expression contains recipes that may have side effects.
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Compute the cost of this recipe either using a recipe's specialized implementation or using the legac...
bool mayReadOrWriteMemory() const
Returns true if this expression contains recipes that may read from or write to memory.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this header phi recipe.
VPValue * getStartValue()
Returns the start value of the phi, if one is set.
Definition VPlan.h:2473
void execute(VPTransformState &State) override
Produce a vectorized histogram operation.
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPHistogramRecipe.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
VPValue * getMask() const
Return the mask operand if one was provided, or a null pointer if all lanes should be executed uncond...
Definition VPlan.h:2194
Class to record and manage LLVM IR flags.
Definition VPlan.h:704
FastMathFlagsTy FMFs
Definition VPlan.h:793
ReductionFlagsTy ReductionFlags
Definition VPlan.h:795
LLVM_ABI_FOR_TEST bool hasRequiredFlagsForOpcode(unsigned Opcode) const
Returns true if Opcode has its required flags set.
LLVM_ABI_FOR_TEST bool flagsValidForOpcode(unsigned Opcode) const
Returns true if the set flags are valid for Opcode.
WrapFlagsTy WrapFlags
Definition VPlan.h:787
void printFlags(raw_ostream &O) const
bool hasFastMathFlags() const
Returns true if the recipe has fast-math flags.
Definition VPlan.h:1010
static VPIRFlags getDefaultFlags(unsigned Opcode, Type *ResultTy=nullptr)
Returns default flags for Opcode and scalar ResultTy for opcodes that support it, asserts otherwise.
bool isReductionOrdered() const
Definition VPlan.h:1071
TruncFlagsTy TruncFlags
Definition VPlan.h:788
CmpInst::Predicate getPredicate() const
Definition VPlan.h:982
LLVM_ABI_FOR_TEST FastMathFlags getFastMathFlagsOrNone() const
ExactFlagsTy ExactFlags
Definition VPlan.h:790
void intersectFlags(const VPIRFlags &Other)
Only keep flags also present in Other.
uint8_t GEPFlagsStorage
Definition VPlan.h:791
GEPNoWrapFlags getGEPNoWrapFlags() const
Definition VPlan.h:1000
bool hasPredicate() const
Returns true if the recipe has a comparison predicate.
Definition VPlan.h:1005
DisjointFlagsTy DisjointFlags
Definition VPlan.h:789
FCmpFlagsTy FCmpFlags
Definition VPlan.h:794
NonNegFlagsTy NonNegFlags
Definition VPlan.h:792
bool isReductionInLoop() const
Definition VPlan.h:1077
void applyFlags(Instruction &I) const
Apply the IR flags to I.
Definition VPlan.h:939
uint8_t CmpPredStorage
Definition VPlan.h:786
RecurKind getRecurKind() const
Definition VPlan.h:1065
void execute(VPTransformState &State) override
The method which generates the output IR instructions that correspond to this VPRecipe,...
LLVM_ABI_FOR_TEST InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPIRInstruction.
VPIRInstruction(Instruction &I)
VPIRInstruction::create() should be used to create VPIRInstructions, as subclasses may need to be cre...
Definition VPlan.h:1729
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
void intersect(const VPIRMetadata &MD)
Intersect this VPIRMetadata object with MD, keeping only metadata nodes that are common to both.
VPIRMetadata()=default
void print(raw_ostream &O, VPSlotTracker &SlotTracker) const
Print metadata with node IDs.
void applyMetadata(Instruction &I) const
Add all metadata to I.
Type * getResultType() const
Definition VPlan.h:1590
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
void execute(VPTransformState &State) override
Generate the instruction.
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPInstruction.
This is a concrete Recipe that models a single VPlan-level instruction.
Definition VPlan.h:1234
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPInstruction.
VPInstruction(unsigned Opcode, ArrayRef< VPValue * > Operands, const VPIRFlags &Flags={}, const VPIRMetadata &MD={}, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", Type *ResultTy=nullptr)
bool doesGeneratePerAllLanes() const
Returns true if this recipe produces scalar values for all VF lanes.
@ ExtractLastActive
Extracts the last active lane from a set of vectors.
Definition VPlan.h:1336
@ Intrinsic
Calls a scalar intrinsic. The intrinsic ID is the last operand.
Definition VPlan.h:1356
@ ExtractLane
Extracts a single lane (first operand) from a set of vector operands.
Definition VPlan.h:1327
@ ExitingIVValue
Compute the exiting value of a wide induction after vectorization, that is the value of the last lane...
Definition VPlan.h:1340
@ WideIVStep
Scale the first operand (vector step) by the second operand (scalar-step).
Definition VPlan.h:1352
@ ResumeForEpilogue
Explicit user for the resume phi of the canonical induction in the main VPlan, used by the epilogue v...
Definition VPlan.h:1330
@ Unpack
Extracts all lanes from its (non-scalable) vector operand.
Definition VPlan.h:1277
@ ReductionStartVector
Start vector for reductions with 3 operands: the original start value, the identity value for the red...
Definition VPlan.h:1323
@ BuildVector
Creates a fixed-width vector containing all operands.
Definition VPlan.h:1272
@ BuildStructVector
Given operands of (the same) struct type, creates a struct of fixed- width vectors each containing a ...
Definition VPlan.h:1269
@ CanonicalIVIncrementForPart
Definition VPlan.h:1253
@ ComputeReductionResult
Reduce the operands to the final reduction result using the operation specified via the operation's V...
Definition VPlan.h:1280
bool hasResult() const
Definition VPlan.h:1441
bool opcodeMayReadOrWriteFromMemory() const
Returns true if the underlying opcode may read from or write to memory.
LLVM_DUMP_METHOD void dump() const
Print the VPInstruction to dbgs() (for debugging).
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the VPInstruction to O.
StringRef getName() const
Returns the symbolic name assigned to the VPInstruction.
Definition VPlan.h:1522
unsigned getOpcode() const
Definition VPlan.h:1420
bool usesFirstLaneOnly(const VPValue *Op) const override
Returns true if the recipe only uses the first lane of operand Op.
void addOperand(VPValue *Op)
Add Op as operand of this VPInstruction.
bool isVectorToScalar() const
Returns true if this VPInstruction produces a scalar value from a vector, e.g.
bool isSingleScalar() const
Returns true if the recipe produces a single scalar value.
unsigned getNumOperandsForOpcode() const
Return the number of operands determined by the opcode of the VPInstruction, excluding mask.
bool isMasked() const
Returns true if the VPInstruction has a mask operand.
Definition VPlan.h:1466
void execute(VPTransformState &State) override
Generate the instruction.
bool usesFirstPartOnly(const VPValue *Op) const override
Returns true if the recipe only uses the first part of operand Op.
bool needsMaskForGaps() const
Return true if the access needs a mask because of the gaps.
Definition VPlan.h:3098
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this recipe.
Instruction * getInsertPos() const
Definition VPlan.h:3102
const InterleaveGroup< Instruction > * getInterleaveGroup() const
Definition VPlan.h:3100
VPValue * getMask() const
Return the mask used by this recipe.
Definition VPlan.h:3092
ArrayRef< VPValue * > getStoredValues() const
Return the VPValues stored by this interleave group.
Definition VPlan.h:3121
VPValue * getAddr() const
Return the address accessed by this recipe.
Definition VPlan.h:3086
VPValue * getEVL() const
The VPValue of the explicit vector length.
Definition VPlan.h:3195
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
unsigned getNumStoreOperands() const override
Returns the number of stored operands of this interleave group.
Definition VPlan.h:3208
void execute(VPTransformState &State) override
Generate the wide load or store, and shuffles.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
unsigned getNumStoreOperands() const override
Returns the number of stored operands of this interleave group.
Definition VPlan.h:3158
void execute(VPTransformState &State) override
Generate the wide load or store, and shuffles.
In what follows, the term "input IR" refers to code that is fed into the vectorizer whereas the term ...
static VPLane getLastLaneForVF(const ElementCount &VF)
static VPLane getLaneFromEnd(const ElementCount &VF, unsigned Offset)
static VPLane getFirstLane()
Helper type to provide functions to access incoming values and blocks for phi-like recipes.
Definition VPlan.h:1609
virtual const VPRecipeBase * getAsRecipe() const =0
Return a VPRecipeBase* to the current object.
VPValue * getIncomingValueForBlock(const VPBasicBlock *VPBB) const
Returns the incoming value for VPBB. VPBB must be an incoming block.
void removeIncomingValueFor(VPBlockBase *IncomingBlock) const
Removes the incoming value for IncomingBlock, which must be a predecessor.
detail::zippy< llvm::detail::zip_first, VPUser::const_operand_range, const_incoming_blocks_range > incoming_values_and_blocks() const
Returns an iterator range over pairs of incoming values and corresponding incoming blocks.
Definition VPlan.h:1658
VPValue * getIncomingValue(unsigned Idx) const
Returns the incoming VPValue with index Idx.
Definition VPlan.h:1618
void printPhiOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const
Print the recipe.
void setIncomingValueForBlock(const VPBasicBlock *VPBB, VPValue *V) const
Sets the incoming value for VPBB to V.
void execute(VPTransformState &State) override
Generates phi nodes for live-outs (from a replicate region) as needed to retain SSA form.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition VPlan.h:411
bool mayReadFromMemory() const
Returns true if the recipe may read from memory.
bool mayHaveSideEffects() const
Returns true if the recipe may have side-effects.
virtual void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const =0
Each concrete VPRecipe prints itself, without printing common information, like debug info or metadat...
VPRegionBlock * getRegion()
Definition VPlan.h:4779
LLVM_ABI_FOR_TEST void dump() const
Dump the recipe to stderr (for debugging).
Definition VPlan.cpp:117
bool isPhi() const
Returns true for PHI-like recipes.
bool mayWriteToMemory() const
Returns true if the recipe may write to memory.
VPRecipeTy getVPRecipeID() const
Definition VPlan.h:529
virtual InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const
Compute the cost of this recipe either using a recipe's specialized implementation or using the legac...
VPBasicBlock * getParent()
Definition VPlan.h:483
DebugLoc getDebugLoc() const
Returns the debug location of the recipe.
Definition VPlan.h:561
void moveBefore(VPBasicBlock &BB, iplist< VPRecipeBase >::iterator I)
Unlink this recipe and insert into BB before I.
bool isSafeToSpeculativelyExecute() const
Return true if we can safely execute this recipe unconditionally even if it is masked originally.
void insertBefore(VPRecipeBase *InsertPos)
Insert an unlinked recipe into a basic block immediately before the specified recipe.
void insertAfter(VPRecipeBase *InsertPos)
Insert an unlinked Recipe into a basic block immediately after the specified Recipe.
iplist< VPRecipeBase >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
VPRecipeBase(VPRecipeTy SC, ArrayRef< VPValue * > Operands, DebugLoc DL=DebugLoc::getUnknown())
Definition VPlan.h:473
InstructionCost cost(ElementCount VF, VPCostContext &Ctx)
Return the cost of this recipe, taking into account if the cost computation should be skipped and the...
void print(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const
Print the recipe, delegating to printRecipe().
void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
void moveAfter(VPRecipeBase *MovePos)
Unlink this recipe from its current VPBasicBlock and insert it into the VPBasicBlock that MovePos liv...
Type * getScalarType() const
Returns the scalar type of this VPRecipeValue.
Definition VPlanValue.h:354
friend class VPValue
Definition VPlanValue.h:333
void execute(VPTransformState &State) override
Generate the reduction in the loop.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
VPValue * getEVL() const
The VPValue of the explicit vector length.
Definition VPlan.h:3366
unsigned getVFScaleFactor() const
Get the factor that the VF of this recipe's output should be scaled by, or 1 if it isn't scaled.
Definition VPlan.h:2900
bool isInLoop() const
Returns true if the phi is part of an in-loop reduction.
Definition VPlan.h:2919
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
void execute(VPTransformState &State) override
Generate the phi/select nodes.
bool isConditional() const
Return true if the in-loop reduction is conditional.
Definition VPlan.h:3308
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of VPReductionRecipe.
VPValue * getVecOp() const
The VPValue of the vector value to be reduced.
Definition VPlan.h:3319
VPValue * getCondOp() const
The VPValue of the condition for the block.
Definition VPlan.h:3321
RecurKind getRecurrenceKind() const
Return the recurrence kind for the in-loop reduction.
Definition VPlan.h:3304
bool isPartialReduction() const
Returns true if the reduction outputs a vector with a scaled down VF.
Definition VPlan.h:3310
VPValue * getChainOp() const
The VPValue of the scalar Chain being accumulated.
Definition VPlan.h:3317
bool isInLoop() const
Returns true if the reduction is in-loop.
Definition VPlan.h:3312
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
void execute(VPTransformState &State) override
Generate the reduction in the loop.
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition VPlan.h:4605
bool isReplicator() const
An indicator whether this region is to generate multiple replicated instances of output IR correspond...
Definition VPlan.h:4681
void execute(VPTransformState &State) override
Generate replicas of the desired Ingredient.
bool isSingleScalar() const
Returns true if the recipe produces a single scalar value.
Definition VPlan.h:3447
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPReplicateRecipe.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
static Type * computeScalarType(const Instruction *I, ArrayRef< VPValue * > Operands)
Compute the scalar result type for a VPReplicateRecipe wrapping I with Operands (excluding any predic...
static InstructionCost computeCallCost(Function *CalledFn, Type *ResultTy, ArrayRef< const VPValue * > ArgOps, bool IsSingleScalar, ElementCount VF, VPCostContext &Ctx)
Return the cost of scalarizing a call to CalledFn with argument operands ArgOps for a given VF.
unsigned getOpcode() const
Definition VPlan.h:3485
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPScalarIVStepsRecipe.
bool doesGeneratePerAllLanes() const
Returns true if this recipe produces scalar values for all VF lanes.
VPValue * getStepValue() const
Definition VPlan.h:4266
VPValue * getStartIndex() const
Return the StartIndex, or null if known to be zero, valid only after unrolling.
Definition VPlan.h:4274
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
void execute(VPTransformState &State) override
Generate the scalarized versions of the phi node as needed by their users.
VPSingleDefRecipe is a base class for recipes that model a sequence of one or more output IR that def...
Definition VPlan.h:619
Instruction * getUnderlyingInstr()
Returns the underlying instruction.
Definition VPlan.h:689
LLVM_ABI_FOR_TEST LLVM_DUMP_METHOD void dump() const
Print this VPSingleDefRecipe to dbgs() (for debugging).
VPSingleDefRecipe(VPRecipeTy SC, ArrayRef< VPValue * > Operands, DebugLoc DL=DebugLoc::getUnknown())
Definition VPlan.h:621
This class can be used to assign names to VPValues.
A symbolic live-in VPValue, used for values like vector trip count, VF, and VFxUF.
Definition VPlanValue.h:217
This class augments VPValue with operands which provide the inverse def-use edges from VPValue's user...
Definition VPlanValue.h:401
void printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const
Print the operands to O.
Definition VPlan.cpp:1541
operand_range operands()
Definition VPlanValue.h:474
unsigned getNumOperands() const
Definition VPlanValue.h:441
VPValue * getOperand(unsigned N) const
Definition VPlanValue.h:442
void addOperand(VPValue *Operand)
Definition VPlanValue.h:427
This is the base class of the VPlan Def/Use graph, used for modeling the data flow into,...
Definition VPlanValue.h:50
Type * getScalarType() const
Returns the scalar type of this VPValue, dispatching based on the concrete subclass.
Definition VPlan.cpp:149
Value * getLiveInIRValue() const
Return the underlying IR value for a VPIRValue.
Definition VPlan.cpp:143
bool isDefinedOutsideLoopRegions() const
Returns true if the VPValue is defined outside any loop.
Definition VPlan.cpp:1492
VPRecipeBase * getDefiningRecipe()
Returns the recipe defining this VPValue or nullptr if it is not defined by a recipe,...
Definition VPlan.cpp:130
void printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const
Definition VPlan.cpp:1537
Value * getUnderlyingValue() const
Return the underlying Value attached to this VPValue.
Definition VPlanValue.h:75
void setUnderlyingValue(Value *Val)
Definition VPlanValue.h:209
VPUser * getSingleUser()
Return the single user of this value, or nullptr if there is not exactly one user.
Definition VPlanValue.h:179
VPValue * getVFValue() const
Definition VPlan.h:2288
void execute(VPTransformState &State) override
The method which generates the output IR instructions that correspond to this VPRecipe,...
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
Type * getSourceElementType() const
Definition VPlan.h:2285
int64_t getStride() const
Definition VPlan.h:2286
void materializeOffset(unsigned Part=0)
Adds the offset operand to the recipe.
VPValue * getStride() const
Definition VPlan.h:2362
Type * getSourceElementType() const
Definition VPlan.h:2377
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
void execute(VPTransformState &State) override
The method which generates the output IR instructions that correspond to this VPRecipe,...
VPValue * getVFxPart() const
Definition VPlan.h:2364
bool usesFirstLaneOnly(const VPValue *Op) const override
Returns true if the recipe only uses the first lane of operand Op.
operand_range args()
Definition VPlan.h:2145
Function * getCalledScalarFunction() const
Definition VPlan.h:2141
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPWidenCallRecipe.
void execute(VPTransformState &State) override
Produce a widened version of the call instruction.
static InstructionCost computeCallCost(Function *Variant, VPCostContext &Ctx)
Return the cost of widening a call using the vector function Variant.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
Instruction::CastOps getOpcode() const
Definition VPlan.h:1916
LLVM_ABI_FOR_TEST void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
LLVM_ABI_FOR_TEST void execute(VPTransformState &State) override
Produce widened copies of the cast.
LLVM_ABI_FOR_TEST InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPWidenCastRecipe.
void execute(VPTransformState &State) override
Generate the gep nodes.
Type * getSourceElementType() const
Definition VPlan.h:2242
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
bool usesFirstLaneOnly(const VPValue *Op) const override
Returns true if the recipe only uses the first lane of operand Op.
VPIRValue * getStartValue() const
Returns the start value of the induction.
Definition VPlan.h:2559
VPValue * getStepValue()
Returns the step value of the induction.
Definition VPlan.h:2562
const InductionDescriptor & getInductionDescriptor() const
Returns the induction descriptor for the recipe.
Definition VPlan.h:2582
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPWidenIntOrFpInductionRecipe.
TruncInst * getTruncInst()
Returns the first defined value as TruncInst, if it is one or nullptr otherwise.
Definition VPlan.h:2670
bool isCanonical() const
Returns true if the induction is canonical, i.e.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
CallInst * createVectorCall(VPTransformState &State)
Helper function to produce the widened intrinsic call.
Intrinsic::ID getVectorIntrinsicID() const
Return the ID of the intrinsic.
Definition VPlan.h:2030
LLVM_ABI_FOR_TEST void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
StringRef getIntrinsicName() const
Return to name of the intrinsic as string.
static InstructionCost computeCallCost(Intrinsic::ID ID, ArrayRef< const VPValue * > Operands, const VPRecipeWithIRFlags &R, ElementCount VF, VPCostContext &Ctx)
Compute the cost of a vector intrinsic with ID and Operands.
LLVM_ABI_FOR_TEST bool usesFirstLaneOnly(const VPValue *Op) const override
Returns true if the VPUser only uses the first lane of operand Op.
LLVM_ABI_FOR_TEST void execute(VPTransformState &State) override
Produce a widened version of the vector intrinsic.
LLVM_ABI_FOR_TEST InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this vector intrinsic.
static InstructionCost computeMemIntrinsicCost(Intrinsic::ID IID, Type *Ty, bool IsMasked, Align Alignment, VPCostContext &Ctx)
Helper function for computing the cost of vector memory intrinsic.
void execute(VPTransformState &State) override
Produce a widened version of the vector memory intrinsic.
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this vector memory intrinsic.
bool IsMasked
Whether the memory access is masked.
Definition VPlan.h:3746
bool isConsecutive() const
Return whether the loaded-from / stored-to addresses are consecutive.
Definition VPlan.h:3771
Instruction & Ingredient
Definition VPlan.h:3737
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const
Return the cost of this VPWidenMemoryRecipe.
bool Consecutive
Whether the accessed addresses are consecutive.
Definition VPlan.h:3743
VPValue * getMask() const
Return the mask used by this recipe.
Definition VPlan.h:3781
Align Alignment
Alignment information for this memory access.
Definition VPlan.h:3740
virtual VPRecipeBase * getAsRecipe()=0
Return a VPRecipeBase* to the current object.
VPValue * getAddr() const
Return the address accessed by this recipe.
Definition VPlan.h:3774
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPWidenPHIRecipe.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
void execute(VPTransformState &State) override
Generate the phi/select nodes.
bool onlyScalarsGenerated(bool IsScalable)
Returns true if only scalar values will be generated.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPWidenRecipe.
void execute(VPTransformState &State) override
Produce a widened instruction using the opcode and operands of the recipe, processing State....
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
unsigned getOpcode() const
Definition VPlan.h:1859
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4792
const DataLayout & getDataLayout() const
Definition VPlan.h:4999
VPValue * getTripCount() const
The trip count of the original loop.
Definition VPlan.h:4953
VPIRValue * getConstantInt(Type *Ty, uint64_t Val, bool IsSigned=false)
Return a VPIRValue wrapping a ConstantInt with the given type and value.
Definition VPlan.h:5101
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:394
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:258
void mutateType(Type *Ty)
Mutate the type of this Value to be of the specified type.
Definition Value.h:807
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
Base class of all SIMD vector types.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Type * getElementType() const
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr LeafTy multiplyCoefficientBy(ScalarTy RHS) const
Definition TypeSize.h:256
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
Definition TypeSize.h:252
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
iterator erase(iterator where)
Definition ilist.h:204
pointer remove(iterator &IT)
Definition ilist.h:188
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
LLVM_ABI Intrinsic::ID getDeinterleaveIntrinsicID(unsigned Factor)
Returns the corresponding llvm.vector.deinterleaveN intrinsic for factor N.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI AttributeSet getFnAttributes(LLVMContext &C, ID id)
Return the function attributes for an intrinsic.
LLVM_ABI StringRef getBaseName(ID id)
Return the LLVM name for an intrinsic, without encoded types for overloading, such as "llvm....
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
auto m_Cmp()
Matches any compare instruction and ignore it.
bool match(Val *V, const Pattern &P)
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
LogicalOp_match< LHS, RHS, Instruction::And, true > m_c_LogicalAnd(const LHS &L, const RHS &R)
Matches L && R with LHS and RHS in either order.
LogicalOp_match< LHS, RHS, Instruction::Or, true > m_c_LogicalOr(const LHS &L, const RHS &R)
Matches L || R with LHS and RHS in either order.
specific_intval< 1 > m_False()
specific_intval< 1 > m_True()
auto m_VPValue()
Match an arbitrary VPValue and ignore it.
VPInstruction_match< VPInstruction::BranchOnCond > m_BranchOnCond()
VPInstruction_match< VPInstruction::Reverse, Op0_t > m_Reverse(const Op0_t &Op0)
initializer< Ty > init(const Ty &Val)
NodeAddr< DefNode * > Def
Definition RDFGraph.h:384
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
bool isSingleScalar(const VPValue *VPV)
Returns true if VPV is a single scalar, either because it produces the same value for all lanes or on...
bool isAddressSCEVForCost(const SCEV *Addr, ScalarEvolution &SE, const Loop *L)
Returns true if Addr is an address SCEV that can be passed to TTI::getAddressComputationCost,...
bool onlyFirstPartUsed(const VPValue *Def)
Returns true if only the first part of Def is used.
Intrinsic::ID getIntrinsicID(const Ty *R)
Return the intrinsic ID underlying a call.
Definition VPlanUtils.h:85
bool onlyFirstLaneUsed(const VPValue *Def)
Returns true if only the first lane of Def is used.
bool onlyScalarValuesUsed(const VPValue *Def)
Returns true if only scalar values of Def are used by all users.
bool isUsedByLoadStoreAddress(const VPValue *V)
Returns true if V is used as part of the address of another load or store.
const SCEV * getSCEVExprForVPValue(const VPValue *V, PredicatedScalarEvolution &PSE, const Loop *L=nullptr)
Return the SCEV expression for V.
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
LLVM_ABI Value * createSimpleReduction(IRBuilderBase &B, Value *Src, RecurKind RdxKind)
Create a reduction of the given vector.
@ Offset
Definition DWP.cpp:578
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
Definition STLExtras.h:830
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
LLVM_ABI Intrinsic::ID getMinMaxReductionIntrinsicOp(Intrinsic::ID RdxID)
Returns the min/max intrinsic used when expanding a min/max reduction.
InstructionCost Cost
@ Undef
Value of the register doesn't matter.
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
VectorInstrContext
Represents a hint about the context in which a vector instruction or intrinsic is used.
@ None
The instruction is not folded.
@ BinaryOp
One of the operands is a binary op.
auto map_to_vector(ContainerTy &&C, FuncTy &&F)
Map a range to a SmallVector with element types deduced from the mapping.
Value * getRuntimeVF(IRBuilderBase &B, Type *Ty, ElementCount VF)
Return the runtime value for VF.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2208
void interleaveComma(const Container &c, StreamT &os, UnaryFunctor each_fn)
Definition STLExtras.h:2313
auto cast_or_null(const Y &Val)
Definition Casting.h:714
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
Align getLoadStoreAlignment(const Value *I)
A helper function that returns the alignment of load or store instruction.
bool isa_and_nonnull(const Y &Val)
Definition Casting.h:676
LLVM_ABI Value * createMinMaxOp(IRBuilderBase &Builder, RecurKind RK, Value *Left, Value *Right)
Returns a Min/Max operation corresponding to MinMaxRecurrenceKind.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
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
LLVM_ABI Constant * createBitMaskForGaps(IRBuilderBase &Builder, unsigned VF, const InterleaveGroup< Instruction > &Group)
Create a mask that filters the members of an interleave group where there are gaps.
LLVM_ABI llvm::SmallVector< int, 16 > createStrideMask(unsigned Start, unsigned Stride, unsigned VF)
Create a stride shuffle mask.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
ElementCount getVectorizedTypeVF(Type *Ty)
Returns the number of vector elements for a vectorized type.
LLVM_ABI llvm::SmallVector< int, 16 > createReplicatedMask(unsigned ReplicationFactor, unsigned VF)
Create a mask with replicated elements.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool isPointerTy(const Type *T)
Definition SPIRVUtils.h:380
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
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
Type * toVectorizedTy(Type *Ty, ElementCount EC)
A helper for converting to vectorized types.
cl::opt< unsigned > ForceTargetInstructionCost
LLVM_ABI Type * computeScalarTypeForInstruction(unsigned Opcode, ArrayRef< VPValue * > Operands)
Compute the scalar result type for an IR Opcode given Operands.
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
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
Definition STLExtras.h:322
LLVM_ABI bool isVectorIntrinsicWithStructReturnOverloadAtField(Intrinsic::ID ID, int RetIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic that returns a struct is overloaded at the struct elem...
@ Other
Any other memory.
Definition ModRef.h:68
static const MachineInstrBuilder & addOffset(const MachineInstrBuilder &MIB, int Offset)
LLVM_ABI llvm::SmallVector< int, 16 > createInterleaveMask(unsigned VF, unsigned NumVecs)
Create an interleave shuffle mask.
RecurKind
These are the kinds of recurrences that we support.
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
@ FMinimumNum
FP min with llvm.minimumnum semantics.
@ FindIV
FindIV reduction with select(icmp(),x,y) where one of (x,y) is a loop induction variable (increasing ...
@ Or
Bitwise or logical OR of integers.
@ FMinimum
FP min with llvm.minimum semantics.
@ FMaxNum
FP max with llvm.maxnum semantics including NaNs.
@ Mul
Product of integers.
@ FSub
Subtraction of floats.
@ FAddChainWithSubs
A chain of fadds and fsubs.
@ None
Not a recurrence.
@ AnyOf
AnyOf reduction with select(cmp(),x,y) where one of (x,y) is loop invariant, and both x and y are int...
@ Xor
Bitwise or logical XOR of integers.
@ FindLast
FindLast reduction with select(cmp(),x,y) where x and y.
@ FMax
FP max implemented in terms of select(cmp()).
@ FMaximum
FP max with llvm.maximum semantics.
@ FMulAdd
Sum of float products with llvm.fmuladd(a * b + sum).
@ FMul
Product of floats.
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ FMin
FP min implemented in terms of select(cmp()).
@ FMinNum
FP min with llvm.minnum semantics including NaNs.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
@ AddChainWithSubs
A chain of adds and subs.
@ FAdd
Sum of floats.
@ FMaximumNum
FP max with llvm.maximumnum semantics.
@ UMax
Unsigned integer max implemented in terms of select(cmp()).
LLVM_ABI bool isVectorIntrinsicWithScalarOpAtArg(Intrinsic::ID ID, unsigned ScalarOpdIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic has a scalar operand.
LLVM_ABI Value * getRecurrenceIdentity(RecurKind K, Type *Tp, FastMathFlags FMF)
Given information about an recurrence kind, return the identity for the @llvm.vector....
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
LLVM_ABI Value * createOrderedReduction(IRBuilderBase &B, RecurKind RdxKind, Value *Src, Value *Start)
Create an ordered reduction intrinsic using the given recurrence kind RdxKind.
ArrayRef< Type * > getContainedTypes(Type *const &Ty)
Returns the types contained in Ty.
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
LLVM_ABI bool isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID, int OpdIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic is overloaded on the type of the operand at index OpdI...
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Struct to hold various analysis needed for cost computations.
static bool isFreeScalarIntrinsic(Intrinsic::ID ID)
Returns true if ID is a pseudo intrinsic that is dropped via scalarization rather than widened.
Definition VPlan.cpp:1990
TargetTransformInfo::TargetCostKind CostKind
void execute(VPTransformState &State) override
Generate the phi nodes.
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this first-order recurrence phi recipe.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
An overlay for VPIRInstructions wrapping PHI nodes enabling convenient use cast/dyn_cast/isa and exec...
Definition VPlan.h:1787
PHINode & getIRPhi()
Definition VPlan.h:1800
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
void execute(VPTransformState &State) override
The method which generates the output IR instructions that correspond to this VPRecipe,...
void execute(VPTransformState &State) override
Generate the instruction.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
VPRecipeWithIRFlags(VPRecipeTy SC, ArrayRef< VPValue * > Operands, const VPIRFlags &Flags, DebugLoc DL=DebugLoc::getUnknown())
Definition VPlan.h:1125
InstructionCost getCostForRecipeWithOpcode(unsigned Opcode, ElementCount VF, VPCostContext &Ctx) const
Compute the cost for this recipe for VF, using Opcode and Ctx.
SmallDenseMap< const VPBasicBlock *, BasicBlock * > VPBB2IRBB
A mapping of each VPBasicBlock to the corresponding BasicBlock.
VPTransformState holds information passed down when "executing" a VPlan, needed for generating the ou...
struct llvm::VPTransformState::CFGState CFG
Value * get(const VPValue *Def, bool IsScalar=false)
Get the generated vector Value for a given VPValue Def if IsScalar is false, otherwise return the gen...
Definition VPlan.cpp:315
IRBuilderBase & Builder
Hold a reference to the IRBuilder used to generate output IR code.
ElementCount VF
The chosen Vectorization Factor of the loop being vectorized.
void execute(VPTransformState &State) override
Generate the wide load or gather.
VPRecipeBase * getAsRecipe() override
Return a VPRecipeBase* to the current object.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPWidenLoadEVLRecipe.
VPValue * getEVL() const
Return the EVL operand.
Definition VPlan.h:3866
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
void execute(VPTransformState &State) override
Generate a wide load or gather.
VPRecipeBase * getAsRecipe() override
Return a VPRecipeBase* to the current object.
VPValue * getStoredValue() const
Return the address accessed by this recipe.
Definition VPlan.h:3968
void execute(VPTransformState &State) override
Generate the wide store or scatter.
VPRecipeBase * getAsRecipe() override
Return a VPRecipeBase* to the current object.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPWidenStoreEVLRecipe.
VPValue * getEVL() const
Return the EVL operand.
Definition VPlan.h:3971
void execute(VPTransformState &State) override
Generate a wide store or scatter.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
VPRecipeBase * getAsRecipe() override
Return a VPRecipeBase* to the current object.
VPValue * getStoredValue() const
Return the value stored by this recipe.
Definition VPlan.h:3916