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 Value *CurrentInsertElt = nullptr, *Default = nullptr;
3414 if (!match(II.getOperand(0),
3416 m_Value(Default), m_Value(CurrentInsertElt), m_Value())) ||
3417 !isa<FixedVectorType>(CurrentInsertElt->getType()))
3418 return std::nullopt;
3419 auto IIScalableTy = cast<ScalableVectorType>(II.getType());
3420
3421 // Insert the scalars into a container ordered by InsertElement index
3422 SmallVector<Value *> Elts(IIScalableTy->getMinNumElements(), nullptr);
3423 while (auto InsertElt = dyn_cast<InsertElementInst>(CurrentInsertElt)) {
3424 auto Idx = cast<ConstantInt>(InsertElt->getOperand(2));
3425 Elts[Idx->getValue().getZExtValue()] = InsertElt->getOperand(1);
3426 CurrentInsertElt = InsertElt->getOperand(0);
3427 }
3428
3429 bool AllowPoison =
3430 isa<PoisonValue>(CurrentInsertElt) && isa<PoisonValue>(Default);
3431 if (!SimplifyValuePattern(Elts, AllowPoison))
3432 return std::nullopt;
3433
3434 // Rebuild the simplified chain of InsertElements. e.g. (a, b, a, b) as (a, b)
3435 Value *InsertEltChain = PoisonValue::get(CurrentInsertElt->getType());
3436 for (size_t I = 0; I < Elts.size(); I++) {
3437 if (Elts[I] == nullptr)
3438 continue;
3439 InsertEltChain = IC.Builder.CreateInsertElement(InsertEltChain, Elts[I],
3440 IC.Builder.getInt64(I));
3441 }
3442 if (InsertEltChain == nullptr)
3443 return std::nullopt;
3444
3445 // Splat the simplified sequence, e.g. (f16 a, f16 b, f16 c, f16 d) as one i64
3446 // value or (f16 a, f16 b) as one i32 value. This requires an InsertSubvector
3447 // be bitcast to a type wide enough to fit the sequence, be splatted, and then
3448 // be narrowed back to the original type.
3449 unsigned PatternWidth = IIScalableTy->getScalarSizeInBits() * Elts.size();
3450 unsigned PatternElementCount = IIScalableTy->getScalarSizeInBits() *
3451 IIScalableTy->getMinNumElements() /
3452 PatternWidth;
3453
3454 IntegerType *WideTy = IC.Builder.getIntNTy(PatternWidth);
3455 auto *WideScalableTy = ScalableVectorType::get(WideTy, PatternElementCount);
3456 auto *WideShuffleMaskTy =
3457 ScalableVectorType::get(IC.Builder.getInt32Ty(), PatternElementCount);
3458
3459 auto InsertSubvector = IC.Builder.CreateInsertVector(
3460 II.getType(), PoisonValue::get(II.getType()), InsertEltChain,
3461 uint64_t(0));
3462 auto WideBitcast =
3463 IC.Builder.CreateBitOrPointerCast(InsertSubvector, WideScalableTy);
3464 auto WideShuffleMask = ConstantAggregateZero::get(WideShuffleMaskTy);
3465 auto WideShuffle = IC.Builder.CreateShuffleVector(
3466 WideBitcast, PoisonValue::get(WideScalableTy), WideShuffleMask);
3467 auto NarrowBitcast =
3468 IC.Builder.CreateBitOrPointerCast(WideShuffle, II.getType());
3469
3470 return IC.replaceInstUsesWith(II, NarrowBitcast);
3471}
3472
3473static std::optional<Instruction *> instCombineMaxMinNM(InstCombiner &IC,
3474 IntrinsicInst &II) {
3475 Value *A = II.getArgOperand(0);
3476 Value *B = II.getArgOperand(1);
3477 if (A == B)
3478 return IC.replaceInstUsesWith(II, A);
3479
3480 return std::nullopt;
3481}
3482
3483static std::optional<Instruction *> instCombineSVESrshl(InstCombiner &IC,
3484 IntrinsicInst &II) {
3485 Value *Pred = II.getOperand(0);
3486 Value *Vec = II.getOperand(1);
3487 Value *Shift = II.getOperand(2);
3488
3489 // Convert SRSHL into the simpler LSL intrinsic when fed by an ABS intrinsic.
3490 Value *AbsPred, *MergedValue;
3492 m_Value(MergedValue), m_Value(AbsPred), m_Value())) &&
3494 m_Value(MergedValue), m_Value(AbsPred), m_Value())))
3495
3496 return std::nullopt;
3497
3498 // Transform is valid if any of the following are true:
3499 // * The ABS merge value is an undef or non-negative
3500 // * The ABS predicate is all active
3501 // * The ABS predicate and the SRSHL predicates are the same
3502 if (!isa<UndefValue>(MergedValue) && !match(MergedValue, m_NonNegative()) &&
3503 AbsPred != Pred && !isAllActivePredicate(AbsPred))
3504 return std::nullopt;
3505
3506 // Only valid when the shift amount is non-negative, otherwise the rounding
3507 // behaviour of SRSHL cannot be ignored.
3508 if (!match(Shift, m_NonNegative()))
3509 return std::nullopt;
3510
3511 auto LSL = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_lsl,
3512 {II.getType()}, {Pred, Vec, Shift});
3513
3514 return IC.replaceInstUsesWith(II, LSL);
3515}
3516
3517static std::optional<Instruction *> instCombineSVEInsr(InstCombiner &IC,
3518 IntrinsicInst &II) {
3519 Value *Vec = II.getOperand(0);
3520
3521 if (getSplatValue(Vec) == II.getOperand(1))
3522 return IC.replaceInstUsesWith(II, Vec);
3523
3524 return std::nullopt;
3525}
3526
3527static std::optional<Instruction *>
3529 unsigned LookaheadThreshold) {
3530 // If this barrier is post-dominated by identical one we can remove it
3531 auto *NI = II.getNextNode();
3532 auto CanSkipOver = [](Instruction *I) {
3533 return !I->mayReadOrWriteMemory() && !I->mayHaveSideEffects();
3534 };
3535 while (LookaheadThreshold-- && CanSkipOver(NI)) {
3536 auto *NIBB = NI->getParent();
3537 NI = NI->getNextNode();
3538 if (!NI) {
3539 if (auto *SuccBB = NIBB->getUniqueSuccessor())
3540 NI = &*SuccBB->getFirstNonPHIOrLifetime();
3541 else
3542 break;
3543 }
3544 }
3545 auto *NextII = dyn_cast_or_null<IntrinsicInst>(NI);
3546 if (NextII && II.isIdenticalTo(NextII))
3547 return IC.eraseInstFromFunction(II);
3548
3549 return std::nullopt;
3550}
3551
3552static std::optional<Instruction *> instCombineWhilelo(InstCombiner &IC,
3553 IntrinsicInst &II) {
3554 return IC.replaceInstUsesWith(
3555 II,
3556 IC.Builder.CreateIntrinsic(Intrinsic::get_active_lane_mask,
3557 {II.getType(), II.getOperand(0)->getType()},
3558 {II.getOperand(0), II.getOperand(1)}));
3559}
3560
3561static std::optional<Instruction *> instCombinePTrue(InstCombiner &IC,
3562 IntrinsicInst &II) {
3563 unsigned PredPattern = cast<ConstantInt>(II.getOperand(0))->getZExtValue();
3564 // SVE vector length is a power-of-two, thus pow2 is synonymous with all.
3565 if (PredPattern == AArch64SVEPredPattern::all ||
3566 PredPattern == AArch64SVEPredPattern::pow2)
3567 return IC.replaceInstUsesWith(II, ConstantInt::getTrue(II.getType()));
3568 return std::nullopt;
3569}
3570
3571static std::optional<Instruction *> instCombineSVEUxt(InstCombiner &IC,
3573 unsigned NumBits) {
3574 Value *Passthru = II.getOperand(0);
3575 Value *Pg = II.getOperand(1);
3576 Value *Op = II.getOperand(2);
3577
3578 // Convert UXT[BHW] to AND.
3579 if (isa<UndefValue>(Passthru) || isAllActivePredicate(Pg)) {
3580 auto *Ty = cast<VectorType>(II.getType());
3581 auto MaskValue = APInt::getLowBitsSet(Ty->getScalarSizeInBits(), NumBits);
3582 auto *Mask = ConstantInt::get(Ty, MaskValue);
3583 auto *And = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_and_u, {Ty},
3584 {Pg, Op, Mask});
3585 return IC.replaceInstUsesWith(II, And);
3586 }
3587
3588 return std::nullopt;
3589}
3590
3591static std::optional<Instruction *>
3593 SMEAttrs FnSMEAttrs(*II.getFunction());
3594 bool IsStreaming = FnSMEAttrs.hasStreamingInterfaceOrBody();
3595 if (IsStreaming || !FnSMEAttrs.hasStreamingCompatibleInterface())
3596 return IC.replaceInstUsesWith(
3597 II, ConstantInt::getBool(II.getType(), IsStreaming));
3598 return std::nullopt;
3599}
3600
3601static std::optional<Instruction *> instCombineSVEUMin(InstCombiner &IC,
3602 IntrinsicInst &II) {
3603 // umin(umin(A, 1), umin(B, 1)) -> umin(umin(A,B), 1)
3604 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3605 Value *A, *B;
3606 Value *Pg = II.getOperand(0);
3607 if (match(II.getOperand(1), m_OneUse(m_Intrinsic<UMinID>(
3608 m_Specific(Pg), m_Value(A), m_One()))) &&
3609 match(II.getOperand(2), m_OneUse(m_Intrinsic<UMinID>(
3610 m_Specific(Pg), m_Value(B), m_One())))) {
3611 Value *NewUMin =
3612 IC.Builder.CreateIntrinsic(UMinID, II.getType(), {Pg, A, B});
3613 Value *NewLogicalUMin = IC.Builder.CreateIntrinsic(
3614 UMinID, II.getType(), {Pg, NewUMin, ConstantInt::get(II.getType(), 1)});
3615 return IC.replaceInstUsesWith(II, NewLogicalUMin);
3616 }
3617
3618 // umin(umin(A, 1), 1) -> umin(A, 1)
3619 if (match(II.getOperand(1),
3621 match(II.getOperand(2), m_One()))
3622 return IC.replaceInstUsesWith(II, II.getOperand(1));
3623
3624 return std::nullopt;
3625}
3626
3627static std::optional<Instruction *> instCombineSVEOrr(InstCombiner &IC,
3628 IntrinsicInst &II) {
3629 // orr(umin(A, 1), umin(B, 1)) -> umin(orr(A, B), 1)
3630 constexpr Intrinsic::ID UMinID = Intrinsic::aarch64_sve_umin_u;
3631 Value *Pg = II.getOperand(0);
3632
3633 Value *A, *B;
3634 if (!match(II.getOperand(1), m_OneUse(m_Intrinsic<UMinID>(
3635 m_Specific(Pg), m_Value(A), m_One()))) ||
3636 !match(II.getOperand(2), m_OneUse(m_Intrinsic<UMinID>(
3637 m_Specific(Pg), m_Value(B), m_One()))))
3638 return std::nullopt;
3639
3640 Value *NewOrr = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_orr_u,
3641 II.getType(), {Pg, A, B});
3642 Value *NewUMin = IC.Builder.CreateIntrinsic(
3643 UMinID, II.getType(), {Pg, NewOrr, ConstantInt::get(II.getType(), 1)});
3644 return IC.replaceInstUsesWith(II, NewUMin);
3645}
3646
3647static std::optional<Instruction *> instCombineSVEAnd(InstCombiner &IC,
3648 IntrinsicInst &II) {
3649 // and(cmphs(pg, ConstA, A), cmphs(pg, A, ConstB))
3650 // ->
3651 // cmphs(pg, ConstA - ConstB, sub(pg, A, ConstB))
3652 constexpr Intrinsic::ID CmphsID = Intrinsic::aarch64_sve_cmphs;
3653 Value *Pg = II.getOperand(0);
3654 Value *LHS = II.getOperand(1);
3655 Value *RHS = II.getOperand(2);
3656
3657 Value *A, *PgLHS, *PgRHS;
3658 uint64_t ConstA, ConstB;
3659 if (!match(LHS, m_Intrinsic<CmphsID>(m_Value(PgLHS), m_ConstantInt(ConstA),
3660 m_Value(A))) ||
3662 m_ConstantInt(ConstB))) ||
3663 !LHS->hasOneUser() || !RHS->hasOneUser())
3664 return std::nullopt;
3665
3666 // Always false regardless of predication
3667 if (ConstB > ConstA)
3668 return IC.replaceInstUsesWith(II, Constant::getNullValue(II.getType()));
3669
3670 // The predicate for both CMPHSs must match.
3671 // The predicate for the AND can either be equal to the CMPHS predicates, or
3672 // either of the CMPHS values.
3673 if (PgLHS != PgRHS || (Pg != LHS && Pg != RHS && Pg != PgLHS))
3674 return std::nullopt;
3675
3676 Type *VecTy = A->getType();
3677 Constant *Base = ConstantInt::get(VecTy, ConstB);
3678 Value *Sub = IC.Builder.CreateIntrinsic(Intrinsic::aarch64_sve_sub_u, VecTy,
3679 {PgLHS, A, Base});
3680 Constant *Limit = ConstantInt::get(VecTy, ConstA - ConstB);
3681 Value *NewCmphs =
3682 IC.Builder.CreateIntrinsic(CmphsID, VecTy, {PgLHS, Limit, Sub});
3683
3684 return IC.replaceInstUsesWith(II, NewCmphs);
3685}
3686
3687std::optional<Instruction *>
3689 IntrinsicInst &II) const {
3691 if (std::optional<Instruction *> I = simplifySVEIntrinsic(IC, II, IInfo))
3692 return I;
3693
3694 Intrinsic::ID IID = II.getIntrinsicID();
3695 switch (IID) {
3696 default:
3697 break;
3698 case Intrinsic::aarch64_dmb:
3699 return instCombineDMB(IC, II, ST->getCLOpts().dmb_lookahead_threshold);
3700 case Intrinsic::aarch64_neon_fmaxnm:
3701 case Intrinsic::aarch64_neon_fminnm:
3702 return instCombineMaxMinNM(IC, II);
3703 case Intrinsic::aarch64_sve_convert_from_svbool:
3704 return instCombineConvertFromSVBool(IC, II);
3705 case Intrinsic::aarch64_sve_dup:
3706 return instCombineSVEDup(IC, II);
3707 case Intrinsic::aarch64_sve_dup_x:
3708 return instCombineSVEDupX(IC, II);
3709 case Intrinsic::aarch64_sve_cmpeq:
3710 case Intrinsic::aarch64_sve_cmpeq_wide:
3711 return instCombineXorSVECmpCC(IC, II);
3712 case Intrinsic::aarch64_sve_cmpne:
3713 case Intrinsic::aarch64_sve_cmpne_wide:
3714 return instCombineSVECmpNE(IC, II);
3715 case Intrinsic::aarch64_sve_rdffr:
3716 return instCombineRDFFR(IC, II);
3717 case Intrinsic::aarch64_sve_lasta:
3718 case Intrinsic::aarch64_sve_lastb:
3719 return instCombineSVELast(IC, II);
3720 case Intrinsic::aarch64_sve_clasta_n:
3721 case Intrinsic::aarch64_sve_clastb_n:
3722 return instCombineSVECondLast(IC, II);
3723 case Intrinsic::aarch64_sve_cntd:
3724 return instCombineSVECntElts(IC, II, 2);
3725 case Intrinsic::aarch64_sve_cntw:
3726 return instCombineSVECntElts(IC, II, 4);
3727 case Intrinsic::aarch64_sve_cnth:
3728 return instCombineSVECntElts(IC, II, 8);
3729 case Intrinsic::aarch64_sve_cntb:
3730 return instCombineSVECntElts(IC, II, 16);
3731 case Intrinsic::aarch64_sme_cntsd:
3732 return instCombineSMECntsd(IC, II, ST);
3733 case Intrinsic::aarch64_sve_ptest_any:
3734 case Intrinsic::aarch64_sve_ptest_first:
3735 case Intrinsic::aarch64_sve_ptest_last:
3736 return instCombineSVEPTest(IC, II);
3737 case Intrinsic::aarch64_sve_fadd:
3738 return instCombineSVEVectorFAdd(IC, II);
3739 case Intrinsic::aarch64_sve_fadd_u:
3740 return instCombineSVEVectorFAddU(IC, II);
3741 case Intrinsic::aarch64_sve_fmul_u:
3742 return instCombineSVEVectorBinOp(IC, II);
3743 case Intrinsic::aarch64_sve_fsub:
3744 return instCombineSVEVectorFSub(IC, II);
3745 case Intrinsic::aarch64_sve_fsub_u:
3746 return instCombineSVEVectorFSubU(IC, II);
3747 case Intrinsic::aarch64_sve_add:
3748 return instCombineSVEVectorAdd(IC, II);
3749 case Intrinsic::aarch64_sve_add_u:
3750 return instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul_u,
3751 Intrinsic::aarch64_sve_mla_u>(
3752 IC, II, true);
3753 case Intrinsic::aarch64_sve_mla_u:
3754 return instCombineSVEVectorMlaU(IC, II);
3755 case Intrinsic::aarch64_sve_sadalp:
3756 case Intrinsic::aarch64_sve_uadalp:
3758 case Intrinsic::aarch64_sve_sub:
3759 return instCombineSVEVectorSub(IC, II);
3760 case Intrinsic::aarch64_sve_sub_u:
3761 return instCombineSVEVectorFuseMulAddSub<Intrinsic::aarch64_sve_mul_u,
3762 Intrinsic::aarch64_sve_mls_u>(
3763 IC, II, true);
3764 case Intrinsic::aarch64_sve_tbl:
3765 return instCombineSVETBL(IC, II);
3766 case Intrinsic::aarch64_sve_uunpkhi:
3767 case Intrinsic::aarch64_sve_uunpklo:
3768 case Intrinsic::aarch64_sve_sunpkhi:
3769 case Intrinsic::aarch64_sve_sunpklo:
3770 return instCombineSVEUnpack(IC, II);
3771 case Intrinsic::aarch64_sve_uzp1:
3772 return instCombineSVEUzp1(IC, II);
3773 case Intrinsic::aarch64_sve_zip1:
3774 case Intrinsic::aarch64_sve_zip2:
3775 return instCombineSVEZip(IC, II);
3776 case Intrinsic::aarch64_sve_ld1_gather_index:
3777 return instCombineLD1GatherIndex(IC, II);
3778 case Intrinsic::aarch64_sve_st1_scatter_index:
3779 return instCombineST1ScatterIndex(IC, II);
3780 case Intrinsic::aarch64_sve_ld1:
3781 return instCombineSVELD1(IC, II, DL);
3782 case Intrinsic::aarch64_sve_st1:
3783 return instCombineSVEST1(IC, II, DL);
3784 case Intrinsic::aarch64_sve_sdiv:
3785 return instCombineSVESDIV(IC, II);
3786 case Intrinsic::aarch64_sve_sel:
3787 return instCombineSVESel(IC, II);
3788 case Intrinsic::aarch64_sve_srshl:
3789 return instCombineSVESrshl(IC, II);
3790 case Intrinsic::aarch64_sve_dupq_lane:
3791 return instCombineSVEDupqLane(IC, II);
3792 case Intrinsic::aarch64_sve_insr:
3793 return instCombineSVEInsr(IC, II);
3794 case Intrinsic::aarch64_sve_whilelo:
3795 return instCombineWhilelo(IC, II);
3796 case Intrinsic::aarch64_sve_ptrue:
3797 return instCombinePTrue(IC, II);
3798 case Intrinsic::aarch64_sve_uxtb:
3799 return instCombineSVEUxt(IC, II, 8);
3800 case Intrinsic::aarch64_sve_uxth:
3801 return instCombineSVEUxt(IC, II, 16);
3802 case Intrinsic::aarch64_sve_uxtw:
3803 return instCombineSVEUxt(IC, II, 32);
3804 case Intrinsic::aarch64_sme_in_streaming_mode:
3805 return instCombineInStreamingMode(IC, II);
3806 case Intrinsic::aarch64_sve_umin_u:
3807 return instCombineSVEUMin(IC, II);
3808 case Intrinsic::aarch64_sve_orr_u:
3809 return instCombineSVEOrr(IC, II);
3810 case Intrinsic::aarch64_sve_and_z:
3811 return instCombineSVEAnd(IC, II);
3812 }
3813
3814 return std::nullopt;
3815}
3816
3818 InstCombiner &IC, IntrinsicInst &II, APInt OrigDemandedElts,
3819 APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3,
3820 std::function<void(Instruction *, unsigned, APInt, APInt &)>
3821 SimplifyAndSetOp) const {
3822 switch (II.getIntrinsicID()) {
3823 default:
3824 break;
3825 case Intrinsic::aarch64_neon_fcvtxn:
3826 case Intrinsic::aarch64_neon_rshrn:
3827 case Intrinsic::aarch64_neon_sqrshrn:
3828 case Intrinsic::aarch64_neon_sqrshrun:
3829 case Intrinsic::aarch64_neon_sqshrn:
3830 case Intrinsic::aarch64_neon_sqshrun:
3831 case Intrinsic::aarch64_neon_sqxtn:
3832 case Intrinsic::aarch64_neon_sqxtun:
3833 case Intrinsic::aarch64_neon_uqrshrn:
3834 case Intrinsic::aarch64_neon_uqshrn:
3835 case Intrinsic::aarch64_neon_uqxtn:
3836 SimplifyAndSetOp(&II, 0, OrigDemandedElts, UndefElts);
3837 break;
3838 }
3839
3840 return std::nullopt;
3841}
3842
3844 return ST->isSVEAvailable() ||
3845 (ST->isSVEorStreamingSVEAvailable() &&
3846 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode);
3847}
3848
3851 switch (K) {
3853 return TypeSize::getFixed(64);
3855 if (ST->useSVEForFixedLengthVectors() &&
3856 (ST->isSVEAvailable() ||
3857 ST->getCLOpts().enable_fixedwidth_autovec_in_streaming_mode))
3858 return TypeSize::getFixed(
3859 std::max(ST->getMinSVEVectorSizeInBits(), 128u));
3860 else if (ST->isNeonAvailable())
3861 return TypeSize::getFixed(128);
3862 else
3863 return TypeSize::getFixed(0);
3865 if (ST->isSVEAvailable() ||
3866 (ST->isSVEorStreamingSVEAvailable() &&
3867 ST->getCLOpts().enable_scalable_autovec_in_streaming_mode))
3868 return TypeSize::getScalable(128);
3869 else
3870 return TypeSize::getScalable(0);
3871 }
3872 llvm_unreachable("Unsupported register kind");
3873}
3874
3875bool AArch64TTIImpl::isSingleExtWideningInstruction(
3876 unsigned Opcode, Type *DstTy, ArrayRef<const Value *> Args,
3877 Type *SrcOverrideTy) const {
3878 // A helper that returns a vector type from the given type. The number of
3879 // elements in type Ty determines the vector width.
3880 auto toVectorTy = [&](Type *ArgTy) {
3881 return VectorType::get(ArgTy->getScalarType(),
3882 cast<VectorType>(DstTy)->getElementCount());
3883 };
3884
3885 // Exit early if DstTy is not a vector type whose elements are one of [i16,
3886 // i32, i64]. SVE doesn't generally have the same set of instructions to
3887 // perform an extend with the add/sub/mul. There are SMULLB style
3888 // instructions, but they operate on top/bottom, requiring some sort of lane
3889 // interleaving to be used with zext/sext.
3890 unsigned DstEltSize = DstTy->getScalarSizeInBits();
3891 if (!useNeonVector(DstTy) || Args.size() != 2 ||
3892 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3893 return false;
3894
3895 Type *SrcTy = SrcOverrideTy;
3896 switch (Opcode) {
3897 case Instruction::Add: // UADDW(2), SADDW(2).
3898 case Instruction::Sub: { // USUBW(2), SSUBW(2).
3899 // The second operand needs to be an extend
3900 if (isa<SExtInst>(Args[1]) || isa<ZExtInst>(Args[1])) {
3901 if (!SrcTy)
3902 SrcTy =
3903 toVectorTy(cast<Instruction>(Args[1])->getOperand(0)->getType());
3904 break;
3905 }
3906
3907 if (Opcode == Instruction::Sub)
3908 return false;
3909
3910 // UADDW(2), SADDW(2) can be commutted.
3911 if (isa<SExtInst>(Args[0]) || isa<ZExtInst>(Args[0])) {
3912 if (!SrcTy)
3913 SrcTy =
3914 toVectorTy(cast<Instruction>(Args[0])->getOperand(0)->getType());
3915 break;
3916 }
3917 return false;
3918 }
3919 default:
3920 return false;
3921 }
3922
3923 // Legalize the destination type and ensure it can be used in a widening
3924 // operation.
3925 auto DstTyL = getTypeLegalizationCost(DstTy);
3926 if (!DstTyL.second.isVector() || DstEltSize != DstTy->getScalarSizeInBits())
3927 return false;
3928
3929 // Legalize the source type and ensure it can be used in a widening
3930 // operation.
3931 assert(SrcTy && "Expected some SrcTy");
3932 auto SrcTyL = getTypeLegalizationCost(SrcTy);
3933 unsigned SrcElTySize = SrcTyL.second.getScalarSizeInBits();
3934 if (!SrcTyL.second.isVector() || SrcElTySize != SrcTy->getScalarSizeInBits())
3935 return false;
3936
3937 // Get the total number of vector elements in the legalized types.
3938 InstructionCost NumDstEls =
3939 DstTyL.first * DstTyL.second.getVectorMinNumElements();
3940 InstructionCost NumSrcEls =
3941 SrcTyL.first * SrcTyL.second.getVectorMinNumElements();
3942
3943 // Return true if the legalized types have the same number of vector elements
3944 // and the destination element type size is twice that of the source type.
3945 return NumDstEls == NumSrcEls && 2 * SrcElTySize == DstEltSize;
3946}
3947
3948Type *AArch64TTIImpl::isBinExtWideningInstruction(unsigned Opcode, Type *DstTy,
3950 Type *SrcOverrideTy) const {
3951 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
3952 Opcode != Instruction::Mul)
3953 return nullptr;
3954
3955 // Exit early if DstTy is not a vector type whose elements are one of [i16,
3956 // i32, i64]. SVE doesn't generally have the same set of instructions to
3957 // perform an extend with the add/sub/mul. There are SMULLB style
3958 // instructions, but they operate on top/bottom, requiring some sort of lane
3959 // interleaving to be used with zext/sext.
3960 unsigned DstEltSize = DstTy->getScalarSizeInBits();
3961 if (!useNeonVector(DstTy) || Args.size() != 2 ||
3962 (DstEltSize != 16 && DstEltSize != 32 && DstEltSize != 64))
3963 return nullptr;
3964
3965 auto getScalarSizeWithOverride = [&](const Value *V) {
3966 if (SrcOverrideTy)
3967 return SrcOverrideTy->getScalarSizeInBits();
3968 return cast<Instruction>(V)
3969 ->getOperand(0)
3970 ->getType()
3971 ->getScalarSizeInBits();
3972 };
3973
3974 unsigned MaxEltSize = 0;
3975 if ((isa<SExtInst>(Args[0]) && isa<SExtInst>(Args[1])) ||
3976 (isa<ZExtInst>(Args[0]) && isa<ZExtInst>(Args[1]))) {
3977 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3978 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3979 MaxEltSize = std::max(EltSize0, EltSize1);
3980 } else if (isa<SExtInst, ZExtInst>(Args[0]) &&
3981 isa<SExtInst, ZExtInst>(Args[1])) {
3982 unsigned EltSize0 = getScalarSizeWithOverride(Args[0]);
3983 unsigned EltSize1 = getScalarSizeWithOverride(Args[1]);
3984 // mul(sext, zext) will become smull(sext, zext) if the extends are large
3985 // enough.
3986 if (EltSize0 >= DstEltSize / 2 || EltSize1 >= DstEltSize / 2)
3987 return nullptr;
3988 MaxEltSize = DstEltSize / 2;
3989 } else if (Opcode == Instruction::Mul &&
3990 (isa<ZExtInst>(Args[0]) || isa<ZExtInst>(Args[1]))) {
3991 // If one of the operands is a Zext and the other has enough zero bits
3992 // to be treated as unsigned, we can still generate a umull, meaning the
3993 // zext is free.
3994 KnownBits Known =
3995 computeKnownBits(isa<ZExtInst>(Args[0]) ? Args[1] : Args[0], DL);
3996 if (Args[0]->getType()->getScalarSizeInBits() -
3997 Known.Zero.countLeadingOnes() >
3998 DstTy->getScalarSizeInBits() / 2)
3999 return nullptr;
4000
4001 MaxEltSize =
4002 getScalarSizeWithOverride(isa<ZExtInst>(Args[0]) ? Args[0] : Args[1]);
4003 } else
4004 return nullptr;
4005
4006 if (MaxEltSize * 2 > DstEltSize)
4007 return nullptr;
4008
4009 Type *ExtTy = DstTy->getWithNewBitWidth(MaxEltSize * 2);
4010 if (ExtTy->getPrimitiveSizeInBits() <= 64)
4011 return nullptr;
4012 return ExtTy;
4013}
4014
4015// s/urhadd instructions implement the following pattern, making the
4016// extends free:
4017// %x = add ((zext i8 -> i16), 1)
4018// %y = (zext i8 -> i16)
4019// trunc i16 (lshr (add %x, %y), 1) -> i8
4020//
4022 Type *Src) const {
4023 // The source should be a legal vector type.
4024 if (!Src->isVectorTy() || !TLI->isTypeLegal(TLI->getValueType(DL, Src)) ||
4025 (Src->isScalableTy() && !ST->hasSVE2()))
4026 return false;
4027
4028 if (ExtUser->getOpcode() != Instruction::Add || !ExtUser->hasOneUse())
4029 return false;
4030
4031 // Look for trunc/shl/add before trying to match the pattern.
4032 const Instruction *Add = ExtUser;
4033 auto *AddUser =
4034 dyn_cast_or_null<Instruction>(Add->getUniqueUndroppableUser());
4035 if (AddUser && AddUser->getOpcode() == Instruction::Add)
4036 Add = AddUser;
4037
4038 auto *Shr = dyn_cast_or_null<Instruction>(Add->getUniqueUndroppableUser());
4039 if (!Shr || Shr->getOpcode() != Instruction::LShr)
4040 return false;
4041
4042 auto *Trunc = dyn_cast_or_null<Instruction>(Shr->getUniqueUndroppableUser());
4043 if (!Trunc || Trunc->getOpcode() != Instruction::Trunc ||
4044 Src->getScalarSizeInBits() !=
4045 cast<CastInst>(Trunc)->getDestTy()->getScalarSizeInBits())
4046 return false;
4047
4048 // Try to match the whole pattern. Ext could be either the first or second
4049 // m_ZExtOrSExt matched.
4050 Instruction *Ex1, *Ex2;
4051 if (!(match(Add, m_c_Add(m_Instruction(Ex1),
4052 m_c_Add(m_Instruction(Ex2), m_One())))))
4053 return false;
4054
4055 // Ensure both extends are of the same type
4056 if (match(Ex1, m_ZExtOrSExt(m_Value())) &&
4057 Ex1->getOpcode() == Ex2->getOpcode())
4058 return true;
4059
4060 return false;
4061}
4062
4064 Type *Src,
4066 TTI::TargetCostKind CostKind,
4067 const Instruction *I) const {
4068 int ISD = TLI->InstructionOpcodeToISD(Opcode);
4069 assert(ISD && "Invalid opcode");
4070
4071 // Codegen is not able to select all <vscale x 1 x Ty> casts yet.
4072 if (auto *VTy = dyn_cast<ScalableVectorType>(Dst);
4073 VTy && VTy->getElementCount() == ElementCount::getScalable(1)) {
4076 ISD))
4078 }
4079
4080 // If the cast is observable, and it is used by a widening instruction (e.g.,
4081 // uaddl, saddw, etc.), it may be free.
4082 if (I && !I->users().empty()) {
4083 // Determine whether Usr can absorb the cast from Src to Dst into a
4084 // widening instruction (e.g. uaddl, saddw, urhadd), making the cast free
4085 // with respect to that user.
4086 auto GetUserAbsorbedCastCost =
4087 [&](const Instruction *Usr) -> std::optional<InstructionCost> {
4088 SmallVector<const Value *, 4> Operands(Usr->operand_values());
4089
4090 if (Type *ExtTy = isBinExtWideningInstruction(
4091 Usr->getOpcode(), Dst, Operands,
4092 Src != I->getOperand(0)->getType() ? Src : nullptr)) {
4093 // The cost from Src->Src*2 needs to be added if required, the cost
4094 // from Src*2->ExtTy is free.
4095 if (ExtTy->getScalarSizeInBits() > Src->getScalarSizeInBits() * 2) {
4096 Type *DoubleSrcTy =
4097 Src->getWithNewBitWidth(Src->getScalarSizeInBits() * 2);
4098 return getCastInstrCost(Opcode, DoubleSrcTy, Src,
4099 TTI::CastContextHint::None, CostKind);
4100 }
4101
4102 return 0;
4103 }
4104
4105 if (isSingleExtWideningInstruction(
4106 Usr->getOpcode(), Dst, Operands,
4107 Src != I->getOperand(0)->getType() ? Src : nullptr)) {
4108 // For adds only count the second operand as free if both operands
4109 // are extends but not the same operation. (i.e both operands are
4110 // not free in add(sext, zext)).
4111 if (Usr->getOpcode() == Instruction::Add) {
4112 if (I == Usr->getOperand(1) ||
4113 (isa<CastInst>(Usr->getOperand(1)) &&
4114 cast<CastInst>(Usr->getOperand(1))->getOpcode() == Opcode))
4115 return 0;
4116 } else {
4117 // Others are free so long as isSingleExtWideningInstruction
4118 // returned true.
4119 return 0;
4120 }
4121 }
4122
4124 return std::nullopt;
4125
4126 // The cast will be free for the s/urhadd instructions
4127 if (isExtPartOfAvgExpr(Usr, Dst, Src))
4128 return 0;
4129
4130 // [US]SHLL/SHLL fold a doubling extend into a shift left by a splat
4131 // immediate of at most the source element width.
4132 const APInt *ShAmt;
4133 unsigned SrcBits = Src->getScalarSizeInBits();
4134 if (match(Usr, m_Shl(m_Specific(I), m_APInt(ShAmt))) &&
4135 ShAmt->ule(SrcBits) && useNeonVector(Dst) &&
4136 Dst->getScalarSizeInBits() == 2 * SrcBits &&
4137 getTypeLegalizationCost(Src).second.getScalarSizeInBits() == SrcBits)
4138 return 0;
4139
4140 return std::nullopt;
4141 };
4142
4143 InstructionCost MaxAbsorbedCost = 0;
4144 bool AllUsersAbsorbCast = true;
4145 for (const User *U : I->users()) {
4146 auto *Usr = cast<Instruction>(U);
4147 std::optional<InstructionCost> UserCost = GetUserAbsorbedCastCost(Usr);
4148 if (!UserCost) {
4149 AllUsersAbsorbCast = false;
4150 break;
4151 }
4152 MaxAbsorbedCost = std::max(MaxAbsorbedCost, *UserCost);
4153 }
4154
4155 if (AllUsersAbsorbCast)
4156 return MaxAbsorbedCost;
4157 }
4158
4159 // A vector compare already produces a lane mask (CMxx/FCMxx), so sign
4160 // extending it to the compare width is free. That only holds while the
4161 // result stays a vector; scalarized lanes still need a CSETM each.
4162 const Instruction *Cmp;
4163 const Value *CmpOp;
4164 if (I && useNeonVector(Dst) &&
4165 match(I, m_SExt(m_Instruction(Cmp, m_Cmp(m_Value(CmpOp), m_Value())))) &&
4166 Cmp->getParent() == I->getParent() &&
4167 CmpOp->getType()->getScalarSizeInBits() == Dst->getScalarSizeInBits() &&
4168 getTypeLegalizationCost(Dst).second.isVector())
4169 return 0;
4170
4171 EVT SrcTy = TLI->getValueType(DL, Src);
4172 EVT DstTy = TLI->getValueType(DL, Dst);
4173
4174 // SVE has no elements wider than 64 bits. The generic cost for a bitcast
4175 // between unsupported scalable types can otherwise appear to be free.
4176 if ((SrcTy.isScalableVector() && SrcTy.getScalarSizeInBits() > 64) ||
4177 (DstTy.isScalableVector() && DstTy.getScalarSizeInBits() > 64))
4179
4180 // A bitcast that crosses register banks is costed as a vector insert/extract.
4181 // Between the same register bank it is free. Note: Some costs are not handled
4182 // well by this, like i1 vectors that need to be packed.
4183 if (ISD == ISD::BITCAST && ST->isLittleEndian()) {
4184 std::pair<InstructionCost, MVT> SrcLT = getTypeLegalizationCost(Src);
4185 std::pair<InstructionCost, MVT> DstLT = getTypeLegalizationCost(Dst);
4186 bool SrcIsFloatOrVec =
4187 SrcLT.second.isVector() || SrcLT.second.isFloatingPoint();
4188 bool DstIsFloatOrVec =
4189 DstLT.second.isVector() || DstLT.second.isFloatingPoint();
4190
4191 // Consider the bitcast free if they are both the same type and have the
4192 // same size after legalization. Scalable vectors are handled specially as
4193 // the type legalization cost of v2i16 is v2i64.
4194 if (SrcIsFloatOrVec == DstIsFloatOrVec &&
4195 (SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits() ||
4196 (SrcLT.second.isScalableVector() &&
4197 SrcLT.second.getScalarSizeInBits() != 1 &&
4198 DstLT.second.getScalarSizeInBits() != 1)))
4199 return 0;
4200
4201 return std::max(SrcLT.first, DstLT.first) *
4202 (CostKind == TTI::TCK_CodeSize
4203 ? 1
4204 : ST->getVectorInsertExtractBaseCost());
4205 }
4206
4207 // From a vector to a scalarized vector will be an series of extract-element
4208 // and extends.
4209 if ((ISD == ISD::ZERO_EXTEND || ISD == ISD::SIGN_EXTEND) &&
4210 DstTy.getScalarSizeInBits() > 64 && SrcTy.getScalarSizeInBits() <= 64 &&
4211 DstTy.isFixedLengthVector()) {
4213 Instruction::ExtractElement, Src, CostKind, -1, nullptr, nullptr);
4215 Opcode, Dst->getScalarType(), Src->getScalarType(), CCH, CostKind);
4216 return DstTy.getVectorNumElements() * (LaneCost + ExtCost);
4217 }
4218
4219 if (!SrcTy.isSimple() || !DstTy.isSimple())
4220 return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I);
4221
4222 // For the moment we do not have lowering for SVE1-only fptrunc f64->bf16 as
4223 // we use fcvtx under SVE2. Give them invalid costs.
4224 if (!ST->hasSVE2() && !ST->isStreamingSVEAvailable() &&
4225 ISD == ISD::FP_ROUND && SrcTy.isScalableVector() &&
4226 DstTy.getScalarType() == MVT::bf16 && SrcTy.getScalarType() == MVT::f64)
4228
4229 static const TypeConversionCostTblEntry BF16Tbl[] = {
4230 {ISD::FP_ROUND, MVT::bf16, MVT::f32, 1}, // bfcvt
4231 {ISD::FP_ROUND, MVT::bf16, MVT::f64, 1}, // bfcvt
4232 {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f32, 1}, // bfcvtn
4233 {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f32, 2}, // bfcvtn+bfcvtn2
4234 {ISD::FP_ROUND, MVT::v2bf16, MVT::v2f64, 2}, // bfcvtn+fcvtn
4235 {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f64, 3}, // fcvtn+fcvtl2+bfcvtn
4236 {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f64, 6}, // 2 * fcvtn+fcvtn2+bfcvtn
4237 {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f32, 1}, // bfcvt
4238 {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f32, 1}, // bfcvt
4239 {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f32, 3}, // bfcvt+bfcvt+uzp1
4240 {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f64, 2}, // fcvtx+bfcvt
4241 {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f64, 5}, // 2*fcvtx+2*bfcvt+uzp1
4242 {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f64, 11}, // 4*fcvt+4*bfcvt+3*uzp
4243 };
4244
4245 if (ST->hasBF16())
4246 if (const auto *Entry = ConvertCostTableLookup(
4247 BF16Tbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()))
4248 return Entry->Cost;
4249
4250 // We have to estimate a cost of fixed length operation upon
4251 // SVE registers(operations) with the number of registers required
4252 // for a fixed type to be represented upon SVE registers.
4253 EVT WiderTy = SrcTy.bitsGT(DstTy) ? SrcTy : DstTy;
4254 if (SrcTy.isFixedLengthVector() && DstTy.isFixedLengthVector() &&
4255 SrcTy.getVectorNumElements() == DstTy.getVectorNumElements() &&
4256 ST->useSVEForFixedLengthVectors(WiderTy)) {
4257 std::pair<InstructionCost, MVT> LT =
4258 getTypeLegalizationCost(WiderTy.getTypeForEVT(Dst->getContext()));
4259 unsigned NumElements =
4260 AArch64::SVEBitsPerBlock / LT.second.getScalarSizeInBits();
4261 return LT.first *
4263 Opcode,
4264 ScalableVectorType::get(Dst->getScalarType(), NumElements),
4265 ScalableVectorType::get(Src->getScalarType(), NumElements), CCH,
4266 CostKind, I);
4267 }
4268
4269 // Symbolic constants for the SVE sitofp/uitofp entries in the table below
4270 // The cost of unpacking twice is artificially increased for now in order
4271 // to avoid regressions against NEON, which will use tbl instructions directly
4272 // instead of multiple layers of [s|u]unpk[lo|hi].
4273 // We use the unpacks in cases where the destination type is illegal and
4274 // requires splitting of the input, even if the input type itself is legal.
4275 const unsigned int SVE_EXT_COST = 1;
4276 const unsigned int SVE_FCVT_COST = 1;
4277 const unsigned int SVE_UNPACK_ONCE = 4;
4278 const unsigned int SVE_UNPACK_TWICE = 16;
4279
4280 static const TypeConversionCostTblEntry ConversionTbl[] = {
4281 {ISD::TRUNCATE, MVT::v2i8, MVT::v2i64, 1}, // xtn
4282 {ISD::TRUNCATE, MVT::v2i16, MVT::v2i64, 1}, // xtn
4283 {ISD::TRUNCATE, MVT::v2i32, MVT::v2i64, 1}, // xtn
4284 {ISD::TRUNCATE, MVT::v4i8, MVT::v4i32, 1}, // xtn
4285 {ISD::TRUNCATE, MVT::v4i8, MVT::v4i64, 3}, // 2 xtn + 1 uzp1
4286 {ISD::TRUNCATE, MVT::v4i16, MVT::v4i32, 1}, // xtn
4287 {ISD::TRUNCATE, MVT::v4i16, MVT::v4i64, 2}, // 1 uzp1 + 1 xtn
4288 {ISD::TRUNCATE, MVT::v4i32, MVT::v4i64, 1}, // 1 uzp1
4289 {ISD::TRUNCATE, MVT::v8i8, MVT::v8i16, 1}, // 1 xtn
4290 {ISD::TRUNCATE, MVT::v8i8, MVT::v8i32, 2}, // 1 uzp1 + 1 xtn
4291 {ISD::TRUNCATE, MVT::v8i8, MVT::v8i64, 4}, // 3 x uzp1 + xtn
4292 {ISD::TRUNCATE, MVT::v8i16, MVT::v8i32, 1}, // 1 uzp1
4293 {ISD::TRUNCATE, MVT::v8i16, MVT::v8i64, 3}, // 3 x uzp1
4294 {ISD::TRUNCATE, MVT::v8i32, MVT::v8i64, 2}, // 2 x uzp1
4295 {ISD::TRUNCATE, MVT::v16i8, MVT::v16i16, 1}, // uzp1
4296 {ISD::TRUNCATE, MVT::v16i8, MVT::v16i32, 3}, // (2 + 1) x uzp1
4297 {ISD::TRUNCATE, MVT::v16i8, MVT::v16i64, 7}, // (4 + 2 + 1) x uzp1
4298 {ISD::TRUNCATE, MVT::v16i16, MVT::v16i32, 2}, // 2 x uzp1
4299 {ISD::TRUNCATE, MVT::v16i16, MVT::v16i64, 6}, // (4 + 2) x uzp1
4300 {ISD::TRUNCATE, MVT::v16i32, MVT::v16i64, 4}, // 4 x uzp1
4301
4302 // Truncations on nxvmiN
4303 {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i8, 2},
4304 {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i16, 2},
4305 {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i32, 2},
4306 {ISD::TRUNCATE, MVT::nxv2i1, MVT::nxv2i64, 2},
4307 {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i8, 2},
4308 {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i16, 2},
4309 {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i32, 2},
4310 {ISD::TRUNCATE, MVT::nxv4i1, MVT::nxv4i64, 5},
4311 {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i8, 2},
4312 {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i16, 2},
4313 {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i32, 5},
4314 {ISD::TRUNCATE, MVT::nxv8i1, MVT::nxv8i64, 11},
4315 {ISD::TRUNCATE, MVT::nxv16i1, MVT::nxv16i8, 2},
4316 {ISD::TRUNCATE, MVT::nxv2i8, MVT::nxv2i16, 0},
4317 {ISD::TRUNCATE, MVT::nxv2i8, MVT::nxv2i32, 0},
4318 {ISD::TRUNCATE, MVT::nxv2i8, MVT::nxv2i64, 0},
4319 {ISD::TRUNCATE, MVT::nxv2i16, MVT::nxv2i32, 0},
4320 {ISD::TRUNCATE, MVT::nxv2i16, MVT::nxv2i64, 0},
4321 {ISD::TRUNCATE, MVT::nxv2i32, MVT::nxv2i64, 0},
4322 {ISD::TRUNCATE, MVT::nxv4i8, MVT::nxv4i16, 0},
4323 {ISD::TRUNCATE, MVT::nxv4i8, MVT::nxv4i32, 0},
4324 {ISD::TRUNCATE, MVT::nxv4i8, MVT::nxv4i64, 1},
4325 {ISD::TRUNCATE, MVT::nxv4i16, MVT::nxv4i32, 0},
4326 {ISD::TRUNCATE, MVT::nxv4i16, MVT::nxv4i64, 1},
4327 {ISD::TRUNCATE, MVT::nxv4i32, MVT::nxv4i64, 1},
4328 {ISD::TRUNCATE, MVT::nxv8i8, MVT::nxv8i16, 0},
4329 {ISD::TRUNCATE, MVT::nxv8i8, MVT::nxv8i32, 1},
4330 {ISD::TRUNCATE, MVT::nxv8i8, MVT::nxv8i64, 3},
4331 {ISD::TRUNCATE, MVT::nxv8i16, MVT::nxv8i32, 1},
4332 {ISD::TRUNCATE, MVT::nxv8i16, MVT::nxv8i64, 3},
4333 {ISD::TRUNCATE, MVT::nxv16i8, MVT::nxv16i16, 1},
4334 {ISD::TRUNCATE, MVT::nxv16i8, MVT::nxv16i32, 3},
4335 {ISD::TRUNCATE, MVT::nxv16i8, MVT::nxv16i64, 7},
4336
4337 // The number of shll instructions for the extension.
4338 {ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i16, 3},
4339 {ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i16, 3},
4340 {ISD::SIGN_EXTEND, MVT::v4i64, MVT::v4i32, 2},
4341 {ISD::ZERO_EXTEND, MVT::v4i64, MVT::v4i32, 2},
4342 {ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i8, 3},
4343 {ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i8, 3},
4344 {ISD::SIGN_EXTEND, MVT::v8i32, MVT::v8i16, 2},
4345 {ISD::ZERO_EXTEND, MVT::v8i32, MVT::v8i16, 2},
4346 {ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i8, 7},
4347 {ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i8, 7},
4348 {ISD::SIGN_EXTEND, MVT::v8i64, MVT::v8i16, 6},
4349 {ISD::ZERO_EXTEND, MVT::v8i64, MVT::v8i16, 6},
4350 {ISD::SIGN_EXTEND, MVT::v16i16, MVT::v16i8, 2},
4351 {ISD::ZERO_EXTEND, MVT::v16i16, MVT::v16i8, 2},
4352 {ISD::SIGN_EXTEND, MVT::v16i32, MVT::v16i8, 6},
4353 {ISD::ZERO_EXTEND, MVT::v16i32, MVT::v16i8, 6},
4354
4355 // FP Ext and trunc
4356 {ISD::FP_EXTEND, MVT::f64, MVT::f32, 1}, // fcvt
4357 {ISD::FP_EXTEND, MVT::v2f64, MVT::v2f32, 1}, // fcvtl
4358 {ISD::FP_EXTEND, MVT::v4f64, MVT::v4f32, 2}, // fcvtl+fcvtl2
4359 // FP16
4360 {ISD::FP_EXTEND, MVT::f32, MVT::f16, 1}, // fcvt
4361 {ISD::FP_EXTEND, MVT::f64, MVT::f16, 1}, // fcvt
4362 {ISD::FP_EXTEND, MVT::v4f32, MVT::v4f16, 1}, // fcvtl
4363 {ISD::FP_EXTEND, MVT::v8f32, MVT::v8f16, 2}, // fcvtl+fcvtl2
4364 {ISD::FP_EXTEND, MVT::v2f64, MVT::v2f16, 2}, // fcvtl+fcvtl
4365 {ISD::FP_EXTEND, MVT::v4f64, MVT::v4f16, 3}, // fcvtl+fcvtl2+fcvtl
4366 {ISD::FP_EXTEND, MVT::v8f64, MVT::v8f16, 6}, // 2 * fcvtl+fcvtl2+fcvtl
4367 // BF16 (uses shift)
4368 {ISD::FP_EXTEND, MVT::f32, MVT::bf16, 1}, // shl
4369 {ISD::FP_EXTEND, MVT::f64, MVT::bf16, 2}, // shl+fcvt
4370 {ISD::FP_EXTEND, MVT::v4f32, MVT::v4bf16, 1}, // shll
4371 {ISD::FP_EXTEND, MVT::v8f32, MVT::v8bf16, 2}, // shll+shll2
4372 {ISD::FP_EXTEND, MVT::v2f64, MVT::v2bf16, 2}, // shll+fcvtl
4373 {ISD::FP_EXTEND, MVT::v4f64, MVT::v4bf16, 3}, // shll+fcvtl+fcvtl2
4374 {ISD::FP_EXTEND, MVT::v8f64, MVT::v8bf16, 6}, // 2 * shll+fcvtl+fcvtl2
4375 // FP Ext and trunc
4376 {ISD::FP_ROUND, MVT::f32, MVT::f64, 1}, // fcvt
4377 {ISD::FP_ROUND, MVT::v2f32, MVT::v2f64, 1}, // fcvtn
4378 {ISD::FP_ROUND, MVT::v4f32, MVT::v4f64, 2}, // fcvtn+fcvtn2
4379 // FP16
4380 {ISD::FP_ROUND, MVT::f16, MVT::f32, 1}, // fcvt
4381 {ISD::FP_ROUND, MVT::f16, MVT::f64, 1}, // fcvt
4382 {ISD::FP_ROUND, MVT::v4f16, MVT::v4f32, 1}, // fcvtn
4383 {ISD::FP_ROUND, MVT::v8f16, MVT::v8f32, 2}, // fcvtn+fcvtn2
4384 {ISD::FP_ROUND, MVT::v2f16, MVT::v2f64, 2}, // fcvtn+fcvtn
4385 {ISD::FP_ROUND, MVT::v4f16, MVT::v4f64, 3}, // fcvtn+fcvtn2+fcvtn
4386 {ISD::FP_ROUND, MVT::v8f16, MVT::v8f64, 6}, // 2 * fcvtn+fcvtn2+fcvtn
4387 // BF16 (more complex, with +bf16 is handled above)
4388 {ISD::FP_ROUND, MVT::bf16, MVT::f32, 8}, // Expansion is ~8 insns
4389 {ISD::FP_ROUND, MVT::bf16, MVT::f64, 9}, // fcvtn + above
4390 {ISD::FP_ROUND, MVT::v2bf16, MVT::v2f32, 8},
4391 {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f32, 8},
4392 {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f32, 15},
4393 {ISD::FP_ROUND, MVT::v2bf16, MVT::v2f64, 9},
4394 {ISD::FP_ROUND, MVT::v4bf16, MVT::v4f64, 10},
4395 {ISD::FP_ROUND, MVT::v8bf16, MVT::v8f64, 19},
4396
4397 // LowerVectorINT_TO_FP:
4398 {ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i32, 1},
4399 {ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i32, 1},
4400 {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i64, 1},
4401 {ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i32, 1},
4402 {ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i32, 1},
4403 {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i64, 1},
4404
4405 // SVE: to nxv2f16
4406 {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i8,
4407 SVE_EXT_COST + SVE_FCVT_COST},
4408 {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i16, SVE_FCVT_COST},
4409 {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i32, SVE_FCVT_COST},
4410 {ISD::SINT_TO_FP, MVT::nxv2f16, MVT::nxv2i64, SVE_FCVT_COST},
4411 {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i8,
4412 SVE_EXT_COST + SVE_FCVT_COST},
4413 {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i16, SVE_FCVT_COST},
4414 {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i32, SVE_FCVT_COST},
4415 {ISD::UINT_TO_FP, MVT::nxv2f16, MVT::nxv2i64, SVE_FCVT_COST},
4416
4417 // SVE: to nxv4f16
4418 {ISD::SINT_TO_FP, MVT::nxv4f16, MVT::nxv4i8,
4419 SVE_EXT_COST + SVE_FCVT_COST},
4420 {ISD::SINT_TO_FP, MVT::nxv4f16, MVT::nxv4i16, SVE_FCVT_COST},
4421 {ISD::SINT_TO_FP, MVT::nxv4f16, MVT::nxv4i32, SVE_FCVT_COST},
4422 {ISD::UINT_TO_FP, MVT::nxv4f16, MVT::nxv4i8,
4423 SVE_EXT_COST + SVE_FCVT_COST},
4424 {ISD::UINT_TO_FP, MVT::nxv4f16, MVT::nxv4i16, SVE_FCVT_COST},
4425 {ISD::UINT_TO_FP, MVT::nxv4f16, MVT::nxv4i32, SVE_FCVT_COST},
4426
4427 // SVE: to nxv8f16
4428 {ISD::SINT_TO_FP, MVT::nxv8f16, MVT::nxv8i8,
4429 SVE_EXT_COST + SVE_FCVT_COST},
4430 {ISD::SINT_TO_FP, MVT::nxv8f16, MVT::nxv8i16, SVE_FCVT_COST},
4431 {ISD::UINT_TO_FP, MVT::nxv8f16, MVT::nxv8i8,
4432 SVE_EXT_COST + SVE_FCVT_COST},
4433 {ISD::UINT_TO_FP, MVT::nxv8f16, MVT::nxv8i16, SVE_FCVT_COST},
4434
4435 // SVE: to nxv16f16
4436 {ISD::SINT_TO_FP, MVT::nxv16f16, MVT::nxv16i8,
4437 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4438 {ISD::UINT_TO_FP, MVT::nxv16f16, MVT::nxv16i8,
4439 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4440
4441 // Complex: to v2f32
4442 {ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i8, 3},
4443 {ISD::SINT_TO_FP, MVT::v2f32, MVT::v2i16, 3},
4444 {ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i8, 3},
4445 {ISD::UINT_TO_FP, MVT::v2f32, MVT::v2i16, 3},
4446
4447 // SVE: to nxv2f32
4448 {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i8,
4449 SVE_EXT_COST + SVE_FCVT_COST},
4450 {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i16, SVE_FCVT_COST},
4451 {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i32, SVE_FCVT_COST},
4452 {ISD::SINT_TO_FP, MVT::nxv2f32, MVT::nxv2i64, SVE_FCVT_COST},
4453 {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i8,
4454 SVE_EXT_COST + SVE_FCVT_COST},
4455 {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i16, SVE_FCVT_COST},
4456 {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i32, SVE_FCVT_COST},
4457 {ISD::UINT_TO_FP, MVT::nxv2f32, MVT::nxv2i64, SVE_FCVT_COST},
4458
4459 // Complex: to v4f32
4460 {ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i8, 4},
4461 {ISD::SINT_TO_FP, MVT::v4f32, MVT::v4i16, 2},
4462 {ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i8, 3},
4463 {ISD::UINT_TO_FP, MVT::v4f32, MVT::v4i16, 2},
4464
4465 // SVE: to nxv4f32
4466 {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i8,
4467 SVE_EXT_COST + SVE_FCVT_COST},
4468 {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i16, SVE_FCVT_COST},
4469 {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i32, SVE_FCVT_COST},
4470 {ISD::UINT_TO_FP, MVT::nxv4f32, MVT::nxv4i8,
4471 SVE_EXT_COST + SVE_FCVT_COST},
4472 {ISD::UINT_TO_FP, MVT::nxv4f32, MVT::nxv4i16, SVE_FCVT_COST},
4473 {ISD::SINT_TO_FP, MVT::nxv4f32, MVT::nxv4i32, SVE_FCVT_COST},
4474
4475 // Complex: to v8f32
4476 {ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i8, 10},
4477 {ISD::SINT_TO_FP, MVT::v8f32, MVT::v8i16, 4},
4478 {ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i8, 10},
4479 {ISD::UINT_TO_FP, MVT::v8f32, MVT::v8i16, 4},
4480
4481 // SVE: to nxv8f32
4482 {ISD::SINT_TO_FP, MVT::nxv8f32, MVT::nxv8i8,
4483 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4484 {ISD::SINT_TO_FP, MVT::nxv8f32, MVT::nxv8i16,
4485 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4486 {ISD::UINT_TO_FP, MVT::nxv8f32, MVT::nxv8i8,
4487 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4488 {ISD::UINT_TO_FP, MVT::nxv8f32, MVT::nxv8i16,
4489 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4490
4491 // SVE: to nxv16f32
4492 {ISD::SINT_TO_FP, MVT::nxv16f32, MVT::nxv16i8,
4493 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4494 {ISD::UINT_TO_FP, MVT::nxv16f32, MVT::nxv16i8,
4495 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4496
4497 // Complex: to v16f32
4498 {ISD::SINT_TO_FP, MVT::v16f32, MVT::v16i8, 21},
4499 {ISD::UINT_TO_FP, MVT::v16f32, MVT::v16i8, 21},
4500
4501 // Complex: to v2f64
4502 {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i8, 4},
4503 {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i16, 4},
4504 {ISD::SINT_TO_FP, MVT::v2f64, MVT::v2i32, 2},
4505 {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i8, 4},
4506 {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i16, 4},
4507 {ISD::UINT_TO_FP, MVT::v2f64, MVT::v2i32, 2},
4508
4509 // SVE: to nxv2f64
4510 {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i8,
4511 SVE_EXT_COST + SVE_FCVT_COST},
4512 {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i16, SVE_FCVT_COST},
4513 {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i32, SVE_FCVT_COST},
4514 {ISD::SINT_TO_FP, MVT::nxv2f64, MVT::nxv2i64, SVE_FCVT_COST},
4515 {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i8,
4516 SVE_EXT_COST + SVE_FCVT_COST},
4517 {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i16, SVE_FCVT_COST},
4518 {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i32, SVE_FCVT_COST},
4519 {ISD::UINT_TO_FP, MVT::nxv2f64, MVT::nxv2i64, SVE_FCVT_COST},
4520
4521 // Complex: to v4f64
4522 {ISD::SINT_TO_FP, MVT::v4f64, MVT::v4i32, 4},
4523 {ISD::UINT_TO_FP, MVT::v4f64, MVT::v4i32, 4},
4524
4525 // SVE: to nxv4f64
4526 {ISD::SINT_TO_FP, MVT::nxv4f64, MVT::nxv4i8,
4527 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4528 {ISD::SINT_TO_FP, MVT::nxv4f64, MVT::nxv4i16,
4529 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4530 {ISD::SINT_TO_FP, MVT::nxv4f64, MVT::nxv4i32,
4531 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4532 {ISD::UINT_TO_FP, MVT::nxv4f64, MVT::nxv4i8,
4533 SVE_EXT_COST + SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4534 {ISD::UINT_TO_FP, MVT::nxv4f64, MVT::nxv4i16,
4535 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4536 {ISD::UINT_TO_FP, MVT::nxv4f64, MVT::nxv4i32,
4537 SVE_UNPACK_ONCE + 2 * SVE_FCVT_COST},
4538
4539 // SVE: to nxv8f64
4540 {ISD::SINT_TO_FP, MVT::nxv8f64, MVT::nxv8i8,
4541 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4542 {ISD::SINT_TO_FP, MVT::nxv8f64, MVT::nxv8i16,
4543 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4544 {ISD::UINT_TO_FP, MVT::nxv8f64, MVT::nxv8i8,
4545 SVE_EXT_COST + SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4546 {ISD::UINT_TO_FP, MVT::nxv8f64, MVT::nxv8i16,
4547 SVE_UNPACK_TWICE + 4 * SVE_FCVT_COST},
4548
4549 // LowerVectorFP_TO_INT
4550 {ISD::FP_TO_SINT, MVT::v2i32, MVT::v2f32, 1},
4551 {ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f32, 1},
4552 {ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f64, 1},
4553 {ISD::FP_TO_UINT, MVT::v2i32, MVT::v2f32, 1},
4554 {ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f32, 1},
4555 {ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f64, 1},
4556
4557 // Complex, from v2f32: legal type is v2i32 (no cost) or v2i64 (1 ext).
4558 {ISD::FP_TO_SINT, MVT::v2i64, MVT::v2f32, 2},
4559 {ISD::FP_TO_SINT, MVT::v2i16, MVT::v2f32, 1},
4560 {ISD::FP_TO_SINT, MVT::v2i8, MVT::v2f32, 1},
4561 {ISD::FP_TO_UINT, MVT::v2i64, MVT::v2f32, 2},
4562 {ISD::FP_TO_UINT, MVT::v2i16, MVT::v2f32, 1},
4563 {ISD::FP_TO_UINT, MVT::v2i8, MVT::v2f32, 1},
4564
4565 // Complex, from v4f32: legal type is v4i16, 1 narrowing => ~2
4566 {ISD::FP_TO_SINT, MVT::v4i16, MVT::v4f32, 2},
4567 {ISD::FP_TO_SINT, MVT::v4i8, MVT::v4f32, 2},
4568 {ISD::FP_TO_UINT, MVT::v4i16, MVT::v4f32, 2},
4569 {ISD::FP_TO_UINT, MVT::v4i8, MVT::v4f32, 2},
4570
4571 // Complex, from v2f64: legal type is v2i32, 1 narrowing => ~2.
4572 {ISD::FP_TO_SINT, MVT::v2i32, MVT::v2f64, 2},
4573 {ISD::FP_TO_SINT, MVT::v2i16, MVT::v2f64, 2},
4574 {ISD::FP_TO_SINT, MVT::v2i8, MVT::v2f64, 2},
4575 {ISD::FP_TO_UINT, MVT::v2i32, MVT::v2f64, 2},
4576 {ISD::FP_TO_UINT, MVT::v2i16, MVT::v2f64, 2},
4577 {ISD::FP_TO_UINT, MVT::v2i8, MVT::v2f64, 2},
4578
4579 // Complex, from nxv2f32.
4580 {ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f32, 1},
4581 {ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f32, 1},
4582 {ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f32, 1},
4583 {ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f32, 1},
4584 {ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f32, 1},
4585 {ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f32, 1},
4586 {ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f32, 1},
4587 {ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f32, 1},
4588
4589 // Complex, from nxv2f64.
4590 {ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f64, 1},
4591 {ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f64, 1},
4592 {ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f64, 1},
4593 {ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f64, 1},
4594 {ISD::FP_TO_SINT, MVT::nxv2i1, MVT::nxv2f64, 1},
4595 {ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f64, 1},
4596 {ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f64, 1},
4597 {ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f64, 1},
4598 {ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f64, 1},
4599 {ISD::FP_TO_UINT, MVT::nxv2i1, MVT::nxv2f64, 1},
4600
4601 // Complex, from nxv4f32.
4602 {ISD::FP_TO_SINT, MVT::nxv4i64, MVT::nxv4f32, 4},
4603 {ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f32, 1},
4604 {ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f32, 1},
4605 {ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f32, 1},
4606 {ISD::FP_TO_SINT, MVT::nxv4i1, MVT::nxv4f32, 1},
4607 {ISD::FP_TO_UINT, MVT::nxv4i64, MVT::nxv4f32, 4},
4608 {ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f32, 1},
4609 {ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f32, 1},
4610 {ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f32, 1},
4611 {ISD::FP_TO_UINT, MVT::nxv4i1, MVT::nxv4f32, 1},
4612
4613 // Complex, from nxv8f64. Illegal -> illegal conversions not required.
4614 {ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f64, 7},
4615 {ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f64, 7},
4616 {ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f64, 7},
4617 {ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f64, 7},
4618
4619 // Complex, from nxv4f64. Illegal -> illegal conversions not required.
4620 {ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f64, 3},
4621 {ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f64, 3},
4622 {ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f64, 3},
4623 {ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f64, 3},
4624 {ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f64, 3},
4625 {ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f64, 3},
4626
4627 // Complex, from nxv8f32. Illegal -> illegal conversions not required.
4628 {ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f32, 3},
4629 {ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f32, 3},
4630 {ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f32, 3},
4631 {ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f32, 3},
4632
4633 // Complex, from nxv8f16.
4634 {ISD::FP_TO_SINT, MVT::nxv8i64, MVT::nxv8f16, 10},
4635 {ISD::FP_TO_SINT, MVT::nxv8i32, MVT::nxv8f16, 4},
4636 {ISD::FP_TO_SINT, MVT::nxv8i16, MVT::nxv8f16, 1},
4637 {ISD::FP_TO_SINT, MVT::nxv8i8, MVT::nxv8f16, 1},
4638 {ISD::FP_TO_SINT, MVT::nxv8i1, MVT::nxv8f16, 1},
4639 {ISD::FP_TO_UINT, MVT::nxv8i64, MVT::nxv8f16, 10},
4640 {ISD::FP_TO_UINT, MVT::nxv8i32, MVT::nxv8f16, 4},
4641 {ISD::FP_TO_UINT, MVT::nxv8i16, MVT::nxv8f16, 1},
4642 {ISD::FP_TO_UINT, MVT::nxv8i8, MVT::nxv8f16, 1},
4643 {ISD::FP_TO_UINT, MVT::nxv8i1, MVT::nxv8f16, 1},
4644
4645 // Complex, from nxv4f16.
4646 {ISD::FP_TO_SINT, MVT::nxv4i64, MVT::nxv4f16, 4},
4647 {ISD::FP_TO_SINT, MVT::nxv4i32, MVT::nxv4f16, 1},
4648 {ISD::FP_TO_SINT, MVT::nxv4i16, MVT::nxv4f16, 1},
4649 {ISD::FP_TO_SINT, MVT::nxv4i8, MVT::nxv4f16, 1},
4650 {ISD::FP_TO_UINT, MVT::nxv4i64, MVT::nxv4f16, 4},
4651 {ISD::FP_TO_UINT, MVT::nxv4i32, MVT::nxv4f16, 1},
4652 {ISD::FP_TO_UINT, MVT::nxv4i16, MVT::nxv4f16, 1},
4653 {ISD::FP_TO_UINT, MVT::nxv4i8, MVT::nxv4f16, 1},
4654
4655 // Complex, from nxv2f16.
4656 {ISD::FP_TO_SINT, MVT::nxv2i64, MVT::nxv2f16, 1},
4657 {ISD::FP_TO_SINT, MVT::nxv2i32, MVT::nxv2f16, 1},
4658 {ISD::FP_TO_SINT, MVT::nxv2i16, MVT::nxv2f16, 1},
4659 {ISD::FP_TO_SINT, MVT::nxv2i8, MVT::nxv2f16, 1},
4660 {ISD::FP_TO_UINT, MVT::nxv2i64, MVT::nxv2f16, 1},
4661 {ISD::FP_TO_UINT, MVT::nxv2i32, MVT::nxv2f16, 1},
4662 {ISD::FP_TO_UINT, MVT::nxv2i16, MVT::nxv2f16, 1},
4663 {ISD::FP_TO_UINT, MVT::nxv2i8, MVT::nxv2f16, 1},
4664
4665 // Truncate from nxvmf32 to nxvmf16.
4666 {ISD::FP_ROUND, MVT::nxv2f16, MVT::nxv2f32, 1},
4667 {ISD::FP_ROUND, MVT::nxv4f16, MVT::nxv4f32, 1},
4668 {ISD::FP_ROUND, MVT::nxv8f16, MVT::nxv8f32, 3},
4669
4670 // Truncate from nxvmf32 to nxvmbf16.
4671 {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f32, 8},
4672 {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f32, 8},
4673 {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f32, 17},
4674
4675 // Truncate from nxvmf64 to nxvmf16.
4676 {ISD::FP_ROUND, MVT::nxv2f16, MVT::nxv2f64, 1},
4677 {ISD::FP_ROUND, MVT::nxv4f16, MVT::nxv4f64, 3},
4678 {ISD::FP_ROUND, MVT::nxv8f16, MVT::nxv8f64, 7},
4679
4680 // Truncate from nxvmf64 to nxvmbf16.
4681 {ISD::FP_ROUND, MVT::nxv2bf16, MVT::nxv2f64, 9},
4682 {ISD::FP_ROUND, MVT::nxv4bf16, MVT::nxv4f64, 19},
4683 {ISD::FP_ROUND, MVT::nxv8bf16, MVT::nxv8f64, 39},
4684
4685 // Truncate from nxvmf64 to nxvmf32.
4686 {ISD::FP_ROUND, MVT::nxv2f32, MVT::nxv2f64, 1},
4687 {ISD::FP_ROUND, MVT::nxv4f32, MVT::nxv4f64, 3},
4688 {ISD::FP_ROUND, MVT::nxv8f32, MVT::nxv8f64, 6},
4689
4690 // Extend from nxvmf16 to nxvmf32.
4691 {ISD::FP_EXTEND, MVT::nxv2f32, MVT::nxv2f16, 1},
4692 {ISD::FP_EXTEND, MVT::nxv4f32, MVT::nxv4f16, 1},
4693 {ISD::FP_EXTEND, MVT::nxv8f32, MVT::nxv8f16, 2},
4694
4695 // Extend from nxvmbf16 to nxvmf32.
4696 {ISD::FP_EXTEND, MVT::nxv2f32, MVT::nxv2bf16, 1}, // lsl
4697 {ISD::FP_EXTEND, MVT::nxv4f32, MVT::nxv4bf16, 1}, // lsl
4698 {ISD::FP_EXTEND, MVT::nxv8f32, MVT::nxv8bf16, 4}, // unpck+unpck+lsl+lsl
4699
4700 // Extend from nxvmf16 to nxvmf64.
4701 {ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2f16, 1},
4702 {ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4f16, 2},
4703 {ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8f16, 4},
4704
4705 // Extend from nxvmbf16 to nxvmf64.
4706 {ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2bf16, 2}, // lsl+fcvt
4707 {ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4bf16, 6}, // 2*unpck+2*lsl+2*fcvt
4708 {ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8bf16, 14}, // 6*unpck+4*lsl+4*fcvt
4709
4710 // Extend from nxvmf32 to nxvmf64.
4711 {ISD::FP_EXTEND, MVT::nxv2f64, MVT::nxv2f32, 1},
4712 {ISD::FP_EXTEND, MVT::nxv4f64, MVT::nxv4f32, 2},
4713 {ISD::FP_EXTEND, MVT::nxv8f64, MVT::nxv8f32, 6},
4714
4715 // Add cost for extending to illegal -too wide- scalable vectors.
4716 // zero/sign extend are implemented by multiple unpack operations,
4717 // where each operation has a cost of 1.
4718 {ISD::ZERO_EXTEND, MVT::nxv16i16, MVT::nxv16i8, 2},
4719 {ISD::ZERO_EXTEND, MVT::nxv16i32, MVT::nxv16i8, 6},
4720 {ISD::ZERO_EXTEND, MVT::nxv16i64, MVT::nxv16i8, 14},
4721 {ISD::ZERO_EXTEND, MVT::nxv8i32, MVT::nxv8i16, 2},
4722 {ISD::ZERO_EXTEND, MVT::nxv8i64, MVT::nxv8i16, 6},
4723 {ISD::ZERO_EXTEND, MVT::nxv4i64, MVT::nxv4i32, 2},
4724
4725 {ISD::SIGN_EXTEND, MVT::nxv16i16, MVT::nxv16i8, 2},
4726 {ISD::SIGN_EXTEND, MVT::nxv16i32, MVT::nxv16i8, 6},
4727 {ISD::SIGN_EXTEND, MVT::nxv16i64, MVT::nxv16i8, 14},
4728 {ISD::SIGN_EXTEND, MVT::nxv8i32, MVT::nxv8i16, 2},
4729 {ISD::SIGN_EXTEND, MVT::nxv8i64, MVT::nxv8i16, 6},
4730 {ISD::SIGN_EXTEND, MVT::nxv4i64, MVT::nxv4i32, 2},
4731 };
4732
4733 if (const auto *Entry = ConvertCostTableLookup(
4734 ConversionTbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()))
4735 return Entry->Cost;
4736
4737 static const TypeConversionCostTblEntry FP16Tbl[] = {
4738 {ISD::FP_TO_SINT, MVT::v4i8, MVT::v4f16, 1}, // fcvtzs
4739 {ISD::FP_TO_UINT, MVT::v4i8, MVT::v4f16, 1},
4740 {ISD::FP_TO_SINT, MVT::v4i16, MVT::v4f16, 1}, // fcvtzs
4741 {ISD::FP_TO_UINT, MVT::v4i16, MVT::v4f16, 1},
4742 {ISD::FP_TO_SINT, MVT::v4i32, MVT::v4f16, 2}, // fcvtl+fcvtzs
4743 {ISD::FP_TO_UINT, MVT::v4i32, MVT::v4f16, 2},
4744 {ISD::FP_TO_SINT, MVT::v8i8, MVT::v8f16, 2}, // fcvtzs+xtn
4745 {ISD::FP_TO_UINT, MVT::v8i8, MVT::v8f16, 2},
4746 {ISD::FP_TO_SINT, MVT::v8i16, MVT::v8f16, 1}, // fcvtzs
4747 {ISD::FP_TO_UINT, MVT::v8i16, MVT::v8f16, 1},
4748 {ISD::FP_TO_SINT, MVT::v8i32, MVT::v8f16, 4}, // 2*fcvtl+2*fcvtzs
4749 {ISD::FP_TO_UINT, MVT::v8i32, MVT::v8f16, 4},
4750 {ISD::FP_TO_SINT, MVT::v16i8, MVT::v16f16, 3}, // 2*fcvtzs+xtn
4751 {ISD::FP_TO_UINT, MVT::v16i8, MVT::v16f16, 3},
4752 {ISD::FP_TO_SINT, MVT::v16i16, MVT::v16f16, 2}, // 2*fcvtzs
4753 {ISD::FP_TO_UINT, MVT::v16i16, MVT::v16f16, 2},
4754 {ISD::FP_TO_SINT, MVT::v16i32, MVT::v16f16, 8}, // 4*fcvtl+4*fcvtzs
4755 {ISD::FP_TO_UINT, MVT::v16i32, MVT::v16f16, 8},
4756 {ISD::UINT_TO_FP, MVT::v8f16, MVT::v8i8, 2}, // ushll + ucvtf
4757 {ISD::SINT_TO_FP, MVT::v8f16, MVT::v8i8, 2}, // sshll + scvtf
4758 {ISD::UINT_TO_FP, MVT::v16f16, MVT::v16i8, 4}, // 2 * ushl(2) + 2 * ucvtf
4759 {ISD::SINT_TO_FP, MVT::v16f16, MVT::v16i8, 4}, // 2 * sshl(2) + 2 * scvtf
4760 };
4761
4762 if (ST->hasFullFP16())
4763 if (const auto *Entry = ConvertCostTableLookup(
4764 FP16Tbl, ISD, DstTy.getSimpleVT(), SrcTy.getSimpleVT()))
4765 return Entry->Cost;
4766
4767 // INT_TO_FP of i64->f32 will scalarize, which is required to avoid
4768 // double-rounding issues.
4769 if ((ISD == ISD::SINT_TO_FP || ISD == ISD::UINT_TO_FP) &&
4770 DstTy.getScalarType() == MVT::f32 && SrcTy.getScalarSizeInBits() > 32 &&
4772 return cast<FixedVectorType>(Dst)->getNumElements() *
4773 getCastInstrCost(Opcode, Dst->getScalarType(),
4774 Src->getScalarType(), CCH, CostKind) +
4776 true, CostKind) +
4778 false, CostKind);
4779
4780 if ((ISD == ISD::ZERO_EXTEND || ISD == ISD::SIGN_EXTEND) &&
4782 ST->isSVEorStreamingSVEAvailable() &&
4783 TLI->getTypeAction(Src->getContext(), SrcTy) ==
4785 TLI->getTypeAction(Dst->getContext(), DstTy) ==
4787 // The standard behaviour in the backend for these cases is to split the
4788 // extend up into two parts:
4789 // 1. Perform an extending load or masked load up to the legal type.
4790 // 2. Extend the loaded data to the final type.
4791 std::pair<InstructionCost, MVT> SrcLT = getTypeLegalizationCost(Src);
4792 Type *LegalTy = EVT(SrcLT.second).getTypeForEVT(Src->getContext());
4794 Opcode, LegalTy, Src, CCH, CostKind, I);
4796 Opcode, Dst, LegalTy, TTI::CastContextHint::None, CostKind, I);
4797 return Part1 + Part2;
4798 }
4799
4800 // The BasicTTIImpl version only deals with CCH==TTI::CastContextHint::Normal,
4801 // but we also want to include the TTI::CastContextHint::Masked case too.
4802 if ((ISD == ISD::ZERO_EXTEND || ISD == ISD::SIGN_EXTEND) &&
4804 ST->isSVEorStreamingSVEAvailable() && TLI->isTypeLegal(DstTy))
4806
4807 return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I);
4808}
4809
4812 VectorType *VecTy, unsigned Index,
4813 TTI::TargetCostKind CostKind) const {
4814
4815 // Make sure we were given a valid extend opcode.
4816 assert((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
4817 "Invalid opcode");
4818
4819 // We are extending an element we extract from a vector, so the source type
4820 // of the extend is the element type of the vector.
4821 auto *Src = VecTy->getElementType();
4822
4823 // Sign- and zero-extends are for integer types only.
4824 assert(isa<IntegerType>(Dst) && isa<IntegerType>(Src) && "Invalid type");
4825
4826 // Get the cost for the extract. We compute the cost (if any) for the extend
4827 // below.
4828 InstructionCost Cost = getVectorInstrCost(Instruction::ExtractElement, VecTy,
4829 CostKind, Index, nullptr, nullptr);
4830
4831 // Legalize the types.
4832 auto VecLT = getTypeLegalizationCost(VecTy);
4833 auto DstVT = TLI->getValueType(DL, Dst);
4834 auto SrcVT = TLI->getValueType(DL, Src);
4835
4836 // If the resulting type is still a vector and the destination type is legal,
4837 // we may get the extension for free. If not, get the default cost for the
4838 // extend.
4839 if (!VecLT.second.isVector() || !TLI->isTypeLegal(DstVT))
4840 return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None,
4841 CostKind);
4842
4843 // The destination type should be larger than the element type. If not, get
4844 // the default cost for the extend.
4845 if (DstVT.getFixedSizeInBits() < SrcVT.getFixedSizeInBits())
4846 return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None,
4847 CostKind);
4848
4849 switch (Opcode) {
4850 default:
4851 llvm_unreachable("Opcode should be either SExt or ZExt");
4852
4853 // For sign-extends, we only need a smov, which performs the extension
4854 // automatically.
4855 case Instruction::SExt:
4856 return Cost;
4857
4858 // For zero-extends, the extend is performed automatically by a umov unless
4859 // the destination type is i64 and the element type is i8 or i16.
4860 case Instruction::ZExt:
4861 if (DstVT.getSizeInBits() != 64u || SrcVT.getSizeInBits() == 32u)
4862 return Cost;
4863 }
4864
4865 // If we are unable to perform the extend for free, get the default cost.
4866 return Cost + getCastInstrCost(Opcode, Dst, Src, TTI::CastContextHint::None,
4867 CostKind);
4868}
4869
4871 TTI::TargetCostKind CostKind,
4872 const Instruction *I) const {
4873 if (CostKind != TTI::TCK_RecipThroughput)
4874 return Opcode == Instruction::PHI ? 0 : 1;
4875 assert(CostKind == TTI::TCK_RecipThroughput && "unexpected CostKind");
4876 // Branches are assumed to be predicted.
4877 return 0;
4878}
4879
4880InstructionCost AArch64TTIImpl::getVectorInstrCostHelper(
4881 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index,
4882 const Instruction *I, Value *Scalar,
4883 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
4884 TTI::VectorInstrContext VIC) const {
4885 assert(Ty->isVectorTy() && "This must be a vector type");
4886
4887 if (Index != -1U) {
4888 // Legalize the type.
4889 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
4890
4891 // This type is legalized to a scalar type.
4892 if (!LT.second.isVector())
4893 return 0;
4894
4895 // The type may be split. For fixed-width vectors we can normalize the
4896 // index to the new type.
4897 if (LT.second.isFixedLengthVector()) {
4898 unsigned Width = LT.second.getVectorNumElements();
4899 Index = Index % Width;
4900 }
4901
4902 // The element at index zero is already inside the vector.
4903 // - For a insert-element or extract-element
4904 // instruction that extracts integers, an explicit FPR -> GPR move is
4905 // needed. So it has non-zero cost.
4906 if (Index == 0 && !Ty->getScalarType()->isIntegerTy())
4907 return 0;
4908
4909 // SVE has no scalar move to an arbitrary lane above the low 128-bit portion
4910 // of a Z register, e.g. there is no equivalent of "mov z0.d[9], d0".
4911 // Fixed-length vectors wider than 128 bits therefore need
4912 // [splice]/index/pred/splat/cmp/pred-mov when scalarizing inserts for those
4913 // lanes, so model them as more expensive than ordinary NEON lane accesses.
4914 if (ST->useSVEForFixedLengthVectors()) {
4915 InstructionCost Cost = CostKind == TTI::TCK_CodeSize
4916 ? 1
4918 if (Index * Ty->getScalarSizeInBits() < 128)
4919 return Cost;
4920 if (Index * Ty->getScalarSizeInBits() < 512 &&
4921 Opcode == Instruction::ExtractElement)
4922 // Integer extracts (>128b, <512b) require extra mov from FPR -> GPR.
4923 return Ty->getScalarType()->isIntegerTy() ? Cost + 1 : Cost;
4924 if (Opcode == Instruction::ExtractElement)
4925 return Cost + 2; // cost of mov imm + whilels + lastb
4926 if (Opcode == Instruction::InsertElement)
4927 return Cost + 3; // cost of insert with cmp/splice
4928 llvm_unreachable("unexpected opcode");
4929 }
4930
4931 // This is recognising a LD1 single-element structure to one lane of one
4932 // register instruction. I.e., if this is an `insertelement` instruction,
4933 // and its second operand is a load, then we will generate a LD1, which
4934 // are expensive instructions on some uArchs.
4935 if (VIC == TTI::VectorInstrContext::Load) {
4936 if (ST->hasFastLD1Single())
4937 return 0;
4938 return CostKind == TTI::TCK_CodeSize
4939 ? 0
4940 : ST->getVectorInsertExtractBaseCost() + 1;
4941 }
4942
4943 // i1 inserts and extract will include an extra cset or cmp of the vector
4944 // value. Increase the cost by 1 to account.
4945 if (Ty->getScalarSizeInBits() == 1)
4946 return CostKind == TTI::TCK_CodeSize
4947 ? 2
4948 : ST->getVectorInsertExtractBaseCost() + 1;
4949
4950 // FIXME:
4951 // If the extract-element and insert-element instructions could be
4952 // simplified away (e.g., could be combined into users by looking at use-def
4953 // context), they have no cost. This is not done in the first place for
4954 // compile-time considerations.
4955 }
4956
4957 // In case of Neon, if there exists extractelement from lane != 0 such that
4958 // 1. extractelement does not necessitate a move from vector_reg -> GPR.
4959 // 2. extractelement result feeds into fmul.
4960 // 3. Other operand of fmul is an extractelement from lane 0 or lane
4961 // equivalent to 0.
4962 // then the extractelement can be merged with fmul in the backend and it
4963 // incurs no cost.
4964 // e.g.
4965 // define double @foo(<2 x double> %a) {
4966 // %1 = extractelement <2 x double> %a, i32 0
4967 // %2 = extractelement <2 x double> %a, i32 1
4968 // %res = fmul double %1, %2
4969 // ret double %res
4970 // }
4971 // %2 and %res can be merged in the backend to generate fmul d0, d0, v1.d[1]
4972 auto ExtractCanFuseWithFmul = [&]() {
4973 // We bail out if the extract is from lane 0.
4974 if (Index == 0)
4975 return false;
4976
4977 // Check if the scalar element type of the vector operand of ExtractElement
4978 // instruction is one of the allowed types.
4979 auto IsAllowedScalarTy = [&](const Type *T) {
4980 return T->isFloatTy() || T->isDoubleTy() ||
4981 (T->isHalfTy() && ST->hasFullFP16());
4982 };
4983
4984 // Check if the extractelement user is scalar fmul.
4985 auto IsUserFMulScalarTy = [](const Value *EEUser) {
4986 // Check if the user is scalar fmul.
4987 const auto *BO = dyn_cast<BinaryOperator>(EEUser);
4988 return BO && BO->getOpcode() == BinaryOperator::FMul &&
4989 !BO->getType()->isVectorTy();
4990 };
4991
4992 // Check if the extract index is from lane 0 or lane equivalent to 0 for a
4993 // certain scalar type and a certain vector register width.
4994 auto IsExtractLaneEquivalentToZero = [&](unsigned Idx, unsigned EltSz) {
4995 auto RegWidth =
4997 .getFixedValue();
4998 return Idx == 0 || (RegWidth != 0 && (Idx * EltSz) % RegWidth == 0);
4999 };
5000
5001 // Check if the type constraints on input vector type and result scalar type
5002 // of extractelement instruction are satisfied.
5003 if (!isa<FixedVectorType>(Ty) || !IsAllowedScalarTy(Ty->getScalarType()))
5004 return false;
5005
5006 if (Scalar) {
5007 DenseMap<User *, unsigned> UserToExtractIdx;
5008 for (auto *U : Scalar->users()) {
5009 if (!IsUserFMulScalarTy(U))
5010 return false;
5011 // Recording entry for the user is important. Index value is not
5012 // important.
5013 UserToExtractIdx[U];
5014 }
5015 if (UserToExtractIdx.empty())
5016 return false;
5017 for (auto &[S, U, L] : ScalarUserAndIdx) {
5018 for (auto *U : S->users()) {
5019 if (UserToExtractIdx.contains(U)) {
5020 auto *FMul = cast<BinaryOperator>(U);
5021 auto *Op0 = FMul->getOperand(0);
5022 auto *Op1 = FMul->getOperand(1);
5023 if ((Op0 == S && Op1 == S) || Op0 != S || Op1 != S) {
5024 UserToExtractIdx[U] = L;
5025 break;
5026 }
5027 }
5028 }
5029 }
5030 for (auto &[U, L] : UserToExtractIdx) {
5031 if (!IsExtractLaneEquivalentToZero(Index, Ty->getScalarSizeInBits()) &&
5032 !IsExtractLaneEquivalentToZero(L, Ty->getScalarSizeInBits()))
5033 return false;
5034 }
5035 } else {
5036 const auto *EE = cast<ExtractElementInst>(I);
5037
5038 const auto *IdxOp = dyn_cast<ConstantInt>(EE->getIndexOperand());
5039 if (!IdxOp)
5040 return false;
5041
5042 return !EE->users().empty() && all_of(EE->users(), [&](const User *U) {
5043 if (!IsUserFMulScalarTy(U))
5044 return false;
5045
5046 // Check if the other operand of extractelement is also extractelement
5047 // from lane equivalent to 0.
5048 const auto *BO = cast<BinaryOperator>(U);
5049 const auto *OtherEE = dyn_cast<ExtractElementInst>(
5050 BO->getOperand(0) == EE ? BO->getOperand(1) : BO->getOperand(0));
5051 if (OtherEE) {
5052 const auto *IdxOp = dyn_cast<ConstantInt>(OtherEE->getIndexOperand());
5053 if (!IdxOp)
5054 return false;
5055 return IsExtractLaneEquivalentToZero(
5056 cast<ConstantInt>(OtherEE->getIndexOperand())
5057 ->getValue()
5058 .getZExtValue(),
5059 OtherEE->getType()->getScalarSizeInBits());
5060 }
5061 return true;
5062 });
5063 }
5064 return true;
5065 };
5066
5067 if (Opcode == Instruction::ExtractElement && (I || Scalar) &&
5068 ExtractCanFuseWithFmul())
5069 return 0;
5070
5071 // All other insert/extracts cost this much.
5072 return CostKind == TTI::TCK_CodeSize ? 1
5073 : ST->getVectorInsertExtractBaseCost();
5074}
5075
5077 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index,
5078 const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC) const {
5079 // Treat insert at lane 0 into a poison vector as having zero cost. This
5080 // ensures vector broadcasts via an insert + shuffle (and will be lowered to a
5081 // single dup) are treated as cheap.
5082 if (Opcode == Instruction::InsertElement && Index == 0 && Op0 &&
5083 isa<PoisonValue>(Op0))
5084 return 0;
5085 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index, nullptr, nullptr,
5086 {}, VIC);
5087}
5088
5090 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, unsigned Index,
5091 Value *Scalar, ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx,
5092 TTI::VectorInstrContext VIC) const {
5093 return getVectorInstrCostHelper(Opcode, Ty, CostKind, Index, nullptr, Scalar,
5094 ScalarUserAndIdx, VIC);
5095}
5096
5099 TTI::TargetCostKind CostKind, unsigned Index,
5100 TTI::VectorInstrContext VIC) const {
5101 return getVectorInstrCostHelper(I.getOpcode(), Ty, CostKind, Index, &I,
5102 nullptr, {}, VIC);
5103}
5104
5107 TTI::TargetCostKind CostKind,
5108 unsigned Index) const {
5109 if (isa<FixedVectorType>(Ty))
5110 return BaseT::getIndexedVectorInstrCostFromEnd(Opcode, Ty, CostKind, Index);
5111
5112 // This typically requires both while and lastb instructions in order
5113 // to extract the last element. If this is in a loop the while
5114 // instruction can at least be hoisted out, although it will consume a
5115 // predicate register. The cost should be more expensive than the base
5116 // extract cost, which is 2 for most CPUs.
5117 return CostKind == TTI::TCK_CodeSize
5118 ? 2
5119 : ST->getVectorInsertExtractBaseCost() + 1;
5120}
5121
5123 VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract,
5124 TTI::TargetCostKind CostKind, bool ForPoisonSrc, ArrayRef<Value *> VL,
5125 TTI::VectorInstrContext VIC) const {
5128
5129 // There's no scalarization overhead if ld1/st1 is cheap and the
5130 // insert/extracts can be folded into the load/stores.
5131 if (ST->hasFastLD1Single()) {
5132 if ((VIC == TTI::VectorInstrContext::Store && Extract) ||
5133 (VIC == TTI::VectorInstrContext::Load && Insert))
5134 return 0;
5135 }
5136
5137 if (Ty->getElementType()->isFloatingPointTy())
5138 return BaseT::getScalarizationOverhead(Ty, DemandedElts, Insert, Extract,
5139 CostKind);
5140 unsigned VecInstCost =
5141 CostKind == TTI::TCK_CodeSize ? 1 : ST->getVectorInsertExtractBaseCost();
5142 return DemandedElts.popcount() * (Insert + Extract) * VecInstCost;
5143}
5144
5145std::optional<InstructionCost> AArch64TTIImpl::getFP16BF16PromoteCost(
5146 Type *Ty, TTI::TargetCostKind CostKind, TTI::OperandValueInfo Op1Info,
5147 TTI::OperandValueInfo Op2Info, bool IncludeTrunc, bool CanUseSVE,
5148 std::function<InstructionCost(Type *)> InstCost) const {
5149 if (!Ty->getScalarType()->isHalfTy() && !Ty->getScalarType()->isBFloatTy())
5150 return std::nullopt;
5151 if (Ty->getScalarType()->isHalfTy() && ST->hasFullFP16())
5152 return std::nullopt;
5153 // If we have +sve-b16b16 the operation can be promoted to SVE.
5154 if (CanUseSVE && ST->hasSVEB16B16() && ST->isNonStreamingSVEorSME2Available())
5155 return std::nullopt;
5156
5157 Type *PromotedTy = Ty->getWithNewType(Type::getFloatTy(Ty->getContext()));
5158 InstructionCost Cost = getCastInstrCost(Instruction::FPExt, PromotedTy, Ty,
5159 TTI::CastContextHint::None, CostKind);
5160 if (!Op1Info.isConstant() && !Op2Info.isConstant())
5161 Cost *= 2;
5162 Cost += InstCost(PromotedTy);
5163 if (IncludeTrunc)
5164 Cost += getCastInstrCost(Instruction::FPTrunc, Ty, PromotedTy,
5165 TTI::CastContextHint::None, CostKind);
5166 return Cost;
5167}
5168
5170 unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind,
5172 ArrayRef<const Value *> Args, const Instruction *CtxI) const {
5173
5174 // The code-generator is currently not able to handle scalable vectors
5175 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
5176 // it until all instructions are vetted.
5177 int ISD = TLI->InstructionOpcodeToISD(Opcode);
5178 if (auto *VTy = dyn_cast<ScalableVectorType>(Ty))
5179 if (VTy->getElementCount() == ElementCount::getScalable(1))
5182
5183 if (CtxI && CtxI->getOpcode() == Opcode && !CtxI->use_empty() &&
5184 useNeonVector(Ty)) {
5185 // The Ands of a bit select are folded into the BSL that the Or becomes.
5186 Instruction *MainAnd, *OtherAnd;
5187 Value *A, *B;
5188 if (Opcode == Instruction::And && CtxI->hasOneUse() &&
5189 matchBSL(CtxI->user_back(), MainAnd, OtherAnd, A, B))
5190 return 0;
5191
5192 // A Not is folded into the BIC, ORN or BSL of each And/Or using it, unless
5193 // that And/Or negates both of its operands.
5194 if (match(CtxI, m_Not(m_Value())) &&
5195 all_of(CtxI->users(), [&](const User *U) {
5196 const auto *UI = cast<Instruction>(U);
5197 return is_contained({Instruction::And, Instruction::Or},
5198 UI->getOpcode()) &&
5199 UI->getParent() == CtxI->getParent() &&
5200 !match(UI, m_BinOp(m_Not(m_Value()), m_Not(m_Value())));
5201 }))
5202 return 0;
5203 }
5204
5205 // Legalize the type.
5206 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
5207
5208 // TODO: Handle more cost kinds for floating point operations.
5209 if (ISD == ISD::FADD || ISD == ISD::FSUB || ISD == ISD::FMUL ||
5210 ISD == ISD::FDIV || ISD == ISD::FREM || ISD == ISD::FNEG)
5211 if (CostKind != TTI::TCK_RecipThroughput)
5212 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5213 Op2Info, Args, CtxI);
5214
5215 if (ISD == ISD::FADD || ISD == ISD::FSUB || ISD == ISD::FMUL ||
5216 ISD == ISD::FDIV || ISD == ISD::FREM) {
5217 // Increase the cost for half and bfloat types if not architecturally
5218 // supported.
5219 if (auto PromotedCost = getFP16BF16PromoteCost(
5220 Ty, CostKind, Op1Info, Op2Info, /*IncludeTrunc=*/true,
5221 // There is not native support for fdiv/frem even with +sve-b16b16.
5222 /*CanUseSVE=*/ISD != ISD::FDIV && ISD != ISD::FREM,
5223 [&](Type *PromotedTy) {
5224 return getArithmeticInstrCost(Opcode, PromotedTy, CostKind,
5225 Op1Info, Op2Info);
5226 }))
5227 return *PromotedCost;
5228
5229 // fp128 all go via libcalls
5230 if (Ty->getScalarType()->isFP128Ty())
5231 return (CostKind == TTI::TCK_CodeSize ? 1 : 10) * LT.first;
5232 }
5233
5234 // If the operation is a widening instruction (smull or umull) and both
5235 // operands are extends the cost can be cheaper by considering that the
5236 // operation will operate on the narrowest type size possible (double the
5237 // largest input size) and a further extend.
5238 if (Type *ExtTy = isBinExtWideningInstruction(Opcode, Ty, Args)) {
5239 if (ExtTy != Ty)
5240 return getArithmeticInstrCost(Opcode, ExtTy, CostKind) +
5241 getCastInstrCost(Instruction::ZExt, Ty, ExtTy,
5242 TTI::CastContextHint::None, CostKind);
5243 return LT.first;
5244 }
5245
5246 switch (ISD) {
5247 default:
5248 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5249 Op2Info);
5250 case ISD::ADD:
5251 case ISD::SUB:
5252 return LT.first; // Also works for i128
5253 case ISD::MUL: {
5254 // i128 multiply is umulh + 2*madd + mul and grows ~O(Bitwidth^2). For
5255 // scalable vectors the cost of LT.first will be invalid, leading to an
5256 // invalid cost overall.
5257 unsigned Mul64CostFactor = (CostKind == TTI::TCK_RecipThroughput &&
5258 ST->hasLimited64bitVectorMulBandwidth())
5259 ? 4
5260 : 1;
5261 if (Ty->getScalarSizeInBits() > 64) {
5262 unsigned NumLanes = isa<FixedVectorType>(Ty)
5263 ? cast<FixedVectorType>(Ty)->getNumElements()
5264 : 1;
5265 InstructionCost CostPerLane = LT.first / NumLanes;
5266 return CostPerLane * CostPerLane * NumLanes * Mul64CostFactor;
5267 }
5268
5269 if (LT.second == MVT::v2i64) {
5270 // When SVE is available, then we can lower the v2i64 operation using
5271 // the SVE mul instruction, which has a lower cost.
5272 if (ST->hasSVE())
5273 return LT.first * Mul64CostFactor;
5274
5275 // When SVE is not available, there is no MUL.2d instruction,
5276 // which means mul <2 x i64> is expensive as elements are extracted
5277 // from the vectors and the muls scalarized.
5278 // As getScalarizationOverhead is a bit too pessimistic, we
5279 // estimate the cost for a i64 vector directly here, which is:
5280 // - four 2-cost i64 extracts,
5281 // - two 2-cost i64 inserts, and
5282 // - two 1-cost muls.
5283 // So, for a v2i64 with LT.First = 1 the cost is 14, and for a v4i64 with
5284 // LT.first = 2 the cost is 28.
5285 return cast<VectorType>(Ty)->getElementCount().getKnownMinValue() *
5286 (getArithmeticInstrCost(Opcode, Ty->getScalarType(), CostKind) +
5287 getVectorInstrCost(Instruction::ExtractElement, Ty, CostKind, -1,
5288 nullptr, nullptr) *
5289 2 +
5290 getVectorInstrCost(Instruction::InsertElement, Ty, CostKind, -1,
5291 nullptr, nullptr));
5292 }
5293
5294 if (LT.second == MVT::nxv2i64)
5295 return LT.first * Mul64CostFactor;
5296
5297 return LT.first;
5298 }
5299 case ISD::SREM:
5300 case ISD::SDIV:
5301 /*
5302 Notes for sdiv/srem specific costs:
5303 1. This only considers the cases where the divisor is constant, uniform and
5304 (pow-of-2/non-pow-of-2). Other cases are not important since they either
5305 result in some form of (ldr + adrp), corresponding to constant vectors, or
5306 scalarization of the division operation.
5307 2. Constant divisors, either negative in whole or partially, don't result in
5308 significantly different codegen as compared to positive constant divisors.
5309 So, we don't consider negative divisors separately.
5310 3. If the codegen is significantly different with SVE, it has been indicated
5311 using comments at appropriate places.
5312
5313 sdiv specific cases:
5314 -----------------------------------------------------------------------
5315 codegen | pow-of-2 | Type
5316 -----------------------------------------------------------------------
5317 add + cmp + csel + asr | Y | i64
5318 add + cmp + csel + asr | Y | i32
5319 -----------------------------------------------------------------------
5320
5321 srem specific cases:
5322 -----------------------------------------------------------------------
5323 codegen | pow-of-2 | Type
5324 -----------------------------------------------------------------------
5325 negs + and + and + csneg | Y | i64
5326 negs + and + and + csneg | Y | i32
5327 -----------------------------------------------------------------------
5328
5329 other sdiv/srem cases:
5330 -------------------------------------------------------------------------
5331 common codegen | + srem | + sdiv | pow-of-2 | Type
5332 -------------------------------------------------------------------------
5333 smulh + asr + add + add | - | - | N | i64
5334 smull + lsr + add + add | - | - | N | i32
5335 usra | and + sub | sshr | Y | <2 x i64>
5336 2 * (scalar code) | - | - | N | <2 x i64>
5337 usra | bic + sub | sshr + neg | Y | <4 x i32>
5338 smull2 + smull + uzp2 | mls | - | N | <4 x i32>
5339 + sshr + usra | | | |
5340 -------------------------------------------------------------------------
5341 */
5342 if (Op2Info.isConstant() && Op2Info.isUniform()) {
5343 InstructionCost AddCost =
5344 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5345 Op1Info.getNoProps(), Op2Info.getNoProps());
5346 InstructionCost AsrCost =
5347 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5348 Op1Info.getNoProps(), Op2Info.getNoProps());
5349 InstructionCost MulCost =
5350 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5351 Op1Info.getNoProps(), Op2Info.getNoProps());
5352 // add/cmp/csel/csneg should have similar cost while asr/negs/and should
5353 // have similar cost.
5354 auto VT = TLI->getValueType(DL, Ty);
5355 if (VT.isScalarInteger() && VT.getSizeInBits() <= 64) {
5356 if (Op2Info.isPowerOf2() || Op2Info.isNegatedPowerOf2()) {
5357 // Neg can be folded into the asr instruction.
5358 return ISD == ISD::SDIV ? (3 * AddCost + AsrCost)
5359 : (3 * AsrCost + AddCost);
5360 } else {
5361 return MulCost + AsrCost + 2 * AddCost;
5362 }
5363 } else if (VT.isVector()) {
5364 InstructionCost UsraCost = 2 * AsrCost;
5365 if (Op2Info.isPowerOf2() || Op2Info.isNegatedPowerOf2()) {
5366 // Division with scalable types corresponds to native 'asrd'
5367 // instruction when SVE is available.
5368 // e.g. %1 = sdiv <vscale x 4 x i32> %a, splat (i32 8)
5369
5370 // One more for the negation in SDIV
5372 (Op2Info.isNegatedPowerOf2() && ISD == ISD::SDIV) ? AsrCost : 0;
5373 if (Ty->isScalableTy() && ST->hasSVE())
5374 Cost += 2 * AsrCost;
5375 else {
5376 Cost +=
5377 UsraCost +
5378 (ISD == ISD::SDIV
5379 ? (LT.second.getScalarType() == MVT::i64 ? 1 : 2) * AsrCost
5380 : 2 * AddCost);
5381 }
5382 return Cost;
5383 } else if (LT.second == MVT::v2i64) {
5384 return VT.getVectorNumElements() *
5385 getArithmeticInstrCost(Opcode, Ty->getScalarType(), CostKind,
5386 Op1Info.getNoProps(),
5387 Op2Info.getNoProps());
5388 } else {
5389 // When SVE is available, we get:
5390 // smulh + lsr + add/sub + asr + add/sub.
5391 if (Ty->isScalableTy() && ST->hasSVE())
5392 return MulCost /*smulh cost*/ + 2 * AddCost + 2 * AsrCost;
5393 return 2 * MulCost + AddCost /*uzp2 cost*/ + AsrCost + UsraCost;
5394 }
5395 }
5396 }
5397 if (Op2Info.isConstant() && !Op2Info.isUniform() &&
5398 LT.second.isFixedLengthVector()) {
5399 // FIXME: When the constant vector is non-uniform, this may result in
5400 // loading the vector from constant pool or in some cases, may also result
5401 // in scalarization. For now, we are approximating this with the
5402 // scalarization cost.
5403 auto ExtractCost = 2 * getVectorInstrCost(Instruction::ExtractElement, Ty,
5404 CostKind, -1, nullptr, nullptr);
5405 auto InsertCost = getVectorInstrCost(Instruction::InsertElement, Ty,
5406 CostKind, -1, nullptr, nullptr);
5407 unsigned NElts = cast<FixedVectorType>(Ty)->getNumElements();
5408 return ExtractCost + InsertCost +
5409 NElts * getArithmeticInstrCost(Opcode, Ty->getScalarType(),
5410 CostKind, Op1Info.getNoProps(),
5411 Op2Info.getNoProps());
5412 }
5413 [[fallthrough]];
5414 case ISD::UDIV:
5415 case ISD::UREM: {
5416 auto VT = TLI->getValueType(DL, Ty);
5417 if (Op2Info.isConstant()) {
5418 // If the operand is a power of 2 we can use the shift or and cost.
5419 if (ISD == ISD::UDIV && Op2Info.isPowerOf2())
5420 return getArithmeticInstrCost(Instruction::LShr, Ty, CostKind,
5421 Op1Info.getNoProps(),
5422 Op2Info.getNoProps());
5423 if (ISD == ISD::UREM && Op2Info.isPowerOf2())
5424 return getArithmeticInstrCost(Instruction::And, Ty, CostKind,
5425 Op1Info.getNoProps(),
5426 Op2Info.getNoProps());
5427
5428 if (ISD == ISD::UDIV || ISD == ISD::UREM) {
5429 // Divides by a constant are expanded to MULHU + SUB + SRL + ADD + SRL.
5430 // The MULHU will be expanded to UMULL for the types not listed below,
5431 // and will become a pair of UMULL+MULL2 for 128bit vectors.
5432 bool HasMULH = VT == MVT::i64 || LT.second == MVT::nxv2i64 ||
5433 LT.second == MVT::nxv4i32 || LT.second == MVT::nxv8i16 ||
5434 LT.second == MVT::nxv16i8;
5435 bool Is128bit = LT.second.is128BitVector();
5436
5437 InstructionCost MulCost =
5438 getArithmeticInstrCost(Instruction::Mul, Ty, CostKind,
5439 Op1Info.getNoProps(), Op2Info.getNoProps());
5440 InstructionCost AddCost =
5441 getArithmeticInstrCost(Instruction::Add, Ty, CostKind,
5442 Op1Info.getNoProps(), Op2Info.getNoProps());
5443 InstructionCost ShrCost =
5444 getArithmeticInstrCost(Instruction::AShr, Ty, CostKind,
5445 Op1Info.getNoProps(), Op2Info.getNoProps());
5446 InstructionCost DivCost = MulCost * (Is128bit ? 2 : 1) + // UMULL/UMULH
5447 (HasMULH ? 0 : ShrCost) + // UMULL shift
5448 AddCost * 2 + ShrCost;
5449 return DivCost + (ISD == ISD::UREM ? MulCost + AddCost : 0);
5450 }
5451 }
5452
5453 // div i128's are lowered as libcalls. Pass nullptr as (u)divti3 calls are
5454 // emitted by the backend even when those functions are not declared in the
5455 // module.
5456 if (!VT.isVector() && VT.getSizeInBits() > 64)
5457 return getCallInstrCost(/*Function*/ nullptr, Ty, {Ty, Ty}, CostKind);
5458
5459 InstructionCost Cost = BaseT::getArithmeticInstrCost(
5460 Opcode, Ty, CostKind, Op1Info, Op2Info);
5461 if (Ty->isVectorTy() && (ISD == ISD::SDIV || ISD == ISD::UDIV)) {
5462 if (TLI->isOperationLegalOrCustom(ISD, LT.second) && ST->hasSVE()) {
5463 // SDIV/UDIV operations are lowered using SVE, then we can have less
5464 // costs.
5465 if (VT.isSimple() && isa<FixedVectorType>(Ty) &&
5466 Ty->getPrimitiveSizeInBits().getFixedValue() < 128) {
5467 static const CostTblEntry DivTbl[]{
5468 {ISD::SDIV, MVT::v2i8, 5}, {ISD::SDIV, MVT::v4i8, 8},
5469 {ISD::SDIV, MVT::v8i8, 8}, {ISD::SDIV, MVT::v2i16, 5},
5470 {ISD::SDIV, MVT::v4i16, 5}, {ISD::SDIV, MVT::v2i32, 1},
5471 {ISD::UDIV, MVT::v2i8, 5}, {ISD::UDIV, MVT::v4i8, 8},
5472 {ISD::UDIV, MVT::v8i8, 8}, {ISD::UDIV, MVT::v2i16, 5},
5473 {ISD::UDIV, MVT::v4i16, 5}, {ISD::UDIV, MVT::v2i32, 1}};
5474
5475 const auto *Entry = CostTableLookup(DivTbl, ISD, VT.getSimpleVT());
5476 if (nullptr != Entry)
5477 return Entry->Cost;
5478 }
5479 // A non-power-of-2 count can't divide as a single whole-register op
5480 // (an inactive lane's leftover value could be a zero divisor and
5481 // trap), so the legalizer emits one div per whole register plus one
5482 // per set bit of the remainder (e.g. <7 x i32> emits 3 divs, not 2).
5483 if (auto *FVTy = dyn_cast<FixedVectorType>(Ty);
5484 FVTy && LT.second.isFixedLengthVector()) {
5485 unsigned NumElts = FVTy->getNumElements();
5486 unsigned RegElts = LT.second.getVectorNumElements();
5487 if (RegElts > 0)
5488 Cost = (NumElts / RegElts + popcount(NumElts % RegElts)) * 2;
5489 }
5490 // For 8/16-bit elements, the cost is higher because the type
5491 // requires promotion and possibly splitting:
5492 if (LT.second.getScalarType() == MVT::i8)
5493 Cost *= 8;
5494 else if (LT.second.getScalarType() == MVT::i16)
5495 Cost *= 4;
5496 return Cost;
5497 } else {
5498 // If one of the operands is a uniform constant then the cost for each
5499 // element is Cost for insertion, extraction and division.
5500 // Insertion cost = 2, Extraction Cost = 2, Division = cost for the
5501 // operation with scalar type
5502 if ((Op1Info.isConstant() && Op1Info.isUniform()) ||
5503 (Op2Info.isConstant() && Op2Info.isUniform())) {
5504 if (auto *VTy = dyn_cast<FixedVectorType>(Ty)) {
5505 InstructionCost DivCost = BaseT::getArithmeticInstrCost(
5506 Opcode, Ty->getScalarType(), CostKind, Op1Info, Op2Info);
5507 return (4 + DivCost) * VTy->getNumElements();
5508 }
5509 }
5510 // On AArch64, without SVE, vector divisions are expanded
5511 // into scalar divisions of each pair of elements.
5512 Cost += getVectorInstrCost(Instruction::ExtractElement, Ty, CostKind,
5513 -1, nullptr, nullptr);
5514 Cost += getVectorInstrCost(Instruction::InsertElement, Ty, CostKind, -1,
5515 nullptr, nullptr);
5516 }
5517
5518 // TODO: if one of the arguments is scalar, then it's not necessary to
5519 // double the cost of handling the vector elements.
5520 Cost += Cost;
5521 }
5522 return Cost;
5523 }
5524 case ISD::XOR:
5525 case ISD::OR:
5526 case ISD::AND:
5527 // TODO: revisit these costs as it's not accurate enough for non-uniform
5528 // constant.
5529 return LT.first;
5530 case ISD::SRL:
5531 case ISD::SRA:
5532 case ISD::SHL: {
5533 // Immediate vector shifts require uniform shift amounts. Non-uniform
5534 // constants therefore use variable shifts and require materializing the
5535 // shift vector. Account for a shift and materialization per legalized
5536 // vector, together with shared setup.
5537 // This cost is for (ldr, shl) + adrp
5538 // TODO: These costs are based on CodeSize only, consider other CostKinds.
5539 if (Op2Info.isConstant() && !Op2Info.isUniform() &&
5540 LT.second.isFixedLengthVector())
5541 return 2 * LT.first + 1;
5542
5543 // Marked 'custom' for combining purposes; a uniform shift amount still
5544 // lowers to a single legal instruction.
5545 return LT.first;
5546 }
5547
5548 case ISD::FNEG:
5549 // Scalar fmul(fneg) or fneg(fmul) can be converted to fnmul
5550 if ((Ty->isFloatTy() || Ty->isDoubleTy() ||
5551 (Ty->isHalfTy() && ST->hasFullFP16())) &&
5552 CtxI &&
5553 ((CtxI->hasOneUse() &&
5554 match(*CtxI->user_begin(), m_FMul(m_Value(), m_Value()))) ||
5555 match(CtxI->getOperand(0), m_FMul(m_Value(), m_Value()))))
5556 return 0;
5557 [[fallthrough]];
5558 case ISD::FADD:
5559 case ISD::FSUB:
5560 if (!Ty->getScalarType()->isFP128Ty())
5561 return LT.first;
5562 [[fallthrough]];
5563 case ISD::FMUL:
5564 case ISD::FDIV:
5565 // These nodes are marked as 'custom' just to lower them to SVE.
5566 // We know said lowering will incur no additional cost.
5567 if (!Ty->getScalarType()->isFP128Ty())
5568 return 2 * LT.first;
5569
5570 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5571 Op2Info);
5572 case ISD::FREM:
5573 // Pass nullptr as fmod/fmodf calls are emitted by the backend even when
5574 // those functions are not declared in the module.
5575 if (!Ty->isVectorTy())
5576 return getCallInstrCost(/*Function*/ nullptr, Ty, {Ty, Ty}, CostKind);
5577 return BaseT::getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info,
5578 Op2Info);
5579 }
5580}
5581
5584 const SCEV *Ptr,
5585 TTI::TargetCostKind CostKind) const {
5586 // Address computations in vectorized code with non-consecutive addresses will
5587 // likely result in more instructions compared to scalar code where the
5588 // computation can more often be merged into the index mode. The resulting
5589 // extra micro-ops can significantly decrease throughput.
5590 unsigned NumVectorInstToHideOverhead =
5591 ST->getCLOpts().neon_nonconst_stride_overhead;
5592 int MaxMergeDistance = 64;
5593
5594 if (PtrTy->isVectorTy() && SE &&
5595 !BaseT::isConstantStridedAccessLessThan(SE, Ptr, MaxMergeDistance + 1))
5596 return NumVectorInstToHideOverhead;
5597
5598 // In many cases the address computation is not merged into the instruction
5599 // addressing mode.
5600 return 1;
5601}
5602
5603/// Check whether Opcode1 has less throughput according to the scheduling
5604/// model than Opcode2. For variant scheduling classes, the lowest throughput
5605/// of Opcode1 and the highest throughput of Opcode2 are compared among all the
5606/// scheduling classes they may be resolved to.
5608 unsigned Opcode1, unsigned Opcode2) const {
5609 const MCSchedModel &Sched = ST->getSchedModel();
5610 const TargetInstrInfo *TII = ST->getInstrInfo();
5611 if (!Sched.hasInstrSchedModel())
5612 return false;
5613
5614 auto GetRThroughput = [&](unsigned Opcode, bool Highest) {
5615 std::optional<double> Res;
5616 SmallVector<unsigned> Worklist = {TII->get(Opcode).getSchedClass()};
5617 while (!Worklist.empty()) {
5618 unsigned SchedClass = Worklist.pop_back_val();
5619 const MCSchedClassDesc *SCD = Sched.getSchedClassDesc(SchedClass);
5620 if (SCD->isVariant()) {
5621 append_range(Worklist, AArch64_MC::getVariantSchedClassTargets(
5622 SchedClass, Sched.getProcessorID()));
5623 continue;
5624 }
5625 if (!SCD->isValid())
5626 continue;
5627 double RThroughput = MCSchedModel::getReciprocalThroughput(*ST, *SCD);
5628 if (!Res || (Highest ? RThroughput > *Res : RThroughput < *Res))
5629 Res = RThroughput;
5630 }
5631 return Res;
5632 };
5633 std::optional<double> RThroughput1 =
5634 GetRThroughput(Opcode1, /*Highest=*/true);
5635 std::optional<double> RThroughput2 =
5636 GetRThroughput(Opcode2, /*Highest=*/false);
5637 return RThroughput1 && RThroughput2 && *RThroughput1 > *RThroughput2;
5638}
5639
5641 unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred,
5643 TTI::OperandValueInfo Op2Info, const Instruction *I) const {
5644 // We don't lower some vector selects well that are wider than the register
5645 // width. TODO: Improve this with different cost kinds.
5646 if (isa<FixedVectorType>(ValTy) && Opcode == Instruction::Select) {
5647 // We would need this many instructions to hide the scalarization happening.
5648 const int AmortizationCost = 20;
5649
5650 // If VecPred is not set, check if we can get a predicate from the context
5651 // instruction, if its type matches the requested ValTy.
5652 if (VecPred == CmpInst::BAD_ICMP_PREDICATE && I && I->getType() == ValTy) {
5653 CmpPredicate CurrentPred;
5654 if (match(I, m_Select(m_Cmp(CurrentPred, m_Value(), m_Value()), m_Value(),
5655 m_Value())))
5656 VecPred = CurrentPred;
5657 }
5658 // Check if we have a compare/select chain that can be lowered using
5659 // a (F)CMxx & BFI pair.
5660 if (CmpInst::isIntPredicate(VecPred) || VecPred == CmpInst::FCMP_OLE ||
5661 VecPred == CmpInst::FCMP_OLT || VecPred == CmpInst::FCMP_OGT ||
5662 VecPred == CmpInst::FCMP_OGE || VecPred == CmpInst::FCMP_OEQ ||
5663 VecPred == CmpInst::FCMP_UNE) {
5664 static const auto ValidMinMaxTys = {
5665 MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
5666 MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32, MVT::v2f64};
5667 static const auto ValidFP16MinMaxTys = {MVT::v4f16, MVT::v8f16};
5668
5669 auto LT = getTypeLegalizationCost(ValTy);
5670 if (any_of(ValidMinMaxTys, equal_to(LT.second)) ||
5671 (ST->hasFullFP16() &&
5672 any_of(ValidFP16MinMaxTys, equal_to(LT.second))))
5673 return LT.first;
5674 }
5675
5676 static const TypeConversionCostTblEntry VectorSelectTbl[] = {
5677 {Instruction::Select, MVT::v2i1, MVT::v2f32, 2},
5678 {Instruction::Select, MVT::v2i1, MVT::v2f64, 2},
5679 {Instruction::Select, MVT::v4i1, MVT::v4f32, 2},
5680 {Instruction::Select, MVT::v4i1, MVT::v4f16, 2},
5681 {Instruction::Select, MVT::v8i1, MVT::v8f16, 2},
5682 {Instruction::Select, MVT::v16i1, MVT::v16i16, 16},
5683 {Instruction::Select, MVT::v8i1, MVT::v8i32, 8},
5684 {Instruction::Select, MVT::v16i1, MVT::v16i32, 16},
5685 {Instruction::Select, MVT::v4i1, MVT::v4i64, 4 * AmortizationCost},
5686 {Instruction::Select, MVT::v8i1, MVT::v8i64, 8 * AmortizationCost},
5687 {Instruction::Select, MVT::v16i1, MVT::v16i64, 16 * AmortizationCost}};
5688
5689 EVT SelCondTy = TLI->getValueType(DL, CondTy);
5690 EVT SelValTy = TLI->getValueType(DL, ValTy);
5691 if (SelCondTy.isSimple() && SelValTy.isSimple()) {
5692 if (const auto *Entry = ConvertCostTableLookup(VectorSelectTbl, Opcode,
5693 SelCondTy.getSimpleVT(),
5694 SelValTy.getSimpleVT()))
5695 return Entry->Cost;
5696 }
5697 }
5698
5699 if (Opcode == Instruction::FCmp) {
5700 if (auto PromotedCost = getFP16BF16PromoteCost(
5701 ValTy, CostKind, Op1Info, Op2Info, /*IncludeTrunc=*/false,
5702 // TODO: Consider costing SVE FCMPs.
5703 /*CanUseSVE=*/false, [&](Type *PromotedTy) {
5705 getCmpSelInstrCost(Opcode, PromotedTy, CondTy, VecPred,
5706 CostKind, Op1Info, Op2Info);
5707 if (isa<VectorType>(PromotedTy))
5709 Instruction::Trunc,
5712 TTI::CastContextHint::None, CostKind);
5713 return Cost;
5714 }))
5715 return *PromotedCost;
5716
5717 auto LT = getTypeLegalizationCost(ValTy);
5718 // Model unknown fp compares as a libcall.
5719 if (LT.second.getScalarType() != MVT::f64 &&
5720 LT.second.getScalarType() != MVT::f32 &&
5721 LT.second.getScalarType() != MVT::f16)
5722 return LT.first * getCallInstrCost(/*Function*/ nullptr, ValTy,
5723 {ValTy, ValTy}, CostKind);
5724
5725 // Some comparison operators require expanding to multiple compares + or.
5726 unsigned Factor = 1;
5727 if (!CondTy->isVectorTy() &&
5728 (VecPred == FCmpInst::FCMP_ONE || VecPred == FCmpInst::FCMP_UEQ))
5729 Factor = 2; // fcmp with 2 selects
5730 else if (isa<FixedVectorType>(ValTy) &&
5731 (VecPred == FCmpInst::FCMP_ONE || VecPred == FCmpInst::FCMP_UEQ ||
5732 VecPred == FCmpInst::FCMP_ORD || VecPred == FCmpInst::FCMP_UNO))
5733 Factor = 3; // fcmxx+fcmyy+or
5734 else if (isa<ScalableVectorType>(ValTy) &&
5735 (VecPred == FCmpInst::FCMP_ONE || VecPred == FCmpInst::FCMP_UEQ))
5736 Factor = 3; // fcmxx+fcmyy+or
5737
5738 if (isa<ScalableVectorType>(ValTy) &&
5739 CostKind == TTI::TCK_RecipThroughput &&
5740 hasKnownLowerThroughputFromSchedulingModel(AArch64::FCMEQ_PPzZZ_S,
5741 AArch64::FCMEQv4f32))
5742 Factor *= 2;
5743
5744 return Factor * (CostKind == TTI::TCK_Latency ? 2 : LT.first);
5745 }
5746
5747 // Treat the icmp in icmp(and, 0) or icmp(and, -1/1) when it can be folded to
5748 // icmp(and, 0) as free, as we can make use of ands, but only if the
5749 // comparison is not unsigned. FIXME: Enable for non-throughput cost kinds
5750 // providing it will not cause performance regressions.
5751 if (CostKind == TTI::TCK_RecipThroughput && ValTy->isIntegerTy() &&
5752 Opcode == Instruction::ICmp && I && !CmpInst::isUnsigned(VecPred) &&
5753 TLI->isTypeLegal(TLI->getValueType(DL, ValTy)) &&
5754 match(I->getOperand(0), m_And(m_Value(), m_Value()))) {
5755 if (match(I->getOperand(1), m_Zero()))
5756 return 0;
5757
5758 // x >= 1 / x < 1 -> x > 0 / x <= 0
5759 if (match(I->getOperand(1), m_One()) &&
5760 (VecPred == CmpInst::ICMP_SLT || VecPred == CmpInst::ICMP_SGE))
5761 return 0;
5762
5763 // x <= -1 / x > -1 -> x > 0 / x <= 0
5764 if (match(I->getOperand(1), m_AllOnes()) &&
5765 (VecPred == CmpInst::ICMP_SLE || VecPred == CmpInst::ICMP_SGT))
5766 return 0;
5767 }
5768
5769 // The base case handles scalable vectors fine for now, since it treats the
5770 // cost as 1 * legalization cost.
5772 Opcode, ValTy, CondTy, VecPred, CostKind, Op1Info, Op2Info, I);
5773 if (Opcode == Instruction::ICmp && isa<ScalableVectorType>(ValTy) &&
5774 CostKind == TTI::TCK_RecipThroughput &&
5775 hasKnownLowerThroughputFromSchedulingModel(AArch64::CMPEQ_PPzZZ_S,
5776 AArch64::CMEQv4i32))
5777 Cost *= 2;
5778 return Cost;
5779}
5780
5782AArch64TTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const {
5784 if (ST->requiresStrictAlign()) {
5785 // TODO: Add cost modeling for strict align. Misaligned loads expand to
5786 // a bunch of instructions when strict align is enabled.
5787 return Options;
5788 }
5789 Options.AllowOverlappingLoads = true;
5790 Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize);
5791 Options.NumLoadsPerBlock = IsZeroCmp ? Options.MaxNumLoads : 1;
5792 // TODO: Though vector loads usually perform well on AArch64, in some targets
5793 // they may wake up the FP unit, which raises the power consumption. Perhaps
5794 // they could be used with no holds barred (-O3).
5795 Options.LoadSizes = {8, 4, 2, 1};
5796 Options.AllowedTailExpansions = {3, 5, 6};
5797 return Options;
5798}
5799
5801 return ST->hasSVE();
5802}
5803
5806 TTI::TargetCostKind CostKind) const {
5807 switch (MICA.getID()) {
5808 case Intrinsic::masked_scatter:
5809 case Intrinsic::masked_gather:
5810 return getGatherScatterOpCost(MICA, CostKind);
5811 case Intrinsic::masked_load:
5812 case Intrinsic::masked_store:
5813 case Intrinsic::masked_expandload:
5814 case Intrinsic::masked_compressstore:
5815 return getMaskedMemoryOpCost(MICA, CostKind);
5816 }
5817 return BaseT::getMemIntrinsicInstrCost(MICA, CostKind);
5818}
5819
5822 TTI::TargetCostKind CostKind) const {
5823 Type *Src = MICA.getDataType();
5824
5825 if (useNeonVector(Src))
5826 return BaseT::getMemIntrinsicInstrCost(MICA, CostKind);
5827 auto LT = getTypeLegalizationCost(Src);
5828 if (!LT.first.isValid())
5830
5831 // Return an invalid cost for element types that we are unable to lower.
5832 auto *VT = cast<VectorType>(Src);
5833 if (VT->getElementType()->isIntegerTy(1))
5835
5836 // <vscale x 1 x eltty> operations require mask adaptation.
5837 // Allow it for normal masked ld/st
5838 if (VT->getElementCount() == ElementCount::getScalable(1))
5839 return is_contained({Intrinsic::masked_load, Intrinsic::masked_store},
5840 MICA.getID())
5841 ? LT.first + 1
5843
5844 InstructionCost MemOpCost = LT.first;
5845 if (MICA.getID() == Intrinsic::masked_expandload) {
5846 if (!isLegalMaskedExpandLoad(Src, MICA.getAlignment()))
5848
5849 // Operation will be split into expand of masked.load
5850 // Something like:
5851 // cntp x8, p0, p0.s
5852 // whilelo p1.s, xzr, x8
5853 // ld1w { z1.s }, p1/z, [x0]
5854 // expand z1.s, p0, z1.s
5855 MemOpCost *= 4;
5856 }
5857
5858 if (MICA.getID() == Intrinsic::masked_compressstore) {
5859 if (!isLegalMaskedCompressStore(Src, MICA.getAlignment()))
5861
5862 // A compress store lowers to something like:
5863 // compact z0.s, p0, z0.s
5864 // cntp x8, p1, p0.s
5865 // whilelo p0.s, xzr, x8
5866 // st1w { z0.s }, p0, [x0]
5867 MemOpCost *= 4;
5868 }
5869
5870 // If we need to split the memory operation, we will also need to split the
5871 // mask. This will likely lead to overestimating the cost in some cases if
5872 // multiple memory operations use the same mask, but we often don't have
5873 // enough context to figure that out here.
5874 //
5875 // If the elements being loaded are bytes then the mask will already be split,
5876 // since the number of bits in a P register matches the number of bytes in a
5877 // Z register.
5878 if (LT.first > 1 && LT.second.getScalarSizeInBits() > 8)
5879 return MemOpCost * 2;
5880
5881 return MemOpCost;
5882}
5883
5884// This function returns gather/scatter overhead either from
5885// user-provided value or specialized values per-target from \p ST.
5886static unsigned getSVEGatherScatterOverhead(unsigned Opcode,
5887 const AArch64Subtarget *ST) {
5888 assert((Opcode == Instruction::Load || Opcode == Instruction::Store) &&
5889 "Should be called on only load or stores.");
5890 switch (Opcode) {
5891 case Instruction::Load:
5892 return ST->getCLOpts().sve_gather_overhead.value_or(
5893 ST->getGatherOverhead());
5894 break;
5895 case Instruction::Store:
5896 return ST->getCLOpts().sve_scatter_overhead.value_or(
5897 ST->getScatterOverhead());
5898 break;
5899 default:
5900 llvm_unreachable("Shouldn't have reached here");
5901 }
5902}
5903
5906 TTI::TargetCostKind CostKind) const {
5907
5908 unsigned Opcode = (MICA.getID() == Intrinsic::masked_gather ||
5909 MICA.getID() == Intrinsic::vp_gather)
5910 ? Instruction::Load
5911 : Instruction::Store;
5912
5913 Type *DataTy = MICA.getDataType();
5914 Align Alignment = MICA.getAlignment();
5915 const Instruction *I = MICA.getInst();
5916
5917 if (useNeonVector(DataTy) || !isLegalMaskedGatherScatter(DataTy))
5918 return BaseT::getMemIntrinsicInstrCost(MICA, CostKind);
5919 auto *VT = cast<VectorType>(DataTy);
5920 auto LT = getTypeLegalizationCost(DataTy);
5921 if (!LT.first.isValid())
5923
5924 // Return an invalid cost for element types that we are unable to lower.
5925 if (!LT.second.isVector() ||
5926 !isElementTypeLegalForScalableVector(VT->getElementType()) ||
5927 VT->getElementType()->isIntegerTy(1))
5929
5930 // The code-generator is currently not able to handle scalable vectors
5931 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
5932 // it. This change will be removed when code-generation for these types is
5933 // sufficiently reliable.
5934 if (VT->getElementCount() == ElementCount::getScalable(1))
5936
5937 ElementCount LegalVF = LT.second.getVectorElementCount();
5938 InstructionCost MemOpCost =
5939 getMemoryOpCost(Opcode, VT->getElementType(), Alignment, 0, CostKind,
5940 {TTI::OK_AnyValue, TTI::OP_None}, I);
5941 // Add on an overhead cost for using gathers/scatters.
5942 MemOpCost *= getSVEGatherScatterOverhead(Opcode, ST);
5943 return LT.first * MemOpCost * getMaxNumElements(LegalVF);
5944}
5945
5947 return isa<FixedVectorType>(Ty) && !ST->useSVEForFixedLengthVectors();
5948}
5949
5951 Align Alignment,
5952 unsigned AddressSpace,
5953 TTI::TargetCostKind CostKind,
5954 TTI::OperandValueInfo OpInfo,
5955 const Instruction *I) const {
5956 EVT VT = TLI->getValueType(DL, Ty, true);
5957 // Type legalization can't handle structs
5958 if (VT == MVT::Other)
5959 return BaseT::getMemoryOpCost(Opcode, Ty, Alignment, AddressSpace,
5960 CostKind);
5961
5962 auto LT = getTypeLegalizationCost(Ty);
5963 if (!LT.first.isValid())
5965
5966 if (auto *VTy = dyn_cast<ScalableVectorType>(Ty)) {
5967
5968 // We only support full register predicate loads and stores.
5969 if (VTy->getElementType()->isIntegerTy(1) &&
5970 !VTy->getElementCount().isKnownMultipleOf(
5973
5974 // <vscale x 1 x eltty> operations require crafting a new mask.
5975 if (VTy->getElementCount() == ElementCount::getScalable(1)) {
5976 Intrinsic::ID IID = Opcode == Instruction::Load ? Intrinsic::masked_load
5977 : Intrinsic::masked_store;
5978 return getMaskedMemoryOpCost(
5979 MemIntrinsicCostAttributes(IID, Ty, Alignment, AddressSpace),
5980 CostKind) +
5981 1;
5982 }
5983 }
5984
5985 // TODO: consider latency as well for TCK_SizeAndLatency.
5986 if (CostKind == TTI::TCK_CodeSize || CostKind == TTI::TCK_SizeAndLatency)
5987 return LT.first;
5988
5989 if (CostKind == TTI::TCK_Latency) {
5990 // Latency doesn't make much sense for stores, so just return 1
5991 if (Opcode == Instruction::Store)
5992 return 1;
5993 // If the subtarget has overridden the load latency then use that instead of
5994 // querying the SchedModel.
5995 if (ST->getFixedLoadLatency())
5996 return (LT.first - 1) + ST->getFixedLoadLatency();
5997 // We expect the load to become LT.first loads of type LT.second. The
5998 // latency will be the latency of the last load plus the time it gets to get
5999 // there, which will be the amount of other loads before that (i.e. total
6000 // loads - 1) multiplied by how long it takes to get through them (the
6001 // reciprocal of the throughput). We get the latency and reciprocal
6002 // throughput from the SchedModel, and assume that the loads become the
6003 // variant with unsigned integer offset.
6004 unsigned Inst = 0;
6005 if (LT.second.isScalableVector() ||
6006 ST->useSVEForFixedLengthVectors(LT.second)) {
6007 Inst = AArch64::LDR_ZXI;
6008 } else if (LT.second.isVector() || LT.second.isFloatingPoint()) {
6009 switch (LT.second.getSizeInBits()) {
6010 case 8:
6011 Inst = AArch64::LDRBui;
6012 break;
6013 case 16:
6014 Inst = AArch64::LDRHui;
6015 break;
6016 case 32:
6017 Inst = AArch64::LDRSui;
6018 break;
6019 case 64:
6020 Inst = AArch64::LDRDui;
6021 break;
6022 case 128:
6023 Inst = AArch64::LDRQui;
6024 break;
6025 default:
6026 llvm_unreachable("Unexpected float or vector type");
6027 }
6028 } else {
6029 switch (LT.second.getSizeInBits()) {
6030 case 8:
6031 Inst = AArch64::LDRBBui;
6032 break;
6033 case 16:
6034 Inst = AArch64::LDRHHui;
6035 break;
6036 case 32:
6037 Inst = AArch64::LDRWui;
6038 break;
6039 case 64:
6040 Inst = AArch64::LDRXui;
6041 break;
6042 default:
6043 llvm_unreachable("Unexpected integer type");
6044 }
6045 }
6046 const MCSchedModel &Sched = ST->getSchedModel();
6047 const TargetInstrInfo *TII = ST->getInstrInfo();
6048 unsigned SchedClass = TII->get(Inst).getSchedClass();
6049 const MCSchedClassDesc *SCD = Sched.hasInstrSchedModel()
6050 ? Sched.getSchedClassDesc(SchedClass)
6051 : nullptr;
6052 // If the cpu has no scheduling model, or it doesn't describe the load, then
6053 // fall back to the default load latency. Variant scheduling classes can't
6054 // be resolved without a MachineInstr, so treat them the same way.
6055 if (!SCD || !SCD->isValid() || SCD->isVariant())
6056 return (LT.first - 1) + ST->getLoadLatency();
6057 // We need to convert the number of loads before the last to a float here,
6058 // as the reciprocal throughput may be fractional.
6059 float NumLoads = (LT.first - 1).getValue();
6060 return NumLoads * Sched.getReciprocalThroughput(*ST, *SCD) +
6061 Sched.computeInstrLatency(*ST, *SCD);
6062 }
6063
6064 if (ST->isMisaligned128StoreSlow() && Opcode == Instruction::Store &&
6065 LT.second.is128BitVector() && Alignment < Align(16)) {
6066 // Unaligned stores are extremely inefficient. We don't split all
6067 // unaligned 128-bit stores because the negative impact that has shown in
6068 // practice on inlined block copy code.
6069 // We make such stores expensive so that we will only vectorize if there
6070 // are 6 other instructions getting vectorized.
6071 const int AmortizationCost = 6;
6072
6073 return LT.first * 2 * AmortizationCost;
6074 }
6075
6076 // Opaque ptr or ptr vector types are i64s and can be lowered to STP/LDPs.
6077 if (Ty->isPtrOrPtrVectorTy())
6078 return LT.first;
6079
6080 if (useNeonVector(Ty)) {
6081 // Check truncating stores and extending loads.
6082 if (Ty->getScalarSizeInBits() != LT.second.getScalarSizeInBits()) {
6083 // v4i8 types are lowered to scalar a load/store and sshll/xtn.
6084 if (VT == MVT::v4i8)
6085 return 2;
6086 // Otherwise we need to scalarize.
6087 return cast<FixedVectorType>(Ty)->getNumElements() * 2;
6088 }
6089 EVT EltVT = VT.getVectorElementType();
6090 unsigned EltSize = EltVT.getScalarSizeInBits();
6091 if (!isPowerOf2_32(EltSize) || EltSize < 8 || EltSize > 64 ||
6092 Alignment != Align(1))
6093 return LT.first;
6094 // FIXME: v3i8 lowering currently is very inefficient, due to automatic
6095 // widening to v4i8, which produces suboptimal results.
6096 if (VT.getVectorNumElements() == 3 && EltVT == MVT::i8)
6097 return LT.first;
6098
6099 // Check non-power-of-2 loads/stores for legal vector element types with
6100 // NEON. Non-power-of-2 memory ops will get broken down to a set of
6101 // operations on smaller power-of-2 ops, including ld1/st1.
6102 InstructionCost Cost = VT.getVectorNumElements() / (128 / EltSize);
6103 unsigned Remainder = VT.getVectorNumElements() % (128 / EltSize);
6104 if (Remainder != 0) {
6106 TypeWorklist.push_back({Remainder, 0});
6107 while (!TypeWorklist.empty()) {
6108 auto [CurrNumElements, Offset] = TypeWorklist.pop_back_val();
6109 if (isPowerOf2_32(CurrNumElements)) {
6110 // 1 per load/store + possible lane insert.
6111 Cost += 1 + (Offset == 0 ? 0 : 1);
6112 continue;
6113 }
6114
6115 unsigned PrevPow2 = NextPowerOf2(CurrNumElements) / 2;
6116 TypeWorklist.push_back({PrevPow2, Offset});
6117 TypeWorklist.push_back({CurrNumElements - PrevPow2, Offset + PrevPow2});
6118 }
6119 }
6120 return Cost;
6121 }
6122
6123 return LT.first;
6124}
6125
6127 unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices,
6128 Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind,
6129 bool UseMaskForCond, bool UseMaskForGaps) const {
6130 assert(Factor >= 2 && "Invalid interleave factor");
6131 auto *VecVTy = cast<VectorType>(VecTy);
6132
6133 if (VecTy->isScalableTy() && !ST->hasSVE())
6135
6136 // Scalable VFs emit vector.[de]interleave intrinsics, for which the target
6137 // supports factors up to the maximum supported interleave factor.
6138 if (VecTy->isScalableTy()) {
6139 if (Factor > TLI->getMaxSupportedInterleaveFactor())
6141
6142 if (Factor == 3 &&
6143 DL.getTypeSizeInBits(VecTy).getKnownMinValue() != (3 * 128))
6145 }
6146
6147 auto LT = getTypeLegalizationCost(VecTy);
6148 unsigned MaxNativeInterleaveFactor = TLI->getMaxSupportedInterleaveFactor();
6149 // Vectorization for masked interleaved accesses is only enabled for scalable
6150 // VF. For fixed-length SVE, avoid non-native interleave factor because
6151 // the generic fallback costs wide fixed-vector shuffles too optimistically.
6152 if (!VecTy->isScalableTy() &&
6153 (UseMaskForCond || UseMaskForGaps ||
6154 (Factor > MaxNativeInterleaveFactor &&
6155 TLI->useSVEForFixedLengthVectorVT(LT.second))))
6157
6158 if (!UseMaskForGaps && Factor <= MaxNativeInterleaveFactor) {
6159 ElementCount EC = VecVTy->getElementCount();
6160 auto *SubVecTy = VectorType::get(VecVTy->getElementType(),
6161 EC.divideCoefficientBy(Factor));
6162
6163 // ldN/stN only support legal vector types of size 64 or 128 in bits.
6164 // Accesses having vector types that are a multiple of 128 bits can be
6165 // matched to more than one ldN/stN instruction.
6166 bool UseScalable;
6167 if (EC.isKnownMultipleOf(Factor) &&
6168 TLI->isLegalInterleavedAccessType(SubVecTy, DL, UseScalable))
6169 return Factor * TLI->getNumInterleavedAccesses(SubVecTy, DL, UseScalable);
6170
6171 // Cost the alternative approach for scalable vectors where the interleave
6172 // factor is larger than the VF: use a contiguous load/store of the full
6173 // wide vector followed by deinterleave/interleave shuffles.
6174 if (VecTy->isScalableTy() && EC.isKnownMultipleOf(Factor)) {
6175 if (SubVecTy->getElementCount() == ElementCount::getScalable(1))
6177
6178 // Cost of the contiguous memory operation on the wide vector.
6179 InstructionCost MemCost;
6180 if (UseMaskForCond) {
6181 unsigned IID = Opcode == Instruction::Load ? Intrinsic::masked_load
6182 : Intrinsic::masked_store;
6183 MemCost = getMemIntrinsicInstrCost(
6184 MemIntrinsicCostAttributes(IID, VecTy, Alignment, AddressSpace),
6185 CostKind);
6186 } else {
6187 MemCost =
6188 getMemoryOpCost(Opcode, VecTy, Alignment, AddressSpace, CostKind);
6189 }
6190
6191 // llvm.vector.deinterleaveN is lowered as a binary tree of deinterleave2
6192 // operations. The tree has Log2(Factor) levels, with Factor UZP/ZIP
6193 // operations at each level, giving a total shuffle cost of
6194 // Factor * Log2(Factor).
6195 auto SubVecCost = getTypeLegalizationCost(SubVecTy);
6196 auto ResultCost = getTypeLegalizationCost(VecTy);
6197 llvm::InstructionCost LegalizationCost = SubVecCost.first;
6198
6199 // FIXME: A temporary increase to the cost in cases where the input
6200 // element type is 4x the output type. Otherwise it produces an SVE tail
6201 // loop which is significantly larger than the NEON equivalent.
6202 if (Opcode == Instruction::Store && Factor == 4 &&
6203 SubVecCost.second.getScalarSizeInBits() ==
6204 (4 * ResultCost.second.getScalarSizeInBits()))
6205 LegalizationCost *= 4;
6206
6207 return MemCost + (Factor * LegalizationCost) + (Factor * Log2_64(Factor));
6208 }
6209 }
6210
6211 return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
6212 Alignment, AddressSpace, CostKind,
6213 UseMaskForCond, UseMaskForGaps);
6214}
6215
6220 for (auto *I : Tys) {
6221 if (!I->isVectorTy())
6222 continue;
6223 if (I->getScalarSizeInBits() * cast<FixedVectorType>(I)->getNumElements() ==
6224 128)
6225 Cost += getMemoryOpCost(Instruction::Store, I, Align(128), 0, CostKind) +
6226 getMemoryOpCost(Instruction::Load, I, Align(128), 0, CostKind);
6227 }
6228 return Cost;
6229}
6230
6232 Align Alignment) const {
6233 // Neon types should be scalarised when we are not choosing to use SVE.
6234 if (useNeonVector(DataTy))
6235 return false;
6236
6237 // Return true only if we are able to lower using the SVE2p2/SME2p2
6238 // expand instruction.
6239 return (ST->isSVEAvailable() && ST->hasSVE2p2()) ||
6240 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2());
6241}
6242
6244 unsigned AddressSpace) const {
6245 // Matches AArch64TargetLowering::emitCanLoadSpeculatively: only address
6246 // space 0 and power-of-2 sizes up to the 16-byte MTE tag granule.
6247 // TODO: Support scalable vectors.
6248 if (AddressSpace != 0)
6249 return false;
6250 TypeSize Size = DL.getTypeStoreSize(DataType);
6251 return !Size.isScalable() && isPowerOf2_64(Size.getFixedValue()) &&
6252 Size.getFixedValue() <= 16;
6253}
6254
6256 unsigned NumVectors, TTI::MaskSource Mask, VectorType *VectorTy,
6257 bool IsStore, std::optional<Instruction::CastOps> CastHint) const {
6258 if (NumVectors <= 1 || !ST->enableSubRegLiveness() || !ST->hasSVE2p1())
6259 return false;
6260
6261 // TODO: Support masked multi-vector loads/stores.
6262 if (Mask != TTI::MaskSource::None)
6263 return false;
6264
6265 // A null vector type queries whether the target supports multi-vector memory
6266 // operations in general.
6267 if (!VectorTy)
6268 return true;
6269
6270 if (!isa<ScalableVectorType>(VectorTy))
6271 return false;
6272
6273 // Conservatively, avoid using multi-vector loads when it's possible we could
6274 // use extending loads instead. Note: We can ignore stores as we only use
6275 // truncating stores when the store vector-width is < a full SVE vector.
6276 if (!IsStore &&
6277 (CastHint == Instruction::ZExt || CastHint == Instruction::SExt))
6278 return false;
6279
6280 // For unpredicated loads/stores allow any pow-of-two multiple of a vector >=
6281 // to a single z-register. We can split operations wider than a single
6282 // multi-vector load/store during ISEL.
6283 return isPowerOf2_32(NumVectors) &&
6284 DL.getTypeSizeInBits(VectorTy).isKnownMultipleOf(
6286}
6287
6288unsigned
6290 bool HasUnorderedReductions) const {
6291 if (VF.isScalar() || (HasUnorderedReductions && VF.getKnownMinValue() <= 4))
6292 return 4;
6293 return ST->getMaxInterleaveFactor();
6294}
6295
6296// For Falkor, we want to avoid having too many strided loads in a loop since
6297// that can exhaust the HW prefetcher resources. We adjust the unroller
6298// MaxCount preference below to attempt to ensure unrolling doesn't create too
6299// many strided loads.
6300static void
6303 enum { MaxStridedLoads = 7 };
6304 auto countStridedLoads = [](Loop *L, ScalarEvolution &SE) {
6305 int StridedLoads = 0;
6306 // FIXME? We could make this more precise by looking at the CFG and
6307 // e.g. not counting loads in each side of an if-then-else diamond.
6308 for (const auto BB : L->blocks()) {
6309 for (auto &I : *BB) {
6310 LoadInst *LMemI = dyn_cast<LoadInst>(&I);
6311 if (!LMemI)
6312 continue;
6313
6314 Value *PtrValue = LMemI->getPointerOperand();
6315 if (L->isLoopInvariant(PtrValue))
6316 continue;
6317
6318 const SCEV *LSCEV = SE.getSCEV(PtrValue);
6319 const SCEVAddRecExpr *LSCEVAddRec = dyn_cast<SCEVAddRecExpr>(LSCEV);
6320 if (!LSCEVAddRec || !LSCEVAddRec->isAffine())
6321 continue;
6322
6323 // FIXME? We could take pairing of unrolled load copies into account
6324 // by looking at the AddRec, but we would probably have to limit this
6325 // to loops with no stores or other memory optimization barriers.
6326 ++StridedLoads;
6327 // We've seen enough strided loads that seeing more won't make a
6328 // difference.
6329 if (StridedLoads > MaxStridedLoads / 2)
6330 return StridedLoads;
6331 }
6332 }
6333 return StridedLoads;
6334 };
6335
6336 int StridedLoads = countStridedLoads(L, SE);
6337 LLVM_DEBUG(dbgs() << "falkor-hwpf: detected " << StridedLoads
6338 << " strided loads\n");
6339 // Pick the largest power of 2 unroll count that won't result in too many
6340 // strided loads.
6341 if (StridedLoads) {
6342 UP.MaxCount = 1 << Log2_32(MaxStridedLoads / StridedLoads);
6343 LLVM_DEBUG(dbgs() << "falkor-hwpf: setting unroll MaxCount to "
6344 << UP.MaxCount << '\n');
6345 }
6346}
6347
6348// This function returns true if the loop:
6349// 1. Has a valid cost, and
6350// 2. Has a cost within the supplied budget.
6351// Otherwise it returns false.
6353 InstructionCost Budget,
6354 unsigned *FinalSize) {
6355 // Estimate the size of the loop.
6356 InstructionCost LoopCost = 0;
6357
6358 for (auto *BB : L->getBlocks()) {
6359 for (auto &I : *BB) {
6360 SmallVector<const Value *, 4> Operands(I.operand_values());
6361 InstructionCost Cost =
6362 TTI.getInstructionCost(&I, Operands, TTI::TCK_CodeSize);
6363 // This can happen with intrinsics that don't currently have a cost model
6364 // or for some operations that require SVE.
6365 if (!Cost.isValid())
6366 return false;
6367
6368 LoopCost += Cost;
6369 if (LoopCost > Budget)
6370 return false;
6371 }
6372 }
6373
6374 if (FinalSize)
6375 *FinalSize = LoopCost.getValue();
6376 return true;
6377}
6378
6380 const AArch64TTIImpl &TTI) {
6381 // Only consider loops with unknown trip counts for which we can determine
6382 // a symbolic expression. Multi-exit loops with small known trip counts will
6383 // likely be unrolled anyway.
6384 const SCEV *BTC = SE.getSymbolicMaxBackedgeTakenCount(L);
6386 return false;
6387
6388 // It might not be worth unrolling loops with low max trip counts. Restrict
6389 // this to max trip counts > 32 for now.
6390 unsigned MaxTC = SE.getSmallConstantMaxTripCount(L);
6391 if (MaxTC > 0 && MaxTC <= 32)
6392 return false;
6393
6394 // Make sure the loop size is <= 5.
6395 if (!isLoopSizeWithinBudget(L, TTI, 5, nullptr))
6396 return false;
6397
6398 // Small search loops with multiple exits can be highly beneficial to unroll.
6399 // We only care about loops with exactly two exiting blocks, although each
6400 // block could jump to the same exit block.
6401 ArrayRef<BasicBlock *> Blocks = L->getBlocks();
6402 if (Blocks.size() != 2)
6403 return false;
6404
6405 if (any_of(Blocks, [](BasicBlock *BB) {
6407 }))
6408 return false;
6409
6410 return true;
6411}
6412
6413/// For Apple CPUs, we want to runtime-unroll loops to make better use if the
6414/// OOO engine's wide instruction window and various predictors.
6415static void
6418 const AArch64TTIImpl &TTI) {
6419 // Limit loops with structure that is highly likely to benefit from runtime
6420 // unrolling; that is we exclude outer loops and loops with many blocks (i.e.
6421 // likely with complex control flow). Note that the heuristics here may be
6422 // overly conservative and we err on the side of avoiding runtime unrolling
6423 // rather than unroll excessively. They are all subject to further refinement.
6424 if (!L->isInnermost() || L->getNumBlocks() > 8)
6425 return;
6426
6427 // Loops with multiple exits are handled by common code.
6428 if (!L->getExitBlock())
6429 return;
6430
6431 // Check if the loop contains any reductions that could be parallelized when
6432 // unrolling. If so, enable partial unrolling, if the trip count is know to be
6433 // a multiple of 2.
6434 bool HasParellelizableReductions =
6435 L->getNumBlocks() == 1 &&
6436 any_of(L->getHeader()->phis(),
6437 [&SE, L](PHINode &Phi) {
6438 return canParallelizeReductionWhenUnrolling(Phi, L, &SE);
6439 }) &&
6440 isLoopSizeWithinBudget(L, TTI, 12, nullptr);
6441 if (HasParellelizableReductions &&
6442 SE.getSmallConstantTripMultiple(L, L->getExitingBlock()) % 2 == 0) {
6443 UP.Partial = true;
6444 UP.MaxCount = 4;
6445 UP.AddAdditionalAccumulators = true;
6446 }
6447
6448 const SCEV *BTC = SE.getSymbolicMaxBackedgeTakenCount(L);
6450 (SE.getSmallConstantMaxTripCount(L) > 0 &&
6451 SE.getSmallConstantMaxTripCount(L) <= 32))
6452 return;
6453
6454 if (getBooleanLoopAttribute(L, "llvm.loop.unroll.runtime.disable"))
6455 return;
6456
6458 return;
6459
6460 // Limit to loops with trip counts that are cheap to expand.
6461 UP.SCEVExpansionBudget = 1;
6462
6463 if (HasParellelizableReductions) {
6464 UP.Runtime = true;
6466 UP.AddAdditionalAccumulators = true;
6467 }
6468
6469 // Try to unroll small, single-block loops with low budget, if they have
6470 // load/store dependencies, to expose more parallel memory access streams,
6471 // or if they do little work inside a block (i.e. load -> X -> store pattern).
6472 BasicBlock *Header = L->getHeader();
6473 BasicBlock *Latch = L->getLoopLatch();
6474 if (Header == Latch) {
6475 // Estimate the size of the loop.
6476 unsigned Size;
6477 unsigned Width = 10;
6478 if (!isLoopSizeWithinBudget(L, TTI, Width, &Size))
6479 return;
6480
6481 // Try to find an unroll count that maximizes the use of the instruction
6482 // window, i.e. trying to fetch as many instructions per cycle as possible.
6483 unsigned MaxInstsPerLine = 16;
6484 unsigned UC = 1;
6485 unsigned BestUC = 1;
6486 unsigned SizeWithBestUC = BestUC * Size;
6487 while (UC <= 8) {
6488 unsigned SizeWithUC = UC * Size;
6489 if (SizeWithUC > 48)
6490 break;
6491 if ((SizeWithUC % MaxInstsPerLine) == 0 ||
6492 (SizeWithBestUC % MaxInstsPerLine) < (SizeWithUC % MaxInstsPerLine)) {
6493 BestUC = UC;
6494 SizeWithBestUC = BestUC * Size;
6495 }
6496 UC++;
6497 }
6498
6499 if (BestUC == 1)
6500 return;
6501
6502 SmallPtrSet<Value *, 8> LoadedValuesPlus;
6504 for (auto *BB : L->blocks()) {
6505 for (auto &I : *BB) {
6507 if (!Ptr)
6508 continue;
6509 const SCEV *PtrSCEV = SE.getSCEV(Ptr);
6510 if (SE.isLoopInvariant(PtrSCEV, L))
6511 continue;
6512 if (isa<LoadInst>(&I)) {
6513 LoadedValuesPlus.insert(&I);
6514 // Include in-loop 1st users of loaded values.
6515 for (auto *U : I.users())
6516 if (L->contains(cast<Instruction>(U)))
6517 LoadedValuesPlus.insert(U);
6518 } else
6519 Stores.push_back(cast<StoreInst>(&I));
6520 }
6521 }
6522
6523 if (none_of(Stores, [&LoadedValuesPlus](StoreInst *SI) {
6524 return LoadedValuesPlus.contains(SI->getOperand(0));
6525 }))
6526 return;
6527
6528 UP.Runtime = true;
6529 UP.DefaultUnrollRuntimeCount = BestUC;
6530 return;
6531 }
6532
6533 // Try to runtime-unroll loops with early-continues depending on loop-varying
6534 // loads; this helps with branch-prediction for the early-continues.
6535 auto *Term = dyn_cast<CondBrInst>(Header->getTerminator());
6537 if (!Term || Preds.size() == 1 || !llvm::is_contained(Preds, Header) ||
6538 none_of(Preds, [L](BasicBlock *Pred) { return L->contains(Pred); }))
6539 return;
6540
6541 std::function<bool(Instruction *, unsigned)> DependsOnLoopLoad =
6542 [&](Instruction *I, unsigned Depth) -> bool {
6543 if (isa<PHINode>(I) || L->isLoopInvariant(I) || Depth > 8)
6544 return false;
6545
6546 if (isa<LoadInst>(I))
6547 return true;
6548
6549 return any_of(I->operands(), [&](Value *V) {
6550 auto *I = dyn_cast<Instruction>(V);
6551 return I && DependsOnLoopLoad(I, Depth + 1);
6552 });
6553 };
6555 Instruction *I;
6556 if (match(Term, m_Br(m_ICmp(Pred, m_Instruction(I), m_Value()), m_Value(),
6557 m_Value())) &&
6558 DependsOnLoopLoad(I, 0)) {
6559 UP.Runtime = true;
6560 }
6561}
6562
6565 OptimizationRemarkEmitter *ORE) const {
6566 // Enable partial unrolling and runtime unrolling.
6567 BaseT::getUnrollingPreferences(L, SE, UP, ORE);
6568
6569 UP.UpperBound = true;
6570
6571 // A loop can have a small maximum trip count while SCEV still cannot
6572 // form an exact backedge count - typically a data-dependent exit, e.g.
6573 // shifting a value until it reaches zero. Unlike for counted loops, the
6574 // unrolled body keeps an exit test per iteration, and whether that pays
6575 // off depends on how many iterations the loop usually runs, which is
6576 // unknown at compile time; the code growth and extra branches are certain.
6577 // Be conservative and hold such loops to a lower upper bound; 5 still lets
6578 // smaller early-exit loops unroll. Also disable runtime unrolling, which
6579 // would clamp the unroll count to the known maximum trip count and produce
6580 // the same complete unroll.
6581 if (L->getExitingBlock() && !SE.isBackedgeTakenCountMaxOrZero(L) &&
6583 UP.MaxUpperBound = 5;
6584 UP.Runtime = false;
6585 }
6586
6587 // For inner loop, it is more likely to be a hot one, and the runtime check
6588 // can be promoted out from LICM pass, so the overhead is less, let's try
6589 // a larger threshold to unroll more loops.
6590 if (L->getLoopDepth() > 1)
6591 UP.PartialThreshold *= 2;
6592
6593 // Disable partial & runtime unrolling on -Os.
6595
6596 // Scan the loop: don't unroll loops with calls as this could prevent
6597 // inlining. Don't unroll auto-vectorized loops either, though do allow
6598 // unrolling of the scalar remainder.
6599 bool IsVectorized = getBooleanLoopAttribute(L, "llvm.loop.isvectorized");
6601 for (auto *BB : L->getBlocks()) {
6602 for (auto &I : *BB) {
6603 // Both auto-vectorized loops and the scalar remainder have the
6604 // isvectorized attribute, so differentiate between them by the presence
6605 // of vector instructions.
6606 if (IsVectorized && I.getType()->isVectorTy())
6607 return;
6608 if (isa<CallBase>(I)) {
6611 if (!isLoweredToCall(F))
6612 continue;
6613 return;
6614 }
6615
6616 // The cost is only compared against Aarch64ForceUnrollThreshold below.
6617 if (Cost >= ST->getCLOpts().force_unroll_threshold)
6618 continue;
6619 SmallVector<const Value *, 4> Operands(I.operand_values());
6622 }
6623 }
6624
6625 // Apply subtarget-specific unrolling preferences.
6626 if (ST->isAppleMLike())
6627 getAppleRuntimeUnrollPreferences(L, SE, UP, *this);
6628 else if (ST->getProcFamily() == AArch64Subtarget::Falkor &&
6629 ST->getCLOpts().enable_falkor_hwpf_unroll_fix)
6631
6632 // If this is a small, multi-exit loop similar to something like std::find,
6633 // then there is typically a performance improvement achieved by unrolling.
6634 if (!L->getExitBlock() && shouldUnrollMultiExitLoop(L, SE, *this)) {
6635 UP.RuntimeUnrollMultiExit = true;
6636 UP.Runtime = true;
6637 // Limit unroll count.
6639 // Allow slightly more costly trip-count expansion to catch search loops
6640 // with pointer inductions.
6641 UP.SCEVExpansionBudget = 5;
6642 return;
6643 }
6644
6645 // Enable runtime unrolling for in-order models
6646 // If mcpu is omitted, getProcFamily() returns AArch64Subtarget::Others, so by
6647 // checking for that case, we can ensure that the default behaviour is
6648 // unchanged
6649 if (ST->getProcFamily() != AArch64Subtarget::Generic &&
6650 !ST->getSchedModel().isOutOfOrder()) {
6651 UP.Runtime = true;
6652 UP.Partial = true;
6653 UP.UnrollRemainder = true;
6655
6656 UP.UnrollAndJam = true;
6658 }
6659
6660 // Force unrolling small loops can be very useful because of the branch
6661 // taken cost of the backedge.
6662 if (Cost < ST->getCLOpts().force_unroll_threshold)
6663 UP.Force = true;
6664}
6665
6670
6672 Type *ExpectedType,
6673 bool CanCreate) const {
6674 switch (Inst->getIntrinsicID()) {
6675 default:
6676 return nullptr;
6677 case Intrinsic::aarch64_neon_st1x2:
6678 case Intrinsic::aarch64_neon_st1x3:
6679 case Intrinsic::aarch64_neon_st1x4:
6680 case Intrinsic::aarch64_neon_st2:
6681 case Intrinsic::aarch64_neon_st3:
6682 case Intrinsic::aarch64_neon_st4: {
6683 // Create a struct type
6684 StructType *ST = dyn_cast<StructType>(ExpectedType);
6685 if (!CanCreate || !ST)
6686 return nullptr;
6687 unsigned NumElts = Inst->arg_size() - 1;
6688 if (ST->getNumElements() != NumElts)
6689 return nullptr;
6690 for (unsigned i = 0, e = NumElts; i != e; ++i) {
6691 if (Inst->getArgOperand(i)->getType() != ST->getElementType(i))
6692 return nullptr;
6693 }
6694 Value *Res = PoisonValue::get(ExpectedType);
6695 IRBuilder<> Builder(Inst);
6696 for (unsigned i = 0, e = NumElts; i != e; ++i) {
6697 Value *L = Inst->getArgOperand(i);
6698 Res = Builder.CreateInsertValue(Res, L, i);
6699 }
6700 return Res;
6701 }
6702 case Intrinsic::aarch64_neon_ld1x2:
6703 case Intrinsic::aarch64_neon_ld1x3:
6704 case Intrinsic::aarch64_neon_ld1x4:
6705 case Intrinsic::aarch64_neon_ld2:
6706 case Intrinsic::aarch64_neon_ld3:
6707 case Intrinsic::aarch64_neon_ld4:
6708 if (Inst->getType() == ExpectedType)
6709 return Inst;
6710 return nullptr;
6711 }
6712}
6713
6715 MemIntrinsicInfo &Info) const {
6716 switch (Inst->getIntrinsicID()) {
6717 default:
6718 break;
6719 case Intrinsic::aarch64_neon_ld1x2:
6720 case Intrinsic::aarch64_neon_ld1x3:
6721 case Intrinsic::aarch64_neon_ld1x4:
6722 case Intrinsic::aarch64_neon_ld2:
6723 case Intrinsic::aarch64_neon_ld3:
6724 case Intrinsic::aarch64_neon_ld4:
6725 Info.ReadMem = true;
6726 Info.WriteMem = false;
6727 Info.PtrVal = Inst->getArgOperand(0);
6728 break;
6729 case Intrinsic::aarch64_neon_st1x2:
6730 case Intrinsic::aarch64_neon_st1x3:
6731 case Intrinsic::aarch64_neon_st1x4:
6732 case Intrinsic::aarch64_neon_st2:
6733 case Intrinsic::aarch64_neon_st3:
6734 case Intrinsic::aarch64_neon_st4:
6735 Info.ReadMem = false;
6736 Info.WriteMem = true;
6737 Info.PtrVal = Inst->getArgOperand(Inst->arg_size() - 1);
6738 break;
6739 }
6740
6741 // Use the ID of neon load as the "matching id".
6742 switch (Inst->getIntrinsicID()) {
6743 default:
6744 return false;
6745 case Intrinsic::aarch64_neon_ld1x2:
6746 case Intrinsic::aarch64_neon_st1x2:
6747 Info.MatchingId = Intrinsic::aarch64_neon_ld1x2;
6748 break;
6749 case Intrinsic::aarch64_neon_ld1x3:
6750 case Intrinsic::aarch64_neon_st1x3:
6751 Info.MatchingId = Intrinsic::aarch64_neon_ld1x3;
6752 break;
6753 case Intrinsic::aarch64_neon_ld1x4:
6754 case Intrinsic::aarch64_neon_st1x4:
6755 Info.MatchingId = Intrinsic::aarch64_neon_ld1x4;
6756 break;
6757 case Intrinsic::aarch64_neon_ld2:
6758 case Intrinsic::aarch64_neon_st2:
6759 Info.MatchingId = Intrinsic::aarch64_neon_ld2;
6760 break;
6761 case Intrinsic::aarch64_neon_ld3:
6762 case Intrinsic::aarch64_neon_st3:
6763 Info.MatchingId = Intrinsic::aarch64_neon_ld3;
6764 break;
6765 case Intrinsic::aarch64_neon_ld4:
6766 case Intrinsic::aarch64_neon_st4:
6767 Info.MatchingId = Intrinsic::aarch64_neon_ld4;
6768 break;
6769 }
6770 return true;
6771}
6772
6773/// See if \p I should be considered for address type promotion. We check if \p
6774/// I is a sext with right type and used in memory accesses. If it used in a
6775/// "complex" getelementptr, we allow it to be promoted without finding other
6776/// sext instructions that sign extended the same initial value. A getelementptr
6777/// is considered as "complex" if it has more than 2 operands.
6779 const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const {
6780 bool Considerable = false;
6781 AllowPromotionWithoutCommonHeader = false;
6782 if (!isa<SExtInst>(&I))
6783 return false;
6784 Type *ConsideredSExtType =
6785 Type::getInt64Ty(I.getParent()->getParent()->getContext());
6786 if (I.getType() != ConsideredSExtType)
6787 return false;
6788 // See if the sext is the one with the right type and used in at least one
6789 // GetElementPtrInst.
6790 for (const User *U : I.users()) {
6791 if (const GetElementPtrInst *GEPInst = dyn_cast<GetElementPtrInst>(U)) {
6792 Considerable = true;
6793 // A getelementptr is considered as "complex" if it has more than 2
6794 // operands. We will promote a SExt used in such complex GEP as we
6795 // expect some computation to be merged if they are done on 64 bits.
6796 if (GEPInst->getNumOperands() > 2) {
6797 AllowPromotionWithoutCommonHeader = true;
6798 break;
6799 }
6800 }
6801 }
6802 return Considerable;
6803}
6804
6806 const RecurrenceDescriptor &RdxDesc, ElementCount VF) const {
6807 if (!VF.isScalable())
6808 return true;
6809
6810 Type *Ty = RdxDesc.getRecurrenceType();
6811 if (Ty->isBFloatTy() || !isElementTypeLegalForScalableVector(Ty))
6812 return false;
6813
6814 switch (RdxDesc.getRecurrenceKind()) {
6815 case RecurKind::Sub:
6816 case RecurKind::FSub:
6819 case RecurKind::Add:
6820 case RecurKind::FAdd:
6821 case RecurKind::And:
6822 case RecurKind::Or:
6823 case RecurKind::Xor:
6824 case RecurKind::SMin:
6825 case RecurKind::SMax:
6826 case RecurKind::UMin:
6827 case RecurKind::UMax:
6828 case RecurKind::FMin:
6829 case RecurKind::FMax:
6830 case RecurKind::FMulAdd:
6831 case RecurKind::AnyOf:
6833 return true;
6834 default:
6835 return false;
6836 }
6837}
6838
6841 FastMathFlags FMF,
6842 TTI::TargetCostKind CostKind) const {
6843 // The code-generator is currently not able to handle scalable vectors
6844 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
6845 // it. This change will be removed when code-generation for these types is
6846 // sufficiently reliable.
6847 if (auto *VTy = dyn_cast<ScalableVectorType>(Ty))
6848 if (VTy->getElementCount() == ElementCount::getScalable(1))
6850
6851 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Ty);
6852
6853 if (LT.second.getScalarType() == MVT::f16 && !ST->hasFullFP16())
6854 return BaseT::getMinMaxReductionCost(IID, Ty, FMF, CostKind);
6855
6856 InstructionCost LegalizationCost = 0;
6857 if (LT.first > 1) {
6858 Type *LegalVTy = EVT(LT.second).getTypeForEVT(Ty->getContext());
6859 IntrinsicCostAttributes Attrs(IID, LegalVTy, {LegalVTy, LegalVTy}, FMF);
6860 LegalizationCost = getIntrinsicInstrCost(Attrs, CostKind) * (LT.first - 1);
6861 }
6862
6863 return LegalizationCost + /*Cost of horizontal reduction*/ 2;
6864}
6865
6867 unsigned Opcode, VectorType *ValTy, TTI::TargetCostKind CostKind) const {
6868 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
6869 InstructionCost LegalizationCost = 0;
6870 if (LT.first > 1) {
6871 Type *LegalVTy = EVT(LT.second).getTypeForEVT(ValTy->getContext());
6872 LegalizationCost = getArithmeticInstrCost(Opcode, LegalVTy, CostKind);
6873 LegalizationCost *= LT.first - 1;
6874 }
6875
6876 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6877 assert(ISD && "Invalid opcode");
6878 // Add the final reduction cost for the legal horizontal reduction
6879 switch (ISD) {
6880 case ISD::ADD:
6881 case ISD::AND:
6882 case ISD::OR:
6883 case ISD::XOR:
6884 case ISD::FADD:
6885 return LegalizationCost + 2;
6886 default:
6888 }
6889}
6890
6893 std::optional<FastMathFlags> FMF,
6894 TTI::TargetCostKind CostKind) const {
6895 // The code-generator is currently not able to handle scalable vectors
6896 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
6897 // it. This change will be removed when code-generation for these types is
6898 // sufficiently reliable.
6899 if (auto *VTy = dyn_cast<ScalableVectorType>(ValTy))
6900 if (VTy->getElementCount() == ElementCount::getScalable(1))
6902
6904 if (auto *FixedVTy = dyn_cast<FixedVectorType>(ValTy)) {
6905 InstructionCost BaseCost =
6906 BaseT::getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind);
6907 // Add on extra cost to reflect the extra overhead on some CPUs. We still
6908 // end up vectorizing for more computationally intensive loops.
6909 return BaseCost + FixedVTy->getNumElements();
6910 }
6911
6912 if (Opcode != Instruction::FAdd || ValTy->getElementType()->isBFloatTy())
6914
6915 auto *VTy = cast<ScalableVectorType>(ValTy);
6917 getArithmeticInstrCost(Opcode, VTy->getScalarType(), CostKind);
6918 Cost *= getMaxNumElements(VTy->getElementCount());
6919 return Cost;
6920 }
6921
6922 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(ValTy);
6923 MVT MTy = LT.second;
6924
6925 if (isa<ScalableVectorType>(ValTy) || TLI->useSVEForFixedLengthVectorVT(MTy))
6926 return getArithmeticReductionCostSVE(Opcode, ValTy, CostKind);
6927
6928 int ISD = TLI->InstructionOpcodeToISD(Opcode);
6929 assert(ISD && "Invalid opcode");
6930
6931 // Horizontal adds can use the 'addv' instruction. We model the cost of these
6932 // instructions as twice a normal vector add, plus 1 for each legalization
6933 // step (LT.first). This is the only arithmetic vector reduction operation for
6934 // which we have an instruction.
6935 // OR, XOR and AND costs should match the codegen from:
6936 // OR: llvm/test/CodeGen/AArch64/reduce-or.ll
6937 // XOR: llvm/test/CodeGen/AArch64/reduce-xor.ll
6938 // AND: llvm/test/CodeGen/AArch64/reduce-and.ll
6939 static const CostTblEntry CostTblNoPairwise[]{
6940 {ISD::ADD, MVT::v8i8, 2},
6941 {ISD::ADD, MVT::v16i8, 2},
6942 {ISD::ADD, MVT::v4i16, 2},
6943 {ISD::ADD, MVT::v8i16, 2},
6944 {ISD::ADD, MVT::v2i32, 2},
6945 {ISD::ADD, MVT::v4i32, 2},
6946 {ISD::ADD, MVT::v2i64, 2},
6947 {ISD::OR, MVT::v8i8, 5}, // fmov + orr_lsr + orr_lsr + lsr + orr
6948 {ISD::OR, MVT::v16i8, 7}, // ext + orr + same as v8i8
6949 {ISD::OR, MVT::v4i16, 4}, // fmov + orr_lsr + lsr + orr
6950 {ISD::OR, MVT::v8i16, 6}, // ext + orr + same as v4i16
6951 {ISD::OR, MVT::v2i32, 3}, // fmov + lsr + orr
6952 {ISD::OR, MVT::v4i32, 5}, // ext + orr + same as v2i32
6953 {ISD::OR, MVT::v2i64, 3}, // ext + orr + fmov
6954 {ISD::XOR, MVT::v8i8, 5}, // Same as above for or...
6955 {ISD::XOR, MVT::v16i8, 7},
6956 {ISD::XOR, MVT::v4i16, 4},
6957 {ISD::XOR, MVT::v8i16, 6},
6958 {ISD::XOR, MVT::v2i32, 3},
6959 {ISD::XOR, MVT::v4i32, 5},
6960 {ISD::XOR, MVT::v2i64, 3},
6961 {ISD::AND, MVT::v8i8, 5}, // Same as above for or...
6962 {ISD::AND, MVT::v16i8, 7},
6963 {ISD::AND, MVT::v4i16, 4},
6964 {ISD::AND, MVT::v8i16, 6},
6965 {ISD::AND, MVT::v2i32, 3},
6966 {ISD::AND, MVT::v4i32, 5},
6967 {ISD::AND, MVT::v2i64, 3},
6968 };
6969 switch (ISD) {
6970 default:
6971 break;
6972 case ISD::FADD:
6973 if (Type *EltTy = ValTy->getScalarType();
6974 // FIXME: For half types without fullfp16 support, this could extend and
6975 // use a fp32 faddp reduction but current codegen unrolls.
6976 MTy.isVector() && (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
6977 (EltTy->isHalfTy() && ST->hasFullFP16()))) {
6978 const unsigned NElts = MTy.getVectorNumElements();
6979 if (ValTy->getElementCount().getFixedValue() >= 2 && NElts >= 2 &&
6980 isPowerOf2_32(NElts))
6981 // Reduction corresponding to series of fadd instructions is lowered to
6982 // series of faddp instructions. faddp has latency/throughput that
6983 // matches fadd instruction and hence, every faddp instruction can be
6984 // considered to have a relative cost = 1 with
6985 // CostKind = TCK_RecipThroughput.
6986 // An faddp will pairwise add vector elements, so the size of input
6987 // vector reduces by half every time, requiring
6988 // #(faddp instructions) = log2_32(NElts).
6989 return (LT.first - 1) + /*No of faddp instructions*/ Log2_32(NElts);
6990 }
6991 break;
6992 case ISD::ADD:
6993 if (const auto *Entry = CostTableLookup(CostTblNoPairwise, ISD, MTy))
6994 return (LT.first - 1) + Entry->Cost;
6995 break;
6996 case ISD::XOR:
6997 case ISD::AND:
6998 case ISD::OR:
6999 const auto *Entry = CostTableLookup(CostTblNoPairwise, ISD, MTy);
7000 if (!Entry)
7001 break;
7002 auto *ValVTy = cast<FixedVectorType>(ValTy);
7003 if (MTy.getVectorNumElements() <= ValVTy->getNumElements() &&
7004 isPowerOf2_32(ValVTy->getNumElements())) {
7005 InstructionCost ExtraCost = 0;
7006 if (LT.first != 1) {
7007 // Type needs to be split, so there is an extra cost of LT.first - 1
7008 // arithmetic ops.
7009 auto *Ty = FixedVectorType::get(ValTy->getElementType(),
7010 MTy.getVectorNumElements());
7011 ExtraCost = getArithmeticInstrCost(Opcode, Ty, CostKind);
7012 ExtraCost *= LT.first - 1;
7013 }
7014 // All and/or/xor of i1 will be lowered with maxv/minv/addv + fmov
7015 auto Cost = ValVTy->getElementType()->isIntegerTy(1) ? 2 : Entry->Cost;
7016 return Cost + ExtraCost;
7017 }
7018 break;
7019 }
7020 return BaseT::getArithmeticReductionCost(Opcode, ValTy, FMF, CostKind);
7021}
7022
7024 unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *VecTy,
7025 std::optional<FastMathFlags> FMF, TTI::TargetCostKind CostKind) const {
7026 EVT VecVT = TLI->getValueType(DL, VecTy);
7027 EVT ResVT = TLI->getValueType(DL, ResTy);
7028
7029 if (Opcode == Instruction::Add && VecVT.isSimple() && ResVT.isSimple() &&
7030 VecVT.getSizeInBits() >= 64) {
7031 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(VecTy);
7032
7033 // The legal cases are:
7034 // UADDLV 8/16/32->32
7035 // UADDLP 32->64
7036 unsigned RevVTSize = ResVT.getSizeInBits();
7037 if (((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7038 RevVTSize <= 32) ||
7039 ((LT.second == MVT::v4i16 || LT.second == MVT::v8i16) &&
7040 RevVTSize <= 32) ||
7041 ((LT.second == MVT::v2i32 || LT.second == MVT::v4i32) &&
7042 RevVTSize <= 64))
7043 return (LT.first - 1) * 2 + 2;
7044 }
7045
7046 return BaseT::getExtendedReductionCost(Opcode, IsUnsigned, ResTy, VecTy, FMF,
7047 CostKind);
7048}
7049
7051AArch64TTIImpl::getMulAccReductionCost(bool IsUnsigned, unsigned RedOpcode,
7052 Type *ResTy, VectorType *VecTy,
7053 TTI::TargetCostKind CostKind) const {
7054 EVT VecVT = TLI->getValueType(DL, VecTy);
7055 EVT ResVT = TLI->getValueType(DL, ResTy);
7056
7057 if (ST->hasDotProd() && VecVT.isSimple() && ResVT.isSimple() &&
7058 RedOpcode == Instruction::Add) {
7059 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(VecTy);
7060
7061 // The legal cases with dotprod are
7062 // UDOT 8->32
7063 // Which requires an additional uaddv to sum the i32 values.
7064 if ((LT.second == MVT::v8i8 || LT.second == MVT::v16i8) &&
7065 ResVT == MVT::i32)
7066 return LT.first + 2;
7067 }
7068
7069 return BaseT::getMulAccReductionCost(IsUnsigned, RedOpcode, ResTy, VecTy,
7070 CostKind);
7071}
7072
7075 TTI::TargetCostKind CostKind) const {
7076 static const CostTblEntry ShuffleTbl[] = {
7077 { TTI::SK_Splice, MVT::nxv16i8, 1 },
7078 { TTI::SK_Splice, MVT::nxv8i16, 1 },
7079 { TTI::SK_Splice, MVT::nxv4i32, 1 },
7080 { TTI::SK_Splice, MVT::nxv2i64, 1 },
7081 { TTI::SK_Splice, MVT::nxv2f16, 1 },
7082 { TTI::SK_Splice, MVT::nxv4f16, 1 },
7083 { TTI::SK_Splice, MVT::nxv8f16, 1 },
7084 { TTI::SK_Splice, MVT::nxv2bf16, 1 },
7085 { TTI::SK_Splice, MVT::nxv4bf16, 1 },
7086 { TTI::SK_Splice, MVT::nxv8bf16, 1 },
7087 { TTI::SK_Splice, MVT::nxv2f32, 1 },
7088 { TTI::SK_Splice, MVT::nxv4f32, 1 },
7089 { TTI::SK_Splice, MVT::nxv2f64, 1 },
7090 };
7091
7092 // The code-generator is currently not able to handle scalable vectors
7093 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
7094 // it. This change will be removed when code-generation for these types is
7095 // sufficiently reliable.
7098
7099 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(Tp);
7100 Type *LegalVTy = EVT(LT.second).getTypeForEVT(Tp->getContext());
7101 EVT PromotedVT = LT.second.getScalarType() == MVT::i1
7102 ? TLI->getPromotedVTForPredicate(EVT(LT.second))
7103 : LT.second;
7104 Type *PromotedVTy = EVT(PromotedVT).getTypeForEVT(Tp->getContext());
7105 InstructionCost LegalizationCost = 0;
7106 if (Index < 0) {
7107 LegalizationCost =
7108 getCmpSelInstrCost(Instruction::ICmp, PromotedVTy, PromotedVTy,
7109 CmpInst::BAD_ICMP_PREDICATE, CostKind) +
7110 getCmpSelInstrCost(Instruction::Select, PromotedVTy, LegalVTy,
7111 CmpInst::BAD_ICMP_PREDICATE, CostKind);
7112 }
7113
7114 // Predicated splice are promoted when lowering. See AArch64ISelLowering.cpp
7115 // Cost performed on a promoted type.
7116 if (LT.second.getScalarType() == MVT::i1) {
7117 LegalizationCost +=
7118 getCastInstrCost(Instruction::ZExt, PromotedVTy, LegalVTy,
7119 TTI::CastContextHint::None, CostKind) +
7120 getCastInstrCost(Instruction::Trunc, LegalVTy, PromotedVTy,
7121 TTI::CastContextHint::None, CostKind);
7122 }
7123 const auto *Entry =
7124 CostTableLookup(ShuffleTbl, TTI::SK_Splice, PromotedVT.getSimpleVT());
7125 assert(Entry && "Illegal Type for Splice");
7126 LegalizationCost += Entry->Cost;
7127 return LegalizationCost * LT.first;
7128}
7129
7131 unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType,
7133 TTI::PartialReductionExtendKind OpBExtend, std::optional<unsigned> BinOp,
7134 TTI::TargetCostKind CostKind, std::optional<FastMathFlags> FMF) const {
7136
7137 if (CostKind != TTI::TCK_RecipThroughput)
7138 return Invalid;
7139
7140 if ((Opcode != Instruction::Add && Opcode != Instruction::Sub &&
7141 Opcode != Instruction::FAdd && Opcode != Instruction::FSub))
7142 return Invalid;
7143
7144 // Floating-point partial reductions are invalid if `reassoc` and `contract`
7145 // are not allowed.
7146 if (AccumType->isFloatingPointTy()) {
7147 assert(FMF && "Missing FastMathFlags for floating-point partial reduction");
7148 if (!FMF->allowReassoc() || !FMF->allowContract())
7149 return Invalid;
7150 } else {
7151 assert(!FMF &&
7152 "FastMathFlags only apply to floating-point partial reductions");
7153 }
7154
7155 assert((BinOp || (OpBExtend == TTI::PR_None && !InputTypeB)) &&
7156 (!BinOp || (OpBExtend != TTI::PR_None && InputTypeB)) &&
7157 "Unexpected values for OpBExtend or InputTypeB");
7158
7159 // We only support multiply binary operations for now, and for muls we
7160 // require the types being extended to be the same.
7161 if (BinOp && ((*BinOp != Instruction::Mul && *BinOp != Instruction::FMul) ||
7162 InputTypeA != InputTypeB))
7163 return Invalid;
7164
7165 // We only support the following element sizes.
7166 if (!is_contained({8u, 16u, 32u, 64u}, AccumType->getScalarSizeInBits()))
7167 return Invalid;
7168
7169 // If none of the operands are extended and there's no extra BinOp, just
7170 // cost this as the equivalent arithmetic instruction.
7171 // TODO: Depending on VF and element type, we may be able to improve on this.
7172 if (!OpAExtend) {
7173 assert(!OpBExtend && "Extended second operand without extended first.");
7174 assert(InputTypeA == AccumType && "Type mismatch with no extensions.");
7175
7176 VectorType *VTy = VectorType::get(AccumType, VF);
7177 return getArithmeticInstrCost(Opcode, VTy, CostKind);
7178 }
7179
7180 bool IsUSDot = OpBExtend != TTI::PR_None && OpAExtend != OpBExtend;
7181 // USDot is natively supported with +i8mm. With plain +dotprod, SUMLA is
7182 // lowered to two udots plus an eor and a sub.
7183 if (IsUSDot && !ST->hasMatMulInt8() && !ST->hasDotProd())
7184 // FIXME: Remove this early bailout in favour of expand cost.
7185 return Invalid;
7186
7187 unsigned Ratio =
7188 AccumType->getScalarSizeInBits() / InputTypeA->getScalarSizeInBits();
7189 if (VF.getKnownMinValue() <= Ratio)
7190 return Invalid;
7191
7192 VectorType *InputVectorType = VectorType::get(InputTypeA, VF);
7193 VectorType *AccumVectorType =
7194 VectorType::get(AccumType, VF.divideCoefficientBy(Ratio));
7195 // We don't yet support all kinds of legalization.
7196 auto TC = TLI->getTypeConversion(AccumVectorType->getContext(),
7197 EVT::getEVT(AccumVectorType));
7198 switch (TC.first) {
7199 default:
7200 return Invalid;
7204 // The legalised type (e.g. after splitting) must be legal too.
7205 if (TLI->getTypeAction(AccumVectorType->getContext(), TC.second) !=
7207 return Invalid;
7208 break;
7209 }
7210
7211 std::pair<InstructionCost, MVT> AccumLT =
7212 getTypeLegalizationCost(AccumVectorType);
7213 std::pair<InstructionCost, MVT> InputLT =
7214 getTypeLegalizationCost(InputVectorType);
7215
7216 // Returns true if the subtarget supports the operation for a given type.
7217 auto IsSupported = [&](bool SVEPred, bool NEONPred) -> bool {
7218 return (ST->isSVEorStreamingSVEAvailable() && SVEPred) ||
7219 (AccumLT.second.isFixedLengthVector() &&
7220 AccumLT.second.getSizeInBits() <= 128 && ST->isNeonAvailable() &&
7221 NEONPred);
7222 };
7223
7224 bool IsSub = Opcode == Instruction::Sub || Opcode == Instruction::FSub;
7225 InstructionCost Cost = InputLT.first * TTI::TCC_Basic;
7226 // Integer partial sub-reductions that don't map to a specific instruction,
7227 // carry an extra cost for implementing a double negation:
7228 // partial_reduce_umls acc, lhs, rhs
7229 // <=> -partial_reduce_umla -acc, lhs, rhs
7230 InstructionCost INegCost = IsSub ? 2 * InputLT.first * TTI::TCC_Basic : 0;
7231
7232 if (AccumLT.second.getScalarType() == MVT::i32 &&
7233 InputLT.second.getScalarType() == MVT::i8) {
7234 // i8 -> i32 is natively supported with udot/sdot for both NEON and SVE.
7235 if (!IsUSDot && IsSupported(true, ST->hasDotProd()))
7236 return Cost + INegCost;
7237 // i8 -> i32 usdot requires +i8mm
7238 if (IsUSDot && IsSupported(ST->hasMatMulInt8(), ST->hasMatMulInt8()))
7239 return Cost + INegCost;
7240 // Without +i8mm, lower SUMLA via two udots plus an eor and a sub on plain
7241 // +dotprod targets. Note that this is only implemented for NEON, as all
7242 // modern CPUs with SVE also have +i8mm. Charge an extra factor for the
7243 // expansion.
7244 if (IsUSDot && IsSupported(false, ST->hasDotProd()))
7245 return Cost * 3 + INegCost;
7246 }
7247
7248 if (ST->isSVEorStreamingSVEAvailable() && !IsUSDot) {
7249 // i16 -> i64 is natively supported for udot/sdot
7250 if (AccumLT.second.getScalarType() == MVT::i64 &&
7251 InputLT.second.getScalarType() == MVT::i16)
7252 return Cost + INegCost;
7253 // i16 -> i32 is natively supported with SVE2p1 udot/sdot.
7254 // For sub-reductions, we prefer using the *mlslb/t instructions.
7255 if (AccumLT.second.getScalarType() == MVT::i32 &&
7256 InputLT.second.getScalarType() == MVT::i16 &&
7257 (ST->hasSVE2p1() || ST->hasSME2()) && !IsSub)
7258 return Cost;
7259 // i8 -> i64 is supported with an extra level of extends
7260 if (AccumLT.second.getScalarType() == MVT::i64 &&
7261 InputLT.second.getScalarType() == MVT::i8)
7262 // FIXME: Also account for folding the i32 dot product results into the
7263 // i64 accumulator, as the NEON case below does.
7264 return Cost + INegCost;
7265 // i8 -> i16 is natively supported with SVE2p3 udot/sdot
7266 // For sub-reductions, we prefer using the *mlslb/t instructions.
7267 if (AccumLT.second.getScalarType() == MVT::i16 &&
7268 InputLT.second.getScalarType() == MVT::i8 &&
7269 (ST->hasSVE2p3() || ST->hasSME2p3()) && !IsSub)
7270 return Cost;
7271 }
7272
7273 // With +dotprod, NEON lowers an extended i8 -> i64 partial reduction to a
7274 // udot/sdot into a zeroed i32 vector followed by an [SU]ADALP into the i64
7275 // accumulator. Charge one basic cost for each of the two steps per legal
7276 // input vector. This must stay after the SVE cases, as IsSupported's NEON
7277 // predicate also holds for fixed-length vectors on SVE targets.
7278 // TODO: Handle zero-extended multiplies and sub-reductions. In loops,
7279 // CodeGenPrepare turns zero extends that do not directly feed the partial
7280 // reduction (such as the operands of a multiply, or of the negation in a
7281 // sub-reduction) into TBLs, which hides the udot from instruction selection.
7282 // Sign-extended sub-reductions have not been measured yet.
7283 // TODO: Without +dotprod, pure adds with a ratio of 4 or 8 lower to a chain
7284 // of [SU]ADDLPs and an [SU]ADALP, which is not costed yet either.
7285 bool IsSExtMul = BinOp && OpAExtend == TTI::PR_SignExtend &&
7286 OpBExtend == TTI::PR_SignExtend;
7287 if ((!BinOp || IsSExtMul) && !IsSub &&
7288 AccumLT.second.getScalarType() == MVT::i64 &&
7289 InputLT.second.getScalarType() == MVT::i8 &&
7290 IsSupported(false, ST->hasDotProd()))
7291 return Cost * 2;
7292
7293 // f16 -> f32 is natively supported for fdot using either
7294 // SVE or NEON instruction.
7295 if (Opcode == Instruction::FAdd && !IsSub &&
7296 IsSupported(ST->hasSME2() || ST->hasSVE2p1(), ST->hasF16F32DOT()) &&
7297 AccumLT.second.getScalarType() == MVT::f32 &&
7298 InputLT.second.getScalarType() == MVT::f16)
7299 return Cost;
7300
7301 // For a ratio of 2, we can use *mlal and *mlsl top/bottom instructions.
7302 if (Ratio == 2 && !IsUSDot) {
7303 MVT InVT = InputLT.second.getScalarType();
7304
7305 // SVE2 [us]ml[as]lb/t and NEON [us]ml[as]l(2). A pure widening add with a
7306 // ratio of 2 can use [SU]ADALP instead.
7307 if (IsSupported(ST->hasSVE2() || ST->hasSME(), true) &&
7308 llvm::is_contained({MVT::i8, MVT::i16, MVT::i32}, InVT.SimpleTy))
7309 return (BinOp || IsSub) ? Cost * 2 : Cost;
7310
7311 // SVE2 fml[as]lb/t and NEON fml[as]l(2)
7312 if (IsSupported(ST->hasSVE2(), ST->hasFP16FML()) && InVT == MVT::f16)
7313 return Cost * 2;
7314
7315 // SME2/SVE2p1 bfmlslb/t
7316 if (IsSupported(ST->hasSVE2p1() || ST->hasSME2(), false) &&
7317 InVT == MVT::bf16 && IsSub)
7318 return Cost * 2;
7319
7320 // FP partial sub-reductions that don't map to a specific instruction,
7321 // carry an extra cost for implementing an extra negation:
7322 // partial_reduce_fmls acc, lhs, rhs
7323 // <=> partial_reduce_fmla acc, lhs, -rhs
7324 InstructionCost FNegCost = IsSub ? InputLT.first * TTI::TCC_Basic : 0;
7325
7326 // SVE and NEON bfmlalb/t
7327 if (IsSupported(ST->hasBF16(), ST->hasBF16()) && InVT == MVT::bf16)
7328 return Cost * 2 + FNegCost;
7329 }
7330
7331 return BaseT::getPartialReductionCost(Opcode, InputTypeA, InputTypeB,
7332 AccumType, VF, OpAExtend, OpBExtend,
7333 BinOp, CostKind, FMF);
7334}
7335
7337 TTI::ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy,
7338 TTI::TargetCostKind CostKind, ArrayRef<int> Mask, int Index,
7339 VectorType *SubTp, ArrayRef<const Value *> Args, const Instruction *CtxI,
7340 TTI::VectorInstrContext VIC) const {
7341 assert((Mask.empty() || DstTy->isScalableTy() ||
7342 Mask.size() == DstTy->getElementCount().getKnownMinValue()) &&
7343 "Expected the Mask to match the return size if given");
7344 assert(SrcTy->getScalarType() == DstTy->getScalarType() &&
7345 "Expected the same scalar types");
7346 std::pair<InstructionCost, MVT> LT = getTypeLegalizationCost(SrcTy);
7347
7348 // If we have a Mask, and the LT is being legalized somehow, split the Mask
7349 // into smaller vectors and sum the cost of each shuffle.
7350 if (!Mask.empty() && isa<FixedVectorType>(SrcTy) && LT.second.isVector() &&
7351 LT.second.getScalarSizeInBits() * Mask.size() > 128 &&
7352 SrcTy->getScalarSizeInBits() == LT.second.getScalarSizeInBits() &&
7353 Mask.size() > LT.second.getVectorNumElements() && !Index && !SubTp) {
7354 // Check for LD3/LD4 instructions, which are represented in llvm IR as
7355 // deinterleaving-shuffle(load). The shuffle cost could potentially be free,
7356 // but we model it with a cost of LT.first so that LD3/LD4 have a higher
7357 // cost than just the load.
7358 if (Args.size() >= 1 && isa<LoadInst>(Args[0]) &&
7361 return std::max<InstructionCost>(1, LT.first / 4);
7362
7363 // Check for ST3/ST4 instructions, which are represented in llvm IR as
7364 // store(interleaving-shuffle). The shuffle cost could potentially be free,
7365 // but we model it with a cost of LT.first so that ST3/ST4 have a higher
7366 // cost than just the store.
7367 if (CtxI && CtxI->hasOneUse() && isa<StoreInst>(*CtxI->user_begin()) &&
7369 Mask, 4, SrcTy->getElementCount().getKnownMinValue() * 2) ||
7371 Mask, 3, SrcTy->getElementCount().getKnownMinValue() * 2)))
7372 return LT.first;
7373
7374 unsigned TpNumElts = Mask.size();
7375 unsigned LTNumElts = LT.second.getVectorNumElements();
7376 unsigned NumVecs = (TpNumElts + LTNumElts - 1) / LTNumElts;
7377 VectorType *NTp = VectorType::get(SrcTy->getScalarType(),
7378 LT.second.getVectorElementCount());
7380 std::map<std::tuple<unsigned, unsigned, SmallVector<int>>, InstructionCost>
7381 PreviousCosts;
7382 for (unsigned N = 0; N < NumVecs; N++) {
7383 SmallVector<int> NMask;
7384 // Split the existing mask into chunks of size LTNumElts. Track the source
7385 // sub-vectors to ensure the result has at most 2 inputs.
7386 unsigned Source1 = -1U, Source2 = -1U;
7387 unsigned NumSources = 0;
7388 for (unsigned E = 0; E < LTNumElts; E++) {
7389 int MaskElt = (N * LTNumElts + E < TpNumElts) ? Mask[N * LTNumElts + E]
7391 if (MaskElt < 0) {
7393 continue;
7394 }
7395
7396 // Calculate which source from the input this comes from and whether it
7397 // is new to us.
7398 unsigned Source = MaskElt / LTNumElts;
7399 if (NumSources == 0) {
7400 Source1 = Source;
7401 NumSources = 1;
7402 } else if (NumSources == 1 && Source != Source1) {
7403 Source2 = Source;
7404 NumSources = 2;
7405 } else if (NumSources >= 2 && Source != Source1 && Source != Source2) {
7406 NumSources++;
7407 }
7408
7409 // Add to the new mask. For the NumSources>2 case these are not correct,
7410 // but are only used for the modular lane number.
7411 if (Source == Source1)
7412 NMask.push_back(MaskElt % LTNumElts);
7413 else if (Source == Source2)
7414 NMask.push_back(MaskElt % LTNumElts + LTNumElts);
7415 else
7416 NMask.push_back(MaskElt % LTNumElts);
7417 }
7418 // Check if we have already generated this sub-shuffle, which means we
7419 // will have already generated the output. For example a <16 x i32> splat
7420 // will be the same sub-splat 4 times, which only needs to be generated
7421 // once and reused.
7422 auto Result =
7423 PreviousCosts.insert({std::make_tuple(Source1, Source2, NMask), 0});
7424 // Check if it was already in the map (already costed).
7425 if (!Result.second)
7426 continue;
7427 // If the sub-mask has at most 2 input sub-vectors then re-cost it using
7428 // getShuffleCost. If not then cost it using the worst case as the number
7429 // of element moves into a new vector.
7430 InstructionCost NCost =
7431 NumSources <= 2
7432 ? getShuffleCost(NumSources <= 1 ? TTI::SK_PermuteSingleSrc
7434 NTp, NTp, CostKind, NMask, 0, nullptr, Args,
7435 CtxI)
7436 : LTNumElts;
7437 Result.first->second = NCost;
7438 Cost += NCost;
7439 }
7440 return Cost;
7441 }
7442
7443 Kind = improveShuffleKindFromMask(Kind, Mask, SrcTy, Index, SubTp);
7444 bool IsExtractSubvector = Kind == TTI::SK_ExtractSubvector;
7445 // A subvector extract can be implemented with a NEON/SVE ext (or trivial
7446 // extract, if from lane 0) for 128-bit NEON vectors or legal SVE vectors.
7447 // This currently only handles low or high extracts to prevent SLP vectorizer
7448 // regressions.
7449 // Note that SVE's ext instruction is destructive, but it can be fused with
7450 // a movprfx to act like a constructive instruction.
7451 if (IsExtractSubvector && LT.second.isFixedLengthVector()) {
7452 if (LT.second.getFixedSizeInBits() >= 128 &&
7453 cast<FixedVectorType>(SubTp)->getNumElements() ==
7454 LT.second.getVectorNumElements() / 2) {
7455 if (Index == 0)
7456 return 0;
7457 if (Index == (int)LT.second.getVectorNumElements() / 2)
7458 return 1;
7459 }
7461 }
7462 // FIXME: This was added to keep the costs equal when adding DstTys. Update
7463 // the code to handle length-changing shuffles.
7464 if (Kind == TTI::SK_InsertSubvector) {
7465 LT = getTypeLegalizationCost(DstTy);
7466 SrcTy = DstTy;
7467 }
7468
7469 // Check for identity masks, which we can treat as free for both fixed and
7470 // scalable vector paths.
7471 if (!Mask.empty() && LT.second.isFixedLengthVector() &&
7472 (Kind == TTI::SK_PermuteTwoSrc || Kind == TTI::SK_PermuteSingleSrc) &&
7473 all_of(enumerate(Mask), [](const auto &M) {
7474 return M.value() < 0 || M.value() == (int)M.index();
7475 }))
7476 return 0;
7477
7478 // Segmented shuffle matching.
7479 if (Kind == TTI::SK_PermuteSingleSrc && isa<FixedVectorType>(SrcTy) &&
7480 !Mask.empty() && SrcTy->getPrimitiveSizeInBits().isNonZero() &&
7481 SrcTy->getPrimitiveSizeInBits().isKnownMultipleOf(
7483
7485 unsigned Segments =
7487 unsigned SegmentElts = VTy->getNumElements() / Segments;
7488
7489 // dupq zd.t, zn.t[idx]
7490 if ((ST->hasSVE2p1() || ST->hasSME2p1()) &&
7491 ST->isSVEorStreamingSVEAvailable() &&
7492 isDUPQMask(Mask, Segments, SegmentElts))
7493 return LT.first;
7494
7495 // mov zd.q, vn
7496 if (ST->isSVEorStreamingSVEAvailable() &&
7497 isDUPFirstSegmentMask(Mask, Segments, SegmentElts))
7498 return LT.first;
7499 }
7500
7501 // Check for broadcast loads, which are supported by the LD1R instruction.
7502 // In terms of code-size, the shuffle vector is free when a load + dup get
7503 // folded into a LD1R. That's what we check and return here. For performance
7504 // and reciprocal throughput, a LD1R is not completely free. In this case, we
7505 // return the cost for the broadcast below (i.e. 1 for most/all types), so
7506 // that we model the load + dup sequence slightly higher because LD1R is a
7507 // high latency instruction.
7508 if (CostKind == TTI::TCK_CodeSize && Kind == TTI::SK_Broadcast) {
7509 bool IsLoad = !Args.empty() && isa<LoadInst>(Args[0]);
7510 if (IsLoad && LT.second.isVector() &&
7511 isLegalBroadcastLoad(SrcTy->getElementType(),
7512 LT.second.getVectorElementCount()))
7513 return 0;
7514 }
7515
7516 // If we have 4 elements for the shuffle and a Mask, get the cost straight
7517 // from the perfect shuffle tables.
7518 if (Mask.size() == 4 &&
7519 SrcTy->getElementCount() == ElementCount::getFixed(4) &&
7520 (SrcTy->getScalarSizeInBits() == 16 ||
7521 SrcTy->getScalarSizeInBits() == 32) &&
7522 all_of(Mask, [](int E) { return E < 8; }))
7523 return getPerfectShuffleCost(Mask);
7524
7525 // Check for other shuffles that are not SK_ kinds but we have native
7526 // instructions for, for example ZIP and UZP.
7527 unsigned Unused;
7528 if (LT.second.isFixedLengthVector() &&
7529 LT.second.getVectorNumElements() == Mask.size() &&
7530 (Kind == TTI::SK_PermuteTwoSrc || Kind == TTI::SK_PermuteSingleSrc ||
7531 // Discrepancies between isTRNMask and ShuffleVectorInst::isTransposeMask
7532 // mean that we can end up with shuffles that satisfy isTRNMask, but end
7533 // up labelled as TTI::SK_InsertSubvector. (e.g. {2, 0}).
7534 Kind == TTI::SK_InsertSubvector) &&
7535 (isZIPMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7536 isTRNMask(Mask, LT.second.getVectorNumElements(), Unused, Unused) ||
7537 isUZPMask(Mask, LT.second.getVectorNumElements(), Unused) ||
7538 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7539 LT.second.getVectorNumElements(), 16) ||
7540 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7541 LT.second.getVectorNumElements(), 32) ||
7542 isREVMask(Mask, LT.second.getScalarSizeInBits(),
7543 LT.second.getVectorNumElements(), 64) ||
7544 // Check for non-zero lane splats
7545 all_of(drop_begin(Mask),
7546 [&Mask](int M) { return M < 0 || M == Mask[0]; })))
7547 return 1;
7548
7549 if (Kind == TTI::SK_Broadcast || Kind == TTI::SK_Transpose ||
7550 Kind == TTI::SK_Select || Kind == TTI::SK_PermuteSingleSrc ||
7551 Kind == TTI::SK_Reverse || Kind == TTI::SK_Splice) {
7552 static const CostTblEntry ShuffleTbl[] = {
7553 // Broadcast shuffle kinds can be performed with 'dup'.
7554 {TTI::SK_Broadcast, MVT::v8i8, 1},
7555 {TTI::SK_Broadcast, MVT::v16i8, 1},
7556 {TTI::SK_Broadcast, MVT::v4i16, 1},
7557 {TTI::SK_Broadcast, MVT::v8i16, 1},
7558 {TTI::SK_Broadcast, MVT::v2i32, 1},
7559 {TTI::SK_Broadcast, MVT::v4i32, 1},
7560 {TTI::SK_Broadcast, MVT::v2i64, 1},
7561 {TTI::SK_Broadcast, MVT::v4f16, 1},
7562 {TTI::SK_Broadcast, MVT::v8f16, 1},
7563 {TTI::SK_Broadcast, MVT::v4bf16, 1},
7564 {TTI::SK_Broadcast, MVT::v8bf16, 1},
7565 {TTI::SK_Broadcast, MVT::v2f32, 1},
7566 {TTI::SK_Broadcast, MVT::v4f32, 1},
7567 {TTI::SK_Broadcast, MVT::v2f64, 1},
7568 // Transpose shuffle kinds can be performed with 'trn1/trn2' and
7569 // 'zip1/zip2' instructions.
7570 {TTI::SK_Transpose, MVT::v8i8, 1},
7571 {TTI::SK_Transpose, MVT::v16i8, 1},
7572 {TTI::SK_Transpose, MVT::v4i16, 1},
7573 {TTI::SK_Transpose, MVT::v8i16, 1},
7574 {TTI::SK_Transpose, MVT::v2i32, 1},
7575 {TTI::SK_Transpose, MVT::v4i32, 1},
7576 {TTI::SK_Transpose, MVT::v2i64, 1},
7577 {TTI::SK_Transpose, MVT::v4f16, 1},
7578 {TTI::SK_Transpose, MVT::v8f16, 1},
7579 {TTI::SK_Transpose, MVT::v4bf16, 1},
7580 {TTI::SK_Transpose, MVT::v8bf16, 1},
7581 {TTI::SK_Transpose, MVT::v2f32, 1},
7582 {TTI::SK_Transpose, MVT::v4f32, 1},
7583 {TTI::SK_Transpose, MVT::v2f64, 1},
7584 // Select shuffle kinds.
7585 // TODO: handle vXi8/vXi16.
7586 {TTI::SK_Select, MVT::v2i32, 1}, // mov.
7587 {TTI::SK_Select, MVT::v4i32, 2}, // rev+trn (or similar).
7588 {TTI::SK_Select, MVT::v2i64, 1}, // mov.
7589 {TTI::SK_Select, MVT::v2f32, 1}, // mov.
7590 {TTI::SK_Select, MVT::v4f32, 2}, // rev+trn (or similar).
7591 {TTI::SK_Select, MVT::v2f64, 1}, // mov.
7592 // PermuteSingleSrc shuffle kinds.
7593 {TTI::SK_PermuteSingleSrc, MVT::v2i32, 1}, // mov.
7594 {TTI::SK_PermuteSingleSrc, MVT::v4i32, 3}, // perfectshuffle worst case.
7595 {TTI::SK_PermuteSingleSrc, MVT::v2i64, 1}, // mov.
7596 {TTI::SK_PermuteSingleSrc, MVT::v2f32, 1}, // mov.
7597 {TTI::SK_PermuteSingleSrc, MVT::v4f32, 3}, // perfectshuffle worst case.
7598 {TTI::SK_PermuteSingleSrc, MVT::v2f64, 1}, // mov.
7599 {TTI::SK_PermuteSingleSrc, MVT::v4i16, 3}, // perfectshuffle worst case.
7600 {TTI::SK_PermuteSingleSrc, MVT::v4f16, 3}, // perfectshuffle worst case.
7601 {TTI::SK_PermuteSingleSrc, MVT::v4bf16, 3}, // same
7602 {TTI::SK_PermuteSingleSrc, MVT::v8i16, 8}, // constpool + load + tbl
7603 {TTI::SK_PermuteSingleSrc, MVT::v8f16, 8}, // constpool + load + tbl
7604 {TTI::SK_PermuteSingleSrc, MVT::v8bf16, 8}, // constpool + load + tbl
7605 {TTI::SK_PermuteSingleSrc, MVT::v8i8, 8}, // constpool + load + tbl
7606 {TTI::SK_PermuteSingleSrc, MVT::v16i8, 8}, // constpool + load + tbl
7607 // Reverse can be lowered with `rev`.
7608 {TTI::SK_Reverse, MVT::v2i32, 1}, // REV64
7609 {TTI::SK_Reverse, MVT::v4i32, 2}, // REV64; EXT
7610 {TTI::SK_Reverse, MVT::v2i64, 1}, // EXT
7611 {TTI::SK_Reverse, MVT::v2f32, 1}, // REV64
7612 {TTI::SK_Reverse, MVT::v4f32, 2}, // REV64; EXT
7613 {TTI::SK_Reverse, MVT::v2f64, 1}, // EXT
7614 {TTI::SK_Reverse, MVT::v8f16, 2}, // REV64; EXT
7615 {TTI::SK_Reverse, MVT::v8bf16, 2}, // REV64; EXT
7616 {TTI::SK_Reverse, MVT::v8i16, 2}, // REV64; EXT
7617 {TTI::SK_Reverse, MVT::v16i8, 2}, // REV64; EXT
7618 {TTI::SK_Reverse, MVT::v4f16, 1}, // REV64
7619 {TTI::SK_Reverse, MVT::v4bf16, 1}, // REV64
7620 {TTI::SK_Reverse, MVT::v4i16, 1}, // REV64
7621 {TTI::SK_Reverse, MVT::v8i8, 1}, // REV64
7622 // Splice can all be lowered as `ext`.
7623 {TTI::SK_Splice, MVT::v2i32, 1},
7624 {TTI::SK_Splice, MVT::v4i32, 1},
7625 {TTI::SK_Splice, MVT::v2i64, 1},
7626 {TTI::SK_Splice, MVT::v2f32, 1},
7627 {TTI::SK_Splice, MVT::v4f32, 1},
7628 {TTI::SK_Splice, MVT::v2f64, 1},
7629 {TTI::SK_Splice, MVT::v8f16, 1},
7630 {TTI::SK_Splice, MVT::v8bf16, 1},
7631 {TTI::SK_Splice, MVT::v8i16, 1},
7632 {TTI::SK_Splice, MVT::v16i8, 1},
7633 {TTI::SK_Splice, MVT::v4f16, 1},
7634 {TTI::SK_Splice, MVT::v4bf16, 1},
7635 {TTI::SK_Splice, MVT::v4i16, 1},
7636 {TTI::SK_Splice, MVT::v8i8, 1},
7637 // Broadcast shuffle kinds for scalable vectors
7638 {TTI::SK_Broadcast, MVT::nxv16i8, 1},
7639 {TTI::SK_Broadcast, MVT::nxv8i16, 1},
7640 {TTI::SK_Broadcast, MVT::nxv4i32, 1},
7641 {TTI::SK_Broadcast, MVT::nxv2i64, 1},
7642 {TTI::SK_Broadcast, MVT::nxv2f16, 1},
7643 {TTI::SK_Broadcast, MVT::nxv4f16, 1},
7644 {TTI::SK_Broadcast, MVT::nxv8f16, 1},
7645 {TTI::SK_Broadcast, MVT::nxv2bf16, 1},
7646 {TTI::SK_Broadcast, MVT::nxv4bf16, 1},
7647 {TTI::SK_Broadcast, MVT::nxv8bf16, 1},
7648 {TTI::SK_Broadcast, MVT::nxv2f32, 1},
7649 {TTI::SK_Broadcast, MVT::nxv4f32, 1},
7650 {TTI::SK_Broadcast, MVT::nxv2f64, 1},
7651 {TTI::SK_Broadcast, MVT::nxv16i1, 1},
7652 {TTI::SK_Broadcast, MVT::nxv8i1, 1},
7653 {TTI::SK_Broadcast, MVT::nxv4i1, 1},
7654 {TTI::SK_Broadcast, MVT::nxv2i1, 1},
7655 // Handle the cases for vector.reverse with scalable vectors
7656 {TTI::SK_Reverse, MVT::nxv16i8, 1},
7657 {TTI::SK_Reverse, MVT::nxv8i16, 1},
7658 {TTI::SK_Reverse, MVT::nxv4i32, 1},
7659 {TTI::SK_Reverse, MVT::nxv2i64, 1},
7660 {TTI::SK_Reverse, MVT::nxv2f16, 1},
7661 {TTI::SK_Reverse, MVT::nxv4f16, 1},
7662 {TTI::SK_Reverse, MVT::nxv8f16, 1},
7663 {TTI::SK_Reverse, MVT::nxv2bf16, 1},
7664 {TTI::SK_Reverse, MVT::nxv4bf16, 1},
7665 {TTI::SK_Reverse, MVT::nxv8bf16, 1},
7666 {TTI::SK_Reverse, MVT::nxv2f32, 1},
7667 {TTI::SK_Reverse, MVT::nxv4f32, 1},
7668 {TTI::SK_Reverse, MVT::nxv2f64, 1},
7669 {TTI::SK_Reverse, MVT::nxv16i1, 1},
7670 {TTI::SK_Reverse, MVT::nxv8i1, 1},
7671 {TTI::SK_Reverse, MVT::nxv4i1, 1},
7672 {TTI::SK_Reverse, MVT::nxv2i1, 1},
7673 };
7674 if (const auto *Entry = CostTableLookup(ShuffleTbl, Kind, LT.second))
7675 return LT.first * Entry->Cost;
7676 }
7677
7678 if (Kind == TTI::SK_Splice && isa<ScalableVectorType>(SrcTy))
7679 return getSpliceCost(SrcTy, Index, CostKind);
7680
7681 // Inserting a subvector can often be done with either a D, S or H register
7682 // move, so long as the inserted vector is "aligned".
7683 if (Kind == TTI::SK_InsertSubvector && LT.second.isFixedLengthVector() &&
7684 LT.second.getSizeInBits() <= 128 && SubTp) {
7685 std::pair<InstructionCost, MVT> SubLT = getTypeLegalizationCost(SubTp);
7686 if (SubLT.second.isVector()) {
7687 int NumElts = LT.second.getVectorNumElements();
7688 int NumSubElts = SubLT.second.getVectorNumElements();
7689 if ((Index % NumSubElts) == 0 && (NumElts % NumSubElts) == 0)
7690 return SubLT.first;
7691 }
7692 }
7693
7694 // Restore optimal kind.
7695 if (IsExtractSubvector)
7697 return BaseT::getShuffleCost(Kind, DstTy, SrcTy, CostKind, Mask, Index, SubTp,
7698 Args, CtxI);
7699}
7700
7703 const DominatorTree &DT) {
7704 const auto &Strides = SymbolicStrideMap();
7705 for (BasicBlock *BB : TheLoop->blocks()) {
7706 // Scan the instructions in the block and look for addresses that are
7707 // consecutive and decreasing.
7708 for (Instruction &I : *BB) {
7709 if (isa<LoadInst>(&I) || isa<StoreInst>(&I)) {
7711 Type *AccessTy = getLoadStoreType(&I);
7712 // Analyze assuming predicates will be added, but discard them; this
7713 // query only guides tail-folding and must not add runtime checks to the
7714 // loop.
7716 if (getPtrStride(*PSE, AccessTy, Ptr, TheLoop, DT, Strides,
7717 /*ShouldCheckWrap=*/false, &Predicates)
7718 .value_or(0) < 0)
7719 return true;
7720 }
7721 }
7722 }
7723 return false;
7724}
7725
7727 return valueOr(ST->getCLOpts().sve_prefer_fixed_over_scalable_if_equal,
7728 ST->useFixedOverScalableIfEqualCost());
7729}
7730
7732 return ST->getEpilogueVectorizationMinVF();
7733}
7734
7736 TailFoldingOpts DefaultOpts = ST->getSVETailFoldingDefaultOpts();
7737 if (!ST->hasSVE() || TailFoldingOptionLoc.isDisabled(DefaultOpts))
7738 return false;
7739
7740 // We don't currently support vectorisation with interleaving for SVE - with
7741 // such loops we're better off not using tail-folding. This gives us a chance
7742 // to fall back on fixed-width vectorisation using NEON's ld2/st2/etc.
7743 if (TFI->IAI->hasGroups())
7744 return false;
7745
7747 if (TFI->LVL->getReductionVars().size())
7748 Required |= TailFoldingOpts::Reductions;
7749 if (TFI->LVL->getFixedOrderRecurrences().size())
7750 Required |= TailFoldingOpts::Recurrences;
7751
7752 // We call this to discover whether any load/store pointers in the loop have
7753 // negative strides. This will require extra work to reverse the loop
7754 // predicate, which may be expensive.
7757 *TFI->LVL->getDominatorTree()))
7758 Required |= TailFoldingOpts::Reverse;
7759 if (Required == TailFoldingOpts::Disabled)
7760 Required |= TailFoldingOpts::Simple;
7761
7762 if (!TailFoldingOptionLoc.satisfies(DefaultOpts, Required))
7763 return false;
7764
7765 // Don't tail-fold for tight loops where we would be better off interleaving
7766 // with an unpredicated loop.
7767 unsigned NumInsns = 0;
7768 for (BasicBlock *BB : TFI->LVL->getLoop()->blocks()) {
7769 NumInsns += BB->size();
7770 }
7771
7772 // We expect 4 of these to be a IV PHI, IV add, IV compare and branch.
7773 return NumInsns >= ST->getCLOpts().sve_tail_folding_insn_threshold;
7774}
7775
7778 StackOffset BaseOffset, bool HasBaseReg,
7779 int64_t Scale, unsigned AddrSpace) const {
7780 // Scaling factors are not free at all.
7781 // Operands | Rt Latency
7782 // -------------------------------------------
7783 // Rt, [Xn, Xm] | 4
7784 // -------------------------------------------
7785 // Rt, [Xn, Xm, lsl #imm] | Rn: 4 Rm: 5
7786 // Rt, [Xn, Wm, <extend> #imm] |
7788 AM.BaseGV = BaseGV;
7789 AM.BaseOffs = BaseOffset.getFixed();
7790 AM.HasBaseReg = HasBaseReg;
7791 AM.Scale = Scale;
7792 AM.ScalableOffset = BaseOffset.getScalable();
7793 if (getTLI()->isLegalAddressingMode(DL, AM, Ty, AddrSpace))
7794 // Scale represents reg2 * scale, thus account for 1 if
7795 // it is not equal to 0 or 1.
7796 return AM.Scale != 0 && AM.Scale != 1;
7798}
7799
7801 const Instruction *I) const {
7802 if (ST->getCLOpts().enable_aarch64_or_like_select) {
7803 // For the binary operators (e.g. or) we need to be more careful than
7804 // selects, here we only transform them if they are already at a natural
7805 // break point in the code - the end of a block with an unconditional
7806 // terminator.
7807 if (I->getOpcode() == Instruction::Or &&
7808 isa<UncondBrInst>(I->getNextNode()))
7809 return true;
7810
7811 if (I->getOpcode() == Instruction::Add ||
7812 I->getOpcode() == Instruction::Sub)
7813 return true;
7814 }
7816}
7817
7820 const TargetTransformInfo::LSRCost &C2) const {
7821 // AArch64 specific here is adding the number of instructions to the
7822 // comparison (though not as the first consideration, as some targets do),
7823 // preferring lower number of pre/post-index if numregs and insns are equal,
7824 // as typically pre/post-index instructions use extra processor resources,
7825 // along with changing the priority of the base additions.
7826 // TODO: Maybe a more nuanced tradeoff between instruction count
7827 // and number of registers? To be investigated at a later date.
7828 if (ST->getCLOpts().enable_aarch64_lsr_cost_opt)
7829 return std::tie(C1.NumRegs, C1.Insns, C1.NumPrePostIndex, C1.NumBaseAdds,
7830 C1.AddRecCost, C1.NumIVMuls, C1.ScaleCost, C1.ImmCost,
7831 C1.SetupCost) <
7832 std::tie(C2.NumRegs, C2.Insns, C2.NumPrePostIndex, C2.NumBaseAdds,
7833 C2.AddRecCost, C2.NumIVMuls, C2.ScaleCost, C2.ImmCost,
7834 C2.SetupCost);
7835
7837}
7838
7839static bool isSplatShuffle(Value *V) {
7840 if (auto *Shuf = dyn_cast<ShuffleVectorInst>(V))
7841 return all_equal(Shuf->getShuffleMask());
7842 return false;
7843}
7844
7845/// Check if both Op1 and Op2 are shufflevector extracts of either the lower
7846/// or upper half of the vector elements.
7847static bool areExtractShuffleVectors(Value *Op1, Value *Op2,
7848 bool AllowSplat = false) {
7849 // Scalable types can't be extract shuffle vectors.
7850 if (Op1->getType()->isScalableTy() || Op2->getType()->isScalableTy())
7851 return false;
7852
7853 auto areTypesHalfed = [](Value *FullV, Value *HalfV) {
7854 auto *FullTy = FullV->getType();
7855 auto *HalfTy = HalfV->getType();
7856 return FullTy->getPrimitiveSizeInBits().getFixedValue() ==
7857 2 * HalfTy->getPrimitiveSizeInBits().getFixedValue();
7858 };
7859
7860 auto extractHalf = [](Value *FullV, Value *HalfV) {
7861 auto *FullVT = cast<FixedVectorType>(FullV->getType());
7862 auto *HalfVT = cast<FixedVectorType>(HalfV->getType());
7863 return FullVT->getNumElements() == 2 * HalfVT->getNumElements();
7864 };
7865
7866 ArrayRef<int> M1, M2;
7867 Value *S1Op1 = nullptr, *S2Op1 = nullptr;
7868 if (!match(Op1, m_Shuffle(m_Value(S1Op1), m_Undef(), m_Mask(M1))) ||
7869 !match(Op2, m_Shuffle(m_Value(S2Op1), m_Undef(), m_Mask(M2))))
7870 return false;
7871
7872 // If we allow splats, set S1Op1/S2Op1 to nullptr for the relevant arg so that
7873 // it is not checked as an extract below.
7874 if (AllowSplat && isSplatShuffle(Op1))
7875 S1Op1 = nullptr;
7876 if (AllowSplat && isSplatShuffle(Op2))
7877 S2Op1 = nullptr;
7878
7879 // Check that the operands are half as wide as the result and we extract
7880 // half of the elements of the input vectors.
7881 if ((S1Op1 && (!areTypesHalfed(S1Op1, Op1) || !extractHalf(S1Op1, Op1))) ||
7882 (S2Op1 && (!areTypesHalfed(S2Op1, Op2) || !extractHalf(S2Op1, Op2))))
7883 return false;
7884
7885 // Check the mask extracts either the lower or upper half of vector
7886 // elements.
7887 int M1Start = 0;
7888 int M2Start = 0;
7889 int NumElements = cast<FixedVectorType>(Op1->getType())->getNumElements() * 2;
7890 if ((S1Op1 &&
7891 !ShuffleVectorInst::isExtractSubvectorMask(M1, NumElements, M1Start)) ||
7892 (S2Op1 &&
7893 !ShuffleVectorInst::isExtractSubvectorMask(M2, NumElements, M2Start)))
7894 return false;
7895
7896 if ((M1Start != 0 && M1Start != (NumElements / 2)) ||
7897 (M2Start != 0 && M2Start != (NumElements / 2)))
7898 return false;
7899 if (S1Op1 && S2Op1 && M1Start != M2Start)
7900 return false;
7901
7902 return true;
7903}
7904
7905/// Check if Ext1 and Ext2 are extends of the same type, doubling the bitwidth
7906/// of the vector elements.
7907static bool areExtractExts(Value *Ext1, Value *Ext2) {
7908 auto areExtDoubled = [](Instruction *Ext) {
7909 return Ext->getType()->getScalarSizeInBits() ==
7910 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
7911 };
7912
7913 if (!match(Ext1, m_ZExtOrSExt(m_Value())) ||
7914 !match(Ext2, m_ZExtOrSExt(m_Value())) ||
7915 !areExtDoubled(cast<Instruction>(Ext1)) ||
7916 !areExtDoubled(cast<Instruction>(Ext2)))
7917 return false;
7918
7919 return true;
7920}
7921
7922/// Check if Op could be used with vmull_high_p64 intrinsic.
7924 Value *VectorOperand = nullptr;
7925 ConstantInt *ElementIndex = nullptr;
7926 return match(Op, m_ExtractElt(m_Value(VectorOperand),
7927 m_ConstantInt(ElementIndex))) &&
7928 ElementIndex->getValue() == 1 &&
7929 isa<FixedVectorType>(VectorOperand->getType()) &&
7930 cast<FixedVectorType>(VectorOperand->getType())->getNumElements() == 2;
7931}
7932
7933/// Check if Op1 and Op2 could be used with vmull_high_p64 intrinsic.
7934static bool areOperandsOfVmullHighP64(Value *Op1, Value *Op2) {
7936}
7937
7939 // Restrict ourselves to the form CodeGenPrepare typically constructs.
7940 auto *GEP = dyn_cast<GetElementPtrInst>(Ptrs);
7941 if (!GEP || GEP->getNumOperands() != 2)
7942 return false;
7943
7944 Value *Base = GEP->getOperand(0);
7945 Value *Offsets = GEP->getOperand(1);
7946
7947 // We only care about scalar_base+vector_offsets.
7948 if (Base->getType()->isVectorTy() || !Offsets->getType()->isVectorTy())
7949 return false;
7950
7951 // Sink extends that would allow us to use 32-bit offset vectors.
7952 if (isa<SExtInst>(Offsets) || isa<ZExtInst>(Offsets)) {
7953 auto *OffsetsInst = cast<Instruction>(Offsets);
7954 if (OffsetsInst->getType()->getScalarSizeInBits() > 32 &&
7955 OffsetsInst->getOperand(0)->getType()->getScalarSizeInBits() <= 32)
7956 Ops.push_back(&GEP->getOperandUse(1));
7957 }
7958
7959 // Sink the GEP.
7960 return true;
7961}
7962
7963/// We want to sink following cases:
7964/// (add|sub|gep) A, ((mul|shl) vscale, imm); (add|sub|gep) A, vscale;
7965/// (add|sub|gep) A, ((mul|shl) zext(vscale), imm);
7967 if (match(Op, m_VScale()))
7968 return true;
7969 if (match(Op, m_Shl(m_VScale(), m_ConstantInt())) ||
7971 Ops.push_back(&cast<Instruction>(Op)->getOperandUse(0));
7972 return true;
7973 }
7974 if (match(Op, m_Shl(m_ZExt(m_VScale()), m_ConstantInt())) ||
7976 Value *ZExtOp = cast<Instruction>(Op)->getOperand(0);
7977 Ops.push_back(&cast<Instruction>(ZExtOp)->getOperandUse(0));
7978 Ops.push_back(&cast<Instruction>(Op)->getOperandUse(0));
7979 return true;
7980 }
7981 return false;
7982}
7983
7984static bool isFNeg(Value *Op) {
7985 // TODO: Confirm whether m_FNegOrFSubNegZero is correct.
7986 return match(Op, m_FNegOrFSubNegZero(m_Value()));
7987}
7988
7989/// Check if sinking \p I's operands to I's basic block is profitable, because
7990/// the operands can be folded into a target instruction, e.g.
7991/// shufflevectors extracts and/or sext/zext can be folded into (u,s)subl(2).
7994 const LoopInfo *LI) const {
7996 switch (II->getIntrinsicID()) {
7997 case Intrinsic::aarch64_neon_smull:
7998 case Intrinsic::aarch64_neon_umull:
7999 if (areExtractShuffleVectors(II->getOperand(0), II->getOperand(1),
8000 /*AllowSplat=*/true)) {
8001 Ops.push_back(&II->getOperandUse(0));
8002 Ops.push_back(&II->getOperandUse(1));
8003 return true;
8004 }
8005 [[fallthrough]];
8006
8007 case Intrinsic::fma:
8008 case Intrinsic::fmuladd:
8009 if (isa<VectorType>(I->getType()) &&
8010 cast<VectorType>(I->getType())->getElementType()->isHalfTy() &&
8011 !ST->hasFullFP16())
8012 return false;
8013
8014 if (isFNeg(II->getOperand(0)))
8015 Ops.push_back(&II->getOperandUse(0));
8016 if (isFNeg(II->getOperand(1)))
8017 Ops.push_back(&II->getOperandUse(1));
8018
8019 [[fallthrough]];
8020 case Intrinsic::aarch64_neon_sqdmull:
8021 case Intrinsic::aarch64_neon_sqdmulh:
8022 case Intrinsic::aarch64_neon_sqrdmulh:
8023 // Sink splats for index lane variants
8024 if (isSplatShuffle(II->getOperand(0)))
8025 Ops.push_back(&II->getOperandUse(0));
8026 if (isSplatShuffle(II->getOperand(1)))
8027 Ops.push_back(&II->getOperandUse(1));
8028 return !Ops.empty();
8029 case Intrinsic::aarch64_neon_fmlal:
8030 case Intrinsic::aarch64_neon_fmlal2:
8031 case Intrinsic::aarch64_neon_fmlsl:
8032 case Intrinsic::aarch64_neon_fmlsl2:
8033 // Sink splats for index lane variants
8034 if (isSplatShuffle(II->getOperand(1)))
8035 Ops.push_back(&II->getOperandUse(1));
8036 if (isSplatShuffle(II->getOperand(2)))
8037 Ops.push_back(&II->getOperandUse(2));
8038 return !Ops.empty();
8039 case Intrinsic::aarch64_sve_ptest_first:
8040 case Intrinsic::aarch64_sve_ptest_last:
8041 if (auto *IIOp = dyn_cast<IntrinsicInst>(II->getOperand(0)))
8042 if (IIOp->getIntrinsicID() == Intrinsic::aarch64_sve_ptrue)
8043 Ops.push_back(&II->getOperandUse(0));
8044 return !Ops.empty();
8045 case Intrinsic::aarch64_sme_write_horiz:
8046 case Intrinsic::aarch64_sme_write_vert:
8047 case Intrinsic::aarch64_sme_writeq_horiz:
8048 case Intrinsic::aarch64_sme_writeq_vert: {
8049 auto *Idx = dyn_cast<Instruction>(II->getOperand(1));
8050 if (!Idx || Idx->getOpcode() != Instruction::Add)
8051 return false;
8052 Ops.push_back(&II->getOperandUse(1));
8053 return true;
8054 }
8055 case Intrinsic::aarch64_sme_read_horiz:
8056 case Intrinsic::aarch64_sme_read_vert:
8057 case Intrinsic::aarch64_sme_readq_horiz:
8058 case Intrinsic::aarch64_sme_readq_vert:
8059 case Intrinsic::aarch64_sme_ld1b_vert:
8060 case Intrinsic::aarch64_sme_ld1h_vert:
8061 case Intrinsic::aarch64_sme_ld1w_vert:
8062 case Intrinsic::aarch64_sme_ld1d_vert:
8063 case Intrinsic::aarch64_sme_ld1q_vert:
8064 case Intrinsic::aarch64_sme_st1b_vert:
8065 case Intrinsic::aarch64_sme_st1h_vert:
8066 case Intrinsic::aarch64_sme_st1w_vert:
8067 case Intrinsic::aarch64_sme_st1d_vert:
8068 case Intrinsic::aarch64_sme_st1q_vert:
8069 case Intrinsic::aarch64_sme_ld1b_horiz:
8070 case Intrinsic::aarch64_sme_ld1h_horiz:
8071 case Intrinsic::aarch64_sme_ld1w_horiz:
8072 case Intrinsic::aarch64_sme_ld1d_horiz:
8073 case Intrinsic::aarch64_sme_ld1q_horiz:
8074 case Intrinsic::aarch64_sme_st1b_horiz:
8075 case Intrinsic::aarch64_sme_st1h_horiz:
8076 case Intrinsic::aarch64_sme_st1w_horiz:
8077 case Intrinsic::aarch64_sme_st1d_horiz:
8078 case Intrinsic::aarch64_sme_st1q_horiz: {
8079 auto *Idx = dyn_cast<Instruction>(II->getOperand(3));
8080 if (!Idx || Idx->getOpcode() != Instruction::Add)
8081 return false;
8082 Ops.push_back(&II->getOperandUse(3));
8083 return true;
8084 }
8085 case Intrinsic::aarch64_neon_pmull:
8086 if (!areExtractShuffleVectors(II->getOperand(0), II->getOperand(1)))
8087 return false;
8088 Ops.push_back(&II->getOperandUse(0));
8089 Ops.push_back(&II->getOperandUse(1));
8090 return true;
8091 case Intrinsic::aarch64_neon_pmull64:
8092 if (!areOperandsOfVmullHighP64(II->getArgOperand(0),
8093 II->getArgOperand(1)))
8094 return false;
8095 Ops.push_back(&II->getArgOperandUse(0));
8096 Ops.push_back(&II->getArgOperandUse(1));
8097 return true;
8098 case Intrinsic::masked_gather:
8099 if (!shouldSinkVectorOfPtrs(II->getArgOperand(0), Ops))
8100 return false;
8101 Ops.push_back(&II->getArgOperandUse(0));
8102 return true;
8103 case Intrinsic::masked_scatter:
8104 if (!shouldSinkVectorOfPtrs(II->getArgOperand(1), Ops))
8105 return false;
8106 Ops.push_back(&II->getArgOperandUse(1));
8107 return true;
8108 default:
8109 return false;
8110 }
8111 }
8112
8113 auto ShouldSinkCondition = [](Value *Cond,
8114 SmallVectorImpl<Use *> &Ops) -> bool {
8116 return false;
8118 if (II->getIntrinsicID() != Intrinsic::vector_reduce_or ||
8119 !isa<ScalableVectorType>(II->getOperand(0)->getType()))
8120 return false;
8121 if (isa<CmpInst>(II->getOperand(0)))
8122 Ops.push_back(&II->getOperandUse(0));
8123 return true;
8124 };
8125
8126 switch (I->getOpcode()) {
8127 case Instruction::Store: {
8128 auto *SI = cast<StoreInst>(I);
8129 auto *II = dyn_cast<IntrinsicInst>(SI->getValueOperand());
8130 if (!SI->isSimple() || !II)
8131 break;
8132
8133 if (!LI ||
8134 LI->getLoopFor(SI->getParent()) != LI->getLoopFor(II->getParent()))
8135 break;
8136
8137 unsigned Factor = getInterleaveIntrinsicFactor(II->getIntrinsicID());
8138 if (Factor) {
8139 Ops.push_back(&SI->getOperandUse(0));
8140 return true;
8141 }
8142 break;
8143 }
8144 case Instruction::GetElementPtr:
8145 case Instruction::Add:
8146 case Instruction::Sub:
8147 // Sink vscales closer to uses for better isel
8148 for (unsigned Op = 0; Op < I->getNumOperands(); ++Op) {
8149 if (shouldSinkVScale(I->getOperand(Op), Ops)) {
8150 Ops.push_back(&I->getOperandUse(Op));
8151 return true;
8152 }
8153 }
8154 break;
8155 case Instruction::Select: {
8156 if (!ShouldSinkCondition(I->getOperand(0), Ops))
8157 return false;
8158
8159 Ops.push_back(&I->getOperandUse(0));
8160 return true;
8161 }
8162 case Instruction::UncondBr:
8163 return false;
8164 case Instruction::CondBr: {
8165 if (!ShouldSinkCondition(cast<CondBrInst>(I)->getCondition(), Ops))
8166 return false;
8167
8168 Ops.push_back(&I->getOperandUse(0));
8169 return true;
8170 }
8171 case Instruction::FMul:
8172 // fmul with contract flag can be combined with fadd into fma.
8173 // Sinking fneg into this block enables fmls pattern.
8174 if (cast<FPMathOperator>(I)->hasAllowContract()) {
8175 if (isFNeg(I->getOperand(0)))
8176 Ops.push_back(&I->getOperandUse(0));
8177 if (isFNeg(I->getOperand(1)))
8178 Ops.push_back(&I->getOperandUse(1));
8179 }
8180 break;
8181
8182 // Type | BIC | ORN | EON
8183 // ----------------+-----------+-----------+-----------
8184 // scalar | Base | Base | Base
8185 // scalar w/shift | - | - | -
8186 // fixed vector | NEON/Base | NEON/Base | BSL2N/Base
8187 // scalable vector | SVE | - | BSL2N
8188 case Instruction::Xor:
8189 // EON only for scalars (possibly expanded fixed vectors)
8190 // and vectors using the SVE2/SME BSL2N instruction.
8191 if (I->getType()->isVectorTy() && ST->isNeonAvailable()) {
8192 bool HasBSL2N =
8193 ST->isSVEorStreamingSVEAvailable() && (ST->hasSVE2() || ST->hasSME());
8194 if (!HasBSL2N)
8195 break;
8196 }
8197 [[fallthrough]];
8198 case Instruction::And:
8199 case Instruction::Or:
8200 // Even though we could use the SVE2/SME BSL2N instruction,
8201 // it might pessimize with an extra MOV depending on register allocation.
8202 if (I->getOpcode() == Instruction::Or &&
8203 isa<ScalableVectorType>(I->getType()))
8204 break;
8205 // Shift can be fold into scalar AND/ORR/EOR,
8206 // but not the non-negated operand of BIC/ORN/EON.
8207 if (!(I->getType()->isVectorTy() && ST->hasNEON()) &&
8209 break;
8210 for (auto &Op : I->operands()) {
8211 // (and/or/xor X, (not Y)) -> (bic/orn/eon X, Y)
8212 if (match(Op.get(), m_Not(m_Value()))) {
8213 Ops.push_back(&Op);
8214 return true;
8215 }
8216 // (and/or/xor X, (splat (not Y))) -> (bic/orn/eon X, (splat Y))
8217 if (match(Op.get(),
8219 m_Value(), m_ZeroMask()))) {
8220 Use &InsertElt = cast<Instruction>(Op)->getOperandUse(0);
8221 Use &Not = cast<Instruction>(InsertElt)->getOperandUse(1);
8222 Ops.push_back(&Not);
8223 Ops.push_back(&InsertElt);
8224 Ops.push_back(&Op);
8225 return true;
8226 }
8227 }
8228 break;
8229 default:
8230 break;
8231 }
8232
8233 if (!I->getType()->isVectorTy())
8234 return !Ops.empty();
8235
8236 switch (I->getOpcode()) {
8237 case Instruction::Sub:
8238 case Instruction::Add: {
8239 if (!areExtractExts(I->getOperand(0), I->getOperand(1)))
8240 return false;
8241
8242 // If the exts' operands extract either the lower or upper elements, we
8243 // can sink them too.
8244 auto Ext1 = cast<Instruction>(I->getOperand(0));
8245 auto Ext2 = cast<Instruction>(I->getOperand(1));
8246 if (areExtractShuffleVectors(Ext1->getOperand(0), Ext2->getOperand(0))) {
8247 Ops.push_back(&Ext1->getOperandUse(0));
8248 Ops.push_back(&Ext2->getOperandUse(0));
8249 }
8250
8251 Ops.push_back(&I->getOperandUse(0));
8252 Ops.push_back(&I->getOperandUse(1));
8253
8254 return true;
8255 }
8256 case Instruction::Or: {
8257 // Pattern: Or(And(MaskValue, A), And(Not(MaskValue), B)) ->
8258 // bitselect(MaskValue, A, B) where Not(MaskValue) = Xor(MaskValue, -1)
8259 if (ST->hasNEON()) {
8260 // MainAnd refers to And instruction that has 'Not' as one of its operands
8261 Instruction *MainAnd, *OtherAnd;
8262 Value *A, *B;
8263 if (matchBSL(I, MainAnd, OtherAnd, A, B)) {
8264 Ops.push_back(
8265 &MainAnd->getOperandUse(MainAnd->getOperand(0) == A ? 1 : 0));
8266 Ops.push_back(&I->getOperandUse(0));
8267 Ops.push_back(&I->getOperandUse(1));
8268
8269 return true;
8270 }
8271 }
8272
8273 return false;
8274 }
8275 case Instruction::Mul: {
8276 auto ShouldSinkSplatForIndexedVariant = [](Value *V) {
8277 auto *Ty = cast<VectorType>(V->getType());
8278 // For SVE the lane-indexing is within 128-bits, so we can't fold splats.
8279 if (Ty->isScalableTy())
8280 return false;
8281
8282 // Indexed variants of Mul exist for i16 and i32 element types only.
8283 return Ty->getScalarSizeInBits() == 16 || Ty->getScalarSizeInBits() == 32;
8284 };
8285
8286 int NumZExts = 0, NumSExts = 0;
8287 for (auto &Op : I->operands()) {
8288 // Make sure we are not already sinking this operand
8289 if (any_of(Ops, [&](Use *U) { return U->get() == Op; }))
8290 continue;
8291
8292 if (match(&Op, m_ZExtOrSExt(m_Value()))) {
8293 auto *Ext = cast<Instruction>(Op);
8294 auto *ExtOp = Ext->getOperand(0);
8295 if (isSplatShuffle(ExtOp) && ShouldSinkSplatForIndexedVariant(ExtOp))
8296 Ops.push_back(&Ext->getOperandUse(0));
8297 Ops.push_back(&Op);
8298
8299 if (isa<SExtInst>(Ext)) {
8300 NumSExts++;
8301 } else {
8302 NumZExts++;
8303 // A zext(a) is also a sext(zext(a)), if we take more than 2 steps.
8304 if (Ext->getOperand(0)->getType()->getScalarSizeInBits() * 2 <
8305 I->getType()->getScalarSizeInBits())
8306 NumSExts++;
8307 }
8308
8309 continue;
8310 }
8311
8313 if (!Shuffle)
8314 continue;
8315
8316 // If the Shuffle is a splat and the operand is a zext/sext, sinking the
8317 // operand and the s/zext can help create indexed s/umull. This is
8318 // especially useful to prevent i64 mul being scalarized.
8319 if (isSplatShuffle(Shuffle) &&
8320 match(Shuffle->getOperand(0), m_ZExtOrSExt(m_Value()))) {
8321 Ops.push_back(&Shuffle->getOperandUse(0));
8322 Ops.push_back(&Op);
8323 if (match(Shuffle->getOperand(0), m_SExt(m_Value())))
8324 NumSExts++;
8325 else
8326 NumZExts++;
8327 continue;
8328 }
8329
8330 Value *ShuffleOperand = Shuffle->getOperand(0);
8331 InsertElementInst *Insert = dyn_cast<InsertElementInst>(ShuffleOperand);
8332 if (!Insert)
8333 continue;
8334
8335 Instruction *OperandInstr = dyn_cast<Instruction>(Insert->getOperand(1));
8336 if (!OperandInstr)
8337 continue;
8338
8339 ConstantInt *ElementConstant =
8340 dyn_cast<ConstantInt>(Insert->getOperand(2));
8341 // Check that the insertelement is inserting into element 0
8342 if (!ElementConstant || !ElementConstant->isZero())
8343 continue;
8344
8345 unsigned Opcode = OperandInstr->getOpcode();
8346 if (Opcode == Instruction::SExt)
8347 NumSExts++;
8348 else if (Opcode == Instruction::ZExt)
8349 NumZExts++;
8350 else {
8351 // If we find that the top bits are known 0, then we can sink and allow
8352 // the backend to generate a umull.
8353 unsigned Bitwidth = I->getType()->getScalarSizeInBits();
8354 APInt UpperMask = APInt::getHighBitsSet(Bitwidth, Bitwidth / 2);
8355 if (!MaskedValueIsZero(OperandInstr, UpperMask, DL))
8356 continue;
8357 NumZExts++;
8358 }
8359
8360 // And(Load) is excluded to prevent CGP getting stuck in a loop of sinking
8361 // the And, just to hoist it again back to the load.
8362 if (!match(OperandInstr, m_And(m_Load(m_Value()), m_Value())))
8363 Ops.push_back(&Insert->getOperandUse(1));
8364 Ops.push_back(&Shuffle->getOperandUse(0));
8365 Ops.push_back(&Op);
8366 }
8367
8368 // It is profitable to sink if we found two of the same type of extends.
8369 if (!Ops.empty() && (NumSExts == 2 || NumZExts == 2))
8370 return true;
8371
8372 // Otherwise, see if we should sink splats for indexed variants.
8373 if (!ShouldSinkSplatForIndexedVariant(I))
8374 return false;
8375
8376 Ops.clear();
8377 if (isSplatShuffle(I->getOperand(0)))
8378 Ops.push_back(&I->getOperandUse(0));
8379 if (isSplatShuffle(I->getOperand(1)))
8380 Ops.push_back(&I->getOperandUse(1));
8381
8382 return !Ops.empty();
8383 }
8384 case Instruction::FMul: {
8385 // For SVE the lane-indexing is within 128-bits, so we can't fold splats.
8386 if (I->getType()->isScalableTy())
8387 return !Ops.empty();
8388
8389 if (cast<VectorType>(I->getType())->getElementType()->isHalfTy() &&
8390 !ST->hasFullFP16())
8391 return !Ops.empty();
8392
8393 // Sink splats for index lane variants
8394 if (isSplatShuffle(I->getOperand(0)))
8395 Ops.push_back(&I->getOperandUse(0));
8396 if (isSplatShuffle(I->getOperand(1)))
8397 Ops.push_back(&I->getOperandUse(1));
8398 return !Ops.empty();
8399 }
8400 default:
8401 return false;
8402 }
8403 return false;
8404}
8405
8407 Align Alignment) const {
8408 if (!(ST->isSVEAvailable() ||
8409 (ST->isSVEorStreamingSVEAvailable() && ST->hasSME2p2())))
8410 return false;
8411
8412 if (isa<FixedVectorType>(DataType) &&
8413 DataType->getPrimitiveSizeInBits().getFixedValue() < 128)
8414 return false;
8415
8416 if (!isa<VectorType>(DataType))
8417 return isElementTypeLegalForScalableVector(DataType);
8418
8419 auto LT = getTypeLegalizationCost(DataType);
8420 if (!LT.first.isValid())
8421 return false;
8422
8423 // Use the i32 or i64 compact instructions for f16/bf16 unpacked types.
8424 LLVMContext &Ctx = DataType->getContext();
8425 switch (LT.second.SimpleTy) {
8426 case MVT::nxv2f16:
8427 case MVT::nxv2bf16:
8429 case MVT::nxv4f16:
8430 case MVT::nxv4bf16:
8432 default:
8433 break;
8434 }
8435
8437 EVT(LT.second.getScalarType()).getTypeForEVT(Ctx));
8438}
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:2707
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2695
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:2370
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Definition IRBuilder.h:2585
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:2281
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:2729
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:2361
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:2947
This instruction inserts a single (scalar) element into a VectorType value.
The core instruction combiner logic.
virtual Instruction * eraseInstFromFunction(Instruction &I)=0
Combiner aware instruction erasure.
Instruction * replaceInstUsesWith(Instruction &I, Value *V)
A combiner-aware RAUW-like routine.
Instruction * replaceOperand(Instruction &I, unsigned OpNum, Value *V)
Replace operand of instruction and add old operand to the worklist.
static InstructionCost getInvalid(CostType Val=0)
CostType getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
LLVM_ABI bool isCommutative() const LLVM_READONLY
Return true if the instruction is commutative:
bool isBinaryOp() const
Instruction * user_back()
iterator_range< user_iterator > users()
LLVM_ABI FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
user_iterator user_begin()
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
Class to represent integer types.
bool hasGroups() const
Returns true if we have any interleave groups.
const SmallVectorImpl< Type * > & getArgTypes() const
const SmallVectorImpl< const Value * > & getArgs() const
const IntrinsicInst * getInst() const
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
An instruction for reading from memory.
Value * getPointerOperand()
iterator_range< block_iterator > blocks() const
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
RecurrenceSet & getFixedOrderRecurrences()
Return the fixed-order recurrences found in the loop.
PredicatedScalarEvolution * getPredicatedScalarEvolution() const
const ReductionList & getReductionVars() const
Returns the reduction variables found in the loop.
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
Machine Value Type.
SimpleValueType SimpleTy
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static MVT getScalableVectorVT(MVT VT, unsigned NumElements)
bool isFixedLengthVector() const
MVT getVectorElementType() const
size_type size() const
Definition MapVector.h:58
Information for memory intrinsic cost model.
const Instruction * getInst() const
The optimization diagnostic interface.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
The RecurrenceDescriptor is used to identify recurrences variables in a loop.
Type * getRecurrenceType() const
Returns the type of the recurrence.
RecurKind getRecurrenceKind() const
This node represents a polynomial recurrence on the trip count of the specified loop.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
This class represents an analyzed expression in the program.
SMEAttrs is a utility class to parse the SME ACLE attributes on functions.
bool hasStreamingCompatibleInterface() const
bool hasStreamingInterfaceOrBody() const
SMECallAttrs is a utility class to hold the SMEAttrs for a callsite.
static LLVM_ABI ScalableVectorType * get(Type *ElementType, unsigned MinNumElts)
Definition Type.cpp:865
static ScalableVectorType * getDoubleElementsVectorType(ScalableVectorType *VTy)
The main scalar evolution driver.
LLVM_ABI const SCEV * getBackedgeTakenCount(const Loop *L, ExitCountKind Kind=Exact)
If the specified loop has a predictable backedge-taken count, return it, otherwise return a SCEVCould...
LLVM_ABI unsigned getSmallConstantTripMultiple(const Loop *L, const SCEV *ExitCount)
Returns the largest constant divisor of the trip count as a normal unsigned value,...
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI unsigned getSmallConstantMaxTripCount(const Loop *L, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Returns the upper bound of the loop trip count as a normal unsigned value.
LLVM_ABI bool isBackedgeTakenCountMaxOrZero(const Loop *L)
Return true if the backedge taken count is either the value returned by getConstantMaxBackedgeTakenCo...
LLVM_ABI bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
const SCEV * getSymbolicMaxBackedgeTakenCount(const Loop *L)
When successful, this returns a SCEV that is greater than or equal to (i.e.
This instruction constructs a fixed permutation of two input vectors.
static LLVM_ABI bool isDeInterleaveMaskOfFactor(ArrayRef< int > Mask, unsigned Factor, unsigned &Index)
Check if the mask is a DE-interleave mask of the given factor Factor like: <Index,...
static LLVM_ABI bool isExtractSubvectorMask(ArrayRef< int > Mask, int NumSrcElts, int &Index)
Return true if this shuffle mask is an extract subvector mask.
static LLVM_ABI bool isInterleaveMask(ArrayRef< int > Mask, unsigned Factor, unsigned NumInputElts, SmallVectorImpl< unsigned > &StartIndexes)
Return true if the mask interleaves one or more input vectors together.
size_type size() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator insert(iterator I, T &&Elt)
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
Definition TypeSize.h:31
static StackOffset getScalable(int64_t Scalable)
Definition TypeSize.h:41
static StackOffset getFixed(int64_t Fixed)
Definition TypeSize.h:40
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
Class to represent struct types.
TargetInstrInfo - Interface to description of machine instruction set.
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:986
bool use_empty() const
Definition Value.h:348
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:396
Base class of all SIMD vector types.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
static VectorType * getInteger(VectorType *VTy)
This static method gets a VectorType with the same number of elements as the input type,...
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Type * getElementType() const
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:201
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:169
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
Definition TypeSize.h:253
const ParentTy * getParent() const
Definition ilist_node.h:34
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static bool isLogicalImmediate(uint64_t imm, unsigned regSize)
isLogicalImmediate - Return true if the immediate is valid for a logical immediate instruction of the...
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
LLVM_ABI APInt getCpuSupportsMask(ArrayRef< StringRef > Features)
static constexpr unsigned SVEBitsPerBlock
LLVM_ABI APInt getFMVPriority(ArrayRef< StringRef > Features)
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ Entry
Definition COFF.h:862
ISD namespace - This namespace contains an enum which represents all of the SelectionDAG node types a...
Definition ISDOpcodes.h:26
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:266
@ CTTZ_ELTS
Returns the number of number of trailing (least significant) zero elements in a vector.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:906
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:420
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:870
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:714
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:787
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:876
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:952
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:757
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:985
@ ADDRSPACECAST
ADDRSPACECAST - This operator converts between pointers of different address spaces.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:882
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI bool isTargetIntrinsic(ID IID)
isTargetIntrinsic - Returns true if IID is an intrinsic specific to a certain target.
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
AllOnesConstantMatch m_AllOnes()
CheckType m_SpecificType(LLT Ty)
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
auto m_Cmp()
Matches any compare instruction and ignore it.
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
BinaryOp_match< LHS, RHS, Instruction::And, true > m_c_And(const LHS &L, const RHS &R)
Matches an And with LHS and RHS in either order.
LogicalOp_match< LHS, RHS, Instruction::And > m_LogicalAnd(const LHS &L, const RHS &R)
Matches L && R either in the form of L & R or L ?
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
cst_pred_ty< is_nonnegative > m_NonNegative()
Match an integer or vector of non-negative values.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Xor, true > m_c_Xor(const LHS &L, const RHS &R)
Matches an Xor with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
auto m_VScale()
Matches a call to llvm.vscale().
OneOps_match< OpTy, Instruction::Load > m_Load(const OpTy &Op)
Matches LoadInst.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
is_zero< true > m_Zero()
Match any null constant or a vector with all elements equal to 0.
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
FNeg_match< OpTy, true > m_FNegOrFSubNegZero(const OpTy &X)
Match fneg X or fsub -0.0, X.
AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)
Matches a BinaryOperator with LHS and RHS in either order.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
BinOpPred_match< LHS, RHS, is_shift_op > m_Shift(const LHS &L, const RHS &R)
Matches shift operations.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
brc_match< Cond_t, match_bind< BasicBlock >, match_bind< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
auto m_Undef()
Match an arbitrary undef constant.
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
BinaryOp_match< LHS, RHS, Instruction::Or, true > m_c_Or(const LHS &L, const RHS &R)
Matches an Or with LHS and RHS in either order.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
LocationClass< Ty > location(Ty &L)
InstructionCost getVectorInstrCost(const TargetTransformInfo &TTI, bool ReVec, Type *ScalarTy, unsigned Opcode, Type *Val, const TTI::TargetCostKind CostKind, unsigned Index, Value *Scalar, ArrayRef< std::tuple< Value *, User *, int > > ScalarUserAndIdx, TTI::VectorInstrContext VIC)
This is similar to TargetTransformInfo::getVectorInstrCost, but if ScalarTy is a FixedVectorType,...
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Offset
Definition DWP.cpp:577
std::optional< unsigned > isDUPQMask(ArrayRef< int > Mask, unsigned Segments, unsigned SegmentSize)
isDUPQMask - matches a splat of equivalent lanes within segments of a given number of elements.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
const CostTblEntryT< CostType > * CostTableLookup(ArrayRef< CostTblEntryT< CostType > > Tbl, int ISD, MVT Ty)
Find in cost table.
Definition CostTable.h:36
LLVM_ABI bool getBooleanLoopAttribute(const Loop *TheLoop, StringRef Name)
Returns true if Name is applied to TheLoop and enabled.
bool isZIPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for zip1 or zip2 masks of the form: <0, 8, 1, 9, 2, 10, 3, 11> (WhichResultOut = 0,...
TailFoldingOpts
An enum to describe what types of loops we should attempt to tail-fold: Disabled: None Reductions: Lo...
InstructionCost Cost
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
@ Known
Known to have no common set bits.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
bool isDUPFirstSegmentMask(ArrayRef< int > Mask, unsigned Segments, unsigned SegmentSize)
isDUPFirstSegmentMask - matches a splat of the first 128b segment.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Uninitialized
Definition Threading.h:60
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI std::optional< int64_t > getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, const Loop *Lp, const DominatorTree &DT, const SymbolicStrideMap &StridesMap=SymbolicStrideMap(), bool ShouldCheckWrap=true, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
If the pointer has a constant stride return it in units of the access type size.
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
Definition STLExtras.h:2189
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI bool MaskedValueIsZero(const Value *V, const APInt &Mask, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if 'V & Mask' is known to be zero.
unsigned M1(unsigned Val)
Definition VE.h:394
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
LLVM_ABI bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)
Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...
unsigned getPerfectShuffleCost(llvm::ArrayRef< int > M)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
DenseMap< Value *, const SCEVUnknown * > SymbolicStrideMap
Maps a pointer to its symbolic (non-constant) stride.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1769
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
bool isUZPMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut)
Return true for uzp1 or uzp2 masks of the form: <0, 2, 4, 6, 8, 10, 12, 14> or <1,...
LLVM_ABI unsigned getInterleaveIntrinsicFactor(Intrinsic::ID ID)
Returns the corresponding factor of llvm.vector.interleaveN intrinsics.
bool isREVMask(ArrayRef< int > M, unsigned EltSize, unsigned NumElts, unsigned BlockSize)
isREVMask - Check if a vector shuffle corresponds to a REV instruction with the specified blocksize.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
constexpr int PoisonMaskElem
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
TargetTransformInfo TTI
LLVM_ABI Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a BinaryOperator, fold the result or return null.
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
@ Or
Bitwise or logical OR of integers.
@ FSub
Subtraction of floats.
@ FAddChainWithSubs
A chain of fadds and fsubs.
@ AnyOf
AnyOf reduction with select(cmp(),x,y) where one of (x,y) is loop invariant, and both x and y are int...
@ Xor
Bitwise or logical XOR of integers.
@ FindLast
FindLast reduction with select(cmp(),x,y) where x and y.
@ FMax
FP max implemented in terms of select(cmp()).
@ FMulAdd
Sum of float products with llvm.fmuladd(a * b + sum).
@ FMul
Product of floats.
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ And
Bitwise or logical AND of integers.
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ FMin
FP min implemented in terms of select(cmp()).
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
@ AddChainWithSubs
A chain of adds and subs.
@ FAdd
Sum of floats.
@ UMax
Unsigned integer max implemented in terms of select(cmp()).
DWARFExpression::Operation Op
TypeConversionCostTblEntryT< uint16_t > TypeConversionCostTblEntry
Definition CostTable.h:62
CostTblEntryT< uint16_t > CostTblEntry
Definition CostTable.h:31
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
unsigned getNumElementsFromSVEPredPattern(unsigned Pattern)
Return the number of active elements for VL1 to VL256 predicate pattern, zero for all other patterns.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
constexpr bool valueOr(BoolOrDefault X, bool Default)
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
Definition STLExtras.h:2182
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
const TypeConversionCostTblEntryT< CostType > * ConvertCostTableLookup(ArrayRef< TypeConversionCostTblEntryT< CostType > > Tbl, int ISD, MVT Dst, MVT Src)
Find in type conversion cost table.
Definition CostTable.h:67
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
Definition MathExtras.h:368
bool isTRNMask(ArrayRef< int > M, unsigned NumElts, unsigned &WhichResultOut, unsigned &OperandOrderOut)
Return true for trn1 or trn2 masks of the form: <0, 8, 2, 10, 4, 12, 6, 14> (WhichResultOut = 0,...
#define N
static SVEIntrinsicInfo defaultMergingUnaryNarrowingTopOp()
static SVEIntrinsicInfo defaultZeroingOp()
SVEIntrinsicInfo & setOperandIdxInactiveLanesTakenFrom(unsigned Index)
static SVEIntrinsicInfo defaultMergingOp(Intrinsic::ID IID=Intrinsic::not_intrinsic)
SVEIntrinsicInfo & setOperandIdxWithNoActiveLanes(unsigned Index)
unsigned getOperandIdxWithNoActiveLanes() const
CmpInst::Predicate getCmpPredicate() const
SVEIntrinsicInfo & setInactiveLanesAreUnused()
SVEIntrinsicInfo & setInactiveLanesAreNotDefined()
SVEIntrinsicInfo & setGoverningPredicateOperandIdx(unsigned Index)
static SVEIntrinsicInfo defaultUndefOp()
Intrinsic::ID getMatchingUndefIntrinsic() const
SVEIntrinsicInfo & setResultIsZeroInitialized()
static SVEIntrinsicInfo defaultMergingUnaryOp()
SVEIntrinsicInfo & setMatchingUndefIntrinsic(Intrinsic::ID IID)
unsigned getGoverningPredicateOperandIdx() const
SVEIntrinsicInfo & setCmpPredicate(CmpInst::Predicate Pred)
SVEIntrinsicInfo & setMatchingIROpcode(unsigned Opcode)
unsigned getOperandIdxInactiveLanesTakenFrom() const
static SVEIntrinsicInfo defaultVoidOp(unsigned GPIndex)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Extended Value Type.
Definition ValueTypes.h:35
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h: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:130
bool isVariant() const
Definition MCSchedule.h:151
Machine model for scheduling, bundling, and heuristics.
Definition MCSchedule.h:274
static LLVM_ABI double getReciprocalThroughput(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Matching combinators.
Information about a load/store intrinsic defined by the target.
InterleavedAccessInfo * IAI
LoopVectorizationLegality * LVL
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
unsigned Insns
TODO: Some of these could be merged.
Returns options for expansion of memcmp. IsZeroCmp is.
Parameters that control the generic loop unrolling transformation.
bool UpperBound
Allow using trip count upper bound to unroll loops.
bool Force
Apply loop unroll on any kind of loop (mainly to loops that fail runtime unrolling).
unsigned PartialOptSizeThreshold
The cost threshold for the unrolled loop when optimizing for size, like OptSizeThreshold,...
unsigned DefaultUnrollRuntimeCount
Default unroll count for loops with run-time trip count.
bool RuntimeUnrollMultiExit
Allow runtime unrolling multi-exit loops.
unsigned SCEVExpansionBudget
Don't allow runtime unrolling if expanding the trip count takes more than SCEVExpansionBudget.
bool AddAdditionalAccumulators
Allow unrolling to add parallel reduction phis.
unsigned UnrollAndJamInnerLoopThreshold
Threshold for unroll and jam, for inner loop size.
bool UnrollAndJam
Allow unroll and jam. Used to enable unroll and jam for the target.
bool UnrollRemainder
Allow unrolling of all the iterations of the runtime loop remainder.
unsigned PartialThreshold
The cost threshold for the unrolled loop, like Threshold, but used for partial/runtime unrolling (set...
bool Runtime
Allow runtime unrolling (unrolling of loops to expand the size of the loop body even when the number ...
bool Partial
Allow partial unrolling (unrolling of loops to expand the size of the loop body, not only to eliminat...
unsigned MaxUpperBound
Set the maximum upper bound of trip count.