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