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