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