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