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