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.
452 unsigned Idx = getCalledFnOperandIndex(Operands);
453 return cast<Function>(cast<VPIRValue>(Operands[Idx])->getValue());
454}
455
457 ArrayRef<VPValue *> Operands) {
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:
574 return getCalledFunction(Operands)->getReturnType();
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
595 ArrayRef<VPValue *> Operands) {
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();
602 return computeScalarTypeForInstruction(Opcode, Operands);
603}
604
606 const VPIRFlags &Flags, const VPIRMetadata &MD,
607 DebugLoc DL, const Twine &Name, Type *ResultTy)
609 VPRecipeBase::VPInstructionSC, Operands,
610 ResultTy ? ResultTy
611 : computeScalarTypeForInstruction(Opcode, Operands),
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.getInt32(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.getInt32(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.
2974 // TODO: Also handle truncated inductions.
2975 assert(!getTruncInst() &&
2976 "truncated inductions should be costed by the legacy model");
2978 InstructionCost Cost = Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
2979 Type *StepTy = getScalarType();
2980 unsigned IncOpc = ID.getKind() == InductionDescriptor::IK_IntInduction
2981 ? Instruction::Add
2982 : ID.getInductionOpcode();
2983 assert(IncOpc != Instruction::BinaryOpsEnd &&
2984 "induction must have a valid increment opcode");
2985 return Cost + Ctx.TTI.getArithmeticInstrCost(IncOpc, toVectorTy(StepTy, VF),
2986 Ctx.CostKind);
2987}
2988
2990 VPCostContext &Ctx) const {
2991 // The cost model for this is modelled on expandVPDerivedIV in
2992 // VPlanTransforms.cpp. In order to avoid overly pessimistic costs that can
2993 // negatively affect vectorization it takes into account any expected
2994 // simplifications that happen in simplifyRecipe.
2995 switch (getInductionKind()) {
2996 default:
2997 // TODO: Compute cost for remaining kinds.
2998 break;
3000 // There are currently no tests that expose a path where all lanes are
3001 // used, so it's better to bail out for now.
3002 if (!vputils::onlyFirstLaneUsed(this))
3003 break;
3004
3005 // Start off by assuming we need both mul and add, then refine this.
3006 bool NeedsMul = true, NeedsAdd = true, NeedsShl = false;
3007
3008 // If the start value is zero the add gets folded away.
3009 if (auto *StartC = dyn_cast<VPConstantInt>(getStartValue()))
3010 NeedsAdd = !StartC->isZero();
3011
3012 // For some values of step the arithmetic changes:
3013 // 1. A step of 1 requires no operation.
3014 // 2. A step of -1 requires a negate.
3015 // 3. A power-of-2 step will use a shl, instead of a mul.
3016 Type *StepTy = getStepValue()->getScalarType();
3018 if (auto *StepC = dyn_cast<VPConstantInt>(getStepValue())) {
3019 if (StepC->isOne())
3020 NeedsMul = false;
3021 else if (StepC->getAPInt().isAllOnes()) {
3022 // This will most likely end up as a negate in simplifyRecipe, and
3023 // the negate will be combined with the add to make a sub.
3024 // NOTE: This is perhaps an invalid assumption that the cost of an
3025 // 'add' is the same as a 'sub'.
3026 NeedsMul = false;
3027 NeedsAdd = true;
3028 } else if (StepC->getAPInt().isPowerOf2()) {
3029 // This will most likely end up as a shift-left in simplifyRecipe
3030 NeedsMul = false;
3031 NeedsShl = true;
3032 }
3033 }
3034
3035 // Add the cost of the conversion from index to step type if the index
3036 // will be used.
3037 Type *IndexTy = getIndex()->getScalarType();
3038 unsigned StepTySize = StepTy->getScalarSizeInBits();
3039 unsigned IndexTySize = IndexTy->getScalarSizeInBits();
3040 if ((NeedsAdd || NeedsMul || NeedsShl) && StepTySize != IndexTySize) {
3041 unsigned CastOpc =
3042 StepTySize < IndexTySize ? Instruction::Trunc : Instruction::ZExt;
3043 Cost += Ctx.TTI.getCastInstrCost(
3044 CastOpc, StepTy, IndexTy, TTI::CastContextHint::None, Ctx.CostKind);
3045 }
3046
3047 if (NeedsMul)
3048 Cost += Ctx.TTI.getArithmeticInstrCost(Instruction::Mul, StepTy,
3049 Ctx.CostKind);
3050 if (NeedsShl)
3051 Cost += Ctx.TTI.getArithmeticInstrCost(
3052 Instruction::Shl, StepTy, Ctx.CostKind,
3053 {TargetTransformInfo::OK_AnyValue, TargetTransformInfo::OP_None},
3054 {TargetTransformInfo::OK_UniformConstantValue,
3055 TargetTransformInfo::OP_None});
3056 if (NeedsAdd)
3057 Cost += Ctx.TTI.getArithmeticInstrCost(Instruction::Add, StepTy,
3058 Ctx.CostKind);
3059 return Cost;
3060 }
3061 }
3062
3063 return 0;
3064}
3065
3066#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3068 VPSlotTracker &SlotTracker) const {
3069 O << Indent;
3071 O << " = DERIVED-IV";
3072 printFlags(O);
3073 getStartValue()->printAsOperand(O, SlotTracker);
3074 O << " + ";
3075 getOperand(1)->printAsOperand(O, SlotTracker);
3076 O << " * ";
3077 getStepValue()->printAsOperand(O, SlotTracker);
3078}
3079#endif
3080
3084
3086 VPCostContext &Ctx) const {
3087 // TODO: Add costs for floating point.
3088 Type *BaseIVTy = getOperand(0)->getScalarType();
3089 if (!BaseIVTy->isIntegerTy())
3090 return 0;
3091
3092 // TODO: Add support for predicated regions. Requires scaling the cost by the
3093 // probability of entering the block.
3094 if (getRegion() && getRegion()->isReplicator())
3095 return 0;
3096
3097 // If only the first lane is used, then there won't be any code that remains
3098 // in the loop for the first unrolled part.
3100 return 0;
3101
3102 // Typically the operations are:
3103 // 1. Add the start index to each lane value.
3104 // 2. Multiply the start index by the step.
3105 // 3. Add the scaled start index to base IV.
3106 // Any code generated for 1 and 2 should be loop invariant and therefore
3107 // hoisted out of the loop. We only need to add on the cost of 3.
3108
3109 // Given the users of VPScalarIVStepsRecipe tend to be scalarized GEPs, i.e.
3110 // %add1 = add i32 %iv, 0
3111 // %add2 = add i32 %iv, 1
3112 // %gep1 = getelementptr i8, ptr %p, i32 %add1
3113 // %gep2 = getelementptr i8, ptr %p, i32 %add2
3114 // it's very likely that these GEPs will all be rewritten to have a common
3115 // base such that what's left is just
3116 // %base_gep = getelementptr i8, ptr %p, i32 %iv
3117 // %gep1 = getelementptr i8, ptr %base_gep, i32 0
3118 // %gep2 = getelementptr i8, ptr %base_gep, i32 1
3119 // Therefore, in reality the cost is somewhere betwen 1*AddCost and
3120 // (NumLanes - 1) * AddCost. For now, assume the cost of a single add.
3121 return Ctx.TTI.getArithmeticInstrCost(Instruction::Add, BaseIVTy,
3122 Ctx.CostKind);
3123}
3124
3126 // Fast-math-flags propagate from the original induction instruction.
3127 IRBuilder<>::FastMathFlagGuard FMFG(State.Builder);
3128 State.Builder.setFastMathFlags(getFastMathFlagsOrNone());
3129
3130 /// Compute scalar induction steps. \p ScalarIV is the scalar induction
3131 /// variable on which to base the steps, \p Step is the size of the step.
3132
3133 Value *BaseIV = State.get(getOperand(0), VPLane(0));
3134 Value *Step = State.get(getStepValue(), VPLane(0));
3135 IRBuilderBase &Builder = State.Builder;
3136
3137 // Ensure step has the same type as that of scalar IV.
3138 Type *BaseIVTy = BaseIV->getType()->getScalarType();
3139 assert(BaseIVTy == Step->getType() && "Types of BaseIV and Step must match!");
3140
3141 // We build scalar steps for both integer and floating-point induction
3142 // variables. Here, we determine the kind of arithmetic we will perform.
3145 if (BaseIVTy->isIntegerTy()) {
3146 AddOp = Instruction::Add;
3147 MulOp = Instruction::Mul;
3148 } else {
3149 AddOp = InductionOpcode;
3150 MulOp = Instruction::FMul;
3151 }
3152
3153 // Determine the number of scalars we need to generate.
3154 bool FirstLaneOnly = vputils::onlyFirstLaneUsed(this);
3155 // Compute the scalar steps and save the results in State.
3156
3157 unsigned EndLane = FirstLaneOnly ? 1 : State.VF.getKnownMinValue();
3158 Value *StartIdx0 = getStartIndex() ? State.get(getStartIndex(), true)
3159 : Constant::getNullValue(BaseIVTy);
3160
3161 for (unsigned Lane = 0; Lane < EndLane; ++Lane) {
3162 // It is okay if the induction variable type cannot hold the lane number,
3163 // we expect truncation in this case.
3164 Constant *LaneValue =
3165 BaseIVTy->isIntegerTy()
3166 ? ConstantInt::get(BaseIVTy, Lane, /*IsSigned=*/false,
3167 /*ImplicitTrunc=*/true)
3168 : ConstantFP::get(BaseIVTy, Lane);
3169 Value *StartIdx = Builder.CreateBinOp(AddOp, StartIdx0, LaneValue);
3170 assert((State.VF.isScalable() || isa<Constant>(StartIdx)) &&
3171 "Expected StartIdx to be folded to a constant when VF is not "
3172 "scalable");
3173 auto *Mul = Builder.CreateBinOp(MulOp, StartIdx, Step);
3174 auto *Add = Builder.CreateBinOp(AddOp, BaseIV, Mul);
3175 State.set(this, Add, VPLane(Lane));
3176 }
3177}
3178
3179#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3181 VPSlotTracker &SlotTracker) const {
3182 O << Indent;
3184 O << " = SCALAR-STEPS ";
3186}
3187#endif
3188
3190 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
3192}
3193
3195 assert(State.VF.isVector() && "not widening");
3196 auto Ops = map_to_vector(operands(), [&](VPValue *Op) {
3197 return State.get(Op, vputils::isSingleScalar(Op));
3198 });
3199 auto *GEP =
3200 State.Builder.CreateGEP(getSourceElementType(), Ops.front(),
3201 drop_begin(Ops), "wide.gep", getGEPNoWrapFlags());
3202 State.set(this, GEP, vputils::isSingleScalar(this));
3203}
3204
3205#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3207 VPSlotTracker &SlotTracker) const {
3208 O << Indent << "WIDEN-GEP ";
3210 O << " = getelementptr";
3211 printFlags(O);
3213}
3214#endif
3215
3217 assert(!getOffset() && "Unexpected offset operand");
3218 VPBuilder Builder(this);
3219 VPlan &Plan = *getParent()->getPlan();
3220 VPValue *VFVal = getVFValue();
3221 const DataLayout &DL = Plan.getDataLayout();
3222 Type *IndexTy = DL.getIndexType(this->getScalarType());
3223 VPValue *Stride =
3224 Plan.getConstantInt(IndexTy, getStride(), /*IsSigned=*/true);
3225 VPValue *VF =
3226 Builder.createScalarZExtOrTrunc(VFVal, IndexTy, DebugLoc::getUnknown());
3227
3228 // Offset for Part0 = Offset0 = Stride * (VF - 1).
3229 VPInstruction *VFMinusOne =
3230 Builder.createSub(VF, Plan.getConstantInt(IndexTy, 1u),
3231 DebugLoc::getUnknown(), "", {true, true});
3232 VPInstruction *Offset0 =
3233 Builder.createOverflowingOp(Instruction::Mul, {VFMinusOne, Stride});
3234
3235 // Offset for PartN = Offset0 + Part * Stride * VF.
3236 VPValue *PartxStride =
3237 Plan.getConstantInt(IndexTy, Part * getStride(), /*IsSigned=*/true);
3238 VPValue *Offset = Builder.createAdd(
3239 Offset0,
3240 Builder.createOverflowingOp(Instruction::Mul, {PartxStride, VF}));
3242}
3243
3245 auto &Builder = State.Builder;
3246 assert(getOffset() && "Expected prior materialization of offset");
3247 Value *Ptr = State.get(getPointer(), true);
3248 Value *Offset = State.get(getOffset(), true);
3249 Value *ResultPtr = Builder.CreateGEP(getSourceElementType(), Ptr, Offset, "",
3251 State.set(this, ResultPtr, /*IsScalar*/ true);
3252}
3253
3254#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3256 VPSlotTracker &SlotTracker) const {
3257 O << Indent;
3259 O << " = vector-end-pointer";
3260 printFlags(O);
3261 getSourceElementType()->print(O);
3262 O << ", ";
3264}
3265#endif
3266
3268 assert(getVFxPart() &&
3269 "Expected prior simplification of recipe without VFxPart");
3270
3271 auto &Builder = State.Builder;
3272 Value *Ptr = State.get(getOperand(0), VPLane(0));
3273 Value *Offset = State.get(getVFxPart(), true);
3274 // TODO: Expand to VPInstruction to support constant folding.
3275 if (!match(getStride(), m_One())) {
3276 Value *Stride = Builder.CreateZExtOrTrunc(State.get(getStride(), true),
3277 Offset->getType());
3278 Offset = Builder.CreateMul(Offset, Stride);
3279 }
3280 Value *ResultPtr = Builder.CreateGEP(getSourceElementType(), Ptr, Offset, "",
3282 State.set(this, ResultPtr, /*IsScalar*/ true);
3283}
3284
3285#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3287 VPSlotTracker &SlotTracker) const {
3288 O << Indent;
3290 O << " = vector-pointer";
3291 printFlags(O);
3292 getSourceElementType()->print(O);
3293 O << ", ";
3295}
3296#endif
3297
3299 VPCostContext &Ctx) const {
3300 // A blend will be expanded to a select VPInstruction, which will generate a
3301 // scalar select if only the first lane is used.
3303 VF = ElementCount::getFixed(1);
3304
3305 Type *ResultTy = toVectorTy(this->getScalarType(), VF);
3306 Type *CmpTy = toVectorTy(Type::getInt1Ty(Ctx.LLVMCtx), VF);
3307 return (getNumIncomingValues() - 1) *
3308 Ctx.TTI.getCmpSelInstrCost(Instruction::Select, ResultTy, CmpTy,
3309 CmpInst::BAD_ICMP_PREDICATE, Ctx.CostKind);
3310}
3311
3312#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3314 VPSlotTracker &SlotTracker) const {
3315 O << Indent << "BLEND ";
3317 O << " =";
3318 printFlags(O);
3319 if (getNumIncomingValues() == 1) {
3320 // Not a User of any mask: not really blending, this is a
3321 // single-predecessor phi.
3322 getIncomingValue(0)->printAsOperand(O, SlotTracker);
3323 } else {
3324 for (unsigned I = 0, E = getNumIncomingValues(); I < E; ++I) {
3325 if (I != 0)
3326 O << " ";
3327 getIncomingValue(I)->printAsOperand(O, SlotTracker);
3328 if (I == 0 && isNormalized())
3329 continue;
3330 O << "/";
3331 getMask(I)->printAsOperand(O, SlotTracker);
3332 }
3333 }
3334}
3335#endif
3336
3340 "In-loop AnyOf reductions aren't currently supported");
3341 // Propagate the fast-math flags carried by the underlying instruction.
3342 IRBuilderBase::FastMathFlagGuard FMFGuard(State.Builder);
3343 State.Builder.setFastMathFlags(getFastMathFlagsOrNone());
3344 Value *NewVecOp = State.get(getVecOp());
3345 if (VPValue *Cond = getCondOp()) {
3346 Value *NewCond = State.get(Cond, State.VF.isScalar());
3347 VectorType *VecTy = dyn_cast<VectorType>(NewVecOp->getType());
3348 Type *ElementTy = VecTy ? VecTy->getElementType() : NewVecOp->getType();
3349
3350 Value *Start =
3352 if (State.VF.isVector())
3353 Start = State.Builder.CreateVectorSplat(VecTy->getElementCount(), Start);
3354
3355 Value *Select = State.Builder.CreateSelect(NewCond, NewVecOp, Start);
3356 NewVecOp = Select;
3357 }
3358 Value *NewRed;
3359 Value *NextInChain;
3360 if (isOrdered()) {
3361 Value *PrevInChain = State.get(getChainOp(), /*IsScalar*/ true);
3362 if (State.VF.isVector())
3363 NewRed =
3364 createOrderedReduction(State.Builder, Kind, NewVecOp, PrevInChain);
3365 else
3366 NewRed = State.Builder.CreateBinOp(
3368 PrevInChain, NewVecOp);
3369 PrevInChain = NewRed;
3370 NextInChain = NewRed;
3371 } else if (isPartialReduction()) {
3372 assert((Kind == RecurKind::Add || Kind == RecurKind::FAdd) &&
3373 "Unexpected partial reduction kind");
3374 Value *PrevInChain = State.get(getChainOp(), /*IsScalar*/ false);
3375 NewRed = State.Builder.CreateIntrinsic(
3376 PrevInChain->getType(),
3377 Kind == RecurKind::Add ? Intrinsic::vector_partial_reduce_add
3378 : Intrinsic::vector_partial_reduce_fadd,
3379 {PrevInChain, NewVecOp}, State.Builder.getFastMathFlags(),
3380 "partial.reduce");
3381 PrevInChain = NewRed;
3382 NextInChain = NewRed;
3383 } else {
3384 assert(isInLoop() &&
3385 "The reduction must either be ordered, partial or in-loop");
3386 Value *PrevInChain = State.get(getChainOp(), /*IsScalar*/ true);
3387 NewRed = createSimpleReduction(State.Builder, NewVecOp, Kind);
3389 NextInChain = createMinMaxOp(State.Builder, Kind, NewRed, PrevInChain);
3390 else
3391 NextInChain = State.Builder.CreateBinOp(
3393 PrevInChain, NewRed);
3394 }
3395 State.set(this, NextInChain, /*IsScalar*/ !isPartialReduction());
3396}
3397
3399
3400 auto &Builder = State.Builder;
3401 // Propagate the fast-math flags carried by the underlying instruction.
3402 IRBuilderBase::FastMathFlagGuard FMFGuard(Builder);
3403 Builder.setFastMathFlags(getFastMathFlagsOrNone());
3404
3406 Value *Prev = State.get(getChainOp(), /*IsScalar*/ true);
3407 Value *VecOp = State.get(getVecOp());
3408 Value *EVL = State.get(getEVL(), VPLane(0));
3409
3410 Value *Mask;
3411 if (VPValue *CondOp = getCondOp())
3412 Mask = State.get(CondOp);
3413 else
3414 Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue());
3415
3416 Value *NewRed;
3417 if (isOrdered()) {
3418 NewRed = createOrderedReduction(Builder, Kind, VecOp, Prev, Mask, EVL);
3419 } else {
3420 NewRed = createSimpleReduction(Builder, VecOp, Kind, Mask, EVL);
3422 NewRed = createMinMaxOp(Builder, Kind, NewRed, Prev);
3423 else
3424 NewRed = Builder.CreateBinOp(
3426 Prev);
3427 }
3428 State.set(this, NewRed, /*IsScalar*/ true);
3429}
3430
3432 VPCostContext &Ctx) const {
3433 RecurKind RdxKind = getRecurrenceKind();
3434 Type *ElementTy = this->getScalarType();
3435 auto *VectorTy = cast<VectorType>(toVectorTy(ElementTy, VF));
3436 unsigned Opcode = RecurrenceDescriptor::getOpcode(RdxKind);
3438 std::optional<FastMathFlags> OptionalFMF =
3439 ElementTy->isFloatingPointTy() ? std::make_optional(FMFs) : std::nullopt;
3440
3441 if (isPartialReduction()) {
3442 InstructionCost CondCost = 0;
3443 if (isConditional()) {
3445 auto *CondTy =
3447 CondCost = Ctx.TTI.getCmpSelInstrCost(Instruction::Select, VectorTy,
3448 CondTy, Pred, Ctx.CostKind);
3449 }
3450 return CondCost + Ctx.TTI.getPartialReductionCost(
3451 Opcode, ElementTy, ElementTy, ElementTy, VF,
3452 TTI::PR_None, TTI::PR_None, {}, Ctx.CostKind,
3453 OptionalFMF);
3454 }
3455
3456 // TODO: Support any-of reductions.
3457 assert(
3459 ForceTargetInstructionCost.getNumOccurrences() > 0) &&
3460 "Any-of reduction not implemented in VPlan-based cost model currently.");
3461
3462 // Note that TTI should model the cost of moving result to the scalar register
3463 // and the BinOp cost in the getMinMaxReductionCost().
3466 return Ctx.TTI.getMinMaxReductionCost(Id, VectorTy, FMFs, Ctx.CostKind);
3467 }
3468
3469 // Note that TTI should model the cost of moving result to the scalar register
3470 // and the BinOp cost in the getArithmeticReductionCost().
3471 return Ctx.TTI.getArithmeticReductionCost(Opcode, VectorTy, OptionalFMF,
3472 Ctx.CostKind);
3473}
3474
3475VPExpressionRecipe::VPExpressionRecipe(
3476 ExpressionTypes ExpressionType,
3477 ArrayRef<VPSingleDefRecipe *> ExpressionRecipes)
3478 : VPSingleDefRecipe(VPRecipeBase::VPExpressionSC, {},
3479 cast<VPReductionRecipe>(ExpressionRecipes.back())
3480 ->getChainOp()
3481 ->getScalarType()),
3482 ExpressionRecipes(ExpressionRecipes), ExpressionType(ExpressionType) {
3483 assert(!ExpressionRecipes.empty() && "Nothing to combine?");
3484 assert(
3485 none_of(ExpressionRecipes,
3486 [](VPSingleDefRecipe *R) { return R->mayHaveSideEffects(); }) &&
3487 "expression cannot contain recipes with side-effects");
3488
3489 // Maintain a copy of the expression recipes as a set of users.
3490 SmallPtrSet<VPUser *, 4> ExpressionRecipesAsSetOfUsers;
3491 for (auto *R : ExpressionRecipes)
3492 ExpressionRecipesAsSetOfUsers.insert(R);
3493
3494 // Recipes in the expression, except the last one, must only be used by
3495 // (other) recipes inside the expression. If there are other users, external
3496 // to the expression, use a clone of the recipe for external users.
3497 for (VPSingleDefRecipe *R : reverse(ExpressionRecipes)) {
3498 if (R != ExpressionRecipes.back() &&
3499 any_of(R->users(), [&ExpressionRecipesAsSetOfUsers](VPUser *U) {
3500 return !ExpressionRecipesAsSetOfUsers.contains(U);
3501 })) {
3502 // There are users outside of the expression. Clone the recipe and use the
3503 // clone those external users.
3504 VPSingleDefRecipe *CopyForExtUsers = R->clone();
3505 R->replaceUsesWithIf(CopyForExtUsers, [&ExpressionRecipesAsSetOfUsers](
3506 VPUser &U, unsigned) {
3507 return !ExpressionRecipesAsSetOfUsers.contains(&U);
3508 });
3509 CopyForExtUsers->insertBefore(R);
3510 }
3511 if (R->getParent())
3512 R->removeFromParent();
3513 }
3514
3515 // Internalize all external operands to the expression recipes. To do so,
3516 // create new temporary VPValues for all operands defined by a recipe outside
3517 // the expression. The original operands are added as operands of the
3518 // VPExpressionRecipe itself.
3519 for (auto *R : ExpressionRecipes) {
3520 for (const auto &[Idx, Op] : enumerate(R->operands())) {
3521 auto *Def = Op->getDefiningRecipe();
3522 if (Def && ExpressionRecipesAsSetOfUsers.contains(Def))
3523 continue;
3524 addOperand(Op);
3525 LiveInPlaceholders.push_back(new VPSymbolicValue(Op->getScalarType()));
3526 }
3527 }
3528
3529 // Replace each external operand with the first one created for it in
3530 // LiveInPlaceholders.
3531 for (auto *R : ExpressionRecipes)
3532 for (auto const &[LiveIn, Tmp] : zip(operands(), LiveInPlaceholders))
3533 R->replaceUsesOfWith(LiveIn, Tmp);
3534}
3535
3537 for (auto *R : ExpressionRecipes)
3538 // Since the list could contain duplicates, make sure the recipe hasn't
3539 // already been inserted.
3540 if (!R->getParent())
3541 R->insertBefore(this);
3542
3543 for (const auto &[Idx, Op] : enumerate(operands()))
3544 LiveInPlaceholders[Idx]->replaceAllUsesWith(Op);
3545
3546 replaceAllUsesWith(ExpressionRecipes.back());
3547 ExpressionRecipes.clear();
3548}
3549
3551 VPCostContext &Ctx) const {
3552 Type *RedTy = this->getScalarType();
3553 auto *SrcVecTy =
3555 unsigned Opcode = RecurrenceDescriptor::getOpcode(
3556 cast<VPReductionRecipe>(ExpressionRecipes.back())->getRecurrenceKind());
3557 switch (ExpressionType) {
3558 case ExpressionTypes::NegatedExtendedReduction:
3559 assert((Opcode == Instruction::Add || Opcode == Instruction::FAdd) &&
3560 "Unexpected opcode");
3561 Opcode = Opcode == Instruction::Add ? Instruction::Sub : Instruction::FSub;
3562 [[fallthrough]];
3563 case ExpressionTypes::ExtendedReduction: {
3564 auto *RedR = cast<VPReductionRecipe>(ExpressionRecipes.back());
3565 auto *ExtR = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3566
3567 if (RedR->isPartialReduction())
3568 return Ctx.TTI.getPartialReductionCost(
3569 Opcode, getOperand(0)->getScalarType(), nullptr, RedTy, VF,
3571 TargetTransformInfo::PR_None, std::nullopt, Ctx.CostKind,
3572 RedTy->isFloatingPointTy()
3573 ? std::optional{RedR->getFastMathFlagsOrNone()}
3574 : std::nullopt);
3575 else if (!RedTy->isFloatingPointTy())
3576 // TTI::getExtendedReductionCost only supports integer types.
3577 return Ctx.TTI.getExtendedReductionCost(
3578 Opcode, ExtR->getOpcode() == Instruction::ZExt, RedTy, SrcVecTy,
3579 std::nullopt, Ctx.CostKind);
3580 else
3582 }
3583 case ExpressionTypes::MulAccReduction:
3584 return Ctx.TTI.getMulAccReductionCost(false, Opcode, RedTy, SrcVecTy,
3585 Ctx.CostKind);
3586
3587 case ExpressionTypes::ExtNegatedMulAccReduction:
3588 switch (Opcode) {
3589 case Instruction::Add:
3590 Opcode = Instruction::Sub;
3591 break;
3592 case Instruction::FAdd:
3593 Opcode = Instruction::FSub;
3594 break;
3595 default:
3596 llvm_unreachable("Unsupported opcode for ExtNegatedMulAccReduction");
3597 }
3598 [[fallthrough]];
3599 case ExpressionTypes::ExtMulAccReduction: {
3600 auto *RedR = cast<VPReductionRecipe>(ExpressionRecipes.back());
3601 if (RedR->isPartialReduction()) {
3602 auto *Ext0R = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3603 auto *Ext1R = cast<VPWidenCastRecipe>(ExpressionRecipes[1]);
3604 auto *Mul = cast<VPWidenRecipe>(ExpressionRecipes[2]);
3605 return Ctx.TTI.getPartialReductionCost(
3606 Opcode, getOperand(0)->getScalarType(),
3607 getOperand(1)->getScalarType(), RedTy, VF,
3609 Ext0R->getOpcode()),
3611 Ext1R->getOpcode()),
3612 Mul->getOpcode(), Ctx.CostKind,
3613 RedTy->isFloatingPointTy()
3614 ? std::optional{RedR->getFastMathFlagsOrNone()}
3615 : std::nullopt);
3616 }
3617 assert(Opcode != Instruction::FSub && "Only integer types are supported");
3618 return Ctx.TTI.getMulAccReductionCost(
3619 cast<VPWidenCastRecipe>(ExpressionRecipes.front())->getOpcode() ==
3620 Instruction::ZExt,
3621 Opcode, RedTy, SrcVecTy, Ctx.CostKind);
3622 }
3623 }
3624 llvm_unreachable("Unknown VPExpressionRecipe::ExpressionTypes enum");
3625}
3626
3628 return any_of(ExpressionRecipes, [](VPSingleDefRecipe *R) {
3629 return R->mayReadFromMemory() || R->mayWriteToMemory();
3630 });
3631}
3632
3634 assert(
3635 none_of(ExpressionRecipes,
3636 [](VPSingleDefRecipe *R) { return R->mayHaveSideEffects(); }) &&
3637 "expression cannot contain recipes with side-effects");
3638 return false;
3639}
3640
3642 auto *RR = dyn_cast<VPReductionRecipe>(ExpressionRecipes.back());
3643 return RR && !RR->isPartialReduction();
3644}
3645
3646#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3647
3649 VPSlotTracker &SlotTracker) const {
3650 O << Indent << "EXPRESSION ";
3652 O << " = ";
3653 auto *Red = cast<VPReductionRecipe>(ExpressionRecipes.back());
3654 unsigned Opcode = RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind());
3655 VPValue *RdxStart =
3656 getOperand(getNumOperands() - (Red->isConditional() ? 2 : 1));
3657
3658 switch (ExpressionType) {
3659 case ExpressionTypes::NegatedExtendedReduction:
3660 case ExpressionTypes::ExtendedReduction: {
3661 bool Negated = ExpressionType == ExpressionTypes::NegatedExtendedReduction;
3663 O << " + " << (Red->isPartialReduction() ? "partial." : "") << "reduce.";
3664 O << Instruction::getOpcodeName(Opcode) << " (";
3665 if (Negated)
3666 O << (Opcode == Instruction::Add ? "sub (0, " : "fneg(");
3668 if (Negated)
3669 O << ")";
3670 Red->printFlags(O);
3671
3672 auto *Ext0 = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3673 O << Instruction::getOpcodeName(Ext0->getOpcode()) << " to "
3674 << *Ext0->getScalarType();
3675 if (Red->isConditional()) {
3676 O << ", ";
3678 }
3679 O << ")";
3680 break;
3681 }
3682 case ExpressionTypes::ExtNegatedMulAccReduction: {
3683 RdxStart->printAsOperand(O, SlotTracker);
3684 O << " + " << (Red->isPartialReduction() ? "partial." : "") << "reduce.";
3686 RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind()))
3687 << " (sub (0, mul";
3688 auto *Mul = cast<VPWidenRecipe>(ExpressionRecipes[2]);
3689 Mul->printFlags(O);
3690 O << "(";
3692 auto *Ext0 = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3693 O << " " << Instruction::getOpcodeName(Ext0->getOpcode()) << " to "
3694 << *Ext0->getScalarType() << "), (";
3696 auto *Ext1 = cast<VPWidenCastRecipe>(ExpressionRecipes[1]);
3697 O << " " << Instruction::getOpcodeName(Ext1->getOpcode()) << " to "
3698 << *Ext1->getScalarType() << ")";
3699 if (Red->isConditional()) {
3700 O << ", ";
3702 }
3703 O << "))";
3704 break;
3705 }
3706 case ExpressionTypes::MulAccReduction:
3707 case ExpressionTypes::ExtMulAccReduction: {
3708 RdxStart->printAsOperand(O, SlotTracker);
3709 O << " + " << (Red->isPartialReduction() ? "partial." : "") << "reduce.";
3711 RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind()))
3712 << " (";
3713 O << "mul";
3714 bool IsExtended = ExpressionType == ExpressionTypes::ExtMulAccReduction;
3715 auto *Mul = cast<VPWidenRecipe>(IsExtended ? ExpressionRecipes[2]
3716 : ExpressionRecipes[0]);
3717 Mul->printFlags(O);
3718 if (IsExtended)
3719 O << "(";
3721 if (IsExtended) {
3722 auto *Ext0 = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3723 O << " " << Instruction::getOpcodeName(Ext0->getOpcode()) << " to "
3724 << *Ext0->getScalarType() << "), (";
3725 } else {
3726 O << ", ";
3727 }
3729 if (IsExtended) {
3730 auto *Ext1 = cast<VPWidenCastRecipe>(ExpressionRecipes[1]);
3731 O << " " << Instruction::getOpcodeName(Ext1->getOpcode()) << " to "
3732 << *Ext1->getScalarType() << ")";
3733 }
3734 if (Red->isConditional()) {
3735 O << ", ";
3737 }
3738 O << ")";
3739 break;
3740 }
3741 }
3742}
3743
3745 VPSlotTracker &SlotTracker) const {
3746 if (isPartialReduction())
3747 O << Indent << "PARTIAL-REDUCE ";
3748 else
3749 O << Indent << "REDUCE ";
3751 O << " = ";
3753 O << " +";
3754 printFlags(O);
3755 O << " reduce.";
3757 O << " (";
3759 if (isConditional()) {
3760 O << ", ";
3762 }
3763 O << ")";
3764}
3765
3767 VPSlotTracker &SlotTracker) const {
3768 O << Indent << "REDUCE ";
3770 O << " = ";
3772 O << " +";
3773 printFlags(O);
3774 O << " vp.reduce."
3777 << " (";
3779 O << ", ";
3781 if (isConditional()) {
3782 O << ", ";
3784 }
3785 O << ")";
3786}
3787
3788#endif
3789
3791 assert(IsSingleScalar &&
3792 "VPReplicateRecipes must be unrolled before ::execute");
3793 auto *Instr = getUnderlyingInstr();
3794 Instruction *Cloned = Instr->clone();
3795 Type *ResultTy = getScalarType();
3796 if (!ResultTy->isVoidTy()) {
3797 Cloned->setName(Instr->getName() + ".cloned");
3798 // The operands of the replicate recipe may have been narrowed, resulting in
3799 // a narrower result type. Update the type of the cloned instruction to the
3800 // correct type.
3801 if (ResultTy != Cloned->getType())
3802 Cloned->mutateType(ResultTy);
3803 }
3804
3805 applyFlags(*Cloned);
3806 applyMetadata(*Cloned);
3807
3808 if (hasPredicate())
3809 cast<CmpInst>(Cloned)->setPredicate(getPredicate());
3810
3811 // Replace the operands of the cloned instructions with their scalar
3812 // equivalents in the new loop.
3813 for (const auto &[Idx, V] : enumerate(operands()))
3814 Cloned->setOperand(Idx, State.get(V, true));
3815
3816 // Place the cloned scalar in the new loop.
3817 State.Builder.Insert(Cloned);
3818
3819 State.set(this, Cloned, true);
3820
3821 // If we just cloned a new assumption, add it the assumption cache.
3822 if (auto *II = dyn_cast<AssumeInst>(Cloned))
3823 State.AC->registerAssumption(II);
3824}
3825
3826/// Returns a SCEV expression for \p Ptr if it is a pointer computation for
3827/// which the legacy cost model computes a SCEV expression when computing the
3828/// address cost. Computing SCEVs for VPValues is incomplete and returns
3829/// SCEVCouldNotCompute in cases the legacy cost model can compute SCEVs. In
3830/// those cases we fall back to the legacy cost model. Otherwise return nullptr.
3831static const SCEV *getAddressAccessSCEV(const VPValue *Ptr,
3833 const Loop *L) {
3834 const SCEV *Addr = vputils::getSCEVExprForVPValue(Ptr, PSE, L);
3835 if (isa<SCEVCouldNotCompute>(Addr))
3836 return Addr;
3837
3838 return vputils::isAddressSCEVForCost(Addr, *PSE.getSE(), L) ? Addr : nullptr;
3839}
3840
3842 VPCostContext &Ctx) const {
3844 // VPReplicateRecipe may be cloned as part of an existing VPlan-to-VPlan
3845 // transform, avoid computing their cost multiple times for now.
3846 Ctx.SkipCostComputation.insert(UI);
3847
3848 if (VF.isScalable() && !isSingleScalar())
3850
3851 switch (UI->getOpcode()) {
3852 case Instruction::Alloca:
3853 if (VF.isScalable())
3855 return Ctx.TTI.getArithmeticInstrCost(Instruction::Mul,
3856 this->getScalarType(), Ctx.CostKind);
3857 case Instruction::GetElementPtr:
3858 // We mark this instruction as zero-cost because the cost of GEPs in
3859 // vectorized code depends on whether the corresponding memory instruction
3860 // is scalarized or not. Therefore, we handle GEPs with the memory
3861 // instruction cost.
3862 return 0;
3863 case Instruction::Call: {
3864 auto *CalledFn =
3866 Type *ResultTy = this->getScalarType();
3867 return computeCallCost(CalledFn, ResultTy, drop_end(operands()),
3868 isSingleScalar(), VF, Ctx);
3869 }
3870 case Instruction::Add:
3871 case Instruction::Sub:
3872 case Instruction::FAdd:
3873 case Instruction::FSub:
3874 case Instruction::Mul:
3875 case Instruction::FMul:
3876 case Instruction::FDiv:
3877 case Instruction::FRem:
3878 case Instruction::Shl:
3879 case Instruction::LShr:
3880 case Instruction::AShr:
3881 case Instruction::And:
3882 case Instruction::Or:
3883 case Instruction::Xor:
3884 case Instruction::ICmp:
3885 case Instruction::FCmp:
3887 Ctx) *
3888 (isSingleScalar() ? 1 : VF.getFixedValue());
3889 case Instruction::SDiv:
3890 case Instruction::UDiv:
3891 case Instruction::SRem:
3892 case Instruction::URem: {
3893 InstructionCost ScalarCost =
3895 if (isSingleScalar())
3896 return ScalarCost;
3897
3898 // If any of the operands is from a different replicate region and has its
3899 // cost skipped, it may have been forced to scalar. Fall back to legacy cost
3900 // model to avoid cost mis-match.
3901 if (any_of(operands(), [&Ctx, VF](VPValue *Op) {
3902 auto *PredR = dyn_cast<VPPredInstPHIRecipe>(Op);
3903 if (!PredR)
3904 return false;
3905 return Ctx.skipCostComputation(
3907 PredR->getOperand(0)->getUnderlyingValue()),
3908 VF.isVector());
3909 }))
3910 break;
3911
3912 ScalarCost = ScalarCost * VF.getFixedValue() +
3913 Ctx.getScalarizationOverhead(this->getScalarType(),
3914 to_vector(operands()), VF);
3915 // If the recipe is not predicated (i.e. not in a replicate region), return
3916 // the scalar cost. Otherwise handle predicated cost.
3917 if (!getRegion()->isReplicator())
3918 return ScalarCost;
3919
3920 // Account for the phi nodes that we will create.
3921 ScalarCost += VF.getFixedValue() *
3922 Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
3923 // Scale the cost by the probability of executing the predicated blocks.
3924 // This assumes the predicated block for each vector lane is equally
3925 // likely.
3926 ScalarCost /= Ctx.getPredBlockCostDivisor(UI->getParent());
3927 return ScalarCost;
3928 }
3929 case Instruction::Load:
3930 case Instruction::Store: {
3931 bool IsLoad = UI->getOpcode() == Instruction::Load;
3932 const VPValue *PtrOp = getOperand(!IsLoad);
3933 const SCEV *PtrSCEV = getAddressAccessSCEV(PtrOp, Ctx.PSE, Ctx.L);
3935 break;
3936
3937 Type *ValTy = (IsLoad ? this : getOperand(0))->getScalarType();
3938 Type *ScalarPtrTy = PtrOp->getScalarType();
3939 const Align Alignment = getLoadStoreAlignment(UI);
3940 unsigned AS = cast<PointerType>(ScalarPtrTy)->getAddressSpace();
3942 bool PreferVectorizedAddressing = Ctx.TTI.prefersVectorizedAddressing();
3943 bool UsedByLoadStoreAddress =
3944 !PreferVectorizedAddressing && vputils::isUsedByLoadStoreAddress(this);
3945 InstructionCost ScalarMemOpCost = Ctx.TTI.getMemoryOpCost(
3946 UI->getOpcode(), ValTy, Alignment, AS, Ctx.CostKind, OpInfo,
3947 UsedByLoadStoreAddress ? UI : nullptr);
3948
3949 Type *PtrTy = isSingleScalar() ? ScalarPtrTy : toVectorTy(ScalarPtrTy, VF);
3950 InstructionCost ScalarCost =
3951 ScalarMemOpCost +
3952 Ctx.TTI.getAddressComputationCost(
3953 PtrTy, UsedByLoadStoreAddress ? nullptr : Ctx.PSE.getSE(), PtrSCEV,
3954 Ctx.CostKind);
3955 if (isSingleScalar())
3956 return ScalarCost;
3957
3958 SmallVector<const VPValue *> OpsToScalarize;
3959 Type *ResultTy = Type::getVoidTy(PtrTy->getContext());
3960 // Set ResultTy and OpsToScalarize, if scalarization is needed. Currently we
3961 // don't assign scalarization overhead in general, if the target prefers
3962 // vectorized addressing or the loaded value is used as part of an address
3963 // of another load or store.
3964 if (!UsedByLoadStoreAddress) {
3965 bool EfficientVectorLoadStore =
3966 Ctx.TTI.supportsEfficientVectorElementLoadStore();
3967 if (!(IsLoad && !PreferVectorizedAddressing) &&
3968 !(!IsLoad && EfficientVectorLoadStore))
3969 append_range(OpsToScalarize, operands());
3970
3971 if (!EfficientVectorLoadStore)
3972 ResultTy = this->getScalarType();
3973 }
3974
3976 IsLoad ? TTI::VectorInstrContext::Load : TTI::VectorInstrContext::Store;
3978 (ScalarCost * VF.getFixedValue()) +
3979 Ctx.getScalarizationOverhead(ResultTy, OpsToScalarize, VF, VIC, true);
3980
3981 const VPRegionBlock *ParentRegion = getRegion();
3982 if (ParentRegion && ParentRegion->isReplicator()) {
3983 if (!PtrSCEV)
3984 break;
3985 Cost /= Ctx.getPredBlockCostDivisor(UI->getParent());
3986 Cost += Ctx.TTI.getCFInstrCost(Instruction::CondBr, Ctx.CostKind);
3987
3988 auto *VecI1Ty = VectorType::get(
3989 IntegerType::getInt1Ty(Ctx.L->getHeader()->getContext()), VF);
3990 Cost += Ctx.TTI.getScalarizationOverhead(
3991 VecI1Ty, APInt::getAllOnes(VF.getFixedValue()),
3992 /*Insert=*/false, /*Extract=*/true, Ctx.CostKind);
3993
3994 if (Ctx.useEmulatedMaskMemRefHack(this, VF)) {
3995 // Artificially setting to a high enough value to practically disable
3996 // vectorization with such operations.
3997 return 3000000;
3998 }
3999 }
4000 return Cost;
4001 }
4002 case Instruction::SExt:
4003 case Instruction::ZExt:
4004 case Instruction::FPToUI:
4005 case Instruction::FPToSI:
4006 case Instruction::FPExt:
4007 case Instruction::PtrToInt:
4008 case Instruction::PtrToAddr:
4009 case Instruction::IntToPtr:
4010 case Instruction::SIToFP:
4011 case Instruction::UIToFP:
4012 case Instruction::Trunc:
4013 case Instruction::FPTrunc:
4014 case Instruction::Select:
4015 case Instruction::AddrSpaceCast: {
4017 Ctx) *
4018 (isSingleScalar() ? 1 : VF.getFixedValue());
4019 }
4020 case Instruction::ExtractValue:
4021 case Instruction::InsertValue:
4022 return Ctx.TTI.getInsertExtractValueCost(getOpcode(), Ctx.CostKind);
4023 }
4024
4025 return Ctx.getLegacyCost(UI, VF);
4026}
4027
4029 Function *CalledFn, Type *ResultTy, ArrayRef<const VPValue *> ArgOps,
4030 bool IsSingleScalar, ElementCount VF, VPCostContext &Ctx) {
4032 ArgOps, [&](const VPValue *Op) { return Op->getScalarType(); });
4033
4034 Intrinsic::ID IntrinID = CalledFn->getIntrinsicID();
4035 auto GetIntrinsicCost = [&] {
4036 if (!IntrinID)
4038 return Ctx.TTI.getIntrinsicInstrCost(
4039 IntrinsicCostAttributes(IntrinID, ResultTy, Tys), Ctx.CostKind);
4040 };
4041
4042 if (IntrinID && VPCostContext::isFreeScalarIntrinsic(IntrinID)) {
4043 assert(GetIntrinsicCost() == 0 && "scalarizing intrinsic should be free");
4044 return 0;
4045 }
4046
4047 InstructionCost ScalarCallCost =
4048 Ctx.TTI.getCallInstrCost(CalledFn, ResultTy, Tys, Ctx.CostKind);
4049 if (IsSingleScalar) {
4050 ScalarCallCost = std::min(ScalarCallCost, GetIntrinsicCost());
4051 return ScalarCallCost;
4052 }
4053
4054 // Scalarization overhead is undefined for scalable VFs.
4055 if (VF.isScalable())
4057
4058 return ScalarCallCost * VF.getFixedValue() +
4059 Ctx.getScalarizationOverhead(ResultTy, ArgOps, VF);
4060}
4061
4062#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4064 VPSlotTracker &SlotTracker) const {
4065 O << Indent << (IsSingleScalar ? "CLONE " : "REPLICATE ");
4066
4067 if (!getScalarType()->isVoidTy()) {
4069 O << " = ";
4070 }
4071 if (auto *CB = dyn_cast<CallBase>(getUnderlyingInstr())) {
4072 O << "call";
4073 printFlags(O);
4074 O << "@" << CB->getCalledFunction()->getName() << "(";
4076 Op->printAsOperand(O, SlotTracker);
4077 });
4078 O << ")";
4079 } else {
4081 printFlags(O);
4083 }
4084
4085 // Find if the recipe is used by a widened recipe via an intervening
4086 // VPPredInstPHIRecipe. In this case, also pack the scalar values in a vector.
4087 if (any_of(users(), [](const VPUser *U) {
4088 if (auto *PredR = dyn_cast<VPPredInstPHIRecipe>(U))
4089 return !vputils::onlyScalarValuesUsed(PredR);
4090 return false;
4091 }))
4092 O << " (S->V)";
4093}
4094#endif
4095
4097 llvm_unreachable("recipe must be removed when dissolving replicate region");
4098}
4099
4101 VPCostContext &Ctx) const {
4102 // The legacy cost model doesn't assign costs to branches for individual
4103 // replicate regions. Match the current behavior in the VPlan cost model for
4104 // now.
4105 return 0;
4106}
4107
4109 llvm_unreachable("recipe must be removed when dissolving replicate region");
4110}
4111
4112#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4114 VPSlotTracker &SlotTracker) const {
4115 O << Indent << "PHI-PREDICATED-INSTRUCTION ";
4117 O << " = ";
4119}
4120#endif
4121
4123const VPRecipeBase *VPWidenLoadRecipe::getAsRecipe() const { return this; }
4124
4127
4129const VPRecipeBase *VPWidenStoreRecipe::getAsRecipe() const { return this; }
4130
4133
4135 VPCostContext &Ctx) const {
4136 const VPRecipeBase *R = getAsRecipe();
4138 Type *ScalarTy = IsLoad ? cast<VPSingleDefRecipe>(R)->getScalarType()
4139 : R->getOperand(1)->getScalarType();
4140 Type *Ty = toVectorTy(ScalarTy, VF);
4141 unsigned AS =
4142 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4143 unsigned Opcode = IsLoad ? Instruction::Load : Instruction::Store;
4144
4145 if (!Consecutive) {
4146 // TODO: Using the original IR may not be accurate.
4147 // Currently, ARM will use the underlying IR to calculate gather/scatter
4148 // instruction cost.
4149 Type *PtrTy = getAddr()->getScalarType();
4150 const Value *Ptr = getAddr()->getUnderlyingValue();
4151
4152 // If the address value is uniform across all lanes, then the address can be
4153 // calculated with scalar type and broadcast.
4155 PtrTy = toVectorTy(PtrTy, VF);
4156
4157 unsigned IID = isa<VPWidenLoadRecipe>(R) ? Intrinsic::masked_gather
4158 : isa<VPWidenStoreRecipe>(R) ? Intrinsic::masked_scatter
4159 : isa<VPWidenLoadEVLRecipe>(R) ? Intrinsic::vp_gather
4160 : Intrinsic::vp_scatter;
4161 return Ctx.TTI.getAddressComputationCost(PtrTy, nullptr, nullptr,
4162 Ctx.CostKind) +
4163 Ctx.TTI.getMemIntrinsicInstrCost(
4165 &Ingredient),
4166 Ctx.CostKind);
4167 }
4168
4170 if (IsMasked) {
4171 unsigned IID = isa<VPWidenLoadRecipe>(R) ? Intrinsic::masked_load
4172 : Intrinsic::masked_store;
4173 Cost += Ctx.TTI.getMemIntrinsicInstrCost(
4174 MemIntrinsicCostAttributes(IID, Ty, Alignment, AS), Ctx.CostKind);
4175 } else {
4176 TTI::OperandValueInfo OpInfo = Ctx.getOperandInfo(
4178 : R->getOperand(1));
4179 Cost += Ctx.TTI.getMemoryOpCost(Opcode, Ty, Alignment, AS, Ctx.CostKind,
4180 OpInfo, &Ingredient);
4181 }
4182 return Cost;
4183}
4184
4186 Type *ScalarDataTy = getScalarType();
4187 auto *DataTy = VectorType::get(ScalarDataTy, State.VF);
4188 bool CreateGather = !isConsecutive();
4189
4190 auto &Builder = State.Builder;
4191 Value *Mask = nullptr;
4192 if (auto *VPMask = getMask())
4193 Mask = State.get(VPMask);
4194
4195 Value *Addr = State.get(getAddr(), /*IsScalar*/ !CreateGather);
4196 Value *NewLI;
4197 if (CreateGather) {
4198 NewLI = Builder.CreateMaskedGather(DataTy, Addr, Alignment, Mask, nullptr,
4199 "wide.masked.gather");
4200 } else if (Mask) {
4201 NewLI =
4202 Builder.CreateMaskedLoad(DataTy, Addr, Alignment, Mask,
4203 PoisonValue::get(DataTy), "wide.masked.load");
4204 } else {
4205 NewLI = Builder.CreateAlignedLoad(DataTy, Addr, Alignment, "wide.load");
4206 }
4208 State.set(this, NewLI);
4209}
4210
4211#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4213 VPSlotTracker &SlotTracker) const {
4214 O << Indent << "WIDEN ";
4216 O << " = load ";
4218}
4219#endif
4220
4222 Type *ScalarDataTy = getScalarType();
4223 auto *DataTy = VectorType::get(ScalarDataTy, State.VF);
4224 bool CreateGather = !isConsecutive();
4225
4226 auto &Builder = State.Builder;
4227 CallInst *NewLI;
4228 Value *EVL = State.get(getEVL(), VPLane(0));
4229 Value *Addr = State.get(getAddr(), !CreateGather);
4230 Value *Mask = nullptr;
4231 if (VPValue *VPMask = getMask())
4232 Mask = State.get(VPMask);
4233 else
4234 Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue());
4235
4236 if (CreateGather) {
4237 NewLI = Builder.CreateIntrinsicWithoutFolding(DataTy, Intrinsic::vp_gather,
4238 {Addr, Mask, EVL}, nullptr,
4239 "wide.masked.gather");
4240 } else {
4241 NewLI = Builder.CreateIntrinsicWithoutFolding(
4242 DataTy, Intrinsic::vp_load, {Addr, Mask, EVL}, nullptr, "vp.op.load");
4243 }
4244 NewLI->addParamAttr(
4246 applyMetadata(*NewLI);
4247 State.set(this, NewLI);
4248}
4249
4251 VPCostContext &Ctx) const {
4252 if (!Consecutive || IsMasked)
4253 return VPWidenMemoryRecipe::computeCost(VF, Ctx);
4254
4255 // We need to use the getMemIntrinsicInstrCost() instead of getMemoryOpCost()
4256 // here because the EVL recipes using EVL to replace the tail mask. But in the
4257 // legacy model, it will always calculate the cost of mask.
4258 // TODO: Using getMemoryOpCost() instead of getMemIntrinsicInstrCost when we
4259 // don't need to compare to the legacy cost model.
4260 Type *Ty = toVectorTy(getScalarType(), VF);
4261 unsigned AS =
4262 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4263 return Ctx.TTI.getMemIntrinsicInstrCost(
4264 MemIntrinsicCostAttributes(Intrinsic::vp_load, Ty, Alignment, AS),
4265 Ctx.CostKind);
4266}
4267
4268#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4270 VPSlotTracker &SlotTracker) const {
4271 O << Indent << "WIDEN ";
4273 O << " = vp.load ";
4275}
4276#endif
4277
4279 VPValue *StoredVPValue = getStoredValue();
4280 bool CreateScatter = !isConsecutive();
4281
4282 auto &Builder = State.Builder;
4283
4284 Value *Mask = nullptr;
4285 if (auto *VPMask = getMask())
4286 Mask = State.get(VPMask);
4287
4288 Value *StoredVal = State.get(StoredVPValue);
4289 Value *Addr = State.get(getAddr(), /*IsScalar*/ !CreateScatter);
4290 Instruction *NewSI = nullptr;
4291 if (CreateScatter)
4292 NewSI = Builder.CreateMaskedScatter(StoredVal, Addr, Alignment, Mask);
4293 else if (Mask)
4294 NewSI = Builder.CreateMaskedStore(StoredVal, Addr, Alignment, Mask);
4295 else
4296 NewSI = Builder.CreateAlignedStore(StoredVal, Addr, Alignment);
4297 applyMetadata(*NewSI);
4298}
4299
4300#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4302 VPSlotTracker &SlotTracker) const {
4303 O << Indent << "WIDEN store ";
4305}
4306#endif
4307
4309 VPValue *StoredValue = getStoredValue();
4310 bool CreateScatter = !isConsecutive();
4311
4312 auto &Builder = State.Builder;
4313
4314 CallInst *NewSI = nullptr;
4315 Value *StoredVal = State.get(StoredValue);
4316 Value *EVL = State.get(getEVL(), VPLane(0));
4317 Value *Mask = nullptr;
4318 if (VPValue *VPMask = getMask())
4319 Mask = State.get(VPMask);
4320 else
4321 Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue());
4322
4323 Value *Addr = State.get(getAddr(), !CreateScatter);
4324 if (CreateScatter) {
4325 NewSI = Builder.CreateIntrinsicWithoutFolding(
4326 Type::getVoidTy(EVL->getContext()), Intrinsic::vp_scatter,
4327 {StoredVal, Addr, Mask, EVL});
4328 } else {
4329 NewSI = Builder.CreateIntrinsicWithoutFolding(
4330 Type::getVoidTy(EVL->getContext()), Intrinsic::vp_store,
4331 {StoredVal, Addr, Mask, EVL});
4332 }
4333 NewSI->addParamAttr(
4335 applyMetadata(*NewSI);
4336}
4337
4339 VPCostContext &Ctx) const {
4340 if (!Consecutive || IsMasked)
4341 return VPWidenMemoryRecipe::computeCost(VF, Ctx);
4342
4343 // We need to use the getMemIntrinsicInstrCost() instead of getMemoryOpCost()
4344 // here because the EVL recipes using EVL to replace the tail mask. But in the
4345 // legacy model, it will always calculate the cost of mask.
4346 // TODO: Using getMemoryOpCost() instead of getMemIntrinsicInstrCost when we
4347 // don't need to compare to the legacy cost model.
4348 Type *Ty = toVectorTy(getStoredValue()->getScalarType(), VF);
4349 unsigned AS =
4350 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4351 return Ctx.TTI.getMemIntrinsicInstrCost(
4352 MemIntrinsicCostAttributes(Intrinsic::vp_store, Ty, Alignment, AS),
4353 Ctx.CostKind);
4354}
4355
4356#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4358 VPSlotTracker &SlotTracker) const {
4359 O << Indent << "WIDEN vp.store ";
4361}
4362#endif
4363
4365 VectorType *DstVTy, const DataLayout &DL) {
4366 // Verify that V is a vector type with same number of elements as DstVTy.
4367 auto VF = DstVTy->getElementCount();
4368 auto *SrcVecTy = cast<VectorType>(V->getType());
4369 assert(VF == SrcVecTy->getElementCount() && "Vector dimensions do not match");
4370 Type *SrcElemTy = SrcVecTy->getElementType();
4371 Type *DstElemTy = DstVTy->getElementType();
4372 assert((DL.getTypeSizeInBits(SrcElemTy) == DL.getTypeSizeInBits(DstElemTy)) &&
4373 "Vector elements must have same size");
4374
4375 // Do a direct cast if element types are castable.
4376 if (CastInst::isBitOrNoopPointerCastable(SrcElemTy, DstElemTy, DL)) {
4377 return Builder.CreateBitOrPointerCast(V, DstVTy);
4378 }
4379 // V cannot be directly casted to desired vector type.
4380 // May happen when V is a floating point vector but DstVTy is a vector of
4381 // pointers or vice-versa. Handle this using a two-step bitcast using an
4382 // intermediate Integer type for the bitcast i.e. Ptr <-> Int <-> Float.
4383 assert((DstElemTy->isPointerTy() != SrcElemTy->isPointerTy()) &&
4384 "Only one type should be a pointer type");
4385 assert((DstElemTy->isFloatingPointTy() != SrcElemTy->isFloatingPointTy()) &&
4386 "Only one type should be a floating point type");
4387 Type *IntTy =
4388 IntegerType::getIntNTy(V->getContext(), DL.getTypeSizeInBits(SrcElemTy));
4389 auto *VecIntTy = VectorType::get(IntTy, VF);
4390 Value *CastVal = Builder.CreateBitOrPointerCast(V, VecIntTy);
4391 return Builder.CreateBitOrPointerCast(CastVal, DstVTy);
4392}
4393
4394/// Return a vector containing interleaved elements from multiple
4395/// smaller input vectors.
4397 const Twine &Name) {
4398 unsigned Factor = Vals.size();
4399 assert(Factor > 1 && "Tried to interleave invalid number of vectors");
4400
4401 VectorType *VecTy = cast<VectorType>(Vals[0]->getType());
4402#ifndef NDEBUG
4403 for (Value *Val : Vals)
4404 assert(Val->getType() == VecTy && "Tried to interleave mismatched types");
4405#endif
4406
4407 // Scalable vectors cannot use arbitrary shufflevectors (only splats), so
4408 // must use intrinsics to interleave.
4409 if (VecTy->isScalableTy()) {
4410 assert(Factor <= 8 && "Unsupported interleave factor for scalable vectors");
4411 return Builder.CreateVectorInterleave(Vals, Name);
4412 }
4413
4414 // Fixed length. Start by concatenating all vectors into a wide vector.
4415 Value *WideVec = concatenateVectors(Builder, Vals);
4416
4417 // Interleave the elements into the wide vector.
4418 const unsigned NumElts = VecTy->getElementCount().getFixedValue();
4419 return Builder.CreateShuffleVector(
4420 WideVec, createInterleaveMask(NumElts, Factor), Name);
4421}
4422
4423// Try to vectorize the interleave group that \p Instr belongs to.
4424//
4425// E.g. Translate following interleaved load group (factor = 3):
4426// for (i = 0; i < N; i+=3) {
4427// R = Pic[i]; // Member of index 0
4428// G = Pic[i+1]; // Member of index 1
4429// B = Pic[i+2]; // Member of index 2
4430// ... // do something to R, G, B
4431// }
4432// To:
4433// %wide.vec = load <12 x i32> ; Read 4 tuples of R,G,B
4434// %R.vec = shuffle %wide.vec, poison, <0, 3, 6, 9> ; R elements
4435// %G.vec = shuffle %wide.vec, poison, <1, 4, 7, 10> ; G elements
4436// %B.vec = shuffle %wide.vec, poison, <2, 5, 8, 11> ; B elements
4437//
4438// Or translate following interleaved store group (factor = 3):
4439// for (i = 0; i < N; i+=3) {
4440// ... do something to R, G, B
4441// Pic[i] = R; // Member of index 0
4442// Pic[i+1] = G; // Member of index 1
4443// Pic[i+2] = B; // Member of index 2
4444// }
4445// To:
4446// %R_G.vec = shuffle %R.vec, %G.vec, <0, 1, 2, ..., 7>
4447// %B_U.vec = shuffle %B.vec, poison, <0, 1, 2, 3, u, u, u, u>
4448// %interleaved.vec = shuffle %R_G.vec, %B_U.vec,
4449// <0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11> ; Interleave R,G,B elements
4450// store <12 x i32> %interleaved.vec ; Write 4 tuples of R,G,B
4452 assert((!needsMaskForGaps() || !State.VF.isScalable()) &&
4453 "Masking gaps for scalable vectors is not yet supported.");
4455 Instruction *Instr = Group->getInsertPos();
4456
4457 // Prepare for the vector type of the interleaved load/store.
4458 Type *ScalarTy = getLoadStoreType(Instr);
4459 unsigned InterleaveFactor = Group->getFactor();
4460 auto *VecTy = VectorType::get(ScalarTy, State.VF * InterleaveFactor);
4461
4462 VPValue *BlockInMask = getMask();
4463 VPValue *Addr = getAddr();
4464 Value *ResAddr = State.get(Addr, VPLane(0));
4465
4466 auto CreateGroupMask = [&BlockInMask, &State,
4467 &InterleaveFactor](Value *MaskForGaps) -> Value * {
4468 if (State.VF.isScalable()) {
4469 assert(!MaskForGaps && "Interleaved groups with gaps are not supported.");
4470 assert(InterleaveFactor <= 8 &&
4471 "Unsupported deinterleave factor for scalable vectors");
4472 auto *ResBlockInMask = State.get(BlockInMask);
4473 SmallVector<Value *> Ops(InterleaveFactor, ResBlockInMask);
4474 return interleaveVectors(State.Builder, Ops, "interleaved.mask");
4475 }
4476
4477 if (!BlockInMask)
4478 return MaskForGaps;
4479
4480 Value *ResBlockInMask = State.get(BlockInMask);
4481 Value *ShuffledMask = State.Builder.CreateShuffleVector(
4482 ResBlockInMask,
4483 createReplicatedMask(InterleaveFactor, State.VF.getFixedValue()),
4484 "interleaved.mask");
4485 return MaskForGaps ? State.Builder.CreateBinOp(Instruction::And,
4486 ShuffledMask, MaskForGaps)
4487 : ShuffledMask;
4488 };
4489
4490 const DataLayout &DL = Instr->getDataLayout();
4491 // Vectorize the interleaved load group.
4492 if (isa<LoadInst>(Instr)) {
4493 Value *MaskForGaps = nullptr;
4494 if (needsMaskForGaps()) {
4495 MaskForGaps =
4496 createBitMaskForGaps(State.Builder, State.VF.getFixedValue(), *Group);
4497 assert(MaskForGaps && "Mask for Gaps is required but it is null");
4498 }
4499
4500 Instruction *NewLoad;
4501 if (BlockInMask || MaskForGaps) {
4502 Value *GroupMask = CreateGroupMask(MaskForGaps);
4503 Value *PoisonVec = PoisonValue::get(VecTy);
4504 NewLoad = State.Builder.CreateMaskedLoad(VecTy, ResAddr,
4505 Group->getAlign(), GroupMask,
4506 PoisonVec, "wide.masked.vec");
4507 } else
4508 NewLoad = State.Builder.CreateAlignedLoad(VecTy, ResAddr,
4509 Group->getAlign(), "wide.vec");
4510 applyMetadata(*NewLoad);
4511 // TODO: Also manage existing metadata using VPIRMetadata.
4512 Group->addMetadata(NewLoad);
4513
4515 if (VecTy->isScalableTy()) {
4516 // Scalable vectors cannot use arbitrary shufflevectors (only splats),
4517 // so must use intrinsics to deinterleave.
4518 assert(InterleaveFactor <= 8 &&
4519 "Unsupported deinterleave factor for scalable vectors");
4520 NewLoad = State.Builder.CreateIntrinsicWithoutFolding(
4521 Intrinsic::getDeinterleaveIntrinsicID(InterleaveFactor),
4522 NewLoad->getType(), NewLoad,
4523 /*FMFSource=*/nullptr, "strided.vec");
4524 }
4525
4526 auto CreateStridedVector = [&InterleaveFactor, &State,
4527 &NewLoad](unsigned Index) -> Value * {
4528 assert(Index < InterleaveFactor && "Illegal group index");
4529 if (State.VF.isScalable())
4530 return State.Builder.CreateExtractValue(NewLoad, Index);
4531
4532 // For fixed length VF, use shuffle to extract the sub-vectors from the
4533 // wide load.
4534 auto StrideMask =
4535 createStrideMask(Index, InterleaveFactor, State.VF.getFixedValue());
4536 return State.Builder.CreateShuffleVector(NewLoad, StrideMask,
4537 "strided.vec");
4538 };
4539
4540 for (unsigned I = 0, J = 0; I < InterleaveFactor; ++I) {
4541 Instruction *Member = Group->getMember(I);
4542
4543 // Skip the gaps in the group.
4544 if (!Member)
4545 continue;
4546
4547 Value *StridedVec = CreateStridedVector(I);
4548
4549 // If this member has different type, cast the result type.
4550 if (Member->getType() != ScalarTy) {
4551 VectorType *OtherVTy = VectorType::get(Member->getType(), State.VF);
4552 StridedVec =
4553 createBitOrPointerCast(State.Builder, StridedVec, OtherVTy, DL);
4554 }
4555
4556 if (Group->isReverse())
4557 StridedVec = State.Builder.CreateVectorReverse(StridedVec, "reverse");
4558
4559 State.set(VPDefs[J], StridedVec);
4560 ++J;
4561 }
4562 return;
4563 }
4564
4565 // The sub vector type for current instruction.
4566 auto *SubVT = VectorType::get(ScalarTy, State.VF);
4567
4568 // Vectorize the interleaved store group.
4569 Value *MaskForGaps =
4570 createBitMaskForGaps(State.Builder, State.VF.getKnownMinValue(), *Group);
4571 assert(((MaskForGaps != nullptr) == needsMaskForGaps()) &&
4572 "Mismatch between NeedsMaskForGaps and MaskForGaps");
4573 ArrayRef<VPValue *> StoredValues = getStoredValues();
4574 // Collect the stored vector from each member.
4575 SmallVector<Value *, 4> StoredVecs;
4576 unsigned StoredIdx = 0;
4577 for (unsigned i = 0; i < InterleaveFactor; i++) {
4578 assert((Group->getMember(i) || MaskForGaps) &&
4579 "Fail to get a member from an interleaved store group");
4580 Instruction *Member = Group->getMember(i);
4581
4582 // Skip the gaps in the group.
4583 if (!Member) {
4584 Value *Undef = PoisonValue::get(SubVT);
4585 StoredVecs.push_back(Undef);
4586 continue;
4587 }
4588
4589 Value *StoredVec = State.get(StoredValues[StoredIdx]);
4590 ++StoredIdx;
4591
4592 if (Group->isReverse())
4593 StoredVec = State.Builder.CreateVectorReverse(StoredVec, "reverse");
4594
4595 // If this member has different type, cast it to a unified type.
4596
4597 if (StoredVec->getType() != SubVT)
4598 StoredVec = createBitOrPointerCast(State.Builder, StoredVec, SubVT, DL);
4599
4600 StoredVecs.push_back(StoredVec);
4601 }
4602
4603 // Interleave all the smaller vectors into one wider vector.
4604 Value *IVec = interleaveVectors(State.Builder, StoredVecs, "interleaved.vec");
4605 Instruction *NewStoreInstr;
4606 if (BlockInMask || MaskForGaps) {
4607 Value *GroupMask = CreateGroupMask(MaskForGaps);
4608 NewStoreInstr = State.Builder.CreateMaskedStore(
4609 IVec, ResAddr, Group->getAlign(), GroupMask);
4610 } else
4611 NewStoreInstr =
4612 State.Builder.CreateAlignedStore(IVec, ResAddr, Group->getAlign());
4613
4614 applyMetadata(*NewStoreInstr);
4615 // TODO: Also manage existing metadata using VPIRMetadata.
4616 Group->addMetadata(NewStoreInstr);
4617}
4618
4619#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4621 VPSlotTracker &SlotTracker) const {
4623 O << Indent << "INTERLEAVE-GROUP with factor " << IG->getFactor() << ", ";
4625 VPValue *Mask = getMask();
4626 if (Mask) {
4627 O << ", ";
4628 Mask->printAsOperand(O, SlotTracker);
4629 }
4630
4631 unsigned OpIdx = 0;
4632 for (unsigned i = 0; i < IG->getFactor(); ++i) {
4633 if (!IG->getMember(i))
4634 continue;
4635 if (getNumStoreOperands() > 0) {
4636 O << "\n" << Indent << " store ";
4638 O << " to index " << i;
4639 } else {
4640 O << "\n" << Indent << " ";
4642 O << " = load from index " << i;
4643 }
4644 ++OpIdx;
4645 }
4646}
4647#endif
4648
4650 assert(State.VF.isScalable() &&
4651 "Only support scalable VF for EVL tail-folding.");
4653 "Masking gaps for scalable vectors is not yet supported.");
4655 Instruction *Instr = Group->getInsertPos();
4656
4657 // Prepare for the vector type of the interleaved load/store.
4658 Type *ScalarTy = getLoadStoreType(Instr);
4659 unsigned InterleaveFactor = Group->getFactor();
4660 assert(InterleaveFactor <= 8 &&
4661 "Unsupported deinterleave/interleave factor for scalable vectors");
4662 ElementCount WideVF = State.VF * InterleaveFactor;
4663 auto *VecTy = VectorType::get(ScalarTy, WideVF);
4664
4665 VPValue *Addr = getAddr();
4666 Value *ResAddr = State.get(Addr, VPLane(0));
4667 Value *EVL = State.get(getEVL(), VPLane(0));
4668 Value *InterleaveEVL = State.Builder.CreateMul(
4669 EVL, ConstantInt::get(EVL->getType(), InterleaveFactor), "interleave.evl",
4670 /* NUW= */ true, /* NSW= */ true);
4671 LLVMContext &Ctx = State.Builder.getContext();
4672
4673 Value *GroupMask = nullptr;
4674 if (VPValue *BlockInMask = getMask()) {
4675 SmallVector<Value *> Ops(InterleaveFactor, State.get(BlockInMask));
4676 GroupMask = interleaveVectors(State.Builder, Ops, "interleaved.mask");
4677 } else {
4678 GroupMask =
4679 State.Builder.CreateVectorSplat(WideVF, State.Builder.getTrue());
4680 }
4681
4682 // Vectorize the interleaved load group.
4683 if (isa<LoadInst>(Instr)) {
4684 CallInst *NewLoad = State.Builder.CreateIntrinsicWithoutFolding(
4685 VecTy, Intrinsic::vp_load, {ResAddr, GroupMask, InterleaveEVL}, nullptr,
4686 "wide.vp.load");
4687 NewLoad->addParamAttr(0,
4688 Attribute::getWithAlignment(Ctx, Group->getAlign()));
4689
4690 applyMetadata(*NewLoad);
4691 // TODO: Also manage existing metadata using VPIRMetadata.
4692 Group->addMetadata(NewLoad);
4693
4694 // Scalable vectors cannot use arbitrary shufflevectors (only splats),
4695 // so must use intrinsics to deinterleave.
4696 NewLoad = State.Builder.CreateIntrinsicWithoutFolding(
4697 Intrinsic::getDeinterleaveIntrinsicID(InterleaveFactor),
4698 NewLoad->getType(), NewLoad,
4699 /*FMFSource=*/nullptr, "strided.vec");
4700
4701 const DataLayout &DL = Instr->getDataLayout();
4702 for (unsigned I = 0, J = 0; I < InterleaveFactor; ++I) {
4703 Instruction *Member = Group->getMember(I);
4704 // Skip the gaps in the group.
4705 if (!Member)
4706 continue;
4707
4708 Value *StridedVec = State.Builder.CreateExtractValue(NewLoad, I);
4709 // If this member has different type, cast the result type.
4710 if (Member->getType() != ScalarTy) {
4711 VectorType *OtherVTy = VectorType::get(Member->getType(), State.VF);
4712 StridedVec =
4713 createBitOrPointerCast(State.Builder, StridedVec, OtherVTy, DL);
4714 }
4715
4716 State.set(getVPValue(J), StridedVec);
4717 ++J;
4718 }
4719 return;
4720 } // End for interleaved load.
4721
4722 // The sub vector type for current instruction.
4723 auto *SubVT = VectorType::get(ScalarTy, State.VF);
4724 // Vectorize the interleaved store group.
4725 ArrayRef<VPValue *> StoredValues = getStoredValues();
4726 // Collect the stored vector from each member.
4727 SmallVector<Value *, 4> StoredVecs;
4728 const DataLayout &DL = Instr->getDataLayout();
4729 for (unsigned I = 0, StoredIdx = 0; I < InterleaveFactor; I++) {
4730 Instruction *Member = Group->getMember(I);
4731 // Skip the gaps in the group.
4732 if (!Member) {
4733 StoredVecs.push_back(PoisonValue::get(SubVT));
4734 continue;
4735 }
4736
4737 Value *StoredVec = State.get(StoredValues[StoredIdx]);
4738 // If this member has different type, cast it to a unified type.
4739 if (StoredVec->getType() != SubVT)
4740 StoredVec = createBitOrPointerCast(State.Builder, StoredVec, SubVT, DL);
4741
4742 StoredVecs.push_back(StoredVec);
4743 ++StoredIdx;
4744 }
4745
4746 // Interleave all the smaller vectors into one wider vector.
4747 Value *IVec = interleaveVectors(State.Builder, StoredVecs, "interleaved.vec");
4748 CallInst *NewStore = State.Builder.CreateIntrinsicWithoutFolding(
4749 Type::getVoidTy(Ctx), Intrinsic::vp_store,
4750 {IVec, ResAddr, GroupMask, InterleaveEVL});
4751
4752 NewStore->addParamAttr(1,
4753 Attribute::getWithAlignment(Ctx, Group->getAlign()));
4754
4755 applyMetadata(*NewStore);
4756 // TODO: Also manage existing metadata using VPIRMetadata.
4757 Group->addMetadata(NewStore);
4758}
4759
4760#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4762 VPSlotTracker &SlotTracker) const {
4764 O << Indent << "INTERLEAVE-GROUP with factor " << IG->getFactor() << ", ";
4766 O << ", ";
4768 if (VPValue *Mask = getMask()) {
4769 O << ", ";
4770 Mask->printAsOperand(O, SlotTracker);
4771 }
4772
4773 unsigned OpIdx = 0;
4774 for (unsigned i = 0; i < IG->getFactor(); ++i) {
4775 if (!IG->getMember(i))
4776 continue;
4777 if (getNumStoreOperands() > 0) {
4778 O << "\n" << Indent << " vp.store ";
4780 O << " to index " << i;
4781 } else {
4782 O << "\n" << Indent << " ";
4784 O << " = vp.load from index " << i;
4785 }
4786 ++OpIdx;
4787 }
4788}
4789#endif
4790
4792 VPCostContext &Ctx) const {
4793 Instruction *InsertPos = getInsertPos();
4794 // Find the VPValue index of the interleave group. We need to skip gaps.
4795 unsigned InsertPosIdx = 0;
4796 for (unsigned Idx = 0; IG->getFactor(); ++Idx)
4797 if (auto *Member = IG->getMember(Idx)) {
4798 if (Member == InsertPos)
4799 break;
4800 InsertPosIdx++;
4801 }
4802 const VPValue *ValV = getNumDefinedValues() > 0
4803 ? getVPValue(InsertPosIdx)
4804 : getStoredValues()[InsertPosIdx];
4805 Type *ValTy = ValV->getScalarType();
4806 auto *VectorTy = cast<VectorType>(toVectorTy(ValTy, VF));
4807 unsigned AS =
4808 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4809
4810 unsigned InterleaveFactor = IG->getFactor();
4811 auto *WideVecTy = VectorType::get(ValTy, VF * InterleaveFactor);
4812
4813 // Holds the indices of existing members in the interleaved group.
4815 for (unsigned IF = 0; IF < InterleaveFactor; IF++)
4816 if (IG->getMember(IF))
4817 Indices.push_back(IF);
4818
4819 // Calculate the cost of the whole interleaved group.
4820 InstructionCost Cost = Ctx.TTI.getInterleavedMemoryOpCost(
4821 InsertPos->getOpcode(), WideVecTy, IG->getFactor(), Indices,
4822 IG->getAlign(), AS, Ctx.CostKind, getMask(), NeedsMaskForGaps);
4823
4824 if (!IG->isReverse())
4825 return Cost;
4826
4827 return Cost + IG->getNumMembers() *
4828 Ctx.TTI.getShuffleCost(TargetTransformInfo::SK_Reverse,
4829 VectorTy, VectorTy, {}, Ctx.CostKind,
4830 0);
4831}
4832
4834 return vputils::onlyScalarValuesUsed(this) &&
4835 (!IsScalable || vputils::onlyFirstLaneUsed(this));
4836}
4837
4838#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4840 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
4841 assert((getNumOperands() == 3 || getNumOperands() == 5) &&
4842 "unexpected number of operands");
4843 O << Indent << "EMIT ";
4845 O << " = WIDEN-POINTER-INDUCTION ";
4847 O << ", ";
4849 O << ", ";
4851 if (getNumOperands() == 5) {
4852 O << ", ";
4854 O << ", ";
4856 }
4857}
4858
4860 VPSlotTracker &SlotTracker) const {
4861 O << Indent << "EMIT ";
4863 O << " = EXPAND SCEV " << *Expr;
4864}
4865#endif
4866
4867#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4869 VPSlotTracker &SlotTracker) const {
4870 O << Indent << "EMIT ";
4872 O << " = WIDEN-CANONICAL-INDUCTION";
4873 printFlags(O);
4875}
4876#endif
4877
4879 auto &Builder = State.Builder;
4880 // Create a vector from the initial value.
4881 auto *VectorInit = getStartValue()->getLiveInIRValue();
4882
4883 Type *VecTy = State.VF.isScalar()
4884 ? VectorInit->getType()
4885 : VectorType::get(VectorInit->getType(), State.VF);
4886
4887 BasicBlock *VectorPH =
4888 State.CFG.VPBB2IRBB.at(getParent()->getCFGPredecessor(0));
4889 if (State.VF.isVector()) {
4890 auto *IdxTy = Builder.getInt32Ty();
4891 auto *One = ConstantInt::get(IdxTy, 1);
4892 IRBuilder<>::InsertPointGuard Guard(Builder);
4893 Builder.SetInsertPoint(VectorPH->getTerminator());
4894 auto *RuntimeVF = getRuntimeVF(Builder, IdxTy, State.VF);
4895 auto *LastIdx = Builder.CreateSub(RuntimeVF, One);
4896 VectorInit = Builder.CreateInsertElement(
4897 PoisonValue::get(VecTy), VectorInit, LastIdx, "vector.recur.init");
4898 }
4899
4900 // Create a phi node for the new recurrence.
4901 PHINode *Phi = PHINode::Create(VecTy, 2, "vector.recur");
4902 Phi->insertBefore(State.CFG.PrevBB->getFirstInsertionPt());
4903 Phi->addIncoming(VectorInit, VectorPH);
4904 State.set(this, Phi);
4905}
4906
4909 VPCostContext &Ctx) const {
4910 if (VF.isScalar())
4911 return Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
4912
4913 return 0;
4914}
4915
4916#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4918 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
4919 O << Indent << "FIRST-ORDER-RECURRENCE-PHI ";
4921 O << " = phi ";
4923}
4924#endif
4925
4927 // Reductions do not have to start at zero. They can start with
4928 // any loop invariant values.
4929 VPValue *StartVPV = getStartValue();
4930
4931 // In order to support recurrences we need to be able to vectorize Phi nodes.
4932 // Phi nodes have cycles, so we need to vectorize them in two stages. This is
4933 // stage #1: We create a new vector PHI node with no incoming edges. We'll use
4934 // this value when we vectorize all of the instructions that use the PHI.
4935 BasicBlock *VectorPH =
4936 State.CFG.VPBB2IRBB.at(getParent()->getCFGPredecessor(0));
4937 bool ScalarPHI = State.VF.isScalar() || isInLoop();
4938 Value *StartV = State.get(StartVPV, ScalarPHI);
4939 Type *VecTy = StartV->getType();
4940
4941 BasicBlock *HeaderBB = State.CFG.PrevBB;
4942 assert(State.CurrentParentLoop->getHeader() == HeaderBB &&
4943 "recipe must be in the vector loop header");
4944 auto *Phi = PHINode::Create(VecTy, 2, "vec.phi");
4945 Phi->insertBefore(HeaderBB->getFirstInsertionPt());
4946 State.set(this, Phi, isInLoop());
4947
4948 Phi->addIncoming(StartV, VectorPH);
4949}
4950
4951#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4953 VPSlotTracker &SlotTracker) const {
4954 O << Indent << "WIDEN-REDUCTION-PHI ";
4955
4957 O << " = phi (";
4958 printRecurrenceKind(O, Kind);
4959 O << ")";
4960 printFlags(O);
4962 if (getVFScaleFactor() > 1)
4963 O << " (VF scaled by 1/" << getVFScaleFactor() << ")";
4964}
4965#endif
4966
4968 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
4969 return vputils::onlyFirstLaneUsed(this);
4970}
4971
4973 executePhiRecipe(this, *this, State, /*IsScalar=*/false, Name);
4974}
4975
4977 VPCostContext &Ctx) const {
4978 return Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
4979}
4980
4981#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4983 VPSlotTracker &SlotTracker) const {
4984 O << Indent << "WIDEN-PHI ";
4985
4987 O << " = phi ";
4989}
4990#endif
4991
4993 BasicBlock *VectorPH =
4994 State.CFG.VPBB2IRBB.at(getParent()->getCFGPredecessor(0));
4995 Value *StartMask = State.get(getOperand(0));
4996 PHINode *Phi =
4997 State.Builder.CreatePHI(StartMask->getType(), 2, "active.lane.mask");
4998 Phi->addIncoming(StartMask, VectorPH);
4999 State.set(this, Phi);
5000}
5001
5002#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
5004 VPSlotTracker &SlotTracker) const {
5005 O << Indent << "ACTIVE-LANE-MASK-PHI ";
5006
5008 O << " = phi ";
5010}
5011#endif
5012
5013#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
5015 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
5016 O << Indent << "CURRENT-ITERATION-PHI ";
5017
5019 O << " = phi ";
5021}
5022#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
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
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:1534
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:1485
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:1530
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:378
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:1985
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