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