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