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