LLVM 24.0.0git
AArch64TargetTransformInfo.cpp
Go to the documentation of this file.
1//===-- AArch64TargetTransformInfo.cpp - AArch64 specific TTI -------------===//
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
10#include "AArch64ExpandImm.h"
14#include "llvm/ADT/DenseMap.h"
15#include "llvm/ADT/bit.h"
23#include "llvm/IR/Intrinsics.h"
24#include "llvm/IR/IntrinsicsAArch64.h"
26#include "llvm/Support/Debug.h"
31#include <algorithm>
32#include <optional>
33using namespace llvm;
34using namespace llvm::PatternMatch;
35
36#define DEBUG_TYPE "aarch64tti"
37
38static cl::opt<bool> EnableFalkorHWPFUnrollFix("enable-falkor-hwpf-unroll-fix",
39 cl::init(true), cl::Hidden);
40
42 "sve-prefer-fixed-over-scalable-if-equal", cl::Hidden);
43
44static cl::opt<unsigned> SVEGatherOverhead("sve-gather-overhead", cl::init(10),
46
47static cl::opt<unsigned> SVEScatterOverhead("sve-scatter-overhead",
48 cl::init(10), cl::Hidden);
49
50static cl::opt<unsigned> SVETailFoldInsnThreshold("sve-tail-folding-insn-threshold",
51 cl::init(15), cl::Hidden);
52
54 NeonNonConstStrideOverhead("neon-nonconst-stride-overhead", cl::init(10),
56
58 "call-penalty-sm-change", cl::init(5), cl::Hidden,
60 "Penalty of calling a function that requires a change to PSTATE.SM"));
61
63 "inline-call-penalty-sm-change", cl::init(10), cl::Hidden,
64 cl::desc("Penalty of inlining a call that requires a change to PSTATE.SM"));
65
66static cl::opt<bool> EnableOrLikeSelectOpt("enable-aarch64-or-like-select",
67 cl::init(true), cl::Hidden);
68
69static cl::opt<bool> EnableLSRCostOpt("enable-aarch64-lsr-cost-opt",
70 cl::init(true), cl::Hidden);
71
72// A complete guess as to a reasonable cost.
74 BaseHistCntCost("aarch64-base-histcnt-cost", cl::init(8), cl::Hidden,
75 cl::desc("The cost of a histcnt instruction"));
76
78 "dmb-lookahead-threshold", cl::init(10), cl::Hidden,
79 cl::desc("The number of instructions to search for a redundant dmb"));
80
82 "aarch64-force-unroll-threshold", cl::init(0), cl::Hidden,
83 cl::desc("Threshold for forced unrolling of small loops in AArch64"));
84
85namespace {
86class TailFoldingOption {
87 // These bitfields will only ever be set to something non-zero in operator=,
88 // when setting the -sve-tail-folding option. This option should always be of
89 // the form (default|simple|all|disable)[+(Flag1|Flag2|etc)], where here
90 // InitialBits is one of (disabled|all|simple). EnableBits represents
91 // additional flags we're enabling, and DisableBits for those flags we're
92 // disabling. The default flag is tracked in the variable NeedsDefault, since
93 // at the time of setting the option we may not know what the default value
94 // for the CPU is.
98
99 // This value needs to be initialised to true in case the user does not
100 // explicitly set the -sve-tail-folding option.
101 bool NeedsDefault = true;
102
103 void setInitialBits(TailFoldingOpts Bits) { InitialBits = Bits; }
104
105 void setNeedsDefault(bool V) { NeedsDefault = V; }
106
107 void setEnableBit(TailFoldingOpts Bit) {
108 EnableBits |= Bit;
109 DisableBits &= ~Bit;
110 }
111
112 void setDisableBit(TailFoldingOpts Bit) {
113 EnableBits &= ~Bit;
114 DisableBits |= Bit;
115 }
116
117 TailFoldingOpts getBits(TailFoldingOpts DefaultBits) const {
118 TailFoldingOpts Bits = TailFoldingOpts::Disabled;
119
120 assert((InitialBits == TailFoldingOpts::Disabled || !NeedsDefault) &&
121 "Initial bits should only include one of "
122 "(disabled|all|simple|default)");
123 Bits = NeedsDefault ? DefaultBits : InitialBits;
124 Bits |= EnableBits;
125 Bits &= ~DisableBits;
126
127 return Bits;
128 }
129
130 void reportError(std::string Opt) {
131 errs() << "invalid argument '" << Opt
132 << "' to -sve-tail-folding=; the option should be of the form\n"
133 " (disabled|all|default|simple)[+(reductions|recurrences"
134 "|reverse|noreductions|norecurrences|noreverse)]\n";
135 report_fatal_error("Unrecognised tail-folding option");
136 }
137
138public:
139
140 void operator=(const std::string &Val) {
141 // If the user explicitly sets -sve-tail-folding= then treat as an error.
142 if (Val.empty()) {
143 reportError("");
144 return;
145 }
146
147 // Since the user is explicitly setting the option we don't automatically
148 // need the default unless they require it.
149 setNeedsDefault(false);
150
151 SmallVector<StringRef, 4> TailFoldTypes;
152 StringRef(Val).split(TailFoldTypes, '+', -1, false);
153
154 unsigned StartIdx = 1;
155 if (TailFoldTypes[0] == "disabled")
156 setInitialBits(TailFoldingOpts::Disabled);
157 else if (TailFoldTypes[0] == "all")
158 setInitialBits(TailFoldingOpts::All);
159 else if (TailFoldTypes[0] == "default")
160 setNeedsDefault(true);
161 else if (TailFoldTypes[0] == "simple")
162 setInitialBits(TailFoldingOpts::Simple);
163 else {
164 StartIdx = 0;
165 setInitialBits(TailFoldingOpts::Disabled);
166 }
167
168 for (unsigned I = StartIdx; I < TailFoldTypes.size(); I++) {
169 if (TailFoldTypes[I] == "reductions")
170 setEnableBit(TailFoldingOpts::Reductions);
171 else if (TailFoldTypes[I] == "recurrences")
172 setEnableBit(TailFoldingOpts::Recurrences);
173 else if (TailFoldTypes[I] == "reverse")
174 setEnableBit(TailFoldingOpts::Reverse);
175 else if (TailFoldTypes[I] == "noreductions")
176 setDisableBit(TailFoldingOpts::Reductions);
177 else if (TailFoldTypes[I] == "norecurrences")
178 setDisableBit(TailFoldingOpts::Recurrences);
179 else if (TailFoldTypes[I] == "noreverse")
180 setDisableBit(TailFoldingOpts::Reverse);
181 else
182 reportError(Val);
183 }
184 }
185
186 bool isDisabled(TailFoldingOpts DefaultBits) const {
187 return getBits(DefaultBits) == TailFoldingOpts::Disabled;
188 }
189
190 bool satisfies(TailFoldingOpts DefaultBits, TailFoldingOpts Required) const {
191 return (getBits(DefaultBits) & Required) == Required;
192 }
193};
194} // namespace
195
196TailFoldingOption TailFoldingOptionLoc;
197
199 "sve-tail-folding",
200 cl::desc(
201 "Control the use of vectorisation using tail-folding for SVE where the"
202 " option is specified in the form (Initial)[+(Flag1|Flag2|...)]:"
203 "\ndisabled (Initial) No loop types will vectorize using "
204 "tail-folding"
205 "\ndefault (Initial) Uses the default tail-folding settings for "
206 "the target CPU"
207 "\nall (Initial) All legal loop types will vectorize using "
208 "tail-folding"
209 "\nsimple (Initial) Use tail-folding for simple loops (not "
210 "reductions or recurrences)"
211 "\nreductions Use tail-folding for loops containing reductions"
212 "\nnoreductions Inverse of above"
213 "\nrecurrences Use tail-folding for loops containing fixed order "
214 "recurrences"
215 "\nnorecurrences Inverse of above"
216 "\nreverse Use tail-folding for loops requiring reversed "
217 "predicates"
218 "\nnoreverse Inverse of above"),
220
221// Experimental option that will only be fully functional when the
222// code-generator is changed to use SVE instead of NEON for all fixed-width
223// operations.
225 "enable-fixedwidth-autovec-in-streaming-mode", cl::init(false), cl::Hidden);
226
227// Experimental option that will only be fully functional when the cost-model
228// and code-generator have been changed to avoid using scalable vector
229// instructions that are not legal in streaming SVE mode.
231 "enable-scalable-autovec-in-streaming-mode", cl::init(false), cl::Hidden);
232
233static bool isSMEABIRoutineCall(const CallInst &CI,
234 const AArch64TargetLowering &TLI) {
235 const auto *F = CI.getCalledFunction();
236 return F &&
238}
239
240/// Returns true if the function has explicit operations that can only be
241/// lowered using incompatible instructions for the selected mode. This also
242/// returns true if the function F may use or modify ZA state.
244 const AArch64TargetLowering &TLI) {
245 for (const BasicBlock &BB : *F) {
246 for (const Instruction &I : BB) {
247 // Be conservative for now and assume that any call to inline asm or to
248 // intrinsics could could result in non-streaming ops (e.g. calls to
249 // @llvm.aarch64.* or @llvm.gather/scatter intrinsics). We can assume that
250 // all native LLVM instructions can be lowered to compatible instructions.
251 if (isa<CallInst>(I) && !I.isDebugOrPseudoInst() &&
252 (cast<CallInst>(I).isInlineAsm() || isa<IntrinsicInst>(I) ||
254 return true;
255 }
256 }
257 return false;
258}
259
261 SmallVectorImpl<StringRef> &Features) {
262 StringRef AttributeStr =
263 TTI->isMultiversionedFunction(F) ? "fmv-features" : "target-features";
264 StringRef FeatureStr = F.getFnAttribute(AttributeStr).getValueAsString();
265 FeatureStr.split(Features, ",");
266}
267
270 extractAttrFeatures(F, this, Features);
271 return AArch64::getCpuSupportsMask(Features);
272}
273
276 extractAttrFeatures(F, this, Features);
277 return AArch64::getFMVPriority(Features);
278}
279
281 return F.hasFnAttribute("fmv-features");
282}
283
285 const Function *Callee) const {
286 SMECallAttrs CallAttrs(*Caller, *Callee);
287
288 // Never inline a function explicitly marked as being streaming,
289 // into a non-streaming function. Assume it was marked as streaming
290 // for a reason.
291 if (CallAttrs.caller().hasNonStreamingInterfaceAndBody() &&
292 CallAttrs.callee().hasStreamingInterfaceOrBody())
293 return false;
294
295 // When inlining, we should consider the body of the function, not the
296 // interface.
297 if (CallAttrs.callee().hasStreamingBody()) {
298 CallAttrs.callee().set(SMEAttrs::SM_Compatible, false);
299 CallAttrs.callee().set(SMEAttrs::SM_Enabled, true);
300 }
301
302 if (CallAttrs.callee().isNewZA() || CallAttrs.callee().isNewZT0())
303 return false;
304
305 if (CallAttrs.requiresLazySave() || CallAttrs.requiresSMChange() ||
306 CallAttrs.requiresPreservingZT0() ||
307 CallAttrs.requiresPreservingAllZAState()) {
308 if (hasPossibleIncompatibleOps(Callee, *getTLI()))
309 return false;
310 }
311
312 return BaseT::areInlineCompatible(Caller, Callee);
313}
314
316 const Function *Callee,
317 ArrayRef<Type *> Types) const {
318 if (!BaseT::areTypesABICompatible(Caller, Callee, Types))
319 return false;
320
321 // We need to ensure that argument promotion does not attempt to promote
322 // pointers to fixed-length vector types larger than 128 bits like
323 // <8 x float> (and pointers to aggregate types which have such fixed-length
324 // vector type members) into the values of the pointees. Such vector types
325 // are used for SVE VLS but there is no ABI for SVE VLS arguments and the
326 // backend cannot lower such value arguments. The 128-bit fixed-length SVE
327 // types can be safely treated as 128-bit NEON types and they cannot be
328 // distinguished in IR.
329 if (ST->useSVEForFixedLengthVectors() && llvm::any_of(Types, [](Type *Ty) {
330 auto FVTy = dyn_cast<FixedVectorType>(Ty);
331 return FVTy &&
332 FVTy->getScalarSizeInBits() * FVTy->getNumElements() > 128;
333 }))
334 return false;
335
336 return true;
337}
338
339unsigned
341 unsigned DefaultCallPenalty) const {
342 // This function calculates a penalty for executing Call in F.
343 //
344 // There are two ways this function can be called:
345 // (1) F:
346 // call from F -> G (the call here is Call)
347 //
348 // For (1), Call.getCaller() == F, so it will always return a high cost if
349 // a streaming-mode change is required (thus promoting the need to inline the
350 // function)
351 //
352 // (2) F:
353 // call from F -> G (the call here is not Call)
354 // G:
355 // call from G -> H (the call here is Call)
356 //
357 // For (2), if after inlining the body of G into F the call to H requires a
358 // streaming-mode change, and the call to G from F would also require a
359 // streaming-mode change, then there is benefit to do the streaming-mode
360 // change only once and avoid inlining of G into F.
361
362 SMEAttrs FAttrs(*F);
363 SMECallAttrs CallAttrs(Call, &getTLI()->getRuntimeLibcallsInfo());
364
365 if (SMECallAttrs(FAttrs, CallAttrs.callee()).requiresSMChange()) {
366 if (F == Call.getCaller()) // (1)
367 return CallPenaltyChangeSM * DefaultCallPenalty;
368 if (SMECallAttrs(FAttrs, CallAttrs.caller()).requiresSMChange()) // (2)
369 return InlineCallPenaltyChangeSM * DefaultCallPenalty;
370 }
371
372 return DefaultCallPenalty;
373}
374
378
379 if (K == TargetTransformInfo::RGK_FixedWidthVector && ST->isNeonAvailable())
380 return true;
381
383 ST->isSVEorStreamingSVEAvailable() &&
384 !ST->disableMaximizeScalableBandwidth();
385}
386
387/// Calculate the cost of materializing a 64-bit value. This helper
388/// method might only calculate a fraction of a larger immediate. Therefore it
389/// is valid to return a cost of ZERO.
391 // Check if the immediate can be encoded within an instruction.
392 if (Val == 0 || AArch64_AM::isLogicalImmediate(Val, 64))
393 return 0;
394
395 if (Val < 0)
396 Val = ~Val;
397
398 // Calculate how many moves we will need to materialize this constant.
400 AArch64_IMM::expandMOVImm(Val, 64, Insn);
401 return Insn.size();
402}
403
404/// Calculate the cost of materializing the given constant.
408 assert(Ty->isIntegerTy());
409
410 unsigned BitSize = Ty->getPrimitiveSizeInBits();
411 if (BitSize == 0)
412 return ~0U;
413
414 // Sign-extend all constants to a multiple of 64-bit.
415 APInt ImmVal = Imm;
416 if (BitSize & 0x3f)
417 ImmVal = Imm.sext((BitSize + 63) & ~0x3fU);
418
419 // Split the constant into 64-bit chunks and calculate the cost for each
420 // chunk.
422 for (unsigned ShiftVal = 0; ShiftVal < BitSize; ShiftVal += 64) {
423 APInt Tmp = ImmVal.ashr(ShiftVal).sextOrTrunc(64);
424 int64_t Val = Tmp.getSExtValue();
425 Cost += getIntImmCost(Val);
426 }
427 // We need at least one instruction to materialze the constant.
428 return std::max<InstructionCost>(1, Cost);
429}
430
432 const APInt &Imm, Type *Ty,
434 Instruction *Inst) const {
435 assert(Ty->isIntegerTy());
436
437 unsigned BitSize = Ty->getPrimitiveSizeInBits();
438 // There is no cost model for constants with a bit size of 0. Return TCC_Free
439 // here, so that constant hoisting will ignore this constant.
440 if (BitSize == 0)
441 return TTI::TCC_Free;
442
443 unsigned ImmIdx = ~0U;
444 switch (Opcode) {
445 default:
446 return TTI::TCC_Free;
447 case Instruction::GetElementPtr:
448 // Always hoist the base address of a GetElementPtr.
449 if (Idx == 0)
450 return 2 * TTI::TCC_Basic;
451 return TTI::TCC_Free;
452 case Instruction::Store:
453 ImmIdx = 0;
454 break;
455 case Instruction::Add:
456 case Instruction::Sub:
457 case Instruction::Mul:
458 case Instruction::UDiv:
459 case Instruction::SDiv:
460 case Instruction::URem:
461 case Instruction::SRem:
462 case Instruction::And:
463 case Instruction::Or:
464 case Instruction::Xor:
465 case Instruction::ICmp:
466 ImmIdx = 1;
467 break;
468 // Always return TCC_Free for the shift value of a shift instruction.
469 case Instruction::Shl:
470 case Instruction::LShr:
471 case Instruction::AShr:
472 if (Idx == 1)
473 return TTI::TCC_Free;
474 break;
475 case Instruction::Trunc:
476 case Instruction::ZExt:
477 case Instruction::SExt:
478 case Instruction::IntToPtr:
479 case Instruction::PtrToInt:
480 case Instruction::BitCast:
481 case Instruction::PHI:
482 case Instruction::Call:
483 case Instruction::Select:
484 case Instruction::Ret:
485 case Instruction::Load:
486 break;
487 }
488
489 if (Idx == ImmIdx) {
490 int NumConstants = (BitSize + 63) / 64;
492 return (Cost <= NumConstants * TTI::TCC_Basic)
493 ? static_cast<int>(TTI::TCC_Free)
494 : Cost;
495 }
497}
498
501 const APInt &Imm, Type *Ty,
503 assert(Ty->isIntegerTy());
504
505 unsigned BitSize = Ty->getPrimitiveSizeInBits();
506 // There is no cost model for constants with a bit size of 0. Return TCC_Free
507 // here, so that constant hoisting will ignore this constant.
508 if (BitSize == 0)
509 return TTI::TCC_Free;
510
511 // Most (all?) AArch64 intrinsics do not support folding immediates into the
512 // selected instruction, so we compute the materialization cost for the
513 // immediate directly.
514 if (IID >= Intrinsic::aarch64_addg && IID <= Intrinsic::aarch64_udiv)
516
517 switch (IID) {
518 default:
519 return TTI::TCC_Free;
520 case Intrinsic::sadd_with_overflow:
521 case Intrinsic::uadd_with_overflow:
522 case Intrinsic::ssub_with_overflow:
523 case Intrinsic::usub_with_overflow:
524 case Intrinsic::smul_with_overflow:
525 case Intrinsic::umul_with_overflow:
526 if (Idx == 1) {
527 int NumConstants = (BitSize + 63) / 64;
529 return (Cost <= NumConstants * TTI::TCC_Basic)
530 ? static_cast<int>(TTI::TCC_Free)
531 : Cost;
532 }
533 break;
534 case Intrinsic::experimental_stackmap:
535 if ((Idx < 2) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))
536 return TTI::TCC_Free;
537 break;
538 case Intrinsic::experimental_patchpoint_void:
539 case Intrinsic::experimental_patchpoint:
540 if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))
541 return TTI::TCC_Free;
542 break;
543 case Intrinsic::experimental_gc_statepoint:
544 if ((Idx < 5) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())))
545 return TTI::TCC_Free;
546 break;
547 }
549}
550
552AArch64TTIImpl::getPopcntSupport(unsigned TyWidth) const {
553 assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");
554 if (TyWidth == 32 || TyWidth == 64)
556 // TODO: AArch64TargetLowering::LowerCTPOP() supports 128bit popcount.
557 return TTI::PSK_Software;
558}
559
561 // MispredictPenalty is defined per-CPU in AArch64Sched*.td (e.g.,
562 // AArch64SchedNeoverseV2.td).
563 return ST->getMispredictionPenalty();
564}
565
566static bool isUnpackedVectorVT(EVT VecVT) {
567 return VecVT.isScalableVector() &&
569}
570
572 const IntrinsicCostAttributes &ICA) {
573 // We need to know at least the number of elements in the vector of buckets
574 // and the size of each element to update.
575 if (ICA.getArgTypes().size() < 2)
577
578 // Only interested in costing for the hardware instruction from SVE2.
579 if (!ST->hasSVE2())
581
582 Type *BucketPtrsTy = ICA.getArgTypes()[0]; // Type of vector of pointers
583 Type *EltTy = ICA.getArgTypes()[1]; // Type of bucket elements
584 unsigned TotalHistCnts = 1;
585
586 unsigned EltSize = EltTy->getScalarSizeInBits();
587 // Only allow (up to 64b) integers or pointers
588 if ((!EltTy->isIntegerTy() && !EltTy->isPointerTy()) || EltSize > 64)
590
591 // FIXME: We should be able to generate histcnt for fixed-length vectors
592 // using ptrue with a specific VL.
593 if (VectorType *VTy = dyn_cast<VectorType>(BucketPtrsTy)) {
594 unsigned EC = VTy->getElementCount().getKnownMinValue();
595 if (!isPowerOf2_64(EC) || !VTy->isScalableTy() || EC == 1)
597
598 // HistCnt only supports 32b and 64b element types
599 unsigned LegalEltSize = EltSize <= 32 ? 32 : 64;
600
601 if (EC == 2 || (LegalEltSize == 32 && EC == 4))
603
604 unsigned NaturalVectorWidth = AArch64::SVEBitsPerBlock / LegalEltSize;
605 TotalHistCnts = EC / NaturalVectorWidth;
606
607 return InstructionCost(BaseHistCntCost * TotalHistCnts);
608 }
609
611}
612
616 // The code-generator is currently not able to handle scalable vectors
617 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
618 // it. This change will be removed when code-generation for these types is
619 // sufficiently reliable.
620 // Only allow masked ld/st to pass through to getMemIntrinsicInstrCost().
621 auto *RetTy = ICA.getReturnType();
622 if (auto *VTy = dyn_cast<ScalableVectorType>(RetTy))
623 if (VTy->getElementCount() == ElementCount::getScalable(1) &&
624 !is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
625 ICA.getID()))
627
628 switch (ICA.getID()) {
629 case Intrinsic::experimental_vector_histogram_add: {
630 InstructionCost HistCost = getHistogramCost(ST, ICA);
631 // If the cost isn't valid, we may still be able to scalarize
632 if (HistCost.isValid())
633 return HistCost;
634 break;
635 }
636 case Intrinsic::clmul: {
637 auto LT = getTypeLegalizationCost(RetTy);
638
639 // PMUL v8i8/v16i8 is always available on AArch64
640 if (ST->hasNEON()) {
641 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
642 return LT.first;
643
644 // Scalar i8 lowers through scalar/vector moves around PMUL.
645 if (TLI->getValueType(DL, RetTy, true) == MVT::i8) {
646 auto *VecTy =
647 FixedVectorType::get(Type::getInt8Ty(RetTy->getContext()), 8);
648 return 1 +
649 getVectorInstrCost(Instruction::ExtractElement, VecTy, CostKind,
650 -1, nullptr, nullptr) *
651 2 +
652 getVectorInstrCost(Instruction::InsertElement, VecTy, CostKind,
653 -1, nullptr, nullptr);
654 }
655 }
656
657 if (LT.second.SimpleTy == MVT::nxv2i64)
658 if (ST->hasSVEAES() && (ST->isSVEAvailable() || ST->hasSSVE_AES()))
659 return LT.first * 3;
660
661 if (ST->hasSVE2() || ST->hasSME()) {
662 switch (LT.second.SimpleTy) {
663 case MVT::nxv16i8:
664 return LT.first;
665 case MVT::nxv8i16:
666 return LT.first * 6;
667 case MVT::nxv4i32:
668 return LT.first * 3;
669 case MVT::nxv2i64:
670 return LT.first * 8;
671 default:
672 break;
673 }
674 }
675
676 // Avoid +sve giving this cost 2 due to custom lowering: It's very slow
677 if (LT.second.SimpleTy == MVT::nxv2i64)
678 return 192;
679
680 if (ST->hasAES()) {
681 switch (LT.second.SimpleTy) {
682 case MVT::i16:
683 case MVT::i32:
684 case MVT::i64:
685 case MVT::i128: {
686 auto *VecTy =
687 FixedVectorType::get(Type::getInt64Ty(RetTy->getContext()), 1);
688 return LT.first *
689 (1 +
690 getVectorInstrCost(Instruction::ExtractElement, VecTy, CostKind,
691 -1, nullptr, nullptr) *
692 2 +
693 getVectorInstrCost(Instruction::InsertElement, VecTy, CostKind,
694 -1, nullptr, nullptr));
695 }
696 case MVT::v1i64:
697 return LT.first;
698 case MVT::v2i64:
699 return LT.first * 3;
700 case MVT::v2i32:
701 return LT.first * 6;
702 case MVT::v4i32:
703 return LT.first * 11;
704 case MVT::v4i16:
705 return LT.first * 14;
706 default:
707 break;
708 }
709 }
710 break;
711 }
712 case Intrinsic::umin:
713 case Intrinsic::umax:
714 case Intrinsic::smin:
715 case Intrinsic::smax: {
716 static const auto ValidMinMaxTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
717 MVT::v8i16, MVT::v2i32, MVT::v4i32,
718 MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32,
719 MVT::nxv2i64};
720 auto LT = getTypeLegalizationCost(RetTy);
721 // Type promotion for v2i8 and v2i16 types have a heavy cost when
722 // vectorising. Account for this cost to avoid vectorising unprofitable
723 // examples when vectorising loops with low trip counts.
724 bool IsSigned =
725 ICA.getID() == Intrinsic::smin || ICA.getID() == Intrinsic::smax;
726 EVT VT = TLI->getValueType(DL, RetTy, /*AllowUnknown=*/true);
727 if (VT == MVT::v2i8 || VT == MVT::v2i16 || VT == MVT::v4i8)
728 return LT.first * (IsSigned ? 5 : 3);
729 // v2i64 types get converted to cmp+bif hence the cost of 2
730 if (LT.second == MVT::v2i64)
731 return LT.first * 2;
732 if (any_of(ValidMinMaxTys, equal_to(LT.second)))
733 return LT.first;
734 break;
735 }
736 case Intrinsic::scmp:
737 case Intrinsic::ucmp: {
738 static const CostTblEntry BitreverseTbl[] = {
739 {Intrinsic::scmp, MVT::i32, 3}, // cmp+cset+csinv
740 {Intrinsic::scmp, MVT::i64, 3}, // cmp+cset+csinv
741 {Intrinsic::scmp, MVT::v8i8, 3}, // cmgt+cmgt+sub
742 {Intrinsic::scmp, MVT::v16i8, 3}, // cmgt+cmgt+sub
743 {Intrinsic::scmp, MVT::v4i16, 3}, // cmgt+cmgt+sub
744 {Intrinsic::scmp, MVT::v8i16, 3}, // cmgt+cmgt+sub
745 {Intrinsic::scmp, MVT::v2i32, 3}, // cmgt+cmgt+sub
746 {Intrinsic::scmp, MVT::v4i32, 3}, // cmgt+cmgt+sub
747 {Intrinsic::scmp, MVT::v1i64, 3}, // cmgt+cmgt+sub
748 {Intrinsic::scmp, MVT::v2i64, 3}, // cmgt+cmgt+sub
749 };
750 const auto LT = getTypeLegalizationCost(RetTy);
751 const auto *Entry =
752 CostTableLookup(BitreverseTbl, Intrinsic::scmp, LT.second);
753 if (Entry)
754 return Entry->Cost * LT.first;
755 break;
756 }
757 case Intrinsic::sadd_sat:
758 case Intrinsic::ssub_sat:
759 case Intrinsic::uadd_sat:
760 case Intrinsic::usub_sat: {
761 static const auto ValidSatTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
762 MVT::v8i16, MVT::v2i32, MVT::v4i32,
763 MVT::v2i64};
764 auto LT = getTypeLegalizationCost(RetTy);
765 // This is a base cost of 1 for the vadd, plus 3 extract shifts if we
766 // need to extend the type, as it uses shr(qadd(shl, shl)).
767 unsigned Instrs =
768 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits() ? 1 : 4;
769 if (any_of(ValidSatTys, equal_to(LT.second)))
770 return LT.first * Instrs;
771
773 uint64_t VectorSize = TS.getKnownMinValue();
774
775 if (ST->isSVEAvailable() && VectorSize >= 128 && isPowerOf2_64(VectorSize))
776 return LT.first * Instrs;
777
778 break;
779 }
780 case Intrinsic::abs: {
781 static const auto ValidAbsTys = {MVT::v8i8, MVT::v16i8, MVT::v4i16,
782 MVT::v8i16, MVT::v2i32, MVT::v4i32,
783 MVT::v2i64, MVT::nxv16i8, MVT::nxv8i16,
784 MVT::nxv4i32, MVT::nxv2i64};
785 auto LT = getTypeLegalizationCost(RetTy);
786 if (any_of(ValidAbsTys, equal_to(LT.second)))
787 return LT.first;
788 break;
789 }
790 case Intrinsic::bswap: {
791 static const auto ValidAbsTys = {MVT::v4i16, MVT::v8i16, MVT::v2i32,
792 MVT::v4i32, MVT::v2i64};
793 auto LT = getTypeLegalizationCost(RetTy);
794 if (any_of(ValidAbsTys, equal_to(LT.second)) &&
795 LT.second.getScalarSizeInBits() == RetTy->getScalarSizeInBits())
796 return LT.first;
797 break;
798 }
799 case Intrinsic::fma:
800 case Intrinsic::fmuladd: {
801 // Given a fma or fmuladd, cost it the same as a fmul instruction which are
802 // usually the same for costs. TODO: Add fp16 and bf16 expansion costs.
803 Type *EltTy = RetTy->getScalarType();
804 if (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
805 (EltTy->isHalfTy() && ST->hasFullFP16()))
806 return getArithmeticInstrCost(Instruction::FMul, RetTy, CostKind);
807 break;
808 }
809 case Intrinsic::stepvector: {
810 InstructionCost Cost = 1; // Cost of the `index' instruction
811 auto LT = getTypeLegalizationCost(RetTy);
812 // Legalisation of illegal vectors involves an `index' instruction plus
813 // (LT.first - 1) vector adds.
814 if (LT.first > 1) {
815 Type *LegalVTy = EVT(LT.second).getTypeForEVT(RetTy->getContext());
816 InstructionCost AddCost =
817 getArithmeticInstrCost(Instruction::Add, LegalVTy, CostKind);
818 Cost += AddCost * (LT.first - 1);
819 }
820 return Cost;
821 }
822 case Intrinsic::vector_extract:
823 case Intrinsic::vector_insert: {
824 // If both the vector and subvector types are legal types and the index
825 // is 0, then this should be a no-op or simple operation; return a
826 // relatively low cost.
827
828 // If arguments aren't actually supplied, then we cannot determine the
829 // value of the index. We also want to skip predicate types.
830 if (ICA.getArgs().size() != ICA.getArgTypes().size() ||
832 break;
833
834 LLVMContext &C = RetTy->getContext();
835 EVT VecVT = getTLI()->getValueType(DL, ICA.getArgTypes()[0]);
836 bool IsExtract = ICA.getID() == Intrinsic::vector_extract;
837 EVT SubVecVT = IsExtract ? getTLI()->getValueType(DL, RetTy)
838 : getTLI()->getValueType(DL, ICA.getArgTypes()[1]);
839 // Skip this if either the vector or subvector types are unpacked
840 // SVE types; they may get lowered to stack stores and loads.
841 if (isUnpackedVectorVT(VecVT) || isUnpackedVectorVT(SubVecVT))
842 break;
843
845 getTLI()->getTypeConversion(C, SubVecVT);
847 getTLI()->getTypeConversion(C, VecVT);
848 const Value *Idx = IsExtract ? ICA.getArgs()[1] : ICA.getArgs()[2];
849 const ConstantInt *CIdx = cast<ConstantInt>(Idx);
850 if (SubVecLK.first == TargetLoweringBase::TypeLegal &&
851 VecLK.first == TargetLoweringBase::TypeLegal && CIdx->isZero())
852 return TTI::TCC_Free;
853 break;
854 }
855 case Intrinsic::bitreverse: {
856 static const CostTblEntry BitreverseTbl[] = {
857 {Intrinsic::bitreverse, MVT::i32, 1},
858 {Intrinsic::bitreverse, MVT::i64, 1},
859 {Intrinsic::bitreverse, MVT::v8i8, 1},
860 {Intrinsic::bitreverse, MVT::v16i8, 1},
861 {Intrinsic::bitreverse, MVT::v4i16, 2},
862 {Intrinsic::bitreverse, MVT::v8i16, 2},
863 {Intrinsic::bitreverse, MVT::v2i32, 2},
864 {Intrinsic::bitreverse, MVT::v4i32, 2},
865 {Intrinsic::bitreverse, MVT::v1i64, 2},
866 {Intrinsic::bitreverse, MVT::v2i64, 2},
867 };
868 const auto LegalisationCost = getTypeLegalizationCost(RetTy);
869 const auto *Entry =
870 CostTableLookup(BitreverseTbl, ICA.getID(), LegalisationCost.second);
871 if (Entry) {
872 // Cost Model is using the legal type(i32) that i8 and i16 will be
873 // converted to +1 so that we match the actual lowering cost
874 if (TLI->getValueType(DL, RetTy, true) == MVT::i8 ||
875 TLI->getValueType(DL, RetTy, true) == MVT::i16)
876 return LegalisationCost.first * Entry->Cost + 1;
877
878 return LegalisationCost.first * Entry->Cost;
879 }
880 break;
881 }
882 case Intrinsic::ctpop: {
883 auto LT = getTypeLegalizationCost(RetTy);
884 MVT MTy = LT.second;
885
886 if (ST->hasCSSC() && !RetTy->isVectorTy()) {
887 int ExtraCost =
888 MTy.getScalarSizeInBits() != RetTy->getScalarSizeInBits() ? 1 : 0;
889 return LT.first + ExtraCost;
890 }
891 if (!ST->hasNEON()) {
892 // 32-bit or 64-bit ctpop without NEON is 12 instructions.
893 return getTypeLegalizationCost(RetTy).first * 12;
894 }
895 static const CostTblEntry CtpopCostTbl[] = {
896 {ISD::CTPOP, MVT::v2i64, 4},
897 {ISD::CTPOP, MVT::v4i32, 3},
898 {ISD::CTPOP, MVT::v8i16, 2},
899 {ISD::CTPOP, MVT::v16i8, 1},
900 {ISD::CTPOP, MVT::i64, 4},
901 {ISD::CTPOP, MVT::v2i32, 3},
902 {ISD::CTPOP, MVT::v4i16, 2},
903 {ISD::CTPOP, MVT::v8i8, 1},
904 {ISD::CTPOP, MVT::i32, 5},
905 // SVE types (For targets that override NEON for fixed length vectors)
906 {ISD::CTPOP, MVT::nxv2i64, 1},
907 {ISD::CTPOP, MVT::nxv4i32, 1},
908 {ISD::CTPOP, MVT::nxv8i16, 1},
909 {ISD::CTPOP, MVT::nxv16i8, 1},
910 };
911
912 // When SVE is available CNT will be used for fixed and scalable vectors.
913 if (ST->isSVEorStreamingSVEAvailable() && MTy.isFixedLengthVector())
915 128 / MTy.getScalarSizeInBits());
916
917 if (const auto *Entry = CostTableLookup(CtpopCostTbl, ISD::CTPOP, MTy)) {
918 // Extra cost of +1 when illegal vector types are legalized by promoting
919 // the integer type.
920 int ExtraCost = MTy.isVector() && MTy.getScalarSizeInBits() !=
921 RetTy->getScalarSizeInBits()
922 ? 1
923 : 0;
924 return LT.first * Entry->Cost + ExtraCost;
925 }
926 break;
927 }
928 case Intrinsic::sadd_with_overflow:
929 case Intrinsic::uadd_with_overflow:
930 case Intrinsic::ssub_with_overflow:
931 case Intrinsic::usub_with_overflow:
932 case Intrinsic::smul_with_overflow:
933 case Intrinsic::umul_with_overflow: {
934 static const CostTblEntry WithOverflowCostTbl[] = {
935 {Intrinsic::sadd_with_overflow, MVT::i8, 3},
936 {Intrinsic::uadd_with_overflow, MVT::i8, 3},
937 {Intrinsic::sadd_with_overflow, MVT::i16, 3},
938 {Intrinsic::uadd_with_overflow, MVT::i16, 3},
939 {Intrinsic::sadd_with_overflow, MVT::i32, 1},
940 {Intrinsic::uadd_with_overflow, MVT::i32, 1},
941 {Intrinsic::sadd_with_overflow, MVT::i64, 1},
942 {Intrinsic::uadd_with_overflow, MVT::i64, 1},
943 {Intrinsic::ssub_with_overflow, MVT::i8, 3},
944 {Intrinsic::usub_with_overflow, MVT::i8, 3},
945 {Intrinsic::ssub_with_overflow, MVT::i16, 3},
946 {Intrinsic::usub_with_overflow, MVT::i16, 3},
947 {Intrinsic::ssub_with_overflow, MVT::i32, 1},
948 {Intrinsic::usub_with_overflow, MVT::i32, 1},
949 {Intrinsic::ssub_with_overflow, MVT::i64, 1},
950 {Intrinsic::usub_with_overflow, MVT::i64, 1},
951 {Intrinsic::smul_with_overflow, MVT::i8, 5},
952 {Intrinsic::umul_with_overflow, MVT::i8, 4},
953 {Intrinsic::smul_with_overflow, MVT::i16, 5},
954 {Intrinsic::umul_with_overflow, MVT::i16, 4},
955 {Intrinsic::smul_with_overflow, MVT::i32, 2}, // eg umull;tst
956 {Intrinsic::umul_with_overflow, MVT::i32, 2}, // eg umull;cmp sxtw
957 {Intrinsic::smul_with_overflow, MVT::i64, 3}, // eg mul;smulh;cmp
958 {Intrinsic::umul_with_overflow, MVT::i64, 3}, // eg mul;umulh;cmp asr
959 };
960 EVT MTy = TLI->getValueType(DL, RetTy->getContainedType(0), true);
961 if (MTy.isSimple())
962 if (const auto *Entry = CostTableLookup(WithOverflowCostTbl, ICA.getID(),
963 MTy.getSimpleVT()))
964 return Entry->Cost;
965 break;
966 }
967 case Intrinsic::fptosi_sat:
968 case Intrinsic::fptoui_sat: {
969 if (ICA.getArgTypes().empty())
970 break;
971 bool IsSigned = ICA.getID() == Intrinsic::fptosi_sat;
972 auto LT = getTypeLegalizationCost(ICA.getArgTypes()[0]);
973 EVT MTy = TLI->getValueType(DL, RetTy);
974 // Check for the legal types, which are where the size of the input and the
975 // output are the same, or we are using cvt f64->i32 or f32->i64.
976 if ((LT.second == MVT::f32 || LT.second == MVT::f64 ||
977 LT.second == MVT::v2f32 || LT.second == MVT::v4f32 ||
978 LT.second == MVT::v2f64)) {
979 if ((LT.second.getScalarSizeInBits() == MTy.getScalarSizeInBits() ||
980 (LT.second == MVT::f64 && MTy == MVT::i32) ||
981 (LT.second == MVT::f32 && MTy == MVT::i64)))
982 return LT.first;
983 // Extending vector types v2f32->v2i64, fcvtl*2 + fcvt*2
984 if (LT.second.getScalarType() == MVT::f32 && MTy.isFixedLengthVector() &&
985 MTy.getScalarSizeInBits() == 64)
986 return LT.first * (MTy.getVectorNumElements() > 2 ? 4 : 2);
987 }
988 // Similarly for fp16 sizes. Without FullFP16 we generally need to fcvt to
989 // f32.
990 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
991 return LT.first + getIntrinsicInstrCost(
992 {ICA.getID(),
993 RetTy,
994 {ICA.getArgTypes()[0]->getWithNewType(
995 Type::getFloatTy(RetTy->getContext()))}},
996 CostKind);
997 if ((LT.second == MVT::f16 && MTy == MVT::i32) ||
998 (LT.second == MVT::f16 && MTy == MVT::i64) ||
999 ((LT.second == MVT::v4f16 || LT.second == MVT::v8f16) &&
1000 (LT.second.getScalarSizeInBits() == MTy.getScalarSizeInBits())))
1001 return LT.first;
1002 // Extending vector types v8f16->v8i32, fcvtl*2 + fcvt*2
1003 if (LT.second.getScalarType() == MVT::f16 && MTy.isFixedLengthVector() &&
1004 MTy.getScalarSizeInBits() == 32)
1005 return LT.first * (MTy.getVectorNumElements() > 4 ? 4 : 2);
1006 // Extending vector types v8f16->v8i32. These current scalarize but the
1007 // codegen could be better.
1008 if (LT.second.getScalarType() == MVT::f16 && MTy.isFixedLengthVector() &&
1009 MTy.getScalarSizeInBits() == 64)
1010 return MTy.getVectorNumElements() * 3;
1011
1012 // If we can we use a legal convert followed by a min+max
1013 if ((LT.second.getScalarType() == MVT::f32 ||
1014 LT.second.getScalarType() == MVT::f64 ||
1015 LT.second.getScalarType() == MVT::f16) &&
1016 LT.second.getScalarSizeInBits() >= MTy.getScalarSizeInBits()) {
1017 Type *LegalTy =
1018 Type::getIntNTy(RetTy->getContext(), LT.second.getScalarSizeInBits());
1019 if (LT.second.isVector())
1020 LegalTy = VectorType::get(LegalTy, LT.second.getVectorElementCount());
1022 IntrinsicCostAttributes Attrs1(IsSigned ? Intrinsic::smin
1023 : Intrinsic::umin,
1024 LegalTy, {LegalTy, LegalTy});
1026 IntrinsicCostAttributes Attrs2(IsSigned ? Intrinsic::smax
1027 : Intrinsic::umax,
1028 LegalTy, {LegalTy, LegalTy});
1030 return LT.first * Cost +
1031 ((LT.second.getScalarType() != MVT::f16 || ST->hasFullFP16()) ? 0
1032 : 1);
1033 }
1034 // Otherwise we need to follow the default expansion that clamps the value
1035 // using a float min/max with a fcmp+sel for nan handling when signed.
1036 Type *FPTy = ICA.getArgTypes()[0]->getScalarType();
1037 RetTy = RetTy->getScalarType();
1038 if (LT.second.isVector()) {
1039 FPTy = VectorType::get(FPTy, LT.second.getVectorElementCount());
1040 RetTy = VectorType::get(RetTy, LT.second.getVectorElementCount());
1041 }
1042 IntrinsicCostAttributes Attrs1(Intrinsic::minnum, FPTy, {FPTy, FPTy});
1044 IntrinsicCostAttributes Attrs2(Intrinsic::maxnum, FPTy, {FPTy, FPTy});
1046 Cost +=
1047 getCastInstrCost(IsSigned ? Instruction::FPToSI : Instruction::FPToUI,
1048 RetTy, FPTy, TTI::CastContextHint::None, CostKind);
1049 if (IsSigned) {
1050 Type *CondTy = RetTy->getWithNewBitWidth(1);
1051 Cost += getCmpSelInstrCost(BinaryOperator::FCmp, FPTy, CondTy,
1053 Cost += getCmpSelInstrCost(BinaryOperator::Select, RetTy, CondTy,
1055 }
1056 return LT.first * Cost;
1057 }
1058 case Intrinsic::fshl:
1059 case Intrinsic::fshr: {
1060 if (ICA.getArgs().empty())
1061 break;
1062
1063 const TTI::OperandValueInfo OpInfoZ = TTI::getOperandInfo(ICA.getArgs()[2]);
1064
1065 // ROTR / ROTL is a funnel shift with equal first and second operand. For
1066 // ROTR on integer registers (i32/i64) this can be done in a single ror
1067 // instruction. A fshl with a non-constant shift uses a neg + ror.
1068 if (RetTy->isIntegerTy() && ICA.getArgs()[0] == ICA.getArgs()[1] &&
1069 (RetTy->getPrimitiveSizeInBits() == 32 ||
1070 RetTy->getPrimitiveSizeInBits() == 64)) {
1071 InstructionCost NegCost =
1072 (ICA.getID() == Intrinsic::fshl && !OpInfoZ.isConstant()) ? 1 : 0;
1073 return 1 + NegCost;
1074 }
1075
1076 // TODO: Add handling for fshl where third argument is not a constant.
1077 if (!OpInfoZ.isConstant())
1078 break;
1079
1080 const auto LegalisationCost = getTypeLegalizationCost(RetTy);
1081 if (OpInfoZ.isUniform()) {
1082 static const CostTblEntry FshlTbl[] = {
1083 {Intrinsic::fshl, MVT::v4i32, 2}, // shl + usra
1084 {Intrinsic::fshl, MVT::v2i64, 2}, {Intrinsic::fshl, MVT::v16i8, 2},
1085 {Intrinsic::fshl, MVT::v8i16, 2}, {Intrinsic::fshl, MVT::v2i32, 2},
1086 {Intrinsic::fshl, MVT::v8i8, 2}, {Intrinsic::fshl, MVT::v4i16, 2}};
1087 // Costs for both fshl & fshr are the same, so just pass Intrinsic::fshl
1088 // to avoid having to duplicate the costs.
1089 const auto *Entry =
1090 CostTableLookup(FshlTbl, Intrinsic::fshl, LegalisationCost.second);
1091 if (Entry)
1092 return LegalisationCost.first * Entry->Cost;
1093 }
1094
1095 auto TyL = getTypeLegalizationCost(RetTy);
1096 if (!RetTy->isIntegerTy())
1097 break;
1098
1099 // Estimate cost manually, as types like i8 and i16 will get promoted to
1100 // i32 and CostTableLookup will ignore the extra conversion cost.
1101 bool HigherCost = (RetTy->getScalarSizeInBits() != 32 &&
1102 RetTy->getScalarSizeInBits() < 64) ||
1103 (RetTy->getScalarSizeInBits() % 64 != 0);
1104 unsigned ExtraCost = HigherCost ? 1 : 0;
1105 if (RetTy->getScalarSizeInBits() == 32 ||
1106 RetTy->getScalarSizeInBits() == 64)
1107 ExtraCost = 0; // fhsl/fshr for i32 and i64 can be lowered to a single
1108 // extr instruction.
1109 else if (HigherCost)
1110 ExtraCost = 1;
1111 else
1112 break;
1113 return TyL.first + ExtraCost;
1114 }
1115 case Intrinsic::get_active_lane_mask: {
1116 auto RetTy = cast<VectorType>(ICA.getReturnType());
1117 EVT RetVT = getTLI()->getValueType(DL, RetTy);
1118 EVT OpVT = getTLI()->getValueType(DL, ICA.getArgTypes()[0]);
1119 if (getTLI()->shouldExpandGetActiveLaneMask(RetVT, OpVT))
1120 break;
1121
1122 if (RetTy->isScalableTy()) {
1123 if (TLI->getTypeAction(RetTy->getContext(), RetVT) !=
1125 break;
1126
1127 auto LT = getTypeLegalizationCost(RetTy);
1128 InstructionCost Cost = LT.first;
1129 // When SVE2p1 or SME2 is available, we can halve getTypeLegalizationCost
1130 // as get_active_lane_mask may lower to the sve_whilelo_x2 intrinsic, e.g.
1131 // nxv32i1 = get_active_lane_mask(base, idx) ->
1132 // {nxv16i1, nxv16i1} = sve_whilelo_x2(base, idx)
1133 if (ST->hasSVE2p1() || ST->hasSME2()) {
1134 Cost /= 2;
1135 if (Cost == 1)
1136 return Cost;
1137 }
1138
1139 // If more than one whilelo intrinsic is required, include the extra cost
1140 // required by the saturating add & select required to increment the
1141 // start value after the first intrinsic call.
1142 Type *OpTy = ICA.getArgTypes()[0];
1143 IntrinsicCostAttributes AddAttrs(Intrinsic::uadd_sat, OpTy, {OpTy, OpTy});
1144 InstructionCost SplitCost = getIntrinsicInstrCost(AddAttrs, CostKind);
1145 Type *CondTy = OpTy->getWithNewBitWidth(1);
1146 SplitCost += getCmpSelInstrCost(Instruction::Select, OpTy, CondTy,
1148 return Cost + (SplitCost * (Cost - 1));
1149 } else if (!getTLI()->isTypeLegal(RetVT)) {
1150 // We don't have enough context at this point to determine if the mask
1151 // is going to be kept live after the block, which will force the vXi1
1152 // type to be expanded to legal vectors of integers, e.g. v4i1->v4i32.
1153 // For now, we just assume the vectorizer created this intrinsic and
1154 // the result will be the input for a PHI. In this case the cost will
1155 // be extremely high for fixed-width vectors.
1156 // NOTE: getScalarizationOverhead returns a cost that's far too
1157 // pessimistic for the actual generated codegen. In reality there are
1158 // two instructions generated per lane.
1159 return cast<FixedVectorType>(RetTy)->getNumElements() * 2;
1160 }
1161 break;
1162 }
1163 case Intrinsic::experimental_vector_match: {
1164 if (!ST->hasSVE2() || !ST->isSVEAvailable())
1165 break;
1166
1167 auto *NeedleTy = cast<FixedVectorType>(ICA.getArgTypes()[1]);
1168
1169 // We expand vector.matches with <= 2 elements to a chain of compares.
1170 unsigned SearchSize = NeedleTy->getNumElements();
1171 if (SearchSize <= 2)
1172 break;
1173
1174 auto [LegalParts, SearchVT] = getTypeLegalizationCost(ICA.getArgTypes()[0]);
1175 if (!is_contained(
1176 {MVT::nxv8i16, MVT::nxv16i8, MVT::v8i16, MVT::v16i8, MVT::v8i8},
1177 SearchVT.SimpleTy))
1178 break;
1179
1180 unsigned ElementSizeInBits = SearchVT.getScalarSizeInBits();
1181
1182 // Number of needle elements we can compare per `match` instruction.
1183 unsigned NeedleEltsPerMatch = AArch64::SVEBitsPerBlock / ElementSizeInBits;
1184
1185 // How many `match` instructions we need to match `SearchSize` elements.
1186 unsigned MatchesRequiredForNeedle =
1187 llvm::divideCeil(SearchSize, NeedleEltsPerMatch);
1188
1189 // Base cost for MATCH instructions. At least on the Neoverse V2 and
1190 // Neoverse V3, these are cheap operations with the same latency as a
1191 // vector ADD. In most cases, however, we also need to do an extra DUP.
1192 // For fixed-length vectors we currently need an extra five--six
1193 // instructions besides the MATCH.
1195 if (isa<FixedVectorType>(RetTy))
1196 Cost += 10;
1197
1198 return Cost * LegalParts * MatchesRequiredForNeedle;
1199 }
1200 case Intrinsic::cttz: {
1201 auto LT = getTypeLegalizationCost(ICA.getArgTypes()[0]);
1202 if (LT.second == MVT::v8i8 || LT.second == MVT::v16i8)
1203 return LT.first * 2;
1204 if (LT.second == MVT::v4i16 || LT.second == MVT::v8i16 ||
1205 LT.second == MVT::v2i32 || LT.second == MVT::v4i32)
1206 return LT.first * 3;
1207 break;
1208 }
1209 case Intrinsic::experimental_cttz_elts: {
1210 EVT ArgVT = getTLI()->getValueType(DL, ICA.getArgTypes()[0]);
1211 if (getTLI()->isOperationCustom(ISD::CTTZ_ELTS, ArgVT)) {
1212 // This will consist of a SVE brkb and a cntp instruction. These
1213 // typically have the same latency and half the throughput as a vector
1214 // add instruction.
1215 return 4;
1216 }
1217 break;
1218 }
1219 case Intrinsic::loop_dependence_raw_mask:
1220 case Intrinsic::loop_dependence_war_mask: {
1221 // The whilewr/rw instructions require SVE2 or SME.
1222 if (ST->hasSVE2() || ST->hasSME()) {
1223 EVT VecVT = getTLI()->getValueType(DL, RetTy);
1224 unsigned EltSizeInBytes =
1225 cast<ConstantInt>(ICA.getArgs()[2])->getZExtValue();
1226 if (!is_contained({1u, 2u, 4u, 8u}, EltSizeInBytes) ||
1227 VecVT.getVectorMinNumElements() != (16 / EltSizeInBytes))
1228 break;
1229 // For fixed-vector types we need to AND the mask with a ptrue vl<N>.
1230 return isa<FixedVectorType>(RetTy) ? 2 : 1;
1231 }
1232 break;
1233 }
1234 case Intrinsic::experimental_vector_extract_last_active:
1235 if (ST->isSVEorStreamingSVEAvailable()) {
1236 auto [LegalCost, _] = getTypeLegalizationCost(ICA.getArgTypes()[0]);
1237 // This should turn into chained clastb instructions.
1238 return LegalCost;
1239 }
1240 break;
1241 case Intrinsic::pow: {
1242 // For scalar calls we know the target has the libcall, and for fixed-width
1243 // vectors we know for the worst case it can be scalarised.
1244 EVT VT = getTLI()->getValueType(DL, RetTy);
1245 RTLIB::Libcall LC = RTLIB::getPOW(VT);
1246 bool HasLibcall = getTLI()->getLibcallImpl(LC) != RTLIB::Unsupported;
1247 bool CanLowerWithLibcalls = !isa<ScalableVectorType>(RetTy) || HasLibcall;
1248
1249 // If we know that the call can be lowered with libcalls then it's safe to
1250 // reduce the costs in some cases. This is important for scalable vectors,
1251 // since we cannot scalarize the call in the absence of a vector math
1252 // library.
1253 if (CanLowerWithLibcalls && ICA.getInst() && !ICA.getArgs().empty()) {
1254 // If we know the fast math flags and the exponent is a constant then the
1255 // cost may be less for some exponents like 0.25 and 0.75.
1256 const Constant *ExpC = dyn_cast<Constant>(ICA.getArgs()[1]);
1257 if (ExpC && isa<VectorType>(ExpC->getType()))
1258 ExpC = ExpC->getSplatValue();
1259 if (auto *ExpF = dyn_cast_or_null<ConstantFP>(ExpC)) {
1260 // The argument must be a FP constant.
1261 bool Is025 = ExpF->getValueAPF().isExactlyValue(0.25);
1262 bool Is075 = ExpF->getValueAPF().isExactlyValue(0.75);
1263 FastMathFlags FMF = ICA.getInst()->getFastMathFlags();
1264 if ((Is025 || Is075) && FMF.noInfs() && FMF.approxFunc() &&
1265 (!Is025 || FMF.noSignedZeros())) {
1266 IntrinsicCostAttributes Attrs(Intrinsic::sqrt, RetTy, {RetTy}, FMF);
1268 if (Is025)
1269 return 2 * Sqrt;
1271 getArithmeticInstrCost(Instruction::FMul, RetTy, CostKind);
1272 return (Sqrt * 2) + FMul;
1273 }
1274 // TODO: For 1/3 exponents we expect the cbrt call to be slightly
1275 // cheaper than pow.
1276 }
1277 }
1278
1279 if (HasLibcall)
1280 return getCallInstrCost(nullptr, RetTy, ICA.getArgTypes(), CostKind);
1281 break;
1282 }
1283 case Intrinsic::sqrt:
1284 case Intrinsic::fabs:
1285 case Intrinsic::ceil:
1286 case Intrinsic::floor:
1287 case Intrinsic::nearbyint:
1288 case Intrinsic::round:
1289 case Intrinsic::rint:
1290 case Intrinsic::roundeven:
1291 case Intrinsic::trunc:
1292 case Intrinsic::minnum:
1293 case Intrinsic::maxnum:
1294 case Intrinsic::minimum:
1295 case Intrinsic::maximum: {
1296 if (isa<ScalableVectorType>(RetTy) && ST->isSVEorStreamingSVEAvailable()) {
1297 auto LT = getTypeLegalizationCost(RetTy);
1298 return LT.first;
1299 }
1300 break;
1301 }
1302 default:
1303 break;
1304 }
1306}
1307
1308/// The function will remove redundant reinterprets casting in the presence
1309/// of the control flow
1310static std::optional<Instruction *> processPhiNode(InstCombiner &IC,
1311 IntrinsicInst &II) {
1313 auto RequiredType = II.getType();
1314
1315 auto *PN = dyn_cast<PHINode>(II.getArgOperand(0));
1316 assert(PN && "Expected Phi Node!");
1317
1318 // Don't create a new Phi unless we can remove the old one.
1319 if (!PN->hasOneUse())
1320 return std::nullopt;
1321
1322 for (Value *IncValPhi : PN->incoming_values()) {
1323 auto *Reinterpret = dyn_cast<IntrinsicInst>(IncValPhi);
1324 if (!Reinterpret ||
1325 Reinterpret->getIntrinsicID() !=
1326 Intrinsic::aarch64_sve_convert_to_svbool ||
1327 RequiredType != Reinterpret->getArgOperand(0)->getType())
1328 return std::nullopt;
1329 }
1330
1331 // Create the new Phi
1332 IC.Builder.SetInsertPoint(PN);
1333 PHINode *NPN = IC.Builder.CreatePHI(RequiredType, PN->getNumIncomingValues());
1334 Worklist.push_back(PN);
1335
1336 for (unsigned I = 0; I < PN->getNumIncomingValues(); I++) {
1337 auto *Reinterpret = cast<Instruction>(PN->getIncomingValue(I));
1338 NPN->addIncoming(Reinterpret->getOperand(0), PN->getIncomingBlock(I));
1339 Worklist.push_back(Reinterpret);
1340 }
1341
1342 // Cleanup Phi Node and reinterprets
1343 return IC.replaceInstUsesWith(II, NPN);
1344}
1345
1346// A collection of properties common to SVE intrinsics that allow for combines
1347// to be written without needing to know the specific intrinsic.
1349 //
1350 // Helper routines for common intrinsic definitions.
1351 //
1352
1353 // e.g. llvm.aarch64.sve.add pg, op1, op2
1354 // with IID ==> llvm.aarch64.sve.add_u
1355 static SVEIntrinsicInfo
1362
1363 // e.g. llvm.aarch64.sve.neg inactive, pg, op
1370
1371 // e.g. llvm.aarch64.sve.fcvtnt inactive, pg, op
1377
1378 // e.g. llvm.aarch64.sve.add_u pg, op1, op2
1384
1385 // e.g. llvm.aarch64.sve.prf pg, ptr (GPIndex = 0)
1386 // llvm.aarch64.sve.st1 data, pg, ptr (GPIndex = 1)
1387 static SVEIntrinsicInfo defaultVoidOp(unsigned GPIndex) {
1388 return SVEIntrinsicInfo()
1391 }
1392
1393 // e.g. llvm.aarch64.sve.cmpeq pg, op1, op2
1394 // llvm.aarch64.sve.ld1 pg, ptr
1401
1402 // All properties relate to predication and thus having a general predicate
1403 // is the minimum requirement to say there is intrinsic info to act on.
1404 explicit operator bool() const { return hasGoverningPredicate(); }
1405
1406 //
1407 // Properties relating to the governing predicate.
1408 //
1409
1411 return GoverningPredicateIdx != std::numeric_limits<unsigned>::max();
1412 }
1413
1415 assert(hasGoverningPredicate() && "Property not set!");
1416 return GoverningPredicateIdx;
1417 }
1418
1420 assert(!hasGoverningPredicate() && "Cannot set property twice!");
1421 GoverningPredicateIdx = Index;
1422 return *this;
1423 }
1424
1425 //
1426 // Properties relating to operations the intrinsic could be transformed into.
1427 // NOTE: This does not mean such a transformation is always possible, but the
1428 // knowledge makes it possible to reuse existing optimisations without needing
1429 // to embed specific handling for each intrinsic. For example, instruction
1430 // simplification can be used to optimise an intrinsic's active lanes.
1431 //
1432
1433 //
1434 // Intrinsic that produces the same result for active lanes.
1435 //
1436
1438 return UndefIntrinsic != Intrinsic::not_intrinsic;
1439 }
1440
1442 assert(hasMatchingUndefIntrinsic() && "Property not set!");
1443 return UndefIntrinsic;
1444 }
1445
1447 assert(!hasMatchingUndefIntrinsic() && "Cannot set property twice!");
1448 UndefIntrinsic = IID;
1449 return *this;
1450 }
1451
1452 //
1453 // Instruction where active lanes produce the same result.
1454 //
1455
1456 bool hasMatchingIROpode() const { return IROpcode != 0; }
1457
1458 unsigned getMatchingIROpode() const {
1459 assert(hasMatchingIROpode() && "Property not set!");
1460 return IROpcode;
1461 }
1462
1464 assert(!hasMatchingIROpode() && "Cannot set property twice!");
1465 IROpcode = Opcode;
1466 return *this;
1467 }
1468
1469 bool hasCmpPredicate() const {
1470 return CmpPredicate != CmpInst::BAD_ICMP_PREDICATE;
1471 }
1472
1474 assert(hasCmpPredicate() && "Property not set!");
1475 return CmpPredicate;
1476 }
1477
1479 assert(!hasCmpPredicate() && "Cannot set property twice!");
1480 CmpPredicate = Pred;
1481
1482 if (CmpInst::isFPPredicate(Pred))
1483 return setMatchingIROpcode(Instruction::FCmp);
1484
1485 if (CmpInst::isIntPredicate(Pred))
1486 return setMatchingIROpcode(Instruction::ICmp);
1487
1488 llvm_unreachable("Unsupported compare predicate!");
1489 }
1490
1491 //
1492 // Properties relating to the result of inactive lanes.
1493 //
1494
1496 return ResultLanes == InactiveLanesTakenFromOperand;
1497 }
1498
1500 assert(inactiveLanesTakenFromOperand() && "Property not set!");
1501 return OperandIdxForInactiveLanes;
1502 }
1503
1505 assert(ResultLanes == Uninitialized && "Cannot set property twice!");
1506 ResultLanes = InactiveLanesTakenFromOperand;
1507 OperandIdxForInactiveLanes = Index;
1508 return *this;
1509 }
1510
1512 return ResultLanes == InactiveLanesAreNotDefined;
1513 }
1514
1516 assert(ResultLanes == Uninitialized && "Cannot set property twice!");
1517 ResultLanes = InactiveLanesAreNotDefined;
1518 return *this;
1519 }
1520
1522 return ResultLanes == InactiveLanesAreUnused;
1523 }
1524
1526 assert(ResultLanes == Uninitialized && "Cannot set property twice!");
1527 ResultLanes = InactiveLanesAreUnused;
1528 return *this;
1529 }
1530
1531 // NOTE: Whilst not limited to only inactive lanes, the common use case is:
1532 // inactiveLanesAreZeroed =
1533 // resultIsZeroInitialized() && inactiveLanesAreUnused()
1534 bool resultIsZeroInitialized() const { return ResultIsZeroInitialized; }
1535
1537 ResultIsZeroInitialized = true;
1538 return *this;
1539 }
1540
1541 //
1542 // The first operand of unary merging operations is typically only used to
1543 // set the result for inactive lanes. Knowing this allows us to deadcode the
1544 // operand when we can prove there are no inactive lanes.
1545 //
1546
1548 return OperandIdxWithNoActiveLanes != std::numeric_limits<unsigned>::max();
1549 }
1550
1552 assert(hasOperandWithNoActiveLanes() && "Property not set!");
1553 return OperandIdxWithNoActiveLanes;
1554 }
1555
1557 assert(!hasOperandWithNoActiveLanes() && "Cannot set property twice!");
1558 OperandIdxWithNoActiveLanes = Index;
1559 return *this;
1560 }
1561
1562private:
1563 unsigned GoverningPredicateIdx = std::numeric_limits<unsigned>::max();
1564
1565 Intrinsic::ID UndefIntrinsic = Intrinsic::not_intrinsic;
1566 unsigned IROpcode = 0;
1568
1569 enum PredicationStyle {
1571 InactiveLanesTakenFromOperand,
1572 InactiveLanesAreNotDefined,
1573 InactiveLanesAreUnused
1574 } ResultLanes = Uninitialized;
1575
1576 bool ResultIsZeroInitialized = false;
1577 unsigned OperandIdxForInactiveLanes = std::numeric_limits<unsigned>::max();
1578 unsigned OperandIdxWithNoActiveLanes = std::numeric_limits<unsigned>::max();
1579};
1580
1582 // Some SVE intrinsics do not use scalable vector types, but since they are
1583 // not relevant from an SVEIntrinsicInfo perspective, they are also ignored.
1584 if (!isa<ScalableVectorType>(II.getType()) &&
1585 all_of(II.args(), [&](const Value *V) {
1586 return !isa<ScalableVectorType>(V->getType());
1587 }))
1588 return SVEIntrinsicInfo();
1589
1590 Intrinsic::ID IID = II.getIntrinsicID();
1591 switch (IID) {
1592 default:
1593 break;
1594 case Intrinsic::aarch64_sve_fcvt_bf16f32_v2:
1595 case Intrinsic::aarch64_sve_fcvt_f16f32:
1596 case Intrinsic::aarch64_sve_fcvt_f16f64:
1597 case Intrinsic::aarch64_sve_fcvt_f32f16:
1598 case Intrinsic::aarch64_sve_fcvt_f32f64:
1599 case Intrinsic::aarch64_sve_fcvt_f64f16:
1600 case Intrinsic::aarch64_sve_fcvt_f64f32:
1601 case Intrinsic::aarch64_sve_fcvtlt_f32f16:
1602 case Intrinsic::aarch64_sve_fcvtlt_f64f32:
1603 case Intrinsic::aarch64_sve_fcvtx_f32f64:
1604 case Intrinsic::aarch64_sve_fcvtzs:
1605 case Intrinsic::aarch64_sve_fcvtzs_i32f16:
1606 case Intrinsic::aarch64_sve_fcvtzs_i32f64:
1607 case Intrinsic::aarch64_sve_fcvtzs_i64f16:
1608 case Intrinsic::aarch64_sve_fcvtzs_i64f32:
1609 case Intrinsic::aarch64_sve_fcvtzu:
1610 case Intrinsic::aarch64_sve_fcvtzu_i32f16:
1611 case Intrinsic::aarch64_sve_fcvtzu_i32f64:
1612 case Intrinsic::aarch64_sve_fcvtzu_i64f16:
1613 case Intrinsic::aarch64_sve_fcvtzu_i64f32:
1614 case Intrinsic::aarch64_sve_revb:
1615 case Intrinsic::aarch64_sve_revh:
1616 case Intrinsic::aarch64_sve_revw:
1617 case Intrinsic::aarch64_sve_revd:
1618 case Intrinsic::aarch64_sve_scvtf:
1619 case Intrinsic::aarch64_sve_scvtf_f16i32:
1620 case Intrinsic::aarch64_sve_scvtf_f16i64:
1621 case Intrinsic::aarch64_sve_scvtf_f32i64:
1622 case Intrinsic::aarch64_sve_scvtf_f64i32:
1623 case Intrinsic::aarch64_sve_ucvtf:
1624 case Intrinsic::aarch64_sve_ucvtf_f16i32:
1625 case Intrinsic::aarch64_sve_ucvtf_f16i64:
1626 case Intrinsic::aarch64_sve_ucvtf_f32i64:
1627 case Intrinsic::aarch64_sve_ucvtf_f64i32:
1629
1630 case Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2:
1631 case Intrinsic::aarch64_sve_fcvtnt_f16f32:
1632 case Intrinsic::aarch64_sve_fcvtnt_f32f64:
1633 case Intrinsic::aarch64_sve_fcvtxnt_f32f64:
1635
1636 case Intrinsic::aarch64_sve_fabd:
1637 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fabd_u);
1638 case Intrinsic::aarch64_sve_fadd:
1639 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fadd_u)
1640 .setMatchingIROpcode(Instruction::FAdd);
1641 case Intrinsic::aarch64_sve_fdiv:
1642 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fdiv_u)
1643 .setMatchingIROpcode(Instruction::FDiv);
1644 case Intrinsic::aarch64_sve_fmax:
1645 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmax_u);
1646 case Intrinsic::aarch64_sve_fmaxnm:
1647 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmaxnm_u);
1648 case Intrinsic::aarch64_sve_fmin:
1649 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmin_u);
1650 case Intrinsic::aarch64_sve_fminnm:
1651 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fminnm_u);
1652 case Intrinsic::aarch64_sve_fmla:
1653 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmla_u);
1654 case Intrinsic::aarch64_sve_fmls:
1655 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmls_u);
1656 case Intrinsic::aarch64_sve_fmul:
1657 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmul_u)
1658 .setMatchingIROpcode(Instruction::FMul);
1659 case Intrinsic::aarch64_sve_fmulx:
1660 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fmulx_u);
1661 case Intrinsic::aarch64_sve_fnmla:
1662 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fnmla_u);
1663 case Intrinsic::aarch64_sve_fnmls:
1664 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fnmls_u);
1665 case Intrinsic::aarch64_sve_fsub:
1666 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_fsub_u)
1667 .setMatchingIROpcode(Instruction::FSub);
1668 case Intrinsic::aarch64_sve_add:
1669 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_add_u)
1670 .setMatchingIROpcode(Instruction::Add);
1671 case Intrinsic::aarch64_sve_mla:
1672 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_mla_u);
1673 case Intrinsic::aarch64_sve_mls:
1674 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_mls_u);
1675 case Intrinsic::aarch64_sve_mul:
1676 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_mul_u)
1677 .setMatchingIROpcode(Instruction::Mul);
1678 case Intrinsic::aarch64_sve_sabd:
1679 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sabd_u);
1680 case Intrinsic::aarch64_sve_sdiv:
1681 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sdiv_u)
1682 .setMatchingIROpcode(Instruction::SDiv);
1683 case Intrinsic::aarch64_sve_smax:
1684 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_smax_u);
1685 case Intrinsic::aarch64_sve_smin:
1686 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_smin_u);
1687 case Intrinsic::aarch64_sve_smulh:
1688 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_smulh_u);
1689 case Intrinsic::aarch64_sve_sub:
1690 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sub_u)
1691 .setMatchingIROpcode(Instruction::Sub);
1692 case Intrinsic::aarch64_sve_uabd:
1693 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_uabd_u);
1694 case Intrinsic::aarch64_sve_udiv:
1695 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_udiv_u)
1696 .setMatchingIROpcode(Instruction::UDiv);
1697 case Intrinsic::aarch64_sve_umax:
1698 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_umax_u);
1699 case Intrinsic::aarch64_sve_umin:
1700 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_umin_u);
1701 case Intrinsic::aarch64_sve_umulh:
1702 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_umulh_u);
1703 case Intrinsic::aarch64_sve_asr:
1704 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_asr_u)
1705 .setMatchingIROpcode(Instruction::AShr);
1706 case Intrinsic::aarch64_sve_lsl:
1707 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_lsl_u)
1708 .setMatchingIROpcode(Instruction::Shl);
1709 case Intrinsic::aarch64_sve_lsr:
1710 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_lsr_u)
1711 .setMatchingIROpcode(Instruction::LShr);
1712 case Intrinsic::aarch64_sve_and:
1713 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_and_u)
1714 .setMatchingIROpcode(Instruction::And);
1715 case Intrinsic::aarch64_sve_bic:
1716 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_bic_u);
1717 case Intrinsic::aarch64_sve_eor:
1718 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_eor_u)
1719 .setMatchingIROpcode(Instruction::Xor);
1720 case Intrinsic::aarch64_sve_orr:
1721 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_orr_u)
1722 .setMatchingIROpcode(Instruction::Or);
1723 case Intrinsic::aarch64_sve_shsub:
1724 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_shsub_u);
1725 case Intrinsic::aarch64_sve_shsubr:
1727 case Intrinsic::aarch64_sve_sqrshl:
1728 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sqrshl_u);
1729 case Intrinsic::aarch64_sve_sqshl:
1730 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sqshl_u);
1731 case Intrinsic::aarch64_sve_sqsub:
1732 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_sqsub_u);
1733 case Intrinsic::aarch64_sve_srshl:
1734 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_srshl_u);
1735 case Intrinsic::aarch64_sve_uhsub:
1736 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_uhsub_u);
1737 case Intrinsic::aarch64_sve_uhsubr:
1739 case Intrinsic::aarch64_sve_uqrshl:
1740 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_uqrshl_u);
1741 case Intrinsic::aarch64_sve_uqshl:
1742 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_uqshl_u);
1743 case Intrinsic::aarch64_sve_uqsub:
1744 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_uqsub_u);
1745 case Intrinsic::aarch64_sve_urshl:
1746 return SVEIntrinsicInfo::defaultMergingOp(Intrinsic::aarch64_sve_urshl_u);
1747
1748 case Intrinsic::aarch64_sve_add_u:
1750 Instruction::Add);
1751 case Intrinsic::aarch64_sve_and_u:
1753 Instruction::And);
1754 case Intrinsic::aarch64_sve_asr_u:
1756 Instruction::AShr);
1757 case Intrinsic::aarch64_sve_eor_u:
1759 Instruction::Xor);
1760 case Intrinsic::aarch64_sve_fadd_u:
1762 Instruction::FAdd);
1763 case Intrinsic::aarch64_sve_fdiv_u:
1765 Instruction::FDiv);
1766 case Intrinsic::aarch64_sve_fmul_u:
1768 Instruction::FMul);
1769 case Intrinsic::aarch64_sve_fsub_u:
1771 Instruction::FSub);
1772 case Intrinsic::aarch64_sve_lsl_u:
1774 Instruction::Shl);
1775 case Intrinsic::aarch64_sve_lsr_u:
1777 Instruction::LShr);
1778 case Intrinsic::aarch64_sve_mul_u:
1780 Instruction::Mul);
1781 case Intrinsic::aarch64_sve_orr_u:
1783 Instruction::Or);
1784 case Intrinsic::aarch64_sve_sdiv_u:
1786 Instruction::SDiv);
1787 case Intrinsic::aarch64_sve_sub_u:
1789 Instruction::Sub);
1790 case Intrinsic::aarch64_sve_udiv_u:
1792 Instruction::UDiv);
1793
1794 case Intrinsic::aarch64_sve_addqv:
1795 case Intrinsic::aarch64_sve_bic_z:
1796 case Intrinsic::aarch64_sve_brka_z:
1797 case Intrinsic::aarch64_sve_brkb_z:
1798 case Intrinsic::aarch64_sve_brkn_z:
1799 case Intrinsic::aarch64_sve_brkpa_z:
1800 case Intrinsic::aarch64_sve_brkpb_z:
1801 case Intrinsic::aarch64_sve_cntp:
1802 case Intrinsic::aarch64_sve_compact:
1803 case Intrinsic::aarch64_sve_eorv:
1804 case Intrinsic::aarch64_sve_eorqv:
1805 case Intrinsic::aarch64_sve_nand_z:
1806 case Intrinsic::aarch64_sve_nor_z:
1807 case Intrinsic::aarch64_sve_orn_z:
1808 case Intrinsic::aarch64_sve_orv:
1809 case Intrinsic::aarch64_sve_orqv:
1810 case Intrinsic::aarch64_sve_pnext:
1811 case Intrinsic::aarch64_sve_rdffr_z:
1812 case Intrinsic::aarch64_sve_saddv:
1813 case Intrinsic::aarch64_sve_uaddv:
1814 case Intrinsic::aarch64_sve_umaxv:
1815 case Intrinsic::aarch64_sve_umaxqv:
1816 case Intrinsic::aarch64_sve_facge:
1817 case Intrinsic::aarch64_sve_facgt:
1818 case Intrinsic::aarch64_sve_ld1:
1819 case Intrinsic::aarch64_sve_ld1_gather:
1820 case Intrinsic::aarch64_sve_ld1_gather_index:
1821 case Intrinsic::aarch64_sve_ld1_gather_scalar_offset:
1822 case Intrinsic::aarch64_sve_ld1_gather_sxtw:
1823 case Intrinsic::aarch64_sve_ld1_gather_sxtw_index:
1824 case Intrinsic::aarch64_sve_ld1_gather_uxtw:
1825 case Intrinsic::aarch64_sve_ld1_gather_uxtw_index:
1826 case Intrinsic::aarch64_sve_ld1q_gather_index:
1827 case Intrinsic::aarch64_sve_ld1q_gather_scalar_offset:
1828 case Intrinsic::aarch64_sve_ld1q_gather_vector_offset:
1829 case Intrinsic::aarch64_sve_ld1ro:
1830 case Intrinsic::aarch64_sve_ld1rq:
1831 case Intrinsic::aarch64_sve_ld1udq:
1832 case Intrinsic::aarch64_sve_ld1uwq:
1833 case Intrinsic::aarch64_sve_ld2_sret:
1834 case Intrinsic::aarch64_sve_ld2q_sret:
1835 case Intrinsic::aarch64_sve_ld3_sret:
1836 case Intrinsic::aarch64_sve_ld3q_sret:
1837 case Intrinsic::aarch64_sve_ld4_sret:
1838 case Intrinsic::aarch64_sve_ld4q_sret:
1839 case Intrinsic::aarch64_sve_ldff1:
1840 case Intrinsic::aarch64_sve_ldff1_gather:
1841 case Intrinsic::aarch64_sve_ldff1_gather_index:
1842 case Intrinsic::aarch64_sve_ldff1_gather_scalar_offset:
1843 case Intrinsic::aarch64_sve_ldff1_gather_sxtw:
1844 case Intrinsic::aarch64_sve_ldff1_gather_sxtw_index:
1845 case Intrinsic::aarch64_sve_ldff1_gather_uxtw:
1846 case Intrinsic::aarch64_sve_ldff1_gather_uxtw_index:
1847 case Intrinsic::aarch64_sve_ldnf1:
1848 case Intrinsic::aarch64_sve_ldnt1:
1849 case Intrinsic::aarch64_sve_ldnt1_gather:
1850 case Intrinsic::aarch64_sve_ldnt1_gather_index:
1851 case Intrinsic::aarch64_sve_ldnt1_gather_scalar_offset:
1852 case Intrinsic::aarch64_sve_ldnt1_gather_uxtw:
1854
1855 case Intrinsic::aarch64_sve_and_z:
1857 Instruction::And);
1858 case Intrinsic::aarch64_sve_orr_z:
1860 Instruction::Or);
1861 case Intrinsic::aarch64_sve_eor_z:
1863 Instruction::Xor);
1864
1865 case Intrinsic::aarch64_sve_cmpeq:
1866 case Intrinsic::aarch64_sve_cmpeq_wide:
1869 case Intrinsic::aarch64_sve_cmpge:
1870 case Intrinsic::aarch64_sve_cmpge_wide:
1873 case Intrinsic::aarch64_sve_cmpgt:
1874 case Intrinsic::aarch64_sve_cmpgt_wide:
1877 case Intrinsic::aarch64_sve_cmphi:
1878 case Intrinsic::aarch64_sve_cmphi_wide:
1881 case Intrinsic::aarch64_sve_cmphs:
1882 case Intrinsic::aarch64_sve_cmphs_wide:
1885 case Intrinsic::aarch64_sve_cmple_wide:
1888 case Intrinsic::aarch64_sve_cmplo_wide:
1891 case Intrinsic::aarch64_sve_cmpls_wide:
1894 case Intrinsic::aarch64_sve_cmplt_wide:
1897 case Intrinsic::aarch64_sve_cmpne:
1898 case Intrinsic::aarch64_sve_cmpne_wide:
1901 case Intrinsic::aarch64_sve_fcmpeq:
1904 case Intrinsic::aarch64_sve_fcmpge:
1907 case Intrinsic::aarch64_sve_fcmpgt:
1910 case Intrinsic::aarch64_sve_fcmpne:
1913 case Intrinsic::aarch64_sve_fcmpuo:
1916
1917 case Intrinsic::aarch64_sve_prf:
1918 case Intrinsic::aarch64_sve_prfb_gather_index:
1919 case Intrinsic::aarch64_sve_prfb_gather_scalar_offset:
1920 case Intrinsic::aarch64_sve_prfb_gather_sxtw_index:
1921 case Intrinsic::aarch64_sve_prfb_gather_uxtw_index:
1922 case Intrinsic::aarch64_sve_prfd_gather_index:
1923 case Intrinsic::aarch64_sve_prfd_gather_scalar_offset:
1924 case Intrinsic::aarch64_sve_prfd_gather_sxtw_index:
1925 case Intrinsic::aarch64_sve_prfd_gather_uxtw_index:
1926 case Intrinsic::aarch64_sve_prfh_gather_index:
1927 case Intrinsic::aarch64_sve_prfh_gather_scalar_offset:
1928 case Intrinsic::aarch64_sve_prfh_gather_sxtw_index:
1929 case Intrinsic::aarch64_sve_prfh_gather_uxtw_index:
1930 case Intrinsic::aarch64_sve_prfw_gather_index:
1931 case Intrinsic::aarch64_sve_prfw_gather_scalar_offset:
1932 case Intrinsic::aarch64_sve_prfw_gather_sxtw_index:
1933 case Intrinsic::aarch64_sve_prfw_gather_uxtw_index:
1935
1936 case Intrinsic::aarch64_sve_st1_scatter:
1937 case Intrinsic::aarch64_sve_st1_scatter_scalar_offset:
1938 case Intrinsic::aarch64_sve_st1_scatter_sxtw:
1939 case Intrinsic::aarch64_sve_st1_scatter_sxtw_index:
1940 case Intrinsic::aarch64_sve_st1_scatter_uxtw:
1941 case Intrinsic::aarch64_sve_st1_scatter_uxtw_index:
1942 case Intrinsic::aarch64_sve_st1dq:
1943 case Intrinsic::aarch64_sve_st1q_scatter_index:
1944 case Intrinsic::aarch64_sve_st1q_scatter_scalar_offset:
1945 case Intrinsic::aarch64_sve_st1q_scatter_vector_offset:
1946 case Intrinsic::aarch64_sve_st1wq:
1947 case Intrinsic::aarch64_sve_stnt1:
1948 case Intrinsic::aarch64_sve_stnt1_scatter:
1949 case Intrinsic::aarch64_sve_stnt1_scatter_index:
1950 case Intrinsic::aarch64_sve_stnt1_scatter_scalar_offset:
1951 case Intrinsic::aarch64_sve_stnt1_scatter_uxtw:
1953 case Intrinsic::aarch64_sve_st2:
1954 case Intrinsic::aarch64_sve_st2q:
1956 case Intrinsic::aarch64_sve_st3:
1957 case Intrinsic::aarch64_sve_st3q:
1959 case Intrinsic::aarch64_sve_st4:
1960 case Intrinsic::aarch64_sve_st4q:
1962 }
1963
1964 return SVEIntrinsicInfo();
1965}
1966
1967static bool isAllActivePredicate(Value *Pred) {
1968 Value *UncastedPred;
1969
1970 // Look through predicate casts that only remove lanes.
1972 m_Value(UncastedPred)))) {
1973 auto *OrigPredTy = cast<ScalableVectorType>(Pred->getType());
1974 Pred = UncastedPred;
1975
1977 m_Value(UncastedPred))))
1978 // If the predicate has the same or less lanes than the uncasted predicate
1979 // then we know the casting has no effect.
1980 if (OrigPredTy->getMinNumElements() <=
1981 cast<ScalableVectorType>(UncastedPred->getType())
1982 ->getMinNumElements())
1983 Pred = UncastedPred;
1984 }
1985
1986 auto *C = dyn_cast<Constant>(Pred);
1987 return C && C->isAllOnesValue();
1988}
1989
1990// Simplify `V` by only considering the operations that affect active lanes.
1991// This function should only return existing Values or newly created Constants.
1992static Value *stripInactiveLanes(Value *V, const Value *Pg) {
1993 auto *Dup = dyn_cast<IntrinsicInst>(V);
1994 if (Dup && Dup->getIntrinsicID() == Intrinsic::aarch64_sve_dup &&
1995 Dup->getOperand(1) == Pg && isa<Constant>(Dup->getOperand(2)))
1997 cast<VectorType>(V->getType())->getElementCount(),
1998 cast<Constant>(Dup->getOperand(2)));
1999
2000 return V;
2001}
2002
2003static std::optional<Instruction *>
2005 const SVEIntrinsicInfo &IInfo) {
2006 const unsigned Opc = IInfo.getMatchingIROpode();
2007 assert(Instruction::isBinaryOp(Opc) && "Expected a binary operation!");
2008
2009 Value *Pg = II.getOperand(0);
2010 Value *Op1 = II.getOperand(1);
2011 Value *Op2 = II.getOperand(2);
2012 const DataLayout &DL = II.getDataLayout();
2013
2014 // Canonicalise constants to the RHS.
2016 isa<Constant>(Op1) && !isa<Constant>(Op2)) {
2017 IC.replaceOperand(II, 1, Op2);
2018 IC.replaceOperand(II, 2, Op1);
2019 return &II;
2020 }
2021
2022 // Only active lanes matter when simplifying the operation.
2023 Op1 = stripInactiveLanes(Op1, Pg);
2024 Op2 = stripInactiveLanes(Op2, Pg);
2025
2026 Value *SimpleII;
2027 if (auto FII = dyn_cast<FPMathOperator>(&II))
2028 SimpleII = simplifyBinOp(Opc, Op1, Op2, FII->getFastMathFlags(), DL);
2029 else
2030 SimpleII = simplifyBinOp(Opc, Op1, Op2, DL);
2031
2032 // If both operands are convert.to.svbool from the same narrower predicate
2033 // type, try to simplify the operation at that narrower type. This is valid
2034 // because the conversions zero the lanes not represented by the narrower
2035 // type, so those lanes of the result are zero either way.
2036 Value *NarrowOp1, *NarrowOp2;
2037 if (!SimpleII &&
2039 m_Value(NarrowOp1))) &&
2041 m_Value(NarrowOp2))) &&
2042 NarrowOp1->getType() == NarrowOp2->getType()) {
2043 Value *SimpleNarrow = simplifyBinOp(Opc, NarrowOp1, NarrowOp2, DL);
2044 if (SimpleNarrow && !isa<UndefValue>(SimpleNarrow)) {
2045 if (match(SimpleNarrow, m_ZeroInt()))
2046 SimpleII = Constant::getNullValue(II.getType());
2047 else if (SimpleNarrow == NarrowOp1)
2048 SimpleII = Op1;
2049 else if (SimpleNarrow == NarrowOp2)
2050 SimpleII = Op2;
2051 else
2052 SimpleII =
2053 IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_convert_to_svbool,
2054 SimpleNarrow->getType(), SimpleNarrow);
2055 }
2056 }
2057
2058 // An SVE intrinsic's result is always defined. However, this is not the case
2059 // for its equivalent IR instruction (e.g. when shifting by an amount more
2060 // than the data's bitwidth). Simplifications to an undefined result must be
2061 // ignored to preserve the intrinsic's expected behaviour.
2062 if (!SimpleII || isa<UndefValue>(SimpleII))
2063 return std::nullopt;
2064
2065 if (IInfo.inactiveLanesAreNotDefined())
2066 return IC.replaceInstUsesWith(II, SimpleII);
2067
2068 Value *Inactive =
2070 ? Constant::getNullValue(II.getType())
2071 : II.getOperand(IInfo.getOperandIdxInactiveLanesTakenFrom());
2072
2073 // The intrinsic does nothing (e.g. sve.mul(pg, A, 1.0)).
2074 if (SimpleII == Inactive)
2075 return IC.replaceInstUsesWith(II, SimpleII);
2076
2077 // Inactive lanes must be preserved.
2078 SimpleII = IC.Builder.CreateSelect(Pg, SimpleII, Inactive);
2079 return IC.replaceInstUsesWith(II, SimpleII);
2080}
2081
2082static std::optional<Instruction *>
2084 const SVEIntrinsicInfo &IInfo) {
2085 const unsigned Opc = IInfo.getMatchingIROpode();
2086 assert((Opc == Instruction::ICmp || Opc == Instruction::FCmp) &&
2087 "Expected a compare operation!");
2088
2089 Value *Pg = II.getOperand(0);
2090 Value *LHS = II.getOperand(1);
2091 Value *RHS = II.getOperand(2);
2092 CmpInst::Predicate CmpPred = IInfo.getCmpPredicate();
2093 bool IsWideICmp =
2094 Opc == Instruction::ICmp && LHS->getType() != RHS->getType();
2095 assert((IsWideICmp || LHS->getType() == RHS->getType()) &&
2096 "Unexpected wide compare!");
2097
2098 // Canonicalise constants to the RHS.
2099 if ((ICmpInst::isCommutative(CmpPred) || FCmpInst::isCommutative(CmpPred)) &&
2100 isa<Constant>(LHS) && !isa<Constant>(RHS) && !IsWideICmp) {
2101 IC.replaceOperand(II, 1, RHS);
2102 IC.replaceOperand(II, 2, LHS);
2103 return &II;
2104 }
2105
2106 // Only active lanes matter when simplifying the operation.
2107 LHS = stripInactiveLanes(LHS, Pg);
2108 RHS = stripInactiveLanes(RHS, Pg);
2109
2110 if (IsWideICmp) {
2111 // We can do more for wide compares, but not using simplifyCmpInst.
2112 const APInt *LHSVal, *RHSVal;
2113 if (!match(LHS, m_APInt(LHSVal)) || !match(RHS, m_APInt(RHSVal)))
2114 return std::nullopt;
2115
2116 // Consider cmpge.wide(..., <vscale x 4 x i32> LHS, <vscale x 2 x i64> RHS),
2117 // we must reconstruct the constants because LHS has the wrong element type,
2118 // and RHS the wrong element count.
2119 Type *WideVT = VectorType::get(RHS->getType()->getScalarType(),
2120 cast<VectorType>(LHS->getType()));
2121 // NOTE: Wide equality comparisons are signed.
2122 if (ICmpInst::isUnsigned(CmpPred)) {
2123 LHS = ConstantInt::get(WideVT, LHSVal->getZExtValue());
2124 RHS = ConstantInt::get(WideVT, RHSVal->getZExtValue());
2125 } else {
2126 LHS = ConstantInt::get(WideVT, LHSVal->getSExtValue());
2127 RHS = ConstantInt::get(WideVT, RHSVal->getSExtValue());
2128 }
2129 }
2130
2131 // TODO: Allow fast-math flags for calls to compare intrinsics.
2132 const DataLayout &DL = II.getDataLayout();
2133 Value *SimpleII = simplifyCmpInst(CmpPred, LHS, RHS, DL);
2134
2135 // No simplification happened.
2136 if (!SimpleII)
2137 return std::nullopt;
2138
2139 assert(IInfo.resultIsZeroInitialized() && "Expected a zeroing operation!");
2140
2141 if (match(SimpleII, m_ZeroInt()))
2142 return IC.replaceInstUsesWith(II, SimpleII);
2143
2144 // Inactive lanes must be zeroed.
2145 SimpleII = IC.Builder.CreateLogicalAnd(Pg, SimpleII);
2146 return IC.replaceInstUsesWith(II, SimpleII);
2147}
2148
2149// Use SVE intrinsic info to eliminate redundant operands and/or canonicalise
2150// to operations with less strict inactive lane requirements.
2151static std::optional<Instruction *>
2153 const SVEIntrinsicInfo &IInfo) {
2154 if (!IInfo.hasGoverningPredicate())
2155 return std::nullopt;
2156
2157 auto *OpPredicate = II.getOperand(IInfo.getGoverningPredicateOperandIdx());
2158
2159 // If there are no active lanes.
2160 if (match(OpPredicate, m_ZeroInt())) {
2162 return IC.replaceInstUsesWith(
2163 II, II.getOperand(IInfo.getOperandIdxInactiveLanesTakenFrom()));
2164
2165 if (IInfo.inactiveLanesAreUnused()) {
2166 if (IInfo.resultIsZeroInitialized())
2168
2169 return IC.eraseInstFromFunction(II);
2170 }
2171 }
2172
2173 // If there are no inactive lanes.
2174 if (isAllActivePredicate(OpPredicate)) {
2175 if (IInfo.hasOperandWithNoActiveLanes()) {
2176 unsigned OpIdx = IInfo.getOperandIdxWithNoActiveLanes();
2177 if (!isa<UndefValue>(II.getOperand(OpIdx)))
2178 return IC.replaceOperand(II, OpIdx, UndefValue::get(II.getType()));
2179 }
2180
2181 if (IInfo.hasMatchingUndefIntrinsic()) {
2182 auto *NewDecl = Intrinsic::getOrInsertDeclaration(
2183 II.getModule(), IInfo.getMatchingUndefIntrinsic(), {II.getType()});
2184 II.setCalledFunction(NewDecl);
2185 return &II;
2186 }
2187 }
2188
2189 if (!IInfo.hasMatchingIROpode())
2190 return std::nullopt;
2191
2192 //
2193 // Operation specific simplifications.
2194 //
2195
2196 unsigned Opc = IInfo.getMatchingIROpode();
2197
2199 return simplifySVEIntrinsicBinOp(IC, II, IInfo);
2200
2201 if (Opc == Instruction::FCmp || Opc == Instruction::ICmp)
2202 return simplifySVEIntrinsicCompare(IC, II, IInfo);
2203
2204 return std::nullopt;
2205}
2206
2207// (from_svbool (binop (to_svbool pred) (svbool_t _) (svbool_t _))))
2208// => (binop (pred) (from_svbool _) (from_svbool _))
2209//
2210// The above transformation eliminates a `to_svbool` in the predicate
2211// operand of bitwise operation `binop` by narrowing the vector width of
2212// the operation. For example, it would convert a `<vscale x 16 x i1>
2213// and` into a `<vscale x 4 x i1> and`. This is profitable because
2214// to_svbool must zero the new lanes during widening, whereas
2215// from_svbool is free.
2216static std::optional<Instruction *>
2218 auto m_ConvertToSVBool = [](auto P) {
2220 };
2221 constexpr Intrinsic::ID ConvertFromSVBool =
2222 Intrinsic::aarch64_sve_convert_from_svbool;
2223
2224 Type *Ty = II.getType();
2225 Value *LHS, *RHS, *NarrowLHS, *NarrowRHS;
2226
2227 if (match(II.getOperand(0),
2229 m_ConvertToSVBool(m_SpecificType(Ty, NarrowRHS))))) {
2230 NarrowLHS = IC.Builder.CreateIntrinsic(ConvertFromSVBool, Ty, LHS);
2231 Value *NarrowAnd = IC.Builder.CreateLogicalAnd(NarrowLHS, NarrowRHS);
2232 return IC.replaceInstUsesWith(II, NarrowAnd);
2233 }
2234
2235 if (match(II.getOperand(0),
2236 m_LogicalAnd(m_ConvertToSVBool(m_SpecificType(Ty, NarrowLHS)),
2237 m_Value(RHS)))) {
2238 NarrowRHS = IC.Builder.CreateIntrinsic(ConvertFromSVBool, Ty, RHS);
2239 Value *NarrowAnd = IC.Builder.CreateLogicalAnd(NarrowLHS, NarrowRHS);
2240 return IC.replaceInstUsesWith(II, NarrowAnd);
2241 }
2242
2243 auto BinOp = dyn_cast<IntrinsicInst>(II.getOperand(0));
2244 if (!BinOp)
2245 return std::nullopt;
2246
2247 Intrinsic::ID BinOpIID = BinOp->getIntrinsicID();
2248 switch (BinOpIID) {
2249 case Intrinsic::aarch64_sve_and_z:
2250 case Intrinsic::aarch64_sve_bic_z:
2251 case Intrinsic::aarch64_sve_eor_z:
2252 case Intrinsic::aarch64_sve_nand_z:
2253 case Intrinsic::aarch64_sve_nor_z:
2254 case Intrinsic::aarch64_sve_orn_z:
2255 case Intrinsic::aarch64_sve_orr_z:
2256 break;
2257 default:
2258 return std::nullopt;
2259 }
2260
2261 Value *BinOpPred = BinOp->getOperand(0);
2262 Value *BinOpOp1 = BinOp->getOperand(1);
2263 Value *BinOpOp2 = BinOp->getOperand(2);
2264
2265 Value *NarrowBinOpPred;
2266 if (!match(BinOpPred, m_ConvertToSVBool(m_SpecificType(Ty, NarrowBinOpPred))))
2267 return std::nullopt;
2268
2269 Value *NarrowBinOpOp1 =
2270 IC.Builder.CreateIntrinsic(ConvertFromSVBool, Ty, BinOpOp1);
2271 Value *NarrowBinOpOp2 = NarrowBinOpOp1;
2272 if (BinOpOp1 != BinOpOp2)
2273 NarrowBinOpOp2 =
2274 IC.Builder.CreateIntrinsic(ConvertFromSVBool, Ty, BinOpOp2);
2275 Value *NarrowedBinOp = IC.Builder.CreateIntrinsic(
2276 BinOpIID, Ty, {NarrowBinOpPred, NarrowBinOpOp1, NarrowBinOpOp2});
2277 return IC.replaceInstUsesWith(II, NarrowedBinOp);
2278}
2279
2280static std::optional<Instruction *>
2282 // If the reinterpret instruction operand is a PHI Node
2283 if (isa<PHINode>(II.getArgOperand(0)))
2284 return processPhiNode(IC, II);
2285
2286 if (auto BinOpCombine = tryCombineFromSVBoolBinOp(IC, II))
2287 return BinOpCombine;
2288
2289 // Ignore converts to/from svcount_t.
2290 if (isa<TargetExtType>(II.getArgOperand(0)->getType()) ||
2291 isa<TargetExtType>(II.getType()))
2292 return std::nullopt;
2293
2294 SmallVector<Instruction *, 32> CandidatesForRemoval;
2295 Value *Cursor = II.getOperand(0), *EarliestReplacement = nullptr;
2296
2297 const auto *IVTy = cast<VectorType>(II.getType());
2298
2299 // Walk the chain of conversions.
2300 while (Cursor) {
2301 // If the type of the cursor has fewer lanes than the final result, zeroing
2302 // must take place, which breaks the equivalence chain.
2303 const auto *CursorVTy = cast<VectorType>(Cursor->getType());
2304 if (CursorVTy->getElementCount().getKnownMinValue() <
2305 IVTy->getElementCount().getKnownMinValue())
2306 break;
2307
2308 // If the cursor has the same type as I, it is a viable replacement.
2309 if (Cursor->getType() == IVTy)
2310 EarliestReplacement = Cursor;
2311
2312 auto *IntrinsicCursor = dyn_cast<IntrinsicInst>(Cursor);
2313
2314 // If this is not an SVE conversion intrinsic, this is the end of the chain.
2315 if (!IntrinsicCursor || !(IntrinsicCursor->getIntrinsicID() ==
2316 Intrinsic::aarch64_sve_convert_to_svbool ||
2317 IntrinsicCursor->getIntrinsicID() ==
2318 Intrinsic::aarch64_sve_convert_from_svbool))
2319 break;
2320
2321 CandidatesForRemoval.insert(CandidatesForRemoval.begin(), IntrinsicCursor);
2322 Cursor = IntrinsicCursor->getOperand(0);
2323 }
2324
2325 // If no viable replacement in the conversion chain was found, there is
2326 // nothing to do.
2327 if (!EarliestReplacement)
2328 return std::nullopt;
2329
2330 return IC.replaceInstUsesWith(II, EarliestReplacement);
2331}
2332
2333static std::optional<Instruction *> instCombineSVESel(InstCombiner &IC,
2334 IntrinsicInst &II) {
2335 // svsel(ptrue, x, y) => x
2336 auto *OpPredicate = II.getOperand(0);
2337 if (isAllActivePredicate(OpPredicate))
2338 return IC.replaceInstUsesWith(II, II.getOperand(1));
2339
2340 auto Select =
2341 IC.Builder.CreateSelect(OpPredicate, II.getOperand(1), II.getOperand(2));
2342 return IC.replaceInstUsesWith(II, Select);
2343}
2344
2345static std::optional<Instruction *> instCombineSVEDup(InstCombiner &IC,
2346 IntrinsicInst &II) {
2347 Value *Pg = II.getOperand(1);
2348
2349 // sve.dup(V, all_active, X) ==> splat(X)
2350 if (isAllActivePredicate(Pg)) {
2351 auto *RetTy = cast<ScalableVectorType>(II.getType());
2352 Value *Splat = IC.Builder.CreateVectorSplat(RetTy->getElementCount(),
2353 II.getArgOperand(2));
2354 return IC.replaceInstUsesWith(II, Splat);
2355 }
2356
2358 m_SpecificInt(AArch64SVEPredPattern::vl1))))
2359 return std::nullopt;
2360
2361 // sve.dup(V, sve.ptrue(vl1), X) ==> insertelement V, X, 0
2362 Value *Insert = IC.Builder.CreateInsertElement(
2363 II.getArgOperand(0), II.getArgOperand(2), uint64_t(0));
2364 return IC.replaceInstUsesWith(II, Insert);
2365}
2366
2367static std::optional<Instruction *> instCombineSVEDupX(InstCombiner &IC,
2368 IntrinsicInst &II) {
2369 // Replace DupX with a regular IR splat.
2370 auto *RetTy = cast<ScalableVectorType>(II.getType());
2371 Value *Splat = IC.Builder.CreateVectorSplat(RetTy->getElementCount(),
2372 II.getArgOperand(0));
2373 Splat->takeName(&II);
2374 return IC.replaceInstUsesWith(II, Splat);
2375}
2376
2377// xor(cmpne(%pg, %lhs, %rhs), %pg)
2378// -> cmpeq(%pg, %lhs, %rhs)
2379static std::optional<Instruction *> instCombineXorSVECmpCC(InstCombiner &IC,
2380 IntrinsicInst &II) {
2381 if (!II.hasOneUse())
2382 return std::nullopt;
2383 auto *User = cast<Instruction>(*II.user_begin());
2384 if (!match(User, m_c_Xor(m_Specific(&II), m_Specific(II.getOperand(0)))))
2385 return std::nullopt;
2386
2387 Intrinsic::ID IID;
2388 switch (II.getIntrinsicID()) {
2389 case Intrinsic::aarch64_sve_cmpne:
2390 IID = Intrinsic::aarch64_sve_cmpeq;
2391 break;
2392 case Intrinsic::aarch64_sve_cmpne_wide:
2393 IID = Intrinsic::aarch64_sve_cmpeq_wide;
2394 break;
2395 case Intrinsic::aarch64_sve_cmpeq:
2396 IID = Intrinsic::aarch64_sve_cmpne;
2397 break;
2398 case Intrinsic::aarch64_sve_cmpeq_wide:
2399 IID = Intrinsic::aarch64_sve_cmpne_wide;
2400 break;
2401 default:
2402 return std::nullopt;
2403 }
2404
2406 Value *CMPCC = IC.Builder.CreateIntrinsic(
2407 IID, II.getOperand(1)->getType(),
2408 {II.getOperand(0), II.getOperand(1), II.getOperand(2)});
2409 IC.replaceInstUsesWith(*User, CMPCC);
2411 return &II;
2412}
2413
2414// zext(cmpne(ptrue, %v, 0))
2415// -> umin(%pg, %v, 1)
2416static std::optional<Instruction *> instCombineZExtSVECmpNE(InstCombiner &IC,
2417 IntrinsicInst &II) {
2418 if (!isAllActivePredicate(II.getOperand(0)) ||
2419 !match(II.getOperand(2), m_Zero()))
2420 return std::nullopt;
2421
2422 for (auto *U : II.users()) {
2423 if (match(U, m_ZExt(m_Specific(&II)))) {
2424 auto *User = cast<Instruction>(U);
2425 Type *Ty = II.getOperand(1)->getType();
2426 if (User->getType() != Ty)
2427 continue;
2430 Intrinsic::aarch64_sve_umin, Ty,
2431 {II.getOperand(0), II.getOperand(1), ConstantInt::get(Ty, 1)});
2434 return &II;
2435 }
2436 }
2437 return std::nullopt;
2438}
2439
2440static std::optional<Instruction *> instCombineSVECmpNE(InstCombiner &IC,
2441 IntrinsicInst &II) {
2442 LLVMContext &Ctx = II.getContext();
2443
2444 if (auto Res = instCombineXorSVECmpCC(IC, II))
2445 return Res;
2446
2447 if (auto Res = instCombineZExtSVECmpNE(IC, II))
2448 return Res;
2449
2450 if (!isAllActivePredicate(II.getArgOperand(0)))
2451 return std::nullopt;
2452
2453 // Check that we have a compare of zero..
2454 auto *SplatValue =
2456 if (!SplatValue || !SplatValue->isZero())
2457 return std::nullopt;
2458
2459 // ..against a dupq
2460 auto *DupQLane = dyn_cast<IntrinsicInst>(II.getArgOperand(1));
2461 if (!DupQLane ||
2462 DupQLane->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane)
2463 return std::nullopt;
2464
2465 // Where the dupq is a lane 0 replicate of a vector insert
2466 auto *DupQLaneIdx = dyn_cast<ConstantInt>(DupQLane->getArgOperand(1));
2467 if (!DupQLaneIdx || !DupQLaneIdx->isZero())
2468 return std::nullopt;
2469
2470 auto *VecIns = dyn_cast<IntrinsicInst>(DupQLane->getArgOperand(0));
2471 if (!VecIns || VecIns->getIntrinsicID() != Intrinsic::vector_insert)
2472 return std::nullopt;
2473
2474 // Where the vector insert is a fixed constant vector insert into undef at
2475 // index zero
2476 if (!isa<UndefValue>(VecIns->getArgOperand(0)))
2477 return std::nullopt;
2478
2479 if (!cast<ConstantInt>(VecIns->getArgOperand(2))->isZero())
2480 return std::nullopt;
2481
2482 auto *ConstVec = dyn_cast<Constant>(VecIns->getArgOperand(1));
2483 if (!ConstVec)
2484 return std::nullopt;
2485
2486 auto *VecTy = dyn_cast<FixedVectorType>(ConstVec->getType());
2487 auto *OutTy = dyn_cast<ScalableVectorType>(II.getType());
2488 if (!VecTy || !OutTy || VecTy->getNumElements() != OutTy->getMinNumElements())
2489 return std::nullopt;
2490
2491 unsigned NumElts = VecTy->getNumElements();
2492 unsigned PredicateBits = 0;
2493
2494 // Expand intrinsic operands to a 16-bit byte level predicate
2495 for (unsigned I = 0; I < NumElts; ++I) {
2496 auto *Arg = dyn_cast<ConstantInt>(ConstVec->getAggregateElement(I));
2497 if (!Arg)
2498 return std::nullopt;
2499 if (!Arg->isZero())
2500 PredicateBits |= 1 << (I * (16 / NumElts));
2501 }
2502
2503 // If all bits are zero bail early with an empty predicate
2504 if (PredicateBits == 0) {
2505 auto *PFalse = Constant::getNullValue(II.getType());
2506 PFalse->takeName(&II);
2507 return IC.replaceInstUsesWith(II, PFalse);
2508 }
2509
2510 // Calculate largest predicate type used (where byte predicate is largest)
2511 unsigned Mask = 8;
2512 for (unsigned I = 0; I < 16; ++I)
2513 if ((PredicateBits & (1 << I)) != 0)
2514 Mask |= (I % 8);
2515
2516 unsigned PredSize = Mask & -Mask;
2517 auto *PredType = ScalableVectorType::get(
2518 Type::getInt1Ty(Ctx), AArch64::SVEBitsPerBlock / (PredSize * 8));
2519
2520 // Ensure all relevant bits are set
2521 for (unsigned I = 0; I < 16; I += PredSize)
2522 if ((PredicateBits & (1 << I)) == 0)
2523 return std::nullopt;
2524
2525 auto *ConvertToSVBool =
2526 IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_convert_to_svbool,
2527 PredType, ConstantInt::getTrue(PredType));
2528 auto *ConvertFromSVBool =
2529 IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_convert_from_svbool,
2530 II.getType(), ConvertToSVBool);
2531
2532 ConvertFromSVBool->takeName(&II);
2533 return IC.replaceInstUsesWith(II, ConvertFromSVBool);
2534}
2535
2536static std::optional<Instruction *> instCombineSVELast(InstCombiner &IC,
2537 IntrinsicInst &II) {
2538 Value *Pg = II.getArgOperand(0);
2539 Value *Vec = II.getArgOperand(1);
2540 auto IntrinsicID = II.getIntrinsicID();
2541 bool IsAfter = IntrinsicID == Intrinsic::aarch64_sve_lasta;
2542
2543 // lastX(splat(X)) --> X
2544 if (auto *SplatVal = getSplatValue(Vec))
2545 return IC.replaceInstUsesWith(II, SplatVal);
2546
2547 // If x and/or y is a splat value then:
2548 // lastX (binop (x, y)) --> binop(lastX(x), lastX(y))
2549 Value *LHS, *RHS;
2550 if (match(Vec, m_OneUse(m_BinOp(m_Value(LHS), m_Value(RHS))))) {
2551 if (isSplatValue(LHS) || isSplatValue(RHS)) {
2552 auto *OldBinOp = cast<BinaryOperator>(Vec);
2553 auto OpC = OldBinOp->getOpcode();
2554 auto *NewLHS =
2555 IC.Builder.CreateIntrinsic(IntrinsicID, {Vec->getType()}, {Pg, LHS});
2556 auto *NewRHS =
2557 IC.Builder.CreateIntrinsic(IntrinsicID, {Vec->getType()}, {Pg, RHS});
2559 OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(), II.getIterator());
2560 return IC.replaceInstUsesWith(II, NewBinOp);
2561 }
2562 }
2563
2564 auto *C = dyn_cast<Constant>(Pg);
2565 if (IsAfter && C && C->isNullValue()) {
2566 // The intrinsic is extracting lane 0 so use an extract instead.
2567 auto *IdxTy = Type::getInt64Ty(II.getContext());
2568 auto *Extract = ExtractElementInst::Create(Vec, ConstantInt::get(IdxTy, 0));
2569 Extract->insertBefore(II.getIterator());
2570 Extract->takeName(&II);
2571 return IC.replaceInstUsesWith(II, Extract);
2572 }
2573
2574 auto *IntrPG = dyn_cast<IntrinsicInst>(Pg);
2575 if (!IntrPG)
2576 return std::nullopt;
2577
2578 if (IntrPG->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue)
2579 return std::nullopt;
2580
2581 const auto PTruePattern =
2582 cast<ConstantInt>(IntrPG->getOperand(0))->getZExtValue();
2583
2584 // Can the intrinsic's predicate be converted to a known constant index?
2585 unsigned MinNumElts = getNumElementsFromSVEPredPattern(PTruePattern);
2586 if (!MinNumElts)
2587 return std::nullopt;
2588
2589 unsigned Idx = MinNumElts - 1;
2590 // Increment the index if extracting the element after the last active
2591 // predicate element.
2592 if (IsAfter)
2593 ++Idx;
2594
2595 // Ignore extracts whose index is larger than the known minimum vector
2596 // length. NOTE: This is an artificial constraint where we prefer to
2597 // maintain what the user asked for until an alternative is proven faster.
2598 auto *PgVTy = cast<ScalableVectorType>(Pg->getType());
2599 if (Idx >= PgVTy->getMinNumElements())
2600 return std::nullopt;
2601
2602 // The intrinsic is extracting a fixed lane so use an extract instead.
2603 auto *IdxTy = Type::getInt64Ty(II.getContext());
2604 auto *Extract = ExtractElementInst::Create(Vec, ConstantInt::get(IdxTy, Idx));
2605 Extract->insertBefore(II.getIterator());
2606 Extract->takeName(&II);
2607 return IC.replaceInstUsesWith(II, Extract);
2608}
2609
2610static std::optional<Instruction *> instCombineSVECondLast(InstCombiner &IC,
2611 IntrinsicInst &II) {
2612 // The SIMD&FP variant of CLAST[AB] is significantly faster than the scalar
2613 // integer variant across a variety of micro-architectures. Replace scalar
2614 // integer CLAST[AB] intrinsic with optimal SIMD&FP variant. A simple
2615 // bitcast-to-fp + clast[ab] + bitcast-to-int will cost a cycle or two more
2616 // depending on the micro-architecture, but has been observed as generally
2617 // being faster, particularly when the CLAST[AB] op is a loop-carried
2618 // dependency.
2619 Value *Pg = II.getArgOperand(0);
2620 Value *Fallback = II.getArgOperand(1);
2621 Value *Vec = II.getArgOperand(2);
2622 Type *Ty = II.getType();
2623
2624 if (!Ty->isIntegerTy())
2625 return std::nullopt;
2626
2627 Type *FPTy;
2628 switch (cast<IntegerType>(Ty)->getBitWidth()) {
2629 default:
2630 return std::nullopt;
2631 case 16:
2632 FPTy = IC.Builder.getHalfTy();
2633 break;
2634 case 32:
2635 FPTy = IC.Builder.getFloatTy();
2636 break;
2637 case 64:
2638 FPTy = IC.Builder.getDoubleTy();
2639 break;
2640 }
2641
2642 Value *FPFallBack = IC.Builder.CreateBitCast(Fallback, FPTy);
2643 auto *FPVTy = VectorType::get(
2644 FPTy, cast<VectorType>(Vec->getType())->getElementCount());
2645 Value *FPVec = IC.Builder.CreateBitCast(Vec, FPVTy);
2646 auto *FPII = IC.Builder.CreateIntrinsic(
2647 II.getIntrinsicID(), {FPVec->getType()}, {Pg, FPFallBack, FPVec});
2648 Value *FPIItoInt = IC.Builder.CreateBitCast(FPII, II.getType());
2649 return IC.replaceInstUsesWith(II, FPIItoInt);
2650}
2651
2652static std::optional<Instruction *> instCombineRDFFR(InstCombiner &IC,
2653 IntrinsicInst &II) {
2654 // Replace rdffr with predicated rdffr.z intrinsic, so that optimizePTestInstr
2655 // can work with RDFFR_PP for ptest elimination.
2656 auto *RDFFR = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_rdffr_z,
2657 ConstantInt::getTrue(II.getType()));
2658 RDFFR->takeName(&II);
2659 return IC.replaceInstUsesWith(II, RDFFR);
2660}
2661
2662static std::optional<Instruction *>
2664 const auto Pattern = cast<ConstantInt>(II.getArgOperand(0))->getZExtValue();
2665
2666 if (Pattern == AArch64SVEPredPattern::all) {
2668 II.getType(), ElementCount::getScalable(NumElts));
2669 Cnt->takeName(&II);
2670 return IC.replaceInstUsesWith(II, Cnt);
2671 }
2672
2673 unsigned MinNumElts = getNumElementsFromSVEPredPattern(Pattern);
2674
2675 return MinNumElts && NumElts >= MinNumElts
2676 ? std::optional<Instruction *>(IC.replaceInstUsesWith(
2677 II, ConstantInt::get(II.getType(), MinNumElts)))
2678 : std::nullopt;
2679}
2680
2681static std::optional<Instruction *>
2683 const AArch64Subtarget *ST) {
2684 if (!ST->isStreaming())
2685 return std::nullopt;
2686
2687 // In streaming-mode, aarch64_sme_cntds is equivalent to aarch64_sve_cntd
2688 // with SVEPredPattern::all
2689 Value *Cnt =
2691 Cnt->takeName(&II);
2692 return IC.replaceInstUsesWith(II, Cnt);
2693}
2694
2695static std::optional<Instruction *> instCombineSVEPTest(InstCombiner &IC,
2696 IntrinsicInst &II) {
2697 Value *PgVal = II.getArgOperand(0);
2698 Value *OpVal = II.getArgOperand(1);
2699
2700 // PTEST_<FIRST|LAST>(X, X) is equivalent to PTEST_ANY(X, X).
2701 // Later optimizations prefer this form.
2702 if (PgVal == OpVal &&
2703 (II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_first ||
2704 II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_last)) {
2705 Value *Ops[] = {PgVal, OpVal};
2706 Type *Tys[] = {PgVal->getType()};
2707
2708 auto *PTest =
2709 IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_ptest_any, Tys, Ops);
2710 PTest->takeName(&II);
2711
2712 return IC.replaceInstUsesWith(II, PTest);
2713 }
2714
2717
2718 if (!Pg || !Op)
2719 return std::nullopt;
2720
2721 Intrinsic::ID OpIID = Op->getIntrinsicID();
2722
2723 if (Pg->getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool &&
2724 OpIID == Intrinsic::aarch64_sve_convert_to_svbool &&
2725 Pg->getArgOperand(0)->getType() == Op->getArgOperand(0)->getType()) {
2726 Value *Ops[] = {Pg->getArgOperand(0), Op->getArgOperand(0)};
2727 Type *Tys[] = {Pg->getArgOperand(0)->getType()};
2728
2729 auto *PTest = IC.Builder.CreateIntrinsic(II.getIntrinsicID(), Tys, Ops);
2730
2731 PTest->takeName(&II);
2732 return IC.replaceInstUsesWith(II, PTest);
2733 }
2734
2735 // Transform PTEST_ANY(X=OP(PG,...), X) -> PTEST_ANY(PG, X)).
2736 // Later optimizations may rewrite sequence to use the flag-setting variant
2737 // of instruction X to remove PTEST.
2738 if ((Pg == Op) && (II.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_any) &&
2739 ((OpIID == Intrinsic::aarch64_sve_brka_z) ||
2740 (OpIID == Intrinsic::aarch64_sve_brkb_z) ||
2741 (OpIID == Intrinsic::aarch64_sve_brkpa_z) ||
2742 (OpIID == Intrinsic::aarch64_sve_brkpb_z) ||
2743 (OpIID == Intrinsic::aarch64_sve_rdffr_z) ||
2744 (OpIID == Intrinsic::aarch64_sve_and_z) ||
2745 (OpIID == Intrinsic::aarch64_sve_bic_z) ||
2746 (OpIID == Intrinsic::aarch64_sve_eor_z) ||
2747 (OpIID == Intrinsic::aarch64_sve_nand_z) ||
2748 (OpIID == Intrinsic::aarch64_sve_nor_z) ||
2749 (OpIID == Intrinsic::aarch64_sve_orn_z) ||
2750 (OpIID == Intrinsic::aarch64_sve_orr_z))) {
2751 Value *Ops[] = {Pg->getArgOperand(0), Pg};
2752 Type *Tys[] = {Pg->getType()};
2753
2754 auto *PTest = IC.Builder.CreateIntrinsic(II.getIntrinsicID(), Tys, Ops);
2755 PTest->takeName(&II);
2756
2757 return IC.replaceInstUsesWith(II, PTest);
2758 }
2759
2760 return std::nullopt;
2761}
2762
2763template <Intrinsic::ID MulOpc, Intrinsic::ID FuseOpc>
2764static std::optional<Instruction *>
2766 bool MergeIntoAddendOp) {
2767 Value *P = II.getOperand(0);
2768 Value *MulOp0, *MulOp1, *AddendOp, *Mul;
2769 if (MergeIntoAddendOp) {
2770 AddendOp = II.getOperand(1);
2771 Mul = II.getOperand(2);
2772 } else {
2773 AddendOp = II.getOperand(2);
2774 Mul = II.getOperand(1);
2775 }
2776
2778 m_Value(MulOp1))))
2779 return std::nullopt;
2780
2781 if (!Mul->hasOneUse())
2782 return std::nullopt;
2783
2784 Instruction *FMFSource = nullptr;
2785 if (II.getType()->isFPOrFPVectorTy()) {
2786 llvm::FastMathFlags FAddFlags = II.getFastMathFlags();
2787 // Stop the combine when the flags on the inputs differ in case dropping
2788 // flags would lead to us missing out on more beneficial optimizations.
2789 if (FAddFlags != cast<CallInst>(Mul)->getFastMathFlags())
2790 return std::nullopt;
2791 if (!FAddFlags.allowContract())
2792 return std::nullopt;
2793 FMFSource = &II;
2794 }
2795
2796 Value *Res;
2797 if (MergeIntoAddendOp)
2798 Res = IC.Builder.CreateIntrinsic(FuseOpc, {II.getType()},
2799 {P, AddendOp, MulOp0, MulOp1}, FMFSource);
2800 else
2801 Res = IC.Builder.CreateIntrinsic(FuseOpc, {II.getType()},
2802 {P, MulOp0, MulOp1, AddendOp}, FMFSource);
2803
2804 return IC.replaceInstUsesWith(II, Res);
2805}
2806
2807static std::optional<Instruction *>
2809 Value *Pred = II.getOperand(0);
2810 Value *PtrOp = II.getOperand(1);
2811 Type *VecTy = II.getType();
2812
2813 if (isAllActivePredicate(Pred)) {
2814 LoadInst *Load = IC.Builder.CreateLoad(VecTy, PtrOp);
2815 Load->copyMetadata(II);
2816 return IC.replaceInstUsesWith(II, Load);
2817 }
2818
2819 CallInst *MaskedLoad =
2820 IC.Builder.CreateMaskedLoad(VecTy, PtrOp, PtrOp->getPointerAlignment(DL),
2821 Pred, ConstantAggregateZero::get(VecTy));
2822 MaskedLoad->copyMetadata(II);
2823 return IC.replaceInstUsesWith(II, MaskedLoad);
2824}
2825
2826static std::optional<Instruction *>
2828 Value *VecOp = II.getOperand(0);
2829 Value *Pred = II.getOperand(1);
2830 Value *PtrOp = II.getOperand(2);
2831
2832 if (isAllActivePredicate(Pred)) {
2833 StoreInst *Store = IC.Builder.CreateStore(VecOp, PtrOp);
2834 Store->copyMetadata(II);
2835 return IC.eraseInstFromFunction(II);
2836 }
2837
2838 CallInst *MaskedStore = IC.Builder.CreateMaskedStore(
2839 VecOp, PtrOp, PtrOp->getPointerAlignment(DL), Pred);
2840 MaskedStore->copyMetadata(II);
2841 return IC.eraseInstFromFunction(II);
2842}
2843
2845 switch (Intrinsic) {
2846 case Intrinsic::aarch64_sve_fmul_u:
2847 return Instruction::BinaryOps::FMul;
2848 case Intrinsic::aarch64_sve_fadd_u:
2849 return Instruction::BinaryOps::FAdd;
2850 case Intrinsic::aarch64_sve_fsub_u:
2851 return Instruction::BinaryOps::FSub;
2852 default:
2853 return Instruction::BinaryOpsEnd;
2854 }
2855}
2856
2857static std::optional<Instruction *>
2859 // Bail due to missing support for ISD::STRICT_ scalable vector operations.
2860 if (II.isStrictFP())
2861 return std::nullopt;
2862
2863 auto *OpPredicate = II.getOperand(0);
2864 auto BinOpCode = intrinsicIDToBinOpCode(II.getIntrinsicID());
2865 if (BinOpCode == Instruction::BinaryOpsEnd ||
2866 !isAllActivePredicate(OpPredicate))
2867 return std::nullopt;
2868 auto BinOp = IC.Builder.CreateBinOpFMF(
2869 BinOpCode, II.getOperand(1), II.getOperand(2), II.getFastMathFlags());
2870 return IC.replaceInstUsesWith(II, BinOp);
2871}
2872
2873static std::optional<Instruction *>
2875 assert(II.getIntrinsicID() == Intrinsic::aarch64_sve_mla_u &&
2876 "Expected MLA_U intrinsic");
2877 Value *Acc = II.getArgOperand(1);
2878 Value *MulOp0 = II.getArgOperand(2);
2879 Value *MulOp1 = II.getArgOperand(3);
2880
2881 // For mla_u, inactive lanes are undefined, so it is valid to drop the
2882 // predicate when replacing mla_u(acc, x, 1) with add(acc, x) or
2883 // mla_u(acc, x, -1) with sub(acc, x).
2884 if (match(MulOp0, m_One()))
2885 return IC.replaceInstUsesWith(II, IC.Builder.CreateAdd(Acc, MulOp1));
2886 if (match(MulOp1, m_One()))
2887 return IC.replaceInstUsesWith(II, IC.Builder.CreateAdd(Acc, MulOp0));
2888 if (match(MulOp0, m_AllOnes()))
2889 return IC.replaceInstUsesWith(II, IC.Builder.CreateSub(Acc, MulOp1));
2890 if (match(MulOp1, m_AllOnes()))
2891 return IC.replaceInstUsesWith(II, IC.Builder.CreateSub(Acc, MulOp0));
2892
2893 if (isa<Constant>(MulOp0) && !isa<Constant>(MulOp1)) {
2894 II.setArgOperand(2, MulOp1);
2895 II.setArgOperand(3, MulOp0);
2896 return &II;
2897 }
2898
2899 return std::nullopt;
2900}
2901
2902static std::optional<Instruction *>
2904 assert((II.getIntrinsicID() == Intrinsic::aarch64_sve_sadalp ||
2905 II.getIntrinsicID() == Intrinsic::aarch64_sve_uadalp) &&
2906 "Expected SADALP or UADALP intrinsic");
2907
2908 // Simplify add(adalp(pg, zeroinitializer, in), wide_acc)
2909 // -> adalp(pg, wide_acc, in)
2910 auto *User = dyn_cast_or_null<Instruction>(II.getUniqueUndroppableUser());
2911 if (!User || !match(II.getArgOperand(1), m_Zero()))
2912 return std::nullopt;
2913
2914 Value *Acc;
2915 if (!match(User, m_c_Add(m_Specific(&II), m_Value(Acc))))
2916 return std::nullopt;
2917
2919 Value *PairwiseAddLong = IC.Builder.CreateIntrinsic(
2920 II.getIntrinsicID(), {II.getType()},
2921 {II.getArgOperand(0), Acc, II.getArgOperand(2)});
2922
2923 IC.replaceInstUsesWith(*User, PairwiseAddLong);
2925 return &II; // II is now trivially dead and will get erased.
2926}
2927
2928static std::optional<Instruction *> instCombineSVEVectorAdd(InstCombiner &IC,
2929 IntrinsicInst &II) {
2930 if (auto MLA = instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul,
2931 Intrinsic::aarch64_sve_mla>(
2932 IC, II, true))
2933 return MLA;
2934 if (auto MAD = instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul,
2935 Intrinsic::aarch64_sve_mad>(
2936 IC, II, false))
2937 return MAD;
2938 return std::nullopt;
2939}
2940
2941static std::optional<Instruction *>
2943 if (auto FMLA =
2944 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2945 Intrinsic::aarch64_sve_fmla>(IC, II,
2946 true))
2947 return FMLA;
2948 if (auto FMAD =
2949 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2950 Intrinsic::aarch64_sve_fmad>(IC, II,
2951 false))
2952 return FMAD;
2953 if (auto FMLA =
2954 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul_u,
2955 Intrinsic::aarch64_sve_fmla>(IC, II,
2956 true))
2957 return FMLA;
2958 return std::nullopt;
2959}
2960
2961static std::optional<Instruction *>
2963 if (auto FMLA =
2964 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2965 Intrinsic::aarch64_sve_fmla>(IC, II,
2966 true))
2967 return FMLA;
2968 if (auto FMAD =
2969 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2970 Intrinsic::aarch64_sve_fmad>(IC, II,
2971 false))
2972 return FMAD;
2973 if (auto FMLA_U =
2974 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul_u,
2975 Intrinsic::aarch64_sve_fmla_u>(
2976 IC, II, true))
2977 return FMLA_U;
2978 return instCombineSVEVectorBinOp(IC, II);
2979}
2980
2981static std::optional<Instruction *>
2983 if (auto FMLS =
2984 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2985 Intrinsic::aarch64_sve_fmls>(IC, II,
2986 true))
2987 return FMLS;
2988 if (auto FMSB =
2989 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
2990 Intrinsic::aarch64_sve_fnmsb>(
2991 IC, II, false))
2992 return FMSB;
2993 if (auto FMLS =
2994 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul_u,
2995 Intrinsic::aarch64_sve_fmls>(IC, II,
2996 true))
2997 return FMLS;
2998 return std::nullopt;
2999}
3000
3001static std::optional<Instruction *>
3003 if (auto FMLS =
3004 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
3005 Intrinsic::aarch64_sve_fmls>(IC, II,
3006 true))
3007 return FMLS;
3008 if (auto FMSB =
3009 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul,
3010 Intrinsic::aarch64_sve_fnmsb>(
3011 IC, II, false))
3012 return FMSB;
3013 if (auto FMLS_U =
3014 instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_fmul_u,
3015 Intrinsic::aarch64_sve_fmls_u>(
3016 IC, II, true))
3017 return FMLS_U;
3018 return instCombineSVEVectorBinOp(IC, II);
3019}
3020
3021static std::optional<Instruction *> instCombineSVEVectorSub(InstCombiner &IC,
3022 IntrinsicInst &II) {
3023 if (auto MLS = instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul,
3024 Intrinsic::aarch64_sve_mls>(
3025 IC, II, true))
3026 return MLS;
3027 return std::nullopt;
3028}
3029
3030static std::optional<Instruction *> instCombineSVEUnpack(InstCombiner &IC,
3031 IntrinsicInst &II) {
3032 Value *UnpackArg = II.getArgOperand(0);
3033 auto *RetTy = cast<ScalableVectorType>(II.getType());
3034 bool IsSigned = II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi ||
3035 II.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo;
3036
3037 // Hi = uunpkhi(splat(X)) --> Hi = splat(extend(X))
3038 // Lo = uunpklo(splat(X)) --> Lo = splat(extend(X))
3039 if (auto *ScalarArg = getSplatValue(UnpackArg)) {
3040 ScalarArg =
3041 IC.Builder.CreateIntCast(ScalarArg, RetTy->getScalarType(), IsSigned);
3042 Value *NewVal =
3043 IC.Builder.CreateVectorSplat(RetTy->getElementCount(), ScalarArg);
3044 NewVal->takeName(&II);
3045 return IC.replaceInstUsesWith(II, NewVal);
3046 }
3047
3048 return std::nullopt;
3049}
3050static std::optional<Instruction *> instCombineSVETBL(InstCombiner &IC,
3051 IntrinsicInst &II) {
3052 auto *OpVal = II.getOperand(0);
3053 auto *OpIndices = II.getOperand(1);
3054 VectorType *VTy = cast<VectorType>(II.getType());
3055
3056 // Check whether OpIndices is a constant splat value < minimal element count
3057 // of result.
3058 auto *SplatValue = dyn_cast_or_null<ConstantInt>(getSplatValue(OpIndices));
3059 if (!SplatValue ||
3060 SplatValue->getValue().uge(VTy->getElementCount().getKnownMinValue()))
3061 return std::nullopt;
3062
3063 // Convert sve_tbl(OpVal sve_dup_x(SplatValue)) to
3064 // splat_vector(extractelement(OpVal, SplatValue)) for further optimization.
3065 auto *Extract = IC.Builder.CreateExtractElement(OpVal, SplatValue);
3066 auto *VectorSplat =
3067 IC.Builder.CreateVectorSplat(VTy->getElementCount(), Extract);
3068
3069 VectorSplat->takeName(&II);
3070 return IC.replaceInstUsesWith(II, VectorSplat);
3071}
3072
3073static std::optional<Instruction *> instCombineSVEUzp1(InstCombiner &IC,
3074 IntrinsicInst &II) {
3075 Value *A, *B;
3076 Type *RetTy = II.getType();
3077 constexpr Intrinsic::ID FromSVB = Intrinsic::aarch64_sve_convert_from_svbool;
3078 constexpr Intrinsic::ID ToSVB = Intrinsic::aarch64_sve_convert_to_svbool;
3079
3080 // uzp1(to_svbool(A), to_svbool(B)) --> <A, B>
3081 // uzp1(from_svbool(to_svbool(A)), from_svbool(to_svbool(B))) --> <A, B>
3082 if ((match(II.getArgOperand(0),
3084 match(II.getArgOperand(1),
3086 (match(II.getArgOperand(0), m_Intrinsic<ToSVB>(m_Value(A))) &&
3087 match(II.getArgOperand(1), m_Intrinsic<ToSVB>(m_Value(B))))) {
3088 auto *TyA = cast<ScalableVectorType>(A->getType());
3089 if (TyA == B->getType() &&
3091 auto *SubVec = IC.Builder.CreateInsertVector(
3092 RetTy, PoisonValue::get(RetTy), A, uint64_t(0));
3093 auto *ConcatVec = IC.Builder.CreateInsertVector(RetTy, SubVec, B,
3094 TyA->getMinNumElements());
3095 ConcatVec->takeName(&II);
3096 return IC.replaceInstUsesWith(II, ConcatVec);
3097 }
3098 }
3099
3100 return std::nullopt;
3101}
3102
3103static std::optional<Instruction *> instCombineSVEZip(InstCombiner &IC,
3104 IntrinsicInst &II) {
3105 // zip1(uzp1(A, B), uzp2(A, B)) --> A
3106 // zip2(uzp1(A, B), uzp2(A, B)) --> B
3107 Value *A, *B;
3108 if (match(II.getArgOperand(0),
3111 m_Specific(A), m_Specific(B))))
3112 return IC.replaceInstUsesWith(
3113 II, (II.getIntrinsicID() == Intrinsic::aarch64_sve_zip1 ? A : B));
3114
3115 return std::nullopt;
3116}
3117
3118static std::optional<Instruction *>
3120 Value *Mask = II.getOperand(0);
3121 Value *BasePtr = II.getOperand(1);
3122 Value *Index = II.getOperand(2);
3123 Type *Ty = II.getType();
3124 Value *PassThru = ConstantAggregateZero::get(Ty);
3125
3126 // Contiguous gather => masked load.
3127 // (sve.ld1.gather.index Mask BasePtr (sve.index IndexBase 1))
3128 // => (masked.load (gep BasePtr IndexBase) Align Mask zeroinitializer)
3129 Value *IndexBase;
3131 m_One()))) {
3132 Align Alignment =
3133 BasePtr->getPointerAlignment(II.getDataLayout());
3134
3135 Value *Ptr = IC.Builder.CreateGEP(cast<VectorType>(Ty)->getElementType(),
3136 BasePtr, IndexBase);
3137 CallInst *MaskedLoad =
3138 IC.Builder.CreateMaskedLoad(Ty, Ptr, Alignment, Mask, PassThru);
3139 MaskedLoad->takeName(&II);
3140 return IC.replaceInstUsesWith(II, MaskedLoad);
3141 }
3142
3143 return std::nullopt;
3144}
3145
3146static std::optional<Instruction *>
3148 Value *Val = II.getOperand(0);
3149 Value *Mask = II.getOperand(1);
3150 Value *BasePtr = II.getOperand(2);
3151 Value *Index = II.getOperand(3);
3152 Type *Ty = Val->getType();
3153
3154 // Contiguous scatter => masked store.
3155 // (sve.st1.scatter.index Value Mask BasePtr (sve.index IndexBase 1))
3156 // => (masked.store Value (gep BasePtr IndexBase) Align Mask)
3157 Value *IndexBase;
3159 m_One()))) {
3160 Align Alignment =
3161 BasePtr->getPointerAlignment(II.getDataLayout());
3162
3163 Value *Ptr = IC.Builder.CreateGEP(cast<VectorType>(Ty)->getElementType(),
3164 BasePtr, IndexBase);
3165 (void)IC.Builder.CreateMaskedStore(Val, Ptr, Alignment, Mask);
3166
3167 return IC.eraseInstFromFunction(II);
3168 }
3169
3170 return std::nullopt;
3171}
3172
3173static std::optional<Instruction *> instCombineSVESDIV(InstCombiner &IC,
3174 IntrinsicInst &II) {
3175 Type *Int32Ty = IC.Builder.getInt32Ty();
3176 Value *Pred = II.getOperand(0);
3177 Value *Vec = II.getOperand(1);
3178 Value *DivVec = II.getOperand(2);
3179
3180 Value *SplatValue = getSplatValue(DivVec);
3181 ConstantInt *SplatConstantInt = dyn_cast_or_null<ConstantInt>(SplatValue);
3182 if (!SplatConstantInt)
3183 return std::nullopt;
3184
3185 APInt Divisor = SplatConstantInt->getValue();
3186 const int64_t DivisorValue = Divisor.getSExtValue();
3187 if (DivisorValue == -1)
3188 return std::nullopt;
3189 if (DivisorValue == 1)
3190 IC.replaceInstUsesWith(II, Vec);
3191
3192 if (Divisor.isPowerOf2()) {
3193 Constant *DivisorLog2 = ConstantInt::get(Int32Ty, Divisor.logBase2());
3194 auto ASRD = IC.Builder.CreateIntrinsic(
3195 Intrinsic::aarch64_sve_asrd, {II.getType()}, {Pred, Vec, DivisorLog2});
3196 return IC.replaceInstUsesWith(II, ASRD);
3197 }
3198 if (Divisor.isNegatedPowerOf2()) {
3199 Divisor.negate();
3200 Constant *DivisorLog2 = ConstantInt::get(Int32Ty, Divisor.logBase2());
3201 auto ASRD = IC.Builder.CreateIntrinsic(
3202 Intrinsic::aarch64_sve_asrd, {II.getType()}, {Pred, Vec, DivisorLog2});
3203 auto NEG = IC.Builder.CreateIntrinsic(
3204 Intrinsic::aarch64_sve_neg, {ASRD->getType()}, {ASRD, Pred, ASRD});
3205 return IC.replaceInstUsesWith(II, NEG);
3206 }
3207
3208 return std::nullopt;
3209}
3210
3211bool SimplifyValuePattern(SmallVector<Value *> &Vec, bool AllowPoison) {
3212 size_t VecSize = Vec.size();
3213 if (VecSize == 1)
3214 return true;
3215 if (!isPowerOf2_64(VecSize))
3216 return false;
3217 size_t HalfVecSize = VecSize / 2;
3218
3219 for (auto LHS = Vec.begin(), RHS = Vec.begin() + HalfVecSize;
3220 RHS != Vec.end(); LHS++, RHS++) {
3221 if (*LHS != nullptr && *RHS != nullptr) {
3222 if (*LHS == *RHS)
3223 continue;
3224 else
3225 return false;
3226 }
3227 if (!AllowPoison)
3228 return false;
3229 if (*LHS == nullptr && *RHS != nullptr)
3230 *LHS = *RHS;
3231 }
3232
3233 Vec.resize(HalfVecSize);
3234 SimplifyValuePattern(Vec, AllowPoison);
3235 return true;
3236}
3237
3238// Try to simplify dupqlane patterns like dupqlane(f32 A, f32 B, f32 A, f32 B)
3239// to dupqlane(f64(C)) where C is A concatenated with B
3240static std::optional<Instruction *> instCombineSVEDupqLane(InstCombiner &IC,
3241 IntrinsicInst &II) {
3242 Value *CurrentInsertElt = nullptr, *Default = nullptr;
3243 if (!match(II.getOperand(0),
3245 m_Value(Default), m_Value(CurrentInsertElt), m_Value())) ||
3246 !isa<FixedVectorType>(CurrentInsertElt->getType()))
3247 return std::nullopt;
3248 auto IIScalableTy = cast<ScalableVectorType>(II.getType());
3249
3250 // Insert the scalars into a container ordered by InsertElement index
3251 SmallVector<Value *> Elts(IIScalableTy->getMinNumElements(), nullptr);
3252 while (auto InsertElt = dyn_cast<InsertElementInst>(CurrentInsertElt)) {
3253 auto Idx = cast<ConstantInt>(InsertElt->getOperand(2));
3254 Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);
3255 CurrentInsertElt = InsertElt->getOperand(0);
3256 }
3257
3258 bool AllowPoison =
3259 isa<PoisonValue>(CurrentInsertElt) && isa<PoisonValue>(Default);
3260 if (!SimplifyValuePattern(Elts, AllowPoison))
3261 return std::nullopt;
3262
3263 // Rebuild the simplified chain of InsertElements. e.g. (a, b, a, b) as (a, b)
3264 Value *InsertEltChain = PoisonValue::get(CurrentInsertElt->getType());
3265 for (size_t I = 0; I < Elts.size(); I++) {
3266 if (Elts[I] == nullptr)
3267 continue;
3268 InsertEltChain = IC.Builder.CreateInsertElement(InsertEltChain, Elts[I],
3269 IC.Builder.getInt64(I));
3270 }
3271 if (InsertEltChain == nullptr)
3272 return std::nullopt;
3273
3274 // Splat the simplified sequence, e.g. (f16 a, f16 b, f16 c, f16 d) as one i64
3275 // value or (f16 a, f16 b) as one i32 value. This requires an InsertSubvector
3276 // be bitcast to a type wide enough to fit the sequence, be splatted, and then
3277 // be narrowed back to the original type.
3278 unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.size();
3279 unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *
3280 IIScalableTy->getMinNumElements() /
3281 PatternWidth;
3282
3283 IntegerType *WideTy = IC.Builder.getIntNTy(PatternWidth);
3284 auto *WideScalableTy = ScalableVectorType::get(WideTy, PatternElementCount);
3285 auto *WideShuffleMaskTy =
3286 ScalableVectorType::get(IC.Builder.getInt32Ty(), PatternElementCount);
3287
3288 auto InsertSubvector = IC.Builder.CreateInsertVector(
3289 II.getType(), PoisonValue::get(II.getType()), InsertEltChain,
3290 uint64_t(0));
3291 auto WideBitcast =
3292 IC.Builder.CreateBitOrPointerCast(InsertSubvector, WideScalableTy);
3293 auto WideShuffleMask = ConstantAggregateZero::get(WideShuffleMaskTy);
3294 auto WideShuffle = IC.Builder.CreateShuffleVector(
3295 WideBitcast, PoisonValue::get(WideScalableTy), WideShuffleMask);
3296 auto NarrowBitcast =
3297 IC.Builder.CreateBitOrPointerCast(WideShuffle, II.getType());
3298
3299 return IC.replaceInstUsesWith(II, NarrowBitcast);
3300}
3301
3302static std::optional<Instruction *> instCombineMaxMinNM(InstCombiner &IC,
3303 IntrinsicInst &II) {
3304 Value *A = II.getArgOperand(0);
3305 Value *B = II.getArgOperand(1);
3306 if (A == B)
3307 return IC.replaceInstUsesWith(II, A);
3308
3309 return std::nullopt;
3310}
3311
3312static std::optional<Instruction *> instCombineSVESrshl(InstCombiner &IC,
3313 IntrinsicInst &II) {
3314 Value *Pred = II.getOperand(0);
3315 Value *Vec = II.getOperand(1);
3316 Value *Shift = II.getOperand(2);
3317
3318 // Convert SRSHL into the simpler LSL intrinsic when fed by an ABS intrinsic.
3319 Value *AbsPred, *MergedValue;
3321 m_Value(MergedValue), m_Value(AbsPred), m_Value())) &&
3323 m_Value(MergedValue), m_Value(AbsPred), m_Value())))
3324
3325 return std::nullopt;
3326
3327 // Transform is valid if any of the following are true:
3328 // * The ABS merge value is an undef or non-negative
3329 // * The ABS predicate is all active
3330 // * The ABS predicate and the SRSHL predicates are the same
3331 if (!isa<UndefValue>(MergedValue) && !match(MergedValue, m_NonNegative()) &&
3332 AbsPred != Pred && !isAllActivePredicate(AbsPred))
3333 return std::nullopt;
3334
3335 // Only valid when the shift amount is non-negative, otherwise the rounding
3336 // behaviour of SRSHL cannot be ignored.
3337 if (!match(Shift, m_NonNegative()))
3338 return std::nullopt;
3339
3340 auto LSL = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_lsl,
3341 {II.getType()}, {Pred, Vec, Shift});
3342
3343 return IC.replaceInstUsesWith(II, LSL);
3344}
3345
3346static std::optional<Instruction *> instCombineSVEInsr(InstCombiner &IC,
3347 IntrinsicInst &II) {
3348 Value *Vec = II.getOperand(0);
3349
3350 if (getSplatValue(Vec) == II.getOperand(1))
3351 return IC.replaceInstUsesWith(II, Vec);
3352
3353 return std::nullopt;
3354}
3355
3356static std::optional<Instruction *> instCombineDMB(InstCombiner &IC,
3357 IntrinsicInst &II) {
3358 // If this barrier is post-dominated by identical one we can remove it
3359 auto *NI = II.getNextNode();
3360 unsigned LookaheadThreshold = DMBLookaheadThreshold;
3361 auto CanSkipOver = [](Instruction *I) {
3362 return !I->mayReadOrWriteMemory() && !I->mayHaveSideEffects();
3363 };
3364 while (LookaheadThreshold-- && CanSkipOver(NI)) {
3365 auto *NIBB = NI->getParent();
3366 NI = NI->getNextNode();
3367 if (!NI) {
3368 if (auto *SuccBB = NIBB->getUniqueSuccessor())
3369 NI = &*SuccBB->getFirstNonPHIOrDbgOrLifetime();
3370 else
3371 break;
3372 }
3373 }
3374 auto *NextII = dyn_cast_or_null<IntrinsicInst>(NI);
3375 if (NextII && II.isIdenticalTo(NextII))
3376 return IC.eraseInstFromFunction(II);
3377
3378 return std::nullopt;
3379}
3380
3381static std::optional<Instruction *> instCombineWhilelo(InstCombiner &IC,
3382 IntrinsicInst &II) {
3383 return IC.replaceInstUsesWith(
3384 II,
3385 IC.Builder.CreateIntrinsic(Intrinsic::get_active_lane_mask,
3386 {II.getType(), II.getOperand(0)->getType()},
3387 {II.getOperand(0), II.getOperand(1)}));
3388}
3389
3390static std::optional<Instruction *> instCombinePTrue(InstCombiner &IC,
3391 IntrinsicInst &II) {
3392 unsigned PredPattern = cast<ConstantInt>(II.getOperand(0))->getZExtValue();
3393 // SVE vector length is a power-of-two, thus pow2 is synonymous with all.
3394 if (PredPattern == AArch64SVEPredPattern::all ||
3395 PredPattern == AArch64SVEPredPattern::pow2)
3396 return IC.replaceInstUsesWith(II, ConstantInt::getTrue(II.getType()));
3397 return std::nullopt;
3398}
3399
3400static std::optional<Instruction *> instCombineSVEUxt(InstCombiner &IC,
3402 unsigned NumBits) {
3403 Value *Passthru = II.getOperand(0);
3404 Value *Pg = II.getOperand(1);
3405 Value *Op = II.getOperand(2);
3406
3407 // Convert UXT[BHW] to AND.
3408 if (isa<UndefValue>(Passthru) || isAllActivePredicate(Pg)) {
3409 auto *Ty = cast<VectorType>(II.getType());
3410 auto MaskValue = APInt::getLowBitsSet(Ty->getScalarSizeInBits(), NumBits);
3411 auto *Mask = ConstantInt::get(Ty, MaskValue);
3412 auto *And = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_and_u, {Ty},
3413 {Pg, Op, Mask});
3414 return IC.replaceInstUsesWith(II, And);
3415 }
3416
3417 return std::nullopt;
3418}
3419
3420static std::optional<Instruction *>
3422 SMEAttrs FnSMEAttrs(*II.getFunction());
3423 bool IsStreaming = FnSMEAttrs.hasStreamingInterfaceOrBody();
3424 if (IsStreaming || !FnSMEAttrs.hasStreamingCompatibleInterface())
3425 return IC.replaceInstUsesWith(
3426 II, ConstantInt::getBool(II.getType(), IsStreaming));
3427 return std::nullopt;
3428}
3429
3430static std::optional<Instruction *> instCombineSVEUMin(InstCombiner &IC,
3431 IntrinsicInst &II) {
3432 // umin(umin(A, 1), umin(B, 1)) -> umin(umin(A,B), 1)
3433 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3434 Value *A, *B;
3435 Value *Pg = II.getOperand(0);
3436 if (match(II.getOperand(1), m_OneUse(m_Intrinsic<UMinID>(
3437 m_Specific(Pg), m_Value(A), m_One()))) &&
3438 match(II.getOperand(2), m_OneUse(m_Intrinsic<UMinID>(
3439 m_Specific(Pg), m_Value(B), m_One())))) {
3440 Value *NewUMin =
3441 IC.Builder.CreateIntrinsic(UMinID, II.getType(), {Pg, A, B});
3442 Value *NewLogicalUMin = IC.Builder.CreateIntrinsic(
3443 UMinID, II.getType(), {Pg, NewUMin, ConstantInt::get(II.getType(), 1)});
3444 return IC.replaceInstUsesWith(II, NewLogicalUMin);
3445 }
3446
3447 // umin(umin(A, 1), 1) -> umin(A, 1)
3448 if (match(II.getOperand(1),
3450 match(II.getOperand(2), m_One()))
3451 return IC.replaceInstUsesWith(II, II.getOperand(1));
3452
3453 return std::nullopt;
3454}
3455
3456static std::optional<Instruction *> instCombineSVEOrr(InstCombiner &IC,
3457 IntrinsicInst &II) {
3458 // orr(umin(A, 1), umin(B, 1)) -> umin(orr(A, B), 1)
3459 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3460 Value *Pg = II.getOperand(0);
3461
3462 Value *A, *B;
3463 if (!match(II.getOperand(1), m_OneUse(m_Intrinsic<UMinID>(
3464 m_Specific(Pg), m_Value(A), m_One()))) ||
3465 !match(II.getOperand(2), m_OneUse(m_Intrinsic<UMinID>(
3466 m_Specific(Pg), m_Value(B), m_One()))))
3467 return std::nullopt;
3468
3469 Value *NewOrr = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_orr_u,
3470 II.getType(), {Pg, A, B});
3471 Value *NewUMin = IC.Builder.CreateIntrinsic(
3472 UMinID, II.getType(), {Pg, NewOrr, ConstantInt::get(II.getType(), 1)});
3473 return IC.replaceInstUsesWith(II, NewUMin);
3474}
3475
3476static std::optional<Instruction *> instCombineSVEAnd(InstCombiner &IC,
3477 IntrinsicInst &II) {
3478 // and(cmphs(pg, ConstA, A), cmphs(pg, A, ConstB))
3479 // ->
3480 // cmphs(pg, ConstA - ConstB, sub(pg, A, ConstB))
3481 constexpr Intrinsic::ID CmphsID = Intrinsic::aarch64_sve_cmphs;
3482 Value *Pg = II.getOperand(0);
3483 Value *LHS = II.getOperand(1);
3484 Value *RHS = II.getOperand(2);
3485
3486 Value *A, *PgLHS, *PgRHS;
3487 uint64_t ConstA, ConstB;
3488 if (!match(LHS, m_Intrinsic<CmphsID>(m_Value(PgLHS), m_ConstantInt(ConstA),
3489 m_Value(A))) ||
3491 m_ConstantInt(ConstB))) ||
3492 !LHS->hasOneUser() || !RHS->hasOneUser())
3493 return std::nullopt;
3494
3495 // Always false regardless of predication
3496 if (ConstB > ConstA)
3497 return IC.replaceInstUsesWith(II, Constant::getNullValue(II.getType()));
3498
3499 // The predicate for both CMPHSs must match.
3500 // The predicate for the AND can either be equal to the CMPHS predicates, or
3501 // either of the CMPHS values.
3502 if (PgLHS != PgRHS || (Pg != LHS && Pg != RHS && Pg != PgLHS))
3503 return std::nullopt;
3504
3505 Type *VecTy = A->getType();
3506 Constant *Base = ConstantInt::get(VecTy, ConstB);
3507 Value *Sub = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_sub_u, VecTy,
3508 {PgLHS, A, Base});
3509 Constant *Limit = ConstantInt::get(VecTy, ConstA - ConstB);
3510 Value *NewCmphs =
3511 IC.Builder.CreateIntrinsic(CmphsID, VecTy, {PgLHS, Limit, Sub});
3512
3513 return IC.replaceInstUsesWith(II, NewCmphs);
3514}
3515
3516std::optional<Instruction *>
3518 IntrinsicInst &II) const {
3520 if (std::optional<Instruction *> I = simplifySVEIntrinsic(IC, II, IInfo))
3521 return I;
3522
3523 Intrinsic::ID IID = II.getIntrinsicID();
3524 switch (IID) {
3525 default:
3526 break;
3527 case Intrinsic::aarch64_dmb:
3528 return instCombineDMB(IC, II);
3529 case Intrinsic::aarch64_neon_fmaxnm:
3530 case Intrinsic::aarch64_neon_fminnm:
3531 return instCombineMaxMinNM(IC, II);
3532 case Intrinsic::aarch64_sve_convert_from_svbool:
3533 return instCombineConvertFromSVBool(IC, II);
3534 case Intrinsic::aarch64_sve_dup:
3535 return instCombineSVEDup(IC, II);
3536 case Intrinsic::aarch64_sve_dup_x:
3537 return instCombineSVEDupX(IC, II);
3538 case Intrinsic::aarch64_sve_cmpeq:
3539 case Intrinsic::aarch64_sve_cmpeq_wide:
3540 return instCombineXorSVECmpCC(IC, II);
3541 case Intrinsic::aarch64_sve_cmpne:
3542 case Intrinsic::aarch64_sve_cmpne_wide:
3543 return instCombineSVECmpNE(IC, II);
3544 case Intrinsic::aarch64_sve_rdffr:
3545 return instCombineRDFFR(IC, II);
3546 case Intrinsic::aarch64_sve_lasta:
3547 case Intrinsic::aarch64_sve_lastb:
3548 return instCombineSVELast(IC, II);
3549 case Intrinsic::aarch64_sve_clasta_n:
3550 case Intrinsic::aarch64_sve_clastb_n:
3551 return instCombineSVECondLast(IC, II);
3552 case Intrinsic::aarch64_sve_cntd:
3553 return instCombineSVECntElts(IC, II, 2);
3554 case Intrinsic::aarch64_sve_cntw:
3555 return instCombineSVECntElts(IC, II, 4);
3556 case Intrinsic::aarch64_sve_cnth:
3557 return instCombineSVECntElts(IC, II, 8);
3558 case Intrinsic::aarch64_sve_cntb:
3559 return instCombineSVECntElts(IC, II, 16);
3560 case Intrinsic::aarch64_sme_cntsd:
3561 return instCombineSMECntsd(IC, II, ST);
3562 case Intrinsic::aarch64_sve_ptest_any:
3563 case Intrinsic::aarch64_sve_ptest_first:
3564 case Intrinsic::aarch64_sve_ptest_last:
3565 return instCombineSVEPTest(IC, II);
3566 case Intrinsic::aarch64_sve_fadd:
3567 return instCombineSVEVectorFAdd(IC, II);
3568 case Intrinsic::aarch64_sve_fadd_u:
3569 return instCombineSVEVectorFAddU(IC, II);
3570 case Intrinsic::aarch64_sve_fmul_u:
3571 return instCombineSVEVectorBinOp(IC, II);
3572 case Intrinsic::aarch64_sve_fsub:
3573 return instCombineSVEVectorFSub(IC, II);
3574 case Intrinsic::aarch64_sve_fsub_u:
3575 return instCombineSVEVectorFSubU(IC, II);
3576 case Intrinsic::aarch64_sve_add:
3577 return instCombineSVEVectorAdd(IC, II);
3578 case Intrinsic::aarch64_sve_add_u:
3579 return instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul_u,
3580 Intrinsic::aarch64_sve_mla_u>(
3581 IC, II, true);
3582 case Intrinsic::aarch64_sve_mla_u:
3583 return instCombineSVEVectorMlaU(IC, II);
3584 case Intrinsic::aarch64_sve_sadalp:
3585 case Intrinsic::aarch64_sve_uadalp:
3587 case Intrinsic::aarch64_sve_sub:
3588 return instCombineSVEVectorSub(IC, II);
3589 case Intrinsic::aarch64_sve_sub_u:
3590 return instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul_u,
3591 Intrinsic::aarch64_sve_mls_u>(
3592 IC, II, true);
3593 case Intrinsic::aarch64_sve_tbl:
3594 return instCombineSVETBL(IC, II);
3595 case Intrinsic::aarch64_sve_uunpkhi:
3596 case Intrinsic::aarch64_sve_uunpklo:
3597 case Intrinsic::aarch64_sve_sunpkhi:
3598 case Intrinsic::aarch64_sve_sunpklo:
3599 return instCombineSVEUnpack(IC, II);
3600 case Intrinsic::aarch64_sve_uzp1:
3601 return instCombineSVEUzp1(IC, II);
3602 case Intrinsic::aarch64_sve_zip1:
3603 case Intrinsic::aarch64_sve_zip2:
3604 return instCombineSVEZip(IC, II);
3605 case Intrinsic::aarch64_sve_ld1_gather_index:
3606 return instCombineLD1GatherIndex(IC, II);
3607 case Intrinsic::aarch64_sve_st1_scatter_index:
3608 return instCombineST1ScatterIndex(IC, II);
3609 case Intrinsic::aarch64_sve_ld1:
3610 return instCombineSVELD1(IC, II, DL);
3611 case Intrinsic::aarch64_sve_st1:
3612 return instCombineSVEST1(IC, II, DL);
3613 case Intrinsic::aarch64_sve_sdiv:
3614 return instCombineSVESDIV(IC, II);
3615 case Intrinsic::aarch64_sve_sel:
3616 return instCombineSVESel(IC, II);
3617 case Intrinsic::aarch64_sve_srshl:
3618 return instCombineSVESrshl(IC, II);
3619 case Intrinsic::aarch64_sve_dupq_lane:
3620 return instCombineSVEDupqLane(IC, II);
3621 case Intrinsic::aarch64_sve_insr:
3622 return instCombineSVEInsr(IC, II);
3623 case Intrinsic::aarch64_sve_whilelo:
3624 return instCombineWhilelo(IC, II);
3625 case Intrinsic::aarch64_sve_ptrue:
3626 return instCombinePTrue(IC, II);
3627 case Intrinsic::aarch64_sve_uxtb:
3628 return instCombineSVEUxt(IC, II, 8);
3629 case Intrinsic::aarch64_sve_uxth:
3630 return instCombineSVEUxt(IC, II, 16);
3631 case Intrinsic::aarch64_sve_uxtw:
3632 return instCombineSVEUxt(IC, II, 32);
3633 case Intrinsic::aarch64_sme_in_streaming_mode:
3634 return instCombineInStreamingMode(IC, II);
3635 case Intrinsic::aarch64_sve_umin_u:
3636 return instCombineSVEUMin(IC, II);
3637 case Intrinsic::aarch64_sve_orr_u:
3638 return instCombineSVEOrr(IC, II);
3639 case Intrinsic::aarch64_sve_and_z:
3640 return instCombineSVEAnd(IC, II);
3641 }
3642
3643 return std::nullopt;
3644}
3645
3647 InstCombiner &IC, IntrinsicInst &II, APInt OrigDemandedElts,
3648 APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3,
3649 std::function<void(Instruction *, unsigned, APInt, APInt &)>
3650 SimplifyAndSetOp) const {
3651 switch (II.getIntrinsicID()) {
3652 default:
3653 break;
3654 case Intrinsic::aarch64_neon_fcvtxn:
3655 case Intrinsic::aarch64_neon_rshrn:
3656 case Intrinsic::aarch64_neon_sqrshrn:
3657 case Intrinsic::aarch64_neon_sqrshrun:
3658 case Intrinsic::aarch64_neon_sqshrn:
3659 case Intrinsic::aarch64_neon_sqshrun:
3660 case Intrinsic::aarch64_neon_sqxtn:
3661 case Intrinsic::aarch64_neon_sqxtun:
3662 case Intrinsic::aarch64_neon_uqrshrn:
3663 case Intrinsic::aarch64_neon_uqshrn:
3664 case Intrinsic::aarch64_neon_uqxtn:
3665 SimplifyAndSetOp(&II, 0, OrigDemandedElts, UndefElts);
3666 break;
3667 }
3668
3669 return std::nullopt;
3670}
3671
3673 return ST->isSVEAvailable() || (ST->isSVEorStreamingSVEAvailable() &&
3675}
3676
3679 switch (K) {
3681 return TypeSize::getFixed(64);
3683 if (ST->useSVEForFixedLengthVectors() &&
3684 (ST->isSVEAvailable() || EnableFixedwidthAutovecInStreamingMode))
3685 return TypeSize::getFixed(
3686 std::max(ST->getMinSVEVectorSizeInBits(), 128u));
3687 else if (ST->isNeonAvailable())
3688 return TypeSize::getFixed(128);
3689 else
3690 return TypeSize::getFixed(0);
3692 if (ST->isSVEAvailable() || (ST->isSVEorStreamingSVEAvailable() &&
3694 return TypeSize::getScalable(128);
3695 else
3696 return TypeSize::getScalable(0);
3697 }
3698 llvm_unreachable("Unsupported register kind");
3699}
3700
3701bool AArch64TTIImpl::isSingleExtWideningInstruction(
3702 unsigned Opcode, Type *DstTy, ArrayRef<const Value *> Args,
3703 Type *SrcOverrideTy) const {
3704 // A helper that returns a vector type from the given type. The number of
3705 // elements in type Ty determines the vector width.
3706 auto toVectorTy = [&](Type *ArgTy) {
3707 return VectorType::get(ArgTy->getScalarType(),
3708 cast<VectorType>(DstTy)->getElementCount());
3709 };
3710
3711 // Exit early if DstTy is not a vector type whose elements are one of [i16,
3712 // i32, i64]. SVE doesn't generally have the same set of instructions to
3713 // perform an extend with the add/sub/mul. There are SMULLB style
3714 // instructions, but they operate on top/bottom, requiring some sort of lane
3715 // interleaving to be used with zext/sext.
3716 unsigned DstEltSize = DstTy->getScalarSizeInBits();
3717 if (!useNeonVector(DstTy) || Args.size() != 2 ||
3718 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3719 return false;
3720
3721 Type *SrcTy = SrcOverrideTy;
3722 switch (Opcode) {
3723 case Instruction::Add: // UADDW(2), SADDW(2).
3724 case Instruction::Sub: { // USUBW(2), SSUBW(2).
3725 // The second operand needs to be an extend
3726 if (isa<SExtInst>(Args[1]) || isa<ZExtInst>(Args[1])) {
3727 if (!SrcTy)
3728 SrcTy =
3729 toVectorTy(cast<Instruction>(Args[1])->getOperand(0)->getType());
3730 break;
3731 }
3732
3733 if (Opcode == Instruction::Sub)
3734 return false;
3735
3736 // UADDW(2), SADDW(2) can be commutted.
3737 if (isa<SExtInst>(Args[0]) || isa<ZExtInst>(Args[0])) {
3738 if (!SrcTy)
3739 SrcTy =
3740 toVectorTy(cast<Instruction>(Args[0])->getOperand(0)->getType());
3741 break;
3742 }
3743 return false;
3744 }
3745 default:
3746 return false;
3747 }
3748
3749 // Legalize the destination type and ensure it can be used in a widening
3750 // operation.
3751 auto DstTyL = getTypeLegalizationCost(DstTy);
3752 if (!DstTyL.second.isVector() || DstEltSize != DstTy->getScalarSizeInBits())
3753 return false;
3754
3755 // Legalize the source type and ensure it can be used in a widening
3756 // operation.
3757 assert(SrcTy && "Expected some SrcTy");
3758 auto SrcTyL = getTypeLegalizationCost(SrcTy);
3759 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();
3760 if (!SrcTyL.second.isVector() || SrcElTySize != SrcTy->getScalarSizeInBits())
3761 return false;
3762
3763 // Get the total number of vector elements in the legalized types.
3764 InstructionCost NumDstEls =
3765 DstTyL.first * DstTyL.second.getVectorMinNumElements();
3766 InstructionCost NumSrcEls =
3767 SrcTyL.first * SrcTyL.second.getVectorMinNumElements();
3768
3769 // Return true if the legalized types have the same number of vector elements
3770 // and the destination element type size is twice that of the source type.
3771 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;
3772}
3773
3774Type *AArch64TTIImpl::isBinExtWideningInstruction(unsigned Opcode, Type *DstTy,
3776 Type *SrcOverrideTy) const {
3777 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3778 Opcode != Instruction::Mul)
3779 return nullptr;
3780
3781 // Exit early if DstTy is not a vector type whose elements are one of [i16,
3782 // i32, i64]. SVE doesn't generally have the same set of instructions to
3783 // perform an extend with the add/sub/mul. There are SMULLB style
3784 // instructions, but they operate on top/bottom, requiring some sort of lane
3785 // interleaving to be used with zext/sext.
3786 unsigned DstEltSize = DstTy->getScalarSizeInBits();
3787 if (!useNeonVector(DstTy) || Args.size() != 2 ||
3788 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3789 return nullptr;
3790
3791 auto getScalarSizeWithOverride = [&](const Value *V) {
3792 if (SrcOverrideTy)
3793 return SrcOverrideTy->getScalarSizeInBits();
3794 return cast<Instruction>(V)
3795 ->getOperand(0)
3796 ->getType()
3797 ->getScalarSizeInBits();
3798 };
3799
3800 unsigned MaxEltSize = 0;
3801 if ((isa<SExtInst>(Args[0]) && isa<SExtInst>(Args[1])) ||
3802 (isa<ZExtInst>(Args[0]) && isa<ZExtInst>(Args[1]))) {
3803 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3804 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3805 MaxEltSize = std::max(EltSize0, EltSize1);
3806 } else if (isa<SExtInst, ZExtInst>(Args[0]) &&
3807 isa<SExtInst, ZExtInst>(Args[1])) {
3808 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3809 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3810 // mul(sext, zext) will become smull(sext, zext) if the extends are large
3811 // enough.
3812 if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)
3813 return nullptr;
3814 MaxEltSize = DstEltSize / 2;
3815 } else if (Opcode == Instruction::Mul &&
3816 (isa<ZExtInst>(Args[0]) || isa<ZExtInst>(Args[1]))) {
3817 // If one of the operands is a Zext and the other has enough zero bits
3818 // to be treated as unsigned, we can still generate a umull, meaning the
3819 // zext is free.
3820 KnownBits Known =
3821 computeKnownBits(isa<ZExtInst>(Args[0]) ? Args[1] : Args[0], DL);
3822 if (Args[0]->getType()->getScalarSizeInBits() -
3823 Known.Zero.countLeadingOnes() >
3824 DstTy->getScalarSizeInBits() / 2)
3825 return nullptr;
3826
3827 MaxEltSize =
3828 getScalarSizeWithOverride(isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);
3829 } else
3830 return nullptr;
3831
3832 if (MaxEltSize * 2 > DstEltSize)
3833 return nullptr;
3834
3835 Type *ExtTy = DstTy->getWithNewBitWidth(MaxEltSize * 2);
3836 if (ExtTy->getPrimitiveSizeInBits() <= 64)
3837 return nullptr;
3838 return ExtTy;
3839}
3840
3841// s/urhadd instructions implement the following pattern, making the
3842// extends free:
3843// %x = add ((zext i8 -> i16), 1)
3844// %y = (zext i8 -> i16)
3845// trunc i16 (lshr (add %x, %y), 1) -> i8
3846//
3848 Type *Src) const {
3849 // The source should be a legal vector type.
3850 if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(DL, Src)) ||
3851 (Src->isScalableTy() && !ST->hasSVE2()))
3852 return false;
3853
3854 if (ExtUser->getOpcode() != Instruction::Add || !ExtUser->hasOneUse())
3855 return false;
3856
3857 // Look for trunc/shl/add before trying to match the pattern.
3858 const Instruction *Add = ExtUser;
3859 auto *AddUser =
3860 dyn_cast_or_null<Instruction>(Add->getUniqueUndroppableUser());
3861 if (AddUser && AddUser->getOpcode() == Instruction::Add)
3862 Add = AddUser;
3863
3864 auto *Shr = dyn_cast_or_null<Instruction>(Add->getUniqueUndroppableUser());
3865 if (!Shr || Shr->getOpcode() != Instruction::LShr)
3866 return false;
3867
3868 auto *Trunc = dyn_cast_or_null<Instruction>(Shr->getUniqueUndroppableUser());
3869 if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||
3870 Src->getScalarSizeInBits() !=
3871 cast<CastInst>(Trunc)->getDestTy()->getScalarSizeInBits())
3872 return false;
3873
3874 // Try to match the whole pattern. Ext could be either the first or second
3875 // m_ZExtOrSExt matched.
3876 Instruction *Ex1, *Ex2;
3877 if (!(match(Add, m_c_Add(m_Instruction(Ex1),
3878 m_c_Add(m_Instruction(Ex2), m_One())))))
3879 return false;
3880
3881 // Ensure both extends are of the same type
3882 if (match(Ex1, m_ZExtOrSExt(m_Value())) &&
3883 Ex1->getOpcode() == Ex2->getOpcode())
3884 return true;
3885
3886 return false;
3887}
3888
3890 Type *Src,
3893 const Instruction *I) const {
3894 int ISD = TLI->InstructionOpcodeToISD(Opcode);
3895 assert(ISD && "Invalid opcode");
3896 // If the cast is observable, and it is used by a widening instruction (e.g.,
3897 // uaddl, saddw, etc.), it may be free.
3898 if (I && !I->users().empty()) {
3899 // Determine whether Usr can absorb the cast from Src to Dst into a
3900 // widening instruction (e.g. uaddl, saddw, urhadd), making the cast free
3901 // with respect to that user.
3902 auto GetUserAbsorbedCastCost =
3903 [&](const Instruction *Usr) -> std::optional<InstructionCost> {
3904 SmallVector<const Value *, 4> Operands(Usr->operand_values());
3905
3906 if (Type *ExtTy = isBinExtWideningInstruction(
3907 Usr->getOpcode(), Dst, Operands,
3908 Src != I->getOperand(0)->getType() ? Src : nullptr)) {
3909 // The cost from Src->Src*2 needs to be added if required, the cost
3910 // from Src*2->ExtTy is free.
3911 if (ExtTy->getScalarSizeInBits() > Src->getScalarSizeInBits() * 2) {
3912 Type *DoubleSrcTy =
3913 Src->getWithNewBitWidth(Src->getScalarSizeInBits() * 2);
3914 return getCastInstrCost(Opcode, DoubleSrcTy, Src,
3916 }
3917
3918 return 0;
3919 }
3920
3921 if (isSingleExtWideningInstruction(
3922 Usr->getOpcode(), Dst, Operands,
3923 Src != I->getOperand(0)->getType() ? Src : nullptr)) {
3924 // For adds only count the second operand as free if both operands
3925 // are extends but not the same operation. (i.e both operands are
3926 // not free in add(sext, zext)).
3927 if (Usr->getOpcode() == Instruction::Add) {
3928 if (I == Usr->getOperand(1) ||
3929 (isa<CastInst>(Usr->getOperand(1)) &&
3930 cast<CastInst>(Usr->getOperand(1))->getOpcode() == Opcode))
3931 return 0;
3932 } else {
3933 // Others are free so long as isSingleExtWideningInstruction
3934 // returned true.
3935 return 0;
3936 }
3937 }
3938
3939 // The cast will be free for the s/urhadd instructions
3940 if ((isa<ZExtInst>(I) || isa<SExtInst>(I)) &&
3941 isExtPartOfAvgExpr(Usr, Dst, Src))
3942 return 0;
3943
3944 return std::nullopt;
3945 };
3946
3947 InstructionCost MaxAbsorbedCost = 0;
3948 bool AllUsersAbsorbCast = true;
3949 for (const User *U : I->users()) {
3950 auto *Usr = cast<Instruction>(U);
3951 std::optional<InstructionCost> UserCost = GetUserAbsorbedCastCost(Usr);
3952 if (!UserCost) {
3953 AllUsersAbsorbCast = false;
3954 break;
3955 }
3956 MaxAbsorbedCost = std::max(MaxAbsorbedCost, *UserCost);
3957 }
3958
3959 if (AllUsersAbsorbCast)
3960 return MaxAbsorbedCost;
3961 }
3962
3963 EVT SrcTy = TLI->getValueType(DL, Src);
3964 EVT DstTy = TLI->getValueType(DL, Dst);
3965
3966 // From a vector to a scalarized vector will be an series of extract-element
3967 // and extends.
3968 if ((ISD == ISD::ZERO_EXTEND || ISD == ISD::SIGN_EXTEND) &&
3969 DstTy.getScalarSizeInBits() > 64 && SrcTy.getScalarSizeInBits() <= 64 &&
3970 DstTy.isFixedLengthVector()) {
3972 Instruction::ExtractElement, Src, CostKind, -1, nullptr, nullptr);
3974 Opcode, Dst->getScalarType(), Src->getScalarType(), CCH, CostKind);
3975 return DstTy.getVectorNumElements() * (LaneCost + ExtCost);
3976 }
3977
3978 if (!SrcTy.isSimple() || !DstTy.isSimple())
3979 return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I);
3980
3981 // For the moment we do not have lowering for SVE1-only fptrunc f64->bf16 as
3982 // we use fcvtx under SVE2. Give them invalid costs.
3983 if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&
3984 ISD == ISD::FP_ROUND && SrcTy.isScalableVector() &&
3985 DstTy.getScalarType() == MVT::bf16 && SrcTy.getScalarType() == MVT::f64)
3987
3988 static const TypeConversionCostTblEntry BF16Tbl[] = {
3989 {ISD::FP_ROUND, MVT::bf16, MVT::f32, 1}, // bfcvt
3990 {ISD::FP_ROUND, MVT::bf16, MVT::f64, 1}, // bfcvt
3991 {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f32, 1}, // bfcvtn
3992 {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f32, 2}, // bfcvtn+bfcvtn2
3993 {ISD::FP_ROUND, MVT::v2bf16, MVT::v2f64, 2}, // bfcvtn+fcvtn
3994 {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f64, 3}, // fcvtn+fcvtl2+bfcvtn
3995 {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f64, 6}, // 2 * fcvtn+fcvtn2+bfcvtn
3996 {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f32, 1}, // bfcvt
3997 {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f32, 1}, // bfcvt
3998 {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f32, 3}, // bfcvt+bfcvt+uzp1
3999 {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f64, 2}, // fcvtx+bfcvt
4000 {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f64, 5}, // 2*fcvtx+2*bfcvt+uzp1
4001 {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f64, 11}, // 4*fcvt+4*bfcvt+3*uzp
4002 };
4003
4004 if (ST->hasBF16())
4005 if (const auto *Entry = ConvertCostTableLookup(
4006 BF16Tbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()))
4007 return Entry->Cost;
4008
4009 // We have to estimate a cost of fixed length operation upon
4010 // SVE registers(operations) with the number of registers required
4011 // for a fixed type to be represented upon SVE registers.
4012 EVT WiderTy = SrcTy.bitsGT(DstTy) ? SrcTy : DstTy;
4013 if (SrcTy.isFixedLengthVector() && DstTy.isFixedLengthVector() &&
4014 SrcTy.getVectorNumElements() == DstTy.getVectorNumElements() &&
4015 ST->useSVEForFixedLengthVectors(WiderTy)) {
4016 std::pair<InstructionCost, MVT> LT =
4017 getTypeLegalizationCost(WiderTy.getTypeForEVT(Dst->getContext()));
4018 unsigned NumElements =
4019 AArch64::SVEBitsPerBlock / LT.second.getScalarSizeInBits();
4020 return LT.first *
4022 Opcode,
4023 ScalableVectorType::get(Dst->getScalarType(), NumElements),
4024 ScalableVectorType::get(Src->getScalarType(), NumElements), CCH,
4025 CostKind, I);
4026 }
4027
4028 // Symbolic constants for the SVE sitofp/uitofp entries in the table below
4029 // The cost of unpacking twice is artificially increased for now in order
4030 // to avoid regressions against NEON, which will use tbl instructions directly
4031 // instead of multiple layers of [s|u]unpk[lo|hi].
4032 // We use the unpacks in cases where the destination type is illegal and
4033 // requires splitting of the input, even if the input type itself is legal.
4034 const unsigned int SVE_EXT_COST = 1;
4035 const unsigned int SVE_FCVT_COST = 1;
4036 const unsigned int SVE_UNPACK_ONCE = 4;
4037 const unsigned int SVE_UNPACK_TWICE = 16;
4038
4039 static const TypeConversionCostTblEntry ConversionTbl[] = {
4040 {ISD::TRUNCATE, MVT::v2i8, MVT::v2i64, 1}, // xtn
4041 {ISD::TRUNCATE, MVT::v2i16, MVT::v2i64, 1}, // xtn
4042 {ISD::TRUNCATE, MVT::v2i32, MVT::v2i64, 1}, // xtn
4043 {ISD::TRUNCATE, MVT::v4i8, MVT::v4i32, 1}, // xtn
4044 {ISD::TRUNCATE, MVT::v4i8, MVT::v4i64, 3}, // 2 xtn + 1 uzp1
4045 {ISD::TRUNCATE, MVT::v4i16, MVT::v4i32, 1}, // xtn
4046 {ISD::TRUNCATE, MVT::v4i16, MVT::v4i64, 2}, // 1 uzp1 + 1 xtn
4047 {ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 1}, // 1 uzp1
4048 {ISD::TRUNCATE, MVT::v8i8, MVT::v8i16, 1}, // 1 xtn
4049 {ISD::TRUNCATE, MVT::v8i8, MVT::v8i32, 2}, // 1 uzp1 + 1 xtn
4050 {ISD::TRUNCATE, MVT::v8i8, MVT::v8i64, 4}, // 3 x uzp1 + xtn
4051 {ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, 1}, // 1 uzp1
4052 {ISD::TRUNCATE, MVT::v8i16, MVT::v8i64, 3}, // 3 x uzp1
4053 {ISD::TRUNCATE, MVT::v8i32, MVT::v8i64, 2}, // 2 x uzp1
4054 {ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 1}, // uzp1
4055 {ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, 3}, // (2 + 1) x uzp1
4056 {ISD::TRUNCATE, MVT::v16i8, MVT::v16i64, 7}, // (4 + 2 + 1) x uzp1
4057 {ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, 2}, // 2 x uzp1
4058 {ISD::TRUNCATE, MVT::v16i16, MVT::v16i64, 6}, // (4 + 2) x uzp1
4059 {ISD::TRUNCATE, MVT::v16i32, MVT::v16i64, 4}, // 4 x uzp1
4060
4061 // Truncations on nxvmiN
4062 {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i8, 2},
4063 {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i16, 2},
4064 {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i32, 2},
4065 {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i64, 2},
4066 {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i8, 2},
4067 {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i16, 2},
4068 {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i32, 2},
4069 {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i64, 5},
4070 {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i8, 2},
4071 {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i16, 2},
4072 {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i32, 5},
4073 {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i64, 11},
4074 {ISD::TRUNCATE, MVT::nxv16i1, MVT::nxv16i8, 2},
4075 {ISD::TRUNCATE, MVT::nxv2i8, MVT::nxv2i16, 0},
4076 {ISD::TRUNCATE, MVT::nxv2i8, MVT::nxv2i32, 0},
4077 {ISD::TRUNCATE, MVT::nxv2i8, MVT::nxv2i64, 0},
4078 {ISD::TRUNCATE, MVT::nxv2i16, MVT::nxv2i32, 0},
4079 {ISD::TRUNCATE, MVT::nxv2i16, MVT::nxv2i64, 0},
4080 {ISD::TRUNCATE, MVT::nxv2i32, MVT::nxv2i64, 0},
4081 {ISD::TRUNCATE, MVT::nxv4i8, MVT::nxv4i16, 0},
4082 {ISD::TRUNCATE, MVT::nxv4i8, MVT::nxv4i32, 0},
4083 {ISD::TRUNCATE, MVT::nxv4i8, MVT::nxv4i64, 1},
4084 {ISD::TRUNCATE, MVT::nxv4i16, MVT::nxv4i32, 0},
4085 {ISD::TRUNCATE, MVT::nxv4i16, MVT::nxv4i64, 1},
4086 {ISD::TRUNCATE, MVT::nxv4i32, MVT::nxv4i64, 1},
4087 {ISD::TRUNCATE, MVT::nxv8i8, MVT::nxv8i16, 0},
4088 {ISD::TRUNCATE, MVT::nxv8i8, MVT::nxv8i32, 1},
4089 {ISD::TRUNCATE, MVT::nxv8i8, MVT::nxv8i64, 3},
4090 {ISD::TRUNCATE, MVT::nxv8i16, MVT::nxv8i32, 1},
4091 {ISD::TRUNCATE, MVT::nxv8i16, MVT::nxv8i64, 3},
4092 {ISD::TRUNCATE, MVT::nxv16i8, MVT::nxv16i16, 1},
4093 {ISD::TRUNCATE, MVT::nxv16i8, MVT::nxv16i32, 3},
4094 {ISD::TRUNCATE, MVT::nxv16i8, MVT::nxv16i64, 7},
4095
4096 // The number of shll instructions for the extension.
4097 {ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i16, 3},
4098 {ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i16, 3},
4099 {ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 2},
4100 {ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 2},
4101 {ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i8, 3},
4102 {ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i8, 3},
4103 {ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 2},
4104 {ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 2},
4105 {ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i8, 7},
4106 {ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i8, 7},
4107 {ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i16, 6},
4108 {ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i16, 6},
4109 {ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, 2},
4110 {ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, 2},
4111 {ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i8, 6},
4112 {ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i8, 6},
4113
4114 // FP Ext and trunc
4115 {ISD::FP_EXTEND, MVT::f64, MVT::f32, 1}, // fcvt
4116 {ISD::FP_EXTEND, MVT::v2f64, MVT::v2f32, 1}, // fcvtl
4117 {ISD::FP_EXTEND, MVT::v4f64, MVT::v4f32, 2}, // fcvtl+fcvtl2
4118 // FP16
4119 {ISD::FP_EXTEND, MVT::f32, MVT::f16, 1}, // fcvt
4120 {ISD::FP_EXTEND, MVT::f64, MVT::f16, 1}, // fcvt
4121 {ISD::FP_EXTEND, MVT::v4f32, MVT::v4f16, 1}, // fcvtl
4122 {ISD::FP_EXTEND, MVT::v8f32, MVT::v8f16, 2}, // fcvtl+fcvtl2
4123 {ISD::FP_EXTEND, MVT::v2f64, MVT::v2f16, 2}, // fcvtl+fcvtl
4124 {ISD::FP_EXTEND, MVT::v4f64, MVT::v4f16, 3}, // fcvtl+fcvtl2+fcvtl
4125 {ISD::FP_EXTEND, MVT::v8f64, MVT::v8f16, 6}, // 2 * fcvtl+fcvtl2+fcvtl
4126 // BF16 (uses shift)
4127 {ISD::FP_EXTEND, MVT::f32, MVT::bf16, 1}, // shl
4128 {ISD::FP_EXTEND, MVT::f64, MVT::bf16, 2}, // shl+fcvt
4129 {ISD::FP_EXTEND, MVT::v4f32, MVT::v4bf16, 1}, // shll
4130 {ISD::FP_EXTEND, MVT::v8f32, MVT::v8bf16, 2}, // shll+shll2
4131 {ISD::FP_EXTEND, MVT::v2f64, MVT::v2bf16, 2}, // shll+fcvtl
4132 {ISD::FP_EXTEND, MVT::v4f64, MVT::v4bf16, 3}, // shll+fcvtl+fcvtl2
4133 {ISD::FP_EXTEND, MVT::v8f64, MVT::v8bf16, 6}, // 2 * shll+fcvtl+fcvtl2
4134 // FP Ext and trunc
4135 {ISD::FP_ROUND, MVT::f32, MVT::f64, 1}, // fcvt
4136 {ISD::FP_ROUND, MVT::v2f32, MVT::v2f64, 1}, // fcvtn
4137 {ISD::FP_ROUND, MVT::v4f32, MVT::v4f64, 2}, // fcvtn+fcvtn2
4138 // FP16
4139 {ISD::FP_ROUND, MVT::f16, MVT::f32, 1}, // fcvt
4140 {ISD::FP_ROUND, MVT::f16, MVT::f64, 1}, // fcvt
4141 {ISD::FP_ROUND, MVT::v4f16, MVT::v4f32, 1}, // fcvtn
4142 {ISD::FP_ROUND, MVT::v8f16, MVT::v8f32, 2}, // fcvtn+fcvtn2
4143 {ISD::FP_ROUND, MVT::v2f16, MVT::v2f64, 2}, // fcvtn+fcvtn
4144 {ISD::FP_ROUND, MVT::v4f16, MVT::v4f64, 3}, // fcvtn+fcvtn2+fcvtn
4145 {ISD::FP_ROUND, MVT::v8f16, MVT::v8f64, 6}, // 2 * fcvtn+fcvtn2+fcvtn
4146 // BF16 (more complex, with +bf16 is handled above)
4147 {ISD::FP_ROUND, MVT::bf16, MVT::f32, 8}, // Expansion is ~8 insns
4148 {ISD::FP_ROUND, MVT::bf16, MVT::f64, 9}, // fcvtn + above
4149 {ISD::FP_ROUND, MVT::v2bf16, MVT::v2f32, 8},
4150 {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f32, 8},
4151 {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f32, 15},
4152 {ISD::FP_ROUND, MVT::v2bf16, MVT::v2f64, 9},
4153 {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f64, 10},
4154 {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f64, 19},
4155
4156 // LowerVectorINT_TO_FP:
4157 {ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i32, 1},
4158 {ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, 1},
4159 {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, 1},
4160 {ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 1},
4161 {ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 1},
4162 {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 1},
4163
4164 // SVE: to nxv2f16
4165 {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i8,
4166 SVE_EXT_COST + SVE_FCVT_COST},
4167 {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i16, SVE_FCVT_COST},
4168 {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i32, SVE_FCVT_COST},
4169 {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i64, SVE_FCVT_COST},
4170 {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i8,
4171 SVE_EXT_COST + SVE_FCVT_COST},
4172 {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i16, SVE_FCVT_COST},
4173 {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i32, SVE_FCVT_COST},
4174 {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i64, SVE_FCVT_COST},
4175
4176 // SVE: to nxv4f16
4177 {ISD::SINT_TO_FP, MVT::nxv4f16, MVT::nxv4i8,
4178 SVE_EXT_COST + SVE_FCVT_COST},
4179 {ISD::SINT_TO_FP, MVT::nxv4f16, MVT::nxv4i16, SVE_FCVT_COST},
4180 {ISD::SINT_TO_FP, MVT::nxv4f16, MVT::nxv4i32, SVE_FCVT_COST},
4181 {ISD::UINT_TO_FP, MVT::nxv4f16, MVT::nxv4i8,
4182 SVE_EXT_COST + SVE_FCVT_COST},
4183 {ISD::UINT_TO_FP, MVT::nxv4f16, MVT::nxv4i16, SVE_FCVT_COST},
4184 {ISD::UINT_TO_FP, MVT::nxv4f16, MVT::nxv4i32, SVE_FCVT_COST},
4185
4186 // SVE: to nxv8f16
4187 {ISD::SINT_TO_FP, MVT::nxv8f16, MVT::nxv8i8,
4188 SVE_EXT_COST + SVE_FCVT_COST},
4189 {ISD::SINT_TO_FP, MVT::nxv8f16, MVT::nxv8i16, SVE_FCVT_COST},
4190 {ISD::UINT_TO_FP, MVT::nxv8f16, MVT::nxv8i8,
4191 SVE_EXT_COST + SVE_FCVT_COST},
4192 {ISD::UINT_TO_FP, MVT::nxv8f16, MVT::nxv8i16, SVE_FCVT_COST},
4193
4194 // SVE: to nxv16f16
4195 {ISD::SINT_TO_FP, MVT::nxv16f16, MVT::nxv16i8,
4196 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4197 {ISD::UINT_TO_FP, MVT::nxv16f16, MVT::nxv16i8,
4198 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4199
4200 // Complex: to v2f32
4201 {ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i8, 3},
4202 {ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i16, 3},
4203 {ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i8, 3},
4204 {ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i16, 3},
4205
4206 // SVE: to nxv2f32
4207 {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i8,
4208 SVE_EXT_COST + SVE_FCVT_COST},
4209 {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i16, SVE_FCVT_COST},
4210 {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i32, SVE_FCVT_COST},
4211 {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i64, SVE_FCVT_COST},
4212 {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i8,
4213 SVE_EXT_COST + SVE_FCVT_COST},
4214 {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i16, SVE_FCVT_COST},
4215 {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i32, SVE_FCVT_COST},
4216 {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i64, SVE_FCVT_COST},
4217
4218 // Complex: to v4f32
4219 {ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i8, 4},
4220 {ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i16, 2},
4221 {ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i8, 3},
4222 {ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i16, 2},
4223
4224 // SVE: to nxv4f32
4225 {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i8,
4226 SVE_EXT_COST + SVE_FCVT_COST},
4227 {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i16, SVE_FCVT_COST},
4228 {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i32, SVE_FCVT_COST},
4229 {ISD::UINT_TO_FP, MVT::nxv4f32, MVT::nxv4i8,
4230 SVE_EXT_COST + SVE_FCVT_COST},
4231 {ISD::UINT_TO_FP, MVT::nxv4f32, MVT::nxv4i16, SVE_FCVT_COST},
4232 {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i32, SVE_FCVT_COST},
4233
4234 // Complex: to v8f32
4235 {ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i8, 10},
4236 {ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, 4},
4237 {ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i8, 10},
4238 {ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, 4},
4239
4240 // SVE: to nxv8f32
4241 {ISD::SINT_TO_FP, MVT::nxv8f32, MVT::nxv8i8,
4242 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4243 {ISD::SINT_TO_FP, MVT::nxv8f32, MVT::nxv8i16,
4244 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4245 {ISD::UINT_TO_FP, MVT::nxv8f32, MVT::nxv8i8,
4246 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4247 {ISD::UINT_TO_FP, MVT::nxv8f32, MVT::nxv8i16,
4248 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4249
4250 // SVE: to nxv16f32
4251 {ISD::SINT_TO_FP, MVT::nxv16f32, MVT::nxv16i8,
4252 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4253 {ISD::UINT_TO_FP, MVT::nxv16f32, MVT::nxv16i8,
4254 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4255
4256 // Complex: to v16f32
4257 {ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i8, 21},
4258 {ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i8, 21},
4259
4260 // Complex: to v2f64
4261 {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i8, 4},
4262 {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i16, 4},
4263 {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i32, 2},
4264 {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i8, 4},
4265 {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i16, 4},
4266 {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, 2},
4267
4268 // SVE: to nxv2f64
4269 {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i8,
4270 SVE_EXT_COST + SVE_FCVT_COST},
4271 {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i16, SVE_FCVT_COST},
4272 {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i32, SVE_FCVT_COST},
4273 {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i64, SVE_FCVT_COST},
4274 {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i8,
4275 SVE_EXT_COST + SVE_FCVT_COST},
4276 {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i16, SVE_FCVT_COST},
4277 {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i32, SVE_FCVT_COST},
4278 {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i64, SVE_FCVT_COST},
4279
4280 // Complex: to v4f64
4281 {ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, 4},
4282 {ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, 4},
4283
4284 // SVE: to nxv4f64
4285 {ISD::SINT_TO_FP, MVT::nxv4f64, MVT::nxv4i8,
4286 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4287 {ISD::SINT_TO_FP, MVT::nxv4f64, MVT::nxv4i16,
4288 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4289 {ISD::SINT_TO_FP, MVT::nxv4f64, MVT::nxv4i32,
4290 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4291 {ISD::UINT_TO_FP, MVT::nxv4f64, MVT::nxv4i8,
4292 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4293 {ISD::UINT_TO_FP, MVT::nxv4f64, MVT::nxv4i16,
4294 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4295 {ISD::UINT_TO_FP, MVT::nxv4f64, MVT::nxv4i32,
4296 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4297
4298 // SVE: to nxv8f64
4299 {ISD::SINT_TO_FP, MVT::nxv8f64, MVT::nxv8i8,
4300 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4301 {ISD::SINT_TO_FP, MVT::nxv8f64, MVT::nxv8i16,
4302 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4303 {ISD::UINT_TO_FP, MVT::nxv8f64, MVT::nxv8i8,
4304 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4305 {ISD::UINT_TO_FP, MVT::nxv8f64, MVT::nxv8i16,
4306 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4307
4308 // LowerVectorFP_TO_INT
4309 {ISD::FP_TO_SINT, MVT::v2i32, MVT::v2f32, 1},
4310 {ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, 1},
4311 {ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f64, 1},
4312 {ISD::FP_TO_UINT, MVT::v2i32, MVT::v2f32, 1},
4313 {ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 1},
4314 {ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f64, 1},
4315
4316 // Complex, from v2f32: legal type is v2i32 (no cost) or v2i64 (1 ext).
4317 {ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f32, 2},
4318 {ISD::FP_TO_SINT, MVT::v2i16, MVT::v2f32, 1},
4319 {ISD::FP_TO_SINT, MVT::v2i8, MVT::v2f32, 1},
4320 {ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f32, 2},
4321 {ISD::FP_TO_UINT, MVT::v2i16, MVT::v2f32, 1},
4322 {ISD::FP_TO_UINT, MVT::v2i8, MVT::v2f32, 1},
4323
4324 // Complex, from v4f32: legal type is v4i16, 1 narrowing => ~2
4325 {ISD::FP_TO_SINT, MVT::v4i16, MVT::v4f32, 2},
4326 {ISD::FP_TO_SINT, MVT::v4i8, MVT::v4f32, 2},
4327 {ISD::FP_TO_UINT, MVT::v4i16, MVT::v4f32, 2},
4328 {ISD::FP_TO_UINT, MVT::v4i8, MVT::v4f32, 2},
4329
4330 // Complex, from v2f64: legal type is v2i32, 1 narrowing => ~2.
4331 {ISD::FP_TO_SINT, MVT::v2i32, MVT::v2f64, 2},
4332 {ISD::FP_TO_SINT, MVT::v2i16, MVT::v2f64, 2},
4333 {ISD::FP_TO_SINT, MVT::v2i8, MVT::v2f64, 2},
4334 {ISD::FP_TO_UINT, MVT::v2i32, MVT::v2f64, 2},
4335 {ISD::FP_TO_UINT, MVT::v2i16, MVT::v2f64, 2},
4336 {ISD::FP_TO_UINT, MVT::v2i8, MVT::v2f64, 2},
4337
4338 // Complex, from nxv2f32.
4339 {ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f32, 1},
4340 {ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f32, 1},
4341 {ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f32, 1},
4342 {ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f32, 1},
4343 {ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f32, 1},
4344 {ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f32, 1},
4345 {ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f32, 1},
4346 {ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f32, 1},
4347
4348 // Complex, from nxv2f64.
4349 {ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f64, 1},
4350 {ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f64, 1},
4351 {ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f64, 1},
4352 {ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f64, 1},
4353 {ISD::FP_TO_SINT, MVT::nxv2i1, MVT::nxv2f64, 1},
4354 {ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f64, 1},
4355 {ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f64, 1},
4356 {ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f64, 1},
4357 {ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f64, 1},
4358 {ISD::FP_TO_UINT, MVT::nxv2i1, MVT::nxv2f64, 1},
4359
4360 // Complex, from nxv4f32.
4361 {ISD::FP_TO_SINT, MVT::nxv4i64, MVT::nxv4f32, 4},
4362 {ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f32, 1},
4363 {ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f32, 1},
4364 {ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f32, 1},
4365 {ISD::FP_TO_SINT, MVT::nxv4i1, MVT::nxv4f32, 1},
4366 {ISD::FP_TO_UINT, MVT::nxv4i64, MVT::nxv4f32, 4},
4367 {ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f32, 1},
4368 {ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f32, 1},
4369 {ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f32, 1},
4370 {ISD::FP_TO_UINT, MVT::nxv4i1, MVT::nxv4f32, 1},
4371
4372 // Complex, from nxv8f64. Illegal -> illegal conversions not required.
4373 {ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f64, 7},
4374 {ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f64, 7},
4375 {ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f64, 7},
4376 {ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f64, 7},
4377
4378 // Complex, from nxv4f64. Illegal -> illegal conversions not required.
4379 {ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f64, 3},
4380 {ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f64, 3},
4381 {ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f64, 3},
4382 {ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f64, 3},
4383 {ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f64, 3},
4384 {ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f64, 3},
4385
4386 // Complex, from nxv8f32. Illegal -> illegal conversions not required.
4387 {ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f32, 3},
4388 {ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f32, 3},
4389 {ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f32, 3},
4390 {ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f32, 3},
4391
4392 // Complex, from nxv8f16.
4393 {ISD::FP_TO_SINT, MVT::nxv8i64, MVT::nxv8f16, 10},
4394 {ISD::FP_TO_SINT, MVT::nxv8i32, MVT::nxv8f16, 4},
4395 {ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f16, 1},
4396 {ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f16, 1},
4397 {ISD::FP_TO_SINT, MVT::nxv8i1, MVT::nxv8f16, 1},
4398 {ISD::FP_TO_UINT, MVT::nxv8i64, MVT::nxv8f16, 10},
4399 {ISD::FP_TO_UINT, MVT::nxv8i32, MVT::nxv8f16, 4},
4400 {ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f16, 1},
4401 {ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f16, 1},
4402 {ISD::FP_TO_UINT, MVT::nxv8i1, MVT::nxv8f16, 1},
4403
4404 // Complex, from nxv4f16.
4405 {ISD::FP_TO_SINT, MVT::nxv4i64, MVT::nxv4f16, 4},
4406 {ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f16, 1},
4407 {ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f16, 1},
4408 {ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f16, 1},
4409 {ISD::FP_TO_UINT, MVT::nxv4i64, MVT::nxv4f16, 4},
4410 {ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f16, 1},
4411 {ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f16, 1},
4412 {ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f16, 1},
4413
4414 // Complex, from nxv2f16.
4415 {ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f16, 1},
4416 {ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f16, 1},
4417 {ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f16, 1},
4418 {ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f16, 1},
4419 {ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f16, 1},
4420 {ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f16, 1},
4421 {ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f16, 1},
4422 {ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f16, 1},
4423
4424 // Truncate from nxvmf32 to nxvmf16.
4425 {ISD::FP_ROUND, MVT::nxv2f16, MVT::nxv2f32, 1},
4426 {ISD::FP_ROUND, MVT::nxv4f16, MVT::nxv4f32, 1},
4427 {ISD::FP_ROUND, MVT::nxv8f16, MVT::nxv8f32, 3},
4428
4429 // Truncate from nxvmf32 to nxvmbf16.
4430 {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f32, 8},
4431 {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f32, 8},
4432 {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f32, 17},
4433
4434 // Truncate from nxvmf64 to nxvmf16.
4435 {ISD::FP_ROUND, MVT::nxv2f16, MVT::nxv2f64, 1},
4436 {ISD::FP_ROUND, MVT::nxv4f16, MVT::nxv4f64, 3},
4437 {ISD::FP_ROUND, MVT::nxv8f16, MVT::nxv8f64, 7},
4438
4439 // Truncate from nxvmf64 to nxvmbf16.
4440 {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f64, 9},
4441 {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f64, 19},
4442 {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f64, 39},
4443
4444 // Truncate from nxvmf64 to nxvmf32.
4445 {ISD::FP_ROUND, MVT::nxv2f32, MVT::nxv2f64, 1},
4446 {ISD::FP_ROUND, MVT::nxv4f32, MVT::nxv4f64, 3},
4447 {ISD::FP_ROUND, MVT::nxv8f32, MVT::nxv8f64, 6},
4448
4449 // Extend from nxvmf16 to nxvmf32.
4450 {ISD::FP_EXTEND, MVT::nxv2f32, MVT::nxv2f16, 1},
4451 {ISD::FP_EXTEND, MVT::nxv4f32, MVT::nxv4f16, 1},
4452 {ISD::FP_EXTEND, MVT::nxv8f32, MVT::nxv8f16, 2},
4453
4454 // Extend from nxvmbf16 to nxvmf32.
4455 {ISD::FP_EXTEND, MVT::nxv2f32, MVT::nxv2bf16, 1}, // lsl
4456 {ISD::FP_EXTEND, MVT::nxv4f32, MVT::nxv4bf16, 1}, // lsl
4457 {ISD::FP_EXTEND, MVT::nxv8f32, MVT::nxv8bf16, 4}, // unpck+unpck+lsl+lsl
4458
4459 // Extend from nxvmf16 to nxvmf64.
4460 {ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2f16, 1},
4461 {ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4f16, 2},
4462 {ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8f16, 4},
4463
4464 // Extend from nxvmbf16 to nxvmf64.
4465 {ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2bf16, 2}, // lsl+fcvt
4466 {ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4bf16, 6}, // 2*unpck+2*lsl+2*fcvt
4467 {ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8bf16, 14}, // 6*unpck+4*lsl+4*fcvt
4468
4469 // Extend from nxvmf32 to nxvmf64.
4470 {ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2f32, 1},
4471 {ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4f32, 2},
4472 {ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8f32, 6},
4473
4474 // Bitcasts from float to integer
4475 {ISD::BITCAST, MVT::nxv2f16, MVT::nxv2i16, 0},
4476 {ISD::BITCAST, MVT::nxv4f16, MVT::nxv4i16, 0},
4477 {ISD::BITCAST, MVT::nxv2f32, MVT::nxv2i32, 0},
4478
4479 // Bitcasts from integer to float
4480 {ISD::BITCAST, MVT::nxv2i16, MVT::nxv2f16, 0},
4481 {ISD::BITCAST, MVT::nxv4i16, MVT::nxv4f16, 0},
4482 {ISD::BITCAST, MVT::nxv2i32, MVT::nxv2f32, 0},
4483
4484 // Add cost for extending to illegal -too wide- scalable vectors.
4485 // zero/sign extend are implemented by multiple unpack operations,
4486 // where each operation has a cost of 1.
4487 {ISD::ZERO_EXTEND, MVT::nxv16i16, MVT::nxv16i8, 2},
4488 {ISD::ZERO_EXTEND, MVT::nxv16i32, MVT::nxv16i8, 6},
4489 {ISD::ZERO_EXTEND, MVT::nxv16i64, MVT::nxv16i8, 14},
4490 {ISD::ZERO_EXTEND, MVT::nxv8i32, MVT::nxv8i16, 2},
4491 {ISD::ZERO_EXTEND, MVT::nxv8i64, MVT::nxv8i16, 6},
4492 {ISD::ZERO_EXTEND, MVT::nxv4i64, MVT::nxv4i32, 2},
4493
4494 {ISD::SIGN_EXTEND, MVT::nxv16i16, MVT::nxv16i8, 2},
4495 {ISD::SIGN_EXTEND, MVT::nxv16i32, MVT::nxv16i8, 6},
4496 {ISD::SIGN_EXTEND, MVT::nxv16i64, MVT::nxv16i8, 14},
4497 {ISD::SIGN_EXTEND, MVT::nxv8i32, MVT::nxv8i16, 2},
4498 {ISD::SIGN_EXTEND, MVT::nxv8i64, MVT::nxv8i16, 6},
4499 {ISD::SIGN_EXTEND, MVT::nxv4i64, MVT::nxv4i32, 2},
4500 };
4501
4502 if (const auto *Entry = ConvertCostTableLookup(
4503 ConversionTbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()))
4504 return Entry->Cost;
4505
4506 static const TypeConversionCostTblEntry FP16Tbl[] = {
4507 {ISD::FP_TO_SINT, MVT::v4i8, MVT::v4f16, 1}, // fcvtzs
4508 {ISD::FP_TO_UINT, MVT::v4i8, MVT::v4f16, 1},
4509 {ISD::FP_TO_SINT, MVT::v4i16, MVT::v4f16, 1}, // fcvtzs
4510 {ISD::FP_TO_UINT, MVT::v4i16, MVT::v4f16, 1},
4511 {ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f16, 2}, // fcvtl+fcvtzs
4512 {ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f16, 2},
4513 {ISD::FP_TO_SINT, MVT::v8i8, MVT::v8f16, 2}, // fcvtzs+xtn
4514 {ISD::FP_TO_UINT, MVT::v8i8, MVT::v8f16, 2},
4515 {ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f16, 1}, // fcvtzs
4516 {ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f16, 1},
4517 {ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f16, 4}, // 2*fcvtl+2*fcvtzs
4518 {ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f16, 4},
4519 {ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f16, 3}, // 2*fcvtzs+xtn
4520 {ISD::FP_TO_UINT, MVT::v16i8, MVT::v16f16, 3},
4521 {ISD::FP_TO_SINT, MVT::v16i16, MVT::v16f16, 2}, // 2*fcvtzs
4522 {ISD::FP_TO_UINT, MVT::v16i16, MVT::v16f16, 2},
4523 {ISD::FP_TO_SINT, MVT::v16i32, MVT::v16f16, 8}, // 4*fcvtl+4*fcvtzs
4524 {ISD::FP_TO_UINT, MVT::v16i32, MVT::v16f16, 8},
4525 {ISD::UINT_TO_FP, MVT::v8f16, MVT::v8i8, 2}, // ushll + ucvtf
4526 {ISD::SINT_TO_FP, MVT::v8f16, MVT::v8i8, 2}, // sshll + scvtf
4527 {ISD::UINT_TO_FP, MVT::v16f16, MVT::v16i8, 4}, // 2 * ushl(2) + 2 * ucvtf
4528 {ISD::SINT_TO_FP, MVT::v16f16, MVT::v16i8, 4}, // 2 * sshl(2) + 2 * scvtf
4529 };
4530
4531 if (ST->hasFullFP16())
4532 if (const auto *Entry = ConvertCostTableLookup(
4533 FP16Tbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()))
4534 return Entry->Cost;
4535
4536 // INT_TO_FP of i64->f32 will scalarize, which is required to avoid
4537 // double-rounding issues.
4538 if ((ISD == ISD::SINT_TO_FP || ISD == ISD::UINT_TO_FP) &&
4539 DstTy.getScalarType() == MVT::f32 && SrcTy.getScalarSizeInBits() > 32 &&
4541 return cast<FixedVectorType>(Dst)->getNumElements() *
4542 getCastInstrCost(Opcode, Dst->getScalarType(),
4543 Src->getScalarType(), CCH, CostKind) +
4545 true, CostKind) +
4547 false, CostKind);
4548
4549 if ((ISD == ISD::ZERO_EXTEND || ISD == ISD::SIGN_EXTEND) &&
4551 ST->isSVEorStreamingSVEAvailable() &&
4552 TLI->getTypeAction(Src->getContext(), SrcTy) ==
4554 TLI->getTypeAction(Dst->getContext(), DstTy) ==
4556 // The standard behaviour in the backend for these cases is to split the
4557 // extend up into two parts:
4558 // 1. Perform an extending load or masked load up to the legal type.
4559 // 2. Extend the loaded data to the final type.
4560 std::pair<InstructionCost, MVT> SrcLT = getTypeLegalizationCost(Src);
4561 Type *LegalTy = EVT(SrcLT.second).getTypeForEVT(Src->getContext());
4563 Opcode, LegalTy, Src, CCH, CostKind, I);
4565 Opcode, Dst, LegalTy, TTI::CastContextHint::None, CostKind, I);
4566 return Part1 + Part2;
4567 }
4568
4569 // The BasicTTIImpl version only deals with CCH==TTI::CastContextHint::Normal,
4570 // but we also want to include the TTI::CastContextHint::Masked case too.
4571 if ((ISD == ISD::ZERO_EXTEND || ISD == ISD::SIGN_EXTEND) &&
4573 ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))
4575
4576 return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I);
4577}
4578
4581 VectorType *VecTy, unsigned Index,
4583
4584 // Make sure we were given a valid extend opcode.
4585 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
4586 "Invalid opcode");
4587
4588 // We are extending an element we extract from a vector, so the source type
4589 // of the extend is the element type of the vector.
4590 auto *Src = VecTy->getElementType();
4591
4592 // Sign- and zero-extends are for integer types only.
4593 assert(isa<IntegerType>(Dst) && isa<IntegerType>(Src) && "Invalid type");
4594
4595 // Get the cost for the extract. We compute the cost (if any) for the extend
4596 // below.
4597 InstructionCost Cost = getVectorInstrCost(Instruction::ExtractElement, VecTy,
4598 CostKind, Index, nullptr, nullptr);
4599
4600 // Legalize the types.
4601 auto VecLT = getTypeLegalizationCost(VecTy);
4602 auto DstVT = TLI->getValueType(DL, Dst);
4603 auto SrcVT = TLI->getValueType(DL, Src);
4604
4605 // If the resulting type is still a vector and the destination type is legal,
4606 // we may get the extension for free. If not, get the default cost for the
4607 // extend.
4608 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))
4609 return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None,
4610 CostKind);
4611
4612 // The destination type should be larger than the element type. If not, get
4613 // the default cost for the extend.
4614 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())
4615 return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None,
4616 CostKind);
4617
4618 switch (Opcode) {
4619 default:
4620 llvm_unreachable("Opcode should be either SExt or ZExt");
4621
4622 // For sign-extends, we only need a smov, which performs the extension
4623 // automatically.
4624 case Instruction::SExt:
4625 return Cost;
4626
4627 // For zero-extends, the extend is performed automatically by a umov unless
4628 // the destination type is i64 and the element type is i8 or i16.
4629 case Instruction::ZExt:
4630 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)
4631 return Cost;
4632 }
4633
4634 // If we are unable to perform the extend for free, get the default cost.
4635 return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None,
4636 CostKind);
4637}
4638
4641 const Instruction *I) const {
4643 return Opcode == Instruction::PHI ? 0 : 1;
4644 assert(CostKind == TTI::TCK_RecipThroughput && "unexpected CostKind");
4645 // Branches are assumed to be predicted.
4646 return 0;
4647}
4648
4649InstructionCost AArch64TTIImpl::getVectorInstrCostHelper(
4650 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index,
4651 const Instruction *I, Value *Scalar,
4652 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4653 TTI::VectorInstrContext VIC) const {
4654 assert(Ty->isVectorTy() && "This must be a vector type");
4655
4656 if (Index != -1U) {
4657 // Legalize the type.
4658 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
4659
4660 // This type is legalized to a scalar type.
4661 if (!LT.second.isVector())
4662 return 0;
4663
4664 // The type may be split. For fixed-width vectors we can normalize the
4665 // index to the new type.
4666 if (LT.second.isFixedLengthVector()) {
4667 unsigned Width = LT.second.getVectorNumElements();
4668 Index = Index % Width;
4669 }
4670
4671 // The element at index zero is already inside the vector.
4672 // - For a insert-element or extract-element
4673 // instruction that extracts integers, an explicit FPR -> GPR move is
4674 // needed. So it has non-zero cost.
4675 if (Index == 0 && !Ty->getScalarType()->isIntegerTy())
4676 return 0;
4677
4678 // SVE has no scalar move to an arbitrary lane above the low 128-bit portion
4679 // of a Z register, e.g. there is no equivalent of "mov z0.d[9], d0".
4680 // Fixed-length vectors wider than 128 bits therefore need
4681 // [splice]/index/pred/splat/cmp/pred-mov when scalarizing inserts for those
4682 // lanes, so model them as more expensive than ordinary NEON lane accesses.
4683 if (ST->useSVEForFixedLengthVectors()) {
4685 ? 1
4687 if (Index * Ty->getScalarSizeInBits() < 128)
4688 return Cost;
4689 if (Index * Ty->getScalarSizeInBits() < 512 &&
4690 Opcode == Instruction::ExtractElement)
4691 // Integer extracts (>128b, <512b) require extra mov from FPR -> GPR.
4692 return Ty->getScalarType()->isIntegerTy() ? Cost + 1 : Cost;
4693 if (Opcode == Instruction::ExtractElement)
4694 return Cost + 2; // cost of mov imm + whilels + lastb
4695 if (Opcode == Instruction::InsertElement)
4696 return Cost + 3; // cost of insert with cmp/splice
4697 llvm_unreachable("unexpected opcode");
4698 }
4699
4700 // This is recognising a LD1 single-element structure to one lane of one
4701 // register instruction. I.e., if this is an `insertelement` instruction,
4702 // and its second operand is a load, then we will generate a LD1, which
4703 // are expensive instructions on some uArchs.
4704 if (VIC == TTI::VectorInstrContext::Load) {
4705 if (ST->hasFastLD1Single())
4706 return 0;
4707 return CostKind == TTI::TCK_CodeSize
4708 ? 0
4709 : ST->getVectorInsertExtractBaseCost() + 1;
4710 }
4711
4712 // i1 inserts and extract will include an extra cset or cmp of the vector
4713 // value. Increase the cost by 1 to account.
4714 if (Ty->getScalarSizeInBits() == 1)
4715 return CostKind == TTI::TCK_CodeSize
4716 ? 2
4717 : ST->getVectorInsertExtractBaseCost() + 1;
4718
4719 // FIXME:
4720 // If the extract-element and insert-element instructions could be
4721 // simplified away (e.g., could be combined into users by looking at use-def
4722 // context), they have no cost. This is not done in the first place for
4723 // compile-time considerations.
4724 }
4725
4726 // In case of Neon, if there exists extractelement from lane != 0 such that
4727 // 1. extractelement does not necessitate a move from vector_reg -> GPR.
4728 // 2. extractelement result feeds into fmul.
4729 // 3. Other operand of fmul is an extractelement from lane 0 or lane
4730 // equivalent to 0.
4731 // then the extractelement can be merged with fmul in the backend and it
4732 // incurs no cost.
4733 // e.g.
4734 // define double @foo(<2 x double> %a) {
4735 // %1 = extractelement <2 x double> %a, i32 0
4736 // %2 = extractelement <2 x double> %a, i32 1
4737 // %res = fmul double %1, %2
4738 // ret double %res
4739 // }
4740 // %2 and %res can be merged in the backend to generate fmul d0, d0, v1.d[1]
4741 auto ExtractCanFuseWithFmul = [&]() {
4742 // We bail out if the extract is from lane 0.
4743 if (Index == 0)
4744 return false;
4745
4746 // Check if the scalar element type of the vector operand of ExtractElement
4747 // instruction is one of the allowed types.
4748 auto IsAllowedScalarTy = [&](const Type *T) {
4749 return T->isFloatTy() || T->isDoubleTy() ||
4750 (T->isHalfTy() && ST->hasFullFP16());
4751 };
4752
4753 // Check if the extractelement user is scalar fmul.
4754 auto IsUserFMulScalarTy = [](const Value *EEUser) {
4755 // Check if the user is scalar fmul.
4756 const auto *BO = dyn_cast<BinaryOperator>(EEUser);
4757 return BO && BO->getOpcode() == BinaryOperator::FMul &&
4758 !BO->getType()->isVectorTy();
4759 };
4760
4761 // Check if the extract index is from lane 0 or lane equivalent to 0 for a
4762 // certain scalar type and a certain vector register width.
4763 auto IsExtractLaneEquivalentToZero = [&](unsigned Idx, unsigned EltSz) {
4764 auto RegWidth =
4766 .getFixedValue();
4767 return Idx == 0 || (RegWidth != 0 && (Idx * EltSz) % RegWidth == 0);
4768 };
4769
4770 // Check if the type constraints on input vector type and result scalar type
4771 // of extractelement instruction are satisfied.
4772 if (!isa<FixedVectorType>(Ty) || !IsAllowedScalarTy(Ty->getScalarType()))
4773 return false;
4774
4775 if (Scalar) {
4776 DenseMap<User *, unsigned> UserToExtractIdx;
4777 for (auto *U : Scalar->users()) {
4778 if (!IsUserFMulScalarTy(U))
4779 return false;
4780 // Recording entry for the user is important. Index value is not
4781 // important.
4782 UserToExtractIdx[U];
4783 }
4784 if (UserToExtractIdx.empty())
4785 return false;
4786 for (auto &[S, U, L] : ScalarUserAndIdx) {
4787 for (auto *U : S->users()) {
4788 if (UserToExtractIdx.contains(U)) {
4789 auto *FMul = cast<BinaryOperator>(U);
4790 auto *Op0 = FMul->getOperand(0);
4791 auto *Op1 = FMul->getOperand(1);
4792 if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {
4793 UserToExtractIdx[U] = L;
4794 break;
4795 }
4796 }
4797 }
4798 }
4799 for (auto &[U, L] : UserToExtractIdx) {
4800 if (!IsExtractLaneEquivalentToZero(Index, Ty->getScalarSizeInBits()) &&
4801 !IsExtractLaneEquivalentToZero(L, Ty->getScalarSizeInBits()))
4802 return false;
4803 }
4804 } else {
4805 const auto *EE = cast<ExtractElementInst>(I);
4806
4807 const auto *IdxOp = dyn_cast<ConstantInt>(EE->getIndexOperand());
4808 if (!IdxOp)
4809 return false;
4810
4811 return !EE->users().empty() && all_of(EE->users(), [&](const User *U) {
4812 if (!IsUserFMulScalarTy(U))
4813 return false;
4814
4815 // Check if the other operand of extractelement is also extractelement
4816 // from lane equivalent to 0.
4817 const auto *BO = cast<BinaryOperator>(U);
4818 const auto *OtherEE = dyn_cast<ExtractElementInst>(
4819 BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));
4820 if (OtherEE) {
4821 const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());
4822 if (!IdxOp)
4823 return false;
4824 return IsExtractLaneEquivalentToZero(
4825 cast<ConstantInt>(OtherEE->getIndexOperand())
4826 ->getValue()
4827 .getZExtValue(),
4828 OtherEE->getType()->getScalarSizeInBits());
4829 }
4830 return true;
4831 });
4832 }
4833 return true;
4834 };
4835
4836 if (Opcode == Instruction::ExtractElement && (I || Scalar) &&
4837 ExtractCanFuseWithFmul())
4838 return 0;
4839
4840 // All other insert/extracts cost this much.
4841 return CostKind == TTI::TCK_CodeSize ? 1
4842 : ST->getVectorInsertExtractBaseCost();
4843}
4844
4846 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index,
4847 const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC) const {
4848 // Treat insert at lane 0 into a poison vector as having zero cost. This
4849 // ensures vector broadcasts via an insert + shuffle (and will be lowered to a
4850 // single dup) are treated as cheap.
4851 if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&
4852 isa<PoisonValue>(Op0))
4853 return 0;
4854 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index, nullptr, nullptr,
4855 {}, VIC);
4856}
4857
4859 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index,
4860 Value *Scalar, ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4861 TTI::VectorInstrContext VIC) const {
4862 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index, nullptr, Scalar,
4863 ScalarUserAndIdx, VIC);
4864}
4865
4868 TTI::TargetCostKind CostKind, unsigned Index,
4869 TTI::VectorInstrContext VIC) const {
4870 return getVectorInstrCostHelper(I.getOpcode(), Ty, CostKind, Index, &I,
4871 nullptr, {}, VIC);
4872}
4873
4877 unsigned Index) const {
4878 if (isa<FixedVectorType>(Ty))
4879 return BaseT::getIndexedVectorInstrCostFromEnd(Opcode, Ty, CostKind, Index);
4880
4881 // This typically requires both while and lastb instructions in order
4882 // to extract the last element. If this is in a loop the while
4883 // instruction can at least be hoisted out, although it will consume a
4884 // predicate register. The cost should be more expensive than the base
4885 // extract cost, which is 2 for most CPUs.
4886 return CostKind == TTI::TCK_CodeSize
4887 ? 2
4888 : ST->getVectorInsertExtractBaseCost() + 1;
4889}
4890
4892 VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract,
4893 TTI::TargetCostKind CostKind, bool ForPoisonSrc, ArrayRef<Value *> VL,
4894 TTI::VectorInstrContext VIC) const {
4897 if (Ty->getElementType()->isFloatingPointTy())
4898 return BaseT::getScalarizationOverhead(Ty, DemandedElts, Insert, Extract,
4899 CostKind);
4900 unsigned VecInstCost =
4901 CostKind == TTI::TCK_CodeSize ? 1 : ST->getVectorInsertExtractBaseCost();
4902 return DemandedElts.popcount() * (Insert + Extract) * VecInstCost;
4903}
4904
4905std::optional<InstructionCost> AArch64TTIImpl::getFP16BF16PromoteCost(
4907 TTI::OperandValueInfo Op2Info, bool IncludeTrunc, bool CanUseSVE,
4908 std::function<InstructionCost(Type *)> InstCost) const {
4909 if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())
4910 return std::nullopt;
4911 if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())
4912 return std::nullopt;
4913 // If we have +sve-b16b16 the operation can be promoted to SVE.
4914 if (CanUseSVE && ST->hasSVEB16B16() && ST->isNonStreamingSVEorSME2Available())
4915 return std::nullopt;
4916
4917 Type *PromotedTy = Ty->getWithNewType(Type::getFloatTy(Ty->getContext()));
4918 InstructionCost Cost = getCastInstrCost(Instruction::FPExt, PromotedTy, Ty,
4920 if (!Op1Info.isConstant() && !Op2Info.isConstant())
4921 Cost *= 2;
4922 Cost += InstCost(PromotedTy);
4923 if (IncludeTrunc)
4924 Cost += getCastInstrCost(Instruction::FPTrunc, Ty, PromotedTy,
4926 return Cost;
4927}
4928
4930 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
4932 ArrayRef<const Value *> Args, const Instruction *CtxI) const {
4933
4934 // The code-generator is currently not able to handle scalable vectors
4935 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
4936 // it until all instructions are vetted.
4937 int ISD = TLI->InstructionOpcodeToISD(Opcode);
4938 if (auto *VTy = dyn_cast<ScalableVectorType>(Ty))
4939 if (VTy->getElementCount() == ElementCount::getScalable(1))
4942
4943 // Legalize the type.
4944 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
4945
4946 // TODO: Handle more cost kinds for floating point operations.
4947 if (ISD == ISD::FADD || ISD == ISD::FSUB || ISD == ISD::FMUL ||
4948 ISD == ISD::FDIV || ISD == ISD::FREM || ISD == ISD::FNEG)
4950 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
4951 Op2Info, Args, CtxI);
4952
4953 if (ISD == ISD::FADD || ISD == ISD::FSUB || ISD == ISD::FMUL ||
4954 ISD == ISD::FDIV || ISD == ISD::FREM) {
4955 // Increase the cost for half and bfloat types if not architecturally
4956 // supported.
4957 if (auto PromotedCost = getFP16BF16PromoteCost(
4958 Ty, CostKind, Op1Info, Op2Info, /*IncludeTrunc=*/true,
4959 // There is not native support for fdiv/frem even with +sve-b16b16.
4960 /*CanUseSVE=*/ISD != ISD::FDIV && ISD != ISD::FREM,
4961 [&](Type *PromotedTy) {
4962 return getArithmeticInstrCost(Opcode, PromotedTy, CostKind,
4963 Op1Info, Op2Info);
4964 }))
4965 return *PromotedCost;
4966
4967 // fp128 all go via libcalls
4968 if (Ty->getScalarType()->isFP128Ty())
4969 return (CostKind == TTI::TCK_CodeSize ? 1 : 10) * LT.first;
4970 }
4971
4972 // If the operation is a widening instruction (smull or umull) and both
4973 // operands are extends the cost can be cheaper by considering that the
4974 // operation will operate on the narrowest type size possible (double the
4975 // largest input size) and a further extend.
4976 if (Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {
4977 if (ExtTy != Ty)
4978 return getArithmeticInstrCost(Opcode, ExtTy, CostKind) +
4979 getCastInstrCost(Instruction::ZExt, Ty, ExtTy,
4981 return LT.first;
4982 }
4983
4984 switch (ISD) {
4985 default:
4986 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
4987 Op2Info);
4988 case ISD::ADD:
4989 case ISD::SUB:
4990 return LT.first; // Also works for i128
4991 case ISD::MUL: {
4992 // i128 multiply is umulh + 2*madd + mul and grows ~O(Bitwidth^2). For
4993 // scalable vectors the cost of LT.first will be invalid, leading to an
4994 // invalid cost overall.
4995 unsigned Mul64CostFactor = (CostKind == TTI::TCK_RecipThroughput &&
4996 ST->hasLimited64bitVectorMulBandwidth())
4997 ? 4
4998 : 1;
4999 if (Ty->getScalarSizeInBits() > 64) {
5000 unsigned NumLanes = isa<FixedVectorType>(Ty)
5001 ? cast<FixedVectorType>(Ty)->getNumElements()
5002 : 1;
5003 InstructionCost CostPerLane = LT.first / NumLanes;
5004 return CostPerLane * CostPerLane * NumLanes * Mul64CostFactor;
5005 }
5006
5007 if (LT.second == MVT::v2i64) {
5008 // When SVE is available, then we can lower the v2i64 operation using
5009 // the SVE mul instruction, which has a lower cost.
5010 if (ST->hasSVE())
5011 return LT.first * Mul64CostFactor;
5012
5013 // When SVE is not available, there is no MUL.2d instruction,
5014 // which means mul <2 x i64> is expensive as elements are extracted
5015 // from the vectors and the muls scalarized.
5016 // As getScalarizationOverhead is a bit too pessimistic, we
5017 // estimate the cost for a i64 vector directly here, which is:
5018 // - four 2-cost i64 extracts,
5019 // - two 2-cost i64 inserts, and
5020 // - two 1-cost muls.
5021 // So, for a v2i64 with LT.First = 1 the cost is 14, and for a v4i64 with
5022 // LT.first = 2 the cost is 28.
5023 return cast<VectorType>(Ty)->getElementCount().getKnownMinValue() *
5024 (getArithmeticInstrCost(Opcode, Ty->getScalarType(), CostKind) +
5025 getVectorInstrCost(Instruction::ExtractElement, Ty, CostKind, -1,
5026 nullptr, nullptr) *
5027 2 +
5028 getVectorInstrCost(Instruction::InsertElement, Ty, CostKind, -1,
5029 nullptr, nullptr));
5030 }
5031
5032 if (LT.second == MVT::nxv2i64)
5033 return LT.first * Mul64CostFactor;
5034
5035 return LT.first;
5036 }
5037 case ISD::SREM:
5038 case ISD::SDIV:
5039 /*
5040 Notes for sdiv/srem specific costs:
5041 1. This only considers the cases where the divisor is constant, uniform and
5042 (pow-of-2/non-pow-of-2). Other cases are not important since they either
5043 result in some form of (ldr + adrp), corresponding to constant vectors, or
5044 scalarization of the division operation.
5045 2. Constant divisors, either negative in whole or partially, don't result in
5046 significantly different codegen as compared to positive constant divisors.
5047 So, we don't consider negative divisors separately.
5048 3. If the codegen is significantly different with SVE, it has been indicated
5049 using comments at appropriate places.
5050
5051 sdiv specific cases:
5052 -----------------------------------------------------------------------
5053 codegen | pow-of-2 | Type
5054 -----------------------------------------------------------------------
5055 add + cmp + csel + asr | Y | i64
5056 add + cmp + csel + asr | Y | i32
5057 -----------------------------------------------------------------------
5058
5059 srem specific cases:
5060 -----------------------------------------------------------------------
5061 codegen | pow-of-2 | Type
5062 -----------------------------------------------------------------------
5063 negs + and + and + csneg | Y | i64
5064 negs + and + and + csneg | Y | i32
5065 -----------------------------------------------------------------------
5066
5067 other sdiv/srem cases:
5068 -------------------------------------------------------------------------
5069 common codegen | + srem | + sdiv | pow-of-2 | Type
5070 -------------------------------------------------------------------------
5071 smulh + asr + add + add | - | - | N | i64
5072 smull + lsr + add + add | - | - | N | i32
5073 usra | and + sub | sshr | Y | <2 x i64>
5074 2 * (scalar code) | - | - | N | <2 x i64>
5075 usra | bic + sub | sshr + neg | Y | <4 x i32>
5076 smull2 + smull + uzp2 | mls | - | N | <4 x i32>
5077 + sshr + usra | | | |
5078 -------------------------------------------------------------------------
5079 */
5080 if (Op2Info.isConstant() && Op2Info.isUniform()) {
5081 InstructionCost AddCost =
5082 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5083 Op1Info.getNoProps(), Op2Info.getNoProps());
5084 InstructionCost AsrCost =
5085 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5086 Op1Info.getNoProps(), Op2Info.getNoProps());
5087 InstructionCost MulCost =
5088 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5089 Op1Info.getNoProps(), Op2Info.getNoProps());
5090 // add/cmp/csel/csneg should have similar cost while asr/negs/and should
5091 // have similar cost.
5092 auto VT = TLI->getValueType(DL, Ty);
5093 if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {
5094 if (Op2Info.isPowerOf2() || Op2Info.isNegatedPowerOf2()) {
5095 // Neg can be folded into the asr instruction.
5096 return ISD == ISD::SDIV ? (3 * AddCost + AsrCost)
5097 : (3 * AsrCost + AddCost);
5098 } else {
5099 return MulCost + AsrCost + 2 * AddCost;
5100 }
5101 } else if (VT.isVector()) {
5102 InstructionCost UsraCost = 2 * AsrCost;
5103 if (Op2Info.isPowerOf2() || Op2Info.isNegatedPowerOf2()) {
5104 // Division with scalable types corresponds to native 'asrd'
5105 // instruction when SVE is available.
5106 // e.g. %1 = sdiv <vscale x 4 x i32> %a, splat (i32 8)
5107
5108 // One more for the negation in SDIV
5110 (Op2Info.isNegatedPowerOf2() && ISD == ISD::SDIV) ? AsrCost : 0;
5111 if (Ty->isScalableTy() && ST->hasSVE())
5112 Cost += 2 * AsrCost;
5113 else {
5114 Cost +=
5115 UsraCost +
5116 (ISD == ISD::SDIV
5117 ? (LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost
5118 : 2 * AddCost);
5119 }
5120 return Cost;
5121 } else if (LT.second == MVT::v2i64) {
5122 return VT.getVectorNumElements() *
5123 getArithmeticInstrCost(Opcode, Ty->getScalarType(), CostKind,
5124 Op1Info.getNoProps(),
5125 Op2Info.getNoProps());
5126 } else {
5127 // When SVE is available, we get:
5128 // smulh + lsr + add/sub + asr + add/sub.
5129 if (Ty->isScalableTy() && ST->hasSVE())
5130 return MulCost /*smulh cost*/ + 2 * AddCost + 2 * AsrCost;
5131 return 2 * MulCost + AddCost /*uzp2 cost*/ + AsrCost + UsraCost;
5132 }
5133 }
5134 }
5135 if (Op2Info.isConstant() && !Op2Info.isUniform() &&
5136 LT.second.isFixedLengthVector()) {
5137 // FIXME: When the constant vector is non-uniform, this may result in
5138 // loading the vector from constant pool or in some cases, may also result
5139 // in scalarization. For now, we are approximating this with the
5140 // scalarization cost.
5141 auto ExtractCost = 2 * getVectorInstrCost(Instruction::ExtractElement, Ty,
5142 CostKind, -1, nullptr, nullptr);
5143 auto InsertCost = getVectorInstrCost(Instruction::InsertElement, Ty,
5144 CostKind, -1, nullptr, nullptr);
5145 unsigned NElts = cast<FixedVectorType>(Ty)->getNumElements();
5146 return ExtractCost + InsertCost +
5147 NElts * getArithmeticInstrCost(Opcode, Ty->getScalarType(),
5148 CostKind, Op1Info.getNoProps(),
5149 Op2Info.getNoProps());
5150 }
5151 [[fallthrough]];
5152 case ISD::UDIV:
5153 case ISD::UREM: {
5154 auto VT = TLI->getValueType(DL, Ty);
5155 if (Op2Info.isConstant()) {
5156 // If the operand is a power of 2 we can use the shift or and cost.
5157 if (ISD == ISD::UDIV && Op2Info.isPowerOf2())
5158 return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
5159 Op1Info.getNoProps(),
5160 Op2Info.getNoProps());
5161 if (ISD == ISD::UREM && Op2Info.isPowerOf2())
5162 return getArithmeticInstrCost(Instruction::And, Ty, CostKind,
5163 Op1Info.getNoProps(),
5164 Op2Info.getNoProps());
5165
5166 if (ISD == ISD::UDIV || ISD == ISD::UREM) {
5167 // Divides by a constant are expanded to MULHU + SUB + SRL + ADD + SRL.
5168 // The MULHU will be expanded to UMULL for the types not listed below,
5169 // and will become a pair of UMULL+MULL2 for 128bit vectors.
5170 bool HasMULH = VT == MVT::i64 || LT.second == MVT::nxv2i64 ||
5171 LT.second == MVT::nxv4i32 || LT.second == MVT::nxv8i16 ||
5172 LT.second == MVT::nxv16i8;
5173 bool Is128bit = LT.second.is128BitVector();
5174
5175 InstructionCost MulCost =
5176 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5177 Op1Info.getNoProps(), Op2Info.getNoProps());
5178 InstructionCost AddCost =
5179 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5180 Op1Info.getNoProps(), Op2Info.getNoProps());
5181 InstructionCost ShrCost =
5182 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5183 Op1Info.getNoProps(), Op2Info.getNoProps());
5184 InstructionCost DivCost = MulCost * (Is128bit ? 2 : 1) + // UMULL/UMULH
5185 (HasMULH ? 0 : ShrCost) + // UMULL shift
5186 AddCost * 2 + ShrCost;
5187 return DivCost + (ISD == ISD::UREM ? MulCost + AddCost : 0);
5188 }
5189 }
5190
5191 // div i128's are lowered as libcalls. Pass nullptr as (u)divti3 calls are
5192 // emitted by the backend even when those functions are not declared in the
5193 // module.
5194 if (!VT.isVector() && VT.getSizeInBits() > 64)
5195 return getCallInstrCost(/*Function*/ nullptr, Ty, {Ty, Ty}, CostKind);
5196
5198 Opcode, Ty, CostKind, Op1Info, Op2Info);
5199 if (Ty->isVectorTy() && (ISD == ISD::SDIV || ISD == ISD::UDIV)) {
5200 if (TLI->isOperationLegalOrCustom(ISD, LT.second) && ST->hasSVE()) {
5201 // SDIV/UDIV operations are lowered using SVE, then we can have less
5202 // costs.
5203 if (VT.isSimple() && isa<FixedVectorType>(Ty) &&
5204 Ty->getPrimitiveSizeInBits().getFixedValue() < 128) {
5205 static const CostTblEntry DivTbl[]{
5206 {ISD::SDIV, MVT::v2i8, 5}, {ISD::SDIV, MVT::v4i8, 8},
5207 {ISD::SDIV, MVT::v8i8, 8}, {ISD::SDIV, MVT::v2i16, 5},
5208 {ISD::SDIV, MVT::v4i16, 5}, {ISD::SDIV, MVT::v2i32, 1},
5209 {ISD::UDIV, MVT::v2i8, 5}, {ISD::UDIV, MVT::v4i8, 8},
5210 {ISD::UDIV, MVT::v8i8, 8}, {ISD::UDIV, MVT::v2i16, 5},
5211 {ISD::UDIV, MVT::v4i16, 5}, {ISD::UDIV, MVT::v2i32, 1}};
5212
5213 const auto *Entry = CostTableLookup(DivTbl, ISD, VT.getSimpleVT());
5214 if (nullptr != Entry)
5215 return Entry->Cost;
5216 }
5217 // A non-power-of-2 count can't divide as a single whole-register op
5218 // (an inactive lane's leftover value could be a zero divisor and
5219 // trap), so the legalizer emits one div per whole register plus one
5220 // per set bit of the remainder (e.g. <7 x i32> emits 3 divs, not 2).
5221 if (auto *FVTy = dyn_cast<FixedVectorType>(Ty);
5222 FVTy && LT.second.isFixedLengthVector()) {
5223 unsigned NumElts = FVTy->getNumElements();
5224 unsigned RegElts = LT.second.getVectorNumElements();
5225 if (RegElts > 0)
5226 Cost = (NumElts / RegElts + popcount(NumElts % RegElts)) * 2;
5227 }
5228 // For 8/16-bit elements, the cost is higher because the type
5229 // requires promotion and possibly splitting:
5230 if (LT.second.getScalarType() == MVT::i8)
5231 Cost *= 8;
5232 else if (LT.second.getScalarType() == MVT::i16)
5233 Cost *= 4;
5234 return Cost;
5235 } else {
5236 // If one of the operands is a uniform constant then the cost for each
5237 // element is Cost for insertion, extraction and division.
5238 // Insertion cost = 2, Extraction Cost = 2, Division = cost for the
5239 // operation with scalar type
5240 if ((Op1Info.isConstant() && Op1Info.isUniform()) ||
5241 (Op2Info.isConstant() && Op2Info.isUniform())) {
5242 if (auto *VTy = dyn_cast<FixedVectorType>(Ty)) {
5244 Opcode, Ty->getScalarType(), CostKind, Op1Info, Op2Info);
5245 return (4 + DivCost) * VTy->getNumElements();
5246 }
5247 }
5248 // On AArch64, without SVE, vector divisions are expanded
5249 // into scalar divisions of each pair of elements.
5250 Cost += getVectorInstrCost(Instruction::ExtractElement, Ty, CostKind,
5251 -1, nullptr, nullptr);
5252 Cost += getVectorInstrCost(Instruction::InsertElement, Ty, CostKind, -1,
5253 nullptr, nullptr);
5254 }
5255
5256 // TODO: if one of the arguments is scalar, then it's not necessary to
5257 // double the cost of handling the vector elements.
5258 Cost += Cost;
5259 }
5260 return Cost;
5261 }
5262 case ISD::XOR:
5263 case ISD::OR:
5264 case ISD::AND:
5265 // TODO: revisit these costs as it's not accurate enough for non-uniform
5266 // constant.
5267 return LT.first;
5268 case ISD::SRL:
5269 case ISD::SRA:
5270 case ISD::SHL: {
5271 // Immediate vector shifts require uniform shift amounts. Non-uniform
5272 // constants therefore use variable shifts and require materializing the
5273 // shift vector. Account for a shift and materialization per legalized
5274 // vector, together with shared setup.
5275 // This cost is for (ldr, shl) + adrp
5276 // TODO: These costs are based on CodeSize only, consider other CostKinds.
5277 if (Op2Info.isConstant() && !Op2Info.isUniform() &&
5278 LT.second.isFixedLengthVector())
5279 return 2 * LT.first + 1;
5280
5281 // Marked 'custom' for combining purposes; a uniform shift amount still
5282 // lowers to a single legal instruction.
5283 return LT.first;
5284 }
5285
5286 case ISD::FNEG:
5287 // Scalar fmul(fneg) or fneg(fmul) can be converted to fnmul
5288 if ((Ty->isFloatTy() || Ty->isDoubleTy() ||
5289 (Ty->isHalfTy() && ST->hasFullFP16())) &&
5290 CtxI &&
5291 ((CtxI->hasOneUse() &&
5292 match(*CtxI->user_begin(), m_FMul(m_Value(), m_Value()))) ||
5293 match(CtxI->getOperand(0), m_FMul(m_Value(), m_Value()))))
5294 return 0;
5295 [[fallthrough]];
5296 case ISD::FADD:
5297 case ISD::FSUB:
5298 if (!Ty->getScalarType()->isFP128Ty())
5299 return LT.first;
5300 [[fallthrough]];
5301 case ISD::FMUL:
5302 case ISD::FDIV:
5303 // These nodes are marked as 'custom' just to lower them to SVE.
5304 // We know said lowering will incur no additional cost.
5305 if (!Ty->getScalarType()->isFP128Ty())
5306 return 2 * LT.first;
5307
5308 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5309 Op2Info);
5310 case ISD::FREM:
5311 // Pass nullptr as fmod/fmodf calls are emitted by the backend even when
5312 // those functions are not declared in the module.
5313 if (!Ty->isVectorTy())
5314 return getCallInstrCost(/*Function*/ nullptr, Ty, {Ty, Ty}, CostKind);
5315 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5316 Op2Info);
5317 }
5318}
5319
5322 const SCEV *Ptr,
5324 // Address computations in vectorized code with non-consecutive addresses will
5325 // likely result in more instructions compared to scalar code where the
5326 // computation can more often be merged into the index mode. The resulting
5327 // extra micro-ops can significantly decrease throughput.
5328 unsigned NumVectorInstToHideOverhead = NeonNonConstStrideOverhead;
5329 int MaxMergeDistance = 64;
5330
5331 if (PtrTy->isVectorTy() && SE &&
5332 !BaseT::isConstantStridedAccessLessThan(SE, Ptr, MaxMergeDistance + 1))
5333 return NumVectorInstToHideOverhead;
5334
5335 // In many cases the address computation is not merged into the instruction
5336 // addressing mode.
5337 return 1;
5338}
5339
5340/// Check whether Opcode1 has less throughput according to the scheduling
5341/// model than Opcode2.
5343 unsigned Opcode1, unsigned Opcode2) const {
5344 const MCSchedModel &Sched = ST->getSchedModel();
5345 const TargetInstrInfo *TII = ST->getInstrInfo();
5346 if (!Sched.hasInstrSchedModel())
5347 return false;
5348
5349 const MCSchedClassDesc *SCD1 =
5350 Sched.getSchedClassDesc(TII->get(Opcode1).getSchedClass());
5351 const MCSchedClassDesc *SCD2 =
5352 Sched.getSchedClassDesc(TII->get(Opcode2).getSchedClass());
5353 // We cannot handle variant scheduling classes without an MI. If we need to
5354 // support them for any of the instructions we query the information of we
5355 // might need to add a way to resolve them without a MI or not use the
5356 // scheduling info.
5357 assert(!SCD1->isVariant() && !SCD2->isVariant() &&
5358 "Cannot handle variant scheduling classes without an MI");
5359 if (!SCD1->isValid() || !SCD2->isValid())
5360 return false;
5361
5362 return MCSchedModel::getReciprocalThroughput(*ST, *SCD1) >
5364}
5365
5367 unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred,
5369 TTI::OperandValueInfo Op2Info, const Instruction *I) const {
5370 // We don't lower some vector selects well that are wider than the register
5371 // width. TODO: Improve this with different cost kinds.
5372 if (isa<FixedVectorType>(ValTy) && Opcode == Instruction::Select) {
5373 // We would need this many instructions to hide the scalarization happening.
5374 const int AmortizationCost = 20;
5375
5376 // If VecPred is not set, check if we can get a predicate from the context
5377 // instruction, if its type matches the requested ValTy.
5378 if (VecPred == CmpInst::BAD_ICMP_PREDICATE && I && I->getType() == ValTy) {
5379 CmpPredicate CurrentPred;
5380 if (match(I, m_Select(m_Cmp(CurrentPred, m_Value(), m_Value()), m_Value(),
5381 m_Value())))
5382 VecPred = CurrentPred;
5383 }
5384 // Check if we have a compare/select chain that can be lowered using
5385 // a (F)CMxx & BFI pair.
5386 if (CmpInst::isIntPredicate(VecPred) || VecPred == CmpInst::FCMP_OLE ||
5387 VecPred == CmpInst::FCMP_OLT || VecPred == CmpInst::FCMP_OGT ||
5388 VecPred == CmpInst::FCMP_OGE || VecPred == CmpInst::FCMP_OEQ ||
5389 VecPred == CmpInst::FCMP_UNE) {
5390 static const auto ValidMinMaxTys = {
5391 MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
5392 MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};
5393 static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};
5394
5395 auto LT = getTypeLegalizationCost(ValTy);
5396 if (any_of(ValidMinMaxTys, equal_to(LT.second)) ||
5397 (ST->hasFullFP16() &&
5398 any_of(ValidFP16MinMaxTys, equal_to(LT.second))))
5399 return LT.first;
5400 }
5401
5402 static const TypeConversionCostTblEntry VectorSelectTbl[] = {
5403 {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},
5404 {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},
5405 {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},
5406 {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},
5407 {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},
5408 {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},
5409 {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},
5410 {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},
5411 {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},
5412 {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},
5413 {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};
5414
5415 EVT SelCondTy = TLI->getValueType(DL, CondTy);
5416 EVT SelValTy = TLI->getValueType(DL, ValTy);
5417 if (SelCondTy.isSimple() && SelValTy.isSimple()) {
5418 if (const auto *Entry = ConvertCostTableLookup(VectorSelectTbl, Opcode,
5419 SelCondTy.getSimpleVT(),
5420 SelValTy.getSimpleVT()))
5421 return Entry->Cost;
5422 }
5423 }
5424
5425 if (Opcode == Instruction::FCmp) {
5426 if (auto PromotedCost = getFP16BF16PromoteCost(
5427 ValTy, CostKind, Op1Info, Op2Info, /*IncludeTrunc=*/false,
5428 // TODO: Consider costing SVE FCMPs.
5429 /*CanUseSVE=*/false, [&](Type *PromotedTy) {
5431 getCmpSelInstrCost(Opcode, PromotedTy, CondTy, VecPred,
5432 CostKind, Op1Info, Op2Info);
5433 if (isa<VectorType>(PromotedTy))
5435 Instruction::Trunc,
5439 return Cost;
5440 }))
5441 return *PromotedCost;
5442
5443 auto LT = getTypeLegalizationCost(ValTy);
5444 // Model unknown fp compares as a libcall.
5445 if (LT.second.getScalarType() != MVT::f64 &&
5446 LT.second.getScalarType() != MVT::f32 &&
5447 LT.second.getScalarType() != MVT::f16)
5448 return LT.first * getCallInstrCost(/*Function*/ nullptr, ValTy,
5449 {ValTy, ValTy}, CostKind);
5450
5451 // Some comparison operators require expanding to multiple compares + or.
5452 unsigned Factor = 1;
5453 if (!CondTy->isVectorTy() &&
5454 (VecPred == FCmpInst::FCMP_ONE || VecPred == FCmpInst::FCMP_UEQ))
5455 Factor = 2; // fcmp with 2 selects
5456 else if (isa<FixedVectorType>(ValTy) &&
5457 (VecPred == FCmpInst::FCMP_ONE || VecPred == FCmpInst::FCMP_UEQ ||
5458 VecPred == FCmpInst::FCMP_ORD || VecPred == FCmpInst::FCMP_UNO))
5459 Factor = 3; // fcmxx+fcmyy+or
5460 else if (isa<ScalableVectorType>(ValTy) &&
5461 (VecPred == FCmpInst::FCMP_ONE || VecPred == FCmpInst::FCMP_UEQ))
5462 Factor = 3; // fcmxx+fcmyy+or
5463
5464 if (isa<ScalableVectorType>(ValTy) &&
5466 hasKnownLowerThroughputFromSchedulingModel(AArch64::FCMEQ_PPzZZ_S,
5467 AArch64::FCMEQv4f32))
5468 Factor *= 2;
5469
5470 return Factor * (CostKind == TTI::TCK_Latency ? 2 : LT.first);
5471 }
5472
5473 // Treat the icmp in icmp(and, 0) or icmp(and, -1/1) when it can be folded to
5474 // icmp(and, 0) as free, as we can make use of ands, but only if the
5475 // comparison is not unsigned. FIXME: Enable for non-throughput cost kinds
5476 // providing it will not cause performance regressions.
5477 if (CostKind == TTI::TCK_RecipThroughput && ValTy->isIntegerTy() &&
5478 Opcode == Instruction::ICmp && I && !CmpInst::isUnsigned(VecPred) &&
5479 TLI->isTypeLegal(TLI->getValueType(DL, ValTy)) &&
5480 match(I->getOperand(0), m_And(m_Value(), m_Value()))) {
5481 if (match(I->getOperand(1), m_Zero()))
5482 return 0;
5483
5484 // x >= 1 / x < 1 -> x > 0 / x <= 0
5485 if (match(I->getOperand(1), m_One()) &&
5486 (VecPred == CmpInst::ICMP_SLT || VecPred == CmpInst::ICMP_SGE))
5487 return 0;
5488
5489 // x <= -1 / x > -1 -> x > 0 / x <= 0
5490 if (match(I->getOperand(1), m_AllOnes()) &&
5491 (VecPred == CmpInst::ICMP_SLE || VecPred == CmpInst::ICMP_SGT))
5492 return 0;
5493 }
5494
5495 // The base case handles scalable vectors fine for now, since it treats the
5496 // cost as 1 * legalization cost.
5497 return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, VecPred, CostKind,
5498 Op1Info, Op2Info, I);
5499}
5500
5502AArch64TTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
5504 if (ST->requiresStrictAlign()) {
5505 // TODO: Add cost modeling for strict align. Misaligned loads expand to
5506 // a bunch of instructions when strict align is enabled.
5507 return Options;
5508 }
5509 Options.AllowOverlappingLoads = true;
5510 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
5511 Options.NumLoadsPerBlock = IsZeroCmp ? Options.MaxNumLoads : 1;
5512 // TODO: Though vector loads usually perform well on AArch64, in some targets
5513 // they may wake up the FP unit, which raises the power consumption. Perhaps
5514 // they could be used with no holds barred (-O3).
5515 Options.LoadSizes = {8, 4, 2, 1};
5516 Options.AllowedTailExpansions = {3, 5, 6};
5517 return Options;
5518}
5519
5521 return ST->hasSVE();
5522}
5523
5527 switch (MICA.getID()) {
5528 case Intrinsic::masked_scatter:
5529 case Intrinsic::masked_gather:
5530 return getGatherScatterOpCost(MICA, CostKind);
5531 case Intrinsic::masked_load:
5532 case Intrinsic::masked_store:
5533 case Intrinsic::masked_expandload:
5534 case Intrinsic::masked_compressstore:
5535 return getMaskedMemoryOpCost(MICA, CostKind);
5536 }
5538}
5539
5543 Type *Src = MICA.getDataType();
5544
5545 if (useNeonVector(Src))
5547 auto LT = getTypeLegalizationCost(Src);
5548 if (!LT.first.isValid())
5550
5551 // Return an invalid cost for element types that we are unable to lower.
5552 auto *VT = cast<VectorType>(Src);
5553 if (VT->getElementType()->isIntegerTy(1))
5555
5556 // <vscale x 1 x eltty> operations require mask adaptation.
5557 // Allow it for normal masked ld/st
5558 if (VT->getElementCount() == ElementCount::getScalable(1))
5559 return is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
5560 MICA.getID())
5561 ? LT.first + 1
5563
5564 InstructionCost MemOpCost = LT.first;
5565 if (MICA.getID() == Intrinsic::masked_expandload) {
5566 if (!isLegalMaskedExpandLoad(Src, MICA.getAlignment()))
5568
5569 // Operation will be split into expand of masked.load
5570 // Something like:
5571 // cntp x8, p0, p0.s
5572 // whilelo p1.s, xzr, x8
5573 // ld1w { z1.s }, p1/z, [x0]
5574 // expand z1.s, p0, z1.s
5575 MemOpCost *= 4;
5576 }
5577
5578 if (MICA.getID() == Intrinsic::masked_compressstore) {
5579 if (!isLegalMaskedCompressStore(Src, MICA.getAlignment()))
5581
5582 // A compress store lowers to something like:
5583 // compact z0.s, p0, z0.s
5584 // cntp x8, p1, p0.s
5585 // whilelo p0.s, xzr, x8
5586 // st1w { z0.s }, p0, [x0]
5587 MemOpCost *= 4;
5588 }
5589
5590 // If we need to split the memory operation, we will also need to split the
5591 // mask. This will likely lead to overestimating the cost in some cases if
5592 // multiple memory operations use the same mask, but we often don't have
5593 // enough context to figure that out here.
5594 //
5595 // If the elements being loaded are bytes then the mask will already be split,
5596 // since the number of bits in a P register matches the number of bytes in a
5597 // Z register.
5598 if (LT.first > 1 && LT.second.getScalarSizeInBits() > 8)
5599 return MemOpCost * 2;
5600
5601 return MemOpCost;
5602}
5603
5604// This function returns gather/scatter overhead either from
5605// user-provided value or specialized values per-target from \p ST.
5606static unsigned getSVEGatherScatterOverhead(unsigned Opcode,
5607 const AArch64Subtarget *ST) {
5608 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5609 "Should be called on only load or stores.");
5610 switch (Opcode) {
5611 case Instruction::Load:
5612 if (SVEGatherOverhead.getNumOccurrences() > 0)
5613 return SVEGatherOverhead;
5614 return ST->getGatherOverhead();
5615 break;
5616 case Instruction::Store:
5617 if (SVEScatterOverhead.getNumOccurrences() > 0)
5618 return SVEScatterOverhead;
5619 return ST->getScatterOverhead();
5620 break;
5621 default:
5622 llvm_unreachable("Shouldn't have reached here");
5623 }
5624}
5625
5629
5630 unsigned Opcode = (MICA.getID() == Intrinsic::masked_gather ||
5631 MICA.getID() == Intrinsic::vp_gather)
5632 ? Instruction::Load
5633 : Instruction::Store;
5634
5635 Type *DataTy = MICA.getDataType();
5636 Align Alignment = MICA.getAlignment();
5637 const Instruction *I = MICA.getInst();
5638
5639 if (useNeonVector(DataTy) || !isLegalMaskedGatherScatter(DataTy))
5641 auto *VT = cast<VectorType>(DataTy);
5642 auto LT = getTypeLegalizationCost(DataTy);
5643 if (!LT.first.isValid())
5645
5646 // Return an invalid cost for element types that we are unable to lower.
5647 if (!LT.second.isVector() ||
5648 !isElementTypeLegalForScalableVector(VT->getElementType()) ||
5649 VT->getElementType()->isIntegerTy(1))
5651
5652 // The code-generator is currently not able to handle scalable vectors
5653 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
5654 // it. This change will be removed when code-generation for these types is
5655 // sufficiently reliable.
5656 if (VT->getElementCount() == ElementCount::getScalable(1))
5658
5659 ElementCount LegalVF = LT.second.getVectorElementCount();
5660 InstructionCost MemOpCost =
5661 getMemoryOpCost(Opcode, VT->getElementType(), Alignment, 0, CostKind,
5662 {TTI::OK_AnyValue, TTI::OP_None}, I);
5663 // Add on an overhead cost for using gathers/scatters.
5664 MemOpCost *= getSVEGatherScatterOverhead(Opcode, ST);
5665 return LT.first * MemOpCost * getMaxNumElements(LegalVF);
5666}
5667
5669 return isa<FixedVectorType>(Ty) && !ST->useSVEForFixedLengthVectors();
5670}
5671
5673 Align Alignment,
5674 unsigned AddressSpace,
5676 TTI::OperandValueInfo OpInfo,
5677 const Instruction *I) const {
5678 EVT VT = TLI->getValueType(DL, Ty, true);
5679 // Type legalization can't handle structs
5680 if (VT == MVT::Other)
5681 return BaseT::getMemoryOpCost(Opcode, Ty, Alignment, AddressSpace,
5682 CostKind);
5683
5684 auto LT = getTypeLegalizationCost(Ty);
5685 if (!LT.first.isValid())
5687
5688 if (auto *VTy = dyn_cast<ScalableVectorType>(Ty)) {
5689
5690 // We only support full register predicate loads and stores.
5691 if (VTy->getElementType()->isIntegerTy(1) &&
5692 !VTy->getElementCount().isKnownMultipleOf(
5695
5696 // <vscale x 1 x eltty> operations require crafting a new mask.
5697 if (VTy->getElementCount() == ElementCount::getScalable(1)) {
5698 Intrinsic::ID IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5699 : Intrinsic::masked_store;
5700 return getMaskedMemoryOpCost(
5701 MemIntrinsicCostAttributes(IID, Ty, Alignment, AddressSpace),
5702 CostKind) +
5703 1;
5704 }
5705 }
5706
5707 // TODO: consider latency as well for TCK_SizeAndLatency.
5709 return LT.first;
5710
5711 if (CostKind == TTI::TCK_Latency) {
5712 // Latency doesn't make much sense for stores, so just return 1
5713 if (Opcode == Instruction::Store)
5714 return 1;
5715 // If the subtarget has overridden the load latency then use that instead of
5716 // querying the SchedModel.
5717 if (ST->getFixedLoadLatency())
5718 return (LT.first - 1) + ST->getFixedLoadLatency();
5719 // We expect the load to become LT.first loads of type LT.second. The
5720 // latency will be the latency of the last load plus the time it gets to get
5721 // there, which will be the amount of other loads before that (i.e. total
5722 // loads - 1) multiplied by how long it takes to get through them (the
5723 // reciprocal of the throughput). We get the latency and reciprocal
5724 // throughput from the SchedModel, and assume that the loads become the
5725 // variant with unsigned integer offset.
5726 unsigned Inst = 0;
5727 if (LT.second.isScalableVector() ||
5728 ST->useSVEForFixedLengthVectors(LT.second)) {
5729 Inst = AArch64::LDR_ZXI;
5730 } else if (LT.second.isVector() || LT.second.isFloatingPoint()) {
5731 switch (LT.second.getSizeInBits()) {
5732 case 8:
5733 Inst = AArch64::LDRBui;
5734 break;
5735 case 16:
5736 Inst = AArch64::LDRHui;
5737 break;
5738 case 32:
5739 Inst = AArch64::LDRSui;
5740 break;
5741 case 64:
5742 Inst = AArch64::LDRDui;
5743 break;
5744 case 128:
5745 Inst = AArch64::LDRQui;
5746 break;
5747 default:
5748 llvm_unreachable("Unexpected float or vector type");
5749 }
5750 } else {
5751 switch (LT.second.getSizeInBits()) {
5752 case 8:
5753 Inst = AArch64::LDRBBui;
5754 break;
5755 case 16:
5756 Inst = AArch64::LDRHHui;
5757 break;
5758 case 32:
5759 Inst = AArch64::LDRWui;
5760 break;
5761 case 64:
5762 Inst = AArch64::LDRXui;
5763 break;
5764 default:
5765 llvm_unreachable("Unexpected integer type");
5766 }
5767 }
5768 const MCSchedModel &Sched = ST->getSchedModel();
5769 const TargetInstrInfo *TII = ST->getInstrInfo();
5770 unsigned SchedClass = TII->get(Inst).getSchedClass();
5771 const MCSchedClassDesc *SCD = Sched.hasInstrSchedModel()
5772 ? Sched.getSchedClassDesc(SchedClass)
5773 : nullptr;
5774 // If the cpu has no scheduling model, or it doesn't describe the load, then
5775 // fall back to the default load latency. Variant scheduling classes can't
5776 // be resolved without a MachineInstr, so treat them the same way.
5777 if (!SCD || !SCD->isValid() || SCD->isVariant())
5778 return (LT.first - 1) + ST->getLoadLatency();
5779 // We need to convert the number of loads before the last to a float here,
5780 // as the reciprocal throughput may be fractional.
5781 float NumLoads = (LT.first - 1).getValue();
5782 return NumLoads * Sched.getReciprocalThroughput(*ST, *SCD) +
5783 Sched.computeInstrLatency(*ST, *SCD);
5784 }
5785
5786 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&
5787 LT.second.is128BitVector() && Alignment < Align(16)) {
5788 // Unaligned stores are extremely inefficient. We don't split all
5789 // unaligned 128-bit stores because the negative impact that has shown in
5790 // practice on inlined block copy code.
5791 // We make such stores expensive so that we will only vectorize if there
5792 // are 6 other instructions getting vectorized.
5793 const int AmortizationCost = 6;
5794
5795 return LT.first * 2 * AmortizationCost;
5796 }
5797
5798 // Opaque ptr or ptr vector types are i64s and can be lowered to STP/LDPs.
5799 if (Ty->isPtrOrPtrVectorTy())
5800 return LT.first;
5801
5802 if (useNeonVector(Ty)) {
5803 // Check truncating stores and extending loads.
5804 if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {
5805 // v4i8 types are lowered to scalar a load/store and sshll/xtn.
5806 if (VT == MVT::v4i8)
5807 return 2;
5808 // Otherwise we need to scalarize.
5809 return cast<FixedVectorType>(Ty)->getNumElements() * 2;
5810 }
5811 EVT EltVT = VT.getVectorElementType();
5812 unsigned EltSize = EltVT.getScalarSizeInBits();
5813 if (!isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||
5814 Alignment != Align(1))
5815 return LT.first;
5816 // FIXME: v3i8 lowering currently is very inefficient, due to automatic
5817 // widening to v4i8, which produces suboptimal results.
5818 if (VT.getVectorNumElements() == 3 && EltVT == MVT::i8)
5819 return LT.first;
5820
5821 // Check non-power-of-2 loads/stores for legal vector element types with
5822 // NEON. Non-power-of-2 memory ops will get broken down to a set of
5823 // operations on smaller power-of-2 ops, including ld1/st1.
5824 InstructionCost Cost = VT.getVectorNumElements() / (128 / EltSize);
5825 unsigned Remainder = VT.getVectorNumElements() % (128 / EltSize);
5826 if (Remainder != 0) {
5828 TypeWorklist.push_back({Remainder, 0});
5829 while (!TypeWorklist.empty()) {
5830 auto [CurrNumElements, Offset] = TypeWorklist.pop_back_val();
5831 if (isPowerOf2_32(CurrNumElements)) {
5832 // 1 per load/store + possible lane insert.
5833 Cost += 1 + (Offset == 0 ? 0 : 1);
5834 continue;
5835 }
5836
5837 unsigned PrevPow2 = NextPowerOf2(CurrNumElements) / 2;
5838 TypeWorklist.push_back({PrevPow2, Offset});
5839 TypeWorklist.push_back({CurrNumElements - PrevPow2, Offset + PrevPow2});
5840 }
5841 }
5842 return Cost;
5843 }
5844
5845 return LT.first;
5846}
5847
5849 unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,
5850 Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,
5851 bool UseMaskForCond, bool UseMaskForGaps) const {
5852 assert(Factor >= 2 && "Invalid interleave factor");
5853 auto *VecVTy = cast<VectorType>(VecTy);
5854
5855 if (VecTy->isScalableTy() && !ST->hasSVE())
5857
5858 // Scalable VFs emit vector.[de]interleave intrinsics, for which the target
5859 // supports factors up to the maximum supported interleave factor.
5860 if (VecTy->isScalableTy()) {
5861 if (Factor > TLI->getMaxSupportedInterleaveFactor())
5863
5864 if (Factor == 3 &&
5865 DL.getTypeSizeInBits(VecTy).getKnownMinValue() != (3 * 128))
5867 }
5868
5869 auto LT = getTypeLegalizationCost(VecTy);
5870 unsigned MaxNativeInterleaveFactor = TLI->getMaxSupportedInterleaveFactor();
5871 // Vectorization for masked interleaved accesses is only enabled for scalable
5872 // VF. For fixed-length SVE, avoid non-native interleave factor because
5873 // the generic fallback costs wide fixed-vector shuffles too optimistically.
5874 if (!VecTy->isScalableTy() &&
5875 (UseMaskForCond || UseMaskForGaps ||
5876 (Factor > MaxNativeInterleaveFactor &&
5877 TLI->useSVEForFixedLengthVectorVT(LT.second))))
5879
5880 if (!UseMaskForGaps && Factor <= MaxNativeInterleaveFactor) {
5881 ElementCount EC = VecVTy->getElementCount();
5882 auto *SubVecTy = VectorType::get(VecVTy->getElementType(),
5883 EC.divideCoefficientBy(Factor));
5884
5885 // ldN/stN only support legal vector types of size 64 or 128 in bits.
5886 // Accesses having vector types that are a multiple of 128 bits can be
5887 // matched to more than one ldN/stN instruction.
5888 bool UseScalable;
5889 if (EC.isKnownMultipleOf(Factor) &&
5890 TLI->isLegalInterleavedAccessType(SubVecTy, DL, UseScalable))
5891 return Factor * TLI->getNumInterleavedAccesses(SubVecTy, DL, UseScalable);
5892
5893 // Cost the alternative approach for scalable vectors where the interleave
5894 // factor is larger than the VF: use a contiguous load/store of the full
5895 // wide vector followed by deinterleave/interleave shuffles.
5896 if (VecTy->isScalableTy() && EC.isKnownMultipleOf(Factor)) {
5897 if (SubVecTy->getElementCount() == ElementCount::getScalable(1))
5899
5900 // Cost of the contiguous memory operation on the wide vector.
5901 InstructionCost MemCost;
5902 if (UseMaskForCond) {
5903 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5904 : Intrinsic::masked_store;
5905 MemCost = getMemIntrinsicInstrCost(
5906 MemIntrinsicCostAttributes(IID, VecTy, Alignment, AddressSpace),
5907 CostKind);
5908 } else {
5909 MemCost =
5910 getMemoryOpCost(Opcode, VecTy, Alignment, AddressSpace, CostKind);
5911 }
5912
5913 // llvm.vector.deinterleaveN is lowered as a binary tree of deinterleave2
5914 // operations. The tree has Log2(Factor) levels, with Factor UZP/ZIP
5915 // operations at each level, giving a total shuffle cost of
5916 // Factor * Log2(Factor).
5917 auto SubVecCost = getTypeLegalizationCost(SubVecTy);
5918 auto ResultCost = getTypeLegalizationCost(VecTy);
5919 llvm::InstructionCost LegalizationCost = SubVecCost.first;
5920
5921 // FIXME: A temporary increase to the cost in cases where the input
5922 // element type is 4x the output type. Otherwise it produces an SVE tail
5923 // loop which is significantly larger than the NEON equivalent.
5924 if (Opcode == Instruction::Store && Factor == 4 &&
5925 SubVecCost.second.getScalarSizeInBits() ==
5926 (4 * ResultCost.second.getScalarSizeInBits()))
5927 LegalizationCost *= 4;
5928
5929 return MemCost + (Factor * LegalizationCost) + (Factor * Log2_64(Factor));
5930 }
5931 }
5932
5933 return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
5934 Alignment, AddressSpace, CostKind,
5935 UseMaskForCond, UseMaskForGaps);
5936}
5937
5942 for (auto *I : Tys) {
5943 if (!I->isVectorTy())
5944 continue;
5945 if (I->getScalarSizeInBits() * cast<FixedVectorType>(I)->getNumElements() ==
5946 128)
5947 Cost += getMemoryOpCost(Instruction::Store, I, Align(128), 0, CostKind) +
5948 getMemoryOpCost(Instruction::Load, I, Align(128), 0, CostKind);
5949 }
5950 return Cost;
5951}
5952
5954 Align Alignment) const {
5955 // Neon types should be scalarised when we are not choosing to use SVE.
5956 if (useNeonVector(DataTy))
5957 return false;
5958
5959 // Return true only if we are able to lower using the SVE2p2/SME2p2
5960 // expand instruction.
5961 return (ST->isSVEAvailable() && ST->hasSVE2p2()) ||
5962 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2());
5963}
5964
5966 unsigned AddressSpace) const {
5967 // Matches AArch64TargetLowering::emitCanLoadSpeculatively: only address
5968 // space 0 and power-of-2 sizes up to the 16-byte MTE tag granule.
5969 // TODO: Support scalable vectors.
5970 if (AddressSpace != 0)
5971 return false;
5972 TypeSize Size = DL.getTypeStoreSize(DataType);
5973 return !Size.isScalable() && isPowerOf2_64(Size.getFixedValue()) &&
5974 Size.getFixedValue() <= 16;
5975}
5976
5977unsigned
5979 bool HasUnorderedReductions) const {
5980 if (VF.isScalar() || (HasUnorderedReductions && VF.getKnownMinValue() <= 4))
5981 return 4;
5982 return ST->getMaxInterleaveFactor();
5983}
5984
5985// For Falkor, we want to avoid having too many strided loads in a loop since
5986// that can exhaust the HW prefetcher resources. We adjust the unroller
5987// MaxCount preference below to attempt to ensure unrolling doesn't create too
5988// many strided loads.
5989static void
5992 enum { MaxStridedLoads = 7 };
5993 auto countStridedLoads = [](Loop *L, ScalarEvolution &SE) {
5994 int StridedLoads = 0;
5995 // FIXME? We could make this more precise by looking at the CFG and
5996 // e.g. not counting loads in each side of an if-then-else diamond.
5997 for (const auto BB : L->blocks()) {
5998 for (auto &I : *BB) {
5999 LoadInst *LMemI = dyn_cast<LoadInst>(&I);
6000 if (!LMemI)
6001 continue;
6002
6003 Value *PtrValue = LMemI->getPointerOperand();
6004 if (L->isLoopInvariant(PtrValue))
6005 continue;
6006
6007 const SCEV *LSCEV = SE.getSCEV(PtrValue);
6008 const SCEVAddRecExpr *LSCEVAddRec = dyn_cast<SCEVAddRecExpr>(LSCEV);
6009 if (!LSCEVAddRec || !LSCEVAddRec->isAffine())
6010 continue;
6011
6012 // FIXME? We could take pairing of unrolled load copies into account
6013 // by looking at the AddRec, but we would probably have to limit this
6014 // to loops with no stores or other memory optimization barriers.
6015 ++StridedLoads;
6016 // We've seen enough strided loads that seeing more won't make a
6017 // difference.
6018 if (StridedLoads > MaxStridedLoads / 2)
6019 return StridedLoads;
6020 }
6021 }
6022 return StridedLoads;
6023 };
6024
6025 int StridedLoads = countStridedLoads(L, SE);
6026 LLVM_DEBUG(dbgs() << "falkor-hwpf: detected " << StridedLoads
6027 << " strided loads\n");
6028 // Pick the largest power of 2 unroll count that won't result in too many
6029 // strided loads.
6030 if (StridedLoads) {
6031 UP.MaxCount = 1 << Log2_32(MaxStridedLoads / StridedLoads);
6032 LLVM_DEBUG(dbgs() << "falkor-hwpf: setting unroll MaxCount to "
6033 << UP.MaxCount << '\n');
6034 }
6035}
6036
6037// This function returns true if the loop:
6038// 1. Has a valid cost, and
6039// 2. Has a cost within the supplied budget.
6040// Otherwise it returns false.
6042 InstructionCost Budget,
6043 unsigned *FinalSize) {
6044 // Estimate the size of the loop.
6045 InstructionCost LoopCost = 0;
6046
6047 for (auto *BB : L->getBlocks()) {
6048 for (auto &I : *BB) {
6049 SmallVector<const Value *, 4> Operands(I.operand_values());
6050 InstructionCost Cost =
6051 TTI.getInstructionCost(&I, Operands, TTI::TCK_CodeSize);
6052 // This can happen with intrinsics that don't currently have a cost model
6053 // or for some operations that require SVE.
6054 if (!Cost.isValid())
6055 return false;
6056
6057 LoopCost += Cost;
6058 if (LoopCost > Budget)
6059 return false;
6060 }
6061 }
6062
6063 if (FinalSize)
6064 *FinalSize = LoopCost.getValue();
6065 return true;
6066}
6067
6069 const AArch64TTIImpl &TTI) {
6070 // Only consider loops with unknown trip counts for which we can determine
6071 // a symbolic expression. Multi-exit loops with small known trip counts will
6072 // likely be unrolled anyway.
6073 const SCEV *BTC = SE.getSymbolicMaxBackedgeTakenCount(L);
6075 return false;
6076
6077 // It might not be worth unrolling loops with low max trip counts. Restrict
6078 // this to max trip counts > 32 for now.
6079 unsigned MaxTC = SE.getSmallConstantMaxTripCount(L);
6080 if (MaxTC > 0 && MaxTC <= 32)
6081 return false;
6082
6083 // Make sure the loop size is <= 5.
6084 if (!isLoopSizeWithinBudget(L, TTI, 5, nullptr))
6085 return false;
6086
6087 // Small search loops with multiple exits can be highly beneficial to unroll.
6088 // We only care about loops with exactly two exiting blocks, although each
6089 // block could jump to the same exit block.
6090 ArrayRef<BasicBlock *> Blocks = L->getBlocks();
6091 if (Blocks.size() != 2)
6092 return false;
6093
6094 if (any_of(Blocks, [](BasicBlock *BB) {
6096 }))
6097 return false;
6098
6099 return true;
6100}
6101
6102/// For Apple CPUs, we want to runtime-unroll loops to make better use if the
6103/// OOO engine's wide instruction window and various predictors.
6104static void
6107 const AArch64TTIImpl &TTI) {
6108 // Limit loops with structure that is highly likely to benefit from runtime
6109 // unrolling; that is we exclude outer loops and loops with many blocks (i.e.
6110 // likely with complex control flow). Note that the heuristics here may be
6111 // overly conservative and we err on the side of avoiding runtime unrolling
6112 // rather than unroll excessively. They are all subject to further refinement.
6113 if (!L->isInnermost() || L->getNumBlocks() > 8)
6114 return;
6115
6116 // Loops with multiple exits are handled by common code.
6117 if (!L->getExitBlock())
6118 return;
6119
6120 // Check if the loop contains any reductions that could be parallelized when
6121 // unrolling. If so, enable partial unrolling, if the trip count is know to be
6122 // a multiple of 2.
6123 bool HasParellelizableReductions =
6124 L->getNumBlocks() == 1 &&
6125 any_of(L->getHeader()->phis(),
6126 [&SE, L](PHINode &Phi) {
6127 return canParallelizeReductionWhenUnrolling(Phi, L, &SE);
6128 }) &&
6129 isLoopSizeWithinBudget(L, TTI, 12, nullptr);
6130 if (HasParellelizableReductions &&
6131 SE.getSmallConstantTripMultiple(L, L->getExitingBlock()) % 2 == 0) {
6132 UP.Partial = true;
6133 UP.MaxCount = 4;
6134 UP.AddAdditionalAccumulators = true;
6135 }
6136
6137 const SCEV *BTC = SE.getSymbolicMaxBackedgeTakenCount(L);
6139 (SE.getSmallConstantMaxTripCount(L) > 0 &&
6140 SE.getSmallConstantMaxTripCount(L) <= 32))
6141 return;
6142
6143 if (findStringMetadataForLoop(L, "llvm.loop.isvectorized"))
6144 return;
6145
6147 return;
6148
6149 // Limit to loops with trip counts that are cheap to expand.
6150 UP.SCEVExpansionBudget = 1;
6151
6152 if (HasParellelizableReductions) {
6153 UP.Runtime = true;
6155 UP.AddAdditionalAccumulators = true;
6156 }
6157
6158 // Try to unroll small, single-block loops with low budget, if they have
6159 // load/store dependencies, to expose more parallel memory access streams,
6160 // or if they do little work inside a block (i.e. load -> X -> store pattern).
6161 BasicBlock *Header = L->getHeader();
6162 BasicBlock *Latch = L->getLoopLatch();
6163 if (Header == Latch) {
6164 // Estimate the size of the loop.
6165 unsigned Size;
6166 unsigned Width = 10;
6167 if (!isLoopSizeWithinBudget(L, TTI, Width, &Size))
6168 return;
6169
6170 // Try to find an unroll count that maximizes the use of the instruction
6171 // window, i.e. trying to fetch as many instructions per cycle as possible.
6172 unsigned MaxInstsPerLine = 16;
6173 unsigned UC = 1;
6174 unsigned BestUC = 1;
6175 unsigned SizeWithBestUC = BestUC * Size;
6176 while (UC <= 8) {
6177 unsigned SizeWithUC = UC * Size;
6178 if (SizeWithUC > 48)
6179 break;
6180 if ((SizeWithUC % MaxInstsPerLine) == 0 ||
6181 (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {
6182 BestUC = UC;
6183 SizeWithBestUC = BestUC * Size;
6184 }
6185 UC++;
6186 }
6187
6188 if (BestUC == 1)
6189 return;
6190
6191 SmallPtrSet<Value *, 8> LoadedValuesPlus;
6193 for (auto *BB : L->blocks()) {
6194 for (auto &I : *BB) {
6196 if (!Ptr)
6197 continue;
6198 const SCEV *PtrSCEV = SE.getSCEV(Ptr);
6199 if (SE.isLoopInvariant(PtrSCEV, L))
6200 continue;
6201 if (isa<LoadInst>(&I)) {
6202 LoadedValuesPlus.insert(&I);
6203 // Include in-loop 1st users of loaded values.
6204 for (auto *U : I.users())
6205 if (L->contains(cast<Instruction>(U)))
6206 LoadedValuesPlus.insert(U);
6207 } else
6208 Stores.push_back(cast<StoreInst>(&I));
6209 }
6210 }
6211
6212 if (none_of(Stores, [&LoadedValuesPlus](StoreInst *SI) {
6213 return LoadedValuesPlus.contains(SI->getOperand(0));
6214 }))
6215 return;
6216
6217 UP.Runtime = true;
6218 UP.DefaultUnrollRuntimeCount = BestUC;
6219 return;
6220 }
6221
6222 // Try to runtime-unroll loops with early-continues depending on loop-varying
6223 // loads; this helps with branch-prediction for the early-continues.
6224 auto *Term = dyn_cast<CondBrInst>(Header->getTerminator());
6226 if (!Term || Preds.size() == 1 || !llvm::is_contained(Preds, Header) ||
6227 none_of(Preds, [L](BasicBlock *Pred) { return L->contains(Pred); }))
6228 return;
6229
6230 std::function<bool(Instruction *, unsigned)> DependsOnLoopLoad =
6231 [&](Instruction *I, unsigned Depth) -> bool {
6232 if (isa<PHINode>(I) || L->isLoopInvariant(I) || Depth > 8)
6233 return false;
6234
6235 if (isa<LoadInst>(I))
6236 return true;
6237
6238 return any_of(I->operands(), [&](Value *V) {
6239 auto *I = dyn_cast<Instruction>(V);
6240 return I && DependsOnLoopLoad(I, Depth + 1);
6241 });
6242 };
6243 CmpPredicate Pred;
6244 Instruction *I;
6245 if (match(Term, m_Br(m_ICmp(Pred, m_Instruction(I), m_Value()), m_Value(),
6246 m_Value())) &&
6247 DependsOnLoopLoad(I, 0)) {
6248 UP.Runtime = true;
6249 }
6250}
6251
6254 OptimizationRemarkEmitter *ORE) const {
6255 // Enable partial unrolling and runtime unrolling.
6256 BaseT::getUnrollingPreferences(L, SE, UP, ORE);
6257
6258 UP.UpperBound = true;
6259
6260 // A loop can have a small maximum trip count while SCEV still cannot
6261 // form an exact backedge count - typically a data-dependent exit, e.g.
6262 // shifting a value until it reaches zero. Unlike for counted loops, the
6263 // unrolled body keeps an exit test per iteration, and whether that pays
6264 // off depends on how many iterations the loop usually runs, which is
6265 // unknown at compile time; the code growth and extra branches are certain.
6266 // Be conservative and hold such loops to a lower upper bound; 5 still lets
6267 // smaller early-exit loops unroll. Also disable runtime unrolling, which
6268 // would clamp the unroll count to the known maximum trip count and produce
6269 // the same complete unroll.
6270 if (L->getExitingBlock() && !SE.isBackedgeTakenCountMaxOrZero(L) &&
6272 UP.MaxUpperBound = 5;
6273 UP.Runtime = false;
6274 }
6275
6276 // For inner loop, it is more likely to be a hot one, and the runtime check
6277 // can be promoted out from LICM pass, so the overhead is less, let's try
6278 // a larger threshold to unroll more loops.
6279 if (L->getLoopDepth() > 1)
6280 UP.PartialThreshold *= 2;
6281
6282 // Disable partial & runtime unrolling on -Os.
6284
6285 // Scan the loop: don't unroll loops with calls as this could prevent
6286 // inlining. Don't unroll auto-vectorized loops either, though do allow
6287 // unrolling of the scalar remainder.
6288 bool IsVectorized = getBooleanLoopAttribute(L, "llvm.loop.isvectorized");
6290 for (auto *BB : L->getBlocks()) {
6291 for (auto &I : *BB) {
6292 // Both auto-vectorized loops and the scalar remainder have the
6293 // isvectorized attribute, so differentiate between them by the presence
6294 // of vector instructions.
6295 if (IsVectorized && I.getType()->isVectorTy())
6296 return;
6297 if (isa<CallBase>(I)) {
6300 if (!isLoweredToCall(F))
6301 continue;
6302 return;
6303 }
6304
6305 SmallVector<const Value *, 4> Operands(I.operand_values());
6308 }
6309 }
6310
6311 // Apply subtarget-specific unrolling preferences.
6312 if (ST->isAppleMLike())
6313 getAppleRuntimeUnrollPreferences(L, SE, UP, *this);
6314 else if (ST->getProcFamily() == AArch64Subtarget::Falkor &&
6317
6318 // If this is a small, multi-exit loop similar to something like std::find,
6319 // then there is typically a performance improvement achieved by unrolling.
6320 if (!L->getExitBlock() && shouldUnrollMultiExitLoop(L, SE, *this)) {
6321 UP.RuntimeUnrollMultiExit = true;
6322 UP.Runtime = true;
6323 // Limit unroll count.
6325 // Allow slightly more costly trip-count expansion to catch search loops
6326 // with pointer inductions.
6327 UP.SCEVExpansionBudget = 5;
6328 return;
6329 }
6330
6331 // Enable runtime unrolling for in-order models
6332 // If mcpu is omitted, getProcFamily() returns AArch64Subtarget::Others, so by
6333 // checking for that case, we can ensure that the default behaviour is
6334 // unchanged
6335 if (ST->getProcFamily() != AArch64Subtarget::Generic &&
6336 !ST->getSchedModel().isOutOfOrder()) {
6337 UP.Runtime = true;
6338 UP.Partial = true;
6339 UP.UnrollRemainder = true;
6341
6342 UP.UnrollAndJam = true;
6344 }
6345
6346 // Force unrolling small loops can be very useful because of the branch
6347 // taken cost of the backedge.
6349 UP.Force = true;
6350}
6351
6356
6358 Type *ExpectedType,
6359 bool CanCreate) const {
6360 switch (Inst->getIntrinsicID()) {
6361 default:
6362 return nullptr;
6363 case Intrinsic::aarch64_neon_st1x2:
6364 case Intrinsic::aarch64_neon_st1x3:
6365 case Intrinsic::aarch64_neon_st1x4:
6366 case Intrinsic::aarch64_neon_st2:
6367 case Intrinsic::aarch64_neon_st3:
6368 case Intrinsic::aarch64_neon_st4: {
6369 // Create a struct type
6370 StructType *ST = dyn_cast<StructType>(ExpectedType);
6371 if (!CanCreate || !ST)
6372 return nullptr;
6373 unsigned NumElts = Inst->arg_size() - 1;
6374 if (ST->getNumElements() != NumElts)
6375 return nullptr;
6376 for (unsigned i = 0, e = NumElts; i != e; ++i) {
6377 if (Inst->getArgOperand(i)->getType() != ST->getElementType(i))
6378 return nullptr;
6379 }
6380 Value *Res = PoisonValue::get(ExpectedType);
6381 IRBuilder<> Builder(Inst);
6382 for (unsigned i = 0, e = NumElts; i != e; ++i) {
6383 Value *L = Inst->getArgOperand(i);
6384 Res = Builder.CreateInsertValue(Res, L, i);
6385 }
6386 return Res;
6387 }
6388 case Intrinsic::aarch64_neon_ld1x2:
6389 case Intrinsic::aarch64_neon_ld1x3:
6390 case Intrinsic::aarch64_neon_ld1x4:
6391 case Intrinsic::aarch64_neon_ld2:
6392 case Intrinsic::aarch64_neon_ld3:
6393 case Intrinsic::aarch64_neon_ld4:
6394 if (Inst->getType() == ExpectedType)
6395 return Inst;
6396 return nullptr;
6397 }
6398}
6399
6401 MemIntrinsicInfo &Info) const {
6402 switch (Inst->getIntrinsicID()) {
6403 default:
6404 break;
6405 case Intrinsic::aarch64_neon_ld1x2:
6406 case Intrinsic::aarch64_neon_ld1x3:
6407 case Intrinsic::aarch64_neon_ld1x4:
6408 case Intrinsic::aarch64_neon_ld2:
6409 case Intrinsic::aarch64_neon_ld3:
6410 case Intrinsic::aarch64_neon_ld4:
6411 Info.ReadMem = true;
6412 Info.WriteMem = false;
6413 Info.PtrVal = Inst->getArgOperand(0);
6414 break;
6415 case Intrinsic::aarch64_neon_st1x2:
6416 case Intrinsic::aarch64_neon_st1x3:
6417 case Intrinsic::aarch64_neon_st1x4:
6418 case Intrinsic::aarch64_neon_st2:
6419 case Intrinsic::aarch64_neon_st3:
6420 case Intrinsic::aarch64_neon_st4:
6421 Info.ReadMem = false;
6422 Info.WriteMem = true;
6423 Info.PtrVal = Inst->getArgOperand(Inst->arg_size() - 1);
6424 break;
6425 }
6426
6427 // Use the ID of neon load as the "matching id".
6428 switch (Inst->getIntrinsicID()) {
6429 default:
6430 return false;
6431 case Intrinsic::aarch64_neon_ld1x2:
6432 case Intrinsic::aarch64_neon_st1x2:
6433 Info.MatchingId = Intrinsic::aarch64_neon_ld1x2;
6434 break;
6435 case Intrinsic::aarch64_neon_ld1x3:
6436 case Intrinsic::aarch64_neon_st1x3:
6437 Info.MatchingId = Intrinsic::aarch64_neon_ld1x3;
6438 break;
6439 case Intrinsic::aarch64_neon_ld1x4:
6440 case Intrinsic::aarch64_neon_st1x4:
6441 Info.MatchingId = Intrinsic::aarch64_neon_ld1x4;
6442 break;
6443 case Intrinsic::aarch64_neon_ld2:
6444 case Intrinsic::aarch64_neon_st2:
6445 Info.MatchingId = Intrinsic::aarch64_neon_ld2;
6446 break;
6447 case Intrinsic::aarch64_neon_ld3:
6448 case Intrinsic::aarch64_neon_st3:
6449 Info.MatchingId = Intrinsic::aarch64_neon_ld3;
6450 break;
6451 case Intrinsic::aarch64_neon_ld4:
6452 case Intrinsic::aarch64_neon_st4:
6453 Info.MatchingId = Intrinsic::aarch64_neon_ld4;
6454 break;
6455 }
6456 return true;
6457}
6458
6459/// See if \p I should be considered for address type promotion. We check if \p
6460/// I is a sext with right type and used in memory accesses. If it used in a
6461/// "complex" getelementptr, we allow it to be promoted without finding other
6462/// sext instructions that sign extended the same initial value. A getelementptr
6463/// is considered as "complex" if it has more than 2 operands.
6465 const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const {
6466 bool Considerable = false;
6467 AllowPromotionWithoutCommonHeader = false;
6468 if (!isa<SExtInst>(&I))
6469 return false;
6470 Type *ConsideredSExtType =
6471 Type::getInt64Ty(I.getParent()->getParent()->getContext());
6472 if (I.getType() != ConsideredSExtType)
6473 return false;
6474 // See if the sext is the one with the right type and used in at least one
6475 // GetElementPtrInst.
6476 for (const User *U : I.users()) {
6477 if (const GetElementPtrInst *GEPInst = dyn_cast<GetElementPtrInst>(U)) {
6478 Considerable = true;
6479 // A getelementptr is considered as "complex" if it has more than 2
6480 // operands. We will promote a SExt used in such complex GEP as we
6481 // expect some computation to be merged if they are done on 64 bits.
6482 if (GEPInst->getNumOperands() > 2) {
6483 AllowPromotionWithoutCommonHeader = true;
6484 break;
6485 }
6486 }
6487 }
6488 return Considerable;
6489}
6490
6492 const RecurrenceDescriptor &RdxDesc, ElementCount VF) const {
6493 if (!VF.isScalable())
6494 return true;
6495
6496 Type *Ty = RdxDesc.getRecurrenceType();
6497 if (Ty->isBFloatTy() || !isElementTypeLegalForScalableVector(Ty))
6498 return false;
6499
6500 switch (RdxDesc.getRecurrenceKind()) {
6501 case RecurKind::Sub:
6502 case RecurKind::FSub:
6505 case RecurKind::Add:
6506 case RecurKind::FAdd:
6507 case RecurKind::And:
6508 case RecurKind::Or:
6509 case RecurKind::Xor:
6510 case RecurKind::SMin:
6511 case RecurKind::SMax:
6512 case RecurKind::UMin:
6513 case RecurKind::UMax:
6514 case RecurKind::FMin:
6515 case RecurKind::FMax:
6516 case RecurKind::FMulAdd:
6517 case RecurKind::AnyOf:
6519 return true;
6520 default:
6521 return false;
6522 }
6523}
6524
6527 FastMathFlags FMF,
6529 // The code-generator is currently not able to handle scalable vectors
6530 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
6531 // it. This change will be removed when code-generation for these types is
6532 // sufficiently reliable.
6533 if (auto *VTy = dyn_cast<ScalableVectorType>(Ty))
6534 if (VTy->getElementCount() == ElementCount::getScalable(1))
6536
6537 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
6538
6539 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
6540 return BaseT::getMinMaxReductionCost(IID, Ty, FMF, CostKind);
6541
6542 InstructionCost LegalizationCost = 0;
6543 if (LT.first > 1) {
6544 Type *LegalVTy = EVT(LT.second).getTypeForEVT(Ty->getContext());
6545 IntrinsicCostAttributes Attrs(IID, LegalVTy, {LegalVTy, LegalVTy}, FMF);
6546 LegalizationCost = getIntrinsicInstrCost(Attrs, CostKind) * (LT.first - 1);
6547 }
6548
6549 return LegalizationCost + /*Cost of horizontal reduction*/ 2;
6550}
6551
6553 unsigned Opcode, VectorType *ValTy, TTI::TargetCostKind CostKind) const {
6554 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
6555 InstructionCost LegalizationCost = 0;
6556 if (LT.first > 1) {
6557 Type *LegalVTy = EVT(LT.second).getTypeForEVT(ValTy->getContext());
6558 LegalizationCost = getArithmeticInstrCost(Opcode, LegalVTy, CostKind);
6559 LegalizationCost *= LT.first - 1;
6560 }
6561
6562 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6563 assert(ISD && "Invalid opcode");
6564 // Add the final reduction cost for the legal horizontal reduction
6565 switch (ISD) {
6566 case ISD::ADD:
6567 case ISD::AND:
6568 case ISD::OR:
6569 case ISD::XOR:
6570 case ISD::FADD:
6571 return LegalizationCost + 2;
6572 default:
6574 }
6575}
6576
6579 std::optional<FastMathFlags> FMF,
6581 // The code-generator is currently not able to handle scalable vectors
6582 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
6583 // it. This change will be removed when code-generation for these types is
6584 // sufficiently reliable.
6585 if (auto *VTy = dyn_cast<ScalableVectorType>(ValTy))
6586 if (VTy->getElementCount() == ElementCount::getScalable(1))
6588
6590 if (auto *FixedVTy = dyn_cast<FixedVectorType>(ValTy)) {
6591 InstructionCost BaseCost =
6592 BaseT::getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind);
6593 // Add on extra cost to reflect the extra overhead on some CPUs. We still
6594 // end up vectorizing for more computationally intensive loops.
6595 return BaseCost + FixedVTy->getNumElements();
6596 }
6597
6598 if (Opcode != Instruction::FAdd || ValTy->getElementType()->isBFloatTy())
6600
6601 auto *VTy = cast<ScalableVectorType>(ValTy);
6603 getArithmeticInstrCost(Opcode, VTy->getScalarType(), CostKind);
6604 Cost *= getMaxNumElements(VTy->getElementCount());
6605 return Cost;
6606 }
6607
6608 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
6609 MVT MTy = LT.second;
6610
6611 if (isa<ScalableVectorType>(ValTy) || TLI->useSVEForFixedLengthVectorVT(MTy))
6612 return getArithmeticReductionCostSVE(Opcode, ValTy, CostKind);
6613
6614 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6615 assert(ISD && "Invalid opcode");
6616
6617 // Horizontal adds can use the 'addv' instruction. We model the cost of these
6618 // instructions as twice a normal vector add, plus 1 for each legalization
6619 // step (LT.first). This is the only arithmetic vector reduction operation for
6620 // which we have an instruction.
6621 // OR, XOR and AND costs should match the codegen from:
6622 // OR: llvm/test/CodeGen/AArch64/reduce-or.ll
6623 // XOR: llvm/test/CodeGen/AArch64/reduce-xor.ll
6624 // AND: llvm/test/CodeGen/AArch64/reduce-and.ll
6625 static const CostTblEntry CostTblNoPairwise[]{
6626 {ISD::ADD, MVT::v8i8, 2},
6627 {ISD::ADD, MVT::v16i8, 2},
6628 {ISD::ADD, MVT::v4i16, 2},
6629 {ISD::ADD, MVT::v8i16, 2},
6630 {ISD::ADD, MVT::v2i32, 2},
6631 {ISD::ADD, MVT::v4i32, 2},
6632 {ISD::ADD, MVT::v2i64, 2},
6633 {ISD::OR, MVT::v8i8, 5}, // fmov + orr_lsr + orr_lsr + lsr + orr
6634 {ISD::OR, MVT::v16i8, 7}, // ext + orr + same as v8i8
6635 {ISD::OR, MVT::v4i16, 4}, // fmov + orr_lsr + lsr + orr
6636 {ISD::OR, MVT::v8i16, 6}, // ext + orr + same as v4i16
6637 {ISD::OR, MVT::v2i32, 3}, // fmov + lsr + orr
6638 {ISD::OR, MVT::v4i32, 5}, // ext + orr + same as v2i32
6639 {ISD::OR, MVT::v2i64, 3}, // ext + orr + fmov
6640 {ISD::XOR, MVT::v8i8, 5}, // Same as above for or...
6641 {ISD::XOR, MVT::v16i8, 7},
6642 {ISD::XOR, MVT::v4i16, 4},
6643 {ISD::XOR, MVT::v8i16, 6},
6644 {ISD::XOR, MVT::v2i32, 3},
6645 {ISD::XOR, MVT::v4i32, 5},
6646 {ISD::XOR, MVT::v2i64, 3},
6647 {ISD::AND, MVT::v8i8, 5}, // Same as above for or...
6648 {ISD::AND, MVT::v16i8, 7},
6649 {ISD::AND, MVT::v4i16, 4},
6650 {ISD::AND, MVT::v8i16, 6},
6651 {ISD::AND, MVT::v2i32, 3},
6652 {ISD::AND, MVT::v4i32, 5},
6653 {ISD::AND, MVT::v2i64, 3},
6654 };
6655 switch (ISD) {
6656 default:
6657 break;
6658 case ISD::FADD:
6659 if (Type *EltTy = ValTy->getScalarType();
6660 // FIXME: For half types without fullfp16 support, this could extend and
6661 // use a fp32 faddp reduction but current codegen unrolls.
6662 MTy.isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
6663 (EltTy->isHalfTy() && ST->hasFullFP16()))) {
6664 const unsigned NElts = MTy.getVectorNumElements();
6665 if (ValTy->getElementCount().getFixedValue() >= 2 && NElts >= 2 &&
6666 isPowerOf2_32(NElts))
6667 // Reduction corresponding to series of fadd instructions is lowered to
6668 // series of faddp instructions. faddp has latency/throughput that
6669 // matches fadd instruction and hence, every faddp instruction can be
6670 // considered to have a relative cost = 1 with
6671 // CostKind = TCK_RecipThroughput.
6672 // An faddp will pairwise add vector elements, so the size of input
6673 // vector reduces by half every time, requiring
6674 // #(faddp instructions) = log2_32(NElts).
6675 return (LT.first - 1) + /*No of faddp instructions*/ Log2_32(NElts);
6676 }
6677 break;
6678 case ISD::ADD:
6679 if (const auto *Entry = CostTableLookup(CostTblNoPairwise, ISD, MTy))
6680 return (LT.first - 1) + Entry->Cost;
6681 break;
6682 case ISD::XOR:
6683 case ISD::AND:
6684 case ISD::OR:
6685 const auto *Entry = CostTableLookup(CostTblNoPairwise, ISD, MTy);
6686 if (!Entry)
6687 break;
6688 auto *ValVTy = cast<FixedVectorType>(ValTy);
6689 if (MTy.getVectorNumElements() <= ValVTy->getNumElements() &&
6690 isPowerOf2_32(ValVTy->getNumElements())) {
6691 InstructionCost ExtraCost = 0;
6692 if (LT.first != 1) {
6693 // Type needs to be split, so there is an extra cost of LT.first - 1
6694 // arithmetic ops.
6695 auto *Ty = FixedVectorType::get(ValTy->getElementType(),
6696 MTy.getVectorNumElements());
6697 ExtraCost = getArithmeticInstrCost(Opcode, Ty, CostKind);
6698 ExtraCost *= LT.first - 1;
6699 }
6700 // All and/or/xor of i1 will be lowered with maxv/minv/addv + fmov
6701 auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;
6702 return Cost + ExtraCost;
6703 }
6704 break;
6705 }
6706 return BaseT::getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind);
6707}
6708
6710 unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *VecTy,
6711 std::optional<FastMathFlags> FMF, TTI::TargetCostKind CostKind) const {
6712 EVT VecVT = TLI->getValueType(DL, VecTy);
6713 EVT ResVT = TLI->getValueType(DL, ResTy);
6714
6715 if (Opcode == Instruction::Add && VecVT.isSimple() && ResVT.isSimple() &&
6716 VecVT.getSizeInBits() >= 64) {
6717 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(VecTy);
6718
6719 // The legal cases are:
6720 // UADDLV 8/16/32->32
6721 // UADDLP 32->64
6722 unsigned RevVTSize = ResVT.getSizeInBits();
6723 if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
6724 RevVTSize <= 32) ||
6725 ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&
6726 RevVTSize <= 32) ||
6727 ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&
6728 RevVTSize <= 64))
6729 return (LT.first - 1) * 2 + 2;
6730 }
6731
6732 return BaseT::getExtendedReductionCost(Opcode, IsUnsigned, ResTy, VecTy, FMF,
6733 CostKind);
6734}
6735
6737AArch64TTIImpl::getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode,
6738 Type *ResTy, VectorType *VecTy,
6740 EVT VecVT = TLI->getValueType(DL, VecTy);
6741 EVT ResVT = TLI->getValueType(DL, ResTy);
6742
6743 if (ST->hasDotProd() && VecVT.isSimple() && ResVT.isSimple() &&
6744 RedOpcode == Instruction::Add) {
6745 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(VecTy);
6746
6747 // The legal cases with dotprod are
6748 // UDOT 8->32
6749 // Which requires an additional uaddv to sum the i32 values.
6750 if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
6751 ResVT == MVT::i32)
6752 return LT.first + 2;
6753 }
6754
6755 return BaseT::getMulAccReductionCost(IsUnsigned, RedOpcode, ResTy, VecTy,
6756 CostKind);
6757}
6758
6762 static const CostTblEntry ShuffleTbl[] = {
6763 { TTI::SK_Splice, MVT::nxv16i8, 1 },
6764 { TTI::SK_Splice, MVT::nxv8i16, 1 },
6765 { TTI::SK_Splice, MVT::nxv4i32, 1 },
6766 { TTI::SK_Splice, MVT::nxv2i64, 1 },
6767 { TTI::SK_Splice, MVT::nxv2f16, 1 },
6768 { TTI::SK_Splice, MVT::nxv4f16, 1 },
6769 { TTI::SK_Splice, MVT::nxv8f16, 1 },
6770 { TTI::SK_Splice, MVT::nxv2bf16, 1 },
6771 { TTI::SK_Splice, MVT::nxv4bf16, 1 },
6772 { TTI::SK_Splice, MVT::nxv8bf16, 1 },
6773 { TTI::SK_Splice, MVT::nxv2f32, 1 },
6774 { TTI::SK_Splice, MVT::nxv4f32, 1 },
6775 { TTI::SK_Splice, MVT::nxv2f64, 1 },
6776 };
6777
6778 // The code-generator is currently not able to handle scalable vectors
6779 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
6780 // it. This change will be removed when code-generation for these types is
6781 // sufficiently reliable.
6784
6785 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Tp);
6786 Type *LegalVTy = EVT(LT.second).getTypeForEVT(Tp->getContext());
6787 EVT PromotedVT = LT.second.getScalarType() == MVT::i1
6788 ? TLI->getPromotedVTForPredicate(EVT(LT.second))
6789 : LT.second;
6790 Type *PromotedVTy = EVT(PromotedVT).getTypeForEVT(Tp->getContext());
6791 InstructionCost LegalizationCost = 0;
6792 if (Index < 0) {
6793 LegalizationCost =
6794 getCmpSelInstrCost(Instruction::ICmp, PromotedVTy, PromotedVTy,
6796 getCmpSelInstrCost(Instruction::Select, PromotedVTy, LegalVTy,
6798 }
6799
6800 // Predicated splice are promoted when lowering. See AArch64ISelLowering.cpp
6801 // Cost performed on a promoted type.
6802 if (LT.second.getScalarType() == MVT::i1) {
6803 LegalizationCost +=
6804 getCastInstrCost(Instruction::ZExt, PromotedVTy, LegalVTy,
6806 getCastInstrCost(Instruction::Trunc, LegalVTy, PromotedVTy,
6808 }
6809 const auto *Entry =
6810 CostTableLookup(ShuffleTbl, TTI::SK_Splice, PromotedVT.getSimpleVT());
6811 assert(Entry && "Illegal Type for Splice");
6812 LegalizationCost += Entry->Cost;
6813 return LegalizationCost * LT.first;
6814}
6815
6817 unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType,
6819 TTI::PartialReductionExtendKind OpBExtend, std::optional<unsigned> BinOp,
6820 TTI::TargetCostKind CostKind, std::optional<FastMathFlags> FMF) const {
6822
6824 return Invalid;
6825
6826 if ((Opcode != Instruction::Add && Opcode != Instruction::Sub &&
6827 Opcode != Instruction::FAdd && Opcode != Instruction::FSub))
6828 return Invalid;
6829
6830 // Floating-point partial reductions are invalid if `reassoc` and `contract`
6831 // are not allowed.
6832 if (AccumType->isFloatingPointTy()) {
6833 assert(FMF && "Missing FastMathFlags for floating-point partial reduction");
6834 if (!FMF->allowReassoc() || !FMF->allowContract())
6835 return Invalid;
6836 } else {
6837 assert(!FMF &&
6838 "FastMathFlags only apply to floating-point partial reductions");
6839 }
6840
6841 assert((BinOp || (OpBExtend == TTI::PR_None && !InputTypeB)) &&
6842 (!BinOp || (OpBExtend != TTI::PR_None && InputTypeB)) &&
6843 "Unexpected values for OpBExtend or InputTypeB");
6844
6845 // We only support multiply binary operations for now, and for muls we
6846 // require the types being extended to be the same.
6847 if (BinOp && ((*BinOp != Instruction::Mul && *BinOp != Instruction::FMul) ||
6848 InputTypeA != InputTypeB))
6849 return Invalid;
6850
6851 // We only support the following element sizes.
6852 if (!is_contained({8u, 16u, 32u, 64u}, AccumType->getScalarSizeInBits()))
6853 return Invalid;
6854
6855 // If none of the operands are extended and there's no extra BinOp, just
6856 // cost this as the equivalent arithmetic instruction.
6857 // TODO: Depending on VF and element type, we may be able to improve on this.
6858 if (!OpAExtend) {
6859 assert(!OpBExtend && "Extended second operand without extended first.");
6860 assert(InputTypeA == AccumType && "Type mismatch with no extensions.");
6861
6862 VectorType *VTy = VectorType::get(AccumType, VF);
6863 return getArithmeticInstrCost(Opcode, VTy, CostKind);
6864 }
6865
6866 bool IsUSDot = OpBExtend != TTI::PR_None && OpAExtend != OpBExtend;
6867 // USDot is natively supported with +i8mm. With plain +dotprod, SUMLA is
6868 // lowered to two udots plus an eor and a sub.
6869 if (IsUSDot && !ST->hasMatMulInt8() && !ST->hasDotProd())
6870 // FIXME: Remove this early bailout in favour of expand cost.
6871 return Invalid;
6872
6873 unsigned Ratio =
6874 AccumType->getScalarSizeInBits() / InputTypeA->getScalarSizeInBits();
6875 if (VF.getKnownMinValue() <= Ratio)
6876 return Invalid;
6877
6878 VectorType *InputVectorType = VectorType::get(InputTypeA, VF);
6879 VectorType *AccumVectorType =
6880 VectorType::get(AccumType, VF.divideCoefficientBy(Ratio));
6881 // We don't yet support all kinds of legalization.
6882 auto TC = TLI->getTypeConversion(AccumVectorType->getContext(),
6883 EVT::getEVT(AccumVectorType));
6884 switch (TC.first) {
6885 default:
6886 return Invalid;
6890 // The legalised type (e.g. after splitting) must be legal too.
6891 if (TLI->getTypeAction(AccumVectorType->getContext(), TC.second) !=
6893 return Invalid;
6894 break;
6895 }
6896
6897 std::pair<InstructionCost, MVT> AccumLT =
6898 getTypeLegalizationCost(AccumVectorType);
6899 std::pair<InstructionCost, MVT> InputLT =
6900 getTypeLegalizationCost(InputVectorType);
6901
6902 // Returns true if the subtarget supports the operation for a given type.
6903 auto IsSupported = [&](bool SVEPred, bool NEONPred) -> bool {
6904 return (ST->isSVEorStreamingSVEAvailable() && SVEPred) ||
6905 (AccumLT.second.isFixedLengthVector() &&
6906 AccumLT.second.getSizeInBits() <= 128 && ST->isNeonAvailable() &&
6907 NEONPred);
6908 };
6909
6910 bool IsSub = Opcode == Instruction::Sub || Opcode == Instruction::FSub;
6911 InstructionCost Cost = InputLT.first * TTI::TCC_Basic;
6912 // Integer partial sub-reductions that don't map to a specific instruction,
6913 // carry an extra cost for implementing a double negation:
6914 // partial_reduce_umls acc, lhs, rhs
6915 // <=> -partial_reduce_umla -acc, lhs, rhs
6916 InstructionCost INegCost = IsSub ? 2 * InputLT.first * TTI::TCC_Basic : 0;
6917
6918 if (AccumLT.second.getScalarType() == MVT::i32 &&
6919 InputLT.second.getScalarType() == MVT::i8) {
6920 // i8 -> i32 is natively supported with udot/sdot for both NEON and SVE.
6921 if (!IsUSDot && IsSupported(true, ST->hasDotProd()))
6922 return Cost + INegCost;
6923 // i8 -> i32 usdot requires +i8mm
6924 if (IsUSDot && IsSupported(ST->hasMatMulInt8(), ST->hasMatMulInt8()))
6925 return Cost + INegCost;
6926 // Without +i8mm, lower SUMLA via two udots plus an eor and a sub on plain
6927 // +dotprod targets. Note that this is only implemented for NEON, as all
6928 // modern CPUs with SVE also have +i8mm. Charge an extra factor for the
6929 // expansion.
6930 if (IsUSDot && IsSupported(false, ST->hasDotProd()))
6931 return Cost * 3 + INegCost;
6932 }
6933
6934 if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {
6935 // i16 -> i64 is natively supported for udot/sdot
6936 if (AccumLT.second.getScalarType() == MVT::i64 &&
6937 InputLT.second.getScalarType() == MVT::i16)
6938 return Cost + INegCost;
6939 // i16 -> i32 is natively supported with SVE2p1 udot/sdot.
6940 // For sub-reductions, we prefer using the *mlslb/t instructions.
6941 if (AccumLT.second.getScalarType() == MVT::i32 &&
6942 InputLT.second.getScalarType() == MVT::i16 &&
6943 (ST->hasSVE2p1() || ST->hasSME2()) && !IsSub)
6944 return Cost;
6945 // i8 -> i64 is supported with an extra level of extends
6946 if (AccumLT.second.getScalarType() == MVT::i64 &&
6947 InputLT.second.getScalarType() == MVT::i8)
6948 // FIXME: This cost should probably be a little higher, e.g. Cost + 2
6949 // because it requires two extra extends on the inputs. But if we'd change
6950 // that now, a regular reduction would be cheaper because the costs of
6951 // the extends in the IR are still counted. This can be fixed
6952 // after https://github.com/llvm/llvm-project/pull/147302 has landed.
6953 return Cost + INegCost;
6954 // i8 -> i16 is natively supported with SVE2p3 udot/sdot
6955 // For sub-reductions, we prefer using the *mlslb/t instructions.
6956 if (AccumLT.second.getScalarType() == MVT::i16 &&
6957 InputLT.second.getScalarType() == MVT::i8 &&
6958 (ST->hasSVE2p3() || ST->hasSME2p3()) && !IsSub)
6959 return Cost;
6960 }
6961
6962 // f16 -> f32 is natively supported for fdot using either
6963 // SVE or NEON instruction.
6964 if (Opcode == Instruction::FAdd && !IsSub &&
6965 IsSupported(ST->hasSME2() || ST->hasSVE2p1(), ST->hasF16F32DOT()) &&
6966 AccumLT.second.getScalarType() == MVT::f32 &&
6967 InputLT.second.getScalarType() == MVT::f16)
6968 return Cost;
6969
6970 // For a ratio of 2, we can use *mlal and *mlsl top/bottom instructions.
6971 if (Ratio == 2 && !IsUSDot) {
6972 MVT InVT = InputLT.second.getScalarType();
6973
6974 // SVE2 [us]ml[as]lb/t and NEON [us]ml[as]l(2). A pure widening add with a
6975 // ratio of 2 can use [SU]ADALP instead.
6976 if (IsSupported(ST->hasSVE2() || ST->hasSME(), true) &&
6977 llvm::is_contained({MVT::i8, MVT::i16, MVT::i32}, InVT.SimpleTy))
6978 return (BinOp || IsSub) ? Cost * 2 : Cost;
6979
6980 // SVE2 fml[as]lb/t and NEON fml[as]l(2)
6981 if (IsSupported(ST->hasSVE2(), ST->hasFP16FML()) && InVT == MVT::f16)
6982 return Cost * 2;
6983
6984 // SME2/SVE2p1 bfmlslb/t
6985 if (IsSupported(ST->hasSVE2p1() || ST->hasSME2(), false) &&
6986 InVT == MVT::bf16 && IsSub)
6987 return Cost * 2;
6988
6989 // FP partial sub-reductions that don't map to a specific instruction,
6990 // carry an extra cost for implementing an extra negation:
6991 // partial_reduce_fmls acc, lhs, rhs
6992 // <=> partial_reduce_fmla acc, lhs, -rhs
6993 InstructionCost FNegCost = IsSub ? InputLT.first * TTI::TCC_Basic : 0;
6994
6995 // SVE and NEON bfmlalb/t
6996 if (IsSupported(ST->hasBF16(), ST->hasBF16()) && InVT == MVT::bf16)
6997 return Cost * 2 + FNegCost;
6998 }
6999
7000 return BaseT::getPartialReductionCost(Opcode, InputTypeA, InputTypeB,
7001 AccumType, VF, OpAExtend, OpBExtend,
7002 BinOp, CostKind, FMF);
7003}
7004
7006 TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy,
7008 VectorType *SubTp, ArrayRef<const Value *> Args, const Instruction *CtxI,
7009 TTI::VectorInstrContext VIC) const {
7010 assert((Mask.empty() || DstTy->isScalableTy() ||
7011 Mask.size() == DstTy->getElementCount().getKnownMinValue()) &&
7012 "Expected the Mask to match the return size if given");
7013 assert(SrcTy->getScalarType() == DstTy->getScalarType() &&
7014 "Expected the same scalar types");
7015 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(SrcTy);
7016
7017 // If we have a Mask, and the LT is being legalized somehow, split the Mask
7018 // into smaller vectors and sum the cost of each shuffle.
7019 if (!Mask.empty() && isa<FixedVectorType>(SrcTy) && LT.second.isVector() &&
7020 LT.second.getScalarSizeInBits() * Mask.size() > 128 &&
7021 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
7022 Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {
7023 // Check for LD3/LD4 instructions, which are represented in llvm IR as
7024 // deinterleaving-shuffle(load). The shuffle cost could potentially be free,
7025 // but we model it with a cost of LT.first so that LD3/LD4 have a higher
7026 // cost than just the load.
7027 if (Args.size() >= 1 && isa<LoadInst>(Args[0]) &&
7030 return std::max<InstructionCost>(1, LT.first / 4);
7031
7032 // Check for ST3/ST4 instructions, which are represented in llvm IR as
7033 // store(interleaving-shuffle). The shuffle cost could potentially be free,
7034 // but we model it with a cost of LT.first so that ST3/ST4 have a higher
7035 // cost than just the store.
7036 if (CtxI && CtxI->hasOneUse() && isa<StoreInst>(*CtxI->user_begin()) &&
7038 Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||
7040 Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))
7041 return LT.first;
7042
7043 unsigned TpNumElts = Mask.size();
7044 unsigned LTNumElts = LT.second.getVectorNumElements();
7045 unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;
7046 VectorType *NTp = VectorType::get(SrcTy->getScalarType(),
7047 LT.second.getVectorElementCount());
7049 std::map<std::tuple<unsigned, unsigned, SmallVector<int>>, InstructionCost>
7050 PreviousCosts;
7051 for (unsigned N = 0; N < NumVecs; N++) {
7052 SmallVector<int> NMask;
7053 // Split the existing mask into chunks of size LTNumElts. Track the source
7054 // sub-vectors to ensure the result has at most 2 inputs.
7055 unsigned Source1 = -1U, Source2 = -1U;
7056 unsigned NumSources = 0;
7057 for (unsigned E = 0; E < LTNumElts; E++) {
7058 int MaskElt = (N * LTNumElts + E < TpNumElts) ? Mask[N * LTNumElts + E]
7060 if (MaskElt < 0) {
7062 continue;
7063 }
7064
7065 // Calculate which source from the input this comes from and whether it
7066 // is new to us.
7067 unsigned Source = MaskElt / LTNumElts;
7068 if (NumSources == 0) {
7069 Source1 = Source;
7070 NumSources = 1;
7071 } else if (NumSources == 1 && Source != Source1) {
7072 Source2 = Source;
7073 NumSources = 2;
7074 } else if (NumSources >= 2 && Source != Source1 && Source != Source2) {
7075 NumSources++;
7076 }
7077
7078 // Add to the new mask. For the NumSources>2 case these are not correct,
7079 // but are only used for the modular lane number.
7080 if (Source == Source1)
7081 NMask.push_back(MaskElt % LTNumElts);
7082 else if (Source == Source2)
7083 NMask.push_back(MaskElt % LTNumElts + LTNumElts);
7084 else
7085 NMask.push_back(MaskElt % LTNumElts);
7086 }
7087 // Check if we have already generated this sub-shuffle, which means we
7088 // will have already generated the output. For example a <16 x i32> splat
7089 // will be the same sub-splat 4 times, which only needs to be generated
7090 // once and reused.
7091 auto Result =
7092 PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});
7093 // Check if it was already in the map (already costed).
7094 if (!Result.second)
7095 continue;
7096 // If the sub-mask has at most 2 input sub-vectors then re-cost it using
7097 // getShuffleCost. If not then cost it using the worst case as the number
7098 // of element moves into a new vector.
7099 InstructionCost NCost =
7100 NumSources <= 2
7101 ? getShuffleCost(NumSources <= 1 ? TTI::SK_PermuteSingleSrc
7103 NTp, NTp, CostKind, NMask, 0, nullptr, Args,
7104 CtxI)
7105 : LTNumElts;
7106 Result.first->second = NCost;
7107 Cost += NCost;
7108 }
7109 return Cost;
7110 }
7111
7112 Kind = improveShuffleKindFromMask(Kind, Mask, SrcTy, Index, SubTp);
7113 bool IsExtractSubvector = Kind == TTI::SK_ExtractSubvector;
7114 // A subvector extract can be implemented with a NEON/SVE ext (or trivial
7115 // extract, if from lane 0) for 128-bit NEON vectors or legal SVE vectors.
7116 // This currently only handles low or high extracts to prevent SLP vectorizer
7117 // regressions.
7118 // Note that SVE's ext instruction is destructive, but it can be fused with
7119 // a movprfx to act like a constructive instruction.
7120 if (IsExtractSubvector && LT.second.isFixedLengthVector()) {
7121 if (LT.second.getFixedSizeInBits() >= 128 &&
7122 cast<FixedVectorType>(SubTp)->getNumElements() ==
7123 LT.second.getVectorNumElements() / 2) {
7124 if (Index == 0)
7125 return 0;
7126 if (Index == (int)LT.second.getVectorNumElements() / 2)
7127 return 1;
7128 }
7130 }
7131 // FIXME: This was added to keep the costs equal when adding DstTys. Update
7132 // the code to handle length-changing shuffles.
7133 if (Kind == TTI::SK_InsertSubvector) {
7134 LT = getTypeLegalizationCost(DstTy);
7135 SrcTy = DstTy;
7136 }
7137
7138 // Check for identity masks, which we can treat as free for both fixed and
7139 // scalable vector paths.
7140 if (!Mask.empty() && LT.second.isFixedLengthVector() &&
7141 (Kind == TTI::SK_PermuteTwoSrc || Kind == TTI::SK_PermuteSingleSrc) &&
7142 all_of(enumerate(Mask), [](const auto &M) {
7143 return M.value() < 0 || M.value() == (int)M.index();
7144 }))
7145 return 0;
7146
7147 // Segmented shuffle matching.
7148 if (Kind == TTI::SK_PermuteSingleSrc && isa<FixedVectorType>(SrcTy) &&
7149 !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&
7150 SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(
7152
7154 unsigned Segments =
7156 unsigned SegmentElts = VTy->getNumElements() / Segments;
7157
7158 // dupq zd.t, zn.t[idx]
7159 if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&
7160 ST->isSVEorStreamingSVEAvailable() &&
7161 isDUPQMask(Mask, Segments, SegmentElts))
7162 return LT.first;
7163
7164 // mov zd.q, vn
7165 if (ST->isSVEorStreamingSVEAvailable() &&
7166 isDUPFirstSegmentMask(Mask, Segments, SegmentElts))
7167 return LT.first;
7168 }
7169
7170 // Check for broadcast loads, which are supported by the LD1R instruction.
7171 // In terms of code-size, the shuffle vector is free when a load + dup get
7172 // folded into a LD1R. That's what we check and return here. For performance
7173 // and reciprocal throughput, a LD1R is not completely free. In this case, we
7174 // return the cost for the broadcast below (i.e. 1 for most/all types), so
7175 // that we model the load + dup sequence slightly higher because LD1R is a
7176 // high latency instruction.
7177 if (CostKind == TTI::TCK_CodeSize && Kind == TTI::SK_Broadcast) {
7178 bool IsLoad = !Args.empty() && isa<LoadInst>(Args[0]);
7179 if (IsLoad && LT.second.isVector() &&
7180 isLegalBroadcastLoad(SrcTy->getElementType(),
7181 LT.second.getVectorElementCount()))
7182 return 0;
7183 }
7184
7185 // If we have 4 elements for the shuffle and a Mask, get the cost straight
7186 // from the perfect shuffle tables.
7187 if (Mask.size() == 4 &&
7188 SrcTy->getElementCount() == ElementCount::getFixed(4) &&
7189 (SrcTy->getScalarSizeInBits() == 16 ||
7190 SrcTy->getScalarSizeInBits() == 32) &&
7191 all_of(Mask, [](int E) { return E < 8; }))
7192 return getPerfectShuffleCost(Mask);
7193
7194 // Check for other shuffles that are not SK_ kinds but we have native
7195 // instructions for, for example ZIP and UZP.
7196 unsigned Unused;
7197 if (LT.second.isFixedLengthVector() &&
7198 LT.second.getVectorNumElements() == Mask.size() &&
7199 (Kind == TTI::SK_PermuteTwoSrc || Kind == TTI::SK_PermuteSingleSrc ||
7200 // Discrepancies between isTRNMask and ShuffleVectorInst::isTransposeMask
7201 // mean that we can end up with shuffles that satisfy isTRNMask, but end
7202 // up labelled as TTI::SK_InsertSubvector. (e.g. {2, 0}).
7203 Kind == TTI::SK_InsertSubvector) &&
7204 (isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7205 isTRNMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7206 isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||
7207 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7208 LT.second.getVectorNumElements(), 16) ||
7209 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7210 LT.second.getVectorNumElements(), 32) ||
7211 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7212 LT.second.getVectorNumElements(), 64) ||
7213 // Check for non-zero lane splats
7214 all_of(drop_begin(Mask),
7215 [&Mask](int M) { return M < 0 || M == Mask[0]; })))
7216 return 1;
7217
7218 if (Kind == TTI::SK_Broadcast || Kind == TTI::SK_Transpose ||
7219 Kind == TTI::SK_Select || Kind == TTI::SK_PermuteSingleSrc ||
7220 Kind == TTI::SK_Reverse || Kind == TTI::SK_Splice) {
7221 static const CostTblEntry ShuffleTbl[] = {
7222 // Broadcast shuffle kinds can be performed with 'dup'.
7223 {TTI::SK_Broadcast, MVT::v8i8, 1},
7224 {TTI::SK_Broadcast, MVT::v16i8, 1},
7225 {TTI::SK_Broadcast, MVT::v4i16, 1},
7226 {TTI::SK_Broadcast, MVT::v8i16, 1},
7227 {TTI::SK_Broadcast, MVT::v2i32, 1},
7228 {TTI::SK_Broadcast, MVT::v4i32, 1},
7229 {TTI::SK_Broadcast, MVT::v2i64, 1},
7230 {TTI::SK_Broadcast, MVT::v4f16, 1},
7231 {TTI::SK_Broadcast, MVT::v8f16, 1},
7232 {TTI::SK_Broadcast, MVT::v4bf16, 1},
7233 {TTI::SK_Broadcast, MVT::v8bf16, 1},
7234 {TTI::SK_Broadcast, MVT::v2f32, 1},
7235 {TTI::SK_Broadcast, MVT::v4f32, 1},
7236 {TTI::SK_Broadcast, MVT::v2f64, 1},
7237 // Transpose shuffle kinds can be performed with 'trn1/trn2' and
7238 // 'zip1/zip2' instructions.
7239 {TTI::SK_Transpose, MVT::v8i8, 1},
7240 {TTI::SK_Transpose, MVT::v16i8, 1},
7241 {TTI::SK_Transpose, MVT::v4i16, 1},
7242 {TTI::SK_Transpose, MVT::v8i16, 1},
7243 {TTI::SK_Transpose, MVT::v2i32, 1},
7244 {TTI::SK_Transpose, MVT::v4i32, 1},
7245 {TTI::SK_Transpose, MVT::v2i64, 1},
7246 {TTI::SK_Transpose, MVT::v4f16, 1},
7247 {TTI::SK_Transpose, MVT::v8f16, 1},
7248 {TTI::SK_Transpose, MVT::v4bf16, 1},
7249 {TTI::SK_Transpose, MVT::v8bf16, 1},
7250 {TTI::SK_Transpose, MVT::v2f32, 1},
7251 {TTI::SK_Transpose, MVT::v4f32, 1},
7252 {TTI::SK_Transpose, MVT::v2f64, 1},
7253 // Select shuffle kinds.
7254 // TODO: handle vXi8/vXi16.
7255 {TTI::SK_Select, MVT::v2i32, 1}, // mov.
7256 {TTI::SK_Select, MVT::v4i32, 2}, // rev+trn (or similar).
7257 {TTI::SK_Select, MVT::v2i64, 1}, // mov.
7258 {TTI::SK_Select, MVT::v2f32, 1}, // mov.
7259 {TTI::SK_Select, MVT::v4f32, 2}, // rev+trn (or similar).
7260 {TTI::SK_Select, MVT::v2f64, 1}, // mov.
7261 // PermuteSingleSrc shuffle kinds.
7262 {TTI::SK_PermuteSingleSrc, MVT::v2i32, 1}, // mov.
7263 {TTI::SK_PermuteSingleSrc, MVT::v4i32, 3}, // perfectshuffle worst case.
7264 {TTI::SK_PermuteSingleSrc, MVT::v2i64, 1}, // mov.
7265 {TTI::SK_PermuteSingleSrc, MVT::v2f32, 1}, // mov.
7266 {TTI::SK_PermuteSingleSrc, MVT::v4f32, 3}, // perfectshuffle worst case.
7267 {TTI::SK_PermuteSingleSrc, MVT::v2f64, 1}, // mov.
7268 {TTI::SK_PermuteSingleSrc, MVT::v4i16, 3}, // perfectshuffle worst case.
7269 {TTI::SK_PermuteSingleSrc, MVT::v4f16, 3}, // perfectshuffle worst case.
7270 {TTI::SK_PermuteSingleSrc, MVT::v4bf16, 3}, // same
7271 {TTI::SK_PermuteSingleSrc, MVT::v8i16, 8}, // constpool + load + tbl
7272 {TTI::SK_PermuteSingleSrc, MVT::v8f16, 8}, // constpool + load + tbl
7273 {TTI::SK_PermuteSingleSrc, MVT::v8bf16, 8}, // constpool + load + tbl
7274 {TTI::SK_PermuteSingleSrc, MVT::v8i8, 8}, // constpool + load + tbl
7275 {TTI::SK_PermuteSingleSrc, MVT::v16i8, 8}, // constpool + load + tbl
7276 // Reverse can be lowered with `rev`.
7277 {TTI::SK_Reverse, MVT::v2i32, 1}, // REV64
7278 {TTI::SK_Reverse, MVT::v4i32, 2}, // REV64; EXT
7279 {TTI::SK_Reverse, MVT::v2i64, 1}, // EXT
7280 {TTI::SK_Reverse, MVT::v2f32, 1}, // REV64
7281 {TTI::SK_Reverse, MVT::v4f32, 2}, // REV64; EXT
7282 {TTI::SK_Reverse, MVT::v2f64, 1}, // EXT
7283 {TTI::SK_Reverse, MVT::v8f16, 2}, // REV64; EXT
7284 {TTI::SK_Reverse, MVT::v8bf16, 2}, // REV64; EXT
7285 {TTI::SK_Reverse, MVT::v8i16, 2}, // REV64; EXT
7286 {TTI::SK_Reverse, MVT::v16i8, 2}, // REV64; EXT
7287 {TTI::SK_Reverse, MVT::v4f16, 1}, // REV64
7288 {TTI::SK_Reverse, MVT::v4bf16, 1}, // REV64
7289 {TTI::SK_Reverse, MVT::v4i16, 1}, // REV64
7290 {TTI::SK_Reverse, MVT::v8i8, 1}, // REV64
7291 // Splice can all be lowered as `ext`.
7292 {TTI::SK_Splice, MVT::v2i32, 1},
7293 {TTI::SK_Splice, MVT::v4i32, 1},
7294 {TTI::SK_Splice, MVT::v2i64, 1},
7295 {TTI::SK_Splice, MVT::v2f32, 1},
7296 {TTI::SK_Splice, MVT::v4f32, 1},
7297 {TTI::SK_Splice, MVT::v2f64, 1},
7298 {TTI::SK_Splice, MVT::v8f16, 1},
7299 {TTI::SK_Splice, MVT::v8bf16, 1},
7300 {TTI::SK_Splice, MVT::v8i16, 1},
7301 {TTI::SK_Splice, MVT::v16i8, 1},
7302 {TTI::SK_Splice, MVT::v4f16, 1},
7303 {TTI::SK_Splice, MVT::v4bf16, 1},
7304 {TTI::SK_Splice, MVT::v4i16, 1},
7305 {TTI::SK_Splice, MVT::v8i8, 1},
7306 // Broadcast shuffle kinds for scalable vectors
7307 {TTI::SK_Broadcast, MVT::nxv16i8, 1},
7308 {TTI::SK_Broadcast, MVT::nxv8i16, 1},
7309 {TTI::SK_Broadcast, MVT::nxv4i32, 1},
7310 {TTI::SK_Broadcast, MVT::nxv2i64, 1},
7311 {TTI::SK_Broadcast, MVT::nxv2f16, 1},
7312 {TTI::SK_Broadcast, MVT::nxv4f16, 1},
7313 {TTI::SK_Broadcast, MVT::nxv8f16, 1},
7314 {TTI::SK_Broadcast, MVT::nxv2bf16, 1},
7315 {TTI::SK_Broadcast, MVT::nxv4bf16, 1},
7316 {TTI::SK_Broadcast, MVT::nxv8bf16, 1},
7317 {TTI::SK_Broadcast, MVT::nxv2f32, 1},
7318 {TTI::SK_Broadcast, MVT::nxv4f32, 1},
7319 {TTI::SK_Broadcast, MVT::nxv2f64, 1},
7320 {TTI::SK_Broadcast, MVT::nxv16i1, 1},
7321 {TTI::SK_Broadcast, MVT::nxv8i1, 1},
7322 {TTI::SK_Broadcast, MVT::nxv4i1, 1},
7323 {TTI::SK_Broadcast, MVT::nxv2i1, 1},
7324 // Handle the cases for vector.reverse with scalable vectors
7325 {TTI::SK_Reverse, MVT::nxv16i8, 1},
7326 {TTI::SK_Reverse, MVT::nxv8i16, 1},
7327 {TTI::SK_Reverse, MVT::nxv4i32, 1},
7328 {TTI::SK_Reverse, MVT::nxv2i64, 1},
7329 {TTI::SK_Reverse, MVT::nxv2f16, 1},
7330 {TTI::SK_Reverse, MVT::nxv4f16, 1},
7331 {TTI::SK_Reverse, MVT::nxv8f16, 1},
7332 {TTI::SK_Reverse, MVT::nxv2bf16, 1},
7333 {TTI::SK_Reverse, MVT::nxv4bf16, 1},
7334 {TTI::SK_Reverse, MVT::nxv8bf16, 1},
7335 {TTI::SK_Reverse, MVT::nxv2f32, 1},
7336 {TTI::SK_Reverse, MVT::nxv4f32, 1},
7337 {TTI::SK_Reverse, MVT::nxv2f64, 1},
7338 {TTI::SK_Reverse, MVT::nxv16i1, 1},
7339 {TTI::SK_Reverse, MVT::nxv8i1, 1},
7340 {TTI::SK_Reverse, MVT::nxv4i1, 1},
7341 {TTI::SK_Reverse, MVT::nxv2i1, 1},
7342 };
7343 if (const auto *Entry = CostTableLookup(ShuffleTbl, Kind, LT.second))
7344 return LT.first * Entry->Cost;
7345 }
7346
7347 if (Kind == TTI::SK_Splice && isa<ScalableVectorType>(SrcTy))
7348 return getSpliceCost(SrcTy, Index, CostKind);
7349
7350 // Inserting a subvector can often be done with either a D, S or H register
7351 // move, so long as the inserted vector is "aligned".
7352 if (Kind == TTI::SK_InsertSubvector && LT.second.isFixedLengthVector() &&
7353 LT.second.getSizeInBits() <= 128 && SubTp) {
7354 std::pair<InstructionCost, MVT> SubLT = getTypeLegalizationCost(SubTp);
7355 if (SubLT.second.isVector()) {
7356 int NumElts = LT.second.getVectorNumElements();
7357 int NumSubElts = SubLT.second.getVectorNumElements();
7358 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
7359 return SubLT.first;
7360 }
7361 }
7362
7363 // Restore optimal kind.
7364 if (IsExtractSubvector)
7366 return BaseT::getShuffleCost(Kind, DstTy, SrcTy, CostKind, Mask, Index, SubTp,
7367 Args, CtxI);
7368}
7369
7372 const DominatorTree &DT) {
7373 const auto &Strides = SymbolicStrideMap();
7374 for (BasicBlock *BB : TheLoop->blocks()) {
7375 // Scan the instructions in the block and look for addresses that are
7376 // consecutive and decreasing.
7377 for (Instruction &I : *BB) {
7378 if (isa<LoadInst>(&I) || isa<StoreInst>(&I)) {
7380 Type *AccessTy = getLoadStoreType(&I);
7381 // Analyze assuming predicates will be added, but discard them; this
7382 // query only guides tail-folding and must not add runtime checks to the
7383 // loop.
7385 if (getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,
7386 /*ShouldCheckWrap=*/false, &Predicates)
7387 .value_or(0) < 0)
7388 return true;
7389 }
7390 }
7391 }
7392 return false;
7393}
7394
7396 if (SVEPreferFixedOverScalableIfEqualCost.getNumOccurrences())
7398 return ST->useFixedOverScalableIfEqualCost();
7399}
7400
7402 return ST->getEpilogueVectorizationMinVF();
7403}
7404
7406 TailFoldingOpts DefaultOpts = ST->getSVETailFoldingDefaultOpts();
7407 if (!ST->hasSVE() || TailFoldingOptionLoc.isDisabled(DefaultOpts))
7408 return false;
7409
7410 // We don't currently support vectorisation with interleaving for SVE - with
7411 // such loops we're better off not using tail-folding. This gives us a chance
7412 // to fall back on fixed-width vectorisation using NEON's ld2/st2/etc.
7413 if (TFI->IAI->hasGroups())
7414 return false;
7415
7417 if (TFI->LVL->getReductionVars().size())
7418 Required |= TailFoldingOpts::Reductions;
7419 if (TFI->LVL->getFixedOrderRecurrences().size())
7420 Required |= TailFoldingOpts::Recurrences;
7421
7422 // We call this to discover whether any load/store pointers in the loop have
7423 // negative strides. This will require extra work to reverse the loop
7424 // predicate, which may be expensive.
7427 *TFI->LVL->getDominatorTree()))
7428 Required |= TailFoldingOpts::Reverse;
7429 if (Required == TailFoldingOpts::Disabled)
7430 Required |= TailFoldingOpts::Simple;
7431
7432 if (!TailFoldingOptionLoc.satisfies(DefaultOpts, Required))
7433 return false;
7434
7435 // Don't tail-fold for tight loops where we would be better off interleaving
7436 // with an unpredicated loop.
7437 unsigned NumInsns = 0;
7438 for (BasicBlock *BB : TFI->LVL->getLoop()->blocks()) {
7439 NumInsns += BB->size();
7440 }
7441
7442 // We expect 4 of these to be a IV PHI, IV add, IV compare and branch.
7443 return NumInsns >= SVETailFoldInsnThreshold;
7444}
7445
7448 StackOffset BaseOffset, bool HasBaseReg,
7449 int64_t Scale, unsigned AddrSpace) const {
7450 // Scaling factors are not free at all.
7451 // Operands | Rt Latency
7452 // -------------------------------------------
7453 // Rt, [Xn, Xm] | 4
7454 // -------------------------------------------
7455 // Rt, [Xn, Xm, lsl #imm] | Rn: 4 Rm: 5
7456 // Rt, [Xn, Wm, <extend> #imm] |
7458 AM.BaseGV = BaseGV;
7459 AM.BaseOffs = BaseOffset.getFixed();
7460 AM.HasBaseReg = HasBaseReg;
7461 AM.Scale = Scale;
7462 AM.ScalableOffset = BaseOffset.getScalable();
7463 if (getTLI()->isLegalAddressingMode(DL, AM, Ty, AddrSpace))
7464 // Scale represents reg2 * scale, thus account for 1 if
7465 // it is not equal to 0 or 1.
7466 return AM.Scale != 0 && AM.Scale != 1;
7468}
7469
7471 const Instruction *I) const {
7473 // For the binary operators (e.g. or) we need to be more careful than
7474 // selects, here we only transform them if they are already at a natural
7475 // break point in the code - the end of a block with an unconditional
7476 // terminator.
7477 if (I->getOpcode() == Instruction::Or &&
7478 isa<UncondBrInst>(I->getNextNode()))
7479 return true;
7480
7481 if (I->getOpcode() == Instruction::Add ||
7482 I->getOpcode() == Instruction::Sub)
7483 return true;
7484 }
7486}
7487
7490 const TargetTransformInfo::LSRCost &C2) const {
7491 // AArch64 specific here is adding the number of instructions to the
7492 // comparison (though not as the first consideration, as some targets do)
7493 // along with changing the priority of the base additions.
7494 // TODO: Maybe a more nuanced tradeoff between instruction count
7495 // and number of registers? To be investigated at a later date.
7496 if (EnableLSRCostOpt)
7497 return std::tie(C1.NumRegs, C1.Insns, C1.NumBaseAdds, C1.AddRecCost,
7498 C1.NumIVMuls, C1.ScaleCost, C1.ImmCost, C1.SetupCost) <
7499 std::tie(C2.NumRegs, C2.Insns, C2.NumBaseAdds, C2.AddRecCost,
7500 C2.NumIVMuls, C2.ScaleCost, C2.ImmCost, C2.SetupCost);
7501
7503}
7504
7505static bool isSplatShuffle(Value *V) {
7506 if (auto *Shuf = dyn_cast<ShuffleVectorInst>(V))
7507 return all_equal(Shuf->getShuffleMask());
7508 return false;
7509}
7510
7511/// Check if both Op1 and Op2 are shufflevector extracts of either the lower
7512/// or upper half of the vector elements.
7513static bool areExtractShuffleVectors(Value *Op1, Value *Op2,
7514 bool AllowSplat = false) {
7515 // Scalable types can't be extract shuffle vectors.
7516 if (Op1->getType()->isScalableTy() || Op2->getType()->isScalableTy())
7517 return false;
7518
7519 auto areTypesHalfed = [](Value *FullV, Value *HalfV) {
7520 auto *FullTy = FullV->getType();
7521 auto *HalfTy = HalfV->getType();
7522 return FullTy->getPrimitiveSizeInBits().getFixedValue() ==
7523 2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();
7524 };
7525
7526 auto extractHalf = [](Value *FullV, Value *HalfV) {
7527 auto *FullVT = cast<FixedVectorType>(FullV->getType());
7528 auto *HalfVT = cast<FixedVectorType>(HalfV->getType());
7529 return FullVT->getNumElements() == 2 * HalfVT->getNumElements();
7530 };
7531
7532 ArrayRef<int> M1, M2;
7533 Value *S1Op1 = nullptr, *S2Op1 = nullptr;
7534 if (!match(Op1, m_Shuffle(m_Value(S1Op1), m_Undef(), m_Mask(M1))) ||
7535 !match(Op2, m_Shuffle(m_Value(S2Op1), m_Undef(), m_Mask(M2))))
7536 return false;
7537
7538 // If we allow splats, set S1Op1/S2Op1 to nullptr for the relevant arg so that
7539 // it is not checked as an extract below.
7540 if (AllowSplat && isSplatShuffle(Op1))
7541 S1Op1 = nullptr;
7542 if (AllowSplat && isSplatShuffle(Op2))
7543 S2Op1 = nullptr;
7544
7545 // Check that the operands are half as wide as the result and we extract
7546 // half of the elements of the input vectors.
7547 if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||
7548 (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))
7549 return false;
7550
7551 // Check the mask extracts either the lower or upper half of vector
7552 // elements.
7553 int M1Start = 0;
7554 int M2Start = 0;
7555 int NumElements = cast<FixedVectorType>(Op1->getType())->getNumElements() * 2;
7556 if ((S1Op1 &&
7557 !ShuffleVectorInst::isExtractSubvectorMask(M1, NumElements, M1Start)) ||
7558 (S2Op1 &&
7559 !ShuffleVectorInst::isExtractSubvectorMask(M2, NumElements, M2Start)))
7560 return false;
7561
7562 if ((M1Start != 0 && M1Start != (NumElements / 2)) ||
7563 (M2Start != 0 && M2Start != (NumElements / 2)))
7564 return false;
7565 if (S1Op1 && S2Op1 && M1Start != M2Start)
7566 return false;
7567
7568 return true;
7569}
7570
7571/// Check if Ext1 and Ext2 are extends of the same type, doubling the bitwidth
7572/// of the vector elements.
7573static bool areExtractExts(Value *Ext1, Value *Ext2) {
7574 auto areExtDoubled = [](Instruction *Ext) {
7575 return Ext->getType()->getScalarSizeInBits() ==
7576 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
7577 };
7578
7579 if (!match(Ext1, m_ZExtOrSExt(m_Value())) ||
7580 !match(Ext2, m_ZExtOrSExt(m_Value())) ||
7581 !areExtDoubled(cast<Instruction>(Ext1)) ||
7582 !areExtDoubled(cast<Instruction>(Ext2)))
7583 return false;
7584
7585 return true;
7586}
7587
7588/// Check if Op could be used with vmull_high_p64 intrinsic.
7590 Value *VectorOperand = nullptr;
7591 ConstantInt *ElementIndex = nullptr;
7592 return match(Op, m_ExtractElt(m_Value(VectorOperand),
7593 m_ConstantInt(ElementIndex))) &&
7594 ElementIndex->getValue() == 1 &&
7595 isa<FixedVectorType>(VectorOperand->getType()) &&
7596 cast<FixedVectorType>(VectorOperand->getType())->getNumElements() == 2;
7597}
7598
7599/// Check if Op1 and Op2 could be used with vmull_high_p64 intrinsic.
7600static bool areOperandsOfVmullHighP64(Value *Op1, Value *Op2) {
7602}
7603
7605 // Restrict ourselves to the form CodeGenPrepare typically constructs.
7606 auto *GEP = dyn_cast<GetElementPtrInst>(Ptrs);
7607 if (!GEP || GEP->getNumOperands() != 2)
7608 return false;
7609
7610 Value *Base = GEP->getOperand(0);
7611 Value *Offsets = GEP->getOperand(1);
7612
7613 // We only care about scalar_base+vector_offsets.
7614 if (Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())
7615 return false;
7616
7617 // Sink extends that would allow us to use 32-bit offset vectors.
7618 if (isa<SExtInst>(Offsets) || isa<ZExtInst>(Offsets)) {
7619 auto *OffsetsInst = cast<Instruction>(Offsets);
7620 if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&
7621 OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)
7622 Ops.push_back(&GEP->getOperandUse(1));
7623 }
7624
7625 // Sink the GEP.
7626 return true;
7627}
7628
7629/// We want to sink following cases:
7630/// (add|sub|gep) A, ((mul|shl) vscale, imm); (add|sub|gep) A, vscale;
7631/// (add|sub|gep) A, ((mul|shl) zext(vscale), imm);
7633 if (match(Op, m_VScale()))
7634 return true;
7635 if (match(Op, m_Shl(m_VScale(), m_ConstantInt())) ||
7637 Ops.push_back(&cast<Instruction>(Op)->getOperandUse(0));
7638 return true;
7639 }
7640 if (match(Op, m_Shl(m_ZExt(m_VScale()), m_ConstantInt())) ||
7642 Value *ZExtOp = cast<Instruction>(Op)->getOperand(0);
7643 Ops.push_back(&cast<Instruction>(ZExtOp)->getOperandUse(0));
7644 Ops.push_back(&cast<Instruction>(Op)->getOperandUse(0));
7645 return true;
7646 }
7647 return false;
7648}
7649
7650static bool isFNeg(Value *Op) { return match(Op, m_FNeg(m_Value())); }
7651
7652/// Check if sinking \p I's operands to I's basic block is profitable, because
7653/// the operands can be folded into a target instruction, e.g.
7654/// shufflevectors extracts and/or sext/zext can be folded into (u,s)subl(2).
7658 switch (II->getIntrinsicID()) {
7659 case Intrinsic::aarch64_neon_smull:
7660 case Intrinsic::aarch64_neon_umull:
7661 if (areExtractShuffleVectors(II->getOperand(0), II->getOperand(1),
7662 /*AllowSplat=*/true)) {
7663 Ops.push_back(&II->getOperandUse(0));
7664 Ops.push_back(&II->getOperandUse(1));
7665 return true;
7666 }
7667 [[fallthrough]];
7668
7669 case Intrinsic::fma:
7670 case Intrinsic::fmuladd:
7671 if (isa<VectorType>(I->getType()) &&
7672 cast<VectorType>(I->getType())->getElementType()->isHalfTy() &&
7673 !ST->hasFullFP16())
7674 return false;
7675
7676 if (isFNeg(II->getOperand(0)))
7677 Ops.push_back(&II->getOperandUse(0));
7678 if (isFNeg(II->getOperand(1)))
7679 Ops.push_back(&II->getOperandUse(1));
7680
7681 [[fallthrough]];
7682 case Intrinsic::aarch64_neon_sqdmull:
7683 case Intrinsic::aarch64_neon_sqdmulh:
7684 case Intrinsic::aarch64_neon_sqrdmulh:
7685 // Sink splats for index lane variants
7686 if (isSplatShuffle(II->getOperand(0)))
7687 Ops.push_back(&II->getOperandUse(0));
7688 if (isSplatShuffle(II->getOperand(1)))
7689 Ops.push_back(&II->getOperandUse(1));
7690 return !Ops.empty();
7691 case Intrinsic::aarch64_neon_fmlal:
7692 case Intrinsic::aarch64_neon_fmlal2:
7693 case Intrinsic::aarch64_neon_fmlsl:
7694 case Intrinsic::aarch64_neon_fmlsl2:
7695 // Sink splats for index lane variants
7696 if (isSplatShuffle(II->getOperand(1)))
7697 Ops.push_back(&II->getOperandUse(1));
7698 if (isSplatShuffle(II->getOperand(2)))
7699 Ops.push_back(&II->getOperandUse(2));
7700 return !Ops.empty();
7701 case Intrinsic::aarch64_sve_ptest_first:
7702 case Intrinsic::aarch64_sve_ptest_last:
7703 if (auto *IIOp = dyn_cast<IntrinsicInst>(II->getOperand(0)))
7704 if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)
7705 Ops.push_back(&II->getOperandUse(0));
7706 return !Ops.empty();
7707 case Intrinsic::aarch64_sme_write_horiz:
7708 case Intrinsic::aarch64_sme_write_vert:
7709 case Intrinsic::aarch64_sme_writeq_horiz:
7710 case Intrinsic::aarch64_sme_writeq_vert: {
7711 auto *Idx = dyn_cast<Instruction>(II->getOperand(1));
7712 if (!Idx || Idx->getOpcode() != Instruction::Add)
7713 return false;
7714 Ops.push_back(&II->getOperandUse(1));
7715 return true;
7716 }
7717 case Intrinsic::aarch64_sme_read_horiz:
7718 case Intrinsic::aarch64_sme_read_vert:
7719 case Intrinsic::aarch64_sme_readq_horiz:
7720 case Intrinsic::aarch64_sme_readq_vert:
7721 case Intrinsic::aarch64_sme_ld1b_vert:
7722 case Intrinsic::aarch64_sme_ld1h_vert:
7723 case Intrinsic::aarch64_sme_ld1w_vert:
7724 case Intrinsic::aarch64_sme_ld1d_vert:
7725 case Intrinsic::aarch64_sme_ld1q_vert:
7726 case Intrinsic::aarch64_sme_st1b_vert:
7727 case Intrinsic::aarch64_sme_st1h_vert:
7728 case Intrinsic::aarch64_sme_st1w_vert:
7729 case Intrinsic::aarch64_sme_st1d_vert:
7730 case Intrinsic::aarch64_sme_st1q_vert:
7731 case Intrinsic::aarch64_sme_ld1b_horiz:
7732 case Intrinsic::aarch64_sme_ld1h_horiz:
7733 case Intrinsic::aarch64_sme_ld1w_horiz:
7734 case Intrinsic::aarch64_sme_ld1d_horiz:
7735 case Intrinsic::aarch64_sme_ld1q_horiz:
7736 case Intrinsic::aarch64_sme_st1b_horiz:
7737 case Intrinsic::aarch64_sme_st1h_horiz:
7738 case Intrinsic::aarch64_sme_st1w_horiz:
7739 case Intrinsic::aarch64_sme_st1d_horiz:
7740 case Intrinsic::aarch64_sme_st1q_horiz: {
7741 auto *Idx = dyn_cast<Instruction>(II->getOperand(3));
7742 if (!Idx || Idx->getOpcode() != Instruction::Add)
7743 return false;
7744 Ops.push_back(&II->getOperandUse(3));
7745 return true;
7746 }
7747 case Intrinsic::aarch64_neon_pmull:
7748 if (!areExtractShuffleVectors(II->getOperand(0), II->getOperand(1)))
7749 return false;
7750 Ops.push_back(&II->getOperandUse(0));
7751 Ops.push_back(&II->getOperandUse(1));
7752 return true;
7753 case Intrinsic::aarch64_neon_pmull64:
7754 if (!areOperandsOfVmullHighP64(II->getArgOperand(0),
7755 II->getArgOperand(1)))
7756 return false;
7757 Ops.push_back(&II->getArgOperandUse(0));
7758 Ops.push_back(&II->getArgOperandUse(1));
7759 return true;
7760 case Intrinsic::masked_gather:
7761 if (!shouldSinkVectorOfPtrs(II->getArgOperand(0), Ops))
7762 return false;
7763 Ops.push_back(&II->getArgOperandUse(0));
7764 return true;
7765 case Intrinsic::masked_scatter:
7766 if (!shouldSinkVectorOfPtrs(II->getArgOperand(1), Ops))
7767 return false;
7768 Ops.push_back(&II->getArgOperandUse(1));
7769 return true;
7770 default:
7771 return false;
7772 }
7773 }
7774
7775 auto ShouldSinkCondition = [](Value *Cond,
7776 SmallVectorImpl<Use *> &Ops) -> bool {
7778 return false;
7780 if (II->getIntrinsicID() != Intrinsic::vector_reduce_or ||
7781 !isa<ScalableVectorType>(II->getOperand(0)->getType()))
7782 return false;
7783 if (isa<CmpInst>(II->getOperand(0)))
7784 Ops.push_back(&II->getOperandUse(0));
7785 return true;
7786 };
7787
7788 switch (I->getOpcode()) {
7789 case Instruction::GetElementPtr:
7790 case Instruction::Add:
7791 case Instruction::Sub:
7792 // Sink vscales closer to uses for better isel
7793 for (unsigned Op = 0; Op < I->getNumOperands(); ++Op) {
7794 if (shouldSinkVScale(I->getOperand(Op), Ops)) {
7795 Ops.push_back(&I->getOperandUse(Op));
7796 return true;
7797 }
7798 }
7799 break;
7800 case Instruction::Select: {
7801 if (!ShouldSinkCondition(I->getOperand(0), Ops))
7802 return false;
7803
7804 Ops.push_back(&I->getOperandUse(0));
7805 return true;
7806 }
7807 case Instruction::UncondBr:
7808 return false;
7809 case Instruction::CondBr: {
7810 if (!ShouldSinkCondition(cast<CondBrInst>(I)->getCondition(), Ops))
7811 return false;
7812
7813 Ops.push_back(&I->getOperandUse(0));
7814 return true;
7815 }
7816 case Instruction::FMul:
7817 // fmul with contract flag can be combined with fadd into fma.
7818 // Sinking fneg into this block enables fmls pattern.
7819 if (cast<FPMathOperator>(I)->hasAllowContract()) {
7820 if (isFNeg(I->getOperand(0)))
7821 Ops.push_back(&I->getOperandUse(0));
7822 if (isFNeg(I->getOperand(1)))
7823 Ops.push_back(&I->getOperandUse(1));
7824 }
7825 break;
7826
7827 // Type | BIC | ORN | EON
7828 // ----------------+-----------+-----------+-----------
7829 // scalar | Base | Base | Base
7830 // scalar w/shift | - | - | -
7831 // fixed vector | NEON/Base | NEON/Base | BSL2N/Base
7832 // scalable vector | SVE | - | BSL2N
7833 case Instruction::Xor:
7834 // EON only for scalars (possibly expanded fixed vectors)
7835 // and vectors using the SVE2/SME BSL2N instruction.
7836 if (I->getType()->isVectorTy() && ST->isNeonAvailable()) {
7837 bool HasBSL2N =
7838 ST->isSVEorStreamingSVEAvailable() && (ST->hasSVE2() || ST->hasSME());
7839 if (!HasBSL2N)
7840 break;
7841 }
7842 [[fallthrough]];
7843 case Instruction::And:
7844 case Instruction::Or:
7845 // Even though we could use the SVE2/SME BSL2N instruction,
7846 // it might pessimize with an extra MOV depending on register allocation.
7847 if (I->getOpcode() == Instruction::Or &&
7848 isa<ScalableVectorType>(I->getType()))
7849 break;
7850 // Shift can be fold into scalar AND/ORR/EOR,
7851 // but not the non-negated operand of BIC/ORN/EON.
7852 if (!(I->getType()->isVectorTy() && ST->hasNEON()) &&
7854 break;
7855 for (auto &Op : I->operands()) {
7856 // (and/or/xor X, (not Y)) -> (bic/orn/eon X, Y)
7857 if (match(Op.get(), m_Not(m_Value()))) {
7858 Ops.push_back(&Op);
7859 return true;
7860 }
7861 // (and/or/xor X, (splat (not Y))) -> (bic/orn/eon X, (splat Y))
7862 if (match(Op.get(),
7864 m_Value(), m_ZeroMask()))) {
7865 Use &InsertElt = cast<Instruction>(Op)->getOperandUse(0);
7866 Use &Not = cast<Instruction>(InsertElt)->getOperandUse(1);
7867 Ops.push_back(&Not);
7868 Ops.push_back(&InsertElt);
7869 Ops.push_back(&Op);
7870 return true;
7871 }
7872 }
7873 break;
7874 default:
7875 break;
7876 }
7877
7878 if (!I->getType()->isVectorTy())
7879 return !Ops.empty();
7880
7881 switch (I->getOpcode()) {
7882 case Instruction::Sub:
7883 case Instruction::Add: {
7884 if (!areExtractExts(I->getOperand(0), I->getOperand(1)))
7885 return false;
7886
7887 // If the exts' operands extract either the lower or upper elements, we
7888 // can sink them too.
7889 auto Ext1 = cast<Instruction>(I->getOperand(0));
7890 auto Ext2 = cast<Instruction>(I->getOperand(1));
7891 if (areExtractShuffleVectors(Ext1->getOperand(0), Ext2->getOperand(0))) {
7892 Ops.push_back(&Ext1->getOperandUse(0));
7893 Ops.push_back(&Ext2->getOperandUse(0));
7894 }
7895
7896 Ops.push_back(&I->getOperandUse(0));
7897 Ops.push_back(&I->getOperandUse(1));
7898
7899 return true;
7900 }
7901 case Instruction::Or: {
7902 // Pattern: Or(And(MaskValue, A), And(Not(MaskValue), B)) ->
7903 // bitselect(MaskValue, A, B) where Not(MaskValue) = Xor(MaskValue, -1)
7904 if (ST->hasNEON()) {
7905 Instruction *OtherAnd, *IA, *IB;
7906 Value *MaskValue;
7907 // MainAnd refers to And instruction that has 'Not' as one of its operands
7908 if (match(I, m_c_Or(m_OneUse(m_Instruction(OtherAnd)),
7909 m_OneUse(m_c_And(m_OneUse(m_Not(m_Value(MaskValue))),
7910 m_Instruction(IA)))))) {
7911 if (match(OtherAnd,
7912 m_c_And(m_Specific(MaskValue), m_Instruction(IB)))) {
7913 Instruction *MainAnd = I->getOperand(0) == OtherAnd
7914 ? cast<Instruction>(I->getOperand(1))
7915 : cast<Instruction>(I->getOperand(0));
7916
7917 // Both Ands should be in same basic block as Or
7918 if (I->getParent() != MainAnd->getParent() ||
7919 I->getParent() != OtherAnd->getParent())
7920 return false;
7921
7922 // Non-mask operands of both Ands should also be in same basic block
7923 if (I->getParent() != IA->getParent() ||
7924 I->getParent() != IB->getParent())
7925 return false;
7926
7927 Ops.push_back(
7928 &MainAnd->getOperandUse(MainAnd->getOperand(0) == IA ? 1 : 0));
7929 Ops.push_back(&I->getOperandUse(0));
7930 Ops.push_back(&I->getOperandUse(1));
7931
7932 return true;
7933 }
7934 }
7935 }
7936
7937 return false;
7938 }
7939 case Instruction::Mul: {
7940 auto ShouldSinkSplatForIndexedVariant = [](Value *V) {
7941 auto *Ty = cast<VectorType>(V->getType());
7942 // For SVE the lane-indexing is within 128-bits, so we can't fold splats.
7943 if (Ty->isScalableTy())
7944 return false;
7945
7946 // Indexed variants of Mul exist for i16 and i32 element types only.
7947 return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;
7948 };
7949
7950 int NumZExts = 0, NumSExts = 0;
7951 for (auto &Op : I->operands()) {
7952 // Make sure we are not already sinking this operand
7953 if (any_of(Ops, [&](Use *U) { return U->get() == Op; }))
7954 continue;
7955
7956 if (match(&Op, m_ZExtOrSExt(m_Value()))) {
7957 auto *Ext = cast<Instruction>(Op);
7958 auto *ExtOp = Ext->getOperand(0);
7959 if (isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))
7960 Ops.push_back(&Ext->getOperandUse(0));
7961 Ops.push_back(&Op);
7962
7963 if (isa<SExtInst>(Ext)) {
7964 NumSExts++;
7965 } else {
7966 NumZExts++;
7967 // A zext(a) is also a sext(zext(a)), if we take more than 2 steps.
7968 if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <
7969 I->getType()->getScalarSizeInBits())
7970 NumSExts++;
7971 }
7972
7973 continue;
7974 }
7975
7977 if (!Shuffle)
7978 continue;
7979
7980 // If the Shuffle is a splat and the operand is a zext/sext, sinking the
7981 // operand and the s/zext can help create indexed s/umull. This is
7982 // especially useful to prevent i64 mul being scalarized.
7983 if (isSplatShuffle(Shuffle) &&
7984 match(Shuffle->getOperand(0), m_ZExtOrSExt(m_Value()))) {
7985 Ops.push_back(&Shuffle->getOperandUse(0));
7986 Ops.push_back(&Op);
7987 if (match(Shuffle->getOperand(0), m_SExt(m_Value())))
7988 NumSExts++;
7989 else
7990 NumZExts++;
7991 continue;
7992 }
7993
7994 Value *ShuffleOperand = Shuffle->getOperand(0);
7995 InsertElementInst *Insert = dyn_cast<InsertElementInst>(ShuffleOperand);
7996 if (!Insert)
7997 continue;
7998
7999 Instruction *OperandInstr = dyn_cast<Instruction>(Insert->getOperand(1));
8000 if (!OperandInstr)
8001 continue;
8002
8003 ConstantInt *ElementConstant =
8004 dyn_cast<ConstantInt>(Insert->getOperand(2));
8005 // Check that the insertelement is inserting into element 0
8006 if (!ElementConstant || !ElementConstant->isZero())
8007 continue;
8008
8009 unsigned Opcode = OperandInstr->getOpcode();
8010 if (Opcode == Instruction::SExt)
8011 NumSExts++;
8012 else if (Opcode == Instruction::ZExt)
8013 NumZExts++;
8014 else {
8015 // If we find that the top bits are known 0, then we can sink and allow
8016 // the backend to generate a umull.
8017 unsigned Bitwidth = I->getType()->getScalarSizeInBits();
8018 APInt UpperMask = APInt::getHighBitsSet(Bitwidth, Bitwidth / 2);
8019 if (!MaskedValueIsZero(OperandInstr, UpperMask, DL))
8020 continue;
8021 NumZExts++;
8022 }
8023
8024 // And(Load) is excluded to prevent CGP getting stuck in a loop of sinking
8025 // the And, just to hoist it again back to the load.
8026 if (!match(OperandInstr, m_And(m_Load(m_Value()), m_Value())))
8027 Ops.push_back(&Insert->getOperandUse(1));
8028 Ops.push_back(&Shuffle->getOperandUse(0));
8029 Ops.push_back(&Op);
8030 }
8031
8032 // It is profitable to sink if we found two of the same type of extends.
8033 if (!Ops.empty() && (NumSExts == 2 || NumZExts == 2))
8034 return true;
8035
8036 // Otherwise, see if we should sink splats for indexed variants.
8037 if (!ShouldSinkSplatForIndexedVariant(I))
8038 return false;
8039
8040 Ops.clear();
8041 if (isSplatShuffle(I->getOperand(0)))
8042 Ops.push_back(&I->getOperandUse(0));
8043 if (isSplatShuffle(I->getOperand(1)))
8044 Ops.push_back(&I->getOperandUse(1));
8045
8046 return !Ops.empty();
8047 }
8048 case Instruction::FMul: {
8049 // For SVE the lane-indexing is within 128-bits, so we can't fold splats.
8050 if (I->getType()->isScalableTy())
8051 return !Ops.empty();
8052
8053 if (cast<VectorType>(I->getType())->getElementType()->isHalfTy() &&
8054 !ST->hasFullFP16())
8055 return !Ops.empty();
8056
8057 // Sink splats for index lane variants
8058 if (isSplatShuffle(I->getOperand(0)))
8059 Ops.push_back(&I->getOperandUse(0));
8060 if (isSplatShuffle(I->getOperand(1)))
8061 Ops.push_back(&I->getOperandUse(1));
8062 return !Ops.empty();
8063 }
8064 default:
8065 return false;
8066 }
8067 return false;
8068}
8069
8071 Align Alignment) const {
8072 if (!(ST->isSVEAvailable() ||
8073 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2())))
8074 return false;
8075
8076 if (isa<FixedVectorType>(DataType) &&
8077 DataType->getPrimitiveSizeInBits().getFixedValue() < 128)
8078 return false;
8079
8080 if (!isa<VectorType>(DataType))
8081 return isElementTypeLegalForScalableVector(DataType);
8082
8083 auto LT = getTypeLegalizationCost(DataType);
8084 if (!LT.first.isValid())
8085 return false;
8086
8087 // Use the i32 or i64 compact instructions for f16/bf16 unpacked types.
8088 LLVMContext &Ctx = DataType->getContext();
8089 switch (LT.second.SimpleTy) {
8090 case MVT::nxv2f16:
8091 case MVT::nxv2bf16:
8093 case MVT::nxv4f16:
8094 case MVT::nxv4bf16:
8096 default:
8097 break;
8098 }
8099
8101 EVT(LT.second.getScalarType()).getTypeForEVT(Ctx));
8102}
static bool isAllActivePredicate(const SelectionDAG &DAG, SDValue N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static std::optional< Instruction * > instCombinePTrue(InstCombiner &IC, IntrinsicInst &II)
TailFoldingOption TailFoldingOptionLoc
static std::optional< Instruction * > instCombineSVEVectorFAdd(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEVectorFuseMulAddSub(InstCombiner &IC, IntrinsicInst &II, bool MergeIntoAddendOp)
static std::optional< Instruction * > instCombineZExtSVECmpNE(InstCombiner &IC, IntrinsicInst &II)
static void getFalkorUnrollingPreferences(Loop *L, ScalarEvolution &SE, TargetTransformInfo::UnrollingPreferences &UP)
bool SimplifyValuePattern(SmallVector< Value * > &Vec, bool AllowPoison)
static std::optional< Instruction * > instCombineSVESel(InstCombiner &IC, IntrinsicInst &II)
static bool hasPossibleIncompatibleOps(const Function *F, const AArch64TargetLowering &TLI)
Returns true if the function has explicit operations that can only be lowered using incompatible inst...
static bool shouldSinkVScale(Value *Op, SmallVectorImpl< Use * > &Ops)
We want to sink following cases: (add|sub|gep) A, ((mul|shl) vscale, imm); (add|sub|gep) A,...
static InstructionCost getHistogramCost(const AArch64Subtarget *ST, const IntrinsicCostAttributes &ICA)
static std::optional< Instruction * > tryCombineFromSVBoolBinOp(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEUnpack(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< unsigned > SVETailFoldInsnThreshold("sve-tail-folding-insn-threshold", cl::init(15), cl::Hidden)
static cl::opt< bool > EnableFixedwidthAutovecInStreamingMode("enable-fixedwidth-autovec-in-streaming-mode", cl::init(false), cl::Hidden)
static void getAppleRuntimeUnrollPreferences(Loop *L, ScalarEvolution &SE, TargetTransformInfo::UnrollingPreferences &UP, const AArch64TTIImpl &TTI)
For Apple CPUs, we want to runtime-unroll loops to make better use if the OOO engine's wide instructi...
static std::optional< Instruction * > instCombineWhilelo(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEVectorFAddU(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEPairwiseAddLong(InstCombiner &IC, IntrinsicInst &II)
static bool areExtractExts(Value *Ext1, Value *Ext2)
Check if Ext1 and Ext2 are extends of the same type, doubling the bitwidth of the vector elements.
static cl::opt< bool > EnableLSRCostOpt("enable-aarch64-lsr-cost-opt", cl::init(true), cl::Hidden)
static std::optional< Instruction * > instCombineSVEUMin(InstCombiner &IC, IntrinsicInst &II)
static bool shouldSinkVectorOfPtrs(Value *Ptrs, SmallVectorImpl< Use * > &Ops)
static bool shouldUnrollMultiExitLoop(Loop *L, ScalarEvolution &SE, const AArch64TTIImpl &TTI)
static std::optional< Instruction * > simplifySVEIntrinsicBinOp(InstCombiner &IC, IntrinsicInst &II, const SVEIntrinsicInfo &IInfo)
static std::optional< Instruction * > instCombineSVEVectorSub(InstCombiner &IC, IntrinsicInst &II)
static bool isLoopSizeWithinBudget(Loop *L, const AArch64TTIImpl &TTI, InstructionCost Budget, unsigned *FinalSize)
static std::optional< Instruction * > instCombineLD1GatherIndex(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEVectorFSub(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > processPhiNode(InstCombiner &IC, IntrinsicInst &II)
The function will remove redundant reinterprets casting in the presence of the control flow.
static std::optional< Instruction * > instCombineSVEInsr(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSMECntsd(InstCombiner &IC, IntrinsicInst &II, const AArch64Subtarget *ST)
static void extractAttrFeatures(const Function &F, const AArch64TTIImpl *TTI, SmallVectorImpl< StringRef > &Features)
static std::optional< Instruction * > instCombineST1ScatterIndex(InstCombiner &IC, IntrinsicInst &II)
static bool isSMEABIRoutineCall(const CallInst &CI, const AArch64TargetLowering &TLI)
static std::optional< Instruction * > instCombineSVESDIV(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEST1(InstCombiner &IC, IntrinsicInst &II, const DataLayout &DL)
static Value * stripInactiveLanes(Value *V, const Value *Pg)
static cl::opt< bool > SVEPreferFixedOverScalableIfEqualCost("sve-prefer-fixed-over-scalable-if-equal", cl::Hidden)
static bool isUnpackedVectorVT(EVT VecVT)
static std::optional< Instruction * > instCombineSVEDupX(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVECmpNE(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineDMB(InstCombiner &IC, IntrinsicInst &II)
static SVEIntrinsicInfo constructSVEIntrinsicInfo(IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEVectorFSubU(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineRDFFR(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineMaxMinNM(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > simplifySVEIntrinsicCompare(InstCombiner &IC, IntrinsicInst &II, const SVEIntrinsicInfo &IInfo)
static cl::opt< unsigned > SVEGatherOverhead("sve-gather-overhead", cl::init(10), cl::Hidden)
static std::optional< Instruction * > instCombineSVECondLast(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEPTest(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEZip(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< int > Aarch64ForceUnrollThreshold("aarch64-force-unroll-threshold", cl::init(0), cl::Hidden, cl::desc("Threshold for forced unrolling of small loops in AArch64"))
static std::optional< Instruction * > instCombineSVEDup(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< unsigned > BaseHistCntCost("aarch64-base-histcnt-cost", cl::init(8), cl::Hidden, cl::desc("The cost of a histcnt instruction"))
static std::optional< Instruction * > instCombineConvertFromSVBool(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< unsigned > CallPenaltyChangeSM("call-penalty-sm-change", cl::init(5), cl::Hidden, cl::desc("Penalty of calling a function that requires a change to PSTATE.SM"))
static std::optional< Instruction * > instCombineSVEUzp1(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVEVectorBinOp(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< bool > EnableScalableAutovecInStreamingMode("enable-scalable-autovec-in-streaming-mode", cl::init(false), cl::Hidden)
static std::optional< Instruction * > instCombineSVETBL(InstCombiner &IC, IntrinsicInst &II)
static bool areOperandsOfVmullHighP64(Value *Op1, Value *Op2)
Check if Op1 and Op2 could be used with vmull_high_p64 intrinsic.
static bool isFNeg(Value *Op)
static Instruction::BinaryOps intrinsicIDToBinOpCode(unsigned Intrinsic)
static bool containsDecreasingPointers(Loop *TheLoop, PredicatedScalarEvolution *PSE, const DominatorTree &DT)
static std::optional< Instruction * > instCombineSVEAnd(InstCombiner &IC, IntrinsicInst &II)
static bool isSplatShuffle(Value *V)
static cl::opt< unsigned > InlineCallPenaltyChangeSM("inline-call-penalty-sm-change", cl::init(10), cl::Hidden, cl::desc("Penalty of inlining a call that requires a change to PSTATE.SM"))
static std::optional< Instruction * > instCombineSVELD1(InstCombiner &IC, IntrinsicInst &II, const DataLayout &DL)
static std::optional< Instruction * > instCombineSVESrshl(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineXorSVECmpCC(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< unsigned > DMBLookaheadThreshold("dmb-lookahead-threshold", cl::init(10), cl::Hidden, cl::desc("The number of instructions to search for a redundant dmb"))
static std::optional< Instruction * > simplifySVEIntrinsic(InstCombiner &IC, IntrinsicInst &II, const SVEIntrinsicInfo &IInfo)
static unsigned getSVEGatherScatterOverhead(unsigned Opcode, const AArch64Subtarget *ST)
static std::optional< Instruction * > instCombineSVEVectorMlaU(InstCombiner &IC, IntrinsicInst &II)
static bool isOperandOfVmullHighP64(Value *Op)
Check if Op could be used with vmull_high_p64 intrinsic.
static std::optional< Instruction * > instCombineInStreamingMode(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVELast(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< unsigned > NeonNonConstStrideOverhead("neon-nonconst-stride-overhead", cl::init(10), cl::Hidden)
static cl::opt< bool > EnableFalkorHWPFUnrollFix("enable-falkor-hwpf-unroll-fix", cl::init(true), cl::Hidden)
static std::optional< Instruction * > instCombineSVEOrr(InstCombiner &IC, IntrinsicInst &II)
static std::optional< Instruction * > instCombineSVECntElts(InstCombiner &IC, IntrinsicInst &II, unsigned NumElts)
static std::optional< Instruction * > instCombineSVEUxt(InstCombiner &IC, IntrinsicInst &II, unsigned NumBits)
static cl::opt< TailFoldingOption, true, cl::parser< std::string > > SVETailFolding("sve-tail-folding", cl::desc("Control the use of vectorisation using tail-folding for SVE where the" " option is specified in the form (Initial)[+(Flag1|Flag2|...)]:" "\ndisabled (Initial) No loop types will vectorize using " "tail-folding" "\ndefault (Initial) Uses the default tail-folding settings for " "the target CPU" "\nall (Initial) All legal loop types will vectorize using " "tail-folding" "\nsimple (Initial) Use tail-folding for simple loops (not " "reductions or recurrences)" "\nreductions Use tail-folding for loops containing reductions" "\nnoreductions Inverse of above" "\nrecurrences Use tail-folding for loops containing fixed order " "recurrences" "\nnorecurrences Inverse of above" "\nreverse Use tail-folding for loops requiring reversed " "predicates" "\nnoreverse Inverse of above"), cl::location(TailFoldingOptionLoc))
static bool areExtractShuffleVectors(Value *Op1, Value *Op2, bool AllowSplat=false)
Check if both Op1 and Op2 are shufflevector extracts of either the lower or upper half of the vector ...
static std::optional< Instruction * > instCombineSVEVectorAdd(InstCombiner &IC, IntrinsicInst &II)
static cl::opt< bool > EnableOrLikeSelectOpt("enable-aarch64-or-like-select", cl::init(true), cl::Hidden)
static cl::opt< unsigned > SVEScatterOverhead("sve-scatter-overhead", cl::init(10), cl::Hidden)
static std::optional< Instruction * > instCombineSVEDupqLane(InstCombiner &IC, IntrinsicInst &II)
This file a TargetTransformInfoImplBase conforming object specific to the AArch64 target machine.
unsigned Imm
unsigned uint64_t
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file provides a helper that implements much of the TTI interface in terms of the target-independ...
static Error reportError(StringRef Message)
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 cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
Cost tables and simple lookup functions.
This file defines the DenseMap class.
@ Default
static Value * getCondition(Instruction *I)
Hexagon Common GEP
const HexagonInstrInfo * TII
#define _
This file provides the interface for the instcombine pass implementation.
static constexpr Value * getValue(Ty &ValueOrUse)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static LVOptions Options
Definition LVOptions.cpp:25
This file defines the LoopVectorizationLegality class.
#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)
#define T
AttributeSet CallAttrs
uint64_t IntrinsicInst * II
#define P(N)
const SmallVectorImpl< MachineOperand > & Cond
static uint64_t getBits(uint64_t Val, int Start, int End)
SI Fold Operands
static unsigned getFastMathFlags(const MachineInstr &I, const SPIRVSubtarget &ST)
#define LLVM_DEBUG(...)
Definition Debug.h:119
static unsigned getScalarSizeInBits(Type *Ty)
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
This file describes how to lower LLVM code to machine code.
This pass exposes codegen information to IR-level passes.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
Value * RHS
Value * LHS
BinaryOperator * Mul
This file implements the C++20 <bit> header.
unsigned getVectorInsertExtractBaseCost() const
bool useSVEForFixedLengthVectors() const
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getScalarizationOverhead(VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getCostOfKeepingLiveOverCall(ArrayRef< Type * > Tys) const override
InstructionCost getMaskedMemoryOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
InstructionCost getGatherScatterOpCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const
bool isLegalBroadcastLoad(Type *ElementTy, ElementCount NumElements) const override
InstructionCost getAddressComputationCost(Type *PtrTy, ScalarEvolution *SE, const SCEV *Ptr, TTI::TargetCostKind CostKind) const override
bool isExtPartOfAvgExpr(const Instruction *ExtUser, Type *Dst, Type *Src) const
InstructionCost getIntImmCost(int64_t Val) const
Calculate the cost of materializing a 64-bit value.
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index) const override
std::optional< InstructionCost > getFP16BF16PromoteCost(Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info, TTI::OperandValueInfo Op2Info, bool IncludeTrunc, bool CanUseSVE, std::function< InstructionCost(Type *)> InstCost) const
FP16 and BF16 operations are lowered to fptrunc(op(fpext, fpext) if the architecture features are not...
bool prefersVectorizedAddressing() const override
bool preferFixedOverScalableIfEqualCost() const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, TTI::TargetCostKind CostKind=TTI::TCK_RecipThroughput) const override
InstructionCost getVectorInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index, const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getIntImmCostInst(unsigned Opcode, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind, Instruction *Inst=nullptr) const override
bool isElementTypeLegalForScalableVector(Type *Ty) const override
void getPeelingPreferences(Loop *L, ScalarEvolution &SE, TTI::PeelingPreferences &PP) const override
InstructionCost getPartialReductionCost(unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, ElementCount VF, TTI::PartialReductionExtendKind OpAExtend, TTI::PartialReductionExtendKind OpBExtend, std::optional< unsigned > BinOp, TTI::TargetCostKind CostKind, std::optional< FastMathFlags > FMF) const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const override
bool preferTailFoldingOverEpilogue(TailFoldingInfo *TFI) const override
InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
APInt getPriorityMask(const Function &F) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
bool shouldMaximizeVectorBandwidth(TargetTransformInfo::RegisterKind K) const override
bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1, const TargetTransformInfo::LSRCost &C2) const override
InstructionCost getCFInstrCost(unsigned Opcode, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
bool isProfitableToSinkOperands(Instruction *I, SmallVectorImpl< Use * > &Ops) const override
Check if sinking I's operands to I's basic block is profitable, because the operands can be folded in...
std::optional< Value * > simplifyDemandedVectorEltsIntrinsic(InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3, std::function< void(Instruction *, unsigned, APInt, APInt &)> SimplifyAndSetOp) const override
bool useNeonVector(const Type *Ty) const
std::optional< Instruction * > instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *ValTy, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
bool isLegalSpeculativeLoad(Type *DataType, unsigned AddressSpace) const override
bool isLegalMaskedExpandLoad(Type *DataTy, Align Alignment) const override
TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth) const override
bool isElementTypeLegalForCompressStore(Type *Ty) const
InstructionCost getExtractWithExtendCost(unsigned Opcode, Type *Dst, VectorType *VecTy, unsigned Index, TTI::TargetCostKind CostKind) const override
unsigned getInlineCallPenalty(const Function *F, const CallBase &Call, unsigned DefaultCallPenalty) const override
bool areInlineCompatible(const Function *Caller, const Function *Callee) const override
unsigned getMaxNumElements(ElementCount VF) const
Try to return an estimate cost factor that can be used as a multiplier when scalarizing an operation ...
bool shouldTreatInstructionLikeSelect(const Instruction *I) const override
bool isMultiversionedFunction(const Function &F) const override
TypeSize getRegisterBitWidth(TargetTransformInfo::RegisterKind K) const override
bool isLegalToVectorizeReduction(const RecurrenceDescriptor &RdxDesc, ElementCount VF) const override
TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const override
bool isLegalMaskedCompressStore(Type *DataType, Align Alignment) const override
InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind) const override
bool isLegalMaskedGatherScatter(Type *DataType) const
InstructionCost getBranchMispredictPenalty() const override
bool shouldConsiderAddressTypePromotion(const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const override
See if I should be considered for address type promotion.
APInt getFeatureMask(const Function &F) const override
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
bool areTypesABICompatible(const Function *Caller, const Function *Callee, ArrayRef< Type * > Types) const override
bool enableScalableVectorization() const override
InstructionCost getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr) const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
Value * getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, Type *ExpectedType, bool CanCreate=true) const override
bool hasKnownLowerThroughputFromSchedulingModel(unsigned Opcode1, unsigned Opcode2) const
Check whether Opcode1 has less throughput according to the scheduling model than Opcode2.
unsigned getEpilogueVectorizationMinVF() const override
InstructionCost getSpliceCost(VectorType *Tp, int Index, TTI::TargetCostKind CostKind) const
InstructionCost getArithmeticReductionCostSVE(unsigned Opcode, VectorType *ValTy, TTI::TargetCostKind CostKind) const
InstructionCost getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, StackOffset BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace) const override
Return the cost of the scaling factor used in the addressing mode represented by AM for this target,...
unsigned getMaxInterleaveFactor(ElementCount VF, bool HasUnorderedReductions) const override
Class for arbitrary precision integers.
Definition APInt.h:78
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
Definition APInt.h:445
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1560
unsigned popcount() const
Count the number of bits set.
Definition APInt.h:1690
void negate()
Negate this APInt in place.
Definition APInt.h:1488
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
Definition APInt.cpp:1086
unsigned logBase2() const
Definition APInt.h:1781
APInt ashr(unsigned ShiftAmt) const
Arithmetic right-shift function.
Definition APInt.h:829
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
Definition APInt.h:436
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:302
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Definition APInt.h:292
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1582
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
LLVM Basic Block Representation.
Definition BasicBlock.h:62
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
InstructionCost getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef< unsigned > Indices, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, bool UseMaskForCond=false, bool UseMaskForGaps=false) const override
InstructionCost getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, TTI::TargetCostKind CostKind) const override
TTI::ShuffleKind improveShuffleKindFromMask(TTI::ShuffleKind Kind, ArrayRef< int > Mask, VectorType *SrcTy, int &Index, VectorType *&SubTy) const
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace, Instruction *I=nullptr, int64_t ScalableOffset=0) const override
bool areInlineCompatible(const Function *Caller, const Function *Callee) const override
InstructionCost getScalarizationOverhead(VectorType *InTy, const APInt &DemandedElts, bool Insert, bool Extract, TTI::TargetCostKind CostKind, bool ForPoisonSrc=true, ArrayRef< Value * > VL={}, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getArithmeticReductionCost(unsigned Opcode, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Op2Info={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
InstructionCost getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Opd1Info={TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Opd2Info={TTI::OK_AnyValue, TTI::OP_None}, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr) const override
InstructionCost getCallInstrCost(Function *F, Type *RetTy, ArrayRef< Type * > Tys, TTI::TargetCostKind CostKind) const override
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP, OptimizationRemarkEmitter *ORE) const override
void getPeelingPreferences(Loop *L, ScalarEvolution &SE, TTI::PeelingPreferences &PP) const override
InstructionCost getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, TTI::TargetCostKind CostKind) const override
InstructionCost getShuffleCost(TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args={}, const Instruction *CtxI=nullptr, TTI::VectorInstrContext VIC=TTI::VectorInstrContext::None) const override
InstructionCost getIndexedVectorInstrCostFromEnd(unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index) const override
InstructionCost getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I=nullptr) const override
std::pair< InstructionCost, MVT > getTypeLegalizationCost(Type *Ty) const
InstructionCost getPartialReductionCost(unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, ElementCount VF, TTI::PartialReductionExtendKind OpAExtend, TTI::PartialReductionExtendKind OpBExtend, std::optional< unsigned > BinOp, TTI::TargetCostKind CostKind, std::optional< FastMathFlags > FMF) const override
InstructionCost getExtendedReductionCost(unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *Ty, std::optional< FastMathFlags > FMF, TTI::TargetCostKind CostKind) const override
InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMemIntrinsicInstrCost(const MemIntrinsicCostAttributes &MICA, TTI::TargetCostKind CostKind) const override
InstructionCost getMemoryOpCost(unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo={TTI::OK_AnyValue, TTI::OP_None}, const Instruction *I=nullptr) const override
bool isTypeLegal(Type *Ty) const override
static BinaryOperator * CreateWithCopiedFlags(BinaryOps Opc, Value *V1, Value *V2, Value *CopyO, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Definition InstrTypes.h:254
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition InstrTypes.h:743
@ ICMP_SLT
signed less than
Definition InstrTypes.h:769
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:770
@ FCMP_OLT
0 1 0 0 True if ordered and less than
Definition InstrTypes.h:746
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
Definition InstrTypes.h:744
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
Definition InstrTypes.h:745
@ ICMP_UGE
unsigned greater or equal
Definition InstrTypes.h:764
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:763
@ ICMP_SGT
signed greater than
Definition InstrTypes.h:767
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
Definition InstrTypes.h:748
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
Definition InstrTypes.h:751
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Definition InstrTypes.h:747
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
Definition InstrTypes.h:749
@ ICMP_NE
not equal
Definition InstrTypes.h:762
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:768
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
Definition InstrTypes.h:756
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:766
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:750
static bool isFPPredicate(Predicate P)
Definition InstrTypes.h:833
static bool isIntPredicate(Predicate P)
Definition InstrTypes.h:839
bool isUnsigned() const
Definition InstrTypes.h:999
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
This is the shared class of boolean and integer constants.
Definition Constants.h:87
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Definition Constants.h:219
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
static LLVM_ABI ConstantInt * getBool(LLVMContext &Context, bool V)
static LLVM_ABI Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
This is an important base class in LLVM.
Definition Constant.h:43
LLVM_ABI Constant * getSplatValue(bool AllowPoison=false) const
If all elements of the vector constant have the same value, return that value.
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
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
Definition DataLayout.h:791
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:773
bool empty() const
Definition DenseMap.h:732
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:308
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:305
constexpr bool isScalar() const
Exactly one element.
Definition TypeSize.h:316
static ExtractElementInst * Create(Value *Vec, Value *Idx, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
static bool isCommutative(Predicate Pred)
This provides a helper for copying FMF from an instruction or setting specified flags.
Definition IRBuilder.h:93
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
bool noSignedZeros() const
Definition FMF.h:67
bool noInfs() const
Definition FMF.h:66
bool approxFunc() const
Definition FMF.h:70
bool allowContract() const
Definition FMF.h:69
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:843
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
static bool isCommutative(Predicate P)
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2661
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2649
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
Definition IRBuilder.h:526
Type * getDoubleTy()
Fetch the type representing a 64-bit floating point value.
Definition IRBuilder.h:546
LLVM_ABI Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
LLVM_ABI CallInst * CreateMaskedLoad(Type *Ty, Value *Ptr, Align Alignment, Value *Mask, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Load intrinsic.
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition IRBuilder.h:513
Type * getHalfTy()
Fetch the type representing a 16-bit floating point value.
Definition IRBuilder.h:531
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Definition IRBuilder.h:2003
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Definition IRBuilder.h:461
Value * CreateLogicalAnd(Value *Cond1, Value *Cond2, const Twine &Name="", Instruction *MDFrom=nullptr)
Definition IRBuilder.h:1757
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2324
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Definition IRBuilder.h:2539
Value * CreateBinOpFMF(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:1724
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1426
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2235
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition IRBuilder.h:1898
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
Definition IRBuilder.h:2683
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.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition IRBuilder.h:1917
LLVM_ABI CallInst * CreateMaskedStore(Value *Val, Value *Ptr, Align Alignment, Value *Mask)
Create a call to Masked Store intrinsic.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1409
Type * getFloatTy()
Fetch the type representing a 32-bit floating point value.
Definition IRBuilder.h:541
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
Definition IRBuilder.h:2315
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition IRBuilder.h:179
Value * CreateInsertVector(Type *DstType, Value *SrcVec, Value *SubVec, Value *Idx, const Twine &Name="")
Create a call to the vector.insert intrinsic.
Definition IRBuilder.h:1113
LLVM_ABI Value * CreateElementCount(Type *Ty, ElementCount EC)
Create an expression which evaluates to the number of elements in EC at runtime.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2901
This instruction inserts a single (scalar) element into a VectorType value.
The core instruction combiner logic.
virtual Instruction * eraseInstFromFunction(Instruction &I)=0
Combiner aware instruction erasure.
Instruction * replaceInstUsesWith(Instruction &I, Value *V)
A combiner-aware RAUW-like routine.
Instruction * replaceOperand(Instruction &I, unsigned OpNum, Value *V)
Replace operand of instruction and add old operand to the worklist.
static InstructionCost getInvalid(CostType Val=0)
CostType getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
LLVM_ABI bool isCommutative() const LLVM_READONLY
Return true if the instruction is commutative:
bool isBinaryOp() const
LLVM_ABI FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
user_iterator user_begin()
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
Class to represent integer types.
bool hasGroups() const
Returns true if we have any interleave groups.
const SmallVectorImpl< Type * > & getArgTypes() const
const SmallVectorImpl< const Value * > & getArgs() const
const IntrinsicInst * getInst() const
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
An instruction for reading from memory.
Value * getPointerOperand()
iterator_range< block_iterator > blocks() const
RecurrenceSet & getFixedOrderRecurrences()
Return the fixed-order recurrences found in the loop.
PredicatedScalarEvolution * getPredicatedScalarEvolution() const
const ReductionList & getReductionVars() const
Returns the reduction variables found in the loop.
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
Machine Value Type.
SimpleValueType SimpleTy
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
static MVT getScalableVectorVT(MVT VT, unsigned NumElements)
bool isFixedLengthVector() const
MVT getVectorElementType() const
size_type size() const
Definition MapVector.h:58
Information for memory intrinsic cost model.
const Instruction * getInst() const
The optimization diagnostic interface.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
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 ...
The RecurrenceDescriptor is used to identify recurrences variables in a loop.
Type * getRecurrenceType() const
Returns the type of the recurrence.
RecurKind getRecurrenceKind() const
This node represents a polynomial recurrence on the trip count of the specified loop.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
This class represents an analyzed expression in the program.
SMEAttrs is a utility class to parse the SME ACLE attributes on functions.
bool hasStreamingCompatibleInterface() const
bool hasStreamingInterfaceOrBody() const
bool isSMEABIRoutine() const
SMECallAttrs is a utility class to hold the SMEAttrs for a callsite.
static LLVM_ABI ScalableVectorType * get(Type *ElementType, unsigned MinNumElts)
Definition Type.cpp:865
static ScalableVectorType * getDoubleElementsVectorType(ScalableVectorType *VTy)
The main scalar evolution driver.
LLVM_ABI const SCEV * getBackedgeTakenCount(const Loop *L, ExitCountKind Kind=Exact)
If the specified loop has a predictable backedge-taken count, return it, otherwise return a SCEVCould...
LLVM_ABI unsigned getSmallConstantTripMultiple(const Loop *L, const SCEV *ExitCount)
Returns the largest constant divisor of the trip count as a normal unsigned value,...
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI unsigned getSmallConstantMaxTripCount(const Loop *L, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Returns the upper bound of the loop trip count as a normal unsigned value.
LLVM_ABI bool isBackedgeTakenCountMaxOrZero(const Loop *L)
Return true if the backedge taken count is either the value returned by getConstantMaxBackedgeTakenCo...
LLVM_ABI bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
const SCEV * getSymbolicMaxBackedgeTakenCount(const Loop *L)
When successful, this returns a SCEV that is greater than or equal to (i.e.
This instruction constructs a fixed permutation of two input vectors.
static LLVM_ABI bool isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static LLVM_ABI bool isExtractSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &Index)
Return true if this shuffle mask is an extract subvector mask.
static LLVM_ABI bool isInterleaveMask(ArrayRef< int > Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl< unsigned > &StartIndexes)
Return true if the mask interleaves one or more input vectors together.
size_type size() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
Definition TypeSize.h:30
static StackOffset getScalable(int64_t Scalable)
Definition TypeSize.h:40
static StackOffset getFixed(int64_t Fixed)
Definition TypeSize.h:39
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
Class to represent struct types.
TargetInstrInfo - Interface to description of machine instruction set.
std::pair< LegalizeTypeAction, EVT > LegalizeKind
LegalizeKind holds the legalization kind that needs to happen to EVT in order to type-legalize it.
const RTLIB::RuntimeLibcallsInfo & getRuntimeLibcallsInfo() const
virtual const DataLayout & getDataLayout() const
virtual bool shouldTreatInstructionLikeSelect(const Instruction *I) const
virtual bool isLoweredToCall(const Function *F) const
virtual bool isLSRCostLess(const TTI::LSRCost &C1, const TTI::LSRCost &C2) const
bool isConstantStridedAccessLessThan(ScalarEvolution *SE, const SCEV *Ptr, int64_t MergeDistance) const
virtual bool areTypesABICompatible(const Function *Caller, const Function *Callee, ArrayRef< Type * > Types) const
InstructionCost getInstructionCost(const User *U, ArrayRef< const Value * > Operands, TTI::TargetCostKind CostKind) const override
static LLVM_ABI OperandValueInfo getOperandInfo(const Value *V)
Collect properties of V used in cost analysis, e.g. OP_PowerOf2.
TargetCostKind
The kind of cost model.
@ TCK_RecipThroughput
Reciprocal throughput.
@ TCK_CodeSize
Instruction code size.
@ TCK_SizeAndLatency
The weighted sum of size and latency.
@ TCK_Latency
The latency of instruction.
static bool requiresOrderedReduction(std::optional< FastMathFlags > FMF)
A helper function to determine the type of reduction algorithm used for a given Opcode and set of Fas...
PopcntSupportKind
Flags indicating the kind of support for population count.
llvm::VectorInstrContext VectorInstrContext
@ TCC_Free
Expected to fold away in lowering.
@ TCC_Basic
The cost of a typical 'add' instruction.
ShuffleKind
The various kinds of shuffle patterns for vector queries.
@ SK_InsertSubvector
InsertSubvector. Index indicates start offset.
@ SK_Select
Selects elements from the corresponding lane of either source operand.
@ SK_PermuteSingleSrc
Shuffle elements of single source vector with any shuffle mask.
@ SK_Transpose
Transpose two vectors.
@ SK_Splice
Concatenates elements from the first input vector with elements of the second input vector.
@ SK_Broadcast
Broadcast element 0 to all other elements.
@ SK_PermuteTwoSrc
Merge elements from two source vectors into one with any shuffle mask.
@ SK_Reverse
Reverse the order of the vector.
@ SK_ExtractSubvector
ExtractSubvector Index indicates start offset.
CastContextHint
Represents a hint about the context in which a cast is used.
@ 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.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:339
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:342
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
Definition Type.cpp:300
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:283
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:277
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition Type.h:155
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
Definition Type.h:147
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:297
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:363
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:187
LLVM_ABI Type * getWithNewBitWidth(unsigned NewBitWidth) const
Given an integer or vector type, change the lane bitwidth to NewBitwidth, whilst keeping the old numb...
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
Definition Type.h:144
LLVM_ABI Type * getWithNewType(Type *EltTy) const
Given vector type, change the element type, whilst keeping the old number of elements.
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:222
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition Type.h:158
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:296
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
LLVM_ABI bool isScalableTy() const
Return true if this is a type whose size is a known multiple of vscale.
Definition Type.cpp:61
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:303
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:276
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
const Use & getOperandUse(unsigned i) const
Definition User.h:220
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
bool hasOneUse() const
Return true if there is exactly one use of this value.
Definition Value.h:441
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
Definition Value.cpp:1002
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:400
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 VectorType * getInteger(VectorType *VTy)
This static method gets a VectorType with the same number of elements as the input type,...
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 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
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
LLVM_ABI APInt getCpuSupportsMask(ArrayRef< StringRef > Features)
static constexpr unsigned SVEBitsPerBlock
LLVM_ABI APInt getFMVPriority(ArrayRef< StringRef > Features)
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
ISD namespace - This namespace contains an enum which represents all of the SelectionDAG node types a...
Definition ISDOpcodes.h:26
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:266
@ CTTZ_ELTS
Returns the number of number of trailing (least significant) zero elements in a vector.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:898
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:420
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:862
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:779
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:868
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:996
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:944
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:749
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:977
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:874
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
AllOnesConstantMatch m_AllOnes()
CheckType m_SpecificType(LLT Ty)
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
auto m_Cmp()
Matches any compare instruction and ignore it.
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
BinaryOp_match< LHS, RHS, Instruction::And, true > m_c_And(const LHS &L, const RHS &R)
Matches an And with LHS and RHS in either order.
LogicalOp_match< LHS, RHS, Instruction::And > m_LogicalAnd(const LHS &L, const RHS &R)
Matches L && R either in the form of L & R or L ?
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
cst_pred_ty< is_nonnegative > m_NonNegative()
Match an integer or vector of non-negative values.
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_BinOp()
Match an arbitrary binary operation and ignore it.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Xor, true > m_c_Xor(const LHS &L, const RHS &R)
Matches an Xor with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
auto m_VScale()
Matches a call to llvm.vscale().
OneOps_match< OpTy, Instruction::Load > m_Load(const OpTy &Op)
Matches LoadInst.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)
Matches a BinaryOperator with LHS and RHS in either order.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinOpPred_match< LHS, RHS, is_shift_op > m_Shift(const LHS &L, const RHS &R)
Matches shift operations.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
auto m_Undef()
Match an arbitrary undef constant.
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
BinaryOp_match< LHS, RHS, Instruction::Or, true > m_c_Or(const LHS &L, const RHS &R)
Matches an Or with LHS and RHS in either order.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
initializer< Ty > init(const Ty &Val)
LocationClass< Ty > location(Ty &L)
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:316
@ Offset
Definition DWP.cpp:577
std::optional< unsigned > isDUPQMask(ArrayRef< int > Mask, unsigned Segments, unsigned SegmentSize)
isDUPQMask - matches a splat of equivalent lanes within segments of a given number of elements.
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:1755
const CostTblEntryT< CostType > * CostTableLookup(ArrayRef< CostTblEntryT< CostType > > Tbl, int ISD, MVT Ty)
Find in cost table.
Definition CostTable.h:36
LLVM_ABI bool getBooleanLoopAttribute(const Loop *TheLoop, StringRef Name)
Returns true if Name is applied to TheLoop and enabled.
bool isZIPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for zip1 or zip2 masks of the form: <0, 8, 1, 9, 2, 10, 3, 11> (WhichResultOut = 0,...
TailFoldingOpts
An enum to describe what types of loops we should attempt to tail-fold: Disabled: None Reductions: Lo...
InstructionCost Cost
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
@ Known
Known to have no common set bits.
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:2570
bool isDUPFirstSegmentMask(ArrayRef< int > Mask, unsigned Segments, unsigned SegmentSize)
isDUPFirstSegmentMask - matches a splat of the first 128b segment.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Uninitialized
Definition Threading.h:60
LLVM_ABI std::optional< const MDOperand * > findStringMetadataForLoop(const Loop *TheLoop, StringRef Name)
Find string metadata for loop.
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI std::optional< int64_t > getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp, const DominatorTree &DT, const SymbolicStrideMap &StridesMap=SymbolicStrideMap(), bool ShouldCheckWrap=true, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
If the pointer has a constant stride return it in units of the access type size.
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
Definition STLExtras.h:2189
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI bool MaskedValueIsZero(const Value *V, const APInt &Mask, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if 'V & Mask' is known to be zero.
unsigned M1(unsigned Val)
Definition VE.h:377
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
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:1762
LLVM_ABI bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)
Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...
unsigned getPerfectShuffleCost(llvm::ArrayRef< int > M)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
DenseMap< Value *, const SCEVUnknown * > SymbolicStrideMap
Maps a pointer to its symbolic (non-constant) stride.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1769
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
bool isUZPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut)
Return true for uzp1 or uzp2 masks of the form: <0, 2, 4, 6, 8, 10, 12, 14> or <1,...
bool isREVMask(ArrayRef< int > M, unsigned EltSize, unsigned NumElts, unsigned BlockSize)
isREVMask - Check if a vector shuffle corresponds to a REV instruction with the specified blocksize.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
constexpr int PoisonMaskElem
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
TargetTransformInfo TTI
LLVM_ABI Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a BinaryOperator, fold the result or return null.
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
@ Or
Bitwise or logical OR of integers.
@ FSub
Subtraction of floats.
@ FAddChainWithSubs
A chain of fadds and fsubs.
@ 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()).
@ 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()).
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
@ AddChainWithSubs
A chain of adds and subs.
@ FAdd
Sum of floats.
@ UMax
Unsigned integer max implemented in terms of select(cmp()).
DWARFExpression::Operation Op
TypeConversionCostTblEntryT< uint16_t > TypeConversionCostTblEntry
Definition CostTable.h:62
CostTblEntryT< uint16_t > CostTblEntry
Definition CostTable.h:31
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
unsigned getNumElementsFromSVEPredPattern(unsigned Pattern)
Return the number of active elements for VL1 to VL256 predicate pattern, zero for all other patterns.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
Definition STLExtras.h:2182
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
const TypeConversionCostTblEntryT< CostType > * ConvertCostTableLookup(ArrayRef< TypeConversionCostTblEntryT< CostType > > Tbl, int ISD, MVT Dst, MVT Src)
Find in type conversion cost table.
Definition CostTable.h:67
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
Definition MathExtras.h:368
bool isTRNMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for trn1 or trn2 masks of the form: <0, 8, 2, 10, 4, 12, 6, 14> (WhichResultOut = 0,...
#define N
static SVEIntrinsicInfo defaultMergingUnaryNarrowingTopOp()
static SVEIntrinsicInfo defaultZeroingOp()
SVEIntrinsicInfo & setOperandIdxInactiveLanesTakenFrom(unsigned Index)
static SVEIntrinsicInfo defaultMergingOp(Intrinsic::ID IID=Intrinsic::not_intrinsic)
SVEIntrinsicInfo & setOperandIdxWithNoActiveLanes(unsigned Index)
unsigned getOperandIdxWithNoActiveLanes() const
CmpInst::Predicate getCmpPredicate() const
SVEIntrinsicInfo & setInactiveLanesAreUnused()
SVEIntrinsicInfo & setInactiveLanesAreNotDefined()
SVEIntrinsicInfo & setGoverningPredicateOperandIdx(unsigned Index)
static SVEIntrinsicInfo defaultUndefOp()
Intrinsic::ID getMatchingUndefIntrinsic() const
SVEIntrinsicInfo & setResultIsZeroInitialized()
static SVEIntrinsicInfo defaultMergingUnaryOp()
SVEIntrinsicInfo & setMatchingUndefIntrinsic(Intrinsic::ID IID)
unsigned getGoverningPredicateOperandIdx() const
SVEIntrinsicInfo & setCmpPredicate(CmpInst::Predicate Pred)
SVEIntrinsicInfo & setMatchingIROpcode(unsigned Opcode)
unsigned getOperandIdxInactiveLanesTakenFrom() const
static SVEIntrinsicInfo defaultVoidOp(unsigned GPIndex)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Extended Value Type.
Definition ValueTypes.h:35
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h:145
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
Definition ValueTypes.h:307
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
Definition ValueTypes.h:382
uint64_t getScalarSizeInBits() const
Definition ValueTypes.h:408
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339
bool isFixedLengthVector() const
Definition ValueTypes.h:199
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
Definition ValueTypes.h:346
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
Definition ValueTypes.h:187
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:129
bool isVariant() const
Definition MCSchedule.h:150
Machine model for scheduling, bundling, and heuristics.
Definition MCSchedule.h:273
static LLVM_ABI double getReciprocalThroughput(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Matching combinators.
Information about a load/store intrinsic defined by the target.
InterleavedAccessInfo * IAI
LoopVectorizationLegality * LVL
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
unsigned Insns
TODO: Some of these could be merged.
Returns options for expansion of memcmp. IsZeroCmp is.
Parameters that control the generic loop unrolling transformation.
bool UpperBound
Allow using trip count upper bound to unroll loops.
bool Force
Apply loop unroll on any kind of loop (mainly to loops that fail runtime unrolling).
unsigned PartialOptSizeThreshold
The cost threshold for the unrolled loop when optimizing for size, like OptSizeThreshold,...
unsigned DefaultUnrollRuntimeCount
Default unroll count for loops with run-time trip count.
bool RuntimeUnrollMultiExit
Allow runtime unrolling multi-exit loops.
unsigned SCEVExpansionBudget
Don't allow runtime unrolling if expanding the trip count takes more than SCEVExpansionBudget.
bool AddAdditionalAccumulators
Allow unrolling to add parallel reduction phis.
unsigned UnrollAndJamInnerLoopThreshold
Threshold for unroll and jam, for inner loop size.
bool UnrollAndJam
Allow unroll and jam. Used to enable unroll and jam for the target.
bool UnrollRemainder
Allow unrolling of all the iterations of the runtime loop remainder.
unsigned PartialThreshold
The cost threshold for the unrolled loop, like Threshold, but used for partial/runtime unrolling (set...
bool Runtime
Allow runtime unrolling (unrolling of loops to expand the size of the loop body even when the number ...
bool Partial
Allow partial unrolling (unrolling of loops to expand the size of the loop body, not only to eliminat...
unsigned MaxUpperBound
Set the maximum upper bound of trip count.