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