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 case VPExpandSCEVSC:
95 return false;
96 case VPBlendSC:
97 case VPReductionEVLSC:
98 case VPReductionSC:
99 case VPVectorPointerSC:
100 case VPWidenCanonicalIVSC:
101 case VPWidenCastSC:
102 case VPWidenGEPSC:
103 case VPWidenIntOrFpInductionSC:
104 case VPWidenLoadEVLSC:
105 case VPWidenLoadSC:
106 case VPWidenPHISC:
107 case VPWidenPointerInductionSC:
108 case VPWidenSC: {
109 const Instruction *I =
110 dyn_cast_or_null<Instruction>(getVPSingleValue()->getUnderlyingValue());
111 (void)I;
112 assert((!I || !I->mayWriteToMemory()) &&
113 "underlying instruction may write to memory");
114 return false;
115 }
116 default:
117 return true;
118 }
119}
120
122 switch (getVPRecipeID()) {
123 case VPExpressionSC:
124 return cast<VPExpressionRecipe>(this)->mayReadOrWriteMemory();
125 case VPInstructionSC:
126 return cast<VPInstruction>(this)->opcodeMayReadOrWriteFromMemory();
127 case VPWidenLoadEVLSC:
128 case VPWidenLoadSC:
129 return true;
130 case VPReplicateSC:
131 return cast<Instruction>(getVPSingleValue()->getUnderlyingValue())
132 ->mayReadFromMemory();
133 case VPWidenCallSC:
134 return !cast<VPWidenCallRecipe>(this)
135 ->getCalledScalarFunction()
136 ->onlyWritesMemory();
137 case VPWidenMemIntrinsicSC:
138 case VPWidenIntrinsicSC:
139 return cast<VPWidenIntrinsicRecipe>(this)->mayReadFromMemory();
140 case VPBranchOnMaskSC:
141 case VPDerivedIVSC:
142 case VPCurrentIterationPHISC:
143 case VPFirstOrderRecurrencePHISC:
144 case VPReductionPHISC:
145 case VPPredInstPHISC:
146 case VPScalarIVStepsSC:
147 case VPWidenStoreEVLSC:
148 case VPWidenStoreSC:
149 case VPExpandSCEVSC:
150 return false;
151 case VPBlendSC:
152 case VPReductionEVLSC:
153 case VPReductionSC:
154 case VPVectorPointerSC:
155 case VPWidenCanonicalIVSC:
156 case VPWidenCastSC:
157 case VPWidenGEPSC:
158 case VPWidenIntOrFpInductionSC:
159 case VPWidenPHISC:
160 case VPWidenPointerInductionSC:
161 case VPWidenSC: {
162 const Instruction *I =
163 dyn_cast_or_null<Instruction>(getVPSingleValue()->getUnderlyingValue());
164 (void)I;
165 assert((!I || !I->mayReadFromMemory()) &&
166 "underlying instruction may read from memory");
167 return false;
168 }
169 default:
170 // FIXME: Return false if the recipe represents an interleaved store.
171 return true;
172 }
173}
174
176 switch (getVPRecipeID()) {
177 case VPExpressionSC:
178 return cast<VPExpressionRecipe>(this)->mayHaveSideEffects();
179 case VPActiveLaneMaskPHISC:
180 case VPDerivedIVSC:
181 case VPCurrentIterationPHISC:
182 case VPFirstOrderRecurrencePHISC:
183 case VPReductionPHISC:
184 case VPPredInstPHISC:
185 case VPVectorEndPointerSC:
186 case VPExpandSCEVSC:
187 return false;
188 case VPInstructionSC: {
189 auto *VPI = cast<VPInstruction>(this);
190 return mayWriteToMemory() ||
191 VPI->getOpcode() == VPInstruction::BranchOnCount ||
192 VPI->getOpcode() == VPInstruction::BranchOnCond ||
193 VPI->getOpcode() == VPInstruction::BranchOnTwoConds;
194 }
195 case VPWidenCallSC: {
196 Function *Fn = cast<VPWidenCallRecipe>(this)->getCalledScalarFunction();
197 return mayWriteToMemory() || !Fn->doesNotThrow() || !Fn->willReturn();
198 }
199 case VPWidenMemIntrinsicSC:
200 case VPWidenIntrinsicSC:
201 return cast<VPWidenIntrinsicRecipe>(this)->mayHaveSideEffects();
202 case VPBlendSC:
203 case VPReductionEVLSC:
204 case VPReductionSC:
205 case VPScalarIVStepsSC:
206 case VPVectorPointerSC:
207 case VPWidenCanonicalIVSC:
208 case VPWidenCastSC:
209 case VPWidenGEPSC:
210 case VPWidenIntOrFpInductionSC:
211 case VPWidenPHISC:
212 case VPWidenPointerInductionSC:
213 case VPWidenSC: {
214 const Instruction *I =
215 dyn_cast_or_null<Instruction>(getVPSingleValue()->getUnderlyingValue());
216 (void)I;
217 assert((!I || !I->mayHaveSideEffects()) &&
218 "underlying instruction has side-effects");
219 return false;
220 }
221 case VPInterleaveEVLSC:
222 case VPInterleaveSC:
223 return mayWriteToMemory();
224 case VPWidenLoadEVLSC:
225 case VPWidenLoadSC:
226 case VPWidenStoreEVLSC:
227 case VPWidenStoreSC:
228 assert(
229 cast<VPWidenMemoryRecipe>(this)->getIngredient().mayHaveSideEffects() ==
231 "mayHaveSideffects result for ingredient differs from this "
232 "implementation");
233 return mayWriteToMemory();
234 case VPReplicateSC: {
235 auto *R = cast<VPReplicateRecipe>(this);
236 return R->getUnderlyingInstr()->mayHaveSideEffects();
237 }
238 default:
239 return true;
240 }
241}
242
244 switch (getVPRecipeID()) {
245 default:
246 return false;
247 case VPInstructionSC: {
248 unsigned Opcode = cast<VPInstruction>(this)->getOpcode();
249 if (Instruction::isCast(Opcode))
250 return true;
251
252 switch (Opcode) {
253 default:
254 return false;
255 case Instruction::Add:
256 case Instruction::Sub:
257 case Instruction::Mul:
258 case Instruction::GetElementPtr:
259 return true;
260 }
261 }
262 }
263}
264
266 assert(!Parent && "Recipe already in some VPBasicBlock");
267 assert(InsertPos->getParent() &&
268 "Insertion position not in any VPBasicBlock");
269 InsertPos->getParent()->insert(this, InsertPos->getIterator());
270}
271
272void VPRecipeBase::insertBefore(VPBasicBlock &BB,
274 assert(!Parent && "Recipe already in some VPBasicBlock");
275 assert(I == BB.end() || I->getParent() == &BB);
276 BB.insert(this, I);
277}
278
280 assert(!Parent && "Recipe already in some VPBasicBlock");
281 assert(InsertPos->getParent() &&
282 "Insertion position not in any VPBasicBlock");
283 InsertPos->getParent()->insert(this, std::next(InsertPos->getIterator()));
284}
285
287 assert(getParent() && "Recipe not in any VPBasicBlock");
289 Parent = nullptr;
290}
291
293 assert(getParent() && "Recipe not in any VPBasicBlock");
295}
296
299 insertAfter(InsertPos);
300}
301
307
309 // Get the underlying instruction for the recipe, if there is one. It is used
310 // to
311 // * decide if cost computation should be skipped for this recipe,
312 // * apply forced target instruction cost.
313 Instruction *UI = nullptr;
314 if (auto *S = dyn_cast<VPSingleDefRecipe>(this))
315 UI = dyn_cast_or_null<Instruction>(S->getUnderlyingValue());
316 else if (auto *IG = dyn_cast<VPInterleaveBase>(this))
317 UI = IG->getInsertPos();
318 else if (auto *WidenMem = dyn_cast<VPWidenMemoryRecipe>(this))
319 UI = &WidenMem->getIngredient();
320
321 InstructionCost RecipeCost;
322 if (UI && Ctx.skipCostComputation(UI, VF.isVector())) {
323 RecipeCost = 0;
324 } else {
325 RecipeCost = computeCost(VF, Ctx);
326 if (ForceTargetInstructionCost.getNumOccurrences() > 0 &&
327 RecipeCost.isValid()) {
328 if (UI)
330 else
331 RecipeCost = InstructionCost(0);
332 }
333 }
334
335 LLVM_DEBUG({
336 dbgs() << "Cost of " << RecipeCost << " for VF " << VF << ": ";
337 if (VPSlotTracker *SlotTracker = Ctx.getSlotTracker()) {
338 print(dbgs(), "", *SlotTracker);
339 dbgs() << "\n";
340 } else {
341 dump();
342 }
343 });
344 return RecipeCost;
345}
346
348 VPCostContext &Ctx) const {
349 llvm_unreachable("subclasses should implement computeCost");
350}
351
353 return (getVPRecipeID() >= VPFirstPHISC && getVPRecipeID() <= VPLastPHISC) ||
355}
356
358 assert(OpType == Other.OpType && "OpType must match");
359 switch (OpType) {
360 case OperationType::OverflowingBinOp:
361 WrapFlags.HasNUW &= Other.WrapFlags.HasNUW;
362 WrapFlags.HasNSW &= Other.WrapFlags.HasNSW;
363 break;
364 case OperationType::Trunc:
365 TruncFlags.HasNUW &= Other.TruncFlags.HasNUW;
366 TruncFlags.HasNSW &= Other.TruncFlags.HasNSW;
367 break;
368 case OperationType::DisjointOp:
369 DisjointFlags.IsDisjoint &= Other.DisjointFlags.IsDisjoint;
370 break;
371 case OperationType::PossiblyExactOp:
372 ExactFlags.IsExact &= Other.ExactFlags.IsExact;
373 break;
374 case OperationType::GEPOp:
375 GEPFlagsStorage &= Other.GEPFlagsStorage;
376 break;
377 case OperationType::FPMathOp:
378 case OperationType::FCmp:
379 assert((OpType != OperationType::FCmp ||
380 FCmpFlags.CmpPredStorage == Other.FCmpFlags.CmpPredStorage) &&
381 "Cannot drop CmpPredicate");
382 getFMFsRef() = getFastMathFlagsOrNone() & Other.getFastMathFlagsOrNone();
383 break;
384 case OperationType::NonNegOp:
385 NonNegFlags.NonNeg &= Other.NonNegFlags.NonNeg;
386 break;
387 case OperationType::Cmp:
388 assert(CmpPredStorage == Other.CmpPredStorage &&
389 "Cannot drop CmpPredicate");
390 break;
391 case OperationType::ReductionOp:
392 assert(ReductionFlags.Kind == Other.ReductionFlags.Kind &&
393 "Cannot change RecurKind");
394 assert(ReductionFlags.IsOrdered == Other.ReductionFlags.IsOrdered &&
395 "Cannot change IsOrdered");
396 assert(ReductionFlags.IsInLoop == Other.ReductionFlags.IsInLoop &&
397 "Cannot change IsInLoop");
398 getFMFsRef() = getFastMathFlagsOrNone() & Other.getFastMathFlagsOrNone();
399 break;
400 case OperationType::Other:
401 break;
402 }
403}
404
406 if (!hasFastMathFlags())
407 return {};
408 const FastMathFlagsTy &F = getFMFsRef();
409 FastMathFlags Res;
410 Res.setAllowReassoc(F.AllowReassoc);
411 Res.setNoNaNs(F.NoNaNs);
412 Res.setNoInfs(F.NoInfs);
413 Res.setNoSignedZeros(F.NoSignedZeros);
414 Res.setAllowReciprocal(F.AllowReciprocal);
415 Res.setAllowContract(F.AllowContract);
416 Res.setApproxFunc(F.ApproxFunc);
417 return Res;
418}
419
420#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
422
423void VPRecipeBase::print(raw_ostream &O, const Twine &Indent,
424 VPSlotTracker &SlotTracker) const {
425 printRecipe(O, Indent, SlotTracker);
426 if (auto DL = getDebugLoc()) {
427 O << ", !dbg ";
428 DL.print(O);
429 }
430
431 if (auto *Metadata = dyn_cast<VPIRMetadata>(this))
433}
434#endif
435
437 : VPSingleDefRecipe(VPRecipeBase::VPExpandSCEVSC, {}, Expr->getType()),
438 Expr(Expr) {}
439
440/// For call VPInstruction operands, return the operand index of the called
441/// function. The function is either the last operand (for unmasked calls) or
442/// the second-to-last operand (for masked calls).
444 unsigned NumOps = Operands.size();
445 auto *LastOp = dyn_cast<VPIRValue>(Operands[NumOps - 1]);
446 if (LastOp && isa<Function>(LastOp->getValue()))
447 return NumOps - 1;
449 "expected function operand");
450 return NumOps - 2;
451}
452
453/// For call VPInstruction operands, return the called function.
458
461 assert(!Operands.empty() &&
462 "zero-operand VPInstruction opcodes must pass explicit ResultTy");
463 // Assert operand \p Idx (if present and typed) has type \p ExpectedTy.
464 [[maybe_unused]] auto AssertOperandType = [&Operands](unsigned Idx,
465 Type *ExpectedTy) {
466 if (!ExpectedTy || Operands.size() <= Idx)
467 return;
468 [[maybe_unused]] Type *OpTy = Operands[Idx]->getScalarType();
469 assert((!OpTy || OpTy == ExpectedTy) &&
470 "different types inferred for different operands");
471 };
472
473 Type *Op0Ty = Operands[0]->getScalarType();
474 LLVMContext &Ctx = Op0Ty->getContext();
475 switch (Opcode) {
477 assert(Op0Ty->isIntegerTy(1) && "expected bool condition");
478 return Type::getVoidTy(Ctx);
480 assert(Op0Ty->isIntegerTy(1) && "expected bool condition");
481 AssertOperandType(1, IntegerType::get(Ctx, 1));
482 return Type::getVoidTy(Ctx);
484 assert(Op0Ty->isIntegerTy() && "expected integer operand");
485 AssertOperandType(1, Op0Ty);
486 return Type::getVoidTy(Ctx);
489 assert(Op0Ty->isIntegerTy() && "expected integer operand");
490 for (unsigned Idx = 1; Idx != Operands.size(); ++Idx)
491 AssertOperandType(Idx, Op0Ty);
492 return Op0Ty;
493 case Instruction::Switch:
494 for (unsigned Idx = 1; Idx != Operands.size(); ++Idx)
495 AssertOperandType(Idx, Op0Ty);
496 return Type::getVoidTy(Ctx);
497 case Instruction::Store:
498 return Type::getVoidTy(Ctx);
499 case Instruction::ICmp:
500 assert(Op0Ty->isIntOrPtrTy() && "expected integer or pointer operand");
501 AssertOperandType(1, Op0Ty);
502 return IntegerType::get(Ctx, 1);
503 case Instruction::FCmp:
504 assert(Op0Ty->isFloatingPointTy() && "expected floating-point operand");
505 AssertOperandType(1, Op0Ty);
506 return IntegerType::get(Ctx, 1);
509 assert(Op0Ty->isIntegerTy() && "expected integer operand");
510 AssertOperandType(1, Op0Ty);
511 return IntegerType::get(Ctx, 1);
513 assert(Op0Ty->isIntegerTy(1) && "expected bool operand");
514 return IntegerType::get(Ctx, 1);
517 assert(Op0Ty->isIntegerTy(1) && "expected bool operand");
518 AssertOperandType(1, Op0Ty);
519 return IntegerType::get(Ctx, 1);
521 assert(Op0Ty->isIntegerTy(1) && "expected bool operand");
522 for (unsigned Idx = 1; Idx != Operands.size(); ++Idx)
523 AssertOperandType(Idx, Op0Ty);
524 return IntegerType::get(Ctx, 1);
526 assert(Op0Ty->isIntegerTy() && "expected integer operand");
527 return IntegerType::get(Ctx, 32);
528 case Instruction::Select: {
529 assert((!Op0Ty || Op0Ty->isIntegerTy(1)) &&
530 "select condition must be bool");
531 Type *Op1Ty = Operands[1]->getScalarType();
532 AssertOperandType(2, Op1Ty);
533 return Op1Ty;
534 }
535 case Instruction::InsertElement:
536 // The inserted scalar (operand 1) must match the vector element type;
537 // operand 2 must be an integer.
538 AssertOperandType(1, Op0Ty);
539 assert(Operands[2]->getScalarType()->isIntegerTy() &&
540 "expected integer operand");
541 return Op0Ty;
543 // The start value and the identity value (operands 0 and 1) fill the same
544 // vector and must match in type; operand 2 is the scaling factor.
545 AssertOperandType(1, Op0Ty);
546 return Op0Ty;
548 assert(Operands.size() >= 2 && "ExtractLane requires a lane operand and "
549 "at least one source vector operand");
550 // Operand 0 is the lane index, used for integer arithmetic.
551 assert(Op0Ty->isIntegerTy() && "expected integer operand");
552 Type *Op1Ty = Operands[1]->getScalarType();
553 for (unsigned Idx = 2; Idx != Operands.size(); ++Idx)
554 AssertOperandType(Idx, Op1Ty);
555 return Op1Ty;
556 }
559 assert(Operands[0]->getScalarType()->isPointerTy() &&
560 "expected pointer operand");
561 assert(Operands[1]->getScalarType()->isIntegerTy() &&
562 "expected integer operand");
563 return Op0Ty;
564 case Instruction::ExtractValue: {
565 assert(Operands.size() == 2 && "expected single level extractvalue");
566 auto *StructTy = cast<StructType>(Op0Ty);
567 return StructTy->getTypeAtIndex(
568 cast<VPConstantInt>(Operands[1])->getZExtValue());
569 }
574 case Instruction::Load:
575 case Instruction::Alloca:
576 llvm_unreachable("type must be passed explicitly");
577 case Instruction::Call:
579 default:
580 break;
581 }
582
583 // Opcodes that require all operands to share the same scalar type as the
584 // result.
585 bool AllOperandsSameType =
586 Instruction::isBinaryOp(Opcode) ||
590 Opcode);
591 if (AllOperandsSameType)
592 for (unsigned Idx = 1; Idx != Operands.size(); ++Idx)
593 AssertOperandType(Idx, Op0Ty);
594
595 return Op0Ty;
596}
597
600 unsigned Opcode = I->getOpcode();
601 if (Instruction::isCast(Opcode) ||
602 is_contained(ArrayRef<unsigned>({Instruction::ExtractValue,
603 Instruction::Load, Instruction::Alloca}),
604 Opcode))
605 return I->getType();
607}
608
610 const VPIRFlags &Flags, const VPIRMetadata &MD,
611 DebugLoc DL, const Twine &Name, Type *ResultTy)
613 VPRecipeBase::VPInstructionSC, Operands,
614 ResultTy ? ResultTy
616 Flags, DL),
617 VPIRMetadata(MD), Opcode(Opcode), Name(Name.str()) {
619 "Set flags not supported for the provided opcode");
621 "Opcode requires specific flags to be set");
625 "number of operands does not match opcode");
626}
627
629 if (Instruction::isUnaryOp(Opcode) || Instruction::isCast(Opcode))
630 return 1;
631
632 if (Instruction::isBinaryOp(Opcode))
633 return 2;
634
635 switch (Opcode) {
638 return 0;
639 case Instruction::Alloca:
640 case Instruction::ExtractValue:
641 case Instruction::Freeze:
642 case Instruction::Load:
655 return 1;
656 case Instruction::ICmp:
657 case Instruction::FCmp:
658 case Instruction::ExtractElement:
659 case Instruction::Store:
672 return 2;
673 case Instruction::InsertElement:
674 case Instruction::Select:
677 return 3;
678 case Instruction::Call:
679 return getCalledFnOperandIndex(operands()) + 1;
680 case Instruction::GetElementPtr:
681 case Instruction::PHI:
682 case Instruction::Switch:
683 case Instruction::AtomicRMW:
684 case Instruction::AtomicCmpXchg:
685 case Instruction::Fence:
696 // Cannot determine the number of operands from the opcode.
697 return -1u;
698 }
699 llvm_unreachable("all cases should be handled above");
700}
701
703 return Opcode == VPInstruction::Unpack ||
705}
706
707bool VPInstruction::canGenerateScalarForFirstLane() const {
709 return true;
711 return true;
712 switch (Opcode) {
713 case Instruction::Freeze:
714 case Instruction::ICmp:
715 case Instruction::PHI:
716 case Instruction::Select:
726 return true;
727 default:
728 return false;
729 }
730}
731
733 if (Kind == RecurKind::Sub)
734 return Instruction::Add;
735 if (Kind == RecurKind::FSub)
736 return Instruction::FAdd;
737 llvm_unreachable("RecurKind should be Sub/FSub.");
738}
739
740Value *VPInstruction::generate(VPTransformState &State) {
741 IRBuilderBase &Builder = State.Builder;
742
744 bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this);
745 Value *A = State.get(getOperand(0), OnlyFirstLaneUsed);
746 Value *B = State.get(getOperand(1), OnlyFirstLaneUsed);
747 auto *Res =
748 Builder.CreateBinOp((Instruction::BinaryOps)getOpcode(), A, B, Name);
749 if (auto *I = dyn_cast<Instruction>(Res))
750 applyFlags(*I);
751 return Res;
752 }
753
754 switch (getOpcode()) {
755 case VPInstruction::Not: {
756 bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this);
757 Value *A = State.get(getOperand(0), OnlyFirstLaneUsed);
758 return Builder.CreateNot(A, Name);
759 }
760 case Instruction::ExtractElement: {
761 assert(State.VF.isVector() && "Only extract elements from vectors");
762 if (auto *Idx = dyn_cast<VPConstantInt>(getOperand(1)))
763 return State.get(getOperand(0), VPLane(Idx->getZExtValue()));
764 Value *Vec = State.get(getOperand(0));
765 Value *Idx = State.get(getOperand(1), /*IsScalar=*/true);
766 return Builder.CreateExtractElement(Vec, Idx, Name);
767 }
768 case Instruction::InsertElement: {
769 assert(State.VF.isVector() && "Can only insert elements into vectors");
770 Value *Vec = State.get(getOperand(0), /*IsScalar=*/false);
771 Value *Elt = State.get(getOperand(1), /*IsScalar=*/true);
772 Value *Idx = State.get(getOperand(2), /*IsScalar=*/true);
773 return Builder.CreateInsertElement(Vec, Elt, Idx, Name);
774 }
775 case Instruction::Freeze: {
777 return Builder.CreateFreeze(Op, Name);
778 }
779 case Instruction::FCmp:
780 case Instruction::ICmp: {
781 bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this);
782 Value *A = State.get(getOperand(0), OnlyFirstLaneUsed);
783 Value *B = State.get(getOperand(1), OnlyFirstLaneUsed);
784 return Builder.CreateCmp(getPredicate(), A, B, Name);
785 }
786 case Instruction::PHI: {
787 llvm_unreachable("should be handled by VPPhi::execute");
788 }
789 case Instruction::Select: {
790 bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this);
791 Value *Cond =
792 State.get(getOperand(0),
793 OnlyFirstLaneUsed || vputils::isSingleScalar(getOperand(0)));
794 Value *Op1 = State.get(getOperand(1), OnlyFirstLaneUsed);
795 Value *Op2 = State.get(getOperand(2), OnlyFirstLaneUsed);
796 return Builder.CreateSelectFMF(Cond, Op1, Op2, getFastMathFlagsOrNone(),
797 Name);
798 }
801 // Get first lane of vector induction variable.
802 Value *VIVElem0 = State.get(getOperand(0), VPLane(0));
803 // Get the original loop tripcount.
804 Value *ScalarTC = State.get(getOperand(1), VPLane(0));
805
806 uint64_t Multiplier =
808 ? cast<VPConstantInt>(getOperand(2))->getZExtValue()
809 : 1;
810
811 // If this part of the active lane mask is scalar, generate the CMP directly
812 // to avoid unnecessary extracts.
813 if (State.VF.isScalar() && Multiplier == 1)
814 return Builder.CreateCmp(CmpInst::Predicate::ICMP_ULT, VIVElem0, ScalarTC,
815 Name);
816
817 ElementCount EC = State.VF.multiplyCoefficientBy(Multiplier);
818 auto *PredTy = VectorType::get(Builder.getInt1Ty(), EC);
819 return Builder.CreateIntrinsic(Intrinsic::get_active_lane_mask,
820 {PredTy, ScalarTC->getType()},
821 {VIVElem0, ScalarTC}, nullptr, Name);
822 }
824 Value *Op = State.get(getOperand(0));
825 auto *VecTy = cast<VectorType>(Op->getType());
826 assert(VecTy->getScalarSizeInBits() == 1 &&
827 "NumActiveLanes only implemented for i1 vectors");
828
829 Type *Ty = getScalarType();
830 Value *ZExt = Builder.CreateCast(
831 Instruction::ZExt, Op, VectorType::get(Ty, VecTy->getElementCount()));
832 Value *NumActive =
833 Builder.CreateUnaryIntrinsic(Intrinsic::vector_reduce_add, ZExt);
834 return NumActive;
835 }
837 // Generate code to combine the previous and current values in vector v3.
838 //
839 // vector.ph:
840 // v_init = vector(..., ..., ..., a[-1])
841 // br vector.body
842 //
843 // vector.body
844 // i = phi [0, vector.ph], [i+4, vector.body]
845 // v1 = phi [v_init, vector.ph], [v2, vector.body]
846 // v2 = a[i, i+1, i+2, i+3];
847 // v3 = vector(v1(3), v2(0, 1, 2))
848
849 auto *V1 = State.get(getOperand(0));
850 if (!V1->getType()->isVectorTy())
851 return V1;
852 Value *V2 = State.get(getOperand(1));
853 return Builder.CreateVectorSpliceRight(V1, V2, 1, Name);
854 }
856 Value *ScalarTC = State.get(getOperand(0), VPLane(0));
857 Value *VFxUF = State.get(getOperand(1), VPLane(0));
858 Value *Sub = Builder.CreateSub(ScalarTC, VFxUF);
859 Value *Cmp =
860 Builder.CreateICmp(CmpInst::Predicate::ICMP_UGT, ScalarTC, VFxUF);
862 return Builder.CreateSelect(Cmp, Sub, Zero);
863 }
865 // TODO: Restructure this code with an explicit remainder loop, vsetvli can
866 // be outside of the main loop.
867 Value *AVL = State.get(getOperand(0), /*IsScalar*/ true);
868 // Compute EVL
869 assert(AVL->getType()->isIntegerTy() &&
870 "Requested vector length should be an integer.");
871
872 assert(State.VF.isScalable() && "Expected scalable vector factor.");
873 Value *VFArg = Builder.getInt32(State.VF.getKnownMinValue());
874
875 Value *EVL = Builder.CreateIntrinsic(
876 Builder.getInt32Ty(), Intrinsic::experimental_get_vector_length,
877 {AVL, VFArg, Builder.getTrue()});
878 return EVL;
879 }
881 Value *Cond = State.get(getOperand(0), VPLane(0));
882 // Replace the temporary unreachable terminator with a new conditional
883 // branch, hooking it up to backward destination for latch blocks now, and
884 // to forward destination(s) later when they are created.
885 // Second successor may be backwards - iff it is already in VPBB2IRBB.
886 VPBasicBlock *SecondVPSucc =
887 cast<VPBasicBlock>(getParent()->getSuccessors()[1]);
888 BasicBlock *SecondIRSucc = State.CFG.VPBB2IRBB.lookup(SecondVPSucc);
889 BasicBlock *IRBB = State.CFG.VPBB2IRBB[getParent()];
890 auto *Br = Builder.CreateCondBr(Cond, IRBB, SecondIRSucc);
891 // First successor is always forward, reset it to nullptr.
892 Br->setSuccessor(0, nullptr);
894 applyMetadata(*Br);
895 return Br;
896 }
898 return Builder.CreateVectorSplat(
899 State.VF, State.get(getOperand(0), /*IsScalar*/ true), "broadcast");
900 }
902 // For struct types, we need to build a new 'wide' struct type, where each
903 // element is widened, i.e., we create a struct of vectors.
904 auto *StructTy = cast<StructType>(getOperand(0)->getScalarType());
905 Value *Res = PoisonValue::get(toVectorizedTy(StructTy, State.VF));
906 for (const auto &[LaneIndex, Op] : enumerate(operands())) {
907 for (unsigned FieldIndex = 0; FieldIndex != StructTy->getNumElements();
908 FieldIndex++) {
909 Value *ScalarValue =
910 Builder.CreateExtractValue(State.get(Op, true), FieldIndex);
911 Value *VectorValue = Builder.CreateExtractValue(Res, FieldIndex);
912 VectorValue =
913 Builder.CreateInsertElement(VectorValue, ScalarValue, LaneIndex);
914 Res = Builder.CreateInsertValue(Res, VectorValue, FieldIndex);
915 }
916 }
917 return Res;
918 }
920 auto *ScalarTy = getOperand(0)->getScalarType();
921 auto NumOfElements = ElementCount::getFixed(getNumOperands());
922 Value *Res = PoisonValue::get(toVectorizedTy(ScalarTy, NumOfElements));
923 for (const auto &[Idx, Op] : enumerate(operands()))
924 Res = Builder.CreateInsertElement(Res, State.get(Op, true),
925 Builder.getInt64(Idx));
926 return Res;
927 }
929 if (State.VF.isScalar())
930 return State.get(getOperand(0), true);
931 IRBuilderBase::FastMathFlagGuard FMFG(Builder);
933 // If this start vector is scaled then it should produce a vector with fewer
934 // elements than the VF.
935 ElementCount VF = State.VF.divideCoefficientBy(
936 cast<VPConstantInt>(getOperand(2))->getZExtValue());
937 auto *Iden = Builder.CreateVectorSplat(VF, State.get(getOperand(1), true));
938 return Builder.CreateInsertElement(Iden, State.get(getOperand(0), true),
939 Builder.getInt64(0));
940 }
942 RecurKind RK = getRecurKind();
943 bool IsOrdered = isReductionOrdered();
944 bool IsInLoop = isReductionInLoop();
946 "FindIV should use min/max reduction kinds");
947
948 // The recipe may have multiple operands to be reduced together.
949 unsigned NumOperandsToReduce = getNumOperands();
950 VectorParts RdxParts(NumOperandsToReduce);
951 for (unsigned Part = 0; Part < NumOperandsToReduce; ++Part)
952 RdxParts[Part] = State.get(getOperand(Part), IsInLoop);
953
954 IRBuilderBase::FastMathFlagGuard FMFG(Builder);
956
957 // Reduce multiple operands into one.
958 Value *ReducedPartRdx = RdxParts[0];
959 if (IsOrdered) {
960 ReducedPartRdx = RdxParts[NumOperandsToReduce - 1];
961 } else {
962 // Floating-point operations should have some FMF to enable the reduction.
963 for (unsigned Part = 1; Part < NumOperandsToReduce; ++Part) {
964 Value *RdxPart = RdxParts[Part];
966 ReducedPartRdx = createMinMaxOp(Builder, RK, ReducedPartRdx, RdxPart);
967 else {
968 // For sub-recurrences, each part's reduction variable is already
969 // negative, we need to do: reduce.add(-acc_uf0 + -acc_uf1)
973 : (Instruction::BinaryOps)RecurrenceDescriptor::getOpcode(RK);
974 ReducedPartRdx =
975 Builder.CreateBinOp(Opcode, RdxPart, ReducedPartRdx, "bin.rdx");
976 }
977 }
978 }
979
980 // Create the reduction after the loop. Note that inloop reductions create
981 // the target reduction in the loop using a Reduction recipe.
982 if (State.VF.isVector() && !IsInLoop) {
983 // TODO: Support in-order reductions based on the recurrence descriptor.
984 // All ops in the reduction inherit fast-math-flags from the recurrence
985 // descriptor.
986 ReducedPartRdx = createSimpleReduction(Builder, ReducedPartRdx, RK);
987 }
988
989 return ReducedPartRdx;
990 }
993 unsigned Offset =
995 Value *Res;
996 if (State.VF.isVector()) {
997 assert(Offset <= State.VF.getKnownMinValue() &&
998 "invalid offset to extract from");
999 // Extract lane VF - Offset from the operand.
1000 Res = State.get(getOperand(0), VPLane::getLaneFromEnd(State.VF, Offset));
1001 } else {
1002 // TODO: Remove ExtractLastLane for scalar VFs.
1003 assert(Offset <= 1 && "invalid offset to extract from");
1004 Res = State.get(getOperand(0));
1005 }
1006 if (isa<ExtractElementInst>(Res))
1007 Res->setName(Name);
1008 return Res;
1009 }
1011 Value *A = State.get(getOperand(0));
1012 Value *B = State.get(getOperand(1));
1013 return Builder.CreateLogicalAnd(A, B, Name);
1014 }
1016 Value *A = State.get(getOperand(0));
1017 Value *B = State.get(getOperand(1));
1018 return Builder.CreateLogicalOr(A, B, Name);
1019 }
1020 case VPInstruction::PtrAdd: {
1021 assert((State.VF.isScalar() || vputils::onlyFirstLaneUsed(this)) &&
1022 "can only generate first lane for PtrAdd");
1023 Value *Ptr = State.get(getOperand(0), VPLane(0));
1024 Value *Addend = State.get(getOperand(1), VPLane(0));
1025 return Builder.CreatePtrAdd(Ptr, Addend, Name, getGEPNoWrapFlags());
1026 }
1028 Value *Ptr =
1030 Value *Addend = State.get(getOperand(1));
1031 return Builder.CreatePtrAdd(Ptr, Addend, Name, getGEPNoWrapFlags());
1032 }
1033 case VPInstruction::AnyOf: {
1034 Value *Res = Builder.CreateFreeze(State.get(getOperand(0)));
1035 for (VPValue *Op : drop_begin(operands()))
1036 Res = Builder.CreateOr(Res, Builder.CreateFreeze(State.get(Op)));
1037 return State.VF.isScalar() ? Res : Builder.CreateOrReduce(Res);
1038 }
1040 assert(getNumOperands() != 2 && "ExtractLane from single source should be "
1041 "simplified to ExtractElement.");
1042 Value *LaneToExtract = State.get(getOperand(0), true);
1043 Type *IdxTy = getOperand(0)->getScalarType();
1044 Value *Res = nullptr;
1045 Value *RuntimeVF = getRuntimeVF(Builder, IdxTy, State.VF);
1046
1047 for (unsigned Idx = 1; Idx != getNumOperands(); ++Idx) {
1048 Value *VectorStart =
1049 Builder.CreateMul(RuntimeVF, ConstantInt::get(IdxTy, Idx - 1));
1050 Value *VectorIdx = Idx == 1
1051 ? LaneToExtract
1052 : Builder.CreateSub(LaneToExtract, VectorStart);
1053 Value *Ext = State.VF.isScalar()
1054 ? State.get(getOperand(Idx))
1055 : Builder.CreateExtractElement(
1056 State.get(getOperand(Idx)), VectorIdx);
1057 if (Res) {
1058 Value *Cmp = Builder.CreateICmpUGE(LaneToExtract, VectorStart);
1059 Res = Builder.CreateSelect(Cmp, Ext, Res);
1060 } else {
1061 Res = Ext;
1062 }
1063 }
1064 return Res;
1065 }
1067 Type *Ty = this->getScalarType();
1068 if (getNumOperands() == 1) {
1069 Value *Mask = State.get(getOperand(0));
1070 return Builder.CreateCountTrailingZeroElems(Ty, Mask,
1071 /*ZeroIsPoison=*/false, Name);
1072 }
1073 // If there are multiple operands, create a chain of selects to pick the
1074 // first operand with an active lane and add the number of lanes of the
1075 // preceding operands.
1076 Value *RuntimeVF = getRuntimeVF(Builder, Ty, State.VF);
1077 unsigned LastOpIdx = getNumOperands() - 1;
1078 Value *Res = nullptr;
1079 for (int Idx = LastOpIdx; Idx >= 0; --Idx) {
1080 Value *TrailingZeros =
1081 State.VF.isScalar()
1082 ? Builder.CreateZExt(
1083 Builder.CreateICmpEQ(State.get(getOperand(Idx)),
1084 Builder.getFalse()),
1085 Ty)
1087 Ty, State.get(getOperand(Idx)),
1088 /*ZeroIsPoison=*/false, Name);
1089 Value *Current = Builder.CreateAdd(
1090 Builder.CreateMul(RuntimeVF, ConstantInt::get(Ty, Idx)),
1091 TrailingZeros);
1092 if (Res) {
1093 Value *Cmp = Builder.CreateICmpNE(TrailingZeros, RuntimeVF);
1094 Res = Builder.CreateSelect(Cmp, Current, Res);
1095 } else {
1096 Res = Current;
1097 }
1098 }
1099
1100 return Res;
1101 }
1103 return State.get(getOperand(0), true);
1105 return Builder.CreateVectorReverse(State.get(getOperand(0)), "reverse");
1107 Value *Result = State.get(getOperand(0), /*IsScalar=*/true);
1108 for (unsigned Idx = 1; Idx < getNumOperands(); Idx += 2) {
1109 Value *Data = State.get(getOperand(Idx));
1110 Value *Mask = State.get(getOperand(Idx + 1));
1111 Type *VTy = Data->getType();
1112
1113 if (State.VF.isScalar())
1114 Result = Builder.CreateSelect(Mask, Data, Result);
1115 else
1116 Result = Builder.CreateIntrinsic(
1117 Intrinsic::experimental_vector_extract_last_active, {VTy},
1118 {Data, Mask, Result});
1119 }
1120
1121 return Result;
1122 }
1124 Value *Src = State.get(getOperand(0));
1125 Type *DstTy = VectorType::get(getScalarType(), State.VF);
1126 uint64_t Part = cast<VPConstantInt>(getOperand(1))->getZExtValue();
1127
1128 if (Src->getType() == DstTy)
1129 return Src;
1130
1131 return Builder.CreateExtractVector(
1132 DstTy, Src, Builder.getInt64(State.VF.getKnownMinValue() * Part), Name);
1133 }
1134 default:
1135 llvm_unreachable("Unsupported opcode for instruction");
1136 }
1137}
1138
1140 unsigned Opcode, ElementCount VF, VPCostContext &Ctx) const {
1141 Type *ScalarTy = this->getScalarType();
1142 Type *ResultTy = VF.isVector() ? toVectorTy(ScalarTy, VF) : ScalarTy;
1143 switch (Opcode) {
1144 case Instruction::FNeg:
1145 return Ctx.TTI.getArithmeticInstrCost(Opcode, ResultTy, Ctx.CostKind);
1146 case Instruction::UDiv:
1147 case Instruction::SDiv:
1148 case Instruction::SRem:
1149 case Instruction::URem:
1150 case Instruction::Add:
1151 case Instruction::FAdd:
1152 case Instruction::Sub:
1153 case Instruction::FSub:
1154 case Instruction::Mul:
1155 case Instruction::FMul:
1156 case Instruction::FDiv:
1157 case Instruction::FRem:
1158 case Instruction::Shl:
1159 case Instruction::LShr:
1160 case Instruction::AShr:
1161 case Instruction::And:
1162 case Instruction::Or:
1163 case Instruction::Xor: {
1164 // Certain instructions can be cheaper if they have a constant second
1165 // operand. One example of this are shifts on x86.
1166 VPValue *RHS = getOperand(1);
1167 TargetTransformInfo::OperandValueInfo RHSInfo = Ctx.getOperandInfo(RHS);
1168
1169 if (RHSInfo.Kind == TargetTransformInfo::OK_AnyValue &&
1172
1175 if (CtxI)
1176 Operands.append(CtxI->value_op_begin(), CtxI->value_op_end());
1177 return Ctx.TTI.getArithmeticInstrCost(
1178 Opcode, ResultTy, Ctx.CostKind,
1179 {TargetTransformInfo::OK_AnyValue, TargetTransformInfo::OP_None},
1180 RHSInfo, Operands, CtxI, &Ctx.TLI);
1181 }
1182 case Instruction::Freeze:
1183 // NOTE: The only way to ask for the cost is via getInstructionCost, which
1184 // requires the actual vector instruction. Instead, both here and in the
1185 // LoopVectorizationCostModel::getInstructionCost the costs mirror the
1186 // current behaviour in llvm/Analysis/TargetTransformInfoImpl.h to keep
1187 // them in sync.
1188 return TTI::TCC_Free;
1189 case Instruction::ExtractValue:
1190 return Ctx.TTI.getInsertExtractValueCost(Instruction::ExtractValue,
1191 Ctx.CostKind);
1192 case Instruction::ICmp:
1193 case Instruction::FCmp: {
1194 Type *ScalarOpTy = getOperand(0)->getScalarType();
1195 Type *OpTy = VF.isVector() ? toVectorTy(ScalarOpTy, VF) : ScalarOpTy;
1197 return Ctx.TTI.getCmpSelInstrCost(
1199 Ctx.CostKind, {TTI::OK_AnyValue, TTI::OP_None},
1200 {TTI::OK_AnyValue, TTI::OP_None}, CtxI);
1201 }
1202 case Instruction::BitCast: {
1203 Type *ScalarTy = this->getScalarType();
1204 if (ScalarTy->isPointerTy())
1205 return 0;
1206 [[fallthrough]];
1207 }
1208 case Instruction::SExt:
1209 case Instruction::ZExt:
1210 case Instruction::FPToUI:
1211 case Instruction::FPToSI:
1212 case Instruction::FPExt:
1213 case Instruction::PtrToInt:
1214 case Instruction::PtrToAddr:
1215 case Instruction::IntToPtr:
1216 case Instruction::SIToFP:
1217 case Instruction::UIToFP:
1218 case Instruction::Trunc:
1219 case Instruction::FPTrunc:
1220 case Instruction::AddrSpaceCast: {
1221 // Computes the CastContextHint from a recipe that may access memory.
1222 auto ComputeCCH = [&](const VPRecipeBase *R) -> TTI::CastContextHint {
1223 if (isa<VPInterleaveBase>(R))
1225 if (const auto *ReplicateRecipe = dyn_cast<VPReplicateRecipe>(R)) {
1226 // Only compute CCH for memory operations, matching the legacy model
1227 // which only considers loads/stores for cast context hints.
1228 auto *UI = cast<Instruction>(ReplicateRecipe->getUnderlyingValue());
1229 if (!isa<LoadInst, StoreInst>(UI))
1231 return ReplicateRecipe->isPredicated() ? TTI::CastContextHint::Masked
1233 }
1234 const auto *WidenMemoryRecipe = dyn_cast<VPWidenMemoryRecipe>(R);
1235 if (WidenMemoryRecipe == nullptr)
1237 if (VF.isScalar())
1239 if (!WidenMemoryRecipe->isConsecutive())
1241 if (WidenMemoryRecipe->isMasked())
1244 };
1245
1246 VPValue *Operand = getOperand(0);
1248 bool IsReverse = false;
1249 // For Trunc/FPTrunc, get the context from the only user.
1250 if (Opcode == Instruction::Trunc || Opcode == Instruction::FPTrunc) {
1251 if (auto *Recipe = cast_or_null<VPRecipeBase>(getSingleUser())) {
1252 if (match(Recipe,
1256 IsReverse = true;
1258 Recipe->getVPSingleValue()->getSingleUser());
1259 }
1260 if (Recipe)
1261 CCH = ComputeCCH(Recipe);
1262 }
1263 }
1264 // For Z/Sext, get the context from the operand.
1265 else if (Opcode == Instruction::ZExt || Opcode == Instruction::SExt ||
1266 Opcode == Instruction::FPExt) {
1267 if (auto *Recipe = Operand->getDefiningRecipe()) {
1268 VPValue *ReverseOp;
1269 if (match(Recipe,
1270 m_CombineOr(m_Reverse(m_VPValue(ReverseOp)),
1272 m_VPValue(ReverseOp))))) {
1273 Recipe = ReverseOp->getDefiningRecipe();
1274 IsReverse = true;
1275 }
1276 if (Recipe)
1277 CCH = ComputeCCH(Recipe);
1278 }
1279 }
1280 if (IsReverse && CCH != TTI::CastContextHint::None)
1282
1283 auto *ScalarSrcTy = Operand->getScalarType();
1284 Type *SrcTy = VF.isVector() ? toVectorTy(ScalarSrcTy, VF) : ScalarSrcTy;
1285 // Arm TTI will use the underlying instruction to determine the cost.
1286 return Ctx.TTI.getCastInstrCost(
1287 Opcode, ResultTy, SrcTy, CCH, Ctx.CostKind,
1289 }
1290 case Instruction::Select: {
1292 bool IsScalarCond = getOperand(0)->isDefinedOutsideLoopRegions();
1293 Type *ScalarTy = this->getScalarType();
1294
1295 VPValue *Op0, *Op1;
1296 bool IsLogicalAnd =
1297 match(this, m_c_LogicalAnd(m_VPValue(Op0), m_VPValue(Op1)));
1298 bool IsLogicalOr =
1299 match(this, m_c_LogicalOr(m_VPValue(Op0), m_VPValue(Op1)));
1300 // Also match the inverted forms:
1301 // select x, false, y --> !x & y (still AND)
1302 // select x, y, true --> !x | y (still OR)
1303 IsLogicalAnd |=
1304 match(this, m_Select(m_VPValue(Op0), m_False(), m_VPValue(Op1)));
1305 IsLogicalOr |=
1306 match(this, m_Select(m_VPValue(Op0), m_VPValue(Op1), m_True()));
1307
1308 if (!IsScalarCond && ScalarTy->getScalarSizeInBits() == 1 &&
1309 (IsLogicalAnd || IsLogicalOr)) {
1310 // select x, y, false --> x & y
1311 // select x, true, y --> x | y
1312 const auto [Op1VK, Op1VP] = Ctx.getOperandInfo(Op0);
1313 const auto [Op2VK, Op2VP] = Ctx.getOperandInfo(Op1);
1314
1316 if (SI && all_of(operands(),
1317 [](VPValue *Op) { return Op->getUnderlyingValue(); }))
1318 append_range(Operands, SI->operands());
1319 return Ctx.TTI.getArithmeticInstrCost(
1320 IsLogicalOr ? Instruction::Or : Instruction::And, ResultTy,
1321 Ctx.CostKind, {Op1VK, Op1VP}, {Op2VK, Op2VP}, Operands, SI);
1322 }
1323
1324 Type *CondTy = getOperand(0)->getScalarType();
1325 if (!IsScalarCond && VF.isVector())
1326 CondTy = VectorType::get(CondTy, VF);
1327
1328 llvm::CmpPredicate Pred;
1329 if (!match(getOperand(0), m_Cmp(Pred, m_VPValue(), m_VPValue())))
1330 if (auto *CondIRV = dyn_cast<VPIRValue>(getOperand(0)))
1331 if (auto *Cmp = dyn_cast<CmpInst>(CondIRV->getValue()))
1332 Pred = Cmp->getPredicate();
1333 Type *VectorTy = toVectorTy(this->getScalarType(), VF);
1334 return Ctx.TTI.getCmpSelInstrCost(
1335 Instruction::Select, VectorTy, CondTy, Pred, Ctx.CostKind,
1336 {TTI::OK_AnyValue, TTI::OP_None}, {TTI::OK_AnyValue, TTI::OP_None}, SI);
1337 }
1338 }
1339 llvm_unreachable("called for unsupported opcode");
1340}
1341
1343 VPCostContext &Ctx) const {
1345 if (!getUnderlyingValue() && getOpcode() != Instruction::FMul) {
1346 // TODO: Compute cost for VPInstructions without underlying values once
1347 // the legacy cost model has been retired.
1348 return 0;
1349 }
1350
1352 "Should only generate a vector value or single scalar, not scalars "
1353 "for all lanes.");
1355 getOpcode(),
1357 }
1358
1359 switch (getOpcode()) {
1360 case Instruction::Select: {
1362 match(getOperand(0), m_Cmp(Pred, m_VPValue(), m_VPValue()));
1363 auto *CondTy = getOperand(0)->getScalarType();
1364 auto *VecTy = getOperand(1)->getScalarType();
1365 if (!vputils::onlyFirstLaneUsed(this)) {
1366 CondTy = toVectorTy(CondTy, VF);
1367 VecTy = toVectorTy(VecTy, VF);
1368 }
1369 return Ctx.TTI.getCmpSelInstrCost(Instruction::Select, VecTy, CondTy, Pred,
1370 Ctx.CostKind);
1371 }
1372 case Instruction::ExtractElement:
1374 if (VF.isScalar()) {
1375 // ExtractLane with VF=1 takes care of handling extracting across multiple
1376 // parts.
1377 return 0;
1378 }
1379
1380 // Add on the cost of extracting the element.
1381 auto *VecTy = toVectorTy(getOperand(0)->getScalarType(), VF);
1382 return Ctx.TTI.getVectorInstrCost(Instruction::ExtractElement, VecTy,
1383 Ctx.CostKind);
1384 }
1385 case VPInstruction::AnyOf: {
1386 auto *VecTy = toVectorTy(this->getScalarType(), VF);
1387 return Ctx.TTI.getArithmeticReductionCost(
1388 Instruction::Or, cast<VectorType>(VecTy), std::nullopt, Ctx.CostKind);
1389 }
1391 Type *Ty = this->getScalarType();
1392 Type *ScalarTy = getOperand(0)->getScalarType();
1393 if (VF.isScalar())
1394 return Ctx.TTI.getCmpSelInstrCost(Instruction::ICmp, ScalarTy,
1396 CmpInst::ICMP_EQ, Ctx.CostKind);
1397 // Calculate the cost of determining the lane index.
1398 auto *PredTy = toVectorTy(ScalarTy, VF);
1399 IntrinsicCostAttributes Attrs(Intrinsic::experimental_cttz_elts, Ty,
1400 {PredTy, Type::getInt1Ty(Ctx.LLVMCtx)});
1401 return Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
1402 }
1404 Type *Ty = this->getScalarType();
1405 Type *ScalarTy = getOperand(0)->getScalarType();
1406 if (VF.isScalar())
1407 return Ctx.TTI.getCmpSelInstrCost(Instruction::ICmp, ScalarTy,
1409 CmpInst::ICMP_EQ, Ctx.CostKind);
1410 // Calculate the cost of determining the lane index: NOT + cttz_elts + SUB.
1411 auto *PredTy = toVectorTy(ScalarTy, VF);
1412 IntrinsicCostAttributes Attrs(Intrinsic::experimental_cttz_elts, Ty,
1413 {PredTy, Type::getInt1Ty(Ctx.LLVMCtx)});
1414 InstructionCost Cost = Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
1415 // Add cost of NOT operation on the predicate.
1416 Cost += Ctx.TTI.getArithmeticInstrCost(
1417 Instruction::Xor, PredTy, Ctx.CostKind,
1418 {TargetTransformInfo::OK_AnyValue, TargetTransformInfo::OP_None},
1419 {TargetTransformInfo::OK_UniformConstantValue,
1420 TargetTransformInfo::OP_None});
1421 // Add cost of SUB operation on the index.
1422 Cost += Ctx.TTI.getArithmeticInstrCost(Instruction::Sub, Ty, Ctx.CostKind);
1423 return Cost;
1424 }
1426 Type *ScalarTy = this->getScalarType();
1427 Type *VecTy = toVectorTy(ScalarTy, VF);
1428 Type *MaskTy = toVectorTy(Type::getInt1Ty(Ctx.LLVMCtx), VF);
1430 Intrinsic::experimental_vector_extract_last_active, ScalarTy,
1431 {VecTy, MaskTy, ScalarTy});
1432 return Ctx.TTI.getIntrinsicInstrCost(ICA, Ctx.CostKind);
1433 }
1435 assert(VF.isVector() && "Scalar FirstOrderRecurrenceSplice?");
1436 Type *VectorTy = toVectorTy(this->getScalarType(), VF);
1437 return Ctx.TTI.getShuffleCost(
1439 cast<VectorType>(VectorTy), {}, Ctx.CostKind, -1);
1440 }
1443 Type *ArgTy = getOperand(0)->getScalarType();
1444 uint64_t Multiplier =
1446 ? cast<VPConstantInt>(getOperand(2))->getZExtValue()
1447 : 1;
1448 Type *RetTy = toVectorTy(Type::getInt1Ty(Ctx.LLVMCtx), VF * Multiplier);
1449 IntrinsicCostAttributes Attrs(Intrinsic::get_active_lane_mask, RetTy,
1450 {ArgTy, ArgTy});
1451 return Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
1452 }
1454 Type *Arg0Ty = getOperand(0)->getScalarType();
1455 Type *I32Ty = Type::getInt32Ty(Ctx.LLVMCtx);
1456 Type *I1Ty = Type::getInt1Ty(Ctx.LLVMCtx);
1457 IntrinsicCostAttributes Attrs(Intrinsic::experimental_get_vector_length,
1458 I32Ty, {Arg0Ty, I32Ty, I1Ty});
1459 return Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
1460 }
1462 assert(VF.isVector() && "Reverse operation must be vector type");
1463 Type *EltTy = this->getScalarType();
1464 // Skip the reverse operation cost for the mask.
1465 // FIXME: Remove this once redundant mask reverse operations can be
1466 // eliminated by VPlanTransforms::cse before cost computation.
1467 if (EltTy->isIntegerTy(1))
1468 return 0;
1469 auto *VectorTy = cast<VectorType>(toVectorTy(EltTy, VF));
1470 return Ctx.TTI.getShuffleCost(TargetTransformInfo::SK_Reverse, VectorTy,
1471 VectorTy, /*Mask=*/{}, Ctx.CostKind,
1472 /*Index=*/0);
1473 }
1475 // Add on the cost of extracting the element.
1476 auto *VecTy = toVectorTy(getOperand(0)->getScalarType(), VF);
1477 return Ctx.TTI.getIndexedVectorInstrCostFromEnd(Instruction::ExtractElement,
1478 VecTy, Ctx.CostKind, 0);
1479 }
1480 case VPInstruction::Not: {
1481 Type *ValTy = this->getScalarType();
1482 // InstCombine will fold `xor` to the conditional branch.
1483 if (auto *U = const_cast<VPUser *>(getSingleUser()))
1484 if (match(U, m_BranchOnCond(m_VPValue())))
1485 return 0;
1486 if (!vputils::onlyFirstLaneUsed(this))
1487 ValTy = toVectorTy(ValTy, VF);
1488 return Ctx.TTI.getArithmeticInstrCost(Instruction::Xor, ValTy,
1489 Ctx.CostKind);
1490 }
1492 // If TC <= VF then this is just a branch.
1493 // FIXME: Removing the branch happens in simplifyBranchConditionForVFAndUF
1494 // where it checks TC <= VF * UF, but we don't know UF yet. This means in
1495 // some cases we get a cost that's too high due to counting a cmp that
1496 // later gets removed.
1497 // FIXME: The compare could also be removed if TC = M * vscale,
1498 // VF = N * vscale, and M <= N. Detecting that would require having the
1499 // trip count as a SCEV though.
1502 if (TCConst && TCConst->getValue().ule(VF.getKnownMinValue()))
1503 return 0;
1504 // Otherwise BranchOnCount generates ICmpEQ followed by a branch.
1505 Type *ValTy = getOperand(0)->getScalarType();
1506 return Ctx.TTI.getCmpSelInstrCost(Instruction::ICmp, ValTy,
1508 CmpInst::ICMP_EQ, Ctx.CostKind);
1509 }
1510 case Instruction::FCmp:
1511 case Instruction::ICmp:
1513 getOpcode(),
1516 if (VF == ElementCount::getScalable(1))
1518 [[fallthrough]];
1519 default:
1520 // TODO: Compute cost other VPInstructions once the legacy cost model has
1521 // been retired.
1523 "unexpected VPInstruction witht underlying value");
1524 return 0;
1525 }
1526}
1527
1540
1542 switch (getOpcode()) {
1543 case Instruction::Load:
1544 case Instruction::PHI:
1548 return true;
1549 default:
1551 }
1552}
1553
1555#ifndef NDEBUG
1556 Type *Ty = Op->getScalarType();
1557 switch (getOpcode()) {
1561 assert(Ty == getOperand(0)->getScalarType() &&
1562 "types of operand 0 and new operand must match");
1563 break;
1567 assert(Ty == getOperand(0)->getScalarType() &&
1568 "appended operand must match operand 0's scalar type");
1569 break;
1571 assert(Ty == getOperand(1)->getScalarType() &&
1572 "appended operand must match operand 1's scalar type");
1573 break;
1575 // The recipe is constructed with 3 operands (result, data, mask). Extra
1576 // operands beyond that are appended in (data, mask) pairs.
1577 constexpr unsigned NumInitialOperands = 3;
1578 assert(getNumOperands() >= NumInitialOperands &&
1579 "ExtractLastActive must have at least the initial 3 operands");
1580 bool IsMaskSlot = ((getNumOperands() - NumInitialOperands) & 1u) == 1u;
1581 assert((IsMaskSlot ? Ty->isIntegerTy(1)
1582 : Ty == getOperand(1)->getScalarType()) &&
1583 "ExtractLastActive expects alternating data/mask operands "
1584 "matching operand 1's type and i1, respectively");
1585 break;
1586 }
1587 default:
1588 llvm_unreachable("opcode does not support growing the operand list "
1589 "outside of construction");
1590 }
1591#endif
1593}
1594
1596 assert(!isMasked() && "cannot execute masked VPInstruction");
1597 IRBuilderBase::FastMathFlagGuard FMFGuard(State.Builder);
1599 "Set flags not supported for the provided opcode");
1601 "Opcode requires specific flags to be set");
1602 State.Builder.setFastMathFlags(getFastMathFlagsOrNone());
1603 Value *GeneratedValue = generate(State);
1604 if (!hasResult())
1605 return;
1606 assert(GeneratedValue && "generate must produce a value");
1607 bool GeneratesPerFirstLaneOnly = canGenerateScalarForFirstLane() &&
1610 assert((((GeneratedValue->getType()->isVectorTy() ||
1611 GeneratedValue->getType()->isStructTy()) ==
1612 !GeneratesPerFirstLaneOnly) ||
1613 State.VF.isScalar()) &&
1614 "scalar value but not only first lane defined");
1615 State.set(this, GeneratedValue,
1616 /*IsScalar*/ GeneratesPerFirstLaneOnly);
1618 getOpcode() == Instruction::Freeze) {
1619 // FIXME: This is a workaround to enable reliable updates of the scalar loop
1620 // resume phis, and to let epilogue vectorization recover the frozen
1621 // reduction start from the main plan. Must be removed once epilogue
1622 // vectorization explicitly connects VPlans.
1623 setUnderlyingValue(GeneratedValue);
1624 }
1625}
1626
1630 return false;
1631 switch (getOpcode()) {
1632 case Instruction::ExtractValue:
1633 case Instruction::InsertValue:
1634 case Instruction::GetElementPtr:
1635 case Instruction::ExtractElement:
1636 case Instruction::InsertElement:
1637 case Instruction::Freeze:
1638 case Instruction::FCmp:
1639 case Instruction::ICmp:
1640 case Instruction::Select:
1641 case Instruction::PHI:
1669 case VPInstruction::Not:
1677 return false;
1680 AttributeSet Attrs =
1682 return !Attrs.getMemoryEffects().doesNotAccessMemory();
1683 }
1684 case Instruction::Call:
1686 default:
1687 return true;
1688 }
1689}
1690
1692 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
1694 return vputils::onlyFirstLaneUsed(this);
1695
1696 switch (getOpcode()) {
1697 default:
1698 return false;
1699 case Instruction::ExtractElement:
1700 return Op == getOperand(1);
1701 case Instruction::InsertElement:
1702 return Op == getOperand(1) || Op == getOperand(2);
1703 case Instruction::PHI:
1704 return true;
1705 case Instruction::FCmp:
1706 case Instruction::ICmp:
1707 case Instruction::Select:
1708 case Instruction::Or:
1709 case Instruction::Freeze:
1710 case VPInstruction::Not:
1711 // TODO: Cover additional opcodes.
1712 return vputils::onlyFirstLaneUsed(this);
1713 case Instruction::Load:
1726 return true;
1729 // Before replicating by VF, Build(Struct)Vector uses all lanes of the
1730 // operand, after replicating its operands only the first lane is used.
1731 // Before replicating, it will have only a single operand.
1732 return getNumOperands() > 1;
1734 return Op == getOperand(0) || vputils::onlyFirstLaneUsed(this);
1736 // WidePtrAdd supports scalar and vector base addresses.
1737 return false;
1740 return Op == getOperand(0);
1741 };
1742 llvm_unreachable("switch should return");
1743}
1744
1746 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
1748 return vputils::onlyFirstPartUsed(this);
1749
1750 switch (getOpcode()) {
1751 default:
1752 return false;
1753 case Instruction::FCmp:
1754 case Instruction::ICmp:
1755 case Instruction::Select:
1756 return vputils::onlyFirstPartUsed(this);
1761 return true;
1762 };
1763 llvm_unreachable("switch should return");
1764}
1765
1766#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1768 VPSlotTracker SlotTracker(getParent()->getPlan());
1770}
1771
1773 VPSlotTracker &SlotTracker) const {
1774 O << Indent << "EMIT" << (isSingleScalar() ? "-SCALAR" : "") << " ";
1775
1776 if (hasResult()) {
1778 O << " = ";
1779 }
1780
1781 switch (getOpcode()) {
1782 case VPInstruction::Not:
1783 O << "not";
1784 break;
1786 O << "active lane mask";
1787 break;
1789 O << "wide active lane mask";
1790 break;
1792 O << "incoming-alias-mask";
1793 break;
1795 O << "EXPLICIT-VECTOR-LENGTH";
1796 break;
1798 O << "first-order splice";
1799 break;
1801 O << "branch-on-cond";
1802 break;
1804 O << "branch-on-two-conds";
1805 break;
1807 O << "TC > VF ? TC - VF : 0";
1808 break;
1810 O << "VF * Part +";
1811 break;
1813 O << "branch-on-count";
1814 break;
1816 O << "broadcast";
1817 break;
1819 O << "buildstructvector";
1820 break;
1822 O << "buildvector";
1823 break;
1825 O << "exiting-iv-value";
1826 break;
1828 O << "masked-cond";
1829 break;
1831 O << "extract-lane";
1832 break;
1834 O << "extract-last-lane";
1835 break;
1837 O << "extract-last-part";
1838 break;
1840 O << "extract-penultimate-element";
1841 break;
1843 O << "extract-vector-for-part";
1844 break;
1846 O << "compute-reduction-result";
1847 break;
1849 O << "logical-and";
1850 break;
1852 O << "logical-or";
1853 break;
1855 O << "ptradd";
1856 break;
1858 O << "wide-ptradd";
1859 break;
1861 O << "any-of";
1862 break;
1864 O << "first-active-lane";
1865 break;
1867 O << "last-active-lane";
1868 break;
1870 O << "reduction-start-vector";
1871 break;
1873 O << "resume-for-epilogue";
1874 break;
1876 O << "reverse";
1877 break;
1879 O << "unpack";
1880 break;
1882 O << "extract-last-active";
1883 break;
1885 O << "num-active-lanes";
1886 break;
1887 default:
1889 }
1890
1891 printFlags(O);
1893}
1894#endif
1895
1897 Type *ResultTy = getResultType();
1899 Value *Op = State.get(getOperand(0), VPLane(0));
1900 Value *Cast = State.Builder.CreateCast(Instruction::CastOps(getOpcode()),
1901 Op, ResultTy);
1902 if (auto *CastOp = dyn_cast<Instruction>(Cast)) {
1903 applyFlags(*CastOp);
1904 applyMetadata(*CastOp);
1905 }
1906 State.set(this, Cast, VPLane(0));
1907 return;
1908 }
1909 switch (getOpcode()) {
1911 Value *StepVector =
1912 State.Builder.CreateStepVector(VectorType::get(ResultTy, State.VF));
1913 State.set(this, StepVector);
1914 break;
1915 }
1918 for (VPValue *Op : drop_end(operands()))
1919 Args.push_back(State.get(Op, /*IsSingleScalar=*/true));
1920 Value *Call =
1921 State.Builder.CreateIntrinsic(ResultTy, vputils::getIntrinsicID(this),
1922 Args, /*FMFSource=*/nullptr, getName());
1923 State.set(this, Call, true);
1924 break;
1925 }
1926
1927 default:
1928 llvm_unreachable("opcode not implemented yet");
1929 }
1930}
1931
1933 VPCostContext &Ctx) const {
1934 // NOTE: At the moment it seems only possible to expose this path for
1935 // the trunc, zext and sext opcodes. However, isScalarCast also covers
1936 // int<>fp conversions, bitcasts, ptr<>int conversions, etc.
1939 Ctx);
1940
1941 switch (getOpcode()) {
1943 // TODO: This isn't quite right since even if the step-vector is hoisted
1944 // out of the loop it has a non-zero cost in the middle block, etc.
1945 // Once the stepvector is correctly hoisted out of the vector loop by the
1946 // licm transform we can add the cost here so that it doesn't incorrectly
1947 // affect the choice of VF.
1948 return 0;
1950 Type *Ty = getScalarType();
1952 for (const VPValue *Op : drop_end(operands()))
1953 ArgTys.push_back(Op->getScalarType());
1954 IntrinsicCostAttributes Attrs(vputils::getIntrinsicID(this), Ty, ArgTys);
1955 return Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind);
1956 }
1957 default:
1958 // Although VPInstructionWithType is also used for
1959 // VPInstruction::WideIVStep it isn't currently possible to expose cases
1960 // where the cost is queried.
1961 llvm_unreachable("Unhandled opcode");
1962 }
1963 return 0;
1964}
1965
1966#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1968 VPSlotTracker &SlotTracker) const {
1969 O << Indent << "EMIT" << (isSingleScalar() ? "-SCALAR" : "") << " ";
1971 O << " = ";
1972
1973 Type *ResultTy = getResultType();
1974 switch (getOpcode()) {
1976 O << "wide-iv-step ";
1978 break;
1980 O << "step-vector " << *ResultTy;
1981 break;
1983 O << "call " << *ResultTy << " @"
1986 Op->printAsOperand(O, SlotTracker);
1987 });
1988 O << ")";
1989 break;
1990 }
1991 case Instruction::Load:
1992 O << "load ";
1994 break;
1995 default:
1996 assert(Instruction::isCast(getOpcode()) && "unhandled opcode");
1998 printFlags(O);
2000 O << " to " << *ResultTy;
2001 }
2002}
2003#endif
2004
2005/// Shared execute logic for VPPhi and VPWidenPHIRecipe. Creates a PHI node,
2006/// adds incoming values, and stores the result in State. For header phis, only
2007/// the preheader incoming value is added; the backedge is fixed up later by
2008/// VPlan::execute().
2010 VPTransformState &State, bool IsScalar,
2011 const Twine &Name) {
2012 unsigned NumIncoming = VPBlockUtils::isHeader(R->getParent(), State.VPDT)
2013 ? 1
2014 : Phi.getNumIncoming();
2015 Value *FirstInc = State.get(Phi.getIncomingValue(0), IsScalar);
2016 PHINode *NewPhi = State.Builder.CreatePHI(FirstInc->getType(), 2, Name);
2017 NewPhi->addIncoming(FirstInc,
2018 State.CFG.VPBB2IRBB.at(Phi.getIncomingBlock(0)));
2019 for (unsigned Idx = 1; Idx != NumIncoming; ++Idx)
2020 NewPhi->addIncoming(State.get(Phi.getIncomingValue(Idx), IsScalar),
2021 State.CFG.VPBB2IRBB.at(Phi.getIncomingBlock(Idx)));
2022 State.set(R, NewPhi, IsScalar);
2023}
2024
2026 executePhiRecipe(this, *this, State, /*IsScalar=*/true, getName());
2027}
2028
2029#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2030void VPPhi::printRecipe(raw_ostream &O, const Twine &Indent,
2031 VPSlotTracker &SlotTracker) const {
2032 O << Indent << "EMIT" << (isSingleScalar() ? "-SCALAR" : "") << " ";
2034 O << " = phi";
2035 printFlags(O);
2037}
2038#endif
2039
2040VPIRInstruction *VPIRInstruction ::create(Instruction &I) {
2041 if (auto *Phi = dyn_cast<PHINode>(&I))
2042 return new VPIRPhi(*Phi);
2043 return new VPIRInstruction(I);
2044}
2045
2047 assert(!isa<VPIRPhi>(this) && getNumOperands() == 0 &&
2048 "PHINodes must be handled by VPIRPhi");
2049 // Advance the insert point after the wrapped IR instruction. This allows
2050 // interleaving VPIRInstructions and other recipes.
2051 State.Builder.SetInsertPoint(I.getParent(), std::next(I.getIterator()));
2052}
2053
2055 VPCostContext &Ctx) const {
2056 // The recipe wraps an existing IR instruction on the border of VPlan's scope,
2057 // hence it does not contribute to the cost-modeling for the VPlan.
2058 return 0;
2059}
2060
2061#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2063 VPSlotTracker &SlotTracker) const {
2064 O << Indent << "IR " << I;
2065}
2066#endif
2067
2069 PHINode *Phi = &getIRPhi();
2070 for (const auto &[Idx, Op] : enumerate(operands())) {
2071 VPValue *ExitValue = Op;
2072 auto Lane = vputils::isSingleScalar(ExitValue)
2074 : VPLane::getLastLaneForVF(State.VF);
2075 VPBlockBase *Pred = getParent()->getPredecessors()[Idx];
2076 auto *PredVPBB = Pred->getExitingBasicBlock();
2077 BasicBlock *PredBB = State.CFG.VPBB2IRBB[PredVPBB];
2078 // Set insertion point in PredBB in case an extract needs to be generated.
2079 // TODO: Model extracts explicitly.
2080 State.Builder.SetInsertPoint(PredBB->getTerminator());
2081 Value *V = State.get(ExitValue, VPLane(Lane));
2082 // If there is no existing block for PredBB in the phi, add a new incoming
2083 // value. Otherwise update the existing incoming value for PredBB.
2084 if (Phi->getBasicBlockIndex(PredBB) == -1)
2085 Phi->addIncoming(V, PredBB);
2086 else
2087 Phi->setIncomingValueForBlock(PredBB, V);
2088 }
2089
2090 // Advance the insert point after the wrapped IR instruction. This allows
2091 // interleaving VPIRInstructions and other recipes.
2092 State.Builder.SetInsertPoint(Phi->getParent(), std::next(Phi->getIterator()));
2093}
2094
2096 VPRecipeBase *R = const_cast<VPRecipeBase *>(getAsRecipe());
2097 assert(R->getNumOperands() == R->getParent()->getNumPredecessors() &&
2098 "Number of phi operands must match number of predecessors");
2099 unsigned Position = R->getParent()->getIndexForPredecessor(IncomingBlock);
2100 R->removeOperand(Position);
2101}
2102
2103VPValue *
2105 VPRecipeBase *R = const_cast<VPRecipeBase *>(getAsRecipe());
2106 return getIncomingValue(R->getParent()->getIndexForPredecessor(VPBB));
2107}
2108
2110 VPValue *V) const {
2111 VPRecipeBase *R = const_cast<VPRecipeBase *>(getAsRecipe());
2112 R->setOperand(R->getParent()->getIndexForPredecessor(VPBB), V);
2113}
2114
2115#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2117 VPSlotTracker &SlotTracker) const {
2119 O << "[ ";
2120 std::get<0>(Op)->printAsOperand(O, SlotTracker);
2121 O << ", ";
2122 std::get<1>(Op)->printAsOperand(O);
2123 O << " ]";
2124 });
2125}
2126#endif
2127
2128#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2130 VPSlotTracker &SlotTracker) const {
2132
2133 if (getNumOperands() != 0) {
2134 O << " (extra operand" << (getNumOperands() > 1 ? "s" : "") << ": ";
2136 [&O, &SlotTracker](auto Op) {
2137 std::get<0>(Op)->printAsOperand(O, SlotTracker);
2138 O << " from ";
2139 std::get<1>(Op)->printAsOperand(O);
2140 });
2141 O << ")";
2142 }
2143}
2144#endif
2145
2147 for (const auto &[Kind, Node] : Metadata)
2148 I.setMetadata(Kind, Node);
2149}
2150
2152 SmallVector<std::pair<unsigned, MDNode *>> MetadataIntersection;
2153 for (const auto &[KindA, MDA] : Metadata) {
2154 for (const auto &[KindB, MDB] : Other.Metadata) {
2155 if (KindA == KindB && MDA == MDB) {
2156 MetadataIntersection.emplace_back(KindA, MDA);
2157 break;
2158 }
2159 }
2160 }
2161 Metadata = std::move(MetadataIntersection);
2162}
2163
2164#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2166 const Module *M = SlotTracker.getModule();
2167 if (Metadata.empty() || !M || !VPlanPrintMetadata)
2168 return;
2169
2170 ArrayRef<StringRef> MDNames = SlotTracker.getMDNames();
2171 O << " (";
2172 interleaveComma(Metadata, O, [&](const auto &KindNodePair) {
2173 auto [Kind, Node] = KindNodePair;
2174 assert(Kind < MDNames.size() && !MDNames[Kind].empty() &&
2175 "Unexpected unnamed metadata kind");
2176 O << "!" << MDNames[Kind] << " ";
2177 Node->printAsOperand(O, M);
2178 });
2179 O << ")";
2180}
2181#endif
2182
2184 assert(State.VF.isVector() && "not widening");
2185 assert(Variant != nullptr && "Can't create vector function.");
2186
2187 FunctionType *VFTy = Variant->getFunctionType();
2188 // Add return type if intrinsic is overloaded on it.
2190 for (const auto &I : enumerate(args())) {
2191 Value *Arg;
2192 // Some vectorized function variants may also take a scalar argument,
2193 // e.g. linear parameters for pointers. This needs to be the scalar value
2194 // from the start of the respective part when interleaving.
2195 if (!VFTy->getParamType(I.index())->isVectorTy())
2196 Arg = State.get(I.value(), VPLane(0));
2197 else
2198 Arg = State.get(I.value(), usesFirstLaneOnly(I.value()));
2199 Args.push_back(Arg);
2200 }
2201
2204 if (CI)
2205 CI->getOperandBundlesAsDefs(OpBundles);
2206
2207 CallInst *V = State.Builder.CreateCall(Variant, Args, OpBundles);
2208 applyFlags(*V);
2209 applyMetadata(*V);
2210 V->setCallingConv(Variant->getCallingConv());
2211
2212 if (!V->getType()->isVoidTy())
2213 State.set(this, V);
2214}
2215
2217 VPCostContext &Ctx) const {
2218 assert(getVectorizedTypeVF(Variant->getReturnType()) == VF &&
2219 "Variant return type must match VF");
2220 return computeCallCost(Variant, Ctx);
2221}
2222
2224 VPCostContext &Ctx) {
2225 return Ctx.TTI.getCallInstrCost(nullptr, Variant->getReturnType(),
2226 Variant->getFunctionType()->params(),
2227 Ctx.CostKind);
2228}
2229
2231 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
2232 assert(Variant && "Variant not set");
2233 FunctionType *VFTy = Variant->getFunctionType();
2234 return all_of(enumerate(args()), [VFTy, &Op](const auto &Arg) {
2235 auto [Idx, V] = Arg;
2236 Type *ArgTy = VFTy->getParamType(Idx);
2237 return V != Op || ArgTy->isIntegerTy() || ArgTy->isFloatingPointTy() ||
2238 ArgTy->isPointerTy() || ArgTy->isByteTy();
2239 });
2240}
2241
2242#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2244 VPSlotTracker &SlotTracker) const {
2245 O << Indent << "WIDEN-CALL ";
2246
2247 Function *CalledFn = getCalledScalarFunction();
2248 if (CalledFn->getReturnType()->isVoidTy())
2249 O << "void ";
2250 else {
2252 O << " = ";
2253 }
2254
2255 O << "call";
2256 printFlags(O);
2257 O << "@" << CalledFn->getName() << "(";
2258 interleaveComma(args(), O, [&O, &SlotTracker](VPValue *Op) {
2259 Op->printAsOperand(O, SlotTracker);
2260 });
2261 O << ")";
2262
2263 O << " (using library function";
2264 if (Variant->hasName())
2265 O << ": " << Variant->getName();
2266 O << ")";
2267}
2268#endif
2269
2271 assert(State.VF.isVector() && "not widening");
2272
2273 SmallVector<Type *, 2> TysForDecl;
2274 // Add return type if intrinsic is overloaded on it.
2275 if (isVectorIntrinsicWithOverloadTypeAtArg(VectorIntrinsicID, -1,
2276 State.TTI)) {
2277 Type *RetTy = toVectorizedTy(getScalarType(), State.VF);
2278 ArrayRef<Type *> ContainedTys = getContainedTypes(RetTy);
2279 for (auto [Idx, Ty] : enumerate(ContainedTys)) {
2281 Idx, State.TTI))
2282 TysForDecl.push_back(Ty);
2283 }
2284 }
2286 for (const auto &I : enumerate(operands())) {
2287 // Some intrinsics have a scalar argument - don't replace it with a
2288 // vector.
2289 Value *Arg;
2290 if (isVectorIntrinsicWithScalarOpAtArg(VectorIntrinsicID, I.index(),
2291 State.TTI))
2292 Arg = State.get(I.value(), VPLane(0));
2293 else
2294 Arg = State.get(I.value(), usesFirstLaneOnly(I.value()));
2295 if (isVectorIntrinsicWithOverloadTypeAtArg(VectorIntrinsicID, I.index(),
2296 State.TTI))
2297 TysForDecl.push_back(Arg->getType());
2298 Args.push_back(Arg);
2299 }
2300
2301 // Use vector version of the intrinsic.
2302 Module *M = State.Builder.GetInsertBlock()->getModule();
2303 Function *VectorF =
2304 Intrinsic::getOrInsertDeclaration(M, VectorIntrinsicID, TysForDecl);
2305 assert(VectorF &&
2306 "Can't retrieve vector intrinsic or vector-predication intrinsics.");
2307
2310 if (CI)
2311 CI->getOperandBundlesAsDefs(OpBundles);
2312
2313 CallInst *V = State.Builder.CreateCall(VectorF, Args, OpBundles);
2314
2315 applyFlags(*V);
2316 applyMetadata(*V);
2317
2318 return V;
2319}
2320
2322 CallInst *V = createVectorCall(State);
2323 if (!V->getType()->isVoidTy())
2324 State.set(this, V);
2325}
2326
2329 const VPRecipeWithIRFlags &R, ElementCount VF, VPCostContext &Ctx) {
2330 Type *ScalarRetTy = R.getScalarType();
2331 // Skip the reverse operation cost for the mask.
2332 // FIXME: Remove this once redundant mask reverse operations can be eliminated
2333 // by VPlanTransforms::cse before cost computation.
2334 if (ID == Intrinsic::experimental_vp_reverse && ScalarRetTy->isIntegerTy(1))
2335 return InstructionCost(0);
2336
2337 // Some backends analyze intrinsic arguments to determine cost. Use the
2338 // underlying value for the operand if it has one. Otherwise try to use the
2339 // operand of the underlying call instruction, if there is one. Otherwise
2340 // clear Arguments.
2341 // TODO: Rework TTI interface to be independent of concrete IR values.
2343 for (const auto &[Idx, Op] : enumerate(Operands)) {
2344 auto *V = Op->getUnderlyingValue();
2345 if (!V) {
2346 if (auto *UI = dyn_cast_or_null<CallBase>(R.getUnderlyingValue())) {
2347 Arguments.push_back(UI->getArgOperand(Idx));
2348 continue;
2349 }
2350 Arguments.clear();
2351 break;
2352 }
2353 Arguments.push_back(V);
2354 }
2355
2356 Type *RetTy = VF.isVector() ? toVectorizedTy(ScalarRetTy, VF) : ScalarRetTy;
2357 SmallVector<Type *> ParamTys =
2358 map_to_vector(Operands, [&](const VPValue *Op) {
2359 return toVectorTy(Op->getScalarType(), VF);
2360 });
2361
2363 for (const VPValue *Op : Operands)
2364 if (isa<VPWidenRecipe>(Op) &&
2367 break;
2368 }
2369
2370 // TODO: Rework TTI interface to avoid reliance on underlying IntrinsicInst.
2371 IntrinsicCostAttributes CostAttrs(
2372 ID, RetTy, Arguments, ParamTys, R.getFastMathFlagsOrNone(),
2373 dyn_cast_or_null<IntrinsicInst>(R.getUnderlyingValue()),
2375 return Ctx.TTI.getIntrinsicInstrCost(CostAttrs, Ctx.CostKind);
2376}
2377
2379 VPCostContext &Ctx) const {
2380 return computeCallCost(VectorIntrinsicID, operands(), *this, VF, Ctx);
2381}
2382
2384 return Intrinsic::getBaseName(VectorIntrinsicID);
2385}
2386
2388 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
2389 return all_of(enumerate(operands()), [this, &Op](const auto &X) {
2390 auto [Idx, V] = X;
2392 Idx, nullptr);
2393 });
2394}
2395
2396#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2398 VPSlotTracker &SlotTracker) const {
2399 O << Indent << "WIDEN-INTRINSIC ";
2400 if (getScalarType()->isVoidTy()) {
2401 O << "void ";
2402 } else {
2404 O << " = ";
2405 }
2406
2407 O << "call";
2408 printFlags(O);
2409 O << getIntrinsicName() << "(";
2411 O << ")";
2412}
2413#endif
2414
2416 CallInst *MemI = createVectorCall(State);
2418 assert(PtrPos && "Expected a memory intrinsic with a valid pointer position");
2419 MemI->addParamAttr(
2420 *PtrPos, Attribute::getWithAlignment(MemI->getContext(), Alignment));
2421 if (!MemI->getType()->isVoidTy())
2422 State.set(this, MemI);
2423}
2424
2426 Intrinsic::ID IID, Type *Ty, bool IsMasked, Align Alignment,
2427 VPCostContext &Ctx) {
2428 return Ctx.TTI.getMemIntrinsicInstrCost(
2429 MemIntrinsicCostAttributes(IID, Ty, /*Ptr=*/nullptr, IsMasked, Alignment),
2430 Ctx.CostKind);
2431}
2432
2435 VPCostContext &Ctx) const {
2436 Type *DataTy;
2438 DataTy = getOperand(*DataPos)->getScalarType();
2439 else
2440 DataTy = getScalarType();
2441 assert(!DataTy->isVoidTy() && "Expected a non-void data type");
2442 Type *Ty = toVectorTy(DataTy, VF);
2444 assert(MaskPos && "Expected a memory intrinsic with a valid mask position");
2446 !match(getOperand(*MaskPos), m_True()),
2447 Alignment, Ctx);
2448}
2449
2451 IRBuilderBase &Builder = State.Builder;
2452
2453 Value *Address = State.get(getOperand(0));
2454 Value *IncAmt = State.get(getOperand(1), /*IsScalar=*/true);
2455 VectorType *VTy = cast<VectorType>(Address->getType());
2456
2457 // The histogram intrinsic requires a mask even if the recipe doesn't;
2458 // if the mask operand was omitted then all lanes should be executed and
2459 // we just need to synthesize an all-true mask.
2460 Value *Mask = nullptr;
2461 if (VPValue *VPMask = getMask())
2462 Mask = State.get(VPMask);
2463 else
2464 Mask =
2465 Builder.CreateVectorSplat(VTy->getElementCount(), Builder.getInt1(1));
2466
2467 // If this is a subtract, we want to invert the increment amount. We may
2468 // add a separate intrinsic in future, but for now we'll try this.
2469 if (Opcode == Instruction::Sub)
2470 IncAmt = Builder.CreateNeg(IncAmt);
2471 else
2472 assert(Opcode == Instruction::Add && "only add or sub supported for now");
2473
2474 Instruction *HistogramInst = State.Builder.CreateIntrinsicWithoutFolding(
2475 Intrinsic::experimental_vector_histogram_add, {VTy, IncAmt->getType()},
2476 {Address, IncAmt, Mask});
2477 applyMetadata(*HistogramInst);
2478}
2479
2481 VPCostContext &Ctx) const {
2482 // FIXME: Take the gather and scatter into account as well. For now we're
2483 // generating the same cost as the fallback path, but we'll likely
2484 // need to create a new TTI method for determining the cost, including
2485 // whether we can use base + vec-of-smaller-indices or just
2486 // vec-of-pointers.
2487 assert(VF.isVector() && "Invalid VF for histogram cost");
2488 Type *AddressTy = getOperand(0)->getScalarType();
2489 VPValue *IncAmt = getOperand(1);
2490 Type *IncTy = IncAmt->getScalarType();
2491 VectorType *VTy = VectorType::get(IncTy, VF);
2492
2493 // Assume that a non-constant update value (or a constant != 1) requires
2494 // a multiply, and add that into the cost.
2495 InstructionCost MulCost =
2496 Ctx.TTI.getArithmeticInstrCost(Instruction::Mul, VTy, Ctx.CostKind);
2497 if (match(IncAmt, m_One()))
2498 MulCost = TTI::TCC_Free;
2499
2500 // Find the cost of the histogram operation itself.
2501 Type *PtrTy = VectorType::get(AddressTy, VF);
2502 Type *MaskTy = VectorType::get(Type::getInt1Ty(Ctx.LLVMCtx), VF);
2503 IntrinsicCostAttributes ICA(Intrinsic::experimental_vector_histogram_add,
2504 Type::getVoidTy(Ctx.LLVMCtx),
2505 {PtrTy, IncTy, MaskTy});
2506
2507 // Add the costs together with the add/sub operation.
2508 return Ctx.TTI.getIntrinsicInstrCost(ICA, Ctx.CostKind) + MulCost +
2509 Ctx.TTI.getArithmeticInstrCost(Opcode, VTy, Ctx.CostKind);
2510}
2511
2512#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2514 VPSlotTracker &SlotTracker) const {
2515 O << Indent << "WIDEN-HISTOGRAM buckets: ";
2517
2518 if (Opcode == Instruction::Sub)
2519 O << ", dec: ";
2520 else {
2521 assert(Opcode == Instruction::Add);
2522 O << ", inc: ";
2523 }
2525
2526 if (VPValue *Mask = getMask()) {
2527 O << ", mask: ";
2528 Mask->printAsOperand(O, SlotTracker);
2529 }
2530}
2531#endif
2532
2533VPIRFlags::FastMathFlagsTy::FastMathFlagsTy(const FastMathFlags &FMF) {
2534 AllowReassoc = FMF.allowReassoc();
2535 NoNaNs = FMF.noNaNs();
2536 NoInfs = FMF.noInfs();
2537 NoSignedZeros = FMF.noSignedZeros();
2538 AllowReciprocal = FMF.allowReciprocal();
2539 AllowContract = FMF.allowContract();
2540 ApproxFunc = FMF.approxFunc();
2541}
2542
2543VPIRFlags VPIRFlags::getDefaultFlags(unsigned Opcode, Type *ResultTy) {
2544 switch (Opcode) {
2545 case Instruction::Add:
2546 case Instruction::Sub:
2547 case Instruction::Mul:
2548 case Instruction::Shl:
2550 return WrapFlagsTy(false, false);
2551 case Instruction::Trunc:
2552 return TruncFlagsTy(false, false);
2553 case Instruction::Or:
2554 return DisjointFlagsTy(false);
2555 case Instruction::AShr:
2556 case Instruction::LShr:
2557 case Instruction::UDiv:
2558 case Instruction::SDiv:
2559 return ExactFlagsTy(false);
2560 case Instruction::GetElementPtr:
2563 return GEPNoWrapFlags::none();
2564 case Instruction::ZExt:
2565 case Instruction::UIToFP:
2566 return NonNegFlagsTy(false);
2567 case Instruction::FAdd:
2568 case Instruction::FSub:
2569 case Instruction::FMul:
2570 case Instruction::FDiv:
2571 case Instruction::FRem:
2572 case Instruction::FNeg:
2573 case Instruction::FPExt:
2574 case Instruction::FPTrunc:
2575 return FastMathFlags();
2576 case Instruction::Select:
2577 // Selects only have fast-math flags if they produce a floating-point value.
2578 if (ResultTy && FPMathOperator::isSupportedFloatingPointType(ResultTy))
2579 return FastMathFlags();
2580 return VPIRFlags();
2581 case Instruction::ICmp:
2582 case Instruction::FCmp:
2584 llvm_unreachable("opcode requires explicit flags");
2585 default:
2586 return VPIRFlags();
2587 }
2588}
2589
2590#if !defined(NDEBUG)
2591bool VPIRFlags::flagsValidForOpcode(unsigned Opcode) const {
2592 switch (OpType) {
2593 case OperationType::OverflowingBinOp:
2594 return Opcode == Instruction::Add || Opcode == Instruction::Sub ||
2595 Opcode == Instruction::Mul || Opcode == Instruction::Shl ||
2596 Opcode == VPInstruction::VPInstruction::CanonicalIVIncrementForPart;
2597 case OperationType::Trunc:
2598 return Opcode == Instruction::Trunc;
2599 case OperationType::DisjointOp:
2600 return Opcode == Instruction::Or;
2601 case OperationType::PossiblyExactOp:
2602 return Opcode == Instruction::AShr || Opcode == Instruction::LShr ||
2603 Opcode == Instruction::UDiv || Opcode == Instruction::SDiv;
2604 case OperationType::GEPOp:
2605 return Opcode == Instruction::GetElementPtr ||
2606 Opcode == VPInstruction::PtrAdd ||
2607 Opcode == VPInstruction::WidePtrAdd;
2608 case OperationType::FPMathOp:
2609 return Opcode == Instruction::Call || Opcode == Instruction::FAdd ||
2610 Opcode == Instruction::FMul || Opcode == Instruction::FSub ||
2611 Opcode == Instruction::FNeg || Opcode == Instruction::FDiv ||
2612 Opcode == Instruction::FRem || Opcode == Instruction::FPExt ||
2613 Opcode == Instruction::FPTrunc || Opcode == Instruction::PHI ||
2614 Opcode == Instruction::Select || Opcode == Instruction::SIToFP ||
2615 Opcode == Instruction::UIToFP ||
2616 Opcode == VPInstruction::WideIVStep ||
2618 case OperationType::FCmp:
2619 return Opcode == Instruction::FCmp;
2620 case OperationType::NonNegOp:
2621 return Opcode == Instruction::ZExt || Opcode == Instruction::UIToFP;
2622 case OperationType::Cmp:
2623 return Opcode == Instruction::FCmp || Opcode == Instruction::ICmp;
2624 case OperationType::ReductionOp:
2626 case OperationType::Other:
2627 return true;
2628 }
2629 llvm_unreachable("Unknown OperationType enum");
2630}
2631
2632bool VPIRFlags::hasRequiredFlagsForOpcode(unsigned Opcode) const {
2633 // Handle opcodes without default flags.
2634 if (Opcode == Instruction::ICmp)
2635 return OpType == OperationType::Cmp;
2636 if (Opcode == Instruction::FCmp)
2637 return OpType == OperationType::FCmp;
2639 return OpType == OperationType::ReductionOp;
2640
2641 OperationType Required = getDefaultFlags(Opcode).OpType;
2642 return Required == OperationType::Other || Required == OpType;
2643}
2644#endif
2645
2646#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2647static void printRecurrenceKind(raw_ostream &OS, const RecurKind &Kind) {
2648 switch (Kind) {
2649 case RecurKind::None:
2650 OS << "none";
2651 break;
2652 case RecurKind::Add:
2653 OS << "add";
2654 break;
2655 case RecurKind::Sub:
2656 OS << "sub";
2657 break;
2659 OS << "add-chain-with-subs";
2660 break;
2661 case RecurKind::Mul:
2662 OS << "mul";
2663 break;
2664 case RecurKind::Or:
2665 OS << "or";
2666 break;
2667 case RecurKind::And:
2668 OS << "and";
2669 break;
2670 case RecurKind::Xor:
2671 OS << "xor";
2672 break;
2673 case RecurKind::SMin:
2674 OS << "smin";
2675 break;
2676 case RecurKind::SMax:
2677 OS << "smax";
2678 break;
2679 case RecurKind::UMin:
2680 OS << "umin";
2681 break;
2682 case RecurKind::UMax:
2683 OS << "umax";
2684 break;
2685 case RecurKind::FAdd:
2686 OS << "fadd";
2687 break;
2689 OS << "fadd-chain-with-subs";
2690 break;
2691 case RecurKind::FSub:
2692 OS << "fsub";
2693 break;
2694 case RecurKind::FMul:
2695 OS << "fmul";
2696 break;
2697 case RecurKind::FMin:
2698 OS << "fmin";
2699 break;
2700 case RecurKind::FMax:
2701 OS << "fmax";
2702 break;
2703 case RecurKind::FMinNum:
2704 OS << "fminnum";
2705 break;
2706 case RecurKind::FMaxNum:
2707 OS << "fmaxnum";
2708 break;
2710 OS << "fminimum";
2711 break;
2713 OS << "fmaximum";
2714 break;
2716 OS << "fminimumnum";
2717 break;
2719 OS << "fmaximumnum";
2720 break;
2721 case RecurKind::FMulAdd:
2722 OS << "fmuladd";
2723 break;
2724 case RecurKind::AnyOf:
2725 OS << "any-of";
2726 break;
2727 case RecurKind::FindIV:
2728 OS << "find-iv";
2729 break;
2731 OS << "find-last";
2732 break;
2733 }
2734}
2735
2737 switch (OpType) {
2738 case OperationType::Cmp:
2740 break;
2741 case OperationType::FCmp:
2744 break;
2745 case OperationType::DisjointOp:
2746 if (DisjointFlags.IsDisjoint)
2747 O << " disjoint";
2748 break;
2749 case OperationType::PossiblyExactOp:
2750 if (ExactFlags.IsExact)
2751 O << " exact";
2752 break;
2753 case OperationType::OverflowingBinOp:
2754 if (WrapFlags.HasNUW)
2755 O << " nuw";
2756 if (WrapFlags.HasNSW)
2757 O << " nsw";
2758 break;
2759 case OperationType::Trunc:
2760 if (TruncFlags.HasNUW)
2761 O << " nuw";
2762 if (TruncFlags.HasNSW)
2763 O << " nsw";
2764 break;
2765 case OperationType::FPMathOp:
2767 break;
2768 case OperationType::GEPOp: {
2770 if (Flags.isInBounds())
2771 O << " inbounds";
2772 else if (Flags.hasNoUnsignedSignedWrap())
2773 O << " nusw";
2774 if (Flags.hasNoUnsignedWrap())
2775 O << " nuw";
2776 break;
2777 }
2778 case OperationType::NonNegOp:
2779 if (NonNegFlags.NonNeg)
2780 O << " nneg";
2781 break;
2782 case OperationType::ReductionOp: {
2783 O << " (";
2785 if (isReductionInLoop())
2786 O << ", in-loop";
2787 if (isReductionOrdered())
2788 O << ", ordered";
2789 O << ")";
2791 break;
2792 }
2793 case OperationType::Other:
2794 break;
2795 }
2796 O << " ";
2797}
2798#endif
2799
2801 auto &Builder = State.Builder;
2802 switch (Opcode) {
2803 case Instruction::Call:
2804 case Instruction::UncondBr:
2805 case Instruction::CondBr:
2806 case Instruction::PHI:
2807 case Instruction::GetElementPtr:
2808 llvm_unreachable("This instruction is handled by a different recipe.");
2809 case Instruction::UDiv:
2810 case Instruction::SDiv:
2811 case Instruction::SRem:
2812 case Instruction::URem:
2813 case Instruction::Add:
2814 case Instruction::FAdd:
2815 case Instruction::Sub:
2816 case Instruction::FSub:
2817 case Instruction::FNeg:
2818 case Instruction::Mul:
2819 case Instruction::FMul:
2820 case Instruction::FDiv:
2821 case Instruction::FRem:
2822 case Instruction::Shl:
2823 case Instruction::LShr:
2824 case Instruction::AShr:
2825 case Instruction::And:
2826 case Instruction::Or:
2827 case Instruction::Xor: {
2828 // Just widen unops and binops.
2830 for (VPValue *VPOp : operands())
2831 Ops.push_back(State.get(VPOp));
2832
2833 Value *V = Builder.CreateNAryOp(Opcode, Ops);
2834
2835 if (auto *VecOp = dyn_cast<Instruction>(V)) {
2836 applyFlags(*VecOp);
2837 applyMetadata(*VecOp);
2838 }
2839
2840 // Use this vector value for all users of the original instruction.
2841 State.set(this, V);
2842 break;
2843 }
2844 case Instruction::ExtractValue: {
2845 assert(getNumOperands() == 2 && "expected single level extractvalue");
2846 Value *Op = State.get(getOperand(0));
2847 Value *Extract = Builder.CreateExtractValue(
2848 Op, cast<VPConstantInt>(getOperand(1))->getZExtValue());
2849 State.set(this, Extract);
2850 break;
2851 }
2852 case Instruction::Freeze: {
2853 Value *Op = State.get(getOperand(0));
2854 Value *Freeze = Builder.CreateFreeze(Op);
2855 State.set(this, Freeze);
2856 break;
2857 }
2858 case Instruction::ICmp:
2859 case Instruction::FCmp: {
2860 // Widen compares. Generate vector compares.
2861 bool FCmp = Opcode == Instruction::FCmp;
2862 Value *A = State.get(getOperand(0));
2863 Value *B = State.get(getOperand(1));
2864 Value *C = nullptr;
2865 if (FCmp) {
2866 C = Builder.CreateFCmp(getPredicate(), A, B);
2867 } else {
2868 C = Builder.CreateICmp(getPredicate(), A, B);
2869 }
2870 if (auto *I = dyn_cast<Instruction>(C)) {
2871 applyFlags(*I);
2872 applyMetadata(*I);
2873 }
2874 State.set(this, C);
2875 break;
2876 }
2877 case Instruction::Select: {
2878 VPValue *CondOp = getOperand(0);
2879 Value *Cond = State.get(CondOp, vputils::isSingleScalar(CondOp));
2880 Value *Op0 = State.get(getOperand(1));
2881 Value *Op1 = State.get(getOperand(2));
2882 Value *Sel = State.Builder.CreateSelect(Cond, Op0, Op1);
2883 State.set(this, Sel);
2884 if (auto *I = dyn_cast<Instruction>(Sel)) {
2886 applyFlags(*I);
2887 applyMetadata(*I);
2888 }
2889 break;
2890 }
2891 default:
2892 // This instruction is not vectorized by simple widening.
2893 LLVM_DEBUG(dbgs() << "LV: Found an unhandled opcode : "
2894 << Instruction::getOpcodeName(Opcode));
2895 llvm_unreachable("Unhandled instruction!");
2896 } // end of switch.
2897
2898#if !defined(NDEBUG)
2899 // Verify that VPlan type inference results agree with the type of the
2900 // generated values.
2901 assert(VectorType::get(this->getScalarType(), State.VF) ==
2902 State.get(this)->getType() &&
2903 "inferred type and type from generated instructions do not match");
2904#endif
2905}
2906
2908 VPCostContext &Ctx) const {
2909 switch (Opcode) {
2910 case Instruction::UDiv:
2911 case Instruction::SDiv:
2912 case Instruction::SRem:
2913 case Instruction::URem:
2914 // If the div/rem operation isn't safe to speculate and requires
2915 // predication, then the only way we can even create a vplan is to insert
2916 // a select on the second input operand to ensure we use the value of 1
2917 // for the inactive lanes. The select will be costed separately.
2918 case Instruction::FNeg:
2919 case Instruction::Add:
2920 case Instruction::FAdd:
2921 case Instruction::Sub:
2922 case Instruction::FSub:
2923 case Instruction::Mul:
2924 case Instruction::FMul:
2925 case Instruction::FDiv:
2926 case Instruction::FRem:
2927 case Instruction::Shl:
2928 case Instruction::LShr:
2929 case Instruction::AShr:
2930 case Instruction::And:
2931 case Instruction::Or:
2932 case Instruction::Xor:
2933 case Instruction::Freeze:
2934 case Instruction::ExtractValue:
2935 case Instruction::ICmp:
2936 case Instruction::FCmp:
2937 case Instruction::Select:
2938 return getCostForRecipeWithOpcode(getOpcode(), VF, Ctx);
2939 default:
2940 llvm_unreachable("Unsupported opcode for instruction");
2941 }
2942}
2943
2944#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2946 VPSlotTracker &SlotTracker) const {
2947 O << Indent << "WIDEN ";
2949 O << " = " << Instruction::getOpcodeName(Opcode);
2950 printFlags(O);
2952}
2953#endif
2954
2956 auto &Builder = State.Builder;
2957 /// Vectorize casts.
2958 assert(State.VF.isVector() && "Not vectorizing?");
2959 Type *DestTy = VectorType::get(getScalarType(), State.VF);
2960 VPValue *Op = getOperand(0);
2961 Value *A = State.get(Op);
2962 Value *Cast = Builder.CreateCast(Instruction::CastOps(Opcode), A, DestTy);
2963 State.set(this, Cast);
2964 if (auto *CastOp = dyn_cast<Instruction>(Cast)) {
2965 applyFlags(*CastOp);
2966 applyMetadata(*CastOp);
2967 }
2968}
2969
2974
2975#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2977 VPSlotTracker &SlotTracker) const {
2978 O << Indent << "WIDEN-CAST ";
2980 O << " = " << Instruction::getOpcodeName(Opcode);
2981 printFlags(O);
2983 O << " to " << *getScalarType();
2984}
2985#endif
2986
2988 VPCostContext &Ctx) const {
2989 return Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
2990}
2991
2992#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2994 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
2995 O << Indent;
2997 O << " = WIDEN-INDUCTION";
2998 printFlags(O);
3000
3001 if (auto *TI = getTruncInst())
3002 O << " (truncated to " << *TI->getType() << ")";
3003}
3004#endif
3005
3007 // The step may be defined by a recipe in the preheader (e.g. if it requires
3008 // SCEV expansion), but for the canonical induction the step is required to be
3009 // 1, which is represented as live-in.
3010 return match(getStartValue(), m_ZeroInt()) &&
3011 match(getStepValue(), m_One()) &&
3012 getScalarType() == getRegion()->getCanonicalIVType();
3013}
3014
3017 VPCostContext &Ctx) const {
3018 // A widened induction generates a vector phi and increments it by the
3019 // splatted step each iteration.
3021 InstructionCost Cost = Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
3022 Type *StepTy = getScalarType();
3023 unsigned IncOpc = ID.getKind() == InductionDescriptor::IK_IntInduction
3024 ? Instruction::Add
3025 : ID.getInductionOpcode();
3026 assert(IncOpc != Instruction::BinaryOpsEnd &&
3027 "induction must have a valid increment opcode");
3028 return Cost + Ctx.TTI.getArithmeticInstrCost(IncOpc, toVectorTy(StepTy, VF),
3029 Ctx.CostKind);
3030}
3031
3033 VPCostContext &Ctx) const {
3034 // The cost model for this is modelled on expandVPDerivedIV in
3035 // VPlanTransforms.cpp. In order to avoid overly pessimistic costs that can
3036 // negatively affect vectorization it takes into account any expected
3037 // simplifications that happen in simplifyRecipe.
3038 switch (getInductionKind()) {
3039 default:
3040 // TODO: Compute cost for remaining kinds.
3041 break;
3043 // There are currently no tests that expose a path where all lanes are
3044 // used, so it's better to bail out for now.
3045 if (!vputils::onlyFirstLaneUsed(this))
3046 break;
3047
3048 // Start off by assuming we need both mul and add, then refine this.
3049 bool NeedsMul = true, NeedsAdd = true, NeedsShl = false;
3050
3051 // If the start value is zero the add gets folded away.
3052 if (auto *StartC = dyn_cast<VPConstantInt>(getStartValue()))
3053 NeedsAdd = !StartC->isZero();
3054
3055 // For some values of step the arithmetic changes:
3056 // 1. A step of 1 requires no operation.
3057 // 2. A step of -1 requires a negate.
3058 // 3. A power-of-2 step will use a shl, instead of a mul.
3059 Type *StepTy = getStepValue()->getScalarType();
3061 if (auto *StepC = dyn_cast<VPConstantInt>(getStepValue())) {
3062 if (StepC->isOne())
3063 NeedsMul = false;
3064 else if (StepC->getAPInt().isAllOnes()) {
3065 // This will most likely end up as a negate in simplifyRecipe, and
3066 // the negate will be combined with the add to make a sub.
3067 // NOTE: This is perhaps an invalid assumption that the cost of an
3068 // 'add' is the same as a 'sub'.
3069 NeedsMul = false;
3070 NeedsAdd = true;
3071 } else if (StepC->getAPInt().isPowerOf2()) {
3072 // This will most likely end up as a shift-left in simplifyRecipe
3073 NeedsMul = false;
3074 NeedsShl = true;
3075 }
3076 }
3077
3078 // Add the cost of the conversion from index to step type if the index
3079 // will be used.
3080 Type *IndexTy = getIndex()->getScalarType();
3081 unsigned StepTySize = StepTy->getScalarSizeInBits();
3082 unsigned IndexTySize = IndexTy->getScalarSizeInBits();
3083 if ((NeedsAdd || NeedsMul || NeedsShl) && StepTySize != IndexTySize) {
3084 unsigned CastOpc =
3085 StepTySize < IndexTySize ? Instruction::Trunc : Instruction::ZExt;
3086 Cost += Ctx.TTI.getCastInstrCost(
3087 CastOpc, StepTy, IndexTy, TTI::CastContextHint::None, Ctx.CostKind);
3088 }
3089
3090 if (NeedsMul)
3091 Cost += Ctx.TTI.getArithmeticInstrCost(Instruction::Mul, StepTy,
3092 Ctx.CostKind);
3093 if (NeedsShl)
3094 Cost += Ctx.TTI.getArithmeticInstrCost(
3095 Instruction::Shl, StepTy, Ctx.CostKind,
3096 {TargetTransformInfo::OK_AnyValue, TargetTransformInfo::OP_None},
3097 {TargetTransformInfo::OK_UniformConstantValue,
3098 TargetTransformInfo::OP_None});
3099 if (NeedsAdd)
3100 Cost += Ctx.TTI.getArithmeticInstrCost(Instruction::Add, StepTy,
3101 Ctx.CostKind);
3102 return Cost;
3103 }
3104 }
3105
3106 return 0;
3107}
3108
3109#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3111 VPSlotTracker &SlotTracker) const {
3112 O << Indent;
3114 O << " = DERIVED-IV";
3115 printFlags(O);
3116 getStartValue()->printAsOperand(O, SlotTracker);
3117 O << " + ";
3118 getOperand(1)->printAsOperand(O, SlotTracker);
3119 O << " * ";
3120 getStepValue()->printAsOperand(O, SlotTracker);
3121}
3122#endif
3123
3127
3129 VPCostContext &Ctx) const {
3130 // TODO: Add costs for floating point.
3131 Type *BaseIVTy = getOperand(0)->getScalarType();
3132 if (!BaseIVTy->isIntegerTy())
3133 return 0;
3134
3135 // TODO: Add support for predicated regions. Requires scaling the cost by the
3136 // probability of entering the block.
3137 if (getRegion() && getRegion()->isReplicator())
3138 return 0;
3139
3140 // If only the first lane is used, then there won't be any code that remains
3141 // in the loop for the first unrolled part.
3143 return 0;
3144
3145 // Typically the operations are:
3146 // 1. Add the start index to each lane value.
3147 // 2. Multiply the start index by the step.
3148 // 3. Add the scaled start index to base IV.
3149 // Any code generated for 1 and 2 should be loop invariant and therefore
3150 // hoisted out of the loop. We only need to add on the cost of 3.
3151
3152 // Given the users of VPScalarIVStepsRecipe tend to be scalarized GEPs, i.e.
3153 // %add1 = add i32 %iv, 0
3154 // %add2 = add i32 %iv, 1
3155 // %gep1 = getelementptr i8, ptr %p, i32 %add1
3156 // %gep2 = getelementptr i8, ptr %p, i32 %add2
3157 // it's very likely that these GEPs will all be rewritten to have a common
3158 // base such that what's left is just
3159 // %base_gep = getelementptr i8, ptr %p, i32 %iv
3160 // %gep1 = getelementptr i8, ptr %base_gep, i32 0
3161 // %gep2 = getelementptr i8, ptr %base_gep, i32 1
3162 // Therefore, in reality the cost is somewhere betwen 1*AddCost and
3163 // (NumLanes - 1) * AddCost. For now, assume the cost of a single add.
3164 return Ctx.TTI.getArithmeticInstrCost(Instruction::Add, BaseIVTy,
3165 Ctx.CostKind);
3166}
3167
3169 // Fast-math-flags propagate from the original induction instruction.
3170 IRBuilder<>::FastMathFlagGuard FMFG(State.Builder);
3171 State.Builder.setFastMathFlags(getFastMathFlagsOrNone());
3172
3173 /// Compute scalar induction steps. \p ScalarIV is the scalar induction
3174 /// variable on which to base the steps, \p Step is the size of the step.
3175
3176 Value *BaseIV = State.get(getOperand(0), VPLane(0));
3177 Value *Step = State.get(getStepValue(), VPLane(0));
3178 IRBuilderBase &Builder = State.Builder;
3179
3180 // Ensure step has the same type as that of scalar IV.
3181 Type *BaseIVTy = BaseIV->getType()->getScalarType();
3182 assert(BaseIVTy == Step->getType() && "Types of BaseIV and Step must match!");
3183
3184 // We build scalar steps for both integer and floating-point induction
3185 // variables. Here, we determine the kind of arithmetic we will perform.
3188 if (BaseIVTy->isIntegerTy()) {
3189 AddOp = Instruction::Add;
3190 MulOp = Instruction::Mul;
3191 } else {
3192 AddOp = InductionOpcode;
3193 MulOp = Instruction::FMul;
3194 }
3195
3196 // Determine the number of scalars we need to generate.
3197 bool FirstLaneOnly = vputils::onlyFirstLaneUsed(this);
3198 // Compute the scalar steps and save the results in State.
3199
3200 unsigned EndLane = FirstLaneOnly ? 1 : State.VF.getKnownMinValue();
3201 Value *StartIdx0 = getStartIndex() ? State.get(getStartIndex(), true)
3202 : Constant::getNullValue(BaseIVTy);
3203
3204 for (unsigned Lane = 0; Lane < EndLane; ++Lane) {
3205 // It is okay if the induction variable type cannot hold the lane number,
3206 // we expect truncation in this case.
3207 Constant *LaneValue =
3208 BaseIVTy->isIntegerTy()
3209 ? ConstantInt::get(BaseIVTy, Lane, /*IsSigned=*/false,
3210 /*ImplicitTrunc=*/true)
3211 : ConstantFP::get(BaseIVTy, Lane);
3212 Value *StartIdx = Builder.CreateBinOp(AddOp, StartIdx0, LaneValue);
3213 assert((State.VF.isScalable() || isa<Constant>(StartIdx)) &&
3214 "Expected StartIdx to be folded to a constant when VF is not "
3215 "scalable");
3216 auto *Mul = Builder.CreateBinOp(MulOp, StartIdx, Step);
3217 auto *Add = Builder.CreateBinOp(AddOp, BaseIV, Mul);
3218 State.set(this, Add, VPLane(Lane));
3219 }
3220}
3221
3222#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3224 VPSlotTracker &SlotTracker) const {
3225 O << Indent;
3227 O << " = SCALAR-STEPS ";
3229}
3230#endif
3231
3233 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
3235}
3236
3238 assert(State.VF.isVector() && "not widening");
3239 auto Ops = map_to_vector(operands(), [&](VPValue *Op) {
3240 return State.get(Op, vputils::isSingleScalar(Op));
3241 });
3242 auto *GEP =
3243 State.Builder.CreateGEP(getSourceElementType(), Ops.front(),
3244 drop_begin(Ops), "wide.gep", getGEPNoWrapFlags());
3245 State.set(this, GEP, vputils::isSingleScalar(this));
3246}
3247
3248#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3250 VPSlotTracker &SlotTracker) const {
3251 O << Indent << "WIDEN-GEP ";
3253 O << " = getelementptr";
3254 printFlags(O);
3256}
3257#endif
3258
3260 assert(!getOffset() && "Unexpected offset operand");
3261 VPBuilder Builder(this);
3262 VPlan &Plan = *getParent()->getPlan();
3263 VPValue *VFVal = getVFValue();
3264 const DataLayout &DL = Plan.getDataLayout();
3265 Type *IndexTy = DL.getIndexType(this->getScalarType());
3266 VPValue *Stride =
3267 Plan.getConstantInt(IndexTy, getStride(), /*IsSigned=*/true);
3268 VPValue *VF =
3269 Builder.createScalarZExtOrTrunc(VFVal, IndexTy, DebugLoc::getUnknown());
3270
3271 // Offset for Part0 = Offset0 = Stride * (VF - 1).
3272 VPInstruction *VFMinusOne =
3273 Builder.createSub(VF, Plan.getConstantInt(IndexTy, 1u),
3274 DebugLoc::getUnknown(), "", {true, true});
3275 VPInstruction *Offset0 =
3276 Builder.createOverflowingOp(Instruction::Mul, {VFMinusOne, Stride});
3277
3278 // Offset for PartN = Offset0 + Part * Stride * VF.
3279 VPValue *PartxStride =
3280 Plan.getConstantInt(IndexTy, Part * getStride(), /*IsSigned=*/true);
3281 VPValue *Offset = Builder.createAdd(
3282 Offset0,
3283 Builder.createOverflowingOp(Instruction::Mul, {PartxStride, VF}));
3285}
3286
3288 auto &Builder = State.Builder;
3289 assert(getOffset() && "Expected prior materialization of offset");
3290 Value *Ptr = State.get(getPointer(), true);
3291 Value *Offset = State.get(getOffset(), true);
3292 Value *ResultPtr = Builder.CreateGEP(getSourceElementType(), Ptr, Offset, "",
3294 State.set(this, ResultPtr, /*IsScalar*/ true);
3295}
3296
3297#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3299 VPSlotTracker &SlotTracker) const {
3300 O << Indent;
3302 O << " = vector-end-pointer";
3303 printFlags(O);
3304 getSourceElementType()->print(O);
3305 O << ", ";
3307}
3308#endif
3309
3311 assert(getVFxPart() &&
3312 "Expected prior simplification of recipe without VFxPart");
3313
3314 auto &Builder = State.Builder;
3315 Value *Ptr = State.get(getOperand(0), VPLane(0));
3316 Value *Offset = State.get(getVFxPart(), true);
3317 // TODO: Expand to VPInstruction to support constant folding.
3318 if (!match(getStride(), m_One())) {
3319 Value *Stride = Builder.CreateZExtOrTrunc(State.get(getStride(), true),
3320 Offset->getType());
3321 Offset = Builder.CreateMul(Offset, Stride);
3322 }
3323 Value *ResultPtr = Builder.CreateGEP(getSourceElementType(), Ptr, Offset, "",
3325 State.set(this, ResultPtr, /*IsScalar*/ true);
3326}
3327
3328#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3330 VPSlotTracker &SlotTracker) const {
3331 O << Indent;
3333 O << " = vector-pointer";
3334 printFlags(O);
3335 getSourceElementType()->print(O);
3336 O << ", ";
3338}
3339#endif
3340
3342 VPCostContext &Ctx) const {
3343 // A blend will be expanded to a select VPInstruction, which will generate a
3344 // scalar select if only the first lane is used.
3346 VF = ElementCount::getFixed(1);
3347
3348 Type *ResultTy = toVectorTy(this->getScalarType(), VF);
3349 Type *CmpTy = toVectorTy(Type::getInt1Ty(Ctx.LLVMCtx), VF);
3350 return (getNumIncomingValues() - 1) *
3351 Ctx.TTI.getCmpSelInstrCost(Instruction::Select, ResultTy, CmpTy,
3352 CmpInst::BAD_ICMP_PREDICATE, Ctx.CostKind);
3353}
3354
3355#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3357 VPSlotTracker &SlotTracker) const {
3358 O << Indent << "BLEND ";
3360 O << " =";
3361 printFlags(O);
3362 if (getNumIncomingValues() == 1) {
3363 // Not a User of any mask: not really blending, this is a
3364 // single-predecessor phi.
3365 getIncomingValue(0)->printAsOperand(O, SlotTracker);
3366 } else {
3367 for (unsigned I = 0, E = getNumIncomingValues(); I < E; ++I) {
3368 if (I != 0)
3369 O << " ";
3370 getIncomingValue(I)->printAsOperand(O, SlotTracker);
3371 if (I == 0 && isNormalized())
3372 continue;
3373 O << "/";
3374 getMask(I)->printAsOperand(O, SlotTracker);
3375 }
3376 }
3377}
3378#endif
3379
3383 "In-loop AnyOf reductions aren't currently supported");
3384 // Propagate the fast-math flags carried by the underlying instruction.
3385 IRBuilderBase::FastMathFlagGuard FMFGuard(State.Builder);
3386 State.Builder.setFastMathFlags(getFastMathFlagsOrNone());
3387 Value *NewVecOp = State.get(getVecOp());
3388 if (VPValue *Cond = getCondOp()) {
3389 Value *NewCond = State.get(Cond, State.VF.isScalar());
3390 VectorType *VecTy = dyn_cast<VectorType>(NewVecOp->getType());
3391 Type *ElementTy = VecTy ? VecTy->getElementType() : NewVecOp->getType();
3392
3393 Value *Start =
3395 if (State.VF.isVector())
3396 Start = State.Builder.CreateVectorSplat(VecTy->getElementCount(), Start);
3397
3398 Value *Select = State.Builder.CreateSelect(NewCond, NewVecOp, Start);
3399 NewVecOp = Select;
3400 }
3401 Value *NewRed;
3402 Value *NextInChain;
3403 if (isOrdered()) {
3404 Value *PrevInChain = State.get(getChainOp(), /*IsScalar*/ true);
3405 if (State.VF.isVector())
3406 NewRed =
3407 createOrderedReduction(State.Builder, Kind, NewVecOp, PrevInChain);
3408 else
3409 NewRed = State.Builder.CreateBinOp(
3411 PrevInChain, NewVecOp);
3412 PrevInChain = NewRed;
3413 NextInChain = NewRed;
3414 } else if (isPartialReduction()) {
3415 assert((Kind == RecurKind::Add || Kind == RecurKind::FAdd) &&
3416 "Unexpected partial reduction kind");
3417 Value *PrevInChain = State.get(getChainOp(), /*IsScalar*/ false);
3418 NewRed = State.Builder.CreateIntrinsic(
3419 PrevInChain->getType(),
3420 Kind == RecurKind::Add ? Intrinsic::vector_partial_reduce_add
3421 : Intrinsic::vector_partial_reduce_fadd,
3422 {PrevInChain, NewVecOp}, State.Builder.getFastMathFlags(),
3423 "partial.reduce");
3424 PrevInChain = NewRed;
3425 NextInChain = NewRed;
3426 } else {
3427 assert(isInLoop() &&
3428 "The reduction must either be ordered, partial or in-loop");
3429 Value *PrevInChain = State.get(getChainOp(), /*IsScalar*/ true);
3430 NewRed = createSimpleReduction(State.Builder, NewVecOp, Kind);
3432 NextInChain = createMinMaxOp(State.Builder, Kind, NewRed, PrevInChain);
3433 else
3434 NextInChain = State.Builder.CreateBinOp(
3436 PrevInChain, NewRed);
3437 }
3438 State.set(this, NextInChain, /*IsScalar*/ !isPartialReduction());
3439}
3440
3442
3443 auto &Builder = State.Builder;
3444 // Propagate the fast-math flags carried by the underlying instruction.
3445 IRBuilderBase::FastMathFlagGuard FMFGuard(Builder);
3446 Builder.setFastMathFlags(getFastMathFlagsOrNone());
3447
3449 Value *Prev = State.get(getChainOp(), /*IsScalar*/ true);
3450 Value *VecOp = State.get(getVecOp());
3451 Value *EVL = State.get(getEVL(), VPLane(0));
3452
3453 Value *Mask;
3454 if (VPValue *CondOp = getCondOp())
3455 Mask = State.get(CondOp);
3456 else
3457 Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue());
3458
3459 Value *NewRed;
3460 if (isOrdered()) {
3461 NewRed = createOrderedReduction(Builder, Kind, VecOp, Prev, Mask, EVL);
3462 } else {
3463 NewRed = createSimpleReduction(Builder, VecOp, Kind, Mask, EVL);
3465 NewRed = createMinMaxOp(Builder, Kind, NewRed, Prev);
3466 else
3467 NewRed = Builder.CreateBinOp(
3469 Prev);
3470 }
3471 State.set(this, NewRed, /*IsScalar*/ true);
3472}
3473
3475 VPCostContext &Ctx) const {
3476 RecurKind RdxKind = getRecurrenceKind();
3477 Type *ElementTy = this->getScalarType();
3478 auto *VectorTy = cast<VectorType>(toVectorTy(ElementTy, VF));
3479 unsigned Opcode = RecurrenceDescriptor::getOpcode(RdxKind);
3481 std::optional<FastMathFlags> OptionalFMF =
3482 ElementTy->isFloatingPointTy() ? std::make_optional(FMFs) : std::nullopt;
3483
3484 if (isPartialReduction()) {
3485 InstructionCost CondCost = 0;
3486 if (isConditional()) {
3488 auto *CondTy =
3490 CondCost = Ctx.TTI.getCmpSelInstrCost(Instruction::Select, VectorTy,
3491 CondTy, Pred, Ctx.CostKind);
3492 }
3493 return CondCost + Ctx.TTI.getPartialReductionCost(
3494 Opcode, ElementTy, ElementTy, ElementTy, VF,
3495 TTI::PR_None, TTI::PR_None, {}, Ctx.CostKind,
3496 OptionalFMF);
3497 }
3498
3499 // TODO: Support any-of reductions.
3500 assert(
3502 ForceTargetInstructionCost.getNumOccurrences() > 0) &&
3503 "Any-of reduction not implemented in VPlan-based cost model currently.");
3504
3505 // Note that TTI should model the cost of moving result to the scalar register
3506 // and the BinOp cost in the getMinMaxReductionCost().
3509 return Ctx.TTI.getMinMaxReductionCost(Id, VectorTy, FMFs, Ctx.CostKind);
3510 }
3511
3512 // Note that TTI should model the cost of moving result to the scalar register
3513 // and the BinOp cost in the getArithmeticReductionCost().
3514 return Ctx.TTI.getArithmeticReductionCost(Opcode, VectorTy, OptionalFMF,
3515 Ctx.CostKind);
3516}
3517
3518VPExpressionRecipe::VPExpressionRecipe(
3519 ExpressionTypes ExpressionType,
3520 ArrayRef<VPSingleDefRecipe *> ExpressionRecipes)
3521 : VPSingleDefRecipe(VPRecipeBase::VPExpressionSC, {},
3522 cast<VPReductionRecipe>(ExpressionRecipes.back())
3523 ->getChainOp()
3524 ->getScalarType()),
3525 ExpressionRecipes(ExpressionRecipes), ExpressionType(ExpressionType) {
3526 assert(!ExpressionRecipes.empty() && "Nothing to combine?");
3527 assert(
3528 none_of(ExpressionRecipes,
3529 [](VPSingleDefRecipe *R) { return R->mayHaveSideEffects(); }) &&
3530 "expression cannot contain recipes with side-effects");
3531
3532 // Maintain a copy of the expression recipes as a set of users.
3533 SmallPtrSet<VPUser *, 4> ExpressionRecipesAsSetOfUsers;
3534 for (auto *R : ExpressionRecipes)
3535 ExpressionRecipesAsSetOfUsers.insert(R);
3536
3537 // Recipes in the expression, except the last one, must only be used by
3538 // (other) recipes inside the expression. If there are other users, external
3539 // to the expression, use a clone of the recipe for external users.
3540 for (VPSingleDefRecipe *R : reverse(ExpressionRecipes)) {
3541 if (R != ExpressionRecipes.back() &&
3542 any_of(R->users(), [&ExpressionRecipesAsSetOfUsers](VPUser *U) {
3543 return !ExpressionRecipesAsSetOfUsers.contains(U);
3544 })) {
3545 // There are users outside of the expression. Clone the recipe and use the
3546 // clone those external users.
3547 VPSingleDefRecipe *CopyForExtUsers = R->clone();
3548 R->replaceUsesWithIf(CopyForExtUsers, [&ExpressionRecipesAsSetOfUsers](
3549 VPUser &U, unsigned) {
3550 return !ExpressionRecipesAsSetOfUsers.contains(&U);
3551 });
3552 CopyForExtUsers->insertBefore(R);
3553 }
3554 if (R->getParent())
3555 R->removeFromParent();
3556 }
3557
3558 // Internalize all external operands to the expression recipes. To do so,
3559 // create new temporary VPValues for all operands defined by a recipe outside
3560 // the expression. The original operands are added as operands of the
3561 // VPExpressionRecipe itself.
3562 for (auto *R : ExpressionRecipes) {
3563 for (const auto &[Idx, Op] : enumerate(R->operands())) {
3564 auto *Def = Op->getDefiningRecipe();
3565 if (Def && ExpressionRecipesAsSetOfUsers.contains(Def))
3566 continue;
3567 addOperand(Op);
3568 LiveInPlaceholders.push_back(new VPSymbolicValue(Op->getScalarType()));
3569 }
3570 }
3571
3572 // Replace each external operand with the first one created for it in
3573 // LiveInPlaceholders.
3574 for (auto *R : ExpressionRecipes)
3575 for (auto const &[LiveIn, Tmp] : zip(operands(), LiveInPlaceholders))
3576 R->replaceUsesOfWith(LiveIn, Tmp);
3577}
3578
3580 for (auto *R : ExpressionRecipes)
3581 // Since the list could contain duplicates, make sure the recipe hasn't
3582 // already been inserted.
3583 if (!R->getParent())
3584 R->insertBefore(this);
3585
3586 for (const auto &[Idx, Op] : enumerate(operands()))
3587 LiveInPlaceholders[Idx]->replaceAllUsesWith(Op);
3588
3589 replaceAllUsesWith(ExpressionRecipes.back());
3590 ExpressionRecipes.clear();
3591}
3592
3594 VPCostContext &Ctx) const {
3595 Type *RedTy = this->getScalarType();
3596 auto *SrcVecTy =
3598 unsigned Opcode = RecurrenceDescriptor::getOpcode(
3599 cast<VPReductionRecipe>(ExpressionRecipes.back())->getRecurrenceKind());
3600 switch (ExpressionType) {
3601 case ExpressionTypes::NegatedExtendedReduction:
3602 assert((Opcode == Instruction::Add || Opcode == Instruction::FAdd) &&
3603 "Unexpected opcode");
3604 Opcode = Opcode == Instruction::Add ? Instruction::Sub : Instruction::FSub;
3605 [[fallthrough]];
3606 case ExpressionTypes::ExtendedReduction: {
3607 auto *RedR = cast<VPReductionRecipe>(ExpressionRecipes.back());
3608 auto *ExtR = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3609
3610 if (RedR->isPartialReduction())
3611 return Ctx.TTI.getPartialReductionCost(
3612 Opcode, getOperand(0)->getScalarType(), nullptr, RedTy, VF,
3614 TargetTransformInfo::PR_None, std::nullopt, Ctx.CostKind,
3615 RedTy->isFloatingPointTy()
3616 ? std::optional{RedR->getFastMathFlagsOrNone()}
3617 : std::nullopt);
3618 else if (!RedTy->isFloatingPointTy())
3619 // TTI::getExtendedReductionCost only supports integer types.
3620 return Ctx.TTI.getExtendedReductionCost(
3621 Opcode, ExtR->getOpcode() == Instruction::ZExt, RedTy, SrcVecTy,
3622 std::nullopt, Ctx.CostKind);
3623 else
3625 }
3626 case ExpressionTypes::MulAccReduction:
3627 return Ctx.TTI.getMulAccReductionCost(false, Opcode, RedTy, SrcVecTy,
3628 Ctx.CostKind);
3629
3630 case ExpressionTypes::ExtNegatedMulAccReduction:
3631 switch (Opcode) {
3632 case Instruction::Add:
3633 Opcode = Instruction::Sub;
3634 break;
3635 case Instruction::FAdd:
3636 Opcode = Instruction::FSub;
3637 break;
3638 default:
3639 llvm_unreachable("Unsupported opcode for ExtNegatedMulAccReduction");
3640 }
3641 [[fallthrough]];
3642 case ExpressionTypes::ExtMulAccReduction: {
3643 auto *RedR = cast<VPReductionRecipe>(ExpressionRecipes.back());
3644 if (RedR->isPartialReduction()) {
3645 auto *Ext0R = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3646 auto *Ext1R = cast<VPWidenCastRecipe>(ExpressionRecipes[1]);
3647 auto *Mul = cast<VPWidenRecipe>(ExpressionRecipes[2]);
3648 return Ctx.TTI.getPartialReductionCost(
3649 Opcode, getOperand(0)->getScalarType(),
3650 getOperand(1)->getScalarType(), RedTy, VF,
3652 Ext0R->getOpcode()),
3654 Ext1R->getOpcode()),
3655 Mul->getOpcode(), Ctx.CostKind,
3656 RedTy->isFloatingPointTy()
3657 ? std::optional{RedR->getFastMathFlagsOrNone()}
3658 : std::nullopt);
3659 }
3660 assert(Opcode != Instruction::FSub && "Only integer types are supported");
3661 return Ctx.TTI.getMulAccReductionCost(
3662 cast<VPWidenCastRecipe>(ExpressionRecipes.front())->getOpcode() ==
3663 Instruction::ZExt,
3664 Opcode, RedTy, SrcVecTy, Ctx.CostKind);
3665 }
3666 }
3667 llvm_unreachable("Unknown VPExpressionRecipe::ExpressionTypes enum");
3668}
3669
3671 return any_of(ExpressionRecipes, [](VPSingleDefRecipe *R) {
3672 return R->mayReadFromMemory() || R->mayWriteToMemory();
3673 });
3674}
3675
3677 assert(
3678 none_of(ExpressionRecipes,
3679 [](VPSingleDefRecipe *R) { return R->mayHaveSideEffects(); }) &&
3680 "expression cannot contain recipes with side-effects");
3681 return false;
3682}
3683
3685 auto *RR = dyn_cast<VPReductionRecipe>(ExpressionRecipes.back());
3686 return RR && !RR->isPartialReduction();
3687}
3688
3689#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3690
3692 VPSlotTracker &SlotTracker) const {
3693 O << Indent << "EXPRESSION ";
3695 O << " = ";
3696 auto *Red = cast<VPReductionRecipe>(ExpressionRecipes.back());
3697 unsigned Opcode = RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind());
3698 VPValue *RdxStart =
3699 getOperand(getNumOperands() - (Red->isConditional() ? 2 : 1));
3700
3701 switch (ExpressionType) {
3702 case ExpressionTypes::NegatedExtendedReduction:
3703 case ExpressionTypes::ExtendedReduction: {
3704 bool Negated = ExpressionType == ExpressionTypes::NegatedExtendedReduction;
3706 O << " + " << (Red->isPartialReduction() ? "partial." : "") << "reduce.";
3707 O << Instruction::getOpcodeName(Opcode) << " (";
3708 if (Negated)
3709 O << (Opcode == Instruction::Add ? "sub (0, " : "fneg(");
3711 if (Negated)
3712 O << ")";
3713 Red->printFlags(O);
3714
3715 auto *Ext0 = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3716 O << Instruction::getOpcodeName(Ext0->getOpcode()) << " to "
3717 << *Ext0->getScalarType();
3718 if (Red->isConditional()) {
3719 O << ", ";
3721 }
3722 O << ")";
3723 break;
3724 }
3725 case ExpressionTypes::ExtNegatedMulAccReduction: {
3726 RdxStart->printAsOperand(O, SlotTracker);
3727 O << " + " << (Red->isPartialReduction() ? "partial." : "") << "reduce.";
3729 RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind()))
3730 << " (sub (0, mul";
3731 auto *Mul = cast<VPWidenRecipe>(ExpressionRecipes[2]);
3732 Mul->printFlags(O);
3733 O << "(";
3735 auto *Ext0 = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3736 O << " " << Instruction::getOpcodeName(Ext0->getOpcode()) << " to "
3737 << *Ext0->getScalarType() << "), (";
3739 auto *Ext1 = cast<VPWidenCastRecipe>(ExpressionRecipes[1]);
3740 O << " " << Instruction::getOpcodeName(Ext1->getOpcode()) << " to "
3741 << *Ext1->getScalarType() << ")";
3742 if (Red->isConditional()) {
3743 O << ", ";
3745 }
3746 O << "))";
3747 break;
3748 }
3749 case ExpressionTypes::MulAccReduction:
3750 case ExpressionTypes::ExtMulAccReduction: {
3751 RdxStart->printAsOperand(O, SlotTracker);
3752 O << " + " << (Red->isPartialReduction() ? "partial." : "") << "reduce.";
3754 RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind()))
3755 << " (";
3756 O << "mul";
3757 bool IsExtended = ExpressionType == ExpressionTypes::ExtMulAccReduction;
3758 auto *Mul = cast<VPWidenRecipe>(IsExtended ? ExpressionRecipes[2]
3759 : ExpressionRecipes[0]);
3760 Mul->printFlags(O);
3761 if (IsExtended)
3762 O << "(";
3764 if (IsExtended) {
3765 auto *Ext0 = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3766 O << " " << Instruction::getOpcodeName(Ext0->getOpcode()) << " to "
3767 << *Ext0->getScalarType() << "), (";
3768 } else {
3769 O << ", ";
3770 }
3772 if (IsExtended) {
3773 auto *Ext1 = cast<VPWidenCastRecipe>(ExpressionRecipes[1]);
3774 O << " " << Instruction::getOpcodeName(Ext1->getOpcode()) << " to "
3775 << *Ext1->getScalarType() << ")";
3776 }
3777 if (Red->isConditional()) {
3778 O << ", ";
3780 }
3781 O << ")";
3782 break;
3783 }
3784 }
3785}
3786
3788 VPSlotTracker &SlotTracker) const {
3789 if (isPartialReduction())
3790 O << Indent << "PARTIAL-REDUCE ";
3791 else
3792 O << Indent << "REDUCE ";
3794 O << " = ";
3796 O << " +";
3797 printFlags(O);
3798 O << " reduce.";
3800 O << " (";
3802 if (isConditional()) {
3803 O << ", ";
3805 }
3806 O << ")";
3807}
3808
3810 VPSlotTracker &SlotTracker) const {
3811 O << Indent << "REDUCE ";
3813 O << " = ";
3815 O << " +";
3816 printFlags(O);
3817 O << " vp.reduce."
3820 << " (";
3822 O << ", ";
3824 if (isConditional()) {
3825 O << ", ";
3827 }
3828 O << ")";
3829}
3830
3831#endif
3832
3834 assert(IsSingleScalar &&
3835 "VPReplicateRecipes must be unrolled before ::execute");
3836 auto *Instr = getUnderlyingInstr();
3837 Instruction *Cloned = Instr->clone();
3838 Type *ResultTy = getScalarType();
3839 if (!ResultTy->isVoidTy()) {
3840 Cloned->setName(Instr->getName() + ".cloned");
3841 // The operands of the replicate recipe may have been narrowed, resulting in
3842 // a narrower result type. Update the type of the cloned instruction to the
3843 // correct type.
3844 if (ResultTy != Cloned->getType())
3845 Cloned->mutateType(ResultTy);
3846 }
3847
3848 applyFlags(*Cloned);
3849 applyMetadata(*Cloned);
3850
3851 if (hasPredicate())
3852 cast<CmpInst>(Cloned)->setPredicate(getPredicate());
3853
3854 // Replace the operands of the cloned instructions with their scalar
3855 // equivalents in the new loop.
3856 for (const auto &[Idx, V] : enumerate(operands()))
3857 Cloned->setOperand(Idx, State.get(V, true));
3858
3859 // Place the cloned scalar in the new loop.
3860 State.Builder.Insert(Cloned);
3861
3862 State.set(this, Cloned, true);
3863
3864 // If we just cloned a new assumption, add it the assumption cache.
3865 if (auto *II = dyn_cast<AssumeInst>(Cloned))
3866 State.AC->registerAssumption(II);
3867}
3868
3869/// Returns a SCEV expression for \p Ptr if it is a pointer computation for
3870/// which the legacy cost model computes a SCEV expression when computing the
3871/// address cost. Computing SCEVs for VPValues is incomplete and returns
3872/// SCEVCouldNotCompute in cases the legacy cost model can compute SCEVs. In
3873/// those cases we fall back to the legacy cost model. Otherwise return nullptr.
3874static const SCEV *getAddressAccessSCEV(const VPValue *Ptr,
3876 const Loop *L) {
3877 const SCEV *Addr = vputils::getSCEVExprForVPValue(Ptr, PSE, L);
3878 if (isa<SCEVCouldNotCompute>(Addr))
3879 return Addr;
3880
3881 return vputils::isAddressSCEVForCost(Addr, *PSE.getSE(), L) ? Addr : nullptr;
3882}
3883
3885 VPCostContext &Ctx) const {
3887 // VPReplicateRecipe may be cloned as part of an existing VPlan-to-VPlan
3888 // transform, avoid computing their cost multiple times for now.
3889 Ctx.SkipCostComputation.insert(UI);
3890
3891 if (VF.isScalable() && !isSingleScalar())
3893
3894 switch (UI->getOpcode()) {
3895 case Instruction::Alloca:
3896 if (VF.isScalable())
3898 return Ctx.TTI.getArithmeticInstrCost(Instruction::Mul,
3899 this->getScalarType(), Ctx.CostKind);
3900 case Instruction::GetElementPtr:
3901 // We mark this instruction as zero-cost because the cost of GEPs in
3902 // vectorized code depends on whether the corresponding memory instruction
3903 // is scalarized or not. Therefore, we handle GEPs with the memory
3904 // instruction cost.
3905 return 0;
3906 case Instruction::Call: {
3907 auto *CalledFn =
3909 Type *ResultTy = this->getScalarType();
3910 return computeCallCost(CalledFn, ResultTy, drop_end(operands()),
3911 isSingleScalar(), VF, Ctx);
3912 }
3913 case Instruction::Add:
3914 case Instruction::Sub:
3915 case Instruction::FAdd:
3916 case Instruction::FSub:
3917 case Instruction::Mul:
3918 case Instruction::FMul:
3919 case Instruction::FDiv:
3920 case Instruction::FRem:
3921 case Instruction::Shl:
3922 case Instruction::LShr:
3923 case Instruction::AShr:
3924 case Instruction::And:
3925 case Instruction::Or:
3926 case Instruction::Xor:
3927 case Instruction::ICmp:
3928 case Instruction::FCmp:
3930 Ctx) *
3931 (isSingleScalar() ? 1 : VF.getFixedValue());
3932 case Instruction::SDiv:
3933 case Instruction::UDiv:
3934 case Instruction::SRem:
3935 case Instruction::URem: {
3936 InstructionCost ScalarCost =
3938 if (isSingleScalar())
3939 return ScalarCost;
3940
3941 // If any of the operands is from a different replicate region and has its
3942 // cost skipped, it may have been forced to scalar. Fall back to legacy cost
3943 // model to avoid cost mis-match.
3944 if (any_of(operands(), [&Ctx, VF](VPValue *Op) {
3945 auto *PredR = dyn_cast<VPPredInstPHIRecipe>(Op);
3946 if (!PredR)
3947 return false;
3948 return Ctx.skipCostComputation(
3950 PredR->getOperand(0)->getUnderlyingValue()),
3951 VF.isVector());
3952 }))
3953 break;
3954
3955 ScalarCost = ScalarCost * VF.getFixedValue() +
3956 Ctx.getScalarizationOverhead(this->getScalarType(),
3957 to_vector(operands()), VF);
3958 // If the recipe is not predicated (i.e. not in a replicate region), return
3959 // the scalar cost. Otherwise handle predicated cost.
3960 if (!getRegion()->isReplicator())
3961 return ScalarCost;
3962
3963 // Account for the phi nodes that we will create.
3964 ScalarCost += VF.getFixedValue() *
3965 Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
3966 // Scale the cost by the probability of executing the predicated blocks.
3967 // This assumes the predicated block for each vector lane is equally
3968 // likely.
3969 ScalarCost /= Ctx.getPredBlockCostDivisor(UI->getParent());
3970 return ScalarCost;
3971 }
3972 case Instruction::Load:
3973 case Instruction::Store: {
3974 bool IsLoad = UI->getOpcode() == Instruction::Load;
3975 const VPValue *PtrOp = getOperand(!IsLoad);
3976 const SCEV *PtrSCEV = getAddressAccessSCEV(PtrOp, Ctx.PSE, Ctx.L);
3978 break;
3979
3980 Type *ValTy = (IsLoad ? this : getOperand(0))->getScalarType();
3981 Type *ScalarPtrTy = PtrOp->getScalarType();
3982 const Align Alignment = getLoadStoreAlignment(UI);
3983 unsigned AS = cast<PointerType>(ScalarPtrTy)->getAddressSpace();
3985 bool PreferVectorizedAddressing = Ctx.TTI.prefersVectorizedAddressing();
3986 bool UsedByLoadStoreAddress =
3987 !PreferVectorizedAddressing && vputils::isUsedByLoadStoreAddress(this);
3988 InstructionCost ScalarMemOpCost = Ctx.TTI.getMemoryOpCost(
3989 UI->getOpcode(), ValTy, Alignment, AS, Ctx.CostKind, OpInfo,
3990 UsedByLoadStoreAddress ? UI : nullptr);
3991
3992 Type *PtrTy = isSingleScalar() ? ScalarPtrTy : toVectorTy(ScalarPtrTy, VF);
3993 InstructionCost ScalarCost =
3994 ScalarMemOpCost +
3995 Ctx.TTI.getAddressComputationCost(
3996 PtrTy, UsedByLoadStoreAddress ? nullptr : Ctx.PSE.getSE(), PtrSCEV,
3997 Ctx.CostKind);
3998 if (isSingleScalar())
3999 return ScalarCost;
4000
4001 SmallVector<const VPValue *> OpsToScalarize;
4002 Type *ResultTy = Type::getVoidTy(PtrTy->getContext());
4003 // Set ResultTy and OpsToScalarize, if scalarization is needed. Currently we
4004 // don't assign scalarization overhead in general, if the target prefers
4005 // vectorized addressing or the loaded value is used as part of an address
4006 // of another load or store.
4007 if (!UsedByLoadStoreAddress) {
4008 bool EfficientVectorLoadStore =
4009 Ctx.TTI.supportsEfficientVectorElementLoadStore();
4010 if (!(IsLoad && !PreferVectorizedAddressing) &&
4011 !(!IsLoad && EfficientVectorLoadStore))
4012 append_range(OpsToScalarize, operands());
4013
4014 if (!EfficientVectorLoadStore)
4015 ResultTy = this->getScalarType();
4016 }
4017
4019 IsLoad ? TTI::VectorInstrContext::Load : TTI::VectorInstrContext::Store;
4021 (ScalarCost * VF.getFixedValue()) +
4022 Ctx.getScalarizationOverhead(ResultTy, OpsToScalarize, VF, VIC, true);
4023
4024 const VPRegionBlock *ParentRegion = getRegion();
4025 if (ParentRegion && ParentRegion->isReplicator()) {
4026 if (!PtrSCEV)
4027 break;
4028 Cost /= Ctx.getPredBlockCostDivisor(UI->getParent());
4029 Cost += Ctx.TTI.getCFInstrCost(Instruction::CondBr, Ctx.CostKind);
4030
4031 auto *VecI1Ty = VectorType::get(
4032 IntegerType::getInt1Ty(Ctx.L->getHeader()->getContext()), VF);
4033 Cost += Ctx.TTI.getScalarizationOverhead(
4034 VecI1Ty, APInt::getAllOnes(VF.getFixedValue()),
4035 /*Insert=*/false, /*Extract=*/true, Ctx.CostKind);
4036
4037 if (Ctx.useEmulatedMaskMemRefHack(this, VF)) {
4038 // Artificially setting to a high enough value to practically disable
4039 // vectorization with such operations.
4040 return 3000000;
4041 }
4042 }
4043 return Cost;
4044 }
4045 case Instruction::SExt:
4046 case Instruction::ZExt:
4047 case Instruction::FPToUI:
4048 case Instruction::FPToSI:
4049 case Instruction::FPExt:
4050 case Instruction::PtrToInt:
4051 case Instruction::PtrToAddr:
4052 case Instruction::IntToPtr:
4053 case Instruction::SIToFP:
4054 case Instruction::UIToFP:
4055 case Instruction::Trunc:
4056 case Instruction::FPTrunc:
4057 case Instruction::Select:
4058 case Instruction::AddrSpaceCast: {
4060 Ctx) *
4061 (isSingleScalar() ? 1 : VF.getFixedValue());
4062 }
4063 case Instruction::ExtractValue:
4064 case Instruction::InsertValue:
4065 return Ctx.TTI.getInsertExtractValueCost(getOpcode(), Ctx.CostKind);
4066 }
4067
4068 return Ctx.getLegacyCost(UI, VF);
4069}
4070
4072 Function *CalledFn, Type *ResultTy, ArrayRef<const VPValue *> ArgOps,
4073 bool IsSingleScalar, ElementCount VF, VPCostContext &Ctx) {
4075 ArgOps, [&](const VPValue *Op) { return Op->getScalarType(); });
4076
4077 Intrinsic::ID IntrinID = CalledFn->getIntrinsicID();
4078 auto GetIntrinsicCost = [&] {
4079 if (!IntrinID)
4081 return Ctx.TTI.getIntrinsicInstrCost(
4082 IntrinsicCostAttributes(IntrinID, ResultTy, Tys), Ctx.CostKind);
4083 };
4084
4085 if (IntrinID && VPCostContext::isFreeScalarIntrinsic(IntrinID)) {
4086 assert(GetIntrinsicCost() == 0 && "scalarizing intrinsic should be free");
4087 return 0;
4088 }
4089
4090 InstructionCost ScalarCallCost =
4091 Ctx.TTI.getCallInstrCost(CalledFn, ResultTy, Tys, Ctx.CostKind);
4092 if (IsSingleScalar) {
4093 ScalarCallCost = std::min(ScalarCallCost, GetIntrinsicCost());
4094 return ScalarCallCost;
4095 }
4096
4097 // Scalarization overhead is undefined for scalable VFs.
4098 if (VF.isScalable())
4100
4101 return ScalarCallCost * VF.getFixedValue() +
4102 Ctx.getScalarizationOverhead(ResultTy, ArgOps, VF);
4103}
4104
4105#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4107 VPSlotTracker &SlotTracker) const {
4108 O << Indent << (IsSingleScalar ? "CLONE " : "REPLICATE ");
4109
4110 if (!getScalarType()->isVoidTy()) {
4112 O << " = ";
4113 }
4114 if (auto *CB = dyn_cast<CallBase>(getUnderlyingInstr())) {
4115 O << "call";
4116 printFlags(O);
4117 O << "@" << CB->getCalledFunction()->getName() << "(";
4119 Op->printAsOperand(O, SlotTracker);
4120 });
4121 O << ")";
4122 } else {
4124 printFlags(O);
4126 }
4127
4128 // Find if the recipe is used by a widened recipe via an intervening
4129 // VPPredInstPHIRecipe. In this case, also pack the scalar values in a vector.
4130 if (any_of(users(), [](const VPUser *U) {
4131 if (auto *PredR = dyn_cast<VPPredInstPHIRecipe>(U))
4132 return !vputils::onlyScalarValuesUsed(PredR);
4133 return false;
4134 }))
4135 O << " (S->V)";
4136}
4137#endif
4138
4140 llvm_unreachable("recipe must be removed when dissolving replicate region");
4141}
4142
4144 VPCostContext &Ctx) const {
4145 // The legacy cost model doesn't assign costs to branches for individual
4146 // replicate regions. Match the current behavior in the VPlan cost model for
4147 // now.
4148 return 0;
4149}
4150
4152 llvm_unreachable("recipe must be removed when dissolving replicate region");
4153}
4154
4155#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4157 VPSlotTracker &SlotTracker) const {
4158 O << Indent << "PHI-PREDICATED-INSTRUCTION ";
4160 O << " = ";
4162}
4163#endif
4164
4166const VPRecipeBase *VPWidenLoadRecipe::getAsRecipe() const { return this; }
4167
4170
4172const VPRecipeBase *VPWidenStoreRecipe::getAsRecipe() const { return this; }
4173
4176
4178 VPCostContext &Ctx) const {
4179 const VPRecipeBase *R = getAsRecipe();
4181 Type *ScalarTy = IsLoad ? cast<VPSingleDefRecipe>(R)->getScalarType()
4182 : R->getOperand(1)->getScalarType();
4183 Type *Ty = toVectorTy(ScalarTy, VF);
4184 unsigned AS =
4185 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4186 unsigned Opcode = IsLoad ? Instruction::Load : Instruction::Store;
4187
4188 if (!Consecutive) {
4189 // TODO: Using the original IR may not be accurate.
4190 // Currently, ARM will use the underlying IR to calculate gather/scatter
4191 // instruction cost.
4192 Type *PtrTy = getAddr()->getScalarType();
4193 const Value *Ptr = getAddr()->getUnderlyingValue();
4194
4195 // If the address value is uniform across all lanes, then the address can be
4196 // calculated with scalar type and broadcast.
4198 PtrTy = toVectorTy(PtrTy, VF);
4199
4200 unsigned IID = isa<VPWidenLoadRecipe>(R) ? Intrinsic::masked_gather
4201 : isa<VPWidenStoreRecipe>(R) ? Intrinsic::masked_scatter
4202 : isa<VPWidenLoadEVLRecipe>(R) ? Intrinsic::vp_gather
4203 : Intrinsic::vp_scatter;
4204 return Ctx.TTI.getAddressComputationCost(PtrTy, nullptr, nullptr,
4205 Ctx.CostKind) +
4206 Ctx.TTI.getMemIntrinsicInstrCost(
4208 &Ingredient),
4209 Ctx.CostKind);
4210 }
4211
4213 if (IsMasked) {
4214 unsigned IID = isa<VPWidenLoadRecipe>(R) ? Intrinsic::masked_load
4215 : Intrinsic::masked_store;
4216 Cost += Ctx.TTI.getMemIntrinsicInstrCost(
4217 MemIntrinsicCostAttributes(IID, Ty, Alignment, AS), Ctx.CostKind);
4218 } else {
4219 TTI::OperandValueInfo OpInfo = Ctx.getOperandInfo(
4221 : R->getOperand(1));
4222 Cost += Ctx.TTI.getMemoryOpCost(Opcode, Ty, Alignment, AS, Ctx.CostKind,
4223 OpInfo, &Ingredient);
4224 }
4225 return Cost;
4226}
4227
4229 Type *ScalarDataTy = getScalarType();
4230 auto *DataTy = VectorType::get(ScalarDataTy, State.VF);
4231 bool CreateGather = !isConsecutive();
4232
4233 auto &Builder = State.Builder;
4234 Value *Mask = nullptr;
4235 if (auto *VPMask = getMask())
4236 Mask = State.get(VPMask);
4237
4238 Value *Addr = State.get(getAddr(), /*IsScalar*/ !CreateGather);
4239 Value *NewLI;
4240 if (CreateGather) {
4241 NewLI = Builder.CreateMaskedGather(DataTy, Addr, Alignment, Mask, nullptr,
4242 "wide.masked.gather");
4243 } else if (Mask) {
4244 NewLI =
4245 Builder.CreateMaskedLoad(DataTy, Addr, Alignment, Mask,
4246 PoisonValue::get(DataTy), "wide.masked.load");
4247 } else {
4248 NewLI = Builder.CreateAlignedLoad(DataTy, Addr, Alignment, "wide.load");
4249 }
4251 State.set(this, NewLI);
4252}
4253
4254#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4256 VPSlotTracker &SlotTracker) const {
4257 O << Indent << "WIDEN ";
4259 O << " = load ";
4261}
4262#endif
4263
4265 Type *ScalarDataTy = getScalarType();
4266 auto *DataTy = VectorType::get(ScalarDataTy, State.VF);
4267 bool CreateGather = !isConsecutive();
4268
4269 auto &Builder = State.Builder;
4270 CallInst *NewLI;
4271 Value *EVL = State.get(getEVL(), VPLane(0));
4272 Value *Addr = State.get(getAddr(), !CreateGather);
4273 Value *Mask = nullptr;
4274 if (VPValue *VPMask = getMask())
4275 Mask = State.get(VPMask);
4276 else
4277 Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue());
4278
4279 if (CreateGather) {
4280 NewLI = Builder.CreateIntrinsicWithoutFolding(DataTy, Intrinsic::vp_gather,
4281 {Addr, Mask, EVL}, nullptr,
4282 "wide.masked.gather");
4283 } else {
4284 NewLI = Builder.CreateIntrinsicWithoutFolding(
4285 DataTy, Intrinsic::vp_load, {Addr, Mask, EVL}, nullptr, "vp.op.load");
4286 }
4287 NewLI->addParamAttr(
4289 applyMetadata(*NewLI);
4290 State.set(this, NewLI);
4291}
4292
4294 VPCostContext &Ctx) const {
4295 if (!Consecutive || IsMasked)
4296 return VPWidenMemoryRecipe::computeCost(VF, Ctx);
4297
4298 // We need to use the getMemIntrinsicInstrCost() instead of getMemoryOpCost()
4299 // here because the EVL recipes using EVL to replace the tail mask. But in the
4300 // legacy model, it will always calculate the cost of mask.
4301 // TODO: Using getMemoryOpCost() instead of getMemIntrinsicInstrCost when we
4302 // don't need to compare to the legacy cost model.
4303 Type *Ty = toVectorTy(getScalarType(), VF);
4304 unsigned AS =
4305 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4306 return Ctx.TTI.getMemIntrinsicInstrCost(
4307 MemIntrinsicCostAttributes(Intrinsic::vp_load, Ty, Alignment, AS),
4308 Ctx.CostKind);
4309}
4310
4311#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4313 VPSlotTracker &SlotTracker) const {
4314 O << Indent << "WIDEN ";
4316 O << " = vp.load ";
4318}
4319#endif
4320
4322 VPValue *StoredVPValue = getStoredValue();
4323 bool CreateScatter = !isConsecutive();
4324
4325 auto &Builder = State.Builder;
4326
4327 Value *Mask = nullptr;
4328 if (auto *VPMask = getMask())
4329 Mask = State.get(VPMask);
4330
4331 Value *StoredVal = State.get(StoredVPValue);
4332 Value *Addr = State.get(getAddr(), /*IsScalar*/ !CreateScatter);
4333 Instruction *NewSI = nullptr;
4334 if (CreateScatter)
4335 NewSI = Builder.CreateMaskedScatter(StoredVal, Addr, Alignment, Mask);
4336 else if (Mask)
4337 NewSI = Builder.CreateMaskedStore(StoredVal, Addr, Alignment, Mask);
4338 else
4339 NewSI = Builder.CreateAlignedStore(StoredVal, Addr, Alignment);
4340 applyMetadata(*NewSI);
4341}
4342
4343#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4345 VPSlotTracker &SlotTracker) const {
4346 O << Indent << "WIDEN store ";
4348}
4349#endif
4350
4352 VPValue *StoredValue = getStoredValue();
4353 bool CreateScatter = !isConsecutive();
4354
4355 auto &Builder = State.Builder;
4356
4357 CallInst *NewSI = nullptr;
4358 Value *StoredVal = State.get(StoredValue);
4359 Value *EVL = State.get(getEVL(), VPLane(0));
4360 Value *Mask = nullptr;
4361 if (VPValue *VPMask = getMask())
4362 Mask = State.get(VPMask);
4363 else
4364 Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue());
4365
4366 Value *Addr = State.get(getAddr(), !CreateScatter);
4367 if (CreateScatter) {
4368 NewSI = Builder.CreateIntrinsicWithoutFolding(
4369 Type::getVoidTy(EVL->getContext()), Intrinsic::vp_scatter,
4370 {StoredVal, Addr, Mask, EVL});
4371 } else {
4372 NewSI = Builder.CreateIntrinsicWithoutFolding(
4373 Type::getVoidTy(EVL->getContext()), Intrinsic::vp_store,
4374 {StoredVal, Addr, Mask, EVL});
4375 }
4376 NewSI->addParamAttr(
4378 applyMetadata(*NewSI);
4379}
4380
4382 VPCostContext &Ctx) const {
4383 if (!Consecutive || IsMasked)
4384 return VPWidenMemoryRecipe::computeCost(VF, Ctx);
4385
4386 // We need to use the getMemIntrinsicInstrCost() instead of getMemoryOpCost()
4387 // here because the EVL recipes using EVL to replace the tail mask. But in the
4388 // legacy model, it will always calculate the cost of mask.
4389 // TODO: Using getMemoryOpCost() instead of getMemIntrinsicInstrCost when we
4390 // don't need to compare to the legacy cost model.
4391 Type *Ty = toVectorTy(getStoredValue()->getScalarType(), VF);
4392 unsigned AS =
4393 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4394 return Ctx.TTI.getMemIntrinsicInstrCost(
4395 MemIntrinsicCostAttributes(Intrinsic::vp_store, Ty, Alignment, AS),
4396 Ctx.CostKind);
4397}
4398
4399#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4401 VPSlotTracker &SlotTracker) const {
4402 O << Indent << "WIDEN vp.store ";
4404}
4405#endif
4406
4408 VectorType *DstVTy, const DataLayout &DL) {
4409 // Verify that V is a vector type with same number of elements as DstVTy.
4410 auto VF = DstVTy->getElementCount();
4411 auto *SrcVecTy = cast<VectorType>(V->getType());
4412 assert(VF == SrcVecTy->getElementCount() && "Vector dimensions do not match");
4413 Type *SrcElemTy = SrcVecTy->getElementType();
4414 Type *DstElemTy = DstVTy->getElementType();
4415 assert((DL.getTypeSizeInBits(SrcElemTy) == DL.getTypeSizeInBits(DstElemTy)) &&
4416 "Vector elements must have same size");
4417
4418 // Do a direct cast if element types are castable.
4419 if (CastInst::isBitOrNoopPointerCastable(SrcElemTy, DstElemTy, DL)) {
4420 return Builder.CreateBitOrPointerCast(V, DstVTy);
4421 }
4422 // V cannot be directly casted to desired vector type.
4423 // May happen when V is a floating point vector but DstVTy is a vector of
4424 // pointers or vice-versa. Handle this using a two-step bitcast using an
4425 // intermediate Integer type for the bitcast i.e. Ptr <-> Int <-> Float.
4426 assert((DstElemTy->isPointerTy() != SrcElemTy->isPointerTy()) &&
4427 "Only one type should be a pointer type");
4428 assert((DstElemTy->isFloatingPointTy() != SrcElemTy->isFloatingPointTy()) &&
4429 "Only one type should be a floating point type");
4430 Type *IntTy =
4431 IntegerType::getIntNTy(V->getContext(), DL.getTypeSizeInBits(SrcElemTy));
4432 auto *VecIntTy = VectorType::get(IntTy, VF);
4433 Value *CastVal = Builder.CreateBitOrPointerCast(V, VecIntTy);
4434 return Builder.CreateBitOrPointerCast(CastVal, DstVTy);
4435}
4436
4437/// Return a vector containing interleaved elements from multiple
4438/// smaller input vectors.
4440 const Twine &Name) {
4441 unsigned Factor = Vals.size();
4442 assert(Factor > 1 && "Tried to interleave invalid number of vectors");
4443
4444 VectorType *VecTy = cast<VectorType>(Vals[0]->getType());
4445#ifndef NDEBUG
4446 for (Value *Val : Vals)
4447 assert(Val->getType() == VecTy && "Tried to interleave mismatched types");
4448#endif
4449
4450 // Scalable vectors cannot use arbitrary shufflevectors (only splats), so
4451 // must use intrinsics to interleave.
4452 if (VecTy->isScalableTy()) {
4453 assert(Factor <= 8 && "Unsupported interleave factor for scalable vectors");
4454 return Builder.CreateVectorInterleave(Vals, Name);
4455 }
4456
4457 // Fixed length. Start by concatenating all vectors into a wide vector.
4458 Value *WideVec = concatenateVectors(Builder, Vals);
4459
4460 // Interleave the elements into the wide vector.
4461 const unsigned NumElts = VecTy->getElementCount().getFixedValue();
4462 return Builder.CreateShuffleVector(
4463 WideVec, createInterleaveMask(NumElts, Factor), Name);
4464}
4465
4466// Try to vectorize the interleave group that \p Instr belongs to.
4467//
4468// E.g. Translate following interleaved load group (factor = 3):
4469// for (i = 0; i < N; i+=3) {
4470// R = Pic[i]; // Member of index 0
4471// G = Pic[i+1]; // Member of index 1
4472// B = Pic[i+2]; // Member of index 2
4473// ... // do something to R, G, B
4474// }
4475// To:
4476// %wide.vec = load <12 x i32> ; Read 4 tuples of R,G,B
4477// %R.vec = shuffle %wide.vec, poison, <0, 3, 6, 9> ; R elements
4478// %G.vec = shuffle %wide.vec, poison, <1, 4, 7, 10> ; G elements
4479// %B.vec = shuffle %wide.vec, poison, <2, 5, 8, 11> ; B elements
4480//
4481// Or translate following interleaved store group (factor = 3):
4482// for (i = 0; i < N; i+=3) {
4483// ... do something to R, G, B
4484// Pic[i] = R; // Member of index 0
4485// Pic[i+1] = G; // Member of index 1
4486// Pic[i+2] = B; // Member of index 2
4487// }
4488// To:
4489// %R_G.vec = shuffle %R.vec, %G.vec, <0, 1, 2, ..., 7>
4490// %B_U.vec = shuffle %B.vec, poison, <0, 1, 2, 3, u, u, u, u>
4491// %interleaved.vec = shuffle %R_G.vec, %B_U.vec,
4492// <0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11> ; Interleave R,G,B elements
4493// store <12 x i32> %interleaved.vec ; Write 4 tuples of R,G,B
4495 assert((!needsMaskForGaps() || !State.VF.isScalable()) &&
4496 "Masking gaps for scalable vectors is not yet supported.");
4498 Instruction *Instr = Group->getInsertPos();
4499
4500 // Prepare for the vector type of the interleaved load/store.
4501 Type *ScalarTy = getLoadStoreType(Instr);
4502 unsigned InterleaveFactor = Group->getFactor();
4503 auto *VecTy = VectorType::get(ScalarTy, State.VF * InterleaveFactor);
4504
4505 VPValue *BlockInMask = getMask();
4506 VPValue *Addr = getAddr();
4507 Value *ResAddr = State.get(Addr, VPLane(0));
4508
4509 auto CreateGroupMask = [&BlockInMask, &State,
4510 &InterleaveFactor](Value *MaskForGaps) -> Value * {
4511 if (State.VF.isScalable()) {
4512 assert(!MaskForGaps && "Interleaved groups with gaps are not supported.");
4513 assert(InterleaveFactor <= 8 &&
4514 "Unsupported deinterleave factor for scalable vectors");
4515 auto *ResBlockInMask = State.get(BlockInMask);
4516 SmallVector<Value *> Ops(InterleaveFactor, ResBlockInMask);
4517 return interleaveVectors(State.Builder, Ops, "interleaved.mask");
4518 }
4519
4520 if (!BlockInMask)
4521 return MaskForGaps;
4522
4523 Value *ResBlockInMask = State.get(BlockInMask);
4524 Value *ShuffledMask = State.Builder.CreateShuffleVector(
4525 ResBlockInMask,
4526 createReplicatedMask(InterleaveFactor, State.VF.getFixedValue()),
4527 "interleaved.mask");
4528 return MaskForGaps ? State.Builder.CreateBinOp(Instruction::And,
4529 ShuffledMask, MaskForGaps)
4530 : ShuffledMask;
4531 };
4532
4533 const DataLayout &DL = Instr->getDataLayout();
4534 // Vectorize the interleaved load group.
4535 if (isa<LoadInst>(Instr)) {
4536 Value *MaskForGaps = nullptr;
4537 if (needsMaskForGaps()) {
4538 MaskForGaps =
4539 createBitMaskForGaps(State.Builder, State.VF.getFixedValue(), *Group);
4540 assert(MaskForGaps && "Mask for Gaps is required but it is null");
4541 }
4542
4543 Instruction *NewLoad;
4544 if (BlockInMask || MaskForGaps) {
4545 Value *GroupMask = CreateGroupMask(MaskForGaps);
4546 Value *PoisonVec = PoisonValue::get(VecTy);
4547 NewLoad = State.Builder.CreateMaskedLoad(VecTy, ResAddr,
4548 Group->getAlign(), GroupMask,
4549 PoisonVec, "wide.masked.vec");
4550 } else
4551 NewLoad = State.Builder.CreateAlignedLoad(VecTy, ResAddr,
4552 Group->getAlign(), "wide.vec");
4553 applyMetadata(*NewLoad);
4554 // TODO: Also manage existing metadata using VPIRMetadata.
4555 Group->addMetadata(NewLoad);
4556
4558 if (VecTy->isScalableTy()) {
4559 // Scalable vectors cannot use arbitrary shufflevectors (only splats),
4560 // so must use intrinsics to deinterleave.
4561 assert(InterleaveFactor <= 8 &&
4562 "Unsupported deinterleave factor for scalable vectors");
4563 NewLoad = State.Builder.CreateIntrinsicWithoutFolding(
4564 Intrinsic::getDeinterleaveIntrinsicID(InterleaveFactor),
4565 NewLoad->getType(), NewLoad,
4566 /*FMFSource=*/nullptr, "strided.vec");
4567 }
4568
4569 auto CreateStridedVector = [&InterleaveFactor, &State,
4570 &NewLoad](unsigned Index) -> Value * {
4571 assert(Index < InterleaveFactor && "Illegal group index");
4572 if (State.VF.isScalable())
4573 return State.Builder.CreateExtractValue(NewLoad, Index);
4574
4575 // For fixed length VF, use shuffle to extract the sub-vectors from the
4576 // wide load.
4577 auto StrideMask =
4578 createStrideMask(Index, InterleaveFactor, State.VF.getFixedValue());
4579 return State.Builder.CreateShuffleVector(NewLoad, StrideMask,
4580 "strided.vec");
4581 };
4582
4583 for (unsigned I = 0, J = 0; I < InterleaveFactor; ++I) {
4584 Instruction *Member = Group->getMember(I);
4585
4586 // Skip the gaps in the group.
4587 if (!Member)
4588 continue;
4589
4590 Value *StridedVec = CreateStridedVector(I);
4591
4592 // If this member has different type, cast the result type.
4593 if (Member->getType() != ScalarTy) {
4594 VectorType *OtherVTy = VectorType::get(Member->getType(), State.VF);
4595 StridedVec =
4596 createBitOrPointerCast(State.Builder, StridedVec, OtherVTy, DL);
4597 }
4598
4599 if (Group->isReverse())
4600 StridedVec = State.Builder.CreateVectorReverse(StridedVec, "reverse");
4601
4602 State.set(VPDefs[J], StridedVec);
4603 ++J;
4604 }
4605 return;
4606 }
4607
4608 // The sub vector type for current instruction.
4609 auto *SubVT = VectorType::get(ScalarTy, State.VF);
4610
4611 // Vectorize the interleaved store group.
4612 Value *MaskForGaps =
4613 createBitMaskForGaps(State.Builder, State.VF.getKnownMinValue(), *Group);
4614 assert(((MaskForGaps != nullptr) == needsMaskForGaps()) &&
4615 "Mismatch between NeedsMaskForGaps and MaskForGaps");
4616 ArrayRef<VPValue *> StoredValues = getStoredValues();
4617 // Collect the stored vector from each member.
4618 SmallVector<Value *, 4> StoredVecs;
4619 unsigned StoredIdx = 0;
4620 for (unsigned i = 0; i < InterleaveFactor; i++) {
4621 assert((Group->getMember(i) || MaskForGaps) &&
4622 "Fail to get a member from an interleaved store group");
4623 Instruction *Member = Group->getMember(i);
4624
4625 // Skip the gaps in the group.
4626 if (!Member) {
4627 Value *Undef = PoisonValue::get(SubVT);
4628 StoredVecs.push_back(Undef);
4629 continue;
4630 }
4631
4632 Value *StoredVec = State.get(StoredValues[StoredIdx]);
4633 ++StoredIdx;
4634
4635 if (Group->isReverse())
4636 StoredVec = State.Builder.CreateVectorReverse(StoredVec, "reverse");
4637
4638 // If this member has different type, cast it to a unified type.
4639
4640 if (StoredVec->getType() != SubVT)
4641 StoredVec = createBitOrPointerCast(State.Builder, StoredVec, SubVT, DL);
4642
4643 StoredVecs.push_back(StoredVec);
4644 }
4645
4646 // Interleave all the smaller vectors into one wider vector.
4647 Value *IVec = interleaveVectors(State.Builder, StoredVecs, "interleaved.vec");
4648 Instruction *NewStoreInstr;
4649 if (BlockInMask || MaskForGaps) {
4650 Value *GroupMask = CreateGroupMask(MaskForGaps);
4651 NewStoreInstr = State.Builder.CreateMaskedStore(
4652 IVec, ResAddr, Group->getAlign(), GroupMask);
4653 } else
4654 NewStoreInstr =
4655 State.Builder.CreateAlignedStore(IVec, ResAddr, Group->getAlign());
4656
4657 applyMetadata(*NewStoreInstr);
4658 // TODO: Also manage existing metadata using VPIRMetadata.
4659 Group->addMetadata(NewStoreInstr);
4660}
4661
4662#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4664 VPSlotTracker &SlotTracker) const {
4666 O << Indent << "INTERLEAVE-GROUP with factor " << IG->getFactor() << ", ";
4668 VPValue *Mask = getMask();
4669 if (Mask) {
4670 O << ", ";
4671 Mask->printAsOperand(O, SlotTracker);
4672 }
4673
4674 unsigned OpIdx = 0;
4675 for (unsigned i = 0; i < IG->getFactor(); ++i) {
4676 if (!IG->getMember(i))
4677 continue;
4678 if (getNumStoreOperands() > 0) {
4679 O << "\n" << Indent << " store ";
4680 getOperand(1 + OpIdx)->printAsOperand(O, SlotTracker);
4681 O << " to index " << i;
4682 } else {
4683 O << "\n" << Indent << " ";
4685 O << " = load from index " << i;
4686 }
4687 ++OpIdx;
4688 }
4689}
4690#endif
4691
4693 assert(State.VF.isScalable() &&
4694 "Only support scalable VF for EVL tail-folding.");
4696 "Masking gaps for scalable vectors is not yet supported.");
4698 Instruction *Instr = Group->getInsertPos();
4699
4700 // Prepare for the vector type of the interleaved load/store.
4701 Type *ScalarTy = getLoadStoreType(Instr);
4702 unsigned InterleaveFactor = Group->getFactor();
4703 assert(InterleaveFactor <= 8 &&
4704 "Unsupported deinterleave/interleave factor for scalable vectors");
4705 ElementCount WideVF = State.VF * InterleaveFactor;
4706 auto *VecTy = VectorType::get(ScalarTy, WideVF);
4707
4708 VPValue *Addr = getAddr();
4709 Value *ResAddr = State.get(Addr, VPLane(0));
4710 Value *EVL = State.get(getEVL(), VPLane(0));
4711 Value *InterleaveEVL = State.Builder.CreateMul(
4712 EVL, ConstantInt::get(EVL->getType(), InterleaveFactor), "interleave.evl",
4713 /* NUW= */ true, /* NSW= */ true);
4714 LLVMContext &Ctx = State.Builder.getContext();
4715
4716 Value *GroupMask = nullptr;
4717 if (VPValue *BlockInMask = getMask()) {
4718 SmallVector<Value *> Ops(InterleaveFactor, State.get(BlockInMask));
4719 GroupMask = interleaveVectors(State.Builder, Ops, "interleaved.mask");
4720 } else {
4721 GroupMask =
4722 State.Builder.CreateVectorSplat(WideVF, State.Builder.getTrue());
4723 }
4724
4725 // Vectorize the interleaved load group.
4726 if (isa<LoadInst>(Instr)) {
4727 CallInst *NewLoad = State.Builder.CreateIntrinsicWithoutFolding(
4728 VecTy, Intrinsic::vp_load, {ResAddr, GroupMask, InterleaveEVL}, nullptr,
4729 "wide.vp.load");
4730 NewLoad->addParamAttr(0,
4731 Attribute::getWithAlignment(Ctx, Group->getAlign()));
4732
4733 applyMetadata(*NewLoad);
4734 // TODO: Also manage existing metadata using VPIRMetadata.
4735 Group->addMetadata(NewLoad);
4736
4737 // Scalable vectors cannot use arbitrary shufflevectors (only splats),
4738 // so must use intrinsics to deinterleave.
4739 NewLoad = State.Builder.CreateIntrinsicWithoutFolding(
4740 Intrinsic::getDeinterleaveIntrinsicID(InterleaveFactor),
4741 NewLoad->getType(), NewLoad,
4742 /*FMFSource=*/nullptr, "strided.vec");
4743
4744 const DataLayout &DL = Instr->getDataLayout();
4745 for (unsigned I = 0, J = 0; I < InterleaveFactor; ++I) {
4746 Instruction *Member = Group->getMember(I);
4747 // Skip the gaps in the group.
4748 if (!Member)
4749 continue;
4750
4751 Value *StridedVec = State.Builder.CreateExtractValue(NewLoad, I);
4752 // If this member has different type, cast the result type.
4753 if (Member->getType() != ScalarTy) {
4754 VectorType *OtherVTy = VectorType::get(Member->getType(), State.VF);
4755 StridedVec =
4756 createBitOrPointerCast(State.Builder, StridedVec, OtherVTy, DL);
4757 }
4758
4759 State.set(getVPValue(J), StridedVec);
4760 ++J;
4761 }
4762 return;
4763 } // End for interleaved load.
4764
4765 // The sub vector type for current instruction.
4766 auto *SubVT = VectorType::get(ScalarTy, State.VF);
4767 // Vectorize the interleaved store group.
4768 ArrayRef<VPValue *> StoredValues = getStoredValues();
4769 // Collect the stored vector from each member.
4770 SmallVector<Value *, 4> StoredVecs;
4771 const DataLayout &DL = Instr->getDataLayout();
4772 for (unsigned I = 0, StoredIdx = 0; I < InterleaveFactor; I++) {
4773 Instruction *Member = Group->getMember(I);
4774 // Skip the gaps in the group.
4775 if (!Member) {
4776 StoredVecs.push_back(PoisonValue::get(SubVT));
4777 continue;
4778 }
4779
4780 Value *StoredVec = State.get(StoredValues[StoredIdx]);
4781 // If this member has different type, cast it to a unified type.
4782 if (StoredVec->getType() != SubVT)
4783 StoredVec = createBitOrPointerCast(State.Builder, StoredVec, SubVT, DL);
4784
4785 StoredVecs.push_back(StoredVec);
4786 ++StoredIdx;
4787 }
4788
4789 // Interleave all the smaller vectors into one wider vector.
4790 Value *IVec = interleaveVectors(State.Builder, StoredVecs, "interleaved.vec");
4791 CallInst *NewStore = State.Builder.CreateIntrinsicWithoutFolding(
4792 Type::getVoidTy(Ctx), Intrinsic::vp_store,
4793 {IVec, ResAddr, GroupMask, InterleaveEVL});
4794
4795 NewStore->addParamAttr(1,
4796 Attribute::getWithAlignment(Ctx, Group->getAlign()));
4797
4798 applyMetadata(*NewStore);
4799 // TODO: Also manage existing metadata using VPIRMetadata.
4800 Group->addMetadata(NewStore);
4801}
4802
4803#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4805 VPSlotTracker &SlotTracker) const {
4807 O << Indent << "INTERLEAVE-GROUP with factor " << IG->getFactor() << ", ";
4809 O << ", ";
4811 if (VPValue *Mask = getMask()) {
4812 O << ", ";
4813 Mask->printAsOperand(O, SlotTracker);
4814 }
4815
4816 unsigned OpIdx = 0;
4817 for (unsigned i = 0; i < IG->getFactor(); ++i) {
4818 if (!IG->getMember(i))
4819 continue;
4820 if (getNumStoreOperands() > 0) {
4821 O << "\n" << Indent << " vp.store ";
4822 getOperand(2 + OpIdx)->printAsOperand(O, SlotTracker);
4823 O << " to index " << i;
4824 } else {
4825 O << "\n" << Indent << " ";
4827 O << " = vp.load from index " << i;
4828 }
4829 ++OpIdx;
4830 }
4831}
4832#endif
4833
4835 VPCostContext &Ctx) const {
4836 Instruction *InsertPos = getInsertPos();
4837 // Find the VPValue index of the interleave group. We need to skip gaps.
4838 unsigned InsertPosIdx = 0;
4839 for (unsigned Idx = 0; IG->getFactor(); ++Idx)
4840 if (auto *Member = IG->getMember(Idx)) {
4841 if (Member == InsertPos)
4842 break;
4843 InsertPosIdx++;
4844 }
4845 const VPValue *ValV = getNumDefinedValues() > 0
4846 ? getVPValue(InsertPosIdx)
4847 : getStoredValues()[InsertPosIdx];
4848 Type *ValTy = ValV->getScalarType();
4849 auto *VectorTy = cast<VectorType>(toVectorTy(ValTy, VF));
4850 unsigned AS =
4851 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4852
4853 unsigned InterleaveFactor = IG->getFactor();
4854 auto *WideVecTy = VectorType::get(ValTy, VF * InterleaveFactor);
4855
4856 // Holds the indices of existing members in the interleaved group.
4858 for (unsigned IF = 0; IF < InterleaveFactor; IF++)
4859 if (IG->getMember(IF))
4860 Indices.push_back(IF);
4861
4862 // Calculate the cost of the whole interleaved group.
4863 InstructionCost Cost = Ctx.TTI.getInterleavedMemoryOpCost(
4864 InsertPos->getOpcode(), WideVecTy, IG->getFactor(), Indices,
4865 IG->getAlign(), AS, Ctx.CostKind, getMask(), NeedsMaskForGaps);
4866
4867 if (!IG->isReverse())
4868 return Cost;
4869
4870 return Cost + IG->getNumMembers() *
4871 Ctx.TTI.getShuffleCost(TargetTransformInfo::SK_Reverse,
4872 VectorTy, VectorTy, {}, Ctx.CostKind,
4873 0);
4874}
4875
4877 return vputils::onlyScalarValuesUsed(this) &&
4878 (!IsScalable || vputils::onlyFirstLaneUsed(this));
4879}
4880
4881#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4883 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
4884 assert((getNumOperands() == 3 || getNumOperands() == 5) &&
4885 "unexpected number of operands");
4886 O << Indent << "EMIT ";
4888 O << " = WIDEN-POINTER-INDUCTION ";
4890 O << ", ";
4892 O << ", ";
4894 if (getNumOperands() == 5) {
4895 O << ", ";
4897 O << ", ";
4899 }
4900}
4901
4903 VPSlotTracker &SlotTracker) const {
4904 O << Indent << "EMIT ";
4906 O << " = EXPAND SCEV " << *Expr;
4907}
4908#endif
4909
4910#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4912 VPSlotTracker &SlotTracker) const {
4913 O << Indent << "EMIT ";
4915 O << " = WIDEN-CANONICAL-INDUCTION";
4916 printFlags(O);
4918}
4919#endif
4920
4922 auto &Builder = State.Builder;
4923 // Create a vector from the initial value.
4924 auto *VectorInit = getStartValue()->getLiveInIRValue();
4925
4926 Type *VecTy = State.VF.isScalar()
4927 ? VectorInit->getType()
4928 : VectorType::get(VectorInit->getType(), State.VF);
4929
4930 BasicBlock *VectorPH =
4931 State.CFG.VPBB2IRBB.at(getParent()->getCFGPredecessor(0));
4932 if (State.VF.isVector()) {
4933 auto *IdxTy = Builder.getInt32Ty();
4934 auto *One = ConstantInt::get(IdxTy, 1);
4935 IRBuilder<>::InsertPointGuard Guard(Builder);
4936 Builder.SetInsertPoint(VectorPH->getTerminator());
4937 auto *RuntimeVF = getRuntimeVF(Builder, IdxTy, State.VF);
4938 auto *LastIdx = Builder.CreateSub(RuntimeVF, One);
4939 VectorInit = Builder.CreateInsertElement(
4940 PoisonValue::get(VecTy), VectorInit, LastIdx, "vector.recur.init");
4941 }
4942
4943 // Create a phi node for the new recurrence.
4944 PHINode *Phi = PHINode::Create(VecTy, 2, "vector.recur");
4945 Phi->insertBefore(State.CFG.PrevBB->getFirstInsertionPt());
4946 Phi->addIncoming(VectorInit, VectorPH);
4947 State.set(this, Phi);
4948}
4949
4952 VPCostContext &Ctx) const {
4953 if (VF.isScalar())
4954 return Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
4955
4956 return 0;
4957}
4958
4959#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4961 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
4962 O << Indent << "FIRST-ORDER-RECURRENCE-PHI ";
4964 O << " = phi ";
4966}
4967#endif
4968
4970 // Reductions do not have to start at zero. They can start with
4971 // any loop invariant values.
4972 VPValue *StartVPV = getStartValue();
4973
4974 // In order to support recurrences we need to be able to vectorize Phi nodes.
4975 // Phi nodes have cycles, so we need to vectorize them in two stages. This is
4976 // stage #1: We create a new vector PHI node with no incoming edges. We'll use
4977 // this value when we vectorize all of the instructions that use the PHI.
4978 BasicBlock *VectorPH =
4979 State.CFG.VPBB2IRBB.at(getParent()->getCFGPredecessor(0));
4980 bool ScalarPHI = State.VF.isScalar() || isInLoop();
4981 Value *StartV = State.get(StartVPV, ScalarPHI);
4982 Type *VecTy = StartV->getType();
4983
4984 BasicBlock *HeaderBB = State.CFG.PrevBB;
4985 assert(State.CurrentParentLoop->getHeader() == HeaderBB &&
4986 "recipe must be in the vector loop header");
4987 auto *Phi = PHINode::Create(VecTy, 2, "vec.phi");
4988 Phi->insertBefore(HeaderBB->getFirstInsertionPt());
4989 State.set(this, Phi, isInLoop());
4990
4991 Phi->addIncoming(StartV, VectorPH);
4992}
4993
4994#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4996 VPSlotTracker &SlotTracker) const {
4997 O << Indent << "WIDEN-REDUCTION-PHI ";
4998
5000 O << " = phi (";
5001 printRecurrenceKind(O, Kind);
5002 O << ")";
5003 printFlags(O);
5005 if (getVFScaleFactor() > 1)
5006 O << " (VF scaled by 1/" << getVFScaleFactor() << ")";
5007}
5008#endif
5009
5011 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
5012 return vputils::onlyFirstLaneUsed(this);
5013}
5014
5016 executePhiRecipe(this, *this, State, /*IsScalar=*/false, Name);
5017}
5018
5020 VPCostContext &Ctx) const {
5021 return Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
5022}
5023
5024#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
5026 VPSlotTracker &SlotTracker) const {
5027 O << Indent << "WIDEN-PHI ";
5028
5030 O << " = phi ";
5032}
5033#endif
5034
5036 BasicBlock *VectorPH =
5037 State.CFG.VPBB2IRBB.at(getParent()->getCFGPredecessor(0));
5038 Value *StartMask = State.get(getOperand(0));
5039 PHINode *Phi =
5040 State.Builder.CreatePHI(StartMask->getType(), 2, "active.lane.mask");
5041 Phi->addIncoming(StartMask, VectorPH);
5042 State.set(this, Phi);
5043}
5044
5045#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
5047 VPSlotTracker &SlotTracker) const {
5048 O << Indent << "ACTIVE-LANE-MASK-PHI ";
5049
5051 O << " = phi ";
5053}
5054#endif
5055
5056#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
5058 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
5059 O << Indent << "CURRENT-ITERATION-PHI ";
5060
5062 O << " = phi ";
5064}
5065#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)
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > & Cond
SI Fold Operands
This file contains some templates that are useful if you are working with the STL at all.
This file defines less commonly used SmallVector utilities.
This file defines the SmallVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
This file contains the declarations of different VPlan-related auxiliary helpers.
static Value * interleaveVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vals, const Twine &Name)
Return a vector containing interleaved elements from multiple smaller input vectors.
static void executePhiRecipe(VPSingleDefRecipe *R, VPPhiAccessors &Phi, VPTransformState &State, bool IsScalar, const Twine &Name)
Shared execute logic for VPPhi and VPWidenPHIRecipe.
static Value * createBitOrPointerCast(IRBuilderBase &Builder, Value *V, VectorType *DstVTy, const DataLayout &DL)
static Instruction::BinaryOps getSubRecurOpcode(RecurKind Kind)
SmallVector< Value *, 2 > VectorParts
static cl::opt< bool > VPlanPrintMetadata("vplan-print-metadata", cl::init(true), cl::Hidden, cl::desc("Controls the printing of recipe metadata when debugging."))
static void printRecurrenceKind(raw_ostream &OS, const RecurKind &Kind)
static unsigned getCalledFnOperandIndex(ArrayRef< VPValue * > Operands)
For call VPInstruction operands, return the operand index of the called function.
This file contains the declarations of the Vectorization Plan base classes:
void printAsOperand(OutputBuffer &OB, Prec P=Prec::Default, bool StrictlyWorse=false) const
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
Definition APInt.h:231
bool ule(const APInt &RHS) const
Unsigned less or equal comparison.
Definition APInt.h:1155
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 * CreateExtractVector(Type *DstType, Value *SrcVec, Value *Idx, const Twine &Name="")
Create a call to the vector.extract intrinsic.
Definition IRBuilder.h:1112
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Definition IRBuilder.h:2092
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
Definition IRBuilder.h:2277
void setFastMathFlags(FastMathFlags NewFMF)
Set the fast-math flags to be used with generated fp-math operators.
Definition IRBuilder.h:300
LLVM_ABI Value * CreateVectorReverse(Value *V, const Twine &Name="")
Return a vector value that contains the vector V reversed.
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2379
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Definition IRBuilder.h:482
Value * CreateLogicalAnd(Value *Cond1, Value *Cond2, const Twine &Name="", Instruction *MDFrom=nullptr)
Definition IRBuilder.h:1770
LLVM_ABI Value * CreateOrReduce(Value *Src)
Create a vector int OR reduction intrinsic of the source vector.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Definition IRBuilder.h:477
Value * CreateCmp(CmpInst::Predicate Pred, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2509
Value * CreateNot(Value *V, const Twine &Name="")
Definition IRBuilder.h:1854
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2375
Value * CreateCountTrailingZeroElems(Type *ResTy, Value *Mask, bool ZeroIsPoison=true, const Twine &Name="")
Create a call to llvm.experimental_cttz_elts.
Definition IRBuilder.h:1154
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1439
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Definition IRBuilder.h:2121
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1422
ConstantInt * getFalse()
Get the constant value for i1 false.
Definition IRBuilder.h:462
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:1731
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2387
Value * CreateLogicalOr(Value *Cond1, Value *Cond2, const Twine &Name="", Instruction *MDFrom=nullptr)
Definition IRBuilder.h:1778
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2485
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Definition IRBuilder.h:1592
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1456
LLVM_ABI Value * CreateUnaryIntrinsic(Intrinsic::ID ID, Value *Op, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with 1 operand which is mangled on its type.
A struct for saving information about induction variables.
@ IK_IntInduction
Integer induction variable. Step = C.
static InstructionCost getInvalid(CostType Val=0)
bool isCast() const
bool isBinaryOp() const
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
const char * getOpcodeName() const
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
bool isUnaryOp() const
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:348
The group of interleaved loads/stores sharing the same stride and close to each other.
uint32_t getFactor() const
InstTy * getMember(uint32_t Index) const
Get the member with the given index Index.
bool isReverse() const
InstTy * getInsertPos() const
void addMetadata(InstTy *NewInst) const
Add metadata (e.g.
Align getAlign() const
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
Information for memory intrinsic cost model.
Root of the metadata hierarchy.
Definition Metadata.h:64
LLVM_ABI void print(raw_ostream &OS, const Module *M=nullptr, bool IsForDebug=false) const
Print.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
ScalarEvolution * getSE() const
Returns the ScalarEvolution analysis used.
static LLVM_ABI unsigned getOpcode(RecurKind Kind)
Returns the opcode corresponding to the RecurrenceKind.
static bool isAnyOfRecurrenceKind(RecurKind Kind)
Returns true if the recurrence kind is of the form select(cmp(),x,y) where one of (x,...
static LLVM_ABI bool isSubRecurrenceKind(RecurKind Kind)
Returns true if the recurrence kind is for a sub operation.
static bool isFindIVRecurrenceKind(RecurKind Kind)
Returns true if the recurrence kind is of the form select(cmp(),x,y) where one of (x,...
static bool isMinMaxRecurrenceKind(RecurKind Kind)
Returns true if the recurrence kind is any min/max kind.
This class represents an analyzed expression in the program.
This class represents the LLVM 'select' instruction.
This class provides computation of slot numbers for LLVM Assembly writing.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
reference emplace_back(ArgTypes &&... Args)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
static LLVM_ABI PartialReductionExtendKind getPartialReductionExtendKind(Instruction *I)
Get the kind of extension that an instruction represents.
static LLVM_ABI OperandValueInfo getOperandInfo(const Value *V)
Collect properties of V used in cost analysis, e.g. OP_PowerOf2.
llvm::VectorInstrContext VectorInstrContext
@ TCC_Free
Expected to fold away in lowering.
@ SK_Splice
Concatenates elements from the first input vector with elements of the second input vector.
@ SK_Reverse
Reverse the order of the vector.
CastContextHint
Represents a hint about the context in which a cast is used.
@ Reversed
The cast is used with a reversed load/store.
@ Masked
The cast is used with a masked load/store.
@ None
The cast is not used with a load/store of any kind.
@ Normal
The cast is used with a normal load/store.
@ Interleave
The cast is used with an interleaved load/store.
@ GatherScatter
The cast is used with a gather/scatter.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isByteTy() const
True if this is an instance of ByteType.
Definition Type.h:242
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:288
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:282
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:282
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:368
bool isStructTy() const
True if this is an instance of StructType.
Definition Type.h:276
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition Type.h:130
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:232
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:306
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
bool isIntOrPtrTy() const
Return true if this is an integer type or a pointer type.
Definition Type.h:270
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:313
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
value_op_iterator value_op_end()
Definition User.h:288
void setOperand(unsigned i, Value *Val)
Definition User.h:212
Value * getOperand(unsigned i) const
Definition User.h:207
value_op_iterator value_op_begin()
Definition User.h:285
void execute(VPTransformState &State) override
Generate the active lane mask phi of the vector loop.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
Definition VPlan.h:4389
RecipeListTy & getRecipeList()
Returns a reference to the list of recipes.
Definition VPlan.h:4442
iterator end()
Definition VPlan.h:4426
void insert(VPRecipeBase *Recipe, iterator InsertPt)
Definition VPlan.h:4455
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:3003
unsigned getNumIncomingValues() const
Return the number of incoming values, taking into account when normalized the first incoming value wi...
Definition VPlan.h:2998
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:2994
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:4220
VPValue * getIndex() const
Definition VPlan.h:4217
VPValue * getStepValue() const
Definition VPlan.h:4218
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:4216
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:2482
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:2203
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:1738
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:1599
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:1345
@ Intrinsic
Calls a scalar intrinsic. The intrinsic ID is the last operand.
Definition VPlan.h:1365
@ ExtractLane
Extracts a single lane (first operand) from a set of vector operands.
Definition VPlan.h:1336
@ ExitingIVValue
Compute the exiting value of a wide induction after vectorization, that is the value of the last lane...
Definition VPlan.h:1349
@ WideIVStep
Scale the first operand (vector step) by the second operand (scalar-step).
Definition VPlan.h:1361
@ ResumeForEpilogue
Explicit user for the resume phi of the canonical induction in the main VPlan, used by the epilogue v...
Definition VPlan.h:1339
@ Unpack
Extracts all lanes from its (non-scalable) vector operand.
Definition VPlan.h:1286
@ ReductionStartVector
Start vector for reductions with 3 operands: the original start value, the identity value for the red...
Definition VPlan.h:1332
@ BuildVector
Creates a fixed-width vector containing all operands.
Definition VPlan.h:1281
@ BuildStructVector
Given operands of (the same) struct type, creates a struct of fixed- width vectors each containing a ...
Definition VPlan.h:1278
@ CanonicalIVIncrementForPart
Definition VPlan.h:1262
@ ComputeReductionResult
Reduce the operands to the final reduction result using the operation specified via the operation's V...
Definition VPlan.h:1289
bool hasResult() const
Definition VPlan.h:1450
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:1531
unsigned getOpcode() const
Definition VPlan.h:1429
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:1475
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:3107
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this recipe.
Instruction * getInsertPos() const
Definition VPlan.h:3111
const InterleaveGroup< Instruction > * getInterleaveGroup() const
Definition VPlan.h:3109
VPValue * getMask() const
Return the mask used by this recipe.
Definition VPlan.h:3101
ArrayRef< VPValue * > getStoredValues() const
Return the VPValues stored by this interleave group.
Definition VPlan.h:3130
VPValue * getAddr() const
Return the address accessed by this recipe.
Definition VPlan.h:3095
VPValue * getEVL() const
The VPValue of the explicit vector length.
Definition VPlan.h:3204
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:3217
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:3167
void execute(VPTransformState &State) override
Generate the wide load or store, and shuffles.
static LLVM_ABI std::optional< unsigned > getMaskParamPos(Intrinsic::ID IntrinsicID)
static LLVM_ABI std::optional< unsigned > getMemoryDataParamPos(Intrinsic::ID)
static LLVM_ABI std::optional< unsigned > getMemoryPointerParamPos(Intrinsic::ID)
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:1618
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:1667
VPValue * getIncomingValue(unsigned Idx) const
Returns the incoming VPValue with index Idx.
Definition VPlan.h:1627
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:4788
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:3375
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:2909
bool isInLoop() const
Returns true if the phi is part of an in-loop reduction.
Definition VPlan.h:2928
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:3317
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:3328
VPValue * getCondOp() const
The VPValue of the condition for the block.
Definition VPlan.h:3330
RecurKind getRecurrenceKind() const
Return the recurrence kind for the in-loop reduction.
Definition VPlan.h:3313
bool isPartialReduction() const
Returns true if the reduction outputs a vector with a scaled down VF.
Definition VPlan.h:3319
VPValue * getChainOp() const
The VPValue of the scalar Chain being accumulated.
Definition VPlan.h:3326
bool isInLoop() const
Returns true if the reduction is in-loop.
Definition VPlan.h:3321
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:4614
bool isReplicator() const
An indicator whether this region is to generate multiple replicated instances of output IR correspond...
Definition VPlan.h:4690
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:3456
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:3494
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:4275
VPValue * getStartIndex() const
Return the StartIndex, or null if known to be zero, valid only after unrolling.
Definition VPlan.h:4283
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
void execute(VPTransformState &State) override
Generate the scalarized versions of the phi node as needed by their users.
VPSingleDefRecipe is a base class for recipes that model a sequence of one or more output IR that def...
Definition VPlan.h:619
Instruction * getUnderlyingInstr()
Returns the underlying instruction.
Definition VPlan.h:689
LLVM_ABI_FOR_TEST LLVM_DUMP_METHOD void dump() const
Print this VPSingleDefRecipe to dbgs() (for debugging).
VPSingleDefRecipe(VPRecipeTy SC, ArrayRef< VPValue * > Operands, DebugLoc DL=DebugLoc::getUnknown())
Definition VPlan.h:621
This class can be used to assign names to VPValues.
A symbolic live-in VPValue, used for values like vector trip count, VF, and VFxUF.
Definition VPlanValue.h:217
This class augments VPValue with operands which provide the inverse def-use edges from VPValue's user...
Definition VPlanValue.h:401
void printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const
Print the operands to O.
Definition VPlan.cpp:1541
operand_range operands()
Definition VPlanValue.h:474
unsigned getNumOperands() const
Definition VPlanValue.h:441
VPValue * getOperand(unsigned N) const
Definition VPlanValue.h:442
void addOperand(VPValue *Operand)
Definition VPlanValue.h:427
This is the base class of the VPlan Def/Use graph, used for modeling the data flow into,...
Definition VPlanValue.h:50
Type * getScalarType() const
Returns the scalar type of this VPValue, dispatching based on the concrete subclass.
Definition VPlan.cpp:149
Value * getLiveInIRValue() const
Return the underlying IR value for a VPIRValue.
Definition VPlan.cpp:143
bool isDefinedOutsideLoopRegions() const
Returns true if the VPValue is defined outside any loop.
Definition VPlan.cpp:1492
VPRecipeBase * getDefiningRecipe()
Returns the recipe defining this VPValue or nullptr if it is not defined by a recipe,...
Definition VPlan.cpp:130
void printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const
Definition VPlan.cpp:1537
Value * getUnderlyingValue() const
Return the underlying Value attached to this VPValue.
Definition VPlanValue.h:75
void setUnderlyingValue(Value *Val)
Definition VPlanValue.h:209
VPUser * getSingleUser()
Return the single user of this value, or nullptr if there is not exactly one user.
Definition VPlanValue.h:179
VPValue * getVFValue() const
Definition VPlan.h:2297
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:2294
int64_t getStride() const
Definition VPlan.h:2295
void materializeOffset(unsigned Part=0)
Adds the offset operand to the recipe.
VPValue * getStride() const
Definition VPlan.h:2371
Type * getSourceElementType() const
Definition VPlan.h:2386
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:2373
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:2154
Function * getCalledScalarFunction() const
Definition VPlan.h:2150
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:1925
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:2251
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:2568
VPValue * getStepValue()
Returns the step value of the induction.
Definition VPlan.h:2571
const InductionDescriptor & getInductionDescriptor() const
Returns the induction descriptor for the recipe.
Definition VPlan.h:2591
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:2679
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:2039
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:3755
bool isConsecutive() const
Return whether the loaded-from / stored-to addresses are consecutive.
Definition VPlan.h:3780
Instruction & Ingredient
Definition VPlan.h:3746
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const
Return the cost of this VPWidenMemoryRecipe.
bool Consecutive
Whether the accessed addresses are consecutive.
Definition VPlan.h:3752
VPValue * getMask() const
Return the mask used by this recipe.
Definition VPlan.h:3790
Align Alignment
Alignment information for this memory access.
Definition VPlan.h:3749
virtual VPRecipeBase * getAsRecipe()=0
Return a VPRecipeBase* to the current object.
VPValue * getAddr() const
Return the address accessed by this recipe.
Definition VPlan.h:3783
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:1868
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4801
const DataLayout & getDataLayout() const
Definition VPlan.h:5008
VPValue * getTripCount() const
The trip count of the original loop.
Definition VPlan.h:4962
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:5110
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:383
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1753
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
Type * toVectorizedTy(Type *Ty, ElementCount EC)
A helper for converting to vectorized types.
cl::opt< unsigned > ForceTargetInstructionCost
LLVM_ABI Type * computeScalarTypeForInstruction(unsigned Opcode, ArrayRef< VPValue * > Operands)
Compute the scalar result type for an IR Opcode given Operands.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
Definition STLExtras.h:322
LLVM_ABI bool isVectorIntrinsicWithStructReturnOverloadAtField(Intrinsic::ID ID, int RetIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic that returns a struct is overloaded at the struct elem...
@ Other
Any other memory.
Definition ModRef.h:68
static const MachineInstrBuilder & addOffset(const MachineInstrBuilder &MIB, int Offset)
LLVM_ABI llvm::SmallVector< int, 16 > createInterleaveMask(unsigned VF, unsigned NumVecs)
Create an interleave shuffle mask.
RecurKind
These are the kinds of recurrences that we support.
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
@ FMinimumNum
FP min with llvm.minimumnum semantics.
@ FindIV
FindIV reduction with select(icmp(),x,y) where one of (x,y) is a loop induction variable (increasing ...
@ Or
Bitwise or logical OR of integers.
@ FMinimum
FP min with llvm.minimum semantics.
@ FMaxNum
FP max with llvm.maxnum semantics including NaNs.
@ Mul
Product of integers.
@ FSub
Subtraction of floats.
@ FAddChainWithSubs
A chain of fadds and fsubs.
@ None
Not a recurrence.
@ AnyOf
AnyOf reduction with select(cmp(),x,y) where one of (x,y) is loop invariant, and both x and y are int...
@ Xor
Bitwise or logical XOR of integers.
@ FindLast
FindLast reduction with select(cmp(),x,y) where x and y.
@ FMax
FP max implemented in terms of select(cmp()).
@ FMaximum
FP max with llvm.maximum semantics.
@ FMulAdd
Sum of float products with llvm.fmuladd(a * b + sum).
@ FMul
Product of floats.
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ FMin
FP min implemented in terms of select(cmp()).
@ FMinNum
FP min with llvm.minnum semantics including NaNs.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
@ AddChainWithSubs
A chain of adds and subs.
@ FAdd
Sum of floats.
@ FMaximumNum
FP max with llvm.maximumnum semantics.
@ UMax
Unsigned integer max implemented in terms of select(cmp()).
LLVM_ABI bool isVectorIntrinsicWithScalarOpAtArg(Intrinsic::ID ID, unsigned ScalarOpdIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic has a scalar operand.
LLVM_ABI Value * getRecurrenceIdentity(RecurKind K, Type *Tp, FastMathFlags FMF)
Given information about an recurrence kind, return the identity for the @llvm.vector....
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
LLVM_ABI Value * createOrderedReduction(IRBuilderBase &B, RecurKind RdxKind, Value *Src, Value *Start)
Create an ordered reduction intrinsic using the given recurrence kind RdxKind.
ArrayRef< Type * > getContainedTypes(Type *const &Ty)
Returns the types contained in Ty.
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
LLVM_ABI bool isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID, int OpdIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic is overloaded on the type of the operand at index OpdI...
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Struct to hold various analysis needed for cost computations.
static bool isFreeScalarIntrinsic(Intrinsic::ID ID)
Returns true if ID is a pseudo intrinsic that is dropped via scalarization rather than widened.
Definition VPlan.cpp:1990
TargetTransformInfo::TargetCostKind CostKind
void execute(VPTransformState &State) override
Generate the phi nodes.
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this first-order recurrence phi recipe.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
An overlay for VPIRInstructions wrapping PHI nodes enabling convenient use cast/dyn_cast/isa and exec...
Definition VPlan.h:1796
PHINode & getIRPhi()
Definition VPlan.h:1809
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:3875
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:3977
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:3980
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:3925