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);
2417 MemI->addParamAttr(
2418 0, Attribute::getWithAlignment(MemI->getContext(), Alignment));
2419 State.set(this, MemI);
2420}
2421
2423 Intrinsic::ID IID, Type *Ty, bool IsMasked, Align Alignment,
2424 VPCostContext &Ctx) {
2425 return Ctx.TTI.getMemIntrinsicInstrCost(
2426 MemIntrinsicCostAttributes(IID, Ty, /*Ptr=*/nullptr, IsMasked, Alignment),
2427 Ctx.CostKind);
2428}
2429
2432 VPCostContext &Ctx) const {
2433 Type *Ty = toVectorTy(getScalarType(), VF);
2435 !match(getOperand(2), m_True()), Alignment,
2436 Ctx);
2437}
2438
2440 IRBuilderBase &Builder = State.Builder;
2441
2442 Value *Address = State.get(getOperand(0));
2443 Value *IncAmt = State.get(getOperand(1), /*IsScalar=*/true);
2444 VectorType *VTy = cast<VectorType>(Address->getType());
2445
2446 // The histogram intrinsic requires a mask even if the recipe doesn't;
2447 // if the mask operand was omitted then all lanes should be executed and
2448 // we just need to synthesize an all-true mask.
2449 Value *Mask = nullptr;
2450 if (VPValue *VPMask = getMask())
2451 Mask = State.get(VPMask);
2452 else
2453 Mask =
2454 Builder.CreateVectorSplat(VTy->getElementCount(), Builder.getInt1(1));
2455
2456 // If this is a subtract, we want to invert the increment amount. We may
2457 // add a separate intrinsic in future, but for now we'll try this.
2458 if (Opcode == Instruction::Sub)
2459 IncAmt = Builder.CreateNeg(IncAmt);
2460 else
2461 assert(Opcode == Instruction::Add && "only add or sub supported for now");
2462
2463 Instruction *HistogramInst = State.Builder.CreateIntrinsicWithoutFolding(
2464 Intrinsic::experimental_vector_histogram_add, {VTy, IncAmt->getType()},
2465 {Address, IncAmt, Mask});
2466 applyMetadata(*HistogramInst);
2467}
2468
2470 VPCostContext &Ctx) const {
2471 // FIXME: Take the gather and scatter into account as well. For now we're
2472 // generating the same cost as the fallback path, but we'll likely
2473 // need to create a new TTI method for determining the cost, including
2474 // whether we can use base + vec-of-smaller-indices or just
2475 // vec-of-pointers.
2476 assert(VF.isVector() && "Invalid VF for histogram cost");
2477 Type *AddressTy = getOperand(0)->getScalarType();
2478 VPValue *IncAmt = getOperand(1);
2479 Type *IncTy = IncAmt->getScalarType();
2480 VectorType *VTy = VectorType::get(IncTy, VF);
2481
2482 // Assume that a non-constant update value (or a constant != 1) requires
2483 // a multiply, and add that into the cost.
2484 InstructionCost MulCost =
2485 Ctx.TTI.getArithmeticInstrCost(Instruction::Mul, VTy, Ctx.CostKind);
2486 if (match(IncAmt, m_One()))
2487 MulCost = TTI::TCC_Free;
2488
2489 // Find the cost of the histogram operation itself.
2490 Type *PtrTy = VectorType::get(AddressTy, VF);
2491 Type *MaskTy = VectorType::get(Type::getInt1Ty(Ctx.LLVMCtx), VF);
2492 IntrinsicCostAttributes ICA(Intrinsic::experimental_vector_histogram_add,
2493 Type::getVoidTy(Ctx.LLVMCtx),
2494 {PtrTy, IncTy, MaskTy});
2495
2496 // Add the costs together with the add/sub operation.
2497 return Ctx.TTI.getIntrinsicInstrCost(ICA, Ctx.CostKind) + MulCost +
2498 Ctx.TTI.getArithmeticInstrCost(Opcode, VTy, Ctx.CostKind);
2499}
2500
2501#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2503 VPSlotTracker &SlotTracker) const {
2504 O << Indent << "WIDEN-HISTOGRAM buckets: ";
2506
2507 if (Opcode == Instruction::Sub)
2508 O << ", dec: ";
2509 else {
2510 assert(Opcode == Instruction::Add);
2511 O << ", inc: ";
2512 }
2514
2515 if (VPValue *Mask = getMask()) {
2516 O << ", mask: ";
2517 Mask->printAsOperand(O, SlotTracker);
2518 }
2519}
2520#endif
2521
2522VPIRFlags::FastMathFlagsTy::FastMathFlagsTy(const FastMathFlags &FMF) {
2523 AllowReassoc = FMF.allowReassoc();
2524 NoNaNs = FMF.noNaNs();
2525 NoInfs = FMF.noInfs();
2526 NoSignedZeros = FMF.noSignedZeros();
2527 AllowReciprocal = FMF.allowReciprocal();
2528 AllowContract = FMF.allowContract();
2529 ApproxFunc = FMF.approxFunc();
2530}
2531
2532VPIRFlags VPIRFlags::getDefaultFlags(unsigned Opcode, Type *ResultTy) {
2533 switch (Opcode) {
2534 case Instruction::Add:
2535 case Instruction::Sub:
2536 case Instruction::Mul:
2537 case Instruction::Shl:
2539 return WrapFlagsTy(false, false);
2540 case Instruction::Trunc:
2541 return TruncFlagsTy(false, false);
2542 case Instruction::Or:
2543 return DisjointFlagsTy(false);
2544 case Instruction::AShr:
2545 case Instruction::LShr:
2546 case Instruction::UDiv:
2547 case Instruction::SDiv:
2548 return ExactFlagsTy(false);
2549 case Instruction::GetElementPtr:
2552 return GEPNoWrapFlags::none();
2553 case Instruction::ZExt:
2554 case Instruction::UIToFP:
2555 return NonNegFlagsTy(false);
2556 case Instruction::FAdd:
2557 case Instruction::FSub:
2558 case Instruction::FMul:
2559 case Instruction::FDiv:
2560 case Instruction::FRem:
2561 case Instruction::FNeg:
2562 case Instruction::FPExt:
2563 case Instruction::FPTrunc:
2564 return FastMathFlags();
2565 case Instruction::Select:
2566 // Selects only have fast-math flags if they produce a floating-point value.
2567 if (ResultTy && FPMathOperator::isSupportedFloatingPointType(ResultTy))
2568 return FastMathFlags();
2569 return VPIRFlags();
2570 case Instruction::ICmp:
2571 case Instruction::FCmp:
2573 llvm_unreachable("opcode requires explicit flags");
2574 default:
2575 return VPIRFlags();
2576 }
2577}
2578
2579#if !defined(NDEBUG)
2580bool VPIRFlags::flagsValidForOpcode(unsigned Opcode) const {
2581 switch (OpType) {
2582 case OperationType::OverflowingBinOp:
2583 return Opcode == Instruction::Add || Opcode == Instruction::Sub ||
2584 Opcode == Instruction::Mul || Opcode == Instruction::Shl ||
2585 Opcode == VPInstruction::VPInstruction::CanonicalIVIncrementForPart;
2586 case OperationType::Trunc:
2587 return Opcode == Instruction::Trunc;
2588 case OperationType::DisjointOp:
2589 return Opcode == Instruction::Or;
2590 case OperationType::PossiblyExactOp:
2591 return Opcode == Instruction::AShr || Opcode == Instruction::LShr ||
2592 Opcode == Instruction::UDiv || Opcode == Instruction::SDiv;
2593 case OperationType::GEPOp:
2594 return Opcode == Instruction::GetElementPtr ||
2595 Opcode == VPInstruction::PtrAdd ||
2596 Opcode == VPInstruction::WidePtrAdd;
2597 case OperationType::FPMathOp:
2598 return Opcode == Instruction::Call || Opcode == Instruction::FAdd ||
2599 Opcode == Instruction::FMul || Opcode == Instruction::FSub ||
2600 Opcode == Instruction::FNeg || Opcode == Instruction::FDiv ||
2601 Opcode == Instruction::FRem || Opcode == Instruction::FPExt ||
2602 Opcode == Instruction::FPTrunc || Opcode == Instruction::PHI ||
2603 Opcode == Instruction::Select || Opcode == Instruction::SIToFP ||
2604 Opcode == Instruction::UIToFP ||
2605 Opcode == VPInstruction::WideIVStep ||
2607 case OperationType::FCmp:
2608 return Opcode == Instruction::FCmp;
2609 case OperationType::NonNegOp:
2610 return Opcode == Instruction::ZExt || Opcode == Instruction::UIToFP;
2611 case OperationType::Cmp:
2612 return Opcode == Instruction::FCmp || Opcode == Instruction::ICmp;
2613 case OperationType::ReductionOp:
2615 case OperationType::Other:
2616 return true;
2617 }
2618 llvm_unreachable("Unknown OperationType enum");
2619}
2620
2621bool VPIRFlags::hasRequiredFlagsForOpcode(unsigned Opcode) const {
2622 // Handle opcodes without default flags.
2623 if (Opcode == Instruction::ICmp)
2624 return OpType == OperationType::Cmp;
2625 if (Opcode == Instruction::FCmp)
2626 return OpType == OperationType::FCmp;
2628 return OpType == OperationType::ReductionOp;
2629
2630 OperationType Required = getDefaultFlags(Opcode).OpType;
2631 return Required == OperationType::Other || Required == OpType;
2632}
2633#endif
2634
2635#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2636static void printRecurrenceKind(raw_ostream &OS, const RecurKind &Kind) {
2637 switch (Kind) {
2638 case RecurKind::None:
2639 OS << "none";
2640 break;
2641 case RecurKind::Add:
2642 OS << "add";
2643 break;
2644 case RecurKind::Sub:
2645 OS << "sub";
2646 break;
2648 OS << "add-chain-with-subs";
2649 break;
2650 case RecurKind::Mul:
2651 OS << "mul";
2652 break;
2653 case RecurKind::Or:
2654 OS << "or";
2655 break;
2656 case RecurKind::And:
2657 OS << "and";
2658 break;
2659 case RecurKind::Xor:
2660 OS << "xor";
2661 break;
2662 case RecurKind::SMin:
2663 OS << "smin";
2664 break;
2665 case RecurKind::SMax:
2666 OS << "smax";
2667 break;
2668 case RecurKind::UMin:
2669 OS << "umin";
2670 break;
2671 case RecurKind::UMax:
2672 OS << "umax";
2673 break;
2674 case RecurKind::FAdd:
2675 OS << "fadd";
2676 break;
2678 OS << "fadd-chain-with-subs";
2679 break;
2680 case RecurKind::FSub:
2681 OS << "fsub";
2682 break;
2683 case RecurKind::FMul:
2684 OS << "fmul";
2685 break;
2686 case RecurKind::FMin:
2687 OS << "fmin";
2688 break;
2689 case RecurKind::FMax:
2690 OS << "fmax";
2691 break;
2692 case RecurKind::FMinNum:
2693 OS << "fminnum";
2694 break;
2695 case RecurKind::FMaxNum:
2696 OS << "fmaxnum";
2697 break;
2699 OS << "fminimum";
2700 break;
2702 OS << "fmaximum";
2703 break;
2705 OS << "fminimumnum";
2706 break;
2708 OS << "fmaximumnum";
2709 break;
2710 case RecurKind::FMulAdd:
2711 OS << "fmuladd";
2712 break;
2713 case RecurKind::AnyOf:
2714 OS << "any-of";
2715 break;
2716 case RecurKind::FindIV:
2717 OS << "find-iv";
2718 break;
2720 OS << "find-last";
2721 break;
2722 }
2723}
2724
2726 switch (OpType) {
2727 case OperationType::Cmp:
2729 break;
2730 case OperationType::FCmp:
2733 break;
2734 case OperationType::DisjointOp:
2735 if (DisjointFlags.IsDisjoint)
2736 O << " disjoint";
2737 break;
2738 case OperationType::PossiblyExactOp:
2739 if (ExactFlags.IsExact)
2740 O << " exact";
2741 break;
2742 case OperationType::OverflowingBinOp:
2743 if (WrapFlags.HasNUW)
2744 O << " nuw";
2745 if (WrapFlags.HasNSW)
2746 O << " nsw";
2747 break;
2748 case OperationType::Trunc:
2749 if (TruncFlags.HasNUW)
2750 O << " nuw";
2751 if (TruncFlags.HasNSW)
2752 O << " nsw";
2753 break;
2754 case OperationType::FPMathOp:
2756 break;
2757 case OperationType::GEPOp: {
2759 if (Flags.isInBounds())
2760 O << " inbounds";
2761 else if (Flags.hasNoUnsignedSignedWrap())
2762 O << " nusw";
2763 if (Flags.hasNoUnsignedWrap())
2764 O << " nuw";
2765 break;
2766 }
2767 case OperationType::NonNegOp:
2768 if (NonNegFlags.NonNeg)
2769 O << " nneg";
2770 break;
2771 case OperationType::ReductionOp: {
2772 O << " (";
2774 if (isReductionInLoop())
2775 O << ", in-loop";
2776 if (isReductionOrdered())
2777 O << ", ordered";
2778 O << ")";
2780 break;
2781 }
2782 case OperationType::Other:
2783 break;
2784 }
2785 O << " ";
2786}
2787#endif
2788
2790 auto &Builder = State.Builder;
2791 switch (Opcode) {
2792 case Instruction::Call:
2793 case Instruction::UncondBr:
2794 case Instruction::CondBr:
2795 case Instruction::PHI:
2796 case Instruction::GetElementPtr:
2797 llvm_unreachable("This instruction is handled by a different recipe.");
2798 case Instruction::UDiv:
2799 case Instruction::SDiv:
2800 case Instruction::SRem:
2801 case Instruction::URem:
2802 case Instruction::Add:
2803 case Instruction::FAdd:
2804 case Instruction::Sub:
2805 case Instruction::FSub:
2806 case Instruction::FNeg:
2807 case Instruction::Mul:
2808 case Instruction::FMul:
2809 case Instruction::FDiv:
2810 case Instruction::FRem:
2811 case Instruction::Shl:
2812 case Instruction::LShr:
2813 case Instruction::AShr:
2814 case Instruction::And:
2815 case Instruction::Or:
2816 case Instruction::Xor: {
2817 // Just widen unops and binops.
2819 for (VPValue *VPOp : operands())
2820 Ops.push_back(State.get(VPOp));
2821
2822 Value *V = Builder.CreateNAryOp(Opcode, Ops);
2823
2824 if (auto *VecOp = dyn_cast<Instruction>(V)) {
2825 applyFlags(*VecOp);
2826 applyMetadata(*VecOp);
2827 }
2828
2829 // Use this vector value for all users of the original instruction.
2830 State.set(this, V);
2831 break;
2832 }
2833 case Instruction::ExtractValue: {
2834 assert(getNumOperands() == 2 && "expected single level extractvalue");
2835 Value *Op = State.get(getOperand(0));
2836 Value *Extract = Builder.CreateExtractValue(
2837 Op, cast<VPConstantInt>(getOperand(1))->getZExtValue());
2838 State.set(this, Extract);
2839 break;
2840 }
2841 case Instruction::Freeze: {
2842 Value *Op = State.get(getOperand(0));
2843 Value *Freeze = Builder.CreateFreeze(Op);
2844 State.set(this, Freeze);
2845 break;
2846 }
2847 case Instruction::ICmp:
2848 case Instruction::FCmp: {
2849 // Widen compares. Generate vector compares.
2850 bool FCmp = Opcode == Instruction::FCmp;
2851 Value *A = State.get(getOperand(0));
2852 Value *B = State.get(getOperand(1));
2853 Value *C = nullptr;
2854 if (FCmp) {
2855 C = Builder.CreateFCmp(getPredicate(), A, B);
2856 } else {
2857 C = Builder.CreateICmp(getPredicate(), A, B);
2858 }
2859 if (auto *I = dyn_cast<Instruction>(C)) {
2860 applyFlags(*I);
2861 applyMetadata(*I);
2862 }
2863 State.set(this, C);
2864 break;
2865 }
2866 case Instruction::Select: {
2867 VPValue *CondOp = getOperand(0);
2868 Value *Cond = State.get(CondOp, vputils::isSingleScalar(CondOp));
2869 Value *Op0 = State.get(getOperand(1));
2870 Value *Op1 = State.get(getOperand(2));
2871 Value *Sel = State.Builder.CreateSelect(Cond, Op0, Op1);
2872 State.set(this, Sel);
2873 if (auto *I = dyn_cast<Instruction>(Sel)) {
2875 applyFlags(*I);
2876 applyMetadata(*I);
2877 }
2878 break;
2879 }
2880 default:
2881 // This instruction is not vectorized by simple widening.
2882 LLVM_DEBUG(dbgs() << "LV: Found an unhandled opcode : "
2883 << Instruction::getOpcodeName(Opcode));
2884 llvm_unreachable("Unhandled instruction!");
2885 } // end of switch.
2886
2887#if !defined(NDEBUG)
2888 // Verify that VPlan type inference results agree with the type of the
2889 // generated values.
2890 assert(VectorType::get(this->getScalarType(), State.VF) ==
2891 State.get(this)->getType() &&
2892 "inferred type and type from generated instructions do not match");
2893#endif
2894}
2895
2897 VPCostContext &Ctx) const {
2898 switch (Opcode) {
2899 case Instruction::UDiv:
2900 case Instruction::SDiv:
2901 case Instruction::SRem:
2902 case Instruction::URem:
2903 // If the div/rem operation isn't safe to speculate and requires
2904 // predication, then the only way we can even create a vplan is to insert
2905 // a select on the second input operand to ensure we use the value of 1
2906 // for the inactive lanes. The select will be costed separately.
2907 case Instruction::FNeg:
2908 case Instruction::Add:
2909 case Instruction::FAdd:
2910 case Instruction::Sub:
2911 case Instruction::FSub:
2912 case Instruction::Mul:
2913 case Instruction::FMul:
2914 case Instruction::FDiv:
2915 case Instruction::FRem:
2916 case Instruction::Shl:
2917 case Instruction::LShr:
2918 case Instruction::AShr:
2919 case Instruction::And:
2920 case Instruction::Or:
2921 case Instruction::Xor:
2922 case Instruction::Freeze:
2923 case Instruction::ExtractValue:
2924 case Instruction::ICmp:
2925 case Instruction::FCmp:
2926 case Instruction::Select:
2927 return getCostForRecipeWithOpcode(getOpcode(), VF, Ctx);
2928 default:
2929 llvm_unreachable("Unsupported opcode for instruction");
2930 }
2931}
2932
2933#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2935 VPSlotTracker &SlotTracker) const {
2936 O << Indent << "WIDEN ";
2938 O << " = " << Instruction::getOpcodeName(Opcode);
2939 printFlags(O);
2941}
2942#endif
2943
2945 auto &Builder = State.Builder;
2946 /// Vectorize casts.
2947 assert(State.VF.isVector() && "Not vectorizing?");
2948 Type *DestTy = VectorType::get(getScalarType(), State.VF);
2949 VPValue *Op = getOperand(0);
2950 Value *A = State.get(Op);
2951 Value *Cast = Builder.CreateCast(Instruction::CastOps(Opcode), A, DestTy);
2952 State.set(this, Cast);
2953 if (auto *CastOp = dyn_cast<Instruction>(Cast)) {
2954 applyFlags(*CastOp);
2955 applyMetadata(*CastOp);
2956 }
2957}
2958
2963
2964#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2966 VPSlotTracker &SlotTracker) const {
2967 O << Indent << "WIDEN-CAST ";
2969 O << " = " << Instruction::getOpcodeName(Opcode);
2970 printFlags(O);
2972 O << " to " << *getScalarType();
2973}
2974#endif
2975
2977 VPCostContext &Ctx) const {
2978 return Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
2979}
2980
2981#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2983 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
2984 O << Indent;
2986 O << " = WIDEN-INDUCTION";
2987 printFlags(O);
2989
2990 if (auto *TI = getTruncInst())
2991 O << " (truncated to " << *TI->getType() << ")";
2992}
2993#endif
2994
2996 // The step may be defined by a recipe in the preheader (e.g. if it requires
2997 // SCEV expansion), but for the canonical induction the step is required to be
2998 // 1, which is represented as live-in.
2999 return match(getStartValue(), m_ZeroInt()) &&
3000 match(getStepValue(), m_One()) &&
3001 getScalarType() == getRegion()->getCanonicalIVType();
3002}
3003
3006 VPCostContext &Ctx) const {
3007 // A widened induction generates a vector phi and increments it by the
3008 // splatted step each iteration.
3010 InstructionCost Cost = Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
3011 Type *StepTy = getScalarType();
3012 unsigned IncOpc = ID.getKind() == InductionDescriptor::IK_IntInduction
3013 ? Instruction::Add
3014 : ID.getInductionOpcode();
3015 assert(IncOpc != Instruction::BinaryOpsEnd &&
3016 "induction must have a valid increment opcode");
3017 return Cost + Ctx.TTI.getArithmeticInstrCost(IncOpc, toVectorTy(StepTy, VF),
3018 Ctx.CostKind);
3019}
3020
3022 VPCostContext &Ctx) const {
3023 // The cost model for this is modelled on expandVPDerivedIV in
3024 // VPlanTransforms.cpp. In order to avoid overly pessimistic costs that can
3025 // negatively affect vectorization it takes into account any expected
3026 // simplifications that happen in simplifyRecipe.
3027 switch (getInductionKind()) {
3028 default:
3029 // TODO: Compute cost for remaining kinds.
3030 break;
3032 // There are currently no tests that expose a path where all lanes are
3033 // used, so it's better to bail out for now.
3034 if (!vputils::onlyFirstLaneUsed(this))
3035 break;
3036
3037 // Start off by assuming we need both mul and add, then refine this.
3038 bool NeedsMul = true, NeedsAdd = true, NeedsShl = false;
3039
3040 // If the start value is zero the add gets folded away.
3041 if (auto *StartC = dyn_cast<VPConstantInt>(getStartValue()))
3042 NeedsAdd = !StartC->isZero();
3043
3044 // For some values of step the arithmetic changes:
3045 // 1. A step of 1 requires no operation.
3046 // 2. A step of -1 requires a negate.
3047 // 3. A power-of-2 step will use a shl, instead of a mul.
3048 Type *StepTy = getStepValue()->getScalarType();
3050 if (auto *StepC = dyn_cast<VPConstantInt>(getStepValue())) {
3051 if (StepC->isOne())
3052 NeedsMul = false;
3053 else if (StepC->getAPInt().isAllOnes()) {
3054 // This will most likely end up as a negate in simplifyRecipe, and
3055 // the negate will be combined with the add to make a sub.
3056 // NOTE: This is perhaps an invalid assumption that the cost of an
3057 // 'add' is the same as a 'sub'.
3058 NeedsMul = false;
3059 NeedsAdd = true;
3060 } else if (StepC->getAPInt().isPowerOf2()) {
3061 // This will most likely end up as a shift-left in simplifyRecipe
3062 NeedsMul = false;
3063 NeedsShl = true;
3064 }
3065 }
3066
3067 // Add the cost of the conversion from index to step type if the index
3068 // will be used.
3069 Type *IndexTy = getIndex()->getScalarType();
3070 unsigned StepTySize = StepTy->getScalarSizeInBits();
3071 unsigned IndexTySize = IndexTy->getScalarSizeInBits();
3072 if ((NeedsAdd || NeedsMul || NeedsShl) && StepTySize != IndexTySize) {
3073 unsigned CastOpc =
3074 StepTySize < IndexTySize ? Instruction::Trunc : Instruction::ZExt;
3075 Cost += Ctx.TTI.getCastInstrCost(
3076 CastOpc, StepTy, IndexTy, TTI::CastContextHint::None, Ctx.CostKind);
3077 }
3078
3079 if (NeedsMul)
3080 Cost += Ctx.TTI.getArithmeticInstrCost(Instruction::Mul, StepTy,
3081 Ctx.CostKind);
3082 if (NeedsShl)
3083 Cost += Ctx.TTI.getArithmeticInstrCost(
3084 Instruction::Shl, StepTy, Ctx.CostKind,
3085 {TargetTransformInfo::OK_AnyValue, TargetTransformInfo::OP_None},
3086 {TargetTransformInfo::OK_UniformConstantValue,
3087 TargetTransformInfo::OP_None});
3088 if (NeedsAdd)
3089 Cost += Ctx.TTI.getArithmeticInstrCost(Instruction::Add, StepTy,
3090 Ctx.CostKind);
3091 return Cost;
3092 }
3093 }
3094
3095 return 0;
3096}
3097
3098#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3100 VPSlotTracker &SlotTracker) const {
3101 O << Indent;
3103 O << " = DERIVED-IV";
3104 printFlags(O);
3105 getStartValue()->printAsOperand(O, SlotTracker);
3106 O << " + ";
3107 getOperand(1)->printAsOperand(O, SlotTracker);
3108 O << " * ";
3109 getStepValue()->printAsOperand(O, SlotTracker);
3110}
3111#endif
3112
3116
3118 VPCostContext &Ctx) const {
3119 // TODO: Add costs for floating point.
3120 Type *BaseIVTy = getOperand(0)->getScalarType();
3121 if (!BaseIVTy->isIntegerTy())
3122 return 0;
3123
3124 // TODO: Add support for predicated regions. Requires scaling the cost by the
3125 // probability of entering the block.
3126 if (getRegion() && getRegion()->isReplicator())
3127 return 0;
3128
3129 // If only the first lane is used, then there won't be any code that remains
3130 // in the loop for the first unrolled part.
3132 return 0;
3133
3134 // Typically the operations are:
3135 // 1. Add the start index to each lane value.
3136 // 2. Multiply the start index by the step.
3137 // 3. Add the scaled start index to base IV.
3138 // Any code generated for 1 and 2 should be loop invariant and therefore
3139 // hoisted out of the loop. We only need to add on the cost of 3.
3140
3141 // Given the users of VPScalarIVStepsRecipe tend to be scalarized GEPs, i.e.
3142 // %add1 = add i32 %iv, 0
3143 // %add2 = add i32 %iv, 1
3144 // %gep1 = getelementptr i8, ptr %p, i32 %add1
3145 // %gep2 = getelementptr i8, ptr %p, i32 %add2
3146 // it's very likely that these GEPs will all be rewritten to have a common
3147 // base such that what's left is just
3148 // %base_gep = getelementptr i8, ptr %p, i32 %iv
3149 // %gep1 = getelementptr i8, ptr %base_gep, i32 0
3150 // %gep2 = getelementptr i8, ptr %base_gep, i32 1
3151 // Therefore, in reality the cost is somewhere betwen 1*AddCost and
3152 // (NumLanes - 1) * AddCost. For now, assume the cost of a single add.
3153 return Ctx.TTI.getArithmeticInstrCost(Instruction::Add, BaseIVTy,
3154 Ctx.CostKind);
3155}
3156
3158 // Fast-math-flags propagate from the original induction instruction.
3159 IRBuilder<>::FastMathFlagGuard FMFG(State.Builder);
3160 State.Builder.setFastMathFlags(getFastMathFlagsOrNone());
3161
3162 /// Compute scalar induction steps. \p ScalarIV is the scalar induction
3163 /// variable on which to base the steps, \p Step is the size of the step.
3164
3165 Value *BaseIV = State.get(getOperand(0), VPLane(0));
3166 Value *Step = State.get(getStepValue(), VPLane(0));
3167 IRBuilderBase &Builder = State.Builder;
3168
3169 // Ensure step has the same type as that of scalar IV.
3170 Type *BaseIVTy = BaseIV->getType()->getScalarType();
3171 assert(BaseIVTy == Step->getType() && "Types of BaseIV and Step must match!");
3172
3173 // We build scalar steps for both integer and floating-point induction
3174 // variables. Here, we determine the kind of arithmetic we will perform.
3177 if (BaseIVTy->isIntegerTy()) {
3178 AddOp = Instruction::Add;
3179 MulOp = Instruction::Mul;
3180 } else {
3181 AddOp = InductionOpcode;
3182 MulOp = Instruction::FMul;
3183 }
3184
3185 // Determine the number of scalars we need to generate.
3186 bool FirstLaneOnly = vputils::onlyFirstLaneUsed(this);
3187 // Compute the scalar steps and save the results in State.
3188
3189 unsigned EndLane = FirstLaneOnly ? 1 : State.VF.getKnownMinValue();
3190 Value *StartIdx0 = getStartIndex() ? State.get(getStartIndex(), true)
3191 : Constant::getNullValue(BaseIVTy);
3192
3193 for (unsigned Lane = 0; Lane < EndLane; ++Lane) {
3194 // It is okay if the induction variable type cannot hold the lane number,
3195 // we expect truncation in this case.
3196 Constant *LaneValue =
3197 BaseIVTy->isIntegerTy()
3198 ? ConstantInt::get(BaseIVTy, Lane, /*IsSigned=*/false,
3199 /*ImplicitTrunc=*/true)
3200 : ConstantFP::get(BaseIVTy, Lane);
3201 Value *StartIdx = Builder.CreateBinOp(AddOp, StartIdx0, LaneValue);
3202 assert((State.VF.isScalable() || isa<Constant>(StartIdx)) &&
3203 "Expected StartIdx to be folded to a constant when VF is not "
3204 "scalable");
3205 auto *Mul = Builder.CreateBinOp(MulOp, StartIdx, Step);
3206 auto *Add = Builder.CreateBinOp(AddOp, BaseIV, Mul);
3207 State.set(this, Add, VPLane(Lane));
3208 }
3209}
3210
3211#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3213 VPSlotTracker &SlotTracker) const {
3214 O << Indent;
3216 O << " = SCALAR-STEPS ";
3218}
3219#endif
3220
3222 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
3224}
3225
3227 assert(State.VF.isVector() && "not widening");
3228 auto Ops = map_to_vector(operands(), [&](VPValue *Op) {
3229 return State.get(Op, vputils::isSingleScalar(Op));
3230 });
3231 auto *GEP =
3232 State.Builder.CreateGEP(getSourceElementType(), Ops.front(),
3233 drop_begin(Ops), "wide.gep", getGEPNoWrapFlags());
3234 State.set(this, GEP, vputils::isSingleScalar(this));
3235}
3236
3237#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3239 VPSlotTracker &SlotTracker) const {
3240 O << Indent << "WIDEN-GEP ";
3242 O << " = getelementptr";
3243 printFlags(O);
3245}
3246#endif
3247
3249 assert(!getOffset() && "Unexpected offset operand");
3250 VPBuilder Builder(this);
3251 VPlan &Plan = *getParent()->getPlan();
3252 VPValue *VFVal = getVFValue();
3253 const DataLayout &DL = Plan.getDataLayout();
3254 Type *IndexTy = DL.getIndexType(this->getScalarType());
3255 VPValue *Stride =
3256 Plan.getConstantInt(IndexTy, getStride(), /*IsSigned=*/true);
3257 VPValue *VF =
3258 Builder.createScalarZExtOrTrunc(VFVal, IndexTy, DebugLoc::getUnknown());
3259
3260 // Offset for Part0 = Offset0 = Stride * (VF - 1).
3261 VPInstruction *VFMinusOne =
3262 Builder.createSub(VF, Plan.getConstantInt(IndexTy, 1u),
3263 DebugLoc::getUnknown(), "", {true, true});
3264 VPInstruction *Offset0 =
3265 Builder.createOverflowingOp(Instruction::Mul, {VFMinusOne, Stride});
3266
3267 // Offset for PartN = Offset0 + Part * Stride * VF.
3268 VPValue *PartxStride =
3269 Plan.getConstantInt(IndexTy, Part * getStride(), /*IsSigned=*/true);
3270 VPValue *Offset = Builder.createAdd(
3271 Offset0,
3272 Builder.createOverflowingOp(Instruction::Mul, {PartxStride, VF}));
3274}
3275
3277 auto &Builder = State.Builder;
3278 assert(getOffset() && "Expected prior materialization of offset");
3279 Value *Ptr = State.get(getPointer(), true);
3280 Value *Offset = State.get(getOffset(), true);
3281 Value *ResultPtr = Builder.CreateGEP(getSourceElementType(), Ptr, Offset, "",
3283 State.set(this, ResultPtr, /*IsScalar*/ true);
3284}
3285
3286#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3288 VPSlotTracker &SlotTracker) const {
3289 O << Indent;
3291 O << " = vector-end-pointer";
3292 printFlags(O);
3293 getSourceElementType()->print(O);
3294 O << ", ";
3296}
3297#endif
3298
3300 assert(getVFxPart() &&
3301 "Expected prior simplification of recipe without VFxPart");
3302
3303 auto &Builder = State.Builder;
3304 Value *Ptr = State.get(getOperand(0), VPLane(0));
3305 Value *Offset = State.get(getVFxPart(), true);
3306 // TODO: Expand to VPInstruction to support constant folding.
3307 if (!match(getStride(), m_One())) {
3308 Value *Stride = Builder.CreateZExtOrTrunc(State.get(getStride(), true),
3309 Offset->getType());
3310 Offset = Builder.CreateMul(Offset, Stride);
3311 }
3312 Value *ResultPtr = Builder.CreateGEP(getSourceElementType(), Ptr, Offset, "",
3314 State.set(this, ResultPtr, /*IsScalar*/ true);
3315}
3316
3317#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3319 VPSlotTracker &SlotTracker) const {
3320 O << Indent;
3322 O << " = vector-pointer";
3323 printFlags(O);
3324 getSourceElementType()->print(O);
3325 O << ", ";
3327}
3328#endif
3329
3331 VPCostContext &Ctx) const {
3332 // A blend will be expanded to a select VPInstruction, which will generate a
3333 // scalar select if only the first lane is used.
3335 VF = ElementCount::getFixed(1);
3336
3337 Type *ResultTy = toVectorTy(this->getScalarType(), VF);
3338 Type *CmpTy = toVectorTy(Type::getInt1Ty(Ctx.LLVMCtx), VF);
3339 return (getNumIncomingValues() - 1) *
3340 Ctx.TTI.getCmpSelInstrCost(Instruction::Select, ResultTy, CmpTy,
3341 CmpInst::BAD_ICMP_PREDICATE, Ctx.CostKind);
3342}
3343
3344#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3346 VPSlotTracker &SlotTracker) const {
3347 O << Indent << "BLEND ";
3349 O << " =";
3350 printFlags(O);
3351 if (getNumIncomingValues() == 1) {
3352 // Not a User of any mask: not really blending, this is a
3353 // single-predecessor phi.
3354 getIncomingValue(0)->printAsOperand(O, SlotTracker);
3355 } else {
3356 for (unsigned I = 0, E = getNumIncomingValues(); I < E; ++I) {
3357 if (I != 0)
3358 O << " ";
3359 getIncomingValue(I)->printAsOperand(O, SlotTracker);
3360 if (I == 0 && isNormalized())
3361 continue;
3362 O << "/";
3363 getMask(I)->printAsOperand(O, SlotTracker);
3364 }
3365 }
3366}
3367#endif
3368
3372 "In-loop AnyOf reductions aren't currently supported");
3373 // Propagate the fast-math flags carried by the underlying instruction.
3374 IRBuilderBase::FastMathFlagGuard FMFGuard(State.Builder);
3375 State.Builder.setFastMathFlags(getFastMathFlagsOrNone());
3376 Value *NewVecOp = State.get(getVecOp());
3377 if (VPValue *Cond = getCondOp()) {
3378 Value *NewCond = State.get(Cond, State.VF.isScalar());
3379 VectorType *VecTy = dyn_cast<VectorType>(NewVecOp->getType());
3380 Type *ElementTy = VecTy ? VecTy->getElementType() : NewVecOp->getType();
3381
3382 Value *Start =
3384 if (State.VF.isVector())
3385 Start = State.Builder.CreateVectorSplat(VecTy->getElementCount(), Start);
3386
3387 Value *Select = State.Builder.CreateSelect(NewCond, NewVecOp, Start);
3388 NewVecOp = Select;
3389 }
3390 Value *NewRed;
3391 Value *NextInChain;
3392 if (isOrdered()) {
3393 Value *PrevInChain = State.get(getChainOp(), /*IsScalar*/ true);
3394 if (State.VF.isVector())
3395 NewRed =
3396 createOrderedReduction(State.Builder, Kind, NewVecOp, PrevInChain);
3397 else
3398 NewRed = State.Builder.CreateBinOp(
3400 PrevInChain, NewVecOp);
3401 PrevInChain = NewRed;
3402 NextInChain = NewRed;
3403 } else if (isPartialReduction()) {
3404 assert((Kind == RecurKind::Add || Kind == RecurKind::FAdd) &&
3405 "Unexpected partial reduction kind");
3406 Value *PrevInChain = State.get(getChainOp(), /*IsScalar*/ false);
3407 NewRed = State.Builder.CreateIntrinsic(
3408 PrevInChain->getType(),
3409 Kind == RecurKind::Add ? Intrinsic::vector_partial_reduce_add
3410 : Intrinsic::vector_partial_reduce_fadd,
3411 {PrevInChain, NewVecOp}, State.Builder.getFastMathFlags(),
3412 "partial.reduce");
3413 PrevInChain = NewRed;
3414 NextInChain = NewRed;
3415 } else {
3416 assert(isInLoop() &&
3417 "The reduction must either be ordered, partial or in-loop");
3418 Value *PrevInChain = State.get(getChainOp(), /*IsScalar*/ true);
3419 NewRed = createSimpleReduction(State.Builder, NewVecOp, Kind);
3421 NextInChain = createMinMaxOp(State.Builder, Kind, NewRed, PrevInChain);
3422 else
3423 NextInChain = State.Builder.CreateBinOp(
3425 PrevInChain, NewRed);
3426 }
3427 State.set(this, NextInChain, /*IsScalar*/ !isPartialReduction());
3428}
3429
3431
3432 auto &Builder = State.Builder;
3433 // Propagate the fast-math flags carried by the underlying instruction.
3434 IRBuilderBase::FastMathFlagGuard FMFGuard(Builder);
3435 Builder.setFastMathFlags(getFastMathFlagsOrNone());
3436
3438 Value *Prev = State.get(getChainOp(), /*IsScalar*/ true);
3439 Value *VecOp = State.get(getVecOp());
3440 Value *EVL = State.get(getEVL(), VPLane(0));
3441
3442 Value *Mask;
3443 if (VPValue *CondOp = getCondOp())
3444 Mask = State.get(CondOp);
3445 else
3446 Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue());
3447
3448 Value *NewRed;
3449 if (isOrdered()) {
3450 NewRed = createOrderedReduction(Builder, Kind, VecOp, Prev, Mask, EVL);
3451 } else {
3452 NewRed = createSimpleReduction(Builder, VecOp, Kind, Mask, EVL);
3454 NewRed = createMinMaxOp(Builder, Kind, NewRed, Prev);
3455 else
3456 NewRed = Builder.CreateBinOp(
3458 Prev);
3459 }
3460 State.set(this, NewRed, /*IsScalar*/ true);
3461}
3462
3464 VPCostContext &Ctx) const {
3465 RecurKind RdxKind = getRecurrenceKind();
3466 Type *ElementTy = this->getScalarType();
3467 auto *VectorTy = cast<VectorType>(toVectorTy(ElementTy, VF));
3468 unsigned Opcode = RecurrenceDescriptor::getOpcode(RdxKind);
3470 std::optional<FastMathFlags> OptionalFMF =
3471 ElementTy->isFloatingPointTy() ? std::make_optional(FMFs) : std::nullopt;
3472
3473 if (isPartialReduction()) {
3474 InstructionCost CondCost = 0;
3475 if (isConditional()) {
3477 auto *CondTy =
3479 CondCost = Ctx.TTI.getCmpSelInstrCost(Instruction::Select, VectorTy,
3480 CondTy, Pred, Ctx.CostKind);
3481 }
3482 return CondCost + Ctx.TTI.getPartialReductionCost(
3483 Opcode, ElementTy, ElementTy, ElementTy, VF,
3484 TTI::PR_None, TTI::PR_None, {}, Ctx.CostKind,
3485 OptionalFMF);
3486 }
3487
3488 // TODO: Support any-of reductions.
3489 assert(
3491 ForceTargetInstructionCost.getNumOccurrences() > 0) &&
3492 "Any-of reduction not implemented in VPlan-based cost model currently.");
3493
3494 // Note that TTI should model the cost of moving result to the scalar register
3495 // and the BinOp cost in the getMinMaxReductionCost().
3498 return Ctx.TTI.getMinMaxReductionCost(Id, VectorTy, FMFs, Ctx.CostKind);
3499 }
3500
3501 // Note that TTI should model the cost of moving result to the scalar register
3502 // and the BinOp cost in the getArithmeticReductionCost().
3503 return Ctx.TTI.getArithmeticReductionCost(Opcode, VectorTy, OptionalFMF,
3504 Ctx.CostKind);
3505}
3506
3507VPExpressionRecipe::VPExpressionRecipe(
3508 ExpressionTypes ExpressionType,
3509 ArrayRef<VPSingleDefRecipe *> ExpressionRecipes)
3510 : VPSingleDefRecipe(VPRecipeBase::VPExpressionSC, {},
3511 cast<VPReductionRecipe>(ExpressionRecipes.back())
3512 ->getChainOp()
3513 ->getScalarType()),
3514 ExpressionRecipes(ExpressionRecipes), ExpressionType(ExpressionType) {
3515 assert(!ExpressionRecipes.empty() && "Nothing to combine?");
3516 assert(
3517 none_of(ExpressionRecipes,
3518 [](VPSingleDefRecipe *R) { return R->mayHaveSideEffects(); }) &&
3519 "expression cannot contain recipes with side-effects");
3520
3521 // Maintain a copy of the expression recipes as a set of users.
3522 SmallPtrSet<VPUser *, 4> ExpressionRecipesAsSetOfUsers;
3523 for (auto *R : ExpressionRecipes)
3524 ExpressionRecipesAsSetOfUsers.insert(R);
3525
3526 // Recipes in the expression, except the last one, must only be used by
3527 // (other) recipes inside the expression. If there are other users, external
3528 // to the expression, use a clone of the recipe for external users.
3529 for (VPSingleDefRecipe *R : reverse(ExpressionRecipes)) {
3530 if (R != ExpressionRecipes.back() &&
3531 any_of(R->users(), [&ExpressionRecipesAsSetOfUsers](VPUser *U) {
3532 return !ExpressionRecipesAsSetOfUsers.contains(U);
3533 })) {
3534 // There are users outside of the expression. Clone the recipe and use the
3535 // clone those external users.
3536 VPSingleDefRecipe *CopyForExtUsers = R->clone();
3537 R->replaceUsesWithIf(CopyForExtUsers, [&ExpressionRecipesAsSetOfUsers](
3538 VPUser &U, unsigned) {
3539 return !ExpressionRecipesAsSetOfUsers.contains(&U);
3540 });
3541 CopyForExtUsers->insertBefore(R);
3542 }
3543 if (R->getParent())
3544 R->removeFromParent();
3545 }
3546
3547 // Internalize all external operands to the expression recipes. To do so,
3548 // create new temporary VPValues for all operands defined by a recipe outside
3549 // the expression. The original operands are added as operands of the
3550 // VPExpressionRecipe itself.
3551 for (auto *R : ExpressionRecipes) {
3552 for (const auto &[Idx, Op] : enumerate(R->operands())) {
3553 auto *Def = Op->getDefiningRecipe();
3554 if (Def && ExpressionRecipesAsSetOfUsers.contains(Def))
3555 continue;
3556 addOperand(Op);
3557 LiveInPlaceholders.push_back(new VPSymbolicValue(Op->getScalarType()));
3558 }
3559 }
3560
3561 // Replace each external operand with the first one created for it in
3562 // LiveInPlaceholders.
3563 for (auto *R : ExpressionRecipes)
3564 for (auto const &[LiveIn, Tmp] : zip(operands(), LiveInPlaceholders))
3565 R->replaceUsesOfWith(LiveIn, Tmp);
3566}
3567
3569 for (auto *R : ExpressionRecipes)
3570 // Since the list could contain duplicates, make sure the recipe hasn't
3571 // already been inserted.
3572 if (!R->getParent())
3573 R->insertBefore(this);
3574
3575 for (const auto &[Idx, Op] : enumerate(operands()))
3576 LiveInPlaceholders[Idx]->replaceAllUsesWith(Op);
3577
3578 replaceAllUsesWith(ExpressionRecipes.back());
3579 ExpressionRecipes.clear();
3580}
3581
3583 VPCostContext &Ctx) const {
3584 Type *RedTy = this->getScalarType();
3585 auto *SrcVecTy =
3587 unsigned Opcode = RecurrenceDescriptor::getOpcode(
3588 cast<VPReductionRecipe>(ExpressionRecipes.back())->getRecurrenceKind());
3589 switch (ExpressionType) {
3590 case ExpressionTypes::NegatedExtendedReduction:
3591 assert((Opcode == Instruction::Add || Opcode == Instruction::FAdd) &&
3592 "Unexpected opcode");
3593 Opcode = Opcode == Instruction::Add ? Instruction::Sub : Instruction::FSub;
3594 [[fallthrough]];
3595 case ExpressionTypes::ExtendedReduction: {
3596 auto *RedR = cast<VPReductionRecipe>(ExpressionRecipes.back());
3597 auto *ExtR = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3598
3599 if (RedR->isPartialReduction())
3600 return Ctx.TTI.getPartialReductionCost(
3601 Opcode, getOperand(0)->getScalarType(), nullptr, RedTy, VF,
3603 TargetTransformInfo::PR_None, std::nullopt, Ctx.CostKind,
3604 RedTy->isFloatingPointTy()
3605 ? std::optional{RedR->getFastMathFlagsOrNone()}
3606 : std::nullopt);
3607 else if (!RedTy->isFloatingPointTy())
3608 // TTI::getExtendedReductionCost only supports integer types.
3609 return Ctx.TTI.getExtendedReductionCost(
3610 Opcode, ExtR->getOpcode() == Instruction::ZExt, RedTy, SrcVecTy,
3611 std::nullopt, Ctx.CostKind);
3612 else
3614 }
3615 case ExpressionTypes::MulAccReduction:
3616 return Ctx.TTI.getMulAccReductionCost(false, Opcode, RedTy, SrcVecTy,
3617 Ctx.CostKind);
3618
3619 case ExpressionTypes::ExtNegatedMulAccReduction:
3620 switch (Opcode) {
3621 case Instruction::Add:
3622 Opcode = Instruction::Sub;
3623 break;
3624 case Instruction::FAdd:
3625 Opcode = Instruction::FSub;
3626 break;
3627 default:
3628 llvm_unreachable("Unsupported opcode for ExtNegatedMulAccReduction");
3629 }
3630 [[fallthrough]];
3631 case ExpressionTypes::ExtMulAccReduction: {
3632 auto *RedR = cast<VPReductionRecipe>(ExpressionRecipes.back());
3633 if (RedR->isPartialReduction()) {
3634 auto *Ext0R = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3635 auto *Ext1R = cast<VPWidenCastRecipe>(ExpressionRecipes[1]);
3636 auto *Mul = cast<VPWidenRecipe>(ExpressionRecipes[2]);
3637 return Ctx.TTI.getPartialReductionCost(
3638 Opcode, getOperand(0)->getScalarType(),
3639 getOperand(1)->getScalarType(), RedTy, VF,
3641 Ext0R->getOpcode()),
3643 Ext1R->getOpcode()),
3644 Mul->getOpcode(), Ctx.CostKind,
3645 RedTy->isFloatingPointTy()
3646 ? std::optional{RedR->getFastMathFlagsOrNone()}
3647 : std::nullopt);
3648 }
3649 assert(Opcode != Instruction::FSub && "Only integer types are supported");
3650 return Ctx.TTI.getMulAccReductionCost(
3651 cast<VPWidenCastRecipe>(ExpressionRecipes.front())->getOpcode() ==
3652 Instruction::ZExt,
3653 Opcode, RedTy, SrcVecTy, Ctx.CostKind);
3654 }
3655 }
3656 llvm_unreachable("Unknown VPExpressionRecipe::ExpressionTypes enum");
3657}
3658
3660 return any_of(ExpressionRecipes, [](VPSingleDefRecipe *R) {
3661 return R->mayReadFromMemory() || R->mayWriteToMemory();
3662 });
3663}
3664
3666 assert(
3667 none_of(ExpressionRecipes,
3668 [](VPSingleDefRecipe *R) { return R->mayHaveSideEffects(); }) &&
3669 "expression cannot contain recipes with side-effects");
3670 return false;
3671}
3672
3674 auto *RR = dyn_cast<VPReductionRecipe>(ExpressionRecipes.back());
3675 return RR && !RR->isPartialReduction();
3676}
3677
3678#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3679
3681 VPSlotTracker &SlotTracker) const {
3682 O << Indent << "EXPRESSION ";
3684 O << " = ";
3685 auto *Red = cast<VPReductionRecipe>(ExpressionRecipes.back());
3686 unsigned Opcode = RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind());
3687 VPValue *RdxStart =
3688 getOperand(getNumOperands() - (Red->isConditional() ? 2 : 1));
3689
3690 switch (ExpressionType) {
3691 case ExpressionTypes::NegatedExtendedReduction:
3692 case ExpressionTypes::ExtendedReduction: {
3693 bool Negated = ExpressionType == ExpressionTypes::NegatedExtendedReduction;
3695 O << " + " << (Red->isPartialReduction() ? "partial." : "") << "reduce.";
3696 O << Instruction::getOpcodeName(Opcode) << " (";
3697 if (Negated)
3698 O << (Opcode == Instruction::Add ? "sub (0, " : "fneg(");
3700 if (Negated)
3701 O << ")";
3702 Red->printFlags(O);
3703
3704 auto *Ext0 = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3705 O << Instruction::getOpcodeName(Ext0->getOpcode()) << " to "
3706 << *Ext0->getScalarType();
3707 if (Red->isConditional()) {
3708 O << ", ";
3710 }
3711 O << ")";
3712 break;
3713 }
3714 case ExpressionTypes::ExtNegatedMulAccReduction: {
3715 RdxStart->printAsOperand(O, SlotTracker);
3716 O << " + " << (Red->isPartialReduction() ? "partial." : "") << "reduce.";
3718 RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind()))
3719 << " (sub (0, mul";
3720 auto *Mul = cast<VPWidenRecipe>(ExpressionRecipes[2]);
3721 Mul->printFlags(O);
3722 O << "(";
3724 auto *Ext0 = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3725 O << " " << Instruction::getOpcodeName(Ext0->getOpcode()) << " to "
3726 << *Ext0->getScalarType() << "), (";
3728 auto *Ext1 = cast<VPWidenCastRecipe>(ExpressionRecipes[1]);
3729 O << " " << Instruction::getOpcodeName(Ext1->getOpcode()) << " to "
3730 << *Ext1->getScalarType() << ")";
3731 if (Red->isConditional()) {
3732 O << ", ";
3734 }
3735 O << "))";
3736 break;
3737 }
3738 case ExpressionTypes::MulAccReduction:
3739 case ExpressionTypes::ExtMulAccReduction: {
3740 RdxStart->printAsOperand(O, SlotTracker);
3741 O << " + " << (Red->isPartialReduction() ? "partial." : "") << "reduce.";
3743 RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind()))
3744 << " (";
3745 O << "mul";
3746 bool IsExtended = ExpressionType == ExpressionTypes::ExtMulAccReduction;
3747 auto *Mul = cast<VPWidenRecipe>(IsExtended ? ExpressionRecipes[2]
3748 : ExpressionRecipes[0]);
3749 Mul->printFlags(O);
3750 if (IsExtended)
3751 O << "(";
3753 if (IsExtended) {
3754 auto *Ext0 = cast<VPWidenCastRecipe>(ExpressionRecipes[0]);
3755 O << " " << Instruction::getOpcodeName(Ext0->getOpcode()) << " to "
3756 << *Ext0->getScalarType() << "), (";
3757 } else {
3758 O << ", ";
3759 }
3761 if (IsExtended) {
3762 auto *Ext1 = cast<VPWidenCastRecipe>(ExpressionRecipes[1]);
3763 O << " " << Instruction::getOpcodeName(Ext1->getOpcode()) << " to "
3764 << *Ext1->getScalarType() << ")";
3765 }
3766 if (Red->isConditional()) {
3767 O << ", ";
3769 }
3770 O << ")";
3771 break;
3772 }
3773 }
3774}
3775
3777 VPSlotTracker &SlotTracker) const {
3778 if (isPartialReduction())
3779 O << Indent << "PARTIAL-REDUCE ";
3780 else
3781 O << Indent << "REDUCE ";
3783 O << " = ";
3785 O << " +";
3786 printFlags(O);
3787 O << " reduce.";
3789 O << " (";
3791 if (isConditional()) {
3792 O << ", ";
3794 }
3795 O << ")";
3796}
3797
3799 VPSlotTracker &SlotTracker) const {
3800 O << Indent << "REDUCE ";
3802 O << " = ";
3804 O << " +";
3805 printFlags(O);
3806 O << " vp.reduce."
3809 << " (";
3811 O << ", ";
3813 if (isConditional()) {
3814 O << ", ";
3816 }
3817 O << ")";
3818}
3819
3820#endif
3821
3823 assert(IsSingleScalar &&
3824 "VPReplicateRecipes must be unrolled before ::execute");
3825 auto *Instr = getUnderlyingInstr();
3826 Instruction *Cloned = Instr->clone();
3827 Type *ResultTy = getScalarType();
3828 if (!ResultTy->isVoidTy()) {
3829 Cloned->setName(Instr->getName() + ".cloned");
3830 // The operands of the replicate recipe may have been narrowed, resulting in
3831 // a narrower result type. Update the type of the cloned instruction to the
3832 // correct type.
3833 if (ResultTy != Cloned->getType())
3834 Cloned->mutateType(ResultTy);
3835 }
3836
3837 applyFlags(*Cloned);
3838 applyMetadata(*Cloned);
3839
3840 if (hasPredicate())
3841 cast<CmpInst>(Cloned)->setPredicate(getPredicate());
3842
3843 // Replace the operands of the cloned instructions with their scalar
3844 // equivalents in the new loop.
3845 for (const auto &[Idx, V] : enumerate(operands()))
3846 Cloned->setOperand(Idx, State.get(V, true));
3847
3848 // Place the cloned scalar in the new loop.
3849 State.Builder.Insert(Cloned);
3850
3851 State.set(this, Cloned, true);
3852
3853 // If we just cloned a new assumption, add it the assumption cache.
3854 if (auto *II = dyn_cast<AssumeInst>(Cloned))
3855 State.AC->registerAssumption(II);
3856}
3857
3858/// Returns a SCEV expression for \p Ptr if it is a pointer computation for
3859/// which the legacy cost model computes a SCEV expression when computing the
3860/// address cost. Computing SCEVs for VPValues is incomplete and returns
3861/// SCEVCouldNotCompute in cases the legacy cost model can compute SCEVs. In
3862/// those cases we fall back to the legacy cost model. Otherwise return nullptr.
3863static const SCEV *getAddressAccessSCEV(const VPValue *Ptr,
3865 const Loop *L) {
3866 const SCEV *Addr = vputils::getSCEVExprForVPValue(Ptr, PSE, L);
3867 if (isa<SCEVCouldNotCompute>(Addr))
3868 return Addr;
3869
3870 return vputils::isAddressSCEVForCost(Addr, *PSE.getSE(), L) ? Addr : nullptr;
3871}
3872
3874 VPCostContext &Ctx) const {
3876 // VPReplicateRecipe may be cloned as part of an existing VPlan-to-VPlan
3877 // transform, avoid computing their cost multiple times for now.
3878 Ctx.SkipCostComputation.insert(UI);
3879
3880 if (VF.isScalable() && !isSingleScalar())
3882
3883 switch (UI->getOpcode()) {
3884 case Instruction::Alloca:
3885 if (VF.isScalable())
3887 return Ctx.TTI.getArithmeticInstrCost(Instruction::Mul,
3888 this->getScalarType(), Ctx.CostKind);
3889 case Instruction::GetElementPtr:
3890 // We mark this instruction as zero-cost because the cost of GEPs in
3891 // vectorized code depends on whether the corresponding memory instruction
3892 // is scalarized or not. Therefore, we handle GEPs with the memory
3893 // instruction cost.
3894 return 0;
3895 case Instruction::Call: {
3896 auto *CalledFn =
3898 Type *ResultTy = this->getScalarType();
3899 return computeCallCost(CalledFn, ResultTy, drop_end(operands()),
3900 isSingleScalar(), VF, Ctx);
3901 }
3902 case Instruction::Add:
3903 case Instruction::Sub:
3904 case Instruction::FAdd:
3905 case Instruction::FSub:
3906 case Instruction::Mul:
3907 case Instruction::FMul:
3908 case Instruction::FDiv:
3909 case Instruction::FRem:
3910 case Instruction::Shl:
3911 case Instruction::LShr:
3912 case Instruction::AShr:
3913 case Instruction::And:
3914 case Instruction::Or:
3915 case Instruction::Xor:
3916 case Instruction::ICmp:
3917 case Instruction::FCmp:
3919 Ctx) *
3920 (isSingleScalar() ? 1 : VF.getFixedValue());
3921 case Instruction::SDiv:
3922 case Instruction::UDiv:
3923 case Instruction::SRem:
3924 case Instruction::URem: {
3925 InstructionCost ScalarCost =
3927 if (isSingleScalar())
3928 return ScalarCost;
3929
3930 // If any of the operands is from a different replicate region and has its
3931 // cost skipped, it may have been forced to scalar. Fall back to legacy cost
3932 // model to avoid cost mis-match.
3933 if (any_of(operands(), [&Ctx, VF](VPValue *Op) {
3934 auto *PredR = dyn_cast<VPPredInstPHIRecipe>(Op);
3935 if (!PredR)
3936 return false;
3937 return Ctx.skipCostComputation(
3939 PredR->getOperand(0)->getUnderlyingValue()),
3940 VF.isVector());
3941 }))
3942 break;
3943
3944 ScalarCost = ScalarCost * VF.getFixedValue() +
3945 Ctx.getScalarizationOverhead(this->getScalarType(),
3946 to_vector(operands()), VF);
3947 // If the recipe is not predicated (i.e. not in a replicate region), return
3948 // the scalar cost. Otherwise handle predicated cost.
3949 if (!getRegion()->isReplicator())
3950 return ScalarCost;
3951
3952 // Account for the phi nodes that we will create.
3953 ScalarCost += VF.getFixedValue() *
3954 Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
3955 // Scale the cost by the probability of executing the predicated blocks.
3956 // This assumes the predicated block for each vector lane is equally
3957 // likely.
3958 ScalarCost /= Ctx.getPredBlockCostDivisor(UI->getParent());
3959 return ScalarCost;
3960 }
3961 case Instruction::Load:
3962 case Instruction::Store: {
3963 bool IsLoad = UI->getOpcode() == Instruction::Load;
3964 const VPValue *PtrOp = getOperand(!IsLoad);
3965 const SCEV *PtrSCEV = getAddressAccessSCEV(PtrOp, Ctx.PSE, Ctx.L);
3967 break;
3968
3969 Type *ValTy = (IsLoad ? this : getOperand(0))->getScalarType();
3970 Type *ScalarPtrTy = PtrOp->getScalarType();
3971 const Align Alignment = getLoadStoreAlignment(UI);
3972 unsigned AS = cast<PointerType>(ScalarPtrTy)->getAddressSpace();
3974 bool PreferVectorizedAddressing = Ctx.TTI.prefersVectorizedAddressing();
3975 bool UsedByLoadStoreAddress =
3976 !PreferVectorizedAddressing && vputils::isUsedByLoadStoreAddress(this);
3977 InstructionCost ScalarMemOpCost = Ctx.TTI.getMemoryOpCost(
3978 UI->getOpcode(), ValTy, Alignment, AS, Ctx.CostKind, OpInfo,
3979 UsedByLoadStoreAddress ? UI : nullptr);
3980
3981 Type *PtrTy = isSingleScalar() ? ScalarPtrTy : toVectorTy(ScalarPtrTy, VF);
3982 InstructionCost ScalarCost =
3983 ScalarMemOpCost +
3984 Ctx.TTI.getAddressComputationCost(
3985 PtrTy, UsedByLoadStoreAddress ? nullptr : Ctx.PSE.getSE(), PtrSCEV,
3986 Ctx.CostKind);
3987 if (isSingleScalar())
3988 return ScalarCost;
3989
3990 SmallVector<const VPValue *> OpsToScalarize;
3991 Type *ResultTy = Type::getVoidTy(PtrTy->getContext());
3992 // Set ResultTy and OpsToScalarize, if scalarization is needed. Currently we
3993 // don't assign scalarization overhead in general, if the target prefers
3994 // vectorized addressing or the loaded value is used as part of an address
3995 // of another load or store.
3996 if (!UsedByLoadStoreAddress) {
3997 bool EfficientVectorLoadStore =
3998 Ctx.TTI.supportsEfficientVectorElementLoadStore();
3999 if (!(IsLoad && !PreferVectorizedAddressing) &&
4000 !(!IsLoad && EfficientVectorLoadStore))
4001 append_range(OpsToScalarize, operands());
4002
4003 if (!EfficientVectorLoadStore)
4004 ResultTy = this->getScalarType();
4005 }
4006
4008 IsLoad ? TTI::VectorInstrContext::Load : TTI::VectorInstrContext::Store;
4010 (ScalarCost * VF.getFixedValue()) +
4011 Ctx.getScalarizationOverhead(ResultTy, OpsToScalarize, VF, VIC, true);
4012
4013 const VPRegionBlock *ParentRegion = getRegion();
4014 if (ParentRegion && ParentRegion->isReplicator()) {
4015 if (!PtrSCEV)
4016 break;
4017 Cost /= Ctx.getPredBlockCostDivisor(UI->getParent());
4018 Cost += Ctx.TTI.getCFInstrCost(Instruction::CondBr, Ctx.CostKind);
4019
4020 auto *VecI1Ty = VectorType::get(
4021 IntegerType::getInt1Ty(Ctx.L->getHeader()->getContext()), VF);
4022 Cost += Ctx.TTI.getScalarizationOverhead(
4023 VecI1Ty, APInt::getAllOnes(VF.getFixedValue()),
4024 /*Insert=*/false, /*Extract=*/true, Ctx.CostKind);
4025
4026 if (Ctx.useEmulatedMaskMemRefHack(this, VF)) {
4027 // Artificially setting to a high enough value to practically disable
4028 // vectorization with such operations.
4029 return 3000000;
4030 }
4031 }
4032 return Cost;
4033 }
4034 case Instruction::SExt:
4035 case Instruction::ZExt:
4036 case Instruction::FPToUI:
4037 case Instruction::FPToSI:
4038 case Instruction::FPExt:
4039 case Instruction::PtrToInt:
4040 case Instruction::PtrToAddr:
4041 case Instruction::IntToPtr:
4042 case Instruction::SIToFP:
4043 case Instruction::UIToFP:
4044 case Instruction::Trunc:
4045 case Instruction::FPTrunc:
4046 case Instruction::Select:
4047 case Instruction::AddrSpaceCast: {
4049 Ctx) *
4050 (isSingleScalar() ? 1 : VF.getFixedValue());
4051 }
4052 case Instruction::ExtractValue:
4053 case Instruction::InsertValue:
4054 return Ctx.TTI.getInsertExtractValueCost(getOpcode(), Ctx.CostKind);
4055 }
4056
4057 return Ctx.getLegacyCost(UI, VF);
4058}
4059
4061 Function *CalledFn, Type *ResultTy, ArrayRef<const VPValue *> ArgOps,
4062 bool IsSingleScalar, ElementCount VF, VPCostContext &Ctx) {
4064 ArgOps, [&](const VPValue *Op) { return Op->getScalarType(); });
4065
4066 Intrinsic::ID IntrinID = CalledFn->getIntrinsicID();
4067 auto GetIntrinsicCost = [&] {
4068 if (!IntrinID)
4070 return Ctx.TTI.getIntrinsicInstrCost(
4071 IntrinsicCostAttributes(IntrinID, ResultTy, Tys), Ctx.CostKind);
4072 };
4073
4074 if (IntrinID && VPCostContext::isFreeScalarIntrinsic(IntrinID)) {
4075 assert(GetIntrinsicCost() == 0 && "scalarizing intrinsic should be free");
4076 return 0;
4077 }
4078
4079 InstructionCost ScalarCallCost =
4080 Ctx.TTI.getCallInstrCost(CalledFn, ResultTy, Tys, Ctx.CostKind);
4081 if (IsSingleScalar) {
4082 ScalarCallCost = std::min(ScalarCallCost, GetIntrinsicCost());
4083 return ScalarCallCost;
4084 }
4085
4086 // Scalarization overhead is undefined for scalable VFs.
4087 if (VF.isScalable())
4089
4090 return ScalarCallCost * VF.getFixedValue() +
4091 Ctx.getScalarizationOverhead(ResultTy, ArgOps, VF);
4092}
4093
4094#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4096 VPSlotTracker &SlotTracker) const {
4097 O << Indent << (IsSingleScalar ? "CLONE " : "REPLICATE ");
4098
4099 if (!getScalarType()->isVoidTy()) {
4101 O << " = ";
4102 }
4103 if (auto *CB = dyn_cast<CallBase>(getUnderlyingInstr())) {
4104 O << "call";
4105 printFlags(O);
4106 O << "@" << CB->getCalledFunction()->getName() << "(";
4108 Op->printAsOperand(O, SlotTracker);
4109 });
4110 O << ")";
4111 } else {
4113 printFlags(O);
4115 }
4116
4117 // Find if the recipe is used by a widened recipe via an intervening
4118 // VPPredInstPHIRecipe. In this case, also pack the scalar values in a vector.
4119 if (any_of(users(), [](const VPUser *U) {
4120 if (auto *PredR = dyn_cast<VPPredInstPHIRecipe>(U))
4121 return !vputils::onlyScalarValuesUsed(PredR);
4122 return false;
4123 }))
4124 O << " (S->V)";
4125}
4126#endif
4127
4129 llvm_unreachable("recipe must be removed when dissolving replicate region");
4130}
4131
4133 VPCostContext &Ctx) const {
4134 // The legacy cost model doesn't assign costs to branches for individual
4135 // replicate regions. Match the current behavior in the VPlan cost model for
4136 // now.
4137 return 0;
4138}
4139
4141 llvm_unreachable("recipe must be removed when dissolving replicate region");
4142}
4143
4144#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4146 VPSlotTracker &SlotTracker) const {
4147 O << Indent << "PHI-PREDICATED-INSTRUCTION ";
4149 O << " = ";
4151}
4152#endif
4153
4155const VPRecipeBase *VPWidenLoadRecipe::getAsRecipe() const { return this; }
4156
4159
4161const VPRecipeBase *VPWidenStoreRecipe::getAsRecipe() const { return this; }
4162
4165
4167 VPCostContext &Ctx) const {
4168 const VPRecipeBase *R = getAsRecipe();
4170 Type *ScalarTy = IsLoad ? cast<VPSingleDefRecipe>(R)->getScalarType()
4171 : R->getOperand(1)->getScalarType();
4172 Type *Ty = toVectorTy(ScalarTy, VF);
4173 unsigned AS =
4174 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4175 unsigned Opcode = IsLoad ? Instruction::Load : Instruction::Store;
4176
4177 if (!Consecutive) {
4178 // TODO: Using the original IR may not be accurate.
4179 // Currently, ARM will use the underlying IR to calculate gather/scatter
4180 // instruction cost.
4181 Type *PtrTy = getAddr()->getScalarType();
4182 const Value *Ptr = getAddr()->getUnderlyingValue();
4183
4184 // If the address value is uniform across all lanes, then the address can be
4185 // calculated with scalar type and broadcast.
4187 PtrTy = toVectorTy(PtrTy, VF);
4188
4189 unsigned IID = isa<VPWidenLoadRecipe>(R) ? Intrinsic::masked_gather
4190 : isa<VPWidenStoreRecipe>(R) ? Intrinsic::masked_scatter
4191 : isa<VPWidenLoadEVLRecipe>(R) ? Intrinsic::vp_gather
4192 : Intrinsic::vp_scatter;
4193 return Ctx.TTI.getAddressComputationCost(PtrTy, nullptr, nullptr,
4194 Ctx.CostKind) +
4195 Ctx.TTI.getMemIntrinsicInstrCost(
4197 &Ingredient),
4198 Ctx.CostKind);
4199 }
4200
4202 if (IsMasked) {
4203 unsigned IID = isa<VPWidenLoadRecipe>(R) ? Intrinsic::masked_load
4204 : Intrinsic::masked_store;
4205 Cost += Ctx.TTI.getMemIntrinsicInstrCost(
4206 MemIntrinsicCostAttributes(IID, Ty, Alignment, AS), Ctx.CostKind);
4207 } else {
4208 TTI::OperandValueInfo OpInfo = Ctx.getOperandInfo(
4210 : R->getOperand(1));
4211 Cost += Ctx.TTI.getMemoryOpCost(Opcode, Ty, Alignment, AS, Ctx.CostKind,
4212 OpInfo, &Ingredient);
4213 }
4214 return Cost;
4215}
4216
4218 Type *ScalarDataTy = getScalarType();
4219 auto *DataTy = VectorType::get(ScalarDataTy, State.VF);
4220 bool CreateGather = !isConsecutive();
4221
4222 auto &Builder = State.Builder;
4223 Value *Mask = nullptr;
4224 if (auto *VPMask = getMask())
4225 Mask = State.get(VPMask);
4226
4227 Value *Addr = State.get(getAddr(), /*IsScalar*/ !CreateGather);
4228 Value *NewLI;
4229 if (CreateGather) {
4230 NewLI = Builder.CreateMaskedGather(DataTy, Addr, Alignment, Mask, nullptr,
4231 "wide.masked.gather");
4232 } else if (Mask) {
4233 NewLI =
4234 Builder.CreateMaskedLoad(DataTy, Addr, Alignment, Mask,
4235 PoisonValue::get(DataTy), "wide.masked.load");
4236 } else {
4237 NewLI = Builder.CreateAlignedLoad(DataTy, Addr, Alignment, "wide.load");
4238 }
4240 State.set(this, NewLI);
4241}
4242
4243#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4245 VPSlotTracker &SlotTracker) const {
4246 O << Indent << "WIDEN ";
4248 O << " = load ";
4250}
4251#endif
4252
4254 Type *ScalarDataTy = getScalarType();
4255 auto *DataTy = VectorType::get(ScalarDataTy, State.VF);
4256 bool CreateGather = !isConsecutive();
4257
4258 auto &Builder = State.Builder;
4259 CallInst *NewLI;
4260 Value *EVL = State.get(getEVL(), VPLane(0));
4261 Value *Addr = State.get(getAddr(), !CreateGather);
4262 Value *Mask = nullptr;
4263 if (VPValue *VPMask = getMask())
4264 Mask = State.get(VPMask);
4265 else
4266 Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue());
4267
4268 if (CreateGather) {
4269 NewLI = Builder.CreateIntrinsicWithoutFolding(DataTy, Intrinsic::vp_gather,
4270 {Addr, Mask, EVL}, nullptr,
4271 "wide.masked.gather");
4272 } else {
4273 NewLI = Builder.CreateIntrinsicWithoutFolding(
4274 DataTy, Intrinsic::vp_load, {Addr, Mask, EVL}, nullptr, "vp.op.load");
4275 }
4276 NewLI->addParamAttr(
4278 applyMetadata(*NewLI);
4279 State.set(this, NewLI);
4280}
4281
4283 VPCostContext &Ctx) const {
4284 if (!Consecutive || IsMasked)
4285 return VPWidenMemoryRecipe::computeCost(VF, Ctx);
4286
4287 // We need to use the getMemIntrinsicInstrCost() instead of getMemoryOpCost()
4288 // here because the EVL recipes using EVL to replace the tail mask. But in the
4289 // legacy model, it will always calculate the cost of mask.
4290 // TODO: Using getMemoryOpCost() instead of getMemIntrinsicInstrCost when we
4291 // don't need to compare to the legacy cost model.
4292 Type *Ty = toVectorTy(getScalarType(), VF);
4293 unsigned AS =
4294 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4295 return Ctx.TTI.getMemIntrinsicInstrCost(
4296 MemIntrinsicCostAttributes(Intrinsic::vp_load, Ty, Alignment, AS),
4297 Ctx.CostKind);
4298}
4299
4300#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4302 VPSlotTracker &SlotTracker) const {
4303 O << Indent << "WIDEN ";
4305 O << " = vp.load ";
4307}
4308#endif
4309
4311 VPValue *StoredVPValue = getStoredValue();
4312 bool CreateScatter = !isConsecutive();
4313
4314 auto &Builder = State.Builder;
4315
4316 Value *Mask = nullptr;
4317 if (auto *VPMask = getMask())
4318 Mask = State.get(VPMask);
4319
4320 Value *StoredVal = State.get(StoredVPValue);
4321 Value *Addr = State.get(getAddr(), /*IsScalar*/ !CreateScatter);
4322 Instruction *NewSI = nullptr;
4323 if (CreateScatter)
4324 NewSI = Builder.CreateMaskedScatter(StoredVal, Addr, Alignment, Mask);
4325 else if (Mask)
4326 NewSI = Builder.CreateMaskedStore(StoredVal, Addr, Alignment, Mask);
4327 else
4328 NewSI = Builder.CreateAlignedStore(StoredVal, Addr, Alignment);
4329 applyMetadata(*NewSI);
4330}
4331
4332#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4334 VPSlotTracker &SlotTracker) const {
4335 O << Indent << "WIDEN store ";
4337}
4338#endif
4339
4341 VPValue *StoredValue = getStoredValue();
4342 bool CreateScatter = !isConsecutive();
4343
4344 auto &Builder = State.Builder;
4345
4346 CallInst *NewSI = nullptr;
4347 Value *StoredVal = State.get(StoredValue);
4348 Value *EVL = State.get(getEVL(), VPLane(0));
4349 Value *Mask = nullptr;
4350 if (VPValue *VPMask = getMask())
4351 Mask = State.get(VPMask);
4352 else
4353 Mask = Builder.CreateVectorSplat(State.VF, Builder.getTrue());
4354
4355 Value *Addr = State.get(getAddr(), !CreateScatter);
4356 if (CreateScatter) {
4357 NewSI = Builder.CreateIntrinsicWithoutFolding(
4358 Type::getVoidTy(EVL->getContext()), Intrinsic::vp_scatter,
4359 {StoredVal, Addr, Mask, EVL});
4360 } else {
4361 NewSI = Builder.CreateIntrinsicWithoutFolding(
4362 Type::getVoidTy(EVL->getContext()), Intrinsic::vp_store,
4363 {StoredVal, Addr, Mask, EVL});
4364 }
4365 NewSI->addParamAttr(
4367 applyMetadata(*NewSI);
4368}
4369
4371 VPCostContext &Ctx) const {
4372 if (!Consecutive || IsMasked)
4373 return VPWidenMemoryRecipe::computeCost(VF, Ctx);
4374
4375 // We need to use the getMemIntrinsicInstrCost() instead of getMemoryOpCost()
4376 // here because the EVL recipes using EVL to replace the tail mask. But in the
4377 // legacy model, it will always calculate the cost of mask.
4378 // TODO: Using getMemoryOpCost() instead of getMemIntrinsicInstrCost when we
4379 // don't need to compare to the legacy cost model.
4380 Type *Ty = toVectorTy(getStoredValue()->getScalarType(), VF);
4381 unsigned AS =
4382 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4383 return Ctx.TTI.getMemIntrinsicInstrCost(
4384 MemIntrinsicCostAttributes(Intrinsic::vp_store, Ty, Alignment, AS),
4385 Ctx.CostKind);
4386}
4387
4388#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4390 VPSlotTracker &SlotTracker) const {
4391 O << Indent << "WIDEN vp.store ";
4393}
4394#endif
4395
4397 VectorType *DstVTy, const DataLayout &DL) {
4398 // Verify that V is a vector type with same number of elements as DstVTy.
4399 auto VF = DstVTy->getElementCount();
4400 auto *SrcVecTy = cast<VectorType>(V->getType());
4401 assert(VF == SrcVecTy->getElementCount() && "Vector dimensions do not match");
4402 Type *SrcElemTy = SrcVecTy->getElementType();
4403 Type *DstElemTy = DstVTy->getElementType();
4404 assert((DL.getTypeSizeInBits(SrcElemTy) == DL.getTypeSizeInBits(DstElemTy)) &&
4405 "Vector elements must have same size");
4406
4407 // Do a direct cast if element types are castable.
4408 if (CastInst::isBitOrNoopPointerCastable(SrcElemTy, DstElemTy, DL)) {
4409 return Builder.CreateBitOrPointerCast(V, DstVTy);
4410 }
4411 // V cannot be directly casted to desired vector type.
4412 // May happen when V is a floating point vector but DstVTy is a vector of
4413 // pointers or vice-versa. Handle this using a two-step bitcast using an
4414 // intermediate Integer type for the bitcast i.e. Ptr <-> Int <-> Float.
4415 assert((DstElemTy->isPointerTy() != SrcElemTy->isPointerTy()) &&
4416 "Only one type should be a pointer type");
4417 assert((DstElemTy->isFloatingPointTy() != SrcElemTy->isFloatingPointTy()) &&
4418 "Only one type should be a floating point type");
4419 Type *IntTy =
4420 IntegerType::getIntNTy(V->getContext(), DL.getTypeSizeInBits(SrcElemTy));
4421 auto *VecIntTy = VectorType::get(IntTy, VF);
4422 Value *CastVal = Builder.CreateBitOrPointerCast(V, VecIntTy);
4423 return Builder.CreateBitOrPointerCast(CastVal, DstVTy);
4424}
4425
4426/// Return a vector containing interleaved elements from multiple
4427/// smaller input vectors.
4429 const Twine &Name) {
4430 unsigned Factor = Vals.size();
4431 assert(Factor > 1 && "Tried to interleave invalid number of vectors");
4432
4433 VectorType *VecTy = cast<VectorType>(Vals[0]->getType());
4434#ifndef NDEBUG
4435 for (Value *Val : Vals)
4436 assert(Val->getType() == VecTy && "Tried to interleave mismatched types");
4437#endif
4438
4439 // Scalable vectors cannot use arbitrary shufflevectors (only splats), so
4440 // must use intrinsics to interleave.
4441 if (VecTy->isScalableTy()) {
4442 assert(Factor <= 8 && "Unsupported interleave factor for scalable vectors");
4443 return Builder.CreateVectorInterleave(Vals, Name);
4444 }
4445
4446 // Fixed length. Start by concatenating all vectors into a wide vector.
4447 Value *WideVec = concatenateVectors(Builder, Vals);
4448
4449 // Interleave the elements into the wide vector.
4450 const unsigned NumElts = VecTy->getElementCount().getFixedValue();
4451 return Builder.CreateShuffleVector(
4452 WideVec, createInterleaveMask(NumElts, Factor), Name);
4453}
4454
4455// Try to vectorize the interleave group that \p Instr belongs to.
4456//
4457// E.g. Translate following interleaved load group (factor = 3):
4458// for (i = 0; i < N; i+=3) {
4459// R = Pic[i]; // Member of index 0
4460// G = Pic[i+1]; // Member of index 1
4461// B = Pic[i+2]; // Member of index 2
4462// ... // do something to R, G, B
4463// }
4464// To:
4465// %wide.vec = load <12 x i32> ; Read 4 tuples of R,G,B
4466// %R.vec = shuffle %wide.vec, poison, <0, 3, 6, 9> ; R elements
4467// %G.vec = shuffle %wide.vec, poison, <1, 4, 7, 10> ; G elements
4468// %B.vec = shuffle %wide.vec, poison, <2, 5, 8, 11> ; B elements
4469//
4470// Or translate following interleaved store group (factor = 3):
4471// for (i = 0; i < N; i+=3) {
4472// ... do something to R, G, B
4473// Pic[i] = R; // Member of index 0
4474// Pic[i+1] = G; // Member of index 1
4475// Pic[i+2] = B; // Member of index 2
4476// }
4477// To:
4478// %R_G.vec = shuffle %R.vec, %G.vec, <0, 1, 2, ..., 7>
4479// %B_U.vec = shuffle %B.vec, poison, <0, 1, 2, 3, u, u, u, u>
4480// %interleaved.vec = shuffle %R_G.vec, %B_U.vec,
4481// <0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11> ; Interleave R,G,B elements
4482// store <12 x i32> %interleaved.vec ; Write 4 tuples of R,G,B
4484 assert((!needsMaskForGaps() || !State.VF.isScalable()) &&
4485 "Masking gaps for scalable vectors is not yet supported.");
4487 Instruction *Instr = Group->getInsertPos();
4488
4489 // Prepare for the vector type of the interleaved load/store.
4490 Type *ScalarTy = getLoadStoreType(Instr);
4491 unsigned InterleaveFactor = Group->getFactor();
4492 auto *VecTy = VectorType::get(ScalarTy, State.VF * InterleaveFactor);
4493
4494 VPValue *BlockInMask = getMask();
4495 VPValue *Addr = getAddr();
4496 Value *ResAddr = State.get(Addr, VPLane(0));
4497
4498 auto CreateGroupMask = [&BlockInMask, &State,
4499 &InterleaveFactor](Value *MaskForGaps) -> Value * {
4500 if (State.VF.isScalable()) {
4501 assert(!MaskForGaps && "Interleaved groups with gaps are not supported.");
4502 assert(InterleaveFactor <= 8 &&
4503 "Unsupported deinterleave factor for scalable vectors");
4504 auto *ResBlockInMask = State.get(BlockInMask);
4505 SmallVector<Value *> Ops(InterleaveFactor, ResBlockInMask);
4506 return interleaveVectors(State.Builder, Ops, "interleaved.mask");
4507 }
4508
4509 if (!BlockInMask)
4510 return MaskForGaps;
4511
4512 Value *ResBlockInMask = State.get(BlockInMask);
4513 Value *ShuffledMask = State.Builder.CreateShuffleVector(
4514 ResBlockInMask,
4515 createReplicatedMask(InterleaveFactor, State.VF.getFixedValue()),
4516 "interleaved.mask");
4517 return MaskForGaps ? State.Builder.CreateBinOp(Instruction::And,
4518 ShuffledMask, MaskForGaps)
4519 : ShuffledMask;
4520 };
4521
4522 const DataLayout &DL = Instr->getDataLayout();
4523 // Vectorize the interleaved load group.
4524 if (isa<LoadInst>(Instr)) {
4525 Value *MaskForGaps = nullptr;
4526 if (needsMaskForGaps()) {
4527 MaskForGaps =
4528 createBitMaskForGaps(State.Builder, State.VF.getFixedValue(), *Group);
4529 assert(MaskForGaps && "Mask for Gaps is required but it is null");
4530 }
4531
4532 Instruction *NewLoad;
4533 if (BlockInMask || MaskForGaps) {
4534 Value *GroupMask = CreateGroupMask(MaskForGaps);
4535 Value *PoisonVec = PoisonValue::get(VecTy);
4536 NewLoad = State.Builder.CreateMaskedLoad(VecTy, ResAddr,
4537 Group->getAlign(), GroupMask,
4538 PoisonVec, "wide.masked.vec");
4539 } else
4540 NewLoad = State.Builder.CreateAlignedLoad(VecTy, ResAddr,
4541 Group->getAlign(), "wide.vec");
4542 applyMetadata(*NewLoad);
4543 // TODO: Also manage existing metadata using VPIRMetadata.
4544 Group->addMetadata(NewLoad);
4545
4547 if (VecTy->isScalableTy()) {
4548 // Scalable vectors cannot use arbitrary shufflevectors (only splats),
4549 // so must use intrinsics to deinterleave.
4550 assert(InterleaveFactor <= 8 &&
4551 "Unsupported deinterleave factor for scalable vectors");
4552 NewLoad = State.Builder.CreateIntrinsicWithoutFolding(
4553 Intrinsic::getDeinterleaveIntrinsicID(InterleaveFactor),
4554 NewLoad->getType(), NewLoad,
4555 /*FMFSource=*/nullptr, "strided.vec");
4556 }
4557
4558 auto CreateStridedVector = [&InterleaveFactor, &State,
4559 &NewLoad](unsigned Index) -> Value * {
4560 assert(Index < InterleaveFactor && "Illegal group index");
4561 if (State.VF.isScalable())
4562 return State.Builder.CreateExtractValue(NewLoad, Index);
4563
4564 // For fixed length VF, use shuffle to extract the sub-vectors from the
4565 // wide load.
4566 auto StrideMask =
4567 createStrideMask(Index, InterleaveFactor, State.VF.getFixedValue());
4568 return State.Builder.CreateShuffleVector(NewLoad, StrideMask,
4569 "strided.vec");
4570 };
4571
4572 for (unsigned I = 0, J = 0; I < InterleaveFactor; ++I) {
4573 Instruction *Member = Group->getMember(I);
4574
4575 // Skip the gaps in the group.
4576 if (!Member)
4577 continue;
4578
4579 Value *StridedVec = CreateStridedVector(I);
4580
4581 // If this member has different type, cast the result type.
4582 if (Member->getType() != ScalarTy) {
4583 VectorType *OtherVTy = VectorType::get(Member->getType(), State.VF);
4584 StridedVec =
4585 createBitOrPointerCast(State.Builder, StridedVec, OtherVTy, DL);
4586 }
4587
4588 if (Group->isReverse())
4589 StridedVec = State.Builder.CreateVectorReverse(StridedVec, "reverse");
4590
4591 State.set(VPDefs[J], StridedVec);
4592 ++J;
4593 }
4594 return;
4595 }
4596
4597 // The sub vector type for current instruction.
4598 auto *SubVT = VectorType::get(ScalarTy, State.VF);
4599
4600 // Vectorize the interleaved store group.
4601 Value *MaskForGaps =
4602 createBitMaskForGaps(State.Builder, State.VF.getKnownMinValue(), *Group);
4603 assert(((MaskForGaps != nullptr) == needsMaskForGaps()) &&
4604 "Mismatch between NeedsMaskForGaps and MaskForGaps");
4605 ArrayRef<VPValue *> StoredValues = getStoredValues();
4606 // Collect the stored vector from each member.
4607 SmallVector<Value *, 4> StoredVecs;
4608 unsigned StoredIdx = 0;
4609 for (unsigned i = 0; i < InterleaveFactor; i++) {
4610 assert((Group->getMember(i) || MaskForGaps) &&
4611 "Fail to get a member from an interleaved store group");
4612 Instruction *Member = Group->getMember(i);
4613
4614 // Skip the gaps in the group.
4615 if (!Member) {
4616 Value *Undef = PoisonValue::get(SubVT);
4617 StoredVecs.push_back(Undef);
4618 continue;
4619 }
4620
4621 Value *StoredVec = State.get(StoredValues[StoredIdx]);
4622 ++StoredIdx;
4623
4624 if (Group->isReverse())
4625 StoredVec = State.Builder.CreateVectorReverse(StoredVec, "reverse");
4626
4627 // If this member has different type, cast it to a unified type.
4628
4629 if (StoredVec->getType() != SubVT)
4630 StoredVec = createBitOrPointerCast(State.Builder, StoredVec, SubVT, DL);
4631
4632 StoredVecs.push_back(StoredVec);
4633 }
4634
4635 // Interleave all the smaller vectors into one wider vector.
4636 Value *IVec = interleaveVectors(State.Builder, StoredVecs, "interleaved.vec");
4637 Instruction *NewStoreInstr;
4638 if (BlockInMask || MaskForGaps) {
4639 Value *GroupMask = CreateGroupMask(MaskForGaps);
4640 NewStoreInstr = State.Builder.CreateMaskedStore(
4641 IVec, ResAddr, Group->getAlign(), GroupMask);
4642 } else
4643 NewStoreInstr =
4644 State.Builder.CreateAlignedStore(IVec, ResAddr, Group->getAlign());
4645
4646 applyMetadata(*NewStoreInstr);
4647 // TODO: Also manage existing metadata using VPIRMetadata.
4648 Group->addMetadata(NewStoreInstr);
4649}
4650
4651#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4653 VPSlotTracker &SlotTracker) const {
4655 O << Indent << "INTERLEAVE-GROUP with factor " << IG->getFactor() << ", ";
4657 VPValue *Mask = getMask();
4658 if (Mask) {
4659 O << ", ";
4660 Mask->printAsOperand(O, SlotTracker);
4661 }
4662
4663 unsigned OpIdx = 0;
4664 for (unsigned i = 0; i < IG->getFactor(); ++i) {
4665 if (!IG->getMember(i))
4666 continue;
4667 if (getNumStoreOperands() > 0) {
4668 O << "\n" << Indent << " store ";
4669 getOperand(1 + OpIdx)->printAsOperand(O, SlotTracker);
4670 O << " to index " << i;
4671 } else {
4672 O << "\n" << Indent << " ";
4674 O << " = load from index " << i;
4675 }
4676 ++OpIdx;
4677 }
4678}
4679#endif
4680
4682 assert(State.VF.isScalable() &&
4683 "Only support scalable VF for EVL tail-folding.");
4685 "Masking gaps for scalable vectors is not yet supported.");
4687 Instruction *Instr = Group->getInsertPos();
4688
4689 // Prepare for the vector type of the interleaved load/store.
4690 Type *ScalarTy = getLoadStoreType(Instr);
4691 unsigned InterleaveFactor = Group->getFactor();
4692 assert(InterleaveFactor <= 8 &&
4693 "Unsupported deinterleave/interleave factor for scalable vectors");
4694 ElementCount WideVF = State.VF * InterleaveFactor;
4695 auto *VecTy = VectorType::get(ScalarTy, WideVF);
4696
4697 VPValue *Addr = getAddr();
4698 Value *ResAddr = State.get(Addr, VPLane(0));
4699 Value *EVL = State.get(getEVL(), VPLane(0));
4700 Value *InterleaveEVL = State.Builder.CreateMul(
4701 EVL, ConstantInt::get(EVL->getType(), InterleaveFactor), "interleave.evl",
4702 /* NUW= */ true, /* NSW= */ true);
4703 LLVMContext &Ctx = State.Builder.getContext();
4704
4705 Value *GroupMask = nullptr;
4706 if (VPValue *BlockInMask = getMask()) {
4707 SmallVector<Value *> Ops(InterleaveFactor, State.get(BlockInMask));
4708 GroupMask = interleaveVectors(State.Builder, Ops, "interleaved.mask");
4709 } else {
4710 GroupMask =
4711 State.Builder.CreateVectorSplat(WideVF, State.Builder.getTrue());
4712 }
4713
4714 // Vectorize the interleaved load group.
4715 if (isa<LoadInst>(Instr)) {
4716 CallInst *NewLoad = State.Builder.CreateIntrinsicWithoutFolding(
4717 VecTy, Intrinsic::vp_load, {ResAddr, GroupMask, InterleaveEVL}, nullptr,
4718 "wide.vp.load");
4719 NewLoad->addParamAttr(0,
4720 Attribute::getWithAlignment(Ctx, Group->getAlign()));
4721
4722 applyMetadata(*NewLoad);
4723 // TODO: Also manage existing metadata using VPIRMetadata.
4724 Group->addMetadata(NewLoad);
4725
4726 // Scalable vectors cannot use arbitrary shufflevectors (only splats),
4727 // so must use intrinsics to deinterleave.
4728 NewLoad = State.Builder.CreateIntrinsicWithoutFolding(
4729 Intrinsic::getDeinterleaveIntrinsicID(InterleaveFactor),
4730 NewLoad->getType(), NewLoad,
4731 /*FMFSource=*/nullptr, "strided.vec");
4732
4733 const DataLayout &DL = Instr->getDataLayout();
4734 for (unsigned I = 0, J = 0; I < InterleaveFactor; ++I) {
4735 Instruction *Member = Group->getMember(I);
4736 // Skip the gaps in the group.
4737 if (!Member)
4738 continue;
4739
4740 Value *StridedVec = State.Builder.CreateExtractValue(NewLoad, I);
4741 // If this member has different type, cast the result type.
4742 if (Member->getType() != ScalarTy) {
4743 VectorType *OtherVTy = VectorType::get(Member->getType(), State.VF);
4744 StridedVec =
4745 createBitOrPointerCast(State.Builder, StridedVec, OtherVTy, DL);
4746 }
4747
4748 State.set(getVPValue(J), StridedVec);
4749 ++J;
4750 }
4751 return;
4752 } // End for interleaved load.
4753
4754 // The sub vector type for current instruction.
4755 auto *SubVT = VectorType::get(ScalarTy, State.VF);
4756 // Vectorize the interleaved store group.
4757 ArrayRef<VPValue *> StoredValues = getStoredValues();
4758 // Collect the stored vector from each member.
4759 SmallVector<Value *, 4> StoredVecs;
4760 const DataLayout &DL = Instr->getDataLayout();
4761 for (unsigned I = 0, StoredIdx = 0; I < InterleaveFactor; I++) {
4762 Instruction *Member = Group->getMember(I);
4763 // Skip the gaps in the group.
4764 if (!Member) {
4765 StoredVecs.push_back(PoisonValue::get(SubVT));
4766 continue;
4767 }
4768
4769 Value *StoredVec = State.get(StoredValues[StoredIdx]);
4770 // If this member has different type, cast it to a unified type.
4771 if (StoredVec->getType() != SubVT)
4772 StoredVec = createBitOrPointerCast(State.Builder, StoredVec, SubVT, DL);
4773
4774 StoredVecs.push_back(StoredVec);
4775 ++StoredIdx;
4776 }
4777
4778 // Interleave all the smaller vectors into one wider vector.
4779 Value *IVec = interleaveVectors(State.Builder, StoredVecs, "interleaved.vec");
4780 CallInst *NewStore = State.Builder.CreateIntrinsicWithoutFolding(
4781 Type::getVoidTy(Ctx), Intrinsic::vp_store,
4782 {IVec, ResAddr, GroupMask, InterleaveEVL});
4783
4784 NewStore->addParamAttr(1,
4785 Attribute::getWithAlignment(Ctx, Group->getAlign()));
4786
4787 applyMetadata(*NewStore);
4788 // TODO: Also manage existing metadata using VPIRMetadata.
4789 Group->addMetadata(NewStore);
4790}
4791
4792#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4794 VPSlotTracker &SlotTracker) const {
4796 O << Indent << "INTERLEAVE-GROUP with factor " << IG->getFactor() << ", ";
4798 O << ", ";
4800 if (VPValue *Mask = getMask()) {
4801 O << ", ";
4802 Mask->printAsOperand(O, SlotTracker);
4803 }
4804
4805 unsigned OpIdx = 0;
4806 for (unsigned i = 0; i < IG->getFactor(); ++i) {
4807 if (!IG->getMember(i))
4808 continue;
4809 if (getNumStoreOperands() > 0) {
4810 O << "\n" << Indent << " vp.store ";
4811 getOperand(2 + OpIdx)->printAsOperand(O, SlotTracker);
4812 O << " to index " << i;
4813 } else {
4814 O << "\n" << Indent << " ";
4816 O << " = vp.load from index " << i;
4817 }
4818 ++OpIdx;
4819 }
4820}
4821#endif
4822
4824 VPCostContext &Ctx) const {
4825 Instruction *InsertPos = getInsertPos();
4826 // Find the VPValue index of the interleave group. We need to skip gaps.
4827 unsigned InsertPosIdx = 0;
4828 for (unsigned Idx = 0; IG->getFactor(); ++Idx)
4829 if (auto *Member = IG->getMember(Idx)) {
4830 if (Member == InsertPos)
4831 break;
4832 InsertPosIdx++;
4833 }
4834 const VPValue *ValV = getNumDefinedValues() > 0
4835 ? getVPValue(InsertPosIdx)
4836 : getStoredValues()[InsertPosIdx];
4837 Type *ValTy = ValV->getScalarType();
4838 auto *VectorTy = cast<VectorType>(toVectorTy(ValTy, VF));
4839 unsigned AS =
4840 cast<PointerType>(getAddr()->getScalarType())->getAddressSpace();
4841
4842 unsigned InterleaveFactor = IG->getFactor();
4843 auto *WideVecTy = VectorType::get(ValTy, VF * InterleaveFactor);
4844
4845 // Holds the indices of existing members in the interleaved group.
4847 for (unsigned IF = 0; IF < InterleaveFactor; IF++)
4848 if (IG->getMember(IF))
4849 Indices.push_back(IF);
4850
4851 // Calculate the cost of the whole interleaved group.
4852 InstructionCost Cost = Ctx.TTI.getInterleavedMemoryOpCost(
4853 InsertPos->getOpcode(), WideVecTy, IG->getFactor(), Indices,
4854 IG->getAlign(), AS, Ctx.CostKind, getMask(), NeedsMaskForGaps);
4855
4856 if (!IG->isReverse())
4857 return Cost;
4858
4859 return Cost + IG->getNumMembers() *
4860 Ctx.TTI.getShuffleCost(TargetTransformInfo::SK_Reverse,
4861 VectorTy, VectorTy, {}, Ctx.CostKind,
4862 0);
4863}
4864
4866 return vputils::onlyScalarValuesUsed(this) &&
4867 (!IsScalable || vputils::onlyFirstLaneUsed(this));
4868}
4869
4870#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4872 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
4873 assert((getNumOperands() == 3 || getNumOperands() == 5) &&
4874 "unexpected number of operands");
4875 O << Indent << "EMIT ";
4877 O << " = WIDEN-POINTER-INDUCTION ";
4879 O << ", ";
4881 O << ", ";
4883 if (getNumOperands() == 5) {
4884 O << ", ";
4886 O << ", ";
4888 }
4889}
4890
4892 VPSlotTracker &SlotTracker) const {
4893 O << Indent << "EMIT ";
4895 O << " = EXPAND SCEV " << *Expr;
4896}
4897#endif
4898
4899#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4901 VPSlotTracker &SlotTracker) const {
4902 O << Indent << "EMIT ";
4904 O << " = WIDEN-CANONICAL-INDUCTION";
4905 printFlags(O);
4907}
4908#endif
4909
4911 auto &Builder = State.Builder;
4912 // Create a vector from the initial value.
4913 auto *VectorInit = getStartValue()->getLiveInIRValue();
4914
4915 Type *VecTy = State.VF.isScalar()
4916 ? VectorInit->getType()
4917 : VectorType::get(VectorInit->getType(), State.VF);
4918
4919 BasicBlock *VectorPH =
4920 State.CFG.VPBB2IRBB.at(getParent()->getCFGPredecessor(0));
4921 if (State.VF.isVector()) {
4922 auto *IdxTy = Builder.getInt32Ty();
4923 auto *One = ConstantInt::get(IdxTy, 1);
4924 IRBuilder<>::InsertPointGuard Guard(Builder);
4925 Builder.SetInsertPoint(VectorPH->getTerminator());
4926 auto *RuntimeVF = getRuntimeVF(Builder, IdxTy, State.VF);
4927 auto *LastIdx = Builder.CreateSub(RuntimeVF, One);
4928 VectorInit = Builder.CreateInsertElement(
4929 PoisonValue::get(VecTy), VectorInit, LastIdx, "vector.recur.init");
4930 }
4931
4932 // Create a phi node for the new recurrence.
4933 PHINode *Phi = PHINode::Create(VecTy, 2, "vector.recur");
4934 Phi->insertBefore(State.CFG.PrevBB->getFirstInsertionPt());
4935 Phi->addIncoming(VectorInit, VectorPH);
4936 State.set(this, Phi);
4937}
4938
4941 VPCostContext &Ctx) const {
4942 if (VF.isScalar())
4943 return Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
4944
4945 return 0;
4946}
4947
4948#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4950 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
4951 O << Indent << "FIRST-ORDER-RECURRENCE-PHI ";
4953 O << " = phi ";
4955}
4956#endif
4957
4959 // Reductions do not have to start at zero. They can start with
4960 // any loop invariant values.
4961 VPValue *StartVPV = getStartValue();
4962
4963 // In order to support recurrences we need to be able to vectorize Phi nodes.
4964 // Phi nodes have cycles, so we need to vectorize them in two stages. This is
4965 // stage #1: We create a new vector PHI node with no incoming edges. We'll use
4966 // this value when we vectorize all of the instructions that use the PHI.
4967 BasicBlock *VectorPH =
4968 State.CFG.VPBB2IRBB.at(getParent()->getCFGPredecessor(0));
4969 bool ScalarPHI = State.VF.isScalar() || isInLoop();
4970 Value *StartV = State.get(StartVPV, ScalarPHI);
4971 Type *VecTy = StartV->getType();
4972
4973 BasicBlock *HeaderBB = State.CFG.PrevBB;
4974 assert(State.CurrentParentLoop->getHeader() == HeaderBB &&
4975 "recipe must be in the vector loop header");
4976 auto *Phi = PHINode::Create(VecTy, 2, "vec.phi");
4977 Phi->insertBefore(HeaderBB->getFirstInsertionPt());
4978 State.set(this, Phi, isInLoop());
4979
4980 Phi->addIncoming(StartV, VectorPH);
4981}
4982
4983#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4985 VPSlotTracker &SlotTracker) const {
4986 O << Indent << "WIDEN-REDUCTION-PHI ";
4987
4989 O << " = phi (";
4990 printRecurrenceKind(O, Kind);
4991 O << ")";
4992 printFlags(O);
4994 if (getVFScaleFactor() > 1)
4995 O << " (VF scaled by 1/" << getVFScaleFactor() << ")";
4996}
4997#endif
4998
5000 assert(is_contained(operands(), Op) && "Op must be an operand of the recipe");
5001 return vputils::onlyFirstLaneUsed(this);
5002}
5003
5005 executePhiRecipe(this, *this, State, /*IsScalar=*/false, Name);
5006}
5007
5009 VPCostContext &Ctx) const {
5010 return Ctx.TTI.getCFInstrCost(Instruction::PHI, Ctx.CostKind);
5011}
5012
5013#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
5015 VPSlotTracker &SlotTracker) const {
5016 O << Indent << "WIDEN-PHI ";
5017
5019 O << " = phi ";
5021}
5022#endif
5023
5025 BasicBlock *VectorPH =
5026 State.CFG.VPBB2IRBB.at(getParent()->getCFGPredecessor(0));
5027 Value *StartMask = State.get(getOperand(0));
5028 PHINode *Phi =
5029 State.Builder.CreatePHI(StartMask->getType(), 2, "active.lane.mask");
5030 Phi->addIncoming(StartMask, VectorPH);
5031 State.set(this, Phi);
5032}
5033
5034#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
5036 VPSlotTracker &SlotTracker) const {
5037 O << Indent << "ACTIVE-LANE-MASK-PHI ";
5038
5040 O << " = phi ";
5042}
5043#endif
5044
5045#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
5047 raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const {
5048 O << Indent << "CURRENT-ITERATION-PHI ";
5049
5051 O << " = phi ";
5053}
5054#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:235
bool ule(const APInt &RHS) const
Unsigned less or equal comparison.
Definition APInt.h:1159
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
This class holds the attributes for a particular argument, parameter, function, or return value.
Definition Attributes.h:407
static LLVM_ABI Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI bool isBitOrNoopPointerCastable(Type *SrcTy, Type *DestTy, const DataLayout &DL)
Check whether a bitcast, inttoptr, or ptrtoint cast between these types is valid and a no-op.
static Type * makeCmpResultType(Type *opnd_type)
Create a result type for fcmp/icmp.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:763
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
static LLVM_ABI StringRef getPredicateName(Predicate P)
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
void setSuccessor(unsigned idx, BasicBlock *NewSucc)
This is the shared class of boolean and integer constants.
Definition Constants.h:87
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
A debug info location.
Definition DebugLoc.h:126
static DebugLoc getUnknown()
Definition DebugLoc.h:153
constexpr bool isVector() const
One or more elements.
Definition TypeSize.h:324
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:312
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:309
constexpr bool isScalar() const
Exactly one element.
Definition TypeSize.h:320
static bool isSupportedFloatingPointType(Type *Ty)
Returns true if Ty is a supported floating-point type for phi, select, or call FPMathOperators.
Definition Operator.h:302
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
LLVM_ABI void print(raw_ostream &O) const
Print fast-math flags to O.
Definition Operator.cpp:286
void setAllowContract(bool B=true)
Definition FMF.h:90
bool noSignedZeros() const
Definition FMF.h:67
bool noInfs() const
Definition FMF.h:66
void setAllowReciprocal(bool B=true)
Definition FMF.h:87
bool allowReciprocal() const
Definition FMF.h:68
void setNoSignedZeros(bool B=true)
Definition FMF.h:84
bool allowReassoc() const
Flag queries.
Definition FMF.h:64
bool approxFunc() const
Definition FMF.h:70
void setNoNaNs(bool B=true)
Definition FMF.h:78
void setAllowReassoc(bool B=true)
Flag setters.
Definition FMF.h:75
bool noNaNs() const
Definition FMF.h:65
void setApproxFunc(bool B=true)
Definition FMF.h:93
void setNoInfs(bool B=true)
Definition FMF.h:81
bool allowContract() const
Definition FMF.h:69
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
bool willReturn() const
Determine if the function will return.
Definition Function.h:646
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition Function.h:246
bool doesNotThrow() const
Determine if the function cannot unwind.
Definition Function.h:576
bool doesNotAccessMemory() const
Determine if the function does not access memory.
Definition Function.cpp:866
Type * getReturnType() const
Returns the type of the ret val.
Definition Function.h:216
Represents flags for the getelementptr instruction/expression.
static GEPNoWrapFlags none()
Common base class shared among various IRBuilders.
Definition IRBuilder.h:114
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2662
IntegerType * getInt1Ty()
Fetch the type representing a single bit.
Definition IRBuilder.h:519
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition IRBuilder.h:2716
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2650
LLVM_ABI Value * CreateVectorSpliceRight(Value *V1, Value *V2, Value *Offset, const Twine &Name="")
Create a vector.splice.right intrinsic call, or a shufflevector that produces the same result if the ...
CondBrInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
Definition IRBuilder.h:1216
LLVM_ABI Value * CreateSelectFMF(Value *C, Value *True, Value *False, FMFSource FMFSource, const Twine &Name="", Instruction *MDFrom=nullptr)
LLVM_ABI Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition IRBuilder.h:2709
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateFreeze(Value *V, const Twine &Name="")
Definition IRBuilder.h:2728
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition IRBuilder.h:534
Value * 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.
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:380
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1753
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
Type * toVectorizedTy(Type *Ty, ElementCount EC)
A helper for converting to vectorized types.
cl::opt< unsigned > ForceTargetInstructionCost
LLVM_ABI Type * computeScalarTypeForInstruction(unsigned Opcode, ArrayRef< VPValue * > Operands)
Compute the scalar result type for an IR Opcode given Operands.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
Definition STLExtras.h:322
LLVM_ABI bool isVectorIntrinsicWithStructReturnOverloadAtField(Intrinsic::ID ID, int RetIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic that returns a struct is overloaded at the struct elem...
@ Other
Any other memory.
Definition ModRef.h:68
static const MachineInstrBuilder & addOffset(const MachineInstrBuilder &MIB, int Offset)
LLVM_ABI llvm::SmallVector< int, 16 > createInterleaveMask(unsigned VF, unsigned NumVecs)
Create an interleave shuffle mask.
RecurKind
These are the kinds of recurrences that we support.
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
@ FMinimumNum
FP min with llvm.minimumnum semantics.
@ FindIV
FindIV reduction with select(icmp(),x,y) where one of (x,y) is a loop induction variable (increasing ...
@ Or
Bitwise or logical OR of integers.
@ FMinimum
FP min with llvm.minimum semantics.
@ FMaxNum
FP max with llvm.maxnum semantics including NaNs.
@ Mul
Product of integers.
@ FSub
Subtraction of floats.
@ FAddChainWithSubs
A chain of fadds and fsubs.
@ None
Not a recurrence.
@ AnyOf
AnyOf reduction with select(cmp(),x,y) where one of (x,y) is loop invariant, and both x and y are int...
@ Xor
Bitwise or logical XOR of integers.
@ FindLast
FindLast reduction with select(cmp(),x,y) where x and y.
@ FMax
FP max implemented in terms of select(cmp()).
@ FMaximum
FP max with llvm.maximum semantics.
@ FMulAdd
Sum of float products with llvm.fmuladd(a * b + sum).
@ FMul
Product of floats.
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ FMin
FP min implemented in terms of select(cmp()).
@ FMinNum
FP min with llvm.minnum semantics including NaNs.
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
@ AddChainWithSubs
A chain of adds and subs.
@ FAdd
Sum of floats.
@ FMaximumNum
FP max with llvm.maximumnum semantics.
@ UMax
Unsigned integer max implemented in terms of select(cmp()).
LLVM_ABI bool isVectorIntrinsicWithScalarOpAtArg(Intrinsic::ID ID, unsigned ScalarOpdIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic has a scalar operand.
LLVM_ABI Value * getRecurrenceIdentity(RecurKind K, Type *Tp, FastMathFlags FMF)
Given information about an recurrence kind, return the identity for the @llvm.vector....
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
LLVM_ABI Value * createOrderedReduction(IRBuilderBase &B, RecurKind RdxKind, Value *Src, Value *Start)
Create an ordered reduction intrinsic using the given recurrence kind RdxKind.
ArrayRef< Type * > getContainedTypes(Type *const &Ty)
Returns the types contained in Ty.
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
LLVM_ABI bool isVectorIntrinsicWithOverloadTypeAtArg(Intrinsic::ID ID, int OpdIdx, const TargetTransformInfo *TTI)
Identifies if the vector form of the intrinsic is overloaded on the type of the operand at index OpdI...
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Struct to hold various analysis needed for cost computations.
static bool isFreeScalarIntrinsic(Intrinsic::ID ID)
Returns true if ID is a pseudo intrinsic that is dropped via scalarization rather than widened.
Definition VPlan.cpp:1990
TargetTransformInfo::TargetCostKind CostKind
void execute(VPTransformState &State) override
Generate the phi nodes.
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this first-order recurrence phi recipe.
void printRecipe(raw_ostream &O, const Twine &Indent, VPSlotTracker &SlotTracker) const override
Print the recipe.
An overlay for VPIRInstructions wrapping PHI nodes enabling convenient use cast/dyn_cast/isa and exec...
Definition VPlan.h: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