1 //===-- AArch64TargetTransformInfo.cpp - AArch64 specific TTI -------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "AArch64TargetTransformInfo.h"
10 #include "AArch64ExpandImm.h"
11 #include "AArch64PerfectShuffle.h"
12 #include "MCTargetDesc/AArch64AddressingModes.h"
13 #include "llvm/Analysis/IVDescriptors.h"
14 #include "llvm/Analysis/LoopInfo.h"
15 #include "llvm/Analysis/TargetTransformInfo.h"
16 #include "llvm/CodeGen/BasicTTIImpl.h"
17 #include "llvm/CodeGen/CostTable.h"
18 #include "llvm/CodeGen/TargetLowering.h"
19 #include "llvm/IR/IntrinsicInst.h"
20 #include "llvm/IR/Intrinsics.h"
21 #include "llvm/IR/IntrinsicsAArch64.h"
22 #include "llvm/IR/PatternMatch.h"
23 #include "llvm/Support/Debug.h"
24 #include "llvm/Transforms/InstCombine/InstCombiner.h"
25 #include "llvm/Transforms/Vectorize/LoopVectorizationLegality.h"
29 using namespace llvm::PatternMatch
;
31 #define DEBUG_TYPE "aarch64tti"
33 static cl::opt
<bool> EnableFalkorHWPFUnrollFix("enable-falkor-hwpf-unroll-fix",
34 cl::init(true), cl::Hidden
);
36 static cl::opt
<unsigned> SVEGatherOverhead("sve-gather-overhead", cl::init(10),
39 static cl::opt
<unsigned> SVEScatterOverhead("sve-scatter-overhead",
40 cl::init(10), cl::Hidden
);
42 static cl::opt
<unsigned> SVETailFoldInsnThreshold("sve-tail-folding-insn-threshold",
43 cl::init(15), cl::Hidden
);
45 static cl::opt
<unsigned>
46 NeonNonConstStrideOverhead("neon-nonconst-stride-overhead", cl::init(10),
49 static cl::opt
<unsigned> CallPenaltyChangeSM(
50 "call-penalty-sm-change", cl::init(5), cl::Hidden
,
52 "Penalty of calling a function that requires a change to PSTATE.SM"));
54 static cl::opt
<unsigned> InlineCallPenaltyChangeSM(
55 "inline-call-penalty-sm-change", cl::init(10), cl::Hidden
,
56 cl::desc("Penalty of inlining a call that requires a change to PSTATE.SM"));
58 static cl::opt
<bool> EnableOrLikeSelectOpt("enable-aarch64-or-like-select",
59 cl::init(true), cl::Hidden
);
62 class TailFoldingOption
{
63 // These bitfields will only ever be set to something non-zero in operator=,
64 // when setting the -sve-tail-folding option. This option should always be of
65 // the form (default|simple|all|disable)[+(Flag1|Flag2|etc)], where here
66 // InitialBits is one of (disabled|all|simple). EnableBits represents
67 // additional flags we're enabling, and DisableBits for those flags we're
68 // disabling. The default flag is tracked in the variable NeedsDefault, since
69 // at the time of setting the option we may not know what the default value
71 TailFoldingOpts InitialBits
= TailFoldingOpts::Disabled
;
72 TailFoldingOpts EnableBits
= TailFoldingOpts::Disabled
;
73 TailFoldingOpts DisableBits
= TailFoldingOpts::Disabled
;
75 // This value needs to be initialised to true in case the user does not
76 // explicitly set the -sve-tail-folding option.
77 bool NeedsDefault
= true;
79 void setInitialBits(TailFoldingOpts Bits
) { InitialBits
= Bits
; }
81 void setNeedsDefault(bool V
) { NeedsDefault
= V
; }
83 void setEnableBit(TailFoldingOpts Bit
) {
88 void setDisableBit(TailFoldingOpts Bit
) {
93 TailFoldingOpts
getBits(TailFoldingOpts DefaultBits
) const {
94 TailFoldingOpts Bits
= TailFoldingOpts::Disabled
;
96 assert((InitialBits
== TailFoldingOpts::Disabled
|| !NeedsDefault
) &&
97 "Initial bits should only include one of "
98 "(disabled|all|simple|default)");
99 Bits
= NeedsDefault
? DefaultBits
: InitialBits
;
101 Bits
&= ~DisableBits
;
106 void reportError(std::string Opt
) {
107 errs() << "invalid argument '" << Opt
108 << "' to -sve-tail-folding=; the option should be of the form\n"
109 " (disabled|all|default|simple)[+(reductions|recurrences"
110 "|reverse|noreductions|norecurrences|noreverse)]\n";
111 report_fatal_error("Unrecognised tail-folding option");
116 void operator=(const std::string
&Val
) {
117 // If the user explicitly sets -sve-tail-folding= then treat as an error.
123 // Since the user is explicitly setting the option we don't automatically
124 // need the default unless they require it.
125 setNeedsDefault(false);
127 SmallVector
<StringRef
, 4> TailFoldTypes
;
128 StringRef(Val
).split(TailFoldTypes
, '+', -1, false);
130 unsigned StartIdx
= 1;
131 if (TailFoldTypes
[0] == "disabled")
132 setInitialBits(TailFoldingOpts::Disabled
);
133 else if (TailFoldTypes
[0] == "all")
134 setInitialBits(TailFoldingOpts::All
);
135 else if (TailFoldTypes
[0] == "default")
136 setNeedsDefault(true);
137 else if (TailFoldTypes
[0] == "simple")
138 setInitialBits(TailFoldingOpts::Simple
);
141 setInitialBits(TailFoldingOpts::Disabled
);
144 for (unsigned I
= StartIdx
; I
< TailFoldTypes
.size(); I
++) {
145 if (TailFoldTypes
[I
] == "reductions")
146 setEnableBit(TailFoldingOpts::Reductions
);
147 else if (TailFoldTypes
[I
] == "recurrences")
148 setEnableBit(TailFoldingOpts::Recurrences
);
149 else if (TailFoldTypes
[I
] == "reverse")
150 setEnableBit(TailFoldingOpts::Reverse
);
151 else if (TailFoldTypes
[I
] == "noreductions")
152 setDisableBit(TailFoldingOpts::Reductions
);
153 else if (TailFoldTypes
[I
] == "norecurrences")
154 setDisableBit(TailFoldingOpts::Recurrences
);
155 else if (TailFoldTypes
[I
] == "noreverse")
156 setDisableBit(TailFoldingOpts::Reverse
);
162 bool satisfies(TailFoldingOpts DefaultBits
, TailFoldingOpts Required
) const {
163 return (getBits(DefaultBits
) & Required
) == Required
;
168 TailFoldingOption TailFoldingOptionLoc
;
170 cl::opt
<TailFoldingOption
, true, cl::parser
<std::string
>> SVETailFolding(
173 "Control the use of vectorisation using tail-folding for SVE where the"
174 " option is specified in the form (Initial)[+(Flag1|Flag2|...)]:"
175 "\ndisabled (Initial) No loop types will vectorize using "
177 "\ndefault (Initial) Uses the default tail-folding settings for "
179 "\nall (Initial) All legal loop types will vectorize using "
181 "\nsimple (Initial) Use tail-folding for simple loops (not "
182 "reductions or recurrences)"
183 "\nreductions Use tail-folding for loops containing reductions"
184 "\nnoreductions Inverse of above"
185 "\nrecurrences Use tail-folding for loops containing fixed order "
187 "\nnorecurrences Inverse of above"
188 "\nreverse Use tail-folding for loops requiring reversed "
190 "\nnoreverse Inverse of above"),
191 cl::location(TailFoldingOptionLoc
));
193 // Experimental option that will only be fully functional when the
194 // code-generator is changed to use SVE instead of NEON for all fixed-width
196 static cl::opt
<bool> EnableFixedwidthAutovecInStreamingMode(
197 "enable-fixedwidth-autovec-in-streaming-mode", cl::init(false), cl::Hidden
);
199 // Experimental option that will only be fully functional when the cost-model
200 // and code-generator have been changed to avoid using scalable vector
201 // instructions that are not legal in streaming SVE mode.
202 static cl::opt
<bool> EnableScalableAutovecInStreamingMode(
203 "enable-scalable-autovec-in-streaming-mode", cl::init(false), cl::Hidden
);
205 static bool isSMEABIRoutineCall(const CallInst
&CI
) {
206 const auto *F
= CI
.getCalledFunction();
207 return F
&& StringSwitch
<bool>(F
->getName())
208 .Case("__arm_sme_state", true)
209 .Case("__arm_tpidr2_save", true)
210 .Case("__arm_tpidr2_restore", true)
211 .Case("__arm_za_disable", true)
215 /// Returns true if the function has explicit operations that can only be
216 /// lowered using incompatible instructions for the selected mode. This also
217 /// returns true if the function F may use or modify ZA state.
218 static bool hasPossibleIncompatibleOps(const Function
*F
) {
219 for (const BasicBlock
&BB
: *F
) {
220 for (const Instruction
&I
: BB
) {
221 // Be conservative for now and assume that any call to inline asm or to
222 // intrinsics could could result in non-streaming ops (e.g. calls to
223 // @llvm.aarch64.* or @llvm.gather/scatter intrinsics). We can assume that
224 // all native LLVM instructions can be lowered to compatible instructions.
225 if (isa
<CallInst
>(I
) && !I
.isDebugOrPseudoInst() &&
226 (cast
<CallInst
>(I
).isInlineAsm() || isa
<IntrinsicInst
>(I
) ||
227 isSMEABIRoutineCall(cast
<CallInst
>(I
))))
234 bool AArch64TTIImpl::areInlineCompatible(const Function
*Caller
,
235 const Function
*Callee
) const {
236 SMEAttrs
CallerAttrs(*Caller
), CalleeAttrs(*Callee
);
238 // When inlining, we should consider the body of the function, not the
240 if (CalleeAttrs
.hasStreamingBody()) {
241 CalleeAttrs
.set(SMEAttrs::SM_Compatible
, false);
242 CalleeAttrs
.set(SMEAttrs::SM_Enabled
, true);
245 if (CalleeAttrs
.hasNewZABody())
248 if (CallerAttrs
.requiresLazySave(CalleeAttrs
) ||
249 CallerAttrs
.requiresSMChange(CalleeAttrs
)) {
250 if (hasPossibleIncompatibleOps(Callee
))
254 const TargetMachine
&TM
= getTLI()->getTargetMachine();
256 const FeatureBitset
&CallerBits
=
257 TM
.getSubtargetImpl(*Caller
)->getFeatureBits();
258 const FeatureBitset
&CalleeBits
=
259 TM
.getSubtargetImpl(*Callee
)->getFeatureBits();
261 // Inline a callee if its target-features are a subset of the callers
263 return (CallerBits
& CalleeBits
) == CalleeBits
;
266 bool AArch64TTIImpl::areTypesABICompatible(
267 const Function
*Caller
, const Function
*Callee
,
268 const ArrayRef
<Type
*> &Types
) const {
269 if (!BaseT::areTypesABICompatible(Caller
, Callee
, Types
))
272 // We need to ensure that argument promotion does not attempt to promote
273 // pointers to fixed-length vector types larger than 128 bits like
274 // <8 x float> (and pointers to aggregate types which have such fixed-length
275 // vector type members) into the values of the pointees. Such vector types
276 // are used for SVE VLS but there is no ABI for SVE VLS arguments and the
277 // backend cannot lower such value arguments. The 128-bit fixed-length SVE
278 // types can be safely treated as 128-bit NEON types and they cannot be
279 // distinguished in IR.
280 if (ST
->useSVEForFixedLengthVectors() && llvm::any_of(Types
, [](Type
*Ty
) {
281 auto FVTy
= dyn_cast
<FixedVectorType
>(Ty
);
283 FVTy
->getScalarSizeInBits() * FVTy
->getNumElements() > 128;
291 AArch64TTIImpl::getInlineCallPenalty(const Function
*F
, const CallBase
&Call
,
292 unsigned DefaultCallPenalty
) const {
293 // This function calculates a penalty for executing Call in F.
295 // There are two ways this function can be called:
297 // call from F -> G (the call here is Call)
299 // For (1), Call.getCaller() == F, so it will always return a high cost if
300 // a streaming-mode change is required (thus promoting the need to inline the
304 // call from F -> G (the call here is not Call)
306 // call from G -> H (the call here is Call)
308 // For (2), if after inlining the body of G into F the call to H requires a
309 // streaming-mode change, and the call to G from F would also require a
310 // streaming-mode change, then there is benefit to do the streaming-mode
311 // change only once and avoid inlining of G into F.
313 SMEAttrs
CalleeAttrs(Call
);
314 if (FAttrs
.requiresSMChange(CalleeAttrs
)) {
315 if (F
== Call
.getCaller()) // (1)
316 return CallPenaltyChangeSM
* DefaultCallPenalty
;
317 if (FAttrs
.requiresSMChange(SMEAttrs(*Call
.getCaller()))) // (2)
318 return InlineCallPenaltyChangeSM
* DefaultCallPenalty
;
321 return DefaultCallPenalty
;
324 bool AArch64TTIImpl::shouldMaximizeVectorBandwidth(
325 TargetTransformInfo::RegisterKind K
) const {
326 assert(K
!= TargetTransformInfo::RGK_Scalar
);
327 return (K
== TargetTransformInfo::RGK_FixedWidthVector
&&
328 ST
->isNeonAvailable());
331 /// Calculate the cost of materializing a 64-bit value. This helper
332 /// method might only calculate a fraction of a larger immediate. Therefore it
333 /// is valid to return a cost of ZERO.
334 InstructionCost
AArch64TTIImpl::getIntImmCost(int64_t Val
) {
335 // Check if the immediate can be encoded within an instruction.
336 if (Val
== 0 || AArch64_AM::isLogicalImmediate(Val
, 64))
342 // Calculate how many moves we will need to materialize this constant.
343 SmallVector
<AArch64_IMM::ImmInsnModel
, 4> Insn
;
344 AArch64_IMM::expandMOVImm(Val
, 64, Insn
);
348 /// Calculate the cost of materializing the given constant.
349 InstructionCost
AArch64TTIImpl::getIntImmCost(const APInt
&Imm
, Type
*Ty
,
350 TTI::TargetCostKind CostKind
) {
351 assert(Ty
->isIntegerTy());
353 unsigned BitSize
= Ty
->getPrimitiveSizeInBits();
357 // Sign-extend all constants to a multiple of 64-bit.
360 ImmVal
= Imm
.sext((BitSize
+ 63) & ~0x3fU
);
362 // Split the constant into 64-bit chunks and calculate the cost for each
364 InstructionCost Cost
= 0;
365 for (unsigned ShiftVal
= 0; ShiftVal
< BitSize
; ShiftVal
+= 64) {
366 APInt Tmp
= ImmVal
.ashr(ShiftVal
).sextOrTrunc(64);
367 int64_t Val
= Tmp
.getSExtValue();
368 Cost
+= getIntImmCost(Val
);
370 // We need at least one instruction to materialze the constant.
371 return std::max
<InstructionCost
>(1, Cost
);
374 InstructionCost
AArch64TTIImpl::getIntImmCostInst(unsigned Opcode
, unsigned Idx
,
375 const APInt
&Imm
, Type
*Ty
,
376 TTI::TargetCostKind CostKind
,
378 assert(Ty
->isIntegerTy());
380 unsigned BitSize
= Ty
->getPrimitiveSizeInBits();
381 // There is no cost model for constants with a bit size of 0. Return TCC_Free
382 // here, so that constant hoisting will ignore this constant.
384 return TTI::TCC_Free
;
386 unsigned ImmIdx
= ~0U;
389 return TTI::TCC_Free
;
390 case Instruction::GetElementPtr
:
391 // Always hoist the base address of a GetElementPtr.
393 return 2 * TTI::TCC_Basic
;
394 return TTI::TCC_Free
;
395 case Instruction::Store
:
398 case Instruction::Add
:
399 case Instruction::Sub
:
400 case Instruction::Mul
:
401 case Instruction::UDiv
:
402 case Instruction::SDiv
:
403 case Instruction::URem
:
404 case Instruction::SRem
:
405 case Instruction::And
:
406 case Instruction::Or
:
407 case Instruction::Xor
:
408 case Instruction::ICmp
:
411 // Always return TCC_Free for the shift value of a shift instruction.
412 case Instruction::Shl
:
413 case Instruction::LShr
:
414 case Instruction::AShr
:
416 return TTI::TCC_Free
;
418 case Instruction::Trunc
:
419 case Instruction::ZExt
:
420 case Instruction::SExt
:
421 case Instruction::IntToPtr
:
422 case Instruction::PtrToInt
:
423 case Instruction::BitCast
:
424 case Instruction::PHI
:
425 case Instruction::Call
:
426 case Instruction::Select
:
427 case Instruction::Ret
:
428 case Instruction::Load
:
433 int NumConstants
= (BitSize
+ 63) / 64;
434 InstructionCost Cost
= AArch64TTIImpl::getIntImmCost(Imm
, Ty
, CostKind
);
435 return (Cost
<= NumConstants
* TTI::TCC_Basic
)
436 ? static_cast<int>(TTI::TCC_Free
)
439 return AArch64TTIImpl::getIntImmCost(Imm
, Ty
, CostKind
);
443 AArch64TTIImpl::getIntImmCostIntrin(Intrinsic::ID IID
, unsigned Idx
,
444 const APInt
&Imm
, Type
*Ty
,
445 TTI::TargetCostKind CostKind
) {
446 assert(Ty
->isIntegerTy());
448 unsigned BitSize
= Ty
->getPrimitiveSizeInBits();
449 // There is no cost model for constants with a bit size of 0. Return TCC_Free
450 // here, so that constant hoisting will ignore this constant.
452 return TTI::TCC_Free
;
454 // Most (all?) AArch64 intrinsics do not support folding immediates into the
455 // selected instruction, so we compute the materialization cost for the
456 // immediate directly.
457 if (IID
>= Intrinsic::aarch64_addg
&& IID
<= Intrinsic::aarch64_udiv
)
458 return AArch64TTIImpl::getIntImmCost(Imm
, Ty
, CostKind
);
462 return TTI::TCC_Free
;
463 case Intrinsic::sadd_with_overflow
:
464 case Intrinsic::uadd_with_overflow
:
465 case Intrinsic::ssub_with_overflow
:
466 case Intrinsic::usub_with_overflow
:
467 case Intrinsic::smul_with_overflow
:
468 case Intrinsic::umul_with_overflow
:
470 int NumConstants
= (BitSize
+ 63) / 64;
471 InstructionCost Cost
= AArch64TTIImpl::getIntImmCost(Imm
, Ty
, CostKind
);
472 return (Cost
<= NumConstants
* TTI::TCC_Basic
)
473 ? static_cast<int>(TTI::TCC_Free
)
477 case Intrinsic::experimental_stackmap
:
478 if ((Idx
< 2) || (Imm
.getBitWidth() <= 64 && isInt
<64>(Imm
.getSExtValue())))
479 return TTI::TCC_Free
;
481 case Intrinsic::experimental_patchpoint_void
:
482 case Intrinsic::experimental_patchpoint_i64
:
483 if ((Idx
< 4) || (Imm
.getBitWidth() <= 64 && isInt
<64>(Imm
.getSExtValue())))
484 return TTI::TCC_Free
;
486 case Intrinsic::experimental_gc_statepoint
:
487 if ((Idx
< 5) || (Imm
.getBitWidth() <= 64 && isInt
<64>(Imm
.getSExtValue())))
488 return TTI::TCC_Free
;
491 return AArch64TTIImpl::getIntImmCost(Imm
, Ty
, CostKind
);
494 TargetTransformInfo::PopcntSupportKind
495 AArch64TTIImpl::getPopcntSupport(unsigned TyWidth
) {
496 assert(isPowerOf2_32(TyWidth
) && "Ty width must be power of 2");
497 if (TyWidth
== 32 || TyWidth
== 64)
498 return TTI::PSK_FastHardware
;
499 // TODO: AArch64TargetLowering::LowerCTPOP() supports 128bit popcount.
500 return TTI::PSK_Software
;
504 AArch64TTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes
&ICA
,
505 TTI::TargetCostKind CostKind
) {
506 auto *RetTy
= ICA
.getReturnType();
507 switch (ICA
.getID()) {
508 case Intrinsic::umin
:
509 case Intrinsic::umax
:
510 case Intrinsic::smin
:
511 case Intrinsic::smax
: {
512 static const auto ValidMinMaxTys
= {MVT::v8i8
, MVT::v16i8
, MVT::v4i16
,
513 MVT::v8i16
, MVT::v2i32
, MVT::v4i32
,
514 MVT::nxv16i8
, MVT::nxv8i16
, MVT::nxv4i32
,
516 auto LT
= getTypeLegalizationCost(RetTy
);
517 // v2i64 types get converted to cmp+bif hence the cost of 2
518 if (LT
.second
== MVT::v2i64
)
520 if (any_of(ValidMinMaxTys
, [<
](MVT M
) { return M
== LT
.second
; }))
524 case Intrinsic::sadd_sat
:
525 case Intrinsic::ssub_sat
:
526 case Intrinsic::uadd_sat
:
527 case Intrinsic::usub_sat
: {
528 static const auto ValidSatTys
= {MVT::v8i8
, MVT::v16i8
, MVT::v4i16
,
529 MVT::v8i16
, MVT::v2i32
, MVT::v4i32
,
531 auto LT
= getTypeLegalizationCost(RetTy
);
532 // This is a base cost of 1 for the vadd, plus 3 extract shifts if we
533 // need to extend the type, as it uses shr(qadd(shl, shl)).
535 LT
.second
.getScalarSizeInBits() == RetTy
->getScalarSizeInBits() ? 1 : 4;
536 if (any_of(ValidSatTys
, [<
](MVT M
) { return M
== LT
.second
; }))
537 return LT
.first
* Instrs
;
540 case Intrinsic::abs
: {
541 static const auto ValidAbsTys
= {MVT::v8i8
, MVT::v16i8
, MVT::v4i16
,
542 MVT::v8i16
, MVT::v2i32
, MVT::v4i32
,
544 auto LT
= getTypeLegalizationCost(RetTy
);
545 if (any_of(ValidAbsTys
, [<
](MVT M
) { return M
== LT
.second
; }))
549 case Intrinsic::bswap
: {
550 static const auto ValidAbsTys
= {MVT::v4i16
, MVT::v8i16
, MVT::v2i32
,
551 MVT::v4i32
, MVT::v2i64
};
552 auto LT
= getTypeLegalizationCost(RetTy
);
553 if (any_of(ValidAbsTys
, [<
](MVT M
) { return M
== LT
.second
; }) &&
554 LT
.second
.getScalarSizeInBits() == RetTy
->getScalarSizeInBits())
558 case Intrinsic::experimental_stepvector
: {
559 InstructionCost Cost
= 1; // Cost of the `index' instruction
560 auto LT
= getTypeLegalizationCost(RetTy
);
561 // Legalisation of illegal vectors involves an `index' instruction plus
562 // (LT.first - 1) vector adds.
564 Type
*LegalVTy
= EVT(LT
.second
).getTypeForEVT(RetTy
->getContext());
565 InstructionCost AddCost
=
566 getArithmeticInstrCost(Instruction::Add
, LegalVTy
, CostKind
);
567 Cost
+= AddCost
* (LT
.first
- 1);
571 case Intrinsic::bitreverse
: {
572 static const CostTblEntry BitreverseTbl
[] = {
573 {Intrinsic::bitreverse
, MVT::i32
, 1},
574 {Intrinsic::bitreverse
, MVT::i64
, 1},
575 {Intrinsic::bitreverse
, MVT::v8i8
, 1},
576 {Intrinsic::bitreverse
, MVT::v16i8
, 1},
577 {Intrinsic::bitreverse
, MVT::v4i16
, 2},
578 {Intrinsic::bitreverse
, MVT::v8i16
, 2},
579 {Intrinsic::bitreverse
, MVT::v2i32
, 2},
580 {Intrinsic::bitreverse
, MVT::v4i32
, 2},
581 {Intrinsic::bitreverse
, MVT::v1i64
, 2},
582 {Intrinsic::bitreverse
, MVT::v2i64
, 2},
584 const auto LegalisationCost
= getTypeLegalizationCost(RetTy
);
586 CostTableLookup(BitreverseTbl
, ICA
.getID(), LegalisationCost
.second
);
588 // Cost Model is using the legal type(i32) that i8 and i16 will be
589 // converted to +1 so that we match the actual lowering cost
590 if (TLI
->getValueType(DL
, RetTy
, true) == MVT::i8
||
591 TLI
->getValueType(DL
, RetTy
, true) == MVT::i16
)
592 return LegalisationCost
.first
* Entry
->Cost
+ 1;
594 return LegalisationCost
.first
* Entry
->Cost
;
598 case Intrinsic::ctpop
: {
599 if (!ST
->hasNEON()) {
600 // 32-bit or 64-bit ctpop without NEON is 12 instructions.
601 return getTypeLegalizationCost(RetTy
).first
* 12;
603 static const CostTblEntry CtpopCostTbl
[] = {
604 {ISD::CTPOP
, MVT::v2i64
, 4},
605 {ISD::CTPOP
, MVT::v4i32
, 3},
606 {ISD::CTPOP
, MVT::v8i16
, 2},
607 {ISD::CTPOP
, MVT::v16i8
, 1},
608 {ISD::CTPOP
, MVT::i64
, 4},
609 {ISD::CTPOP
, MVT::v2i32
, 3},
610 {ISD::CTPOP
, MVT::v4i16
, 2},
611 {ISD::CTPOP
, MVT::v8i8
, 1},
612 {ISD::CTPOP
, MVT::i32
, 5},
614 auto LT
= getTypeLegalizationCost(RetTy
);
616 if (const auto *Entry
= CostTableLookup(CtpopCostTbl
, ISD::CTPOP
, MTy
)) {
617 // Extra cost of +1 when illegal vector types are legalized by promoting
619 int ExtraCost
= MTy
.isVector() && MTy
.getScalarSizeInBits() !=
620 RetTy
->getScalarSizeInBits()
623 return LT
.first
* Entry
->Cost
+ ExtraCost
;
627 case Intrinsic::sadd_with_overflow
:
628 case Intrinsic::uadd_with_overflow
:
629 case Intrinsic::ssub_with_overflow
:
630 case Intrinsic::usub_with_overflow
:
631 case Intrinsic::smul_with_overflow
:
632 case Intrinsic::umul_with_overflow
: {
633 static const CostTblEntry WithOverflowCostTbl
[] = {
634 {Intrinsic::sadd_with_overflow
, MVT::i8
, 3},
635 {Intrinsic::uadd_with_overflow
, MVT::i8
, 3},
636 {Intrinsic::sadd_with_overflow
, MVT::i16
, 3},
637 {Intrinsic::uadd_with_overflow
, MVT::i16
, 3},
638 {Intrinsic::sadd_with_overflow
, MVT::i32
, 1},
639 {Intrinsic::uadd_with_overflow
, MVT::i32
, 1},
640 {Intrinsic::sadd_with_overflow
, MVT::i64
, 1},
641 {Intrinsic::uadd_with_overflow
, MVT::i64
, 1},
642 {Intrinsic::ssub_with_overflow
, MVT::i8
, 3},
643 {Intrinsic::usub_with_overflow
, MVT::i8
, 3},
644 {Intrinsic::ssub_with_overflow
, MVT::i16
, 3},
645 {Intrinsic::usub_with_overflow
, MVT::i16
, 3},
646 {Intrinsic::ssub_with_overflow
, MVT::i32
, 1},
647 {Intrinsic::usub_with_overflow
, MVT::i32
, 1},
648 {Intrinsic::ssub_with_overflow
, MVT::i64
, 1},
649 {Intrinsic::usub_with_overflow
, MVT::i64
, 1},
650 {Intrinsic::smul_with_overflow
, MVT::i8
, 5},
651 {Intrinsic::umul_with_overflow
, MVT::i8
, 4},
652 {Intrinsic::smul_with_overflow
, MVT::i16
, 5},
653 {Intrinsic::umul_with_overflow
, MVT::i16
, 4},
654 {Intrinsic::smul_with_overflow
, MVT::i32
, 2}, // eg umull;tst
655 {Intrinsic::umul_with_overflow
, MVT::i32
, 2}, // eg umull;cmp sxtw
656 {Intrinsic::smul_with_overflow
, MVT::i64
, 3}, // eg mul;smulh;cmp
657 {Intrinsic::umul_with_overflow
, MVT::i64
, 3}, // eg mul;umulh;cmp asr
659 EVT MTy
= TLI
->getValueType(DL
, RetTy
->getContainedType(0), true);
661 if (const auto *Entry
= CostTableLookup(WithOverflowCostTbl
, ICA
.getID(),
666 case Intrinsic::fptosi_sat
:
667 case Intrinsic::fptoui_sat
: {
668 if (ICA
.getArgTypes().empty())
670 bool IsSigned
= ICA
.getID() == Intrinsic::fptosi_sat
;
671 auto LT
= getTypeLegalizationCost(ICA
.getArgTypes()[0]);
672 EVT MTy
= TLI
->getValueType(DL
, RetTy
);
673 // Check for the legal types, which are where the size of the input and the
674 // output are the same, or we are using cvt f64->i32 or f32->i64.
675 if ((LT
.second
== MVT::f32
|| LT
.second
== MVT::f64
||
676 LT
.second
== MVT::v2f32
|| LT
.second
== MVT::v4f32
||
677 LT
.second
== MVT::v2f64
) &&
678 (LT
.second
.getScalarSizeInBits() == MTy
.getScalarSizeInBits() ||
679 (LT
.second
== MVT::f64
&& MTy
== MVT::i32
) ||
680 (LT
.second
== MVT::f32
&& MTy
== MVT::i64
)))
682 // Similarly for fp16 sizes
683 if (ST
->hasFullFP16() &&
684 ((LT
.second
== MVT::f16
&& MTy
== MVT::i32
) ||
685 ((LT
.second
== MVT::v4f16
|| LT
.second
== MVT::v8f16
) &&
686 (LT
.second
.getScalarSizeInBits() == MTy
.getScalarSizeInBits()))))
689 // Otherwise we use a legal convert followed by a min+max
690 if ((LT
.second
.getScalarType() == MVT::f32
||
691 LT
.second
.getScalarType() == MVT::f64
||
692 (ST
->hasFullFP16() && LT
.second
.getScalarType() == MVT::f16
)) &&
693 LT
.second
.getScalarSizeInBits() >= MTy
.getScalarSizeInBits()) {
695 Type::getIntNTy(RetTy
->getContext(), LT
.second
.getScalarSizeInBits());
696 if (LT
.second
.isVector())
697 LegalTy
= VectorType::get(LegalTy
, LT
.second
.getVectorElementCount());
698 InstructionCost Cost
= 1;
699 IntrinsicCostAttributes
Attrs1(IsSigned
? Intrinsic::smin
: Intrinsic::umin
,
700 LegalTy
, {LegalTy
, LegalTy
});
701 Cost
+= getIntrinsicInstrCost(Attrs1
, CostKind
);
702 IntrinsicCostAttributes
Attrs2(IsSigned
? Intrinsic::smax
: Intrinsic::umax
,
703 LegalTy
, {LegalTy
, LegalTy
});
704 Cost
+= getIntrinsicInstrCost(Attrs2
, CostKind
);
705 return LT
.first
* Cost
;
709 case Intrinsic::fshl
:
710 case Intrinsic::fshr
: {
711 if (ICA
.getArgs().empty())
714 // TODO: Add handling for fshl where third argument is not a constant.
715 const TTI::OperandValueInfo OpInfoZ
= TTI::getOperandInfo(ICA
.getArgs()[2]);
716 if (!OpInfoZ
.isConstant())
719 const auto LegalisationCost
= getTypeLegalizationCost(RetTy
);
720 if (OpInfoZ
.isUniform()) {
721 // FIXME: The costs could be lower if the codegen is better.
722 static const CostTblEntry FshlTbl
[] = {
723 {Intrinsic::fshl
, MVT::v4i32
, 3}, // ushr + shl + orr
724 {Intrinsic::fshl
, MVT::v2i64
, 3}, {Intrinsic::fshl
, MVT::v16i8
, 4},
725 {Intrinsic::fshl
, MVT::v8i16
, 4}, {Intrinsic::fshl
, MVT::v2i32
, 3},
726 {Intrinsic::fshl
, MVT::v8i8
, 4}, {Intrinsic::fshl
, MVT::v4i16
, 4}};
727 // Costs for both fshl & fshr are the same, so just pass Intrinsic::fshl
728 // to avoid having to duplicate the costs.
730 CostTableLookup(FshlTbl
, Intrinsic::fshl
, LegalisationCost
.second
);
732 return LegalisationCost
.first
* Entry
->Cost
;
735 auto TyL
= getTypeLegalizationCost(RetTy
);
736 if (!RetTy
->isIntegerTy())
739 // Estimate cost manually, as types like i8 and i16 will get promoted to
740 // i32 and CostTableLookup will ignore the extra conversion cost.
741 bool HigherCost
= (RetTy
->getScalarSizeInBits() != 32 &&
742 RetTy
->getScalarSizeInBits() < 64) ||
743 (RetTy
->getScalarSizeInBits() % 64 != 0);
744 unsigned ExtraCost
= HigherCost
? 1 : 0;
745 if (RetTy
->getScalarSizeInBits() == 32 ||
746 RetTy
->getScalarSizeInBits() == 64)
747 ExtraCost
= 0; // fhsl/fshr for i32 and i64 can be lowered to a single
753 return TyL
.first
+ ExtraCost
;
758 return BaseT::getIntrinsicInstrCost(ICA
, CostKind
);
761 /// The function will remove redundant reinterprets casting in the presence
762 /// of the control flow
763 static std::optional
<Instruction
*> processPhiNode(InstCombiner
&IC
,
765 SmallVector
<Instruction
*, 32> Worklist
;
766 auto RequiredType
= II
.getType();
768 auto *PN
= dyn_cast
<PHINode
>(II
.getArgOperand(0));
769 assert(PN
&& "Expected Phi Node!");
771 // Don't create a new Phi unless we can remove the old one.
772 if (!PN
->hasOneUse())
775 for (Value
*IncValPhi
: PN
->incoming_values()) {
776 auto *Reinterpret
= dyn_cast
<IntrinsicInst
>(IncValPhi
);
778 Reinterpret
->getIntrinsicID() !=
779 Intrinsic::aarch64_sve_convert_to_svbool
||
780 RequiredType
!= Reinterpret
->getArgOperand(0)->getType())
784 // Create the new Phi
785 IC
.Builder
.SetInsertPoint(PN
);
786 PHINode
*NPN
= IC
.Builder
.CreatePHI(RequiredType
, PN
->getNumIncomingValues());
787 Worklist
.push_back(PN
);
789 for (unsigned I
= 0; I
< PN
->getNumIncomingValues(); I
++) {
790 auto *Reinterpret
= cast
<Instruction
>(PN
->getIncomingValue(I
));
791 NPN
->addIncoming(Reinterpret
->getOperand(0), PN
->getIncomingBlock(I
));
792 Worklist
.push_back(Reinterpret
);
795 // Cleanup Phi Node and reinterprets
796 return IC
.replaceInstUsesWith(II
, NPN
);
799 // (from_svbool (binop (to_svbool pred) (svbool_t _) (svbool_t _))))
800 // => (binop (pred) (from_svbool _) (from_svbool _))
802 // The above transformation eliminates a `to_svbool` in the predicate
803 // operand of bitwise operation `binop` by narrowing the vector width of
804 // the operation. For example, it would convert a `<vscale x 16 x i1>
805 // and` into a `<vscale x 4 x i1> and`. This is profitable because
806 // to_svbool must zero the new lanes during widening, whereas
807 // from_svbool is free.
808 static std::optional
<Instruction
*>
809 tryCombineFromSVBoolBinOp(InstCombiner
&IC
, IntrinsicInst
&II
) {
810 auto BinOp
= dyn_cast
<IntrinsicInst
>(II
.getOperand(0));
814 auto IntrinsicID
= BinOp
->getIntrinsicID();
815 switch (IntrinsicID
) {
816 case Intrinsic::aarch64_sve_and_z
:
817 case Intrinsic::aarch64_sve_bic_z
:
818 case Intrinsic::aarch64_sve_eor_z
:
819 case Intrinsic::aarch64_sve_nand_z
:
820 case Intrinsic::aarch64_sve_nor_z
:
821 case Intrinsic::aarch64_sve_orn_z
:
822 case Intrinsic::aarch64_sve_orr_z
:
828 auto BinOpPred
= BinOp
->getOperand(0);
829 auto BinOpOp1
= BinOp
->getOperand(1);
830 auto BinOpOp2
= BinOp
->getOperand(2);
832 auto PredIntr
= dyn_cast
<IntrinsicInst
>(BinOpPred
);
834 PredIntr
->getIntrinsicID() != Intrinsic::aarch64_sve_convert_to_svbool
)
837 auto PredOp
= PredIntr
->getOperand(0);
838 auto PredOpTy
= cast
<VectorType
>(PredOp
->getType());
839 if (PredOpTy
!= II
.getType())
842 SmallVector
<Value
*> NarrowedBinOpArgs
= {PredOp
};
843 auto NarrowBinOpOp1
= IC
.Builder
.CreateIntrinsic(
844 Intrinsic::aarch64_sve_convert_from_svbool
, {PredOpTy
}, {BinOpOp1
});
845 NarrowedBinOpArgs
.push_back(NarrowBinOpOp1
);
846 if (BinOpOp1
== BinOpOp2
)
847 NarrowedBinOpArgs
.push_back(NarrowBinOpOp1
);
849 NarrowedBinOpArgs
.push_back(IC
.Builder
.CreateIntrinsic(
850 Intrinsic::aarch64_sve_convert_from_svbool
, {PredOpTy
}, {BinOpOp2
}));
853 IC
.Builder
.CreateIntrinsic(IntrinsicID
, {PredOpTy
}, NarrowedBinOpArgs
);
854 return IC
.replaceInstUsesWith(II
, NarrowedBinOp
);
857 static std::optional
<Instruction
*>
858 instCombineConvertFromSVBool(InstCombiner
&IC
, IntrinsicInst
&II
) {
859 // If the reinterpret instruction operand is a PHI Node
860 if (isa
<PHINode
>(II
.getArgOperand(0)))
861 return processPhiNode(IC
, II
);
863 if (auto BinOpCombine
= tryCombineFromSVBoolBinOp(IC
, II
))
866 // Ignore converts to/from svcount_t.
867 if (isa
<TargetExtType
>(II
.getArgOperand(0)->getType()) ||
868 isa
<TargetExtType
>(II
.getType()))
871 SmallVector
<Instruction
*, 32> CandidatesForRemoval
;
872 Value
*Cursor
= II
.getOperand(0), *EarliestReplacement
= nullptr;
874 const auto *IVTy
= cast
<VectorType
>(II
.getType());
876 // Walk the chain of conversions.
878 // If the type of the cursor has fewer lanes than the final result, zeroing
879 // must take place, which breaks the equivalence chain.
880 const auto *CursorVTy
= cast
<VectorType
>(Cursor
->getType());
881 if (CursorVTy
->getElementCount().getKnownMinValue() <
882 IVTy
->getElementCount().getKnownMinValue())
885 // If the cursor has the same type as I, it is a viable replacement.
886 if (Cursor
->getType() == IVTy
)
887 EarliestReplacement
= Cursor
;
889 auto *IntrinsicCursor
= dyn_cast
<IntrinsicInst
>(Cursor
);
891 // If this is not an SVE conversion intrinsic, this is the end of the chain.
892 if (!IntrinsicCursor
|| !(IntrinsicCursor
->getIntrinsicID() ==
893 Intrinsic::aarch64_sve_convert_to_svbool
||
894 IntrinsicCursor
->getIntrinsicID() ==
895 Intrinsic::aarch64_sve_convert_from_svbool
))
898 CandidatesForRemoval
.insert(CandidatesForRemoval
.begin(), IntrinsicCursor
);
899 Cursor
= IntrinsicCursor
->getOperand(0);
902 // If no viable replacement in the conversion chain was found, there is
904 if (!EarliestReplacement
)
907 return IC
.replaceInstUsesWith(II
, EarliestReplacement
);
910 static bool isAllActivePredicate(Value
*Pred
) {
911 // Look through convert.from.svbool(convert.to.svbool(...) chain.
913 if (match(Pred
, m_Intrinsic
<Intrinsic::aarch64_sve_convert_from_svbool
>(
914 m_Intrinsic
<Intrinsic::aarch64_sve_convert_to_svbool
>(
915 m_Value(UncastedPred
)))))
916 // If the predicate has the same or less lanes than the uncasted
917 // predicate then we know the casting has no effect.
918 if (cast
<ScalableVectorType
>(Pred
->getType())->getMinNumElements() <=
919 cast
<ScalableVectorType
>(UncastedPred
->getType())->getMinNumElements())
922 return match(Pred
, m_Intrinsic
<Intrinsic::aarch64_sve_ptrue
>(
923 m_ConstantInt
<AArch64SVEPredPattern::all
>()));
926 static std::optional
<Instruction
*> instCombineSVESel(InstCombiner
&IC
,
928 // svsel(ptrue, x, y) => x
929 auto *OpPredicate
= II
.getOperand(0);
930 if (isAllActivePredicate(OpPredicate
))
931 return IC
.replaceInstUsesWith(II
, II
.getOperand(1));
934 IC
.Builder
.CreateSelect(OpPredicate
, II
.getOperand(1), II
.getOperand(2));
935 return IC
.replaceInstUsesWith(II
, Select
);
938 static std::optional
<Instruction
*> instCombineSVEDup(InstCombiner
&IC
,
940 IntrinsicInst
*Pg
= dyn_cast
<IntrinsicInst
>(II
.getArgOperand(1));
944 if (Pg
->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue
)
947 const auto PTruePattern
=
948 cast
<ConstantInt
>(Pg
->getOperand(0))->getZExtValue();
949 if (PTruePattern
!= AArch64SVEPredPattern::vl1
)
952 // The intrinsic is inserting into lane zero so use an insert instead.
953 auto *IdxTy
= Type::getInt64Ty(II
.getContext());
954 auto *Insert
= InsertElementInst::Create(
955 II
.getArgOperand(0), II
.getArgOperand(2), ConstantInt::get(IdxTy
, 0));
956 Insert
->insertBefore(&II
);
957 Insert
->takeName(&II
);
959 return IC
.replaceInstUsesWith(II
, Insert
);
962 static std::optional
<Instruction
*> instCombineSVEDupX(InstCombiner
&IC
,
964 // Replace DupX with a regular IR splat.
965 auto *RetTy
= cast
<ScalableVectorType
>(II
.getType());
966 Value
*Splat
= IC
.Builder
.CreateVectorSplat(RetTy
->getElementCount(),
967 II
.getArgOperand(0));
968 Splat
->takeName(&II
);
969 return IC
.replaceInstUsesWith(II
, Splat
);
972 static std::optional
<Instruction
*> instCombineSVECmpNE(InstCombiner
&IC
,
974 LLVMContext
&Ctx
= II
.getContext();
976 // Check that the predicate is all active
977 auto *Pg
= dyn_cast
<IntrinsicInst
>(II
.getArgOperand(0));
978 if (!Pg
|| Pg
->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue
)
981 const auto PTruePattern
=
982 cast
<ConstantInt
>(Pg
->getOperand(0))->getZExtValue();
983 if (PTruePattern
!= AArch64SVEPredPattern::all
)
986 // Check that we have a compare of zero..
988 dyn_cast_or_null
<ConstantInt
>(getSplatValue(II
.getArgOperand(2)));
989 if (!SplatValue
|| !SplatValue
->isZero())
993 auto *DupQLane
= dyn_cast
<IntrinsicInst
>(II
.getArgOperand(1));
995 DupQLane
->getIntrinsicID() != Intrinsic::aarch64_sve_dupq_lane
)
998 // Where the dupq is a lane 0 replicate of a vector insert
999 if (!cast
<ConstantInt
>(DupQLane
->getArgOperand(1))->isZero())
1000 return std::nullopt
;
1002 auto *VecIns
= dyn_cast
<IntrinsicInst
>(DupQLane
->getArgOperand(0));
1003 if (!VecIns
|| VecIns
->getIntrinsicID() != Intrinsic::vector_insert
)
1004 return std::nullopt
;
1006 // Where the vector insert is a fixed constant vector insert into undef at
1008 if (!isa
<UndefValue
>(VecIns
->getArgOperand(0)))
1009 return std::nullopt
;
1011 if (!cast
<ConstantInt
>(VecIns
->getArgOperand(2))->isZero())
1012 return std::nullopt
;
1014 auto *ConstVec
= dyn_cast
<Constant
>(VecIns
->getArgOperand(1));
1016 return std::nullopt
;
1018 auto *VecTy
= dyn_cast
<FixedVectorType
>(ConstVec
->getType());
1019 auto *OutTy
= dyn_cast
<ScalableVectorType
>(II
.getType());
1020 if (!VecTy
|| !OutTy
|| VecTy
->getNumElements() != OutTy
->getMinNumElements())
1021 return std::nullopt
;
1023 unsigned NumElts
= VecTy
->getNumElements();
1024 unsigned PredicateBits
= 0;
1026 // Expand intrinsic operands to a 16-bit byte level predicate
1027 for (unsigned I
= 0; I
< NumElts
; ++I
) {
1028 auto *Arg
= dyn_cast
<ConstantInt
>(ConstVec
->getAggregateElement(I
));
1030 return std::nullopt
;
1032 PredicateBits
|= 1 << (I
* (16 / NumElts
));
1035 // If all bits are zero bail early with an empty predicate
1036 if (PredicateBits
== 0) {
1037 auto *PFalse
= Constant::getNullValue(II
.getType());
1038 PFalse
->takeName(&II
);
1039 return IC
.replaceInstUsesWith(II
, PFalse
);
1042 // Calculate largest predicate type used (where byte predicate is largest)
1044 for (unsigned I
= 0; I
< 16; ++I
)
1045 if ((PredicateBits
& (1 << I
)) != 0)
1048 unsigned PredSize
= Mask
& -Mask
;
1049 auto *PredType
= ScalableVectorType::get(
1050 Type::getInt1Ty(Ctx
), AArch64::SVEBitsPerBlock
/ (PredSize
* 8));
1052 // Ensure all relevant bits are set
1053 for (unsigned I
= 0; I
< 16; I
+= PredSize
)
1054 if ((PredicateBits
& (1 << I
)) == 0)
1055 return std::nullopt
;
1058 ConstantInt::get(Type::getInt32Ty(Ctx
), AArch64SVEPredPattern::all
);
1059 auto *PTrue
= IC
.Builder
.CreateIntrinsic(Intrinsic::aarch64_sve_ptrue
,
1060 {PredType
}, {PTruePat
});
1061 auto *ConvertToSVBool
= IC
.Builder
.CreateIntrinsic(
1062 Intrinsic::aarch64_sve_convert_to_svbool
, {PredType
}, {PTrue
});
1063 auto *ConvertFromSVBool
=
1064 IC
.Builder
.CreateIntrinsic(Intrinsic::aarch64_sve_convert_from_svbool
,
1065 {II
.getType()}, {ConvertToSVBool
});
1067 ConvertFromSVBool
->takeName(&II
);
1068 return IC
.replaceInstUsesWith(II
, ConvertFromSVBool
);
1071 static std::optional
<Instruction
*> instCombineSVELast(InstCombiner
&IC
,
1072 IntrinsicInst
&II
) {
1073 Value
*Pg
= II
.getArgOperand(0);
1074 Value
*Vec
= II
.getArgOperand(1);
1075 auto IntrinsicID
= II
.getIntrinsicID();
1076 bool IsAfter
= IntrinsicID
== Intrinsic::aarch64_sve_lasta
;
1078 // lastX(splat(X)) --> X
1079 if (auto *SplatVal
= getSplatValue(Vec
))
1080 return IC
.replaceInstUsesWith(II
, SplatVal
);
1082 // If x and/or y is a splat value then:
1083 // lastX (binop (x, y)) --> binop(lastX(x), lastX(y))
1085 if (match(Vec
, m_OneUse(m_BinOp(m_Value(LHS
), m_Value(RHS
))))) {
1086 if (isSplatValue(LHS
) || isSplatValue(RHS
)) {
1087 auto *OldBinOp
= cast
<BinaryOperator
>(Vec
);
1088 auto OpC
= OldBinOp
->getOpcode();
1090 IC
.Builder
.CreateIntrinsic(IntrinsicID
, {Vec
->getType()}, {Pg
, LHS
});
1092 IC
.Builder
.CreateIntrinsic(IntrinsicID
, {Vec
->getType()}, {Pg
, RHS
});
1093 auto *NewBinOp
= BinaryOperator::CreateWithCopiedFlags(
1094 OpC
, NewLHS
, NewRHS
, OldBinOp
, OldBinOp
->getName(), &II
);
1095 return IC
.replaceInstUsesWith(II
, NewBinOp
);
1099 auto *C
= dyn_cast
<Constant
>(Pg
);
1100 if (IsAfter
&& C
&& C
->isNullValue()) {
1101 // The intrinsic is extracting lane 0 so use an extract instead.
1102 auto *IdxTy
= Type::getInt64Ty(II
.getContext());
1103 auto *Extract
= ExtractElementInst::Create(Vec
, ConstantInt::get(IdxTy
, 0));
1104 Extract
->insertBefore(&II
);
1105 Extract
->takeName(&II
);
1106 return IC
.replaceInstUsesWith(II
, Extract
);
1109 auto *IntrPG
= dyn_cast
<IntrinsicInst
>(Pg
);
1111 return std::nullopt
;
1113 if (IntrPG
->getIntrinsicID() != Intrinsic::aarch64_sve_ptrue
)
1114 return std::nullopt
;
1116 const auto PTruePattern
=
1117 cast
<ConstantInt
>(IntrPG
->getOperand(0))->getZExtValue();
1119 // Can the intrinsic's predicate be converted to a known constant index?
1120 unsigned MinNumElts
= getNumElementsFromSVEPredPattern(PTruePattern
);
1122 return std::nullopt
;
1124 unsigned Idx
= MinNumElts
- 1;
1125 // Increment the index if extracting the element after the last active
1126 // predicate element.
1130 // Ignore extracts whose index is larger than the known minimum vector
1131 // length. NOTE: This is an artificial constraint where we prefer to
1132 // maintain what the user asked for until an alternative is proven faster.
1133 auto *PgVTy
= cast
<ScalableVectorType
>(Pg
->getType());
1134 if (Idx
>= PgVTy
->getMinNumElements())
1135 return std::nullopt
;
1137 // The intrinsic is extracting a fixed lane so use an extract instead.
1138 auto *IdxTy
= Type::getInt64Ty(II
.getContext());
1139 auto *Extract
= ExtractElementInst::Create(Vec
, ConstantInt::get(IdxTy
, Idx
));
1140 Extract
->insertBefore(&II
);
1141 Extract
->takeName(&II
);
1142 return IC
.replaceInstUsesWith(II
, Extract
);
1145 static std::optional
<Instruction
*> instCombineSVECondLast(InstCombiner
&IC
,
1146 IntrinsicInst
&II
) {
1147 // The SIMD&FP variant of CLAST[AB] is significantly faster than the scalar
1148 // integer variant across a variety of micro-architectures. Replace scalar
1149 // integer CLAST[AB] intrinsic with optimal SIMD&FP variant. A simple
1150 // bitcast-to-fp + clast[ab] + bitcast-to-int will cost a cycle or two more
1151 // depending on the micro-architecture, but has been observed as generally
1152 // being faster, particularly when the CLAST[AB] op is a loop-carried
1154 Value
*Pg
= II
.getArgOperand(0);
1155 Value
*Fallback
= II
.getArgOperand(1);
1156 Value
*Vec
= II
.getArgOperand(2);
1157 Type
*Ty
= II
.getType();
1159 if (!Ty
->isIntegerTy())
1160 return std::nullopt
;
1163 switch (cast
<IntegerType
>(Ty
)->getBitWidth()) {
1165 return std::nullopt
;
1167 FPTy
= IC
.Builder
.getHalfTy();
1170 FPTy
= IC
.Builder
.getFloatTy();
1173 FPTy
= IC
.Builder
.getDoubleTy();
1177 Value
*FPFallBack
= IC
.Builder
.CreateBitCast(Fallback
, FPTy
);
1178 auto *FPVTy
= VectorType::get(
1179 FPTy
, cast
<VectorType
>(Vec
->getType())->getElementCount());
1180 Value
*FPVec
= IC
.Builder
.CreateBitCast(Vec
, FPVTy
);
1181 auto *FPII
= IC
.Builder
.CreateIntrinsic(
1182 II
.getIntrinsicID(), {FPVec
->getType()}, {Pg
, FPFallBack
, FPVec
});
1183 Value
*FPIItoInt
= IC
.Builder
.CreateBitCast(FPII
, II
.getType());
1184 return IC
.replaceInstUsesWith(II
, FPIItoInt
);
1187 static std::optional
<Instruction
*> instCombineRDFFR(InstCombiner
&IC
,
1188 IntrinsicInst
&II
) {
1189 LLVMContext
&Ctx
= II
.getContext();
1190 // Replace rdffr with predicated rdffr.z intrinsic, so that optimizePTestInstr
1191 // can work with RDFFR_PP for ptest elimination.
1193 ConstantInt::get(Type::getInt32Ty(Ctx
), AArch64SVEPredPattern::all
);
1194 auto *PTrue
= IC
.Builder
.CreateIntrinsic(Intrinsic::aarch64_sve_ptrue
,
1195 {II
.getType()}, {AllPat
});
1197 IC
.Builder
.CreateIntrinsic(Intrinsic::aarch64_sve_rdffr_z
, {}, {PTrue
});
1198 RDFFR
->takeName(&II
);
1199 return IC
.replaceInstUsesWith(II
, RDFFR
);
1202 static std::optional
<Instruction
*>
1203 instCombineSVECntElts(InstCombiner
&IC
, IntrinsicInst
&II
, unsigned NumElts
) {
1204 const auto Pattern
= cast
<ConstantInt
>(II
.getArgOperand(0))->getZExtValue();
1206 if (Pattern
== AArch64SVEPredPattern::all
) {
1207 Constant
*StepVal
= ConstantInt::get(II
.getType(), NumElts
);
1208 auto *VScale
= IC
.Builder
.CreateVScale(StepVal
);
1209 VScale
->takeName(&II
);
1210 return IC
.replaceInstUsesWith(II
, VScale
);
1213 unsigned MinNumElts
= getNumElementsFromSVEPredPattern(Pattern
);
1215 return MinNumElts
&& NumElts
>= MinNumElts
1216 ? std::optional
<Instruction
*>(IC
.replaceInstUsesWith(
1217 II
, ConstantInt::get(II
.getType(), MinNumElts
)))
1221 static std::optional
<Instruction
*> instCombineSVEPTest(InstCombiner
&IC
,
1222 IntrinsicInst
&II
) {
1223 Value
*PgVal
= II
.getArgOperand(0);
1224 Value
*OpVal
= II
.getArgOperand(1);
1226 // PTEST_<FIRST|LAST>(X, X) is equivalent to PTEST_ANY(X, X).
1227 // Later optimizations prefer this form.
1228 if (PgVal
== OpVal
&&
1229 (II
.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_first
||
1230 II
.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_last
)) {
1231 Value
*Ops
[] = {PgVal
, OpVal
};
1232 Type
*Tys
[] = {PgVal
->getType()};
1235 IC
.Builder
.CreateIntrinsic(Intrinsic::aarch64_sve_ptest_any
, Tys
, Ops
);
1236 PTest
->takeName(&II
);
1238 return IC
.replaceInstUsesWith(II
, PTest
);
1241 IntrinsicInst
*Pg
= dyn_cast
<IntrinsicInst
>(PgVal
);
1242 IntrinsicInst
*Op
= dyn_cast
<IntrinsicInst
>(OpVal
);
1245 return std::nullopt
;
1247 Intrinsic::ID OpIID
= Op
->getIntrinsicID();
1249 if (Pg
->getIntrinsicID() == Intrinsic::aarch64_sve_convert_to_svbool
&&
1250 OpIID
== Intrinsic::aarch64_sve_convert_to_svbool
&&
1251 Pg
->getArgOperand(0)->getType() == Op
->getArgOperand(0)->getType()) {
1252 Value
*Ops
[] = {Pg
->getArgOperand(0), Op
->getArgOperand(0)};
1253 Type
*Tys
[] = {Pg
->getArgOperand(0)->getType()};
1255 auto *PTest
= IC
.Builder
.CreateIntrinsic(II
.getIntrinsicID(), Tys
, Ops
);
1257 PTest
->takeName(&II
);
1258 return IC
.replaceInstUsesWith(II
, PTest
);
1261 // Transform PTEST_ANY(X=OP(PG,...), X) -> PTEST_ANY(PG, X)).
1262 // Later optimizations may rewrite sequence to use the flag-setting variant
1263 // of instruction X to remove PTEST.
1264 if ((Pg
== Op
) && (II
.getIntrinsicID() == Intrinsic::aarch64_sve_ptest_any
) &&
1265 ((OpIID
== Intrinsic::aarch64_sve_brka_z
) ||
1266 (OpIID
== Intrinsic::aarch64_sve_brkb_z
) ||
1267 (OpIID
== Intrinsic::aarch64_sve_brkpa_z
) ||
1268 (OpIID
== Intrinsic::aarch64_sve_brkpb_z
) ||
1269 (OpIID
== Intrinsic::aarch64_sve_rdffr_z
) ||
1270 (OpIID
== Intrinsic::aarch64_sve_and_z
) ||
1271 (OpIID
== Intrinsic::aarch64_sve_bic_z
) ||
1272 (OpIID
== Intrinsic::aarch64_sve_eor_z
) ||
1273 (OpIID
== Intrinsic::aarch64_sve_nand_z
) ||
1274 (OpIID
== Intrinsic::aarch64_sve_nor_z
) ||
1275 (OpIID
== Intrinsic::aarch64_sve_orn_z
) ||
1276 (OpIID
== Intrinsic::aarch64_sve_orr_z
))) {
1277 Value
*Ops
[] = {Pg
->getArgOperand(0), Pg
};
1278 Type
*Tys
[] = {Pg
->getType()};
1280 auto *PTest
= IC
.Builder
.CreateIntrinsic(II
.getIntrinsicID(), Tys
, Ops
);
1281 PTest
->takeName(&II
);
1283 return IC
.replaceInstUsesWith(II
, PTest
);
1286 return std::nullopt
;
1289 template <Intrinsic::ID MulOpc
, typename
Intrinsic::ID FuseOpc
>
1290 static std::optional
<Instruction
*>
1291 instCombineSVEVectorFuseMulAddSub(InstCombiner
&IC
, IntrinsicInst
&II
,
1292 bool MergeIntoAddendOp
) {
1293 Value
*P
= II
.getOperand(0);
1294 Value
*MulOp0
, *MulOp1
, *AddendOp
, *Mul
;
1295 if (MergeIntoAddendOp
) {
1296 AddendOp
= II
.getOperand(1);
1297 Mul
= II
.getOperand(2);
1299 AddendOp
= II
.getOperand(2);
1300 Mul
= II
.getOperand(1);
1303 if (!match(Mul
, m_Intrinsic
<MulOpc
>(m_Specific(P
), m_Value(MulOp0
),
1305 return std::nullopt
;
1307 if (!Mul
->hasOneUse())
1308 return std::nullopt
;
1310 Instruction
*FMFSource
= nullptr;
1311 if (II
.getType()->isFPOrFPVectorTy()) {
1312 llvm::FastMathFlags FAddFlags
= II
.getFastMathFlags();
1313 // Stop the combine when the flags on the inputs differ in case dropping
1314 // flags would lead to us missing out on more beneficial optimizations.
1315 if (FAddFlags
!= cast
<CallInst
>(Mul
)->getFastMathFlags())
1316 return std::nullopt
;
1317 if (!FAddFlags
.allowContract())
1318 return std::nullopt
;
1323 if (MergeIntoAddendOp
)
1324 Res
= IC
.Builder
.CreateIntrinsic(FuseOpc
, {II
.getType()},
1325 {P
, AddendOp
, MulOp0
, MulOp1
}, FMFSource
);
1327 Res
= IC
.Builder
.CreateIntrinsic(FuseOpc
, {II
.getType()},
1328 {P
, MulOp0
, MulOp1
, AddendOp
}, FMFSource
);
1330 return IC
.replaceInstUsesWith(II
, Res
);
1333 static std::optional
<Instruction
*>
1334 instCombineSVELD1(InstCombiner
&IC
, IntrinsicInst
&II
, const DataLayout
&DL
) {
1335 Value
*Pred
= II
.getOperand(0);
1336 Value
*PtrOp
= II
.getOperand(1);
1337 Type
*VecTy
= II
.getType();
1339 if (isAllActivePredicate(Pred
)) {
1340 LoadInst
*Load
= IC
.Builder
.CreateLoad(VecTy
, PtrOp
);
1341 Load
->copyMetadata(II
);
1342 return IC
.replaceInstUsesWith(II
, Load
);
1345 CallInst
*MaskedLoad
=
1346 IC
.Builder
.CreateMaskedLoad(VecTy
, PtrOp
, PtrOp
->getPointerAlignment(DL
),
1347 Pred
, ConstantAggregateZero::get(VecTy
));
1348 MaskedLoad
->copyMetadata(II
);
1349 return IC
.replaceInstUsesWith(II
, MaskedLoad
);
1352 static std::optional
<Instruction
*>
1353 instCombineSVEST1(InstCombiner
&IC
, IntrinsicInst
&II
, const DataLayout
&DL
) {
1354 Value
*VecOp
= II
.getOperand(0);
1355 Value
*Pred
= II
.getOperand(1);
1356 Value
*PtrOp
= II
.getOperand(2);
1358 if (isAllActivePredicate(Pred
)) {
1359 StoreInst
*Store
= IC
.Builder
.CreateStore(VecOp
, PtrOp
);
1360 Store
->copyMetadata(II
);
1361 return IC
.eraseInstFromFunction(II
);
1364 CallInst
*MaskedStore
= IC
.Builder
.CreateMaskedStore(
1365 VecOp
, PtrOp
, PtrOp
->getPointerAlignment(DL
), Pred
);
1366 MaskedStore
->copyMetadata(II
);
1367 return IC
.eraseInstFromFunction(II
);
1370 static Instruction::BinaryOps
intrinsicIDToBinOpCode(unsigned Intrinsic
) {
1371 switch (Intrinsic
) {
1372 case Intrinsic::aarch64_sve_fmul_u
:
1373 return Instruction::BinaryOps::FMul
;
1374 case Intrinsic::aarch64_sve_fadd_u
:
1375 return Instruction::BinaryOps::FAdd
;
1376 case Intrinsic::aarch64_sve_fsub_u
:
1377 return Instruction::BinaryOps::FSub
;
1379 return Instruction::BinaryOpsEnd
;
1383 static std::optional
<Instruction
*>
1384 instCombineSVEVectorBinOp(InstCombiner
&IC
, IntrinsicInst
&II
) {
1385 // Bail due to missing support for ISD::STRICT_ scalable vector operations.
1386 if (II
.isStrictFP())
1387 return std::nullopt
;
1389 auto *OpPredicate
= II
.getOperand(0);
1390 auto BinOpCode
= intrinsicIDToBinOpCode(II
.getIntrinsicID());
1391 if (BinOpCode
== Instruction::BinaryOpsEnd
||
1392 !match(OpPredicate
, m_Intrinsic
<Intrinsic::aarch64_sve_ptrue
>(
1393 m_ConstantInt
<AArch64SVEPredPattern::all
>())))
1394 return std::nullopt
;
1395 IRBuilderBase::FastMathFlagGuard
FMFGuard(IC
.Builder
);
1396 IC
.Builder
.setFastMathFlags(II
.getFastMathFlags());
1398 IC
.Builder
.CreateBinOp(BinOpCode
, II
.getOperand(1), II
.getOperand(2));
1399 return IC
.replaceInstUsesWith(II
, BinOp
);
1402 // Canonicalise operations that take an all active predicate (e.g. sve.add ->
1404 static std::optional
<Instruction
*> instCombineSVEAllActive(IntrinsicInst
&II
,
1405 Intrinsic::ID IID
) {
1406 auto *OpPredicate
= II
.getOperand(0);
1407 if (!match(OpPredicate
, m_Intrinsic
<Intrinsic::aarch64_sve_ptrue
>(
1408 m_ConstantInt
<AArch64SVEPredPattern::all
>())))
1409 return std::nullopt
;
1411 auto *Mod
= II
.getModule();
1412 auto *NewDecl
= Intrinsic::getDeclaration(Mod
, IID
, {II
.getType()});
1413 II
.setCalledFunction(NewDecl
);
1418 // Simplify operations where predicate has all inactive lanes or try to replace
1419 // with _u form when all lanes are active
1420 static std::optional
<Instruction
*>
1421 instCombineSVEAllOrNoActive(InstCombiner
&IC
, IntrinsicInst
&II
,
1422 Intrinsic::ID IID
) {
1423 if (match(II
.getOperand(0), m_ZeroInt())) {
1424 // llvm_ir, pred(0), op1, op2 - Spec says to return op1 when all lanes are
1425 // inactive for sv[func]_m
1426 return IC
.replaceInstUsesWith(II
, II
.getOperand(1));
1428 return instCombineSVEAllActive(II
, IID
);
1431 static std::optional
<Instruction
*> instCombineSVEVectorAdd(InstCombiner
&IC
,
1432 IntrinsicInst
&II
) {
1434 instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_add_u
))
1436 if (auto MLA
= instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_mul
,
1437 Intrinsic::aarch64_sve_mla
>(
1440 if (auto MAD
= instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_mul
,
1441 Intrinsic::aarch64_sve_mad
>(
1444 return std::nullopt
;
1447 static std::optional
<Instruction
*>
1448 instCombineSVEVectorFAdd(InstCombiner
&IC
, IntrinsicInst
&II
) {
1450 instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fadd_u
))
1453 instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_fmul
,
1454 Intrinsic::aarch64_sve_fmla
>(IC
, II
,
1458 instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_fmul
,
1459 Intrinsic::aarch64_sve_fmad
>(IC
, II
,
1463 instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_fmul_u
,
1464 Intrinsic::aarch64_sve_fmla
>(IC
, II
,
1467 return std::nullopt
;
1470 static std::optional
<Instruction
*>
1471 instCombineSVEVectorFAddU(InstCombiner
&IC
, IntrinsicInst
&II
) {
1473 instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_fmul
,
1474 Intrinsic::aarch64_sve_fmla
>(IC
, II
,
1478 instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_fmul
,
1479 Intrinsic::aarch64_sve_fmad
>(IC
, II
,
1483 instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_fmul_u
,
1484 Intrinsic::aarch64_sve_fmla_u
>(
1487 return instCombineSVEVectorBinOp(IC
, II
);
1490 static std::optional
<Instruction
*>
1491 instCombineSVEVectorFSub(InstCombiner
&IC
, IntrinsicInst
&II
) {
1493 instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fsub_u
))
1496 instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_fmul
,
1497 Intrinsic::aarch64_sve_fmls
>(IC
, II
,
1501 instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_fmul
,
1502 Intrinsic::aarch64_sve_fnmsb
>(
1506 instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_fmul_u
,
1507 Intrinsic::aarch64_sve_fmls
>(IC
, II
,
1510 return std::nullopt
;
1513 static std::optional
<Instruction
*>
1514 instCombineSVEVectorFSubU(InstCombiner
&IC
, IntrinsicInst
&II
) {
1516 instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_fmul
,
1517 Intrinsic::aarch64_sve_fmls
>(IC
, II
,
1521 instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_fmul
,
1522 Intrinsic::aarch64_sve_fnmsb
>(
1526 instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_fmul_u
,
1527 Intrinsic::aarch64_sve_fmls_u
>(
1530 return instCombineSVEVectorBinOp(IC
, II
);
1533 static std::optional
<Instruction
*> instCombineSVEVectorSub(InstCombiner
&IC
,
1534 IntrinsicInst
&II
) {
1536 instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_sub_u
))
1538 if (auto MLS
= instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_mul
,
1539 Intrinsic::aarch64_sve_mls
>(
1542 return std::nullopt
;
1545 static std::optional
<Instruction
*> instCombineSVEVectorMul(InstCombiner
&IC
,
1547 Intrinsic::ID IID
) {
1548 auto *OpPredicate
= II
.getOperand(0);
1549 auto *OpMultiplicand
= II
.getOperand(1);
1550 auto *OpMultiplier
= II
.getOperand(2);
1552 // Return true if a given instruction is a unit splat value, false otherwise.
1553 auto IsUnitSplat
= [](auto *I
) {
1554 auto *SplatValue
= getSplatValue(I
);
1557 return match(SplatValue
, m_FPOne()) || match(SplatValue
, m_One());
1560 // Return true if a given instruction is an aarch64_sve_dup intrinsic call
1561 // with a unit splat value, false otherwise.
1562 auto IsUnitDup
= [](auto *I
) {
1563 auto *IntrI
= dyn_cast
<IntrinsicInst
>(I
);
1564 if (!IntrI
|| IntrI
->getIntrinsicID() != Intrinsic::aarch64_sve_dup
)
1567 auto *SplatValue
= IntrI
->getOperand(2);
1568 return match(SplatValue
, m_FPOne()) || match(SplatValue
, m_One());
1571 if (IsUnitSplat(OpMultiplier
)) {
1572 // [f]mul pg %n, (dupx 1) => %n
1573 OpMultiplicand
->takeName(&II
);
1574 return IC
.replaceInstUsesWith(II
, OpMultiplicand
);
1575 } else if (IsUnitDup(OpMultiplier
)) {
1576 // [f]mul pg %n, (dup pg 1) => %n
1577 auto *DupInst
= cast
<IntrinsicInst
>(OpMultiplier
);
1578 auto *DupPg
= DupInst
->getOperand(1);
1579 // TODO: this is naive. The optimization is still valid if DupPg
1580 // 'encompasses' OpPredicate, not only if they're the same predicate.
1581 if (OpPredicate
== DupPg
) {
1582 OpMultiplicand
->takeName(&II
);
1583 return IC
.replaceInstUsesWith(II
, OpMultiplicand
);
1587 return instCombineSVEVectorBinOp(IC
, II
);
1590 static std::optional
<Instruction
*> instCombineSVEUnpack(InstCombiner
&IC
,
1591 IntrinsicInst
&II
) {
1592 Value
*UnpackArg
= II
.getArgOperand(0);
1593 auto *RetTy
= cast
<ScalableVectorType
>(II
.getType());
1594 bool IsSigned
= II
.getIntrinsicID() == Intrinsic::aarch64_sve_sunpkhi
||
1595 II
.getIntrinsicID() == Intrinsic::aarch64_sve_sunpklo
;
1597 // Hi = uunpkhi(splat(X)) --> Hi = splat(extend(X))
1598 // Lo = uunpklo(splat(X)) --> Lo = splat(extend(X))
1599 if (auto *ScalarArg
= getSplatValue(UnpackArg
)) {
1601 IC
.Builder
.CreateIntCast(ScalarArg
, RetTy
->getScalarType(), IsSigned
);
1603 IC
.Builder
.CreateVectorSplat(RetTy
->getElementCount(), ScalarArg
);
1604 NewVal
->takeName(&II
);
1605 return IC
.replaceInstUsesWith(II
, NewVal
);
1608 return std::nullopt
;
1610 static std::optional
<Instruction
*> instCombineSVETBL(InstCombiner
&IC
,
1611 IntrinsicInst
&II
) {
1612 auto *OpVal
= II
.getOperand(0);
1613 auto *OpIndices
= II
.getOperand(1);
1614 VectorType
*VTy
= cast
<VectorType
>(II
.getType());
1616 // Check whether OpIndices is a constant splat value < minimal element count
1618 auto *SplatValue
= dyn_cast_or_null
<ConstantInt
>(getSplatValue(OpIndices
));
1620 SplatValue
->getValue().uge(VTy
->getElementCount().getKnownMinValue()))
1621 return std::nullopt
;
1623 // Convert sve_tbl(OpVal sve_dup_x(SplatValue)) to
1624 // splat_vector(extractelement(OpVal, SplatValue)) for further optimization.
1625 auto *Extract
= IC
.Builder
.CreateExtractElement(OpVal
, SplatValue
);
1627 IC
.Builder
.CreateVectorSplat(VTy
->getElementCount(), Extract
);
1629 VectorSplat
->takeName(&II
);
1630 return IC
.replaceInstUsesWith(II
, VectorSplat
);
1633 static std::optional
<Instruction
*> instCombineSVEZip(InstCombiner
&IC
,
1634 IntrinsicInst
&II
) {
1635 // zip1(uzp1(A, B), uzp2(A, B)) --> A
1636 // zip2(uzp1(A, B), uzp2(A, B)) --> B
1638 if (match(II
.getArgOperand(0),
1639 m_Intrinsic
<Intrinsic::aarch64_sve_uzp1
>(m_Value(A
), m_Value(B
))) &&
1640 match(II
.getArgOperand(1), m_Intrinsic
<Intrinsic::aarch64_sve_uzp2
>(
1641 m_Specific(A
), m_Specific(B
))))
1642 return IC
.replaceInstUsesWith(
1643 II
, (II
.getIntrinsicID() == Intrinsic::aarch64_sve_zip1
? A
: B
));
1645 return std::nullopt
;
1648 static std::optional
<Instruction
*>
1649 instCombineLD1GatherIndex(InstCombiner
&IC
, IntrinsicInst
&II
) {
1650 Value
*Mask
= II
.getOperand(0);
1651 Value
*BasePtr
= II
.getOperand(1);
1652 Value
*Index
= II
.getOperand(2);
1653 Type
*Ty
= II
.getType();
1654 Value
*PassThru
= ConstantAggregateZero::get(Ty
);
1656 // Contiguous gather => masked load.
1657 // (sve.ld1.gather.index Mask BasePtr (sve.index IndexBase 1))
1658 // => (masked.load (gep BasePtr IndexBase) Align Mask zeroinitializer)
1660 if (match(Index
, m_Intrinsic
<Intrinsic::aarch64_sve_index
>(
1661 m_Value(IndexBase
), m_SpecificInt(1)))) {
1663 BasePtr
->getPointerAlignment(II
.getModule()->getDataLayout());
1665 Type
*VecPtrTy
= PointerType::getUnqual(Ty
);
1666 Value
*Ptr
= IC
.Builder
.CreateGEP(cast
<VectorType
>(Ty
)->getElementType(),
1667 BasePtr
, IndexBase
);
1668 Ptr
= IC
.Builder
.CreateBitCast(Ptr
, VecPtrTy
);
1669 CallInst
*MaskedLoad
=
1670 IC
.Builder
.CreateMaskedLoad(Ty
, Ptr
, Alignment
, Mask
, PassThru
);
1671 MaskedLoad
->takeName(&II
);
1672 return IC
.replaceInstUsesWith(II
, MaskedLoad
);
1675 return std::nullopt
;
1678 static std::optional
<Instruction
*>
1679 instCombineST1ScatterIndex(InstCombiner
&IC
, IntrinsicInst
&II
) {
1680 Value
*Val
= II
.getOperand(0);
1681 Value
*Mask
= II
.getOperand(1);
1682 Value
*BasePtr
= II
.getOperand(2);
1683 Value
*Index
= II
.getOperand(3);
1684 Type
*Ty
= Val
->getType();
1686 // Contiguous scatter => masked store.
1687 // (sve.st1.scatter.index Value Mask BasePtr (sve.index IndexBase 1))
1688 // => (masked.store Value (gep BasePtr IndexBase) Align Mask)
1690 if (match(Index
, m_Intrinsic
<Intrinsic::aarch64_sve_index
>(
1691 m_Value(IndexBase
), m_SpecificInt(1)))) {
1693 BasePtr
->getPointerAlignment(II
.getModule()->getDataLayout());
1695 Value
*Ptr
= IC
.Builder
.CreateGEP(cast
<VectorType
>(Ty
)->getElementType(),
1696 BasePtr
, IndexBase
);
1697 Type
*VecPtrTy
= PointerType::getUnqual(Ty
);
1698 Ptr
= IC
.Builder
.CreateBitCast(Ptr
, VecPtrTy
);
1700 (void)IC
.Builder
.CreateMaskedStore(Val
, Ptr
, Alignment
, Mask
);
1702 return IC
.eraseInstFromFunction(II
);
1705 return std::nullopt
;
1708 static std::optional
<Instruction
*> instCombineSVESDIV(InstCombiner
&IC
,
1709 IntrinsicInst
&II
) {
1710 Type
*Int32Ty
= IC
.Builder
.getInt32Ty();
1711 Value
*Pred
= II
.getOperand(0);
1712 Value
*Vec
= II
.getOperand(1);
1713 Value
*DivVec
= II
.getOperand(2);
1715 Value
*SplatValue
= getSplatValue(DivVec
);
1716 ConstantInt
*SplatConstantInt
= dyn_cast_or_null
<ConstantInt
>(SplatValue
);
1717 if (!SplatConstantInt
)
1718 return std::nullopt
;
1719 APInt Divisor
= SplatConstantInt
->getValue();
1721 if (Divisor
.isPowerOf2()) {
1722 Constant
*DivisorLog2
= ConstantInt::get(Int32Ty
, Divisor
.logBase2());
1723 auto ASRD
= IC
.Builder
.CreateIntrinsic(
1724 Intrinsic::aarch64_sve_asrd
, {II
.getType()}, {Pred
, Vec
, DivisorLog2
});
1725 return IC
.replaceInstUsesWith(II
, ASRD
);
1727 if (Divisor
.isNegatedPowerOf2()) {
1729 Constant
*DivisorLog2
= ConstantInt::get(Int32Ty
, Divisor
.logBase2());
1730 auto ASRD
= IC
.Builder
.CreateIntrinsic(
1731 Intrinsic::aarch64_sve_asrd
, {II
.getType()}, {Pred
, Vec
, DivisorLog2
});
1732 auto NEG
= IC
.Builder
.CreateIntrinsic(
1733 Intrinsic::aarch64_sve_neg
, {ASRD
->getType()}, {ASRD
, Pred
, ASRD
});
1734 return IC
.replaceInstUsesWith(II
, NEG
);
1737 return std::nullopt
;
1740 bool SimplifyValuePattern(SmallVector
<Value
*> &Vec
, bool AllowPoison
) {
1741 size_t VecSize
= Vec
.size();
1744 if (!isPowerOf2_64(VecSize
))
1746 size_t HalfVecSize
= VecSize
/ 2;
1748 for (auto LHS
= Vec
.begin(), RHS
= Vec
.begin() + HalfVecSize
;
1749 RHS
!= Vec
.end(); LHS
++, RHS
++) {
1750 if (*LHS
!= nullptr && *RHS
!= nullptr) {
1758 if (*LHS
== nullptr && *RHS
!= nullptr)
1762 Vec
.resize(HalfVecSize
);
1763 SimplifyValuePattern(Vec
, AllowPoison
);
1767 // Try to simplify dupqlane patterns like dupqlane(f32 A, f32 B, f32 A, f32 B)
1768 // to dupqlane(f64(C)) where C is A concatenated with B
1769 static std::optional
<Instruction
*> instCombineSVEDupqLane(InstCombiner
&IC
,
1770 IntrinsicInst
&II
) {
1771 Value
*CurrentInsertElt
= nullptr, *Default
= nullptr;
1772 if (!match(II
.getOperand(0),
1773 m_Intrinsic
<Intrinsic::vector_insert
>(
1774 m_Value(Default
), m_Value(CurrentInsertElt
), m_Value())) ||
1775 !isa
<FixedVectorType
>(CurrentInsertElt
->getType()))
1776 return std::nullopt
;
1777 auto IIScalableTy
= cast
<ScalableVectorType
>(II
.getType());
1779 // Insert the scalars into a container ordered by InsertElement index
1780 SmallVector
<Value
*> Elts(IIScalableTy
->getMinNumElements(), nullptr);
1781 while (auto InsertElt
= dyn_cast
<InsertElementInst
>(CurrentInsertElt
)) {
1782 auto Idx
= cast
<ConstantInt
>(InsertElt
->getOperand(2));
1783 Elts
[Idx
->getValue().getZExtValue()] = InsertElt
->getOperand(1);
1784 CurrentInsertElt
= InsertElt
->getOperand(0);
1788 isa
<PoisonValue
>(CurrentInsertElt
) && isa
<PoisonValue
>(Default
);
1789 if (!SimplifyValuePattern(Elts
, AllowPoison
))
1790 return std::nullopt
;
1792 // Rebuild the simplified chain of InsertElements. e.g. (a, b, a, b) as (a, b)
1793 Value
*InsertEltChain
= PoisonValue::get(CurrentInsertElt
->getType());
1794 for (size_t I
= 0; I
< Elts
.size(); I
++) {
1795 if (Elts
[I
] == nullptr)
1797 InsertEltChain
= IC
.Builder
.CreateInsertElement(InsertEltChain
, Elts
[I
],
1798 IC
.Builder
.getInt64(I
));
1800 if (InsertEltChain
== nullptr)
1801 return std::nullopt
;
1803 // Splat the simplified sequence, e.g. (f16 a, f16 b, f16 c, f16 d) as one i64
1804 // value or (f16 a, f16 b) as one i32 value. This requires an InsertSubvector
1805 // be bitcast to a type wide enough to fit the sequence, be splatted, and then
1806 // be narrowed back to the original type.
1807 unsigned PatternWidth
= IIScalableTy
->getScalarSizeInBits() * Elts
.size();
1808 unsigned PatternElementCount
= IIScalableTy
->getScalarSizeInBits() *
1809 IIScalableTy
->getMinNumElements() /
1812 IntegerType
*WideTy
= IC
.Builder
.getIntNTy(PatternWidth
);
1813 auto *WideScalableTy
= ScalableVectorType::get(WideTy
, PatternElementCount
);
1814 auto *WideShuffleMaskTy
=
1815 ScalableVectorType::get(IC
.Builder
.getInt32Ty(), PatternElementCount
);
1817 auto ZeroIdx
= ConstantInt::get(IC
.Builder
.getInt64Ty(), APInt(64, 0));
1818 auto InsertSubvector
= IC
.Builder
.CreateInsertVector(
1819 II
.getType(), PoisonValue::get(II
.getType()), InsertEltChain
, ZeroIdx
);
1821 IC
.Builder
.CreateBitOrPointerCast(InsertSubvector
, WideScalableTy
);
1822 auto WideShuffleMask
= ConstantAggregateZero::get(WideShuffleMaskTy
);
1823 auto WideShuffle
= IC
.Builder
.CreateShuffleVector(
1824 WideBitcast
, PoisonValue::get(WideScalableTy
), WideShuffleMask
);
1825 auto NarrowBitcast
=
1826 IC
.Builder
.CreateBitOrPointerCast(WideShuffle
, II
.getType());
1828 return IC
.replaceInstUsesWith(II
, NarrowBitcast
);
1831 static std::optional
<Instruction
*> instCombineMaxMinNM(InstCombiner
&IC
,
1832 IntrinsicInst
&II
) {
1833 Value
*A
= II
.getArgOperand(0);
1834 Value
*B
= II
.getArgOperand(1);
1836 return IC
.replaceInstUsesWith(II
, A
);
1838 return std::nullopt
;
1841 static std::optional
<Instruction
*> instCombineSVESrshl(InstCombiner
&IC
,
1842 IntrinsicInst
&II
) {
1843 Value
*Pred
= II
.getOperand(0);
1844 Value
*Vec
= II
.getOperand(1);
1845 Value
*Shift
= II
.getOperand(2);
1847 // Convert SRSHL into the simpler LSL intrinsic when fed by an ABS intrinsic.
1848 Value
*AbsPred
, *MergedValue
;
1849 if (!match(Vec
, m_Intrinsic
<Intrinsic::aarch64_sve_sqabs
>(
1850 m_Value(MergedValue
), m_Value(AbsPred
), m_Value())) &&
1851 !match(Vec
, m_Intrinsic
<Intrinsic::aarch64_sve_abs
>(
1852 m_Value(MergedValue
), m_Value(AbsPred
), m_Value())))
1854 return std::nullopt
;
1856 // Transform is valid if any of the following are true:
1857 // * The ABS merge value is an undef or non-negative
1858 // * The ABS predicate is all active
1859 // * The ABS predicate and the SRSHL predicates are the same
1860 if (!isa
<UndefValue
>(MergedValue
) && !match(MergedValue
, m_NonNegative()) &&
1861 AbsPred
!= Pred
&& !isAllActivePredicate(AbsPred
))
1862 return std::nullopt
;
1864 // Only valid when the shift amount is non-negative, otherwise the rounding
1865 // behaviour of SRSHL cannot be ignored.
1866 if (!match(Shift
, m_NonNegative()))
1867 return std::nullopt
;
1869 auto LSL
= IC
.Builder
.CreateIntrinsic(Intrinsic::aarch64_sve_lsl
,
1870 {II
.getType()}, {Pred
, Vec
, Shift
});
1872 return IC
.replaceInstUsesWith(II
, LSL
);
1875 std::optional
<Instruction
*>
1876 AArch64TTIImpl::instCombineIntrinsic(InstCombiner
&IC
,
1877 IntrinsicInst
&II
) const {
1878 Intrinsic::ID IID
= II
.getIntrinsicID();
1882 case Intrinsic::aarch64_neon_fmaxnm
:
1883 case Intrinsic::aarch64_neon_fminnm
:
1884 return instCombineMaxMinNM(IC
, II
);
1885 case Intrinsic::aarch64_sve_convert_from_svbool
:
1886 return instCombineConvertFromSVBool(IC
, II
);
1887 case Intrinsic::aarch64_sve_dup
:
1888 return instCombineSVEDup(IC
, II
);
1889 case Intrinsic::aarch64_sve_dup_x
:
1890 return instCombineSVEDupX(IC
, II
);
1891 case Intrinsic::aarch64_sve_cmpne
:
1892 case Intrinsic::aarch64_sve_cmpne_wide
:
1893 return instCombineSVECmpNE(IC
, II
);
1894 case Intrinsic::aarch64_sve_rdffr
:
1895 return instCombineRDFFR(IC
, II
);
1896 case Intrinsic::aarch64_sve_lasta
:
1897 case Intrinsic::aarch64_sve_lastb
:
1898 return instCombineSVELast(IC
, II
);
1899 case Intrinsic::aarch64_sve_clasta_n
:
1900 case Intrinsic::aarch64_sve_clastb_n
:
1901 return instCombineSVECondLast(IC
, II
);
1902 case Intrinsic::aarch64_sve_cntd
:
1903 return instCombineSVECntElts(IC
, II
, 2);
1904 case Intrinsic::aarch64_sve_cntw
:
1905 return instCombineSVECntElts(IC
, II
, 4);
1906 case Intrinsic::aarch64_sve_cnth
:
1907 return instCombineSVECntElts(IC
, II
, 8);
1908 case Intrinsic::aarch64_sve_cntb
:
1909 return instCombineSVECntElts(IC
, II
, 16);
1910 case Intrinsic::aarch64_sve_ptest_any
:
1911 case Intrinsic::aarch64_sve_ptest_first
:
1912 case Intrinsic::aarch64_sve_ptest_last
:
1913 return instCombineSVEPTest(IC
, II
);
1914 case Intrinsic::aarch64_sve_fabd
:
1915 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fabd_u
);
1916 case Intrinsic::aarch64_sve_fadd
:
1917 return instCombineSVEVectorFAdd(IC
, II
);
1918 case Intrinsic::aarch64_sve_fadd_u
:
1919 return instCombineSVEVectorFAddU(IC
, II
);
1920 case Intrinsic::aarch64_sve_fdiv
:
1921 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fdiv_u
);
1922 case Intrinsic::aarch64_sve_fmax
:
1923 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fmax_u
);
1924 case Intrinsic::aarch64_sve_fmaxnm
:
1925 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fmaxnm_u
);
1926 case Intrinsic::aarch64_sve_fmin
:
1927 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fmin_u
);
1928 case Intrinsic::aarch64_sve_fminnm
:
1929 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fminnm_u
);
1930 case Intrinsic::aarch64_sve_fmla
:
1931 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fmla_u
);
1932 case Intrinsic::aarch64_sve_fmls
:
1933 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fmls_u
);
1934 case Intrinsic::aarch64_sve_fmul
:
1936 instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fmul_u
))
1938 return instCombineSVEVectorMul(IC
, II
, Intrinsic::aarch64_sve_fmul_u
);
1939 case Intrinsic::aarch64_sve_fmul_u
:
1940 return instCombineSVEVectorMul(IC
, II
, Intrinsic::aarch64_sve_fmul_u
);
1941 case Intrinsic::aarch64_sve_fmulx
:
1942 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fmulx_u
);
1943 case Intrinsic::aarch64_sve_fnmla
:
1944 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fnmla_u
);
1945 case Intrinsic::aarch64_sve_fnmls
:
1946 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_fnmls_u
);
1947 case Intrinsic::aarch64_sve_fsub
:
1948 return instCombineSVEVectorFSub(IC
, II
);
1949 case Intrinsic::aarch64_sve_fsub_u
:
1950 return instCombineSVEVectorFSubU(IC
, II
);
1951 case Intrinsic::aarch64_sve_add
:
1952 return instCombineSVEVectorAdd(IC
, II
);
1953 case Intrinsic::aarch64_sve_add_u
:
1954 return instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_mul_u
,
1955 Intrinsic::aarch64_sve_mla_u
>(
1957 case Intrinsic::aarch64_sve_mla
:
1958 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_mla_u
);
1959 case Intrinsic::aarch64_sve_mls
:
1960 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_mls_u
);
1961 case Intrinsic::aarch64_sve_mul
:
1963 instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_mul_u
))
1965 return instCombineSVEVectorMul(IC
, II
, Intrinsic::aarch64_sve_mul_u
);
1966 case Intrinsic::aarch64_sve_mul_u
:
1967 return instCombineSVEVectorMul(IC
, II
, Intrinsic::aarch64_sve_mul_u
);
1968 case Intrinsic::aarch64_sve_sabd
:
1969 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_sabd_u
);
1970 case Intrinsic::aarch64_sve_smax
:
1971 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_smax_u
);
1972 case Intrinsic::aarch64_sve_smin
:
1973 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_smin_u
);
1974 case Intrinsic::aarch64_sve_smulh
:
1975 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_smulh_u
);
1976 case Intrinsic::aarch64_sve_sub
:
1977 return instCombineSVEVectorSub(IC
, II
);
1978 case Intrinsic::aarch64_sve_sub_u
:
1979 return instCombineSVEVectorFuseMulAddSub
<Intrinsic::aarch64_sve_mul_u
,
1980 Intrinsic::aarch64_sve_mls_u
>(
1982 case Intrinsic::aarch64_sve_uabd
:
1983 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_uabd_u
);
1984 case Intrinsic::aarch64_sve_umax
:
1985 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_umax_u
);
1986 case Intrinsic::aarch64_sve_umin
:
1987 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_umin_u
);
1988 case Intrinsic::aarch64_sve_umulh
:
1989 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_umulh_u
);
1990 case Intrinsic::aarch64_sve_asr
:
1991 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_asr_u
);
1992 case Intrinsic::aarch64_sve_lsl
:
1993 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_lsl_u
);
1994 case Intrinsic::aarch64_sve_lsr
:
1995 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_lsr_u
);
1996 case Intrinsic::aarch64_sve_and
:
1997 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_and_u
);
1998 case Intrinsic::aarch64_sve_bic
:
1999 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_bic_u
);
2000 case Intrinsic::aarch64_sve_eor
:
2001 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_eor_u
);
2002 case Intrinsic::aarch64_sve_orr
:
2003 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_orr_u
);
2004 case Intrinsic::aarch64_sve_sqsub
:
2005 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_sqsub_u
);
2006 case Intrinsic::aarch64_sve_uqsub
:
2007 return instCombineSVEAllOrNoActive(IC
, II
, Intrinsic::aarch64_sve_uqsub_u
);
2008 case Intrinsic::aarch64_sve_tbl
:
2009 return instCombineSVETBL(IC
, II
);
2010 case Intrinsic::aarch64_sve_uunpkhi
:
2011 case Intrinsic::aarch64_sve_uunpklo
:
2012 case Intrinsic::aarch64_sve_sunpkhi
:
2013 case Intrinsic::aarch64_sve_sunpklo
:
2014 return instCombineSVEUnpack(IC
, II
);
2015 case Intrinsic::aarch64_sve_zip1
:
2016 case Intrinsic::aarch64_sve_zip2
:
2017 return instCombineSVEZip(IC
, II
);
2018 case Intrinsic::aarch64_sve_ld1_gather_index
:
2019 return instCombineLD1GatherIndex(IC
, II
);
2020 case Intrinsic::aarch64_sve_st1_scatter_index
:
2021 return instCombineST1ScatterIndex(IC
, II
);
2022 case Intrinsic::aarch64_sve_ld1
:
2023 return instCombineSVELD1(IC
, II
, DL
);
2024 case Intrinsic::aarch64_sve_st1
:
2025 return instCombineSVEST1(IC
, II
, DL
);
2026 case Intrinsic::aarch64_sve_sdiv
:
2027 return instCombineSVESDIV(IC
, II
);
2028 case Intrinsic::aarch64_sve_sel
:
2029 return instCombineSVESel(IC
, II
);
2030 case Intrinsic::aarch64_sve_srshl
:
2031 return instCombineSVESrshl(IC
, II
);
2032 case Intrinsic::aarch64_sve_dupq_lane
:
2033 return instCombineSVEDupqLane(IC
, II
);
2036 return std::nullopt
;
2039 std::optional
<Value
*> AArch64TTIImpl::simplifyDemandedVectorEltsIntrinsic(
2040 InstCombiner
&IC
, IntrinsicInst
&II
, APInt OrigDemandedElts
,
2041 APInt
&UndefElts
, APInt
&UndefElts2
, APInt
&UndefElts3
,
2042 std::function
<void(Instruction
*, unsigned, APInt
, APInt
&)>
2043 SimplifyAndSetOp
) const {
2044 switch (II
.getIntrinsicID()) {
2047 case Intrinsic::aarch64_neon_fcvtxn
:
2048 case Intrinsic::aarch64_neon_rshrn
:
2049 case Intrinsic::aarch64_neon_sqrshrn
:
2050 case Intrinsic::aarch64_neon_sqrshrun
:
2051 case Intrinsic::aarch64_neon_sqshrn
:
2052 case Intrinsic::aarch64_neon_sqshrun
:
2053 case Intrinsic::aarch64_neon_sqxtn
:
2054 case Intrinsic::aarch64_neon_sqxtun
:
2055 case Intrinsic::aarch64_neon_uqrshrn
:
2056 case Intrinsic::aarch64_neon_uqshrn
:
2057 case Intrinsic::aarch64_neon_uqxtn
:
2058 SimplifyAndSetOp(&II
, 0, OrigDemandedElts
, UndefElts
);
2062 return std::nullopt
;
2066 AArch64TTIImpl::getRegisterBitWidth(TargetTransformInfo::RegisterKind K
) const {
2068 case TargetTransformInfo::RGK_Scalar
:
2069 return TypeSize::getFixed(64);
2070 case TargetTransformInfo::RGK_FixedWidthVector
:
2071 if (!ST
->isNeonAvailable() && !EnableFixedwidthAutovecInStreamingMode
)
2072 return TypeSize::getFixed(0);
2075 return TypeSize::getFixed(
2076 std::max(ST
->getMinSVEVectorSizeInBits(), 128u));
2078 return TypeSize::getFixed(ST
->hasNEON() ? 128 : 0);
2079 case TargetTransformInfo::RGK_ScalableVector
:
2080 if (!ST
->isSVEAvailable() && !EnableScalableAutovecInStreamingMode
)
2081 return TypeSize::getScalable(0);
2083 return TypeSize::getScalable(ST
->hasSVE() ? 128 : 0);
2085 llvm_unreachable("Unsupported register kind");
2088 bool AArch64TTIImpl::isWideningInstruction(Type
*DstTy
, unsigned Opcode
,
2089 ArrayRef
<const Value
*> Args
,
2090 Type
*SrcOverrideTy
) {
2091 // A helper that returns a vector type from the given type. The number of
2092 // elements in type Ty determines the vector width.
2093 auto toVectorTy
= [&](Type
*ArgTy
) {
2094 return VectorType::get(ArgTy
->getScalarType(),
2095 cast
<VectorType
>(DstTy
)->getElementCount());
2098 // Exit early if DstTy is not a vector type whose elements are one of [i16,
2099 // i32, i64]. SVE doesn't generally have the same set of instructions to
2100 // perform an extend with the add/sub/mul. There are SMULLB style
2101 // instructions, but they operate on top/bottom, requiring some sort of lane
2102 // interleaving to be used with zext/sext.
2103 unsigned DstEltSize
= DstTy
->getScalarSizeInBits();
2104 if (!useNeonVector(DstTy
) || Args
.size() != 2 ||
2105 (DstEltSize
!= 16 && DstEltSize
!= 32 && DstEltSize
!= 64))
2108 // Determine if the operation has a widening variant. We consider both the
2109 // "long" (e.g., usubl) and "wide" (e.g., usubw) versions of the
2112 // TODO: Add additional widening operations (e.g., shl, etc.) once we
2113 // verify that their extending operands are eliminated during code
2115 Type
*SrcTy
= SrcOverrideTy
;
2117 case Instruction::Add
: // UADDL(2), SADDL(2), UADDW(2), SADDW(2).
2118 case Instruction::Sub
: // USUBL(2), SSUBL(2), USUBW(2), SSUBW(2).
2119 // The second operand needs to be an extend
2120 if (isa
<SExtInst
>(Args
[1]) || isa
<ZExtInst
>(Args
[1])) {
2123 toVectorTy(cast
<Instruction
>(Args
[1])->getOperand(0)->getType());
2127 case Instruction::Mul
: { // SMULL(2), UMULL(2)
2128 // Both operands need to be extends of the same type.
2129 if ((isa
<SExtInst
>(Args
[0]) && isa
<SExtInst
>(Args
[1])) ||
2130 (isa
<ZExtInst
>(Args
[0]) && isa
<ZExtInst
>(Args
[1]))) {
2133 toVectorTy(cast
<Instruction
>(Args
[0])->getOperand(0)->getType());
2134 } else if (isa
<ZExtInst
>(Args
[0]) || isa
<ZExtInst
>(Args
[1])) {
2135 // If one of the operands is a Zext and the other has enough zero bits to
2136 // be treated as unsigned, we can still general a umull, meaning the zext
2139 computeKnownBits(isa
<ZExtInst
>(Args
[0]) ? Args
[1] : Args
[0], DL
);
2140 if (Args
[0]->getType()->getScalarSizeInBits() -
2141 Known
.Zero
.countLeadingOnes() >
2142 DstTy
->getScalarSizeInBits() / 2)
2145 SrcTy
= toVectorTy(Type::getIntNTy(DstTy
->getContext(),
2146 DstTy
->getScalarSizeInBits() / 2));
2155 // Legalize the destination type and ensure it can be used in a widening
2157 auto DstTyL
= getTypeLegalizationCost(DstTy
);
2158 if (!DstTyL
.second
.isVector() || DstEltSize
!= DstTy
->getScalarSizeInBits())
2161 // Legalize the source type and ensure it can be used in a widening
2163 assert(SrcTy
&& "Expected some SrcTy");
2164 auto SrcTyL
= getTypeLegalizationCost(SrcTy
);
2165 unsigned SrcElTySize
= SrcTyL
.second
.getScalarSizeInBits();
2166 if (!SrcTyL
.second
.isVector() || SrcElTySize
!= SrcTy
->getScalarSizeInBits())
2169 // Get the total number of vector elements in the legalized types.
2170 InstructionCost NumDstEls
=
2171 DstTyL
.first
* DstTyL
.second
.getVectorMinNumElements();
2172 InstructionCost NumSrcEls
=
2173 SrcTyL
.first
* SrcTyL
.second
.getVectorMinNumElements();
2175 // Return true if the legalized types have the same number of vector elements
2176 // and the destination element type size is twice that of the source type.
2177 return NumDstEls
== NumSrcEls
&& 2 * SrcElTySize
== DstEltSize
;
2180 // s/urhadd instructions implement the following pattern, making the
2182 // %x = add ((zext i8 -> i16), 1)
2183 // %y = (zext i8 -> i16)
2184 // trunc i16 (lshr (add %x, %y), 1) -> i8
2186 bool AArch64TTIImpl::isExtPartOfAvgExpr(const Instruction
*ExtUser
, Type
*Dst
,
2188 // The source should be a legal vector type.
2189 if (!Src
->isVectorTy() || !TLI
->isTypeLegal(TLI
->getValueType(DL
, Src
)) ||
2190 (Src
->isScalableTy() && !ST
->hasSVE2()))
2193 if (ExtUser
->getOpcode() != Instruction::Add
|| !ExtUser
->hasOneUse())
2196 // Look for trunc/shl/add before trying to match the pattern.
2197 const Instruction
*Add
= ExtUser
;
2199 dyn_cast_or_null
<Instruction
>(Add
->getUniqueUndroppableUser());
2200 if (AddUser
&& AddUser
->getOpcode() == Instruction::Add
)
2203 auto *Shr
= dyn_cast_or_null
<Instruction
>(Add
->getUniqueUndroppableUser());
2204 if (!Shr
|| Shr
->getOpcode() != Instruction::LShr
)
2207 auto *Trunc
= dyn_cast_or_null
<Instruction
>(Shr
->getUniqueUndroppableUser());
2208 if (!Trunc
|| Trunc
->getOpcode() != Instruction::Trunc
||
2209 Src
->getScalarSizeInBits() !=
2210 cast
<CastInst
>(Trunc
)->getDestTy()->getScalarSizeInBits())
2213 // Try to match the whole pattern. Ext could be either the first or second
2214 // m_ZExtOrSExt matched.
2215 Instruction
*Ex1
, *Ex2
;
2216 if (!(match(Add
, m_c_Add(m_Instruction(Ex1
),
2217 m_c_Add(m_Instruction(Ex2
), m_SpecificInt(1))))))
2220 // Ensure both extends are of the same type
2221 if (match(Ex1
, m_ZExtOrSExt(m_Value())) &&
2222 Ex1
->getOpcode() == Ex2
->getOpcode())
2228 InstructionCost
AArch64TTIImpl::getCastInstrCost(unsigned Opcode
, Type
*Dst
,
2230 TTI::CastContextHint CCH
,
2231 TTI::TargetCostKind CostKind
,
2232 const Instruction
*I
) {
2233 int ISD
= TLI
->InstructionOpcodeToISD(Opcode
);
2234 assert(ISD
&& "Invalid opcode");
2235 // If the cast is observable, and it is used by a widening instruction (e.g.,
2236 // uaddl, saddw, etc.), it may be free.
2237 if (I
&& I
->hasOneUser()) {
2238 auto *SingleUser
= cast
<Instruction
>(*I
->user_begin());
2239 SmallVector
<const Value
*, 4> Operands(SingleUser
->operand_values());
2240 if (isWideningInstruction(Dst
, SingleUser
->getOpcode(), Operands
, Src
)) {
2241 // For adds only count the second operand as free if both operands are
2242 // extends but not the same operation. (i.e both operands are not free in
2243 // add(sext, zext)).
2244 if (SingleUser
->getOpcode() == Instruction::Add
) {
2245 if (I
== SingleUser
->getOperand(1) ||
2246 (isa
<CastInst
>(SingleUser
->getOperand(1)) &&
2247 cast
<CastInst
>(SingleUser
->getOperand(1))->getOpcode() == Opcode
))
2249 } else // Others are free so long as isWideningInstruction returned true.
2253 // The cast will be free for the s/urhadd instructions
2254 if ((isa
<ZExtInst
>(I
) || isa
<SExtInst
>(I
)) &&
2255 isExtPartOfAvgExpr(SingleUser
, Dst
, Src
))
2259 // TODO: Allow non-throughput costs that aren't binary.
2260 auto AdjustCost
= [&CostKind
](InstructionCost Cost
) -> InstructionCost
{
2261 if (CostKind
!= TTI::TCK_RecipThroughput
)
2262 return Cost
== 0 ? 0 : 1;
2266 EVT SrcTy
= TLI
->getValueType(DL
, Src
);
2267 EVT DstTy
= TLI
->getValueType(DL
, Dst
);
2269 if (!SrcTy
.isSimple() || !DstTy
.isSimple())
2271 BaseT::getCastInstrCost(Opcode
, Dst
, Src
, CCH
, CostKind
, I
));
2273 static const TypeConversionCostTblEntry
2275 { ISD::TRUNCATE
, MVT::v2i8
, MVT::v2i64
, 1}, // xtn
2276 { ISD::TRUNCATE
, MVT::v2i16
, MVT::v2i64
, 1}, // xtn
2277 { ISD::TRUNCATE
, MVT::v2i32
, MVT::v2i64
, 1}, // xtn
2278 { ISD::TRUNCATE
, MVT::v4i8
, MVT::v4i32
, 1}, // xtn
2279 { ISD::TRUNCATE
, MVT::v4i8
, MVT::v4i64
, 3}, // 2 xtn + 1 uzp1
2280 { ISD::TRUNCATE
, MVT::v4i16
, MVT::v4i32
, 1}, // xtn
2281 { ISD::TRUNCATE
, MVT::v4i16
, MVT::v4i64
, 2}, // 1 uzp1 + 1 xtn
2282 { ISD::TRUNCATE
, MVT::v4i32
, MVT::v4i64
, 1}, // 1 uzp1
2283 { ISD::TRUNCATE
, MVT::v8i8
, MVT::v8i16
, 1}, // 1 xtn
2284 { ISD::TRUNCATE
, MVT::v8i8
, MVT::v8i32
, 2}, // 1 uzp1 + 1 xtn
2285 { ISD::TRUNCATE
, MVT::v8i8
, MVT::v8i64
, 4}, // 3 x uzp1 + xtn
2286 { ISD::TRUNCATE
, MVT::v8i16
, MVT::v8i32
, 1}, // 1 uzp1
2287 { ISD::TRUNCATE
, MVT::v8i16
, MVT::v8i64
, 3}, // 3 x uzp1
2288 { ISD::TRUNCATE
, MVT::v8i32
, MVT::v8i64
, 2}, // 2 x uzp1
2289 { ISD::TRUNCATE
, MVT::v16i8
, MVT::v16i16
, 1}, // uzp1
2290 { ISD::TRUNCATE
, MVT::v16i8
, MVT::v16i32
, 3}, // (2 + 1) x uzp1
2291 { ISD::TRUNCATE
, MVT::v16i8
, MVT::v16i64
, 7}, // (4 + 2 + 1) x uzp1
2292 { ISD::TRUNCATE
, MVT::v16i16
, MVT::v16i32
, 2}, // 2 x uzp1
2293 { ISD::TRUNCATE
, MVT::v16i16
, MVT::v16i64
, 6}, // (4 + 2) x uzp1
2294 { ISD::TRUNCATE
, MVT::v16i32
, MVT::v16i64
, 4}, // 4 x uzp1
2296 // Truncations on nxvmiN
2297 { ISD::TRUNCATE
, MVT::nxv2i1
, MVT::nxv2i16
, 1 },
2298 { ISD::TRUNCATE
, MVT::nxv2i1
, MVT::nxv2i32
, 1 },
2299 { ISD::TRUNCATE
, MVT::nxv2i1
, MVT::nxv2i64
, 1 },
2300 { ISD::TRUNCATE
, MVT::nxv4i1
, MVT::nxv4i16
, 1 },
2301 { ISD::TRUNCATE
, MVT::nxv4i1
, MVT::nxv4i32
, 1 },
2302 { ISD::TRUNCATE
, MVT::nxv4i1
, MVT::nxv4i64
, 2 },
2303 { ISD::TRUNCATE
, MVT::nxv8i1
, MVT::nxv8i16
, 1 },
2304 { ISD::TRUNCATE
, MVT::nxv8i1
, MVT::nxv8i32
, 3 },
2305 { ISD::TRUNCATE
, MVT::nxv8i1
, MVT::nxv8i64
, 5 },
2306 { ISD::TRUNCATE
, MVT::nxv16i1
, MVT::nxv16i8
, 1 },
2307 { ISD::TRUNCATE
, MVT::nxv2i16
, MVT::nxv2i32
, 1 },
2308 { ISD::TRUNCATE
, MVT::nxv2i32
, MVT::nxv2i64
, 1 },
2309 { ISD::TRUNCATE
, MVT::nxv4i16
, MVT::nxv4i32
, 1 },
2310 { ISD::TRUNCATE
, MVT::nxv4i32
, MVT::nxv4i64
, 2 },
2311 { ISD::TRUNCATE
, MVT::nxv8i16
, MVT::nxv8i32
, 3 },
2312 { ISD::TRUNCATE
, MVT::nxv8i32
, MVT::nxv8i64
, 6 },
2314 // The number of shll instructions for the extension.
2315 { ISD::SIGN_EXTEND
, MVT::v4i64
, MVT::v4i16
, 3 },
2316 { ISD::ZERO_EXTEND
, MVT::v4i64
, MVT::v4i16
, 3 },
2317 { ISD::SIGN_EXTEND
, MVT::v4i64
, MVT::v4i32
, 2 },
2318 { ISD::ZERO_EXTEND
, MVT::v4i64
, MVT::v4i32
, 2 },
2319 { ISD::SIGN_EXTEND
, MVT::v8i32
, MVT::v8i8
, 3 },
2320 { ISD::ZERO_EXTEND
, MVT::v8i32
, MVT::v8i8
, 3 },
2321 { ISD::SIGN_EXTEND
, MVT::v8i32
, MVT::v8i16
, 2 },
2322 { ISD::ZERO_EXTEND
, MVT::v8i32
, MVT::v8i16
, 2 },
2323 { ISD::SIGN_EXTEND
, MVT::v8i64
, MVT::v8i8
, 7 },
2324 { ISD::ZERO_EXTEND
, MVT::v8i64
, MVT::v8i8
, 7 },
2325 { ISD::SIGN_EXTEND
, MVT::v8i64
, MVT::v8i16
, 6 },
2326 { ISD::ZERO_EXTEND
, MVT::v8i64
, MVT::v8i16
, 6 },
2327 { ISD::SIGN_EXTEND
, MVT::v16i16
, MVT::v16i8
, 2 },
2328 { ISD::ZERO_EXTEND
, MVT::v16i16
, MVT::v16i8
, 2 },
2329 { ISD::SIGN_EXTEND
, MVT::v16i32
, MVT::v16i8
, 6 },
2330 { ISD::ZERO_EXTEND
, MVT::v16i32
, MVT::v16i8
, 6 },
2332 // LowerVectorINT_TO_FP:
2333 { ISD::SINT_TO_FP
, MVT::v2f32
, MVT::v2i32
, 1 },
2334 { ISD::SINT_TO_FP
, MVT::v4f32
, MVT::v4i32
, 1 },
2335 { ISD::SINT_TO_FP
, MVT::v2f64
, MVT::v2i64
, 1 },
2336 { ISD::UINT_TO_FP
, MVT::v2f32
, MVT::v2i32
, 1 },
2337 { ISD::UINT_TO_FP
, MVT::v4f32
, MVT::v4i32
, 1 },
2338 { ISD::UINT_TO_FP
, MVT::v2f64
, MVT::v2i64
, 1 },
2340 // Complex: to v2f32
2341 { ISD::SINT_TO_FP
, MVT::v2f32
, MVT::v2i8
, 3 },
2342 { ISD::SINT_TO_FP
, MVT::v2f32
, MVT::v2i16
, 3 },
2343 { ISD::SINT_TO_FP
, MVT::v2f32
, MVT::v2i64
, 2 },
2344 { ISD::UINT_TO_FP
, MVT::v2f32
, MVT::v2i8
, 3 },
2345 { ISD::UINT_TO_FP
, MVT::v2f32
, MVT::v2i16
, 3 },
2346 { ISD::UINT_TO_FP
, MVT::v2f32
, MVT::v2i64
, 2 },
2348 // Complex: to v4f32
2349 { ISD::SINT_TO_FP
, MVT::v4f32
, MVT::v4i8
, 4 },
2350 { ISD::SINT_TO_FP
, MVT::v4f32
, MVT::v4i16
, 2 },
2351 { ISD::UINT_TO_FP
, MVT::v4f32
, MVT::v4i8
, 3 },
2352 { ISD::UINT_TO_FP
, MVT::v4f32
, MVT::v4i16
, 2 },
2354 // Complex: to v8f32
2355 { ISD::SINT_TO_FP
, MVT::v8f32
, MVT::v8i8
, 10 },
2356 { ISD::SINT_TO_FP
, MVT::v8f32
, MVT::v8i16
, 4 },
2357 { ISD::UINT_TO_FP
, MVT::v8f32
, MVT::v8i8
, 10 },
2358 { ISD::UINT_TO_FP
, MVT::v8f32
, MVT::v8i16
, 4 },
2360 // Complex: to v16f32
2361 { ISD::SINT_TO_FP
, MVT::v16f32
, MVT::v16i8
, 21 },
2362 { ISD::UINT_TO_FP
, MVT::v16f32
, MVT::v16i8
, 21 },
2364 // Complex: to v2f64
2365 { ISD::SINT_TO_FP
, MVT::v2f64
, MVT::v2i8
, 4 },
2366 { ISD::SINT_TO_FP
, MVT::v2f64
, MVT::v2i16
, 4 },
2367 { ISD::SINT_TO_FP
, MVT::v2f64
, MVT::v2i32
, 2 },
2368 { ISD::UINT_TO_FP
, MVT::v2f64
, MVT::v2i8
, 4 },
2369 { ISD::UINT_TO_FP
, MVT::v2f64
, MVT::v2i16
, 4 },
2370 { ISD::UINT_TO_FP
, MVT::v2f64
, MVT::v2i32
, 2 },
2372 // Complex: to v4f64
2373 { ISD::SINT_TO_FP
, MVT::v4f64
, MVT::v4i32
, 4 },
2374 { ISD::UINT_TO_FP
, MVT::v4f64
, MVT::v4i32
, 4 },
2376 // LowerVectorFP_TO_INT
2377 { ISD::FP_TO_SINT
, MVT::v2i32
, MVT::v2f32
, 1 },
2378 { ISD::FP_TO_SINT
, MVT::v4i32
, MVT::v4f32
, 1 },
2379 { ISD::FP_TO_SINT
, MVT::v2i64
, MVT::v2f64
, 1 },
2380 { ISD::FP_TO_UINT
, MVT::v2i32
, MVT::v2f32
, 1 },
2381 { ISD::FP_TO_UINT
, MVT::v4i32
, MVT::v4f32
, 1 },
2382 { ISD::FP_TO_UINT
, MVT::v2i64
, MVT::v2f64
, 1 },
2384 // Complex, from v2f32: legal type is v2i32 (no cost) or v2i64 (1 ext).
2385 { ISD::FP_TO_SINT
, MVT::v2i64
, MVT::v2f32
, 2 },
2386 { ISD::FP_TO_SINT
, MVT::v2i16
, MVT::v2f32
, 1 },
2387 { ISD::FP_TO_SINT
, MVT::v2i8
, MVT::v2f32
, 1 },
2388 { ISD::FP_TO_UINT
, MVT::v2i64
, MVT::v2f32
, 2 },
2389 { ISD::FP_TO_UINT
, MVT::v2i16
, MVT::v2f32
, 1 },
2390 { ISD::FP_TO_UINT
, MVT::v2i8
, MVT::v2f32
, 1 },
2392 // Complex, from v4f32: legal type is v4i16, 1 narrowing => ~2
2393 { ISD::FP_TO_SINT
, MVT::v4i16
, MVT::v4f32
, 2 },
2394 { ISD::FP_TO_SINT
, MVT::v4i8
, MVT::v4f32
, 2 },
2395 { ISD::FP_TO_UINT
, MVT::v4i16
, MVT::v4f32
, 2 },
2396 { ISD::FP_TO_UINT
, MVT::v4i8
, MVT::v4f32
, 2 },
2398 // Complex, from nxv2f32.
2399 { ISD::FP_TO_SINT
, MVT::nxv2i64
, MVT::nxv2f32
, 1 },
2400 { ISD::FP_TO_SINT
, MVT::nxv2i32
, MVT::nxv2f32
, 1 },
2401 { ISD::FP_TO_SINT
, MVT::nxv2i16
, MVT::nxv2f32
, 1 },
2402 { ISD::FP_TO_SINT
, MVT::nxv2i8
, MVT::nxv2f32
, 1 },
2403 { ISD::FP_TO_UINT
, MVT::nxv2i64
, MVT::nxv2f32
, 1 },
2404 { ISD::FP_TO_UINT
, MVT::nxv2i32
, MVT::nxv2f32
, 1 },
2405 { ISD::FP_TO_UINT
, MVT::nxv2i16
, MVT::nxv2f32
, 1 },
2406 { ISD::FP_TO_UINT
, MVT::nxv2i8
, MVT::nxv2f32
, 1 },
2408 // Complex, from v2f64: legal type is v2i32, 1 narrowing => ~2.
2409 { ISD::FP_TO_SINT
, MVT::v2i32
, MVT::v2f64
, 2 },
2410 { ISD::FP_TO_SINT
, MVT::v2i16
, MVT::v2f64
, 2 },
2411 { ISD::FP_TO_SINT
, MVT::v2i8
, MVT::v2f64
, 2 },
2412 { ISD::FP_TO_UINT
, MVT::v2i32
, MVT::v2f64
, 2 },
2413 { ISD::FP_TO_UINT
, MVT::v2i16
, MVT::v2f64
, 2 },
2414 { ISD::FP_TO_UINT
, MVT::v2i8
, MVT::v2f64
, 2 },
2416 // Complex, from nxv2f64.
2417 { ISD::FP_TO_SINT
, MVT::nxv2i64
, MVT::nxv2f64
, 1 },
2418 { ISD::FP_TO_SINT
, MVT::nxv2i32
, MVT::nxv2f64
, 1 },
2419 { ISD::FP_TO_SINT
, MVT::nxv2i16
, MVT::nxv2f64
, 1 },
2420 { ISD::FP_TO_SINT
, MVT::nxv2i8
, MVT::nxv2f64
, 1 },
2421 { ISD::FP_TO_UINT
, MVT::nxv2i64
, MVT::nxv2f64
, 1 },
2422 { ISD::FP_TO_UINT
, MVT::nxv2i32
, MVT::nxv2f64
, 1 },
2423 { ISD::FP_TO_UINT
, MVT::nxv2i16
, MVT::nxv2f64
, 1 },
2424 { ISD::FP_TO_UINT
, MVT::nxv2i8
, MVT::nxv2f64
, 1 },
2426 // Complex, from nxv4f32.
2427 { ISD::FP_TO_SINT
, MVT::nxv4i64
, MVT::nxv4f32
, 4 },
2428 { ISD::FP_TO_SINT
, MVT::nxv4i32
, MVT::nxv4f32
, 1 },
2429 { ISD::FP_TO_SINT
, MVT::nxv4i16
, MVT::nxv4f32
, 1 },
2430 { ISD::FP_TO_SINT
, MVT::nxv4i8
, MVT::nxv4f32
, 1 },
2431 { ISD::FP_TO_UINT
, MVT::nxv4i64
, MVT::nxv4f32
, 4 },
2432 { ISD::FP_TO_UINT
, MVT::nxv4i32
, MVT::nxv4f32
, 1 },
2433 { ISD::FP_TO_UINT
, MVT::nxv4i16
, MVT::nxv4f32
, 1 },
2434 { ISD::FP_TO_UINT
, MVT::nxv4i8
, MVT::nxv4f32
, 1 },
2436 // Complex, from nxv8f64. Illegal -> illegal conversions not required.
2437 { ISD::FP_TO_SINT
, MVT::nxv8i16
, MVT::nxv8f64
, 7 },
2438 { ISD::FP_TO_SINT
, MVT::nxv8i8
, MVT::nxv8f64
, 7 },
2439 { ISD::FP_TO_UINT
, MVT::nxv8i16
, MVT::nxv8f64
, 7 },
2440 { ISD::FP_TO_UINT
, MVT::nxv8i8
, MVT::nxv8f64
, 7 },
2442 // Complex, from nxv4f64. Illegal -> illegal conversions not required.
2443 { ISD::FP_TO_SINT
, MVT::nxv4i32
, MVT::nxv4f64
, 3 },
2444 { ISD::FP_TO_SINT
, MVT::nxv4i16
, MVT::nxv4f64
, 3 },
2445 { ISD::FP_TO_SINT
, MVT::nxv4i8
, MVT::nxv4f64
, 3 },
2446 { ISD::FP_TO_UINT
, MVT::nxv4i32
, MVT::nxv4f64
, 3 },
2447 { ISD::FP_TO_UINT
, MVT::nxv4i16
, MVT::nxv4f64
, 3 },
2448 { ISD::FP_TO_UINT
, MVT::nxv4i8
, MVT::nxv4f64
, 3 },
2450 // Complex, from nxv8f32. Illegal -> illegal conversions not required.
2451 { ISD::FP_TO_SINT
, MVT::nxv8i16
, MVT::nxv8f32
, 3 },
2452 { ISD::FP_TO_SINT
, MVT::nxv8i8
, MVT::nxv8f32
, 3 },
2453 { ISD::FP_TO_UINT
, MVT::nxv8i16
, MVT::nxv8f32
, 3 },
2454 { ISD::FP_TO_UINT
, MVT::nxv8i8
, MVT::nxv8f32
, 3 },
2456 // Complex, from nxv8f16.
2457 { ISD::FP_TO_SINT
, MVT::nxv8i64
, MVT::nxv8f16
, 10 },
2458 { ISD::FP_TO_SINT
, MVT::nxv8i32
, MVT::nxv8f16
, 4 },
2459 { ISD::FP_TO_SINT
, MVT::nxv8i16
, MVT::nxv8f16
, 1 },
2460 { ISD::FP_TO_SINT
, MVT::nxv8i8
, MVT::nxv8f16
, 1 },
2461 { ISD::FP_TO_UINT
, MVT::nxv8i64
, MVT::nxv8f16
, 10 },
2462 { ISD::FP_TO_UINT
, MVT::nxv8i32
, MVT::nxv8f16
, 4 },
2463 { ISD::FP_TO_UINT
, MVT::nxv8i16
, MVT::nxv8f16
, 1 },
2464 { ISD::FP_TO_UINT
, MVT::nxv8i8
, MVT::nxv8f16
, 1 },
2466 // Complex, from nxv4f16.
2467 { ISD::FP_TO_SINT
, MVT::nxv4i64
, MVT::nxv4f16
, 4 },
2468 { ISD::FP_TO_SINT
, MVT::nxv4i32
, MVT::nxv4f16
, 1 },
2469 { ISD::FP_TO_SINT
, MVT::nxv4i16
, MVT::nxv4f16
, 1 },
2470 { ISD::FP_TO_SINT
, MVT::nxv4i8
, MVT::nxv4f16
, 1 },
2471 { ISD::FP_TO_UINT
, MVT::nxv4i64
, MVT::nxv4f16
, 4 },
2472 { ISD::FP_TO_UINT
, MVT::nxv4i32
, MVT::nxv4f16
, 1 },
2473 { ISD::FP_TO_UINT
, MVT::nxv4i16
, MVT::nxv4f16
, 1 },
2474 { ISD::FP_TO_UINT
, MVT::nxv4i8
, MVT::nxv4f16
, 1 },
2476 // Complex, from nxv2f16.
2477 { ISD::FP_TO_SINT
, MVT::nxv2i64
, MVT::nxv2f16
, 1 },
2478 { ISD::FP_TO_SINT
, MVT::nxv2i32
, MVT::nxv2f16
, 1 },
2479 { ISD::FP_TO_SINT
, MVT::nxv2i16
, MVT::nxv2f16
, 1 },
2480 { ISD::FP_TO_SINT
, MVT::nxv2i8
, MVT::nxv2f16
, 1 },
2481 { ISD::FP_TO_UINT
, MVT::nxv2i64
, MVT::nxv2f16
, 1 },
2482 { ISD::FP_TO_UINT
, MVT::nxv2i32
, MVT::nxv2f16
, 1 },
2483 { ISD::FP_TO_UINT
, MVT::nxv2i16
, MVT::nxv2f16
, 1 },
2484 { ISD::FP_TO_UINT
, MVT::nxv2i8
, MVT::nxv2f16
, 1 },
2486 // Truncate from nxvmf32 to nxvmf16.
2487 { ISD::FP_ROUND
, MVT::nxv2f16
, MVT::nxv2f32
, 1 },
2488 { ISD::FP_ROUND
, MVT::nxv4f16
, MVT::nxv4f32
, 1 },
2489 { ISD::FP_ROUND
, MVT::nxv8f16
, MVT::nxv8f32
, 3 },
2491 // Truncate from nxvmf64 to nxvmf16.
2492 { ISD::FP_ROUND
, MVT::nxv2f16
, MVT::nxv2f64
, 1 },
2493 { ISD::FP_ROUND
, MVT::nxv4f16
, MVT::nxv4f64
, 3 },
2494 { ISD::FP_ROUND
, MVT::nxv8f16
, MVT::nxv8f64
, 7 },
2496 // Truncate from nxvmf64 to nxvmf32.
2497 { ISD::FP_ROUND
, MVT::nxv2f32
, MVT::nxv2f64
, 1 },
2498 { ISD::FP_ROUND
, MVT::nxv4f32
, MVT::nxv4f64
, 3 },
2499 { ISD::FP_ROUND
, MVT::nxv8f32
, MVT::nxv8f64
, 6 },
2501 // Extend from nxvmf16 to nxvmf32.
2502 { ISD::FP_EXTEND
, MVT::nxv2f32
, MVT::nxv2f16
, 1},
2503 { ISD::FP_EXTEND
, MVT::nxv4f32
, MVT::nxv4f16
, 1},
2504 { ISD::FP_EXTEND
, MVT::nxv8f32
, MVT::nxv8f16
, 2},
2506 // Extend from nxvmf16 to nxvmf64.
2507 { ISD::FP_EXTEND
, MVT::nxv2f64
, MVT::nxv2f16
, 1},
2508 { ISD::FP_EXTEND
, MVT::nxv4f64
, MVT::nxv4f16
, 2},
2509 { ISD::FP_EXTEND
, MVT::nxv8f64
, MVT::nxv8f16
, 4},
2511 // Extend from nxvmf32 to nxvmf64.
2512 { ISD::FP_EXTEND
, MVT::nxv2f64
, MVT::nxv2f32
, 1},
2513 { ISD::FP_EXTEND
, MVT::nxv4f64
, MVT::nxv4f32
, 2},
2514 { ISD::FP_EXTEND
, MVT::nxv8f64
, MVT::nxv8f32
, 6},
2516 // Bitcasts from float to integer
2517 { ISD::BITCAST
, MVT::nxv2f16
, MVT::nxv2i16
, 0 },
2518 { ISD::BITCAST
, MVT::nxv4f16
, MVT::nxv4i16
, 0 },
2519 { ISD::BITCAST
, MVT::nxv2f32
, MVT::nxv2i32
, 0 },
2521 // Bitcasts from integer to float
2522 { ISD::BITCAST
, MVT::nxv2i16
, MVT::nxv2f16
, 0 },
2523 { ISD::BITCAST
, MVT::nxv4i16
, MVT::nxv4f16
, 0 },
2524 { ISD::BITCAST
, MVT::nxv2i32
, MVT::nxv2f32
, 0 },
2526 // Add cost for extending to illegal -too wide- scalable vectors.
2527 // zero/sign extend are implemented by multiple unpack operations,
2528 // where each operation has a cost of 1.
2529 { ISD::ZERO_EXTEND
, MVT::nxv16i16
, MVT::nxv16i8
, 2},
2530 { ISD::ZERO_EXTEND
, MVT::nxv16i32
, MVT::nxv16i8
, 6},
2531 { ISD::ZERO_EXTEND
, MVT::nxv16i64
, MVT::nxv16i8
, 14},
2532 { ISD::ZERO_EXTEND
, MVT::nxv8i32
, MVT::nxv8i16
, 2},
2533 { ISD::ZERO_EXTEND
, MVT::nxv8i64
, MVT::nxv8i16
, 6},
2534 { ISD::ZERO_EXTEND
, MVT::nxv4i64
, MVT::nxv4i32
, 2},
2536 { ISD::SIGN_EXTEND
, MVT::nxv16i16
, MVT::nxv16i8
, 2},
2537 { ISD::SIGN_EXTEND
, MVT::nxv16i32
, MVT::nxv16i8
, 6},
2538 { ISD::SIGN_EXTEND
, MVT::nxv16i64
, MVT::nxv16i8
, 14},
2539 { ISD::SIGN_EXTEND
, MVT::nxv8i32
, MVT::nxv8i16
, 2},
2540 { ISD::SIGN_EXTEND
, MVT::nxv8i64
, MVT::nxv8i16
, 6},
2541 { ISD::SIGN_EXTEND
, MVT::nxv4i64
, MVT::nxv4i32
, 2},
2544 // We have to estimate a cost of fixed length operation upon
2545 // SVE registers(operations) with the number of registers required
2546 // for a fixed type to be represented upon SVE registers.
2547 EVT WiderTy
= SrcTy
.bitsGT(DstTy
) ? SrcTy
: DstTy
;
2548 if (SrcTy
.isFixedLengthVector() && DstTy
.isFixedLengthVector() &&
2549 SrcTy
.getVectorNumElements() == DstTy
.getVectorNumElements() &&
2550 ST
->useSVEForFixedLengthVectors(WiderTy
)) {
2551 std::pair
<InstructionCost
, MVT
> LT
=
2552 getTypeLegalizationCost(WiderTy
.getTypeForEVT(Dst
->getContext()));
2553 unsigned NumElements
= AArch64::SVEBitsPerBlock
/
2554 LT
.second
.getVectorElementType().getSizeInBits();
2558 Opcode
, ScalableVectorType::get(Dst
->getScalarType(), NumElements
),
2559 ScalableVectorType::get(Src
->getScalarType(), NumElements
), CCH
,
2563 if (const auto *Entry
= ConvertCostTableLookup(ConversionTbl
, ISD
,
2564 DstTy
.getSimpleVT(),
2565 SrcTy
.getSimpleVT()))
2566 return AdjustCost(Entry
->Cost
);
2568 static const TypeConversionCostTblEntry FP16Tbl
[] = {
2569 {ISD::FP_TO_SINT
, MVT::v4i8
, MVT::v4f16
, 1}, // fcvtzs
2570 {ISD::FP_TO_UINT
, MVT::v4i8
, MVT::v4f16
, 1},
2571 {ISD::FP_TO_SINT
, MVT::v4i16
, MVT::v4f16
, 1}, // fcvtzs
2572 {ISD::FP_TO_UINT
, MVT::v4i16
, MVT::v4f16
, 1},
2573 {ISD::FP_TO_SINT
, MVT::v4i32
, MVT::v4f16
, 2}, // fcvtl+fcvtzs
2574 {ISD::FP_TO_UINT
, MVT::v4i32
, MVT::v4f16
, 2},
2575 {ISD::FP_TO_SINT
, MVT::v8i8
, MVT::v8f16
, 2}, // fcvtzs+xtn
2576 {ISD::FP_TO_UINT
, MVT::v8i8
, MVT::v8f16
, 2},
2577 {ISD::FP_TO_SINT
, MVT::v8i16
, MVT::v8f16
, 1}, // fcvtzs
2578 {ISD::FP_TO_UINT
, MVT::v8i16
, MVT::v8f16
, 1},
2579 {ISD::FP_TO_SINT
, MVT::v8i32
, MVT::v8f16
, 4}, // 2*fcvtl+2*fcvtzs
2580 {ISD::FP_TO_UINT
, MVT::v8i32
, MVT::v8f16
, 4},
2581 {ISD::FP_TO_SINT
, MVT::v16i8
, MVT::v16f16
, 3}, // 2*fcvtzs+xtn
2582 {ISD::FP_TO_UINT
, MVT::v16i8
, MVT::v16f16
, 3},
2583 {ISD::FP_TO_SINT
, MVT::v16i16
, MVT::v16f16
, 2}, // 2*fcvtzs
2584 {ISD::FP_TO_UINT
, MVT::v16i16
, MVT::v16f16
, 2},
2585 {ISD::FP_TO_SINT
, MVT::v16i32
, MVT::v16f16
, 8}, // 4*fcvtl+4*fcvtzs
2586 {ISD::FP_TO_UINT
, MVT::v16i32
, MVT::v16f16
, 8},
2587 {ISD::UINT_TO_FP
, MVT::v8f16
, MVT::v8i8
, 2}, // ushll + ucvtf
2588 {ISD::SINT_TO_FP
, MVT::v8f16
, MVT::v8i8
, 2}, // sshll + scvtf
2589 {ISD::UINT_TO_FP
, MVT::v16f16
, MVT::v16i8
, 4}, // 2 * ushl(2) + 2 * ucvtf
2590 {ISD::SINT_TO_FP
, MVT::v16f16
, MVT::v16i8
, 4}, // 2 * sshl(2) + 2 * scvtf
2593 if (ST
->hasFullFP16())
2594 if (const auto *Entry
= ConvertCostTableLookup(
2595 FP16Tbl
, ISD
, DstTy
.getSimpleVT(), SrcTy
.getSimpleVT()))
2596 return AdjustCost(Entry
->Cost
);
2598 if ((ISD
== ISD::ZERO_EXTEND
|| ISD
== ISD::SIGN_EXTEND
) &&
2599 CCH
== TTI::CastContextHint::Masked
&& ST
->hasSVEorSME() &&
2600 TLI
->getTypeAction(Src
->getContext(), SrcTy
) ==
2601 TargetLowering::TypePromoteInteger
&&
2602 TLI
->getTypeAction(Dst
->getContext(), DstTy
) ==
2603 TargetLowering::TypeSplitVector
) {
2604 // The standard behaviour in the backend for these cases is to split the
2605 // extend up into two parts:
2606 // 1. Perform an extending load or masked load up to the legal type.
2607 // 2. Extend the loaded data to the final type.
2608 std::pair
<InstructionCost
, MVT
> SrcLT
= getTypeLegalizationCost(Src
);
2609 Type
*LegalTy
= EVT(SrcLT
.second
).getTypeForEVT(Src
->getContext());
2610 InstructionCost Part1
= AArch64TTIImpl::getCastInstrCost(
2611 Opcode
, LegalTy
, Src
, CCH
, CostKind
, I
);
2612 InstructionCost Part2
= AArch64TTIImpl::getCastInstrCost(
2613 Opcode
, Dst
, LegalTy
, TTI::CastContextHint::None
, CostKind
, I
);
2614 return Part1
+ Part2
;
2617 // The BasicTTIImpl version only deals with CCH==TTI::CastContextHint::Normal,
2618 // but we also want to include the TTI::CastContextHint::Masked case too.
2619 if ((ISD
== ISD::ZERO_EXTEND
|| ISD
== ISD::SIGN_EXTEND
) &&
2620 CCH
== TTI::CastContextHint::Masked
&& ST
->hasSVEorSME() &&
2621 TLI
->isTypeLegal(DstTy
))
2622 CCH
= TTI::CastContextHint::Normal
;
2625 BaseT::getCastInstrCost(Opcode
, Dst
, Src
, CCH
, CostKind
, I
));
2628 InstructionCost
AArch64TTIImpl::getExtractWithExtendCost(unsigned Opcode
,
2633 // Make sure we were given a valid extend opcode.
2634 assert((Opcode
== Instruction::SExt
|| Opcode
== Instruction::ZExt
) &&
2637 // We are extending an element we extract from a vector, so the source type
2638 // of the extend is the element type of the vector.
2639 auto *Src
= VecTy
->getElementType();
2641 // Sign- and zero-extends are for integer types only.
2642 assert(isa
<IntegerType
>(Dst
) && isa
<IntegerType
>(Src
) && "Invalid type");
2644 // Get the cost for the extract. We compute the cost (if any) for the extend
2646 TTI::TargetCostKind CostKind
= TTI::TCK_RecipThroughput
;
2647 InstructionCost Cost
= getVectorInstrCost(Instruction::ExtractElement
, VecTy
,
2648 CostKind
, Index
, nullptr, nullptr);
2650 // Legalize the types.
2651 auto VecLT
= getTypeLegalizationCost(VecTy
);
2652 auto DstVT
= TLI
->getValueType(DL
, Dst
);
2653 auto SrcVT
= TLI
->getValueType(DL
, Src
);
2655 // If the resulting type is still a vector and the destination type is legal,
2656 // we may get the extension for free. If not, get the default cost for the
2658 if (!VecLT
.second
.isVector() || !TLI
->isTypeLegal(DstVT
))
2659 return Cost
+ getCastInstrCost(Opcode
, Dst
, Src
, TTI::CastContextHint::None
,
2662 // The destination type should be larger than the element type. If not, get
2663 // the default cost for the extend.
2664 if (DstVT
.getFixedSizeInBits() < SrcVT
.getFixedSizeInBits())
2665 return Cost
+ getCastInstrCost(Opcode
, Dst
, Src
, TTI::CastContextHint::None
,
2670 llvm_unreachable("Opcode should be either SExt or ZExt");
2672 // For sign-extends, we only need a smov, which performs the extension
2674 case Instruction::SExt
:
2677 // For zero-extends, the extend is performed automatically by a umov unless
2678 // the destination type is i64 and the element type is i8 or i16.
2679 case Instruction::ZExt
:
2680 if (DstVT
.getSizeInBits() != 64u || SrcVT
.getSizeInBits() == 32u)
2684 // If we are unable to perform the extend for free, get the default cost.
2685 return Cost
+ getCastInstrCost(Opcode
, Dst
, Src
, TTI::CastContextHint::None
,
2689 InstructionCost
AArch64TTIImpl::getCFInstrCost(unsigned Opcode
,
2690 TTI::TargetCostKind CostKind
,
2691 const Instruction
*I
) {
2692 if (CostKind
!= TTI::TCK_RecipThroughput
)
2693 return Opcode
== Instruction::PHI
? 0 : 1;
2694 assert(CostKind
== TTI::TCK_RecipThroughput
&& "unexpected CostKind");
2695 // Branches are assumed to be predicted.
2699 InstructionCost
AArch64TTIImpl::getVectorInstrCostHelper(const Instruction
*I
,
2703 assert(Val
->isVectorTy() && "This must be a vector type");
2706 // Legalize the type.
2707 std::pair
<InstructionCost
, MVT
> LT
= getTypeLegalizationCost(Val
);
2709 // This type is legalized to a scalar type.
2710 if (!LT
.second
.isVector())
2713 // The type may be split. For fixed-width vectors we can normalize the
2714 // index to the new type.
2715 if (LT
.second
.isFixedLengthVector()) {
2716 unsigned Width
= LT
.second
.getVectorNumElements();
2717 Index
= Index
% Width
;
2720 // The element at index zero is already inside the vector.
2721 // - For a physical (HasRealUse==true) insert-element or extract-element
2722 // instruction that extracts integers, an explicit FPR -> GPR move is
2723 // needed. So it has non-zero cost.
2724 // - For the rest of cases (virtual instruction or element type is float),
2725 // consider the instruction free.
2726 if (Index
== 0 && (!HasRealUse
|| !Val
->getScalarType()->isIntegerTy()))
2729 // This is recognising a LD1 single-element structure to one lane of one
2730 // register instruction. I.e., if this is an `insertelement` instruction,
2731 // and its second operand is a load, then we will generate a LD1, which
2732 // are expensive instructions.
2733 if (I
&& dyn_cast
<LoadInst
>(I
->getOperand(1)))
2734 return ST
->getVectorInsertExtractBaseCost() + 1;
2736 // i1 inserts and extract will include an extra cset or cmp of the vector
2737 // value. Increase the cost by 1 to account.
2738 if (Val
->getScalarSizeInBits() == 1)
2739 return ST
->getVectorInsertExtractBaseCost() + 1;
2742 // If the extract-element and insert-element instructions could be
2743 // simplified away (e.g., could be combined into users by looking at use-def
2744 // context), they have no cost. This is not done in the first place for
2745 // compile-time considerations.
2748 // All other insert/extracts cost this much.
2749 return ST
->getVectorInsertExtractBaseCost();
2752 InstructionCost
AArch64TTIImpl::getVectorInstrCost(unsigned Opcode
, Type
*Val
,
2753 TTI::TargetCostKind CostKind
,
2754 unsigned Index
, Value
*Op0
,
2757 Opcode
== Instruction::InsertElement
&& Op0
&& !isa
<UndefValue
>(Op0
);
2758 return getVectorInstrCostHelper(nullptr, Val
, Index
, HasRealUse
);
2761 InstructionCost
AArch64TTIImpl::getVectorInstrCost(const Instruction
&I
,
2763 TTI::TargetCostKind CostKind
,
2765 return getVectorInstrCostHelper(&I
, Val
, Index
, true /* HasRealUse */);
2768 InstructionCost
AArch64TTIImpl::getScalarizationOverhead(
2769 VectorType
*Ty
, const APInt
&DemandedElts
, bool Insert
, bool Extract
,
2770 TTI::TargetCostKind CostKind
) {
2771 if (isa
<ScalableVectorType
>(Ty
))
2772 return InstructionCost::getInvalid();
2773 if (Ty
->getElementType()->isFloatingPointTy())
2774 return BaseT::getScalarizationOverhead(Ty
, DemandedElts
, Insert
, Extract
,
2776 return DemandedElts
.popcount() * (Insert
+ Extract
) *
2777 ST
->getVectorInsertExtractBaseCost();
2780 InstructionCost
AArch64TTIImpl::getArithmeticInstrCost(
2781 unsigned Opcode
, Type
*Ty
, TTI::TargetCostKind CostKind
,
2782 TTI::OperandValueInfo Op1Info
, TTI::OperandValueInfo Op2Info
,
2783 ArrayRef
<const Value
*> Args
,
2784 const Instruction
*CxtI
) {
2786 // TODO: Handle more cost kinds.
2787 if (CostKind
!= TTI::TCK_RecipThroughput
)
2788 return BaseT::getArithmeticInstrCost(Opcode
, Ty
, CostKind
, Op1Info
,
2789 Op2Info
, Args
, CxtI
);
2791 // Legalize the type.
2792 std::pair
<InstructionCost
, MVT
> LT
= getTypeLegalizationCost(Ty
);
2793 int ISD
= TLI
->InstructionOpcodeToISD(Opcode
);
2797 return BaseT::getArithmeticInstrCost(Opcode
, Ty
, CostKind
, Op1Info
,
2800 if (Op2Info
.isConstant() && Op2Info
.isUniform() && Op2Info
.isPowerOf2()) {
2801 // On AArch64, scalar signed division by constants power-of-two are
2802 // normally expanded to the sequence ADD + CMP + SELECT + SRA.
2803 // The OperandValue properties many not be same as that of previous
2804 // operation; conservatively assume OP_None.
2805 InstructionCost Cost
= getArithmeticInstrCost(
2806 Instruction::Add
, Ty
, CostKind
,
2807 Op1Info
.getNoProps(), Op2Info
.getNoProps());
2808 Cost
+= getArithmeticInstrCost(Instruction::Sub
, Ty
, CostKind
,
2809 Op1Info
.getNoProps(), Op2Info
.getNoProps());
2810 Cost
+= getArithmeticInstrCost(
2811 Instruction::Select
, Ty
, CostKind
,
2812 Op1Info
.getNoProps(), Op2Info
.getNoProps());
2813 Cost
+= getArithmeticInstrCost(Instruction::AShr
, Ty
, CostKind
,
2814 Op1Info
.getNoProps(), Op2Info
.getNoProps());
2819 if (Op2Info
.isConstant() && Op2Info
.isUniform()) {
2820 auto VT
= TLI
->getValueType(DL
, Ty
);
2821 if (TLI
->isOperationLegalOrCustom(ISD::MULHU
, VT
)) {
2822 // Vector signed division by constant are expanded to the
2823 // sequence MULHS + ADD/SUB + SRA + SRL + ADD, and unsigned division
2824 // to MULHS + SUB + SRL + ADD + SRL.
2825 InstructionCost MulCost
= getArithmeticInstrCost(
2826 Instruction::Mul
, Ty
, CostKind
, Op1Info
.getNoProps(), Op2Info
.getNoProps());
2827 InstructionCost AddCost
= getArithmeticInstrCost(
2828 Instruction::Add
, Ty
, CostKind
, Op1Info
.getNoProps(), Op2Info
.getNoProps());
2829 InstructionCost ShrCost
= getArithmeticInstrCost(
2830 Instruction::AShr
, Ty
, CostKind
, Op1Info
.getNoProps(), Op2Info
.getNoProps());
2831 return MulCost
* 2 + AddCost
* 2 + ShrCost
* 2 + 1;
2835 InstructionCost Cost
= BaseT::getArithmeticInstrCost(
2836 Opcode
, Ty
, CostKind
, Op1Info
, Op2Info
);
2837 if (Ty
->isVectorTy()) {
2838 if (TLI
->isOperationLegalOrCustom(ISD
, LT
.second
) && ST
->hasSVE()) {
2839 // SDIV/UDIV operations are lowered using SVE, then we can have less
2841 if (isa
<FixedVectorType
>(Ty
) && cast
<FixedVectorType
>(Ty
)
2842 ->getPrimitiveSizeInBits()
2843 .getFixedValue() < 128) {
2844 EVT VT
= TLI
->getValueType(DL
, Ty
);
2845 static const CostTblEntry DivTbl
[]{
2846 {ISD::SDIV
, MVT::v2i8
, 5}, {ISD::SDIV
, MVT::v4i8
, 8},
2847 {ISD::SDIV
, MVT::v8i8
, 8}, {ISD::SDIV
, MVT::v2i16
, 5},
2848 {ISD::SDIV
, MVT::v4i16
, 5}, {ISD::SDIV
, MVT::v2i32
, 1},
2849 {ISD::UDIV
, MVT::v2i8
, 5}, {ISD::UDIV
, MVT::v4i8
, 8},
2850 {ISD::UDIV
, MVT::v8i8
, 8}, {ISD::UDIV
, MVT::v2i16
, 5},
2851 {ISD::UDIV
, MVT::v4i16
, 5}, {ISD::UDIV
, MVT::v2i32
, 1}};
2853 const auto *Entry
= CostTableLookup(DivTbl
, ISD
, VT
.getSimpleVT());
2854 if (nullptr != Entry
)
2857 // For 8/16-bit elements, the cost is higher because the type
2858 // requires promotion and possibly splitting:
2859 if (LT
.second
.getScalarType() == MVT::i8
)
2861 else if (LT
.second
.getScalarType() == MVT::i16
)
2865 // If one of the operands is a uniform constant then the cost for each
2866 // element is Cost for insertion, extraction and division.
2867 // Insertion cost = 2, Extraction Cost = 2, Division = cost for the
2868 // operation with scalar type
2869 if ((Op1Info
.isConstant() && Op1Info
.isUniform()) ||
2870 (Op2Info
.isConstant() && Op2Info
.isUniform())) {
2871 if (auto *VTy
= dyn_cast
<FixedVectorType
>(Ty
)) {
2872 InstructionCost DivCost
= BaseT::getArithmeticInstrCost(
2873 Opcode
, Ty
->getScalarType(), CostKind
, Op1Info
, Op2Info
);
2874 return (4 + DivCost
) * VTy
->getNumElements();
2877 // On AArch64, without SVE, vector divisions are expanded
2878 // into scalar divisions of each pair of elements.
2879 Cost
+= getArithmeticInstrCost(Instruction::ExtractElement
, Ty
,
2880 CostKind
, Op1Info
, Op2Info
);
2881 Cost
+= getArithmeticInstrCost(Instruction::InsertElement
, Ty
, CostKind
,
2885 // TODO: if one of the arguments is scalar, then it's not necessary to
2886 // double the cost of handling the vector elements.
2892 // When SVE is available, then we can lower the v2i64 operation using
2893 // the SVE mul instruction, which has a lower cost.
2894 if (LT
.second
== MVT::v2i64
&& ST
->hasSVE())
2897 // When SVE is not available, there is no MUL.2d instruction,
2898 // which means mul <2 x i64> is expensive as elements are extracted
2899 // from the vectors and the muls scalarized.
2900 // As getScalarizationOverhead is a bit too pessimistic, we
2901 // estimate the cost for a i64 vector directly here, which is:
2902 // - four 2-cost i64 extracts,
2903 // - two 2-cost i64 inserts, and
2904 // - two 1-cost muls.
2905 // So, for a v2i64 with LT.First = 1 the cost is 14, and for a v4i64 with
2906 // LT.first = 2 the cost is 28. If both operands are extensions it will not
2907 // need to scalarize so the cost can be cheaper (smull or umull).
2908 // so the cost can be cheaper (smull or umull).
2909 if (LT
.second
!= MVT::v2i64
|| isWideningInstruction(Ty
, Opcode
, Args
))
2911 return LT
.first
* 14;
2919 // These nodes are marked as 'custom' for combining purposes only.
2920 // We know that they are legal. See LowerAdd in ISelLowering.
2926 // Increase the cost for half and bfloat types if not architecturally
2928 if ((Ty
->getScalarType()->isHalfTy() && !ST
->hasFullFP16()) ||
2929 (Ty
->getScalarType()->isBFloatTy() && !ST
->hasBF16()))
2930 return 2 * LT
.first
;
2931 if (!Ty
->getScalarType()->isFP128Ty())
2936 // These nodes are marked as 'custom' just to lower them to SVE.
2937 // We know said lowering will incur no additional cost.
2938 if (!Ty
->getScalarType()->isFP128Ty())
2939 return 2 * LT
.first
;
2941 return BaseT::getArithmeticInstrCost(Opcode
, Ty
, CostKind
, Op1Info
,
2946 InstructionCost
AArch64TTIImpl::getAddressComputationCost(Type
*Ty
,
2947 ScalarEvolution
*SE
,
2949 // Address computations in vectorized code with non-consecutive addresses will
2950 // likely result in more instructions compared to scalar code where the
2951 // computation can more often be merged into the index mode. The resulting
2952 // extra micro-ops can significantly decrease throughput.
2953 unsigned NumVectorInstToHideOverhead
= NeonNonConstStrideOverhead
;
2954 int MaxMergeDistance
= 64;
2956 if (Ty
->isVectorTy() && SE
&&
2957 !BaseT::isConstantStridedAccessLessThan(SE
, Ptr
, MaxMergeDistance
+ 1))
2958 return NumVectorInstToHideOverhead
;
2960 // In many cases the address computation is not merged into the instruction
2965 InstructionCost
AArch64TTIImpl::getCmpSelInstrCost(unsigned Opcode
, Type
*ValTy
,
2967 CmpInst::Predicate VecPred
,
2968 TTI::TargetCostKind CostKind
,
2969 const Instruction
*I
) {
2970 // TODO: Handle other cost kinds.
2971 if (CostKind
!= TTI::TCK_RecipThroughput
)
2972 return BaseT::getCmpSelInstrCost(Opcode
, ValTy
, CondTy
, VecPred
, CostKind
,
2975 int ISD
= TLI
->InstructionOpcodeToISD(Opcode
);
2976 // We don't lower some vector selects well that are wider than the register
2978 if (isa
<FixedVectorType
>(ValTy
) && ISD
== ISD::SELECT
) {
2979 // We would need this many instructions to hide the scalarization happening.
2980 const int AmortizationCost
= 20;
2982 // If VecPred is not set, check if we can get a predicate from the context
2983 // instruction, if its type matches the requested ValTy.
2984 if (VecPred
== CmpInst::BAD_ICMP_PREDICATE
&& I
&& I
->getType() == ValTy
) {
2985 CmpInst::Predicate CurrentPred
;
2986 if (match(I
, m_Select(m_Cmp(CurrentPred
, m_Value(), m_Value()), m_Value(),
2988 VecPred
= CurrentPred
;
2990 // Check if we have a compare/select chain that can be lowered using
2991 // a (F)CMxx & BFI pair.
2992 if (CmpInst::isIntPredicate(VecPred
) || VecPred
== CmpInst::FCMP_OLE
||
2993 VecPred
== CmpInst::FCMP_OLT
|| VecPred
== CmpInst::FCMP_OGT
||
2994 VecPred
== CmpInst::FCMP_OGE
|| VecPred
== CmpInst::FCMP_OEQ
||
2995 VecPred
== CmpInst::FCMP_UNE
) {
2996 static const auto ValidMinMaxTys
= {
2997 MVT::v8i8
, MVT::v16i8
, MVT::v4i16
, MVT::v8i16
, MVT::v2i32
,
2998 MVT::v4i32
, MVT::v2i64
, MVT::v2f32
, MVT::v4f32
, MVT::v2f64
};
2999 static const auto ValidFP16MinMaxTys
= {MVT::v4f16
, MVT::v8f16
};
3001 auto LT
= getTypeLegalizationCost(ValTy
);
3002 if (any_of(ValidMinMaxTys
, [<
](MVT M
) { return M
== LT
.second
; }) ||
3003 (ST
->hasFullFP16() &&
3004 any_of(ValidFP16MinMaxTys
, [<
](MVT M
) { return M
== LT
.second
; })))
3008 static const TypeConversionCostTblEntry
3009 VectorSelectTbl
[] = {
3010 { ISD::SELECT
, MVT::v2i1
, MVT::v2f32
, 2 },
3011 { ISD::SELECT
, MVT::v2i1
, MVT::v2f64
, 2 },
3012 { ISD::SELECT
, MVT::v4i1
, MVT::v4f32
, 2 },
3013 { ISD::SELECT
, MVT::v4i1
, MVT::v4f16
, 2 },
3014 { ISD::SELECT
, MVT::v8i1
, MVT::v8f16
, 2 },
3015 { ISD::SELECT
, MVT::v16i1
, MVT::v16i16
, 16 },
3016 { ISD::SELECT
, MVT::v8i1
, MVT::v8i32
, 8 },
3017 { ISD::SELECT
, MVT::v16i1
, MVT::v16i32
, 16 },
3018 { ISD::SELECT
, MVT::v4i1
, MVT::v4i64
, 4 * AmortizationCost
},
3019 { ISD::SELECT
, MVT::v8i1
, MVT::v8i64
, 8 * AmortizationCost
},
3020 { ISD::SELECT
, MVT::v16i1
, MVT::v16i64
, 16 * AmortizationCost
}
3023 EVT SelCondTy
= TLI
->getValueType(DL
, CondTy
);
3024 EVT SelValTy
= TLI
->getValueType(DL
, ValTy
);
3025 if (SelCondTy
.isSimple() && SelValTy
.isSimple()) {
3026 if (const auto *Entry
= ConvertCostTableLookup(VectorSelectTbl
, ISD
,
3027 SelCondTy
.getSimpleVT(),
3028 SelValTy
.getSimpleVT()))
3033 if (isa
<FixedVectorType
>(ValTy
) && ISD
== ISD::SETCC
) {
3034 auto LT
= getTypeLegalizationCost(ValTy
);
3035 // Cost v4f16 FCmp without FP16 support via converting to v4f32 and back.
3036 if (LT
.second
== MVT::v4f16
&& !ST
->hasFullFP16())
3037 return LT
.first
* 4; // fcvtl + fcvtl + fcmp + xtn
3040 // Treat the icmp in icmp(and, 0) as free, as we can make use of ands.
3041 // FIXME: This can apply to more conditions and add/sub if it can be shown to
3043 if (ValTy
->isIntegerTy() && ISD
== ISD::SETCC
&& I
&&
3044 ICmpInst::isEquality(VecPred
) &&
3045 TLI
->isTypeLegal(TLI
->getValueType(DL
, ValTy
)) &&
3046 match(I
->getOperand(1), m_Zero()) &&
3047 match(I
->getOperand(0), m_And(m_Value(), m_Value())))
3050 // The base case handles scalable vectors fine for now, since it treats the
3051 // cost as 1 * legalization cost.
3052 return BaseT::getCmpSelInstrCost(Opcode
, ValTy
, CondTy
, VecPred
, CostKind
, I
);
3055 AArch64TTIImpl::TTI::MemCmpExpansionOptions
3056 AArch64TTIImpl::enableMemCmpExpansion(bool OptSize
, bool IsZeroCmp
) const {
3057 TTI::MemCmpExpansionOptions Options
;
3058 if (ST
->requiresStrictAlign()) {
3059 // TODO: Add cost modeling for strict align. Misaligned loads expand to
3060 // a bunch of instructions when strict align is enabled.
3063 Options
.AllowOverlappingLoads
= true;
3064 Options
.MaxNumLoads
= TLI
->getMaxExpandSizeMemcmp(OptSize
);
3065 Options
.NumLoadsPerBlock
= Options
.MaxNumLoads
;
3066 // TODO: Though vector loads usually perform well on AArch64, in some targets
3067 // they may wake up the FP unit, which raises the power consumption. Perhaps
3068 // they could be used with no holds barred (-O3).
3069 Options
.LoadSizes
= {8, 4, 2, 1};
3070 Options
.AllowedTailExpansions
= {3, 5, 6};
3074 bool AArch64TTIImpl::prefersVectorizedAddressing() const {
3075 return ST
->hasSVE();
3079 AArch64TTIImpl::getMaskedMemoryOpCost(unsigned Opcode
, Type
*Src
,
3080 Align Alignment
, unsigned AddressSpace
,
3081 TTI::TargetCostKind CostKind
) {
3082 if (useNeonVector(Src
))
3083 return BaseT::getMaskedMemoryOpCost(Opcode
, Src
, Alignment
, AddressSpace
,
3085 auto LT
= getTypeLegalizationCost(Src
);
3086 if (!LT
.first
.isValid())
3087 return InstructionCost::getInvalid();
3089 // The code-generator is currently not able to handle scalable vectors
3090 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
3091 // it. This change will be removed when code-generation for these types is
3092 // sufficiently reliable.
3093 if (cast
<VectorType
>(Src
)->getElementCount() == ElementCount::getScalable(1))
3094 return InstructionCost::getInvalid();
3099 static unsigned getSVEGatherScatterOverhead(unsigned Opcode
) {
3100 return Opcode
== Instruction::Load
? SVEGatherOverhead
: SVEScatterOverhead
;
3103 InstructionCost
AArch64TTIImpl::getGatherScatterOpCost(
3104 unsigned Opcode
, Type
*DataTy
, const Value
*Ptr
, bool VariableMask
,
3105 Align Alignment
, TTI::TargetCostKind CostKind
, const Instruction
*I
) {
3106 if (useNeonVector(DataTy
) || !isLegalMaskedGatherScatter(DataTy
))
3107 return BaseT::getGatherScatterOpCost(Opcode
, DataTy
, Ptr
, VariableMask
,
3108 Alignment
, CostKind
, I
);
3109 auto *VT
= cast
<VectorType
>(DataTy
);
3110 auto LT
= getTypeLegalizationCost(DataTy
);
3111 if (!LT
.first
.isValid())
3112 return InstructionCost::getInvalid();
3114 if (!LT
.second
.isVector() ||
3115 !isElementTypeLegalForScalableVector(VT
->getElementType()))
3116 return InstructionCost::getInvalid();
3118 // The code-generator is currently not able to handle scalable vectors
3119 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
3120 // it. This change will be removed when code-generation for these types is
3121 // sufficiently reliable.
3122 if (cast
<VectorType
>(DataTy
)->getElementCount() ==
3123 ElementCount::getScalable(1))
3124 return InstructionCost::getInvalid();
3126 ElementCount LegalVF
= LT
.second
.getVectorElementCount();
3127 InstructionCost MemOpCost
=
3128 getMemoryOpCost(Opcode
, VT
->getElementType(), Alignment
, 0, CostKind
,
3129 {TTI::OK_AnyValue
, TTI::OP_None
}, I
);
3130 // Add on an overhead cost for using gathers/scatters.
3131 // TODO: At the moment this is applied unilaterally for all CPUs, but at some
3132 // point we may want a per-CPU overhead.
3133 MemOpCost
*= getSVEGatherScatterOverhead(Opcode
);
3134 return LT
.first
* MemOpCost
* getMaxNumElements(LegalVF
);
3137 bool AArch64TTIImpl::useNeonVector(const Type
*Ty
) const {
3138 return isa
<FixedVectorType
>(Ty
) && !ST
->useSVEForFixedLengthVectors();
3141 InstructionCost
AArch64TTIImpl::getMemoryOpCost(unsigned Opcode
, Type
*Ty
,
3142 MaybeAlign Alignment
,
3143 unsigned AddressSpace
,
3144 TTI::TargetCostKind CostKind
,
3145 TTI::OperandValueInfo OpInfo
,
3146 const Instruction
*I
) {
3147 EVT VT
= TLI
->getValueType(DL
, Ty
, true);
3148 // Type legalization can't handle structs
3149 if (VT
== MVT::Other
)
3150 return BaseT::getMemoryOpCost(Opcode
, Ty
, Alignment
, AddressSpace
,
3153 auto LT
= getTypeLegalizationCost(Ty
);
3154 if (!LT
.first
.isValid())
3155 return InstructionCost::getInvalid();
3157 // The code-generator is currently not able to handle scalable vectors
3158 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
3159 // it. This change will be removed when code-generation for these types is
3160 // sufficiently reliable.
3161 if (auto *VTy
= dyn_cast
<ScalableVectorType
>(Ty
))
3162 if (VTy
->getElementCount() == ElementCount::getScalable(1))
3163 return InstructionCost::getInvalid();
3165 // TODO: consider latency as well for TCK_SizeAndLatency.
3166 if (CostKind
== TTI::TCK_CodeSize
|| CostKind
== TTI::TCK_SizeAndLatency
)
3169 if (CostKind
!= TTI::TCK_RecipThroughput
)
3172 if (ST
->isMisaligned128StoreSlow() && Opcode
== Instruction::Store
&&
3173 LT
.second
.is128BitVector() && (!Alignment
|| *Alignment
< Align(16))) {
3174 // Unaligned stores are extremely inefficient. We don't split all
3175 // unaligned 128-bit stores because the negative impact that has shown in
3176 // practice on inlined block copy code.
3177 // We make such stores expensive so that we will only vectorize if there
3178 // are 6 other instructions getting vectorized.
3179 const int AmortizationCost
= 6;
3181 return LT
.first
* 2 * AmortizationCost
;
3184 // Opaque ptr or ptr vector types are i64s and can be lowered to STP/LDPs.
3185 if (Ty
->isPtrOrPtrVectorTy())
3188 if (useNeonVector(Ty
)) {
3189 // Check truncating stores and extending loads.
3190 if (Ty
->getScalarSizeInBits() != LT
.second
.getScalarSizeInBits()) {
3191 // v4i8 types are lowered to scalar a load/store and sshll/xtn.
3192 if (VT
== MVT::v4i8
)
3194 // Otherwise we need to scalarize.
3195 return cast
<FixedVectorType
>(Ty
)->getNumElements() * 2;
3197 EVT EltVT
= VT
.getVectorElementType();
3198 unsigned EltSize
= EltVT
.getScalarSizeInBits();
3199 if (!isPowerOf2_32(EltSize
) || EltSize
< 8 || EltSize
> 64 ||
3200 VT
.getVectorNumElements() >= (128 / EltSize
) || !Alignment
||
3201 *Alignment
!= Align(1))
3203 // FIXME: v3i8 lowering currently is very inefficient, due to automatic
3204 // widening to v4i8, which produces suboptimal results.
3205 if (VT
.getVectorNumElements() == 3 && EltVT
== MVT::i8
)
3208 // Check non-power-of-2 loads/stores for legal vector element types with
3209 // NEON. Non-power-of-2 memory ops will get broken down to a set of
3210 // operations on smaller power-of-2 ops, including ld1/st1.
3211 LLVMContext
&C
= Ty
->getContext();
3212 InstructionCost
Cost(0);
3213 SmallVector
<EVT
> TypeWorklist
;
3214 TypeWorklist
.push_back(VT
);
3215 while (!TypeWorklist
.empty()) {
3216 EVT CurrVT
= TypeWorklist
.pop_back_val();
3217 unsigned CurrNumElements
= CurrVT
.getVectorNumElements();
3218 if (isPowerOf2_32(CurrNumElements
)) {
3223 unsigned PrevPow2
= NextPowerOf2(CurrNumElements
) / 2;
3224 TypeWorklist
.push_back(EVT::getVectorVT(C
, EltVT
, PrevPow2
));
3225 TypeWorklist
.push_back(
3226 EVT::getVectorVT(C
, EltVT
, CurrNumElements
- PrevPow2
));
3234 InstructionCost
AArch64TTIImpl::getInterleavedMemoryOpCost(
3235 unsigned Opcode
, Type
*VecTy
, unsigned Factor
, ArrayRef
<unsigned> Indices
,
3236 Align Alignment
, unsigned AddressSpace
, TTI::TargetCostKind CostKind
,
3237 bool UseMaskForCond
, bool UseMaskForGaps
) {
3238 assert(Factor
>= 2 && "Invalid interleave factor");
3239 auto *VecVTy
= cast
<VectorType
>(VecTy
);
3241 if (VecTy
->isScalableTy() && (!ST
->hasSVE() || Factor
!= 2))
3242 return InstructionCost::getInvalid();
3244 // Vectorization for masked interleaved accesses is only enabled for scalable
3246 if (!VecTy
->isScalableTy() && (UseMaskForCond
|| UseMaskForGaps
))
3247 return InstructionCost::getInvalid();
3249 if (!UseMaskForGaps
&& Factor
<= TLI
->getMaxSupportedInterleaveFactor()) {
3250 unsigned MinElts
= VecVTy
->getElementCount().getKnownMinValue();
3252 VectorType::get(VecVTy
->getElementType(),
3253 VecVTy
->getElementCount().divideCoefficientBy(Factor
));
3255 // ldN/stN only support legal vector types of size 64 or 128 in bits.
3256 // Accesses having vector types that are a multiple of 128 bits can be
3257 // matched to more than one ldN/stN instruction.
3259 if (MinElts
% Factor
== 0 &&
3260 TLI
->isLegalInterleavedAccessType(SubVecTy
, DL
, UseScalable
))
3261 return Factor
* TLI
->getNumInterleavedAccesses(SubVecTy
, DL
, UseScalable
);
3264 return BaseT::getInterleavedMemoryOpCost(Opcode
, VecTy
, Factor
, Indices
,
3265 Alignment
, AddressSpace
, CostKind
,
3266 UseMaskForCond
, UseMaskForGaps
);
3270 AArch64TTIImpl::getCostOfKeepingLiveOverCall(ArrayRef
<Type
*> Tys
) {
3271 InstructionCost Cost
= 0;
3272 TTI::TargetCostKind CostKind
= TTI::TCK_RecipThroughput
;
3273 for (auto *I
: Tys
) {
3274 if (!I
->isVectorTy())
3276 if (I
->getScalarSizeInBits() * cast
<FixedVectorType
>(I
)->getNumElements() ==
3278 Cost
+= getMemoryOpCost(Instruction::Store
, I
, Align(128), 0, CostKind
) +
3279 getMemoryOpCost(Instruction::Load
, I
, Align(128), 0, CostKind
);
3284 unsigned AArch64TTIImpl::getMaxInterleaveFactor(ElementCount VF
) {
3285 return ST
->getMaxInterleaveFactor();
3288 // For Falkor, we want to avoid having too many strided loads in a loop since
3289 // that can exhaust the HW prefetcher resources. We adjust the unroller
3290 // MaxCount preference below to attempt to ensure unrolling doesn't create too
3291 // many strided loads.
3293 getFalkorUnrollingPreferences(Loop
*L
, ScalarEvolution
&SE
,
3294 TargetTransformInfo::UnrollingPreferences
&UP
) {
3295 enum { MaxStridedLoads
= 7 };
3296 auto countStridedLoads
= [](Loop
*L
, ScalarEvolution
&SE
) {
3297 int StridedLoads
= 0;
3298 // FIXME? We could make this more precise by looking at the CFG and
3299 // e.g. not counting loads in each side of an if-then-else diamond.
3300 for (const auto BB
: L
->blocks()) {
3301 for (auto &I
: *BB
) {
3302 LoadInst
*LMemI
= dyn_cast
<LoadInst
>(&I
);
3306 Value
*PtrValue
= LMemI
->getPointerOperand();
3307 if (L
->isLoopInvariant(PtrValue
))
3310 const SCEV
*LSCEV
= SE
.getSCEV(PtrValue
);
3311 const SCEVAddRecExpr
*LSCEVAddRec
= dyn_cast
<SCEVAddRecExpr
>(LSCEV
);
3312 if (!LSCEVAddRec
|| !LSCEVAddRec
->isAffine())
3315 // FIXME? We could take pairing of unrolled load copies into account
3316 // by looking at the AddRec, but we would probably have to limit this
3317 // to loops with no stores or other memory optimization barriers.
3319 // We've seen enough strided loads that seeing more won't make a
3321 if (StridedLoads
> MaxStridedLoads
/ 2)
3322 return StridedLoads
;
3325 return StridedLoads
;
3328 int StridedLoads
= countStridedLoads(L
, SE
);
3329 LLVM_DEBUG(dbgs() << "falkor-hwpf: detected " << StridedLoads
3330 << " strided loads\n");
3331 // Pick the largest power of 2 unroll count that won't result in too many
3334 UP
.MaxCount
= 1 << Log2_32(MaxStridedLoads
/ StridedLoads
);
3335 LLVM_DEBUG(dbgs() << "falkor-hwpf: setting unroll MaxCount to "
3336 << UP
.MaxCount
<< '\n');
3340 void AArch64TTIImpl::getUnrollingPreferences(Loop
*L
, ScalarEvolution
&SE
,
3341 TTI::UnrollingPreferences
&UP
,
3342 OptimizationRemarkEmitter
*ORE
) {
3343 // Enable partial unrolling and runtime unrolling.
3344 BaseT::getUnrollingPreferences(L
, SE
, UP
, ORE
);
3346 UP
.UpperBound
= true;
3348 // For inner loop, it is more likely to be a hot one, and the runtime check
3349 // can be promoted out from LICM pass, so the overhead is less, let's try
3350 // a larger threshold to unroll more loops.
3351 if (L
->getLoopDepth() > 1)
3352 UP
.PartialThreshold
*= 2;
3354 // Disable partial & runtime unrolling on -Os.
3355 UP
.PartialOptSizeThreshold
= 0;
3357 if (ST
->getProcFamily() == AArch64Subtarget::Falkor
&&
3358 EnableFalkorHWPFUnrollFix
)
3359 getFalkorUnrollingPreferences(L
, SE
, UP
);
3361 // Scan the loop: don't unroll loops with calls as this could prevent
3362 // inlining. Don't unroll vector loops either, as they don't benefit much from
3364 for (auto *BB
: L
->getBlocks()) {
3365 for (auto &I
: *BB
) {
3366 // Don't unroll vectorised loop.
3367 if (I
.getType()->isVectorTy())
3370 if (isa
<CallInst
>(I
) || isa
<InvokeInst
>(I
)) {
3371 if (const Function
*F
= cast
<CallBase
>(I
).getCalledFunction()) {
3372 if (!isLoweredToCall(F
))
3380 // Enable runtime unrolling for in-order models
3381 // If mcpu is omitted, getProcFamily() returns AArch64Subtarget::Others, so by
3382 // checking for that case, we can ensure that the default behaviour is
3384 if (ST
->getProcFamily() != AArch64Subtarget::Others
&&
3385 !ST
->getSchedModel().isOutOfOrder()) {
3388 UP
.UnrollRemainder
= true;
3389 UP
.DefaultUnrollRuntimeCount
= 4;
3391 UP
.UnrollAndJam
= true;
3392 UP
.UnrollAndJamInnerLoopThreshold
= 60;
3396 void AArch64TTIImpl::getPeelingPreferences(Loop
*L
, ScalarEvolution
&SE
,
3397 TTI::PeelingPreferences
&PP
) {
3398 BaseT::getPeelingPreferences(L
, SE
, PP
);
3401 Value
*AArch64TTIImpl::getOrCreateResultFromMemIntrinsic(IntrinsicInst
*Inst
,
3402 Type
*ExpectedType
) {
3403 switch (Inst
->getIntrinsicID()) {
3406 case Intrinsic::aarch64_neon_st2
:
3407 case Intrinsic::aarch64_neon_st3
:
3408 case Intrinsic::aarch64_neon_st4
: {
3409 // Create a struct type
3410 StructType
*ST
= dyn_cast
<StructType
>(ExpectedType
);
3413 unsigned NumElts
= Inst
->arg_size() - 1;
3414 if (ST
->getNumElements() != NumElts
)
3416 for (unsigned i
= 0, e
= NumElts
; i
!= e
; ++i
) {
3417 if (Inst
->getArgOperand(i
)->getType() != ST
->getElementType(i
))
3420 Value
*Res
= PoisonValue::get(ExpectedType
);
3421 IRBuilder
<> Builder(Inst
);
3422 for (unsigned i
= 0, e
= NumElts
; i
!= e
; ++i
) {
3423 Value
*L
= Inst
->getArgOperand(i
);
3424 Res
= Builder
.CreateInsertValue(Res
, L
, i
);
3428 case Intrinsic::aarch64_neon_ld2
:
3429 case Intrinsic::aarch64_neon_ld3
:
3430 case Intrinsic::aarch64_neon_ld4
:
3431 if (Inst
->getType() == ExpectedType
)
3437 bool AArch64TTIImpl::getTgtMemIntrinsic(IntrinsicInst
*Inst
,
3438 MemIntrinsicInfo
&Info
) {
3439 switch (Inst
->getIntrinsicID()) {
3442 case Intrinsic::aarch64_neon_ld2
:
3443 case Intrinsic::aarch64_neon_ld3
:
3444 case Intrinsic::aarch64_neon_ld4
:
3445 Info
.ReadMem
= true;
3446 Info
.WriteMem
= false;
3447 Info
.PtrVal
= Inst
->getArgOperand(0);
3449 case Intrinsic::aarch64_neon_st2
:
3450 case Intrinsic::aarch64_neon_st3
:
3451 case Intrinsic::aarch64_neon_st4
:
3452 Info
.ReadMem
= false;
3453 Info
.WriteMem
= true;
3454 Info
.PtrVal
= Inst
->getArgOperand(Inst
->arg_size() - 1);
3458 switch (Inst
->getIntrinsicID()) {
3461 case Intrinsic::aarch64_neon_ld2
:
3462 case Intrinsic::aarch64_neon_st2
:
3463 Info
.MatchingId
= VECTOR_LDST_TWO_ELEMENTS
;
3465 case Intrinsic::aarch64_neon_ld3
:
3466 case Intrinsic::aarch64_neon_st3
:
3467 Info
.MatchingId
= VECTOR_LDST_THREE_ELEMENTS
;
3469 case Intrinsic::aarch64_neon_ld4
:
3470 case Intrinsic::aarch64_neon_st4
:
3471 Info
.MatchingId
= VECTOR_LDST_FOUR_ELEMENTS
;
3477 /// See if \p I should be considered for address type promotion. We check if \p
3478 /// I is a sext with right type and used in memory accesses. If it used in a
3479 /// "complex" getelementptr, we allow it to be promoted without finding other
3480 /// sext instructions that sign extended the same initial value. A getelementptr
3481 /// is considered as "complex" if it has more than 2 operands.
3482 bool AArch64TTIImpl::shouldConsiderAddressTypePromotion(
3483 const Instruction
&I
, bool &AllowPromotionWithoutCommonHeader
) {
3484 bool Considerable
= false;
3485 AllowPromotionWithoutCommonHeader
= false;
3486 if (!isa
<SExtInst
>(&I
))
3488 Type
*ConsideredSExtType
=
3489 Type::getInt64Ty(I
.getParent()->getParent()->getContext());
3490 if (I
.getType() != ConsideredSExtType
)
3492 // See if the sext is the one with the right type and used in at least one
3493 // GetElementPtrInst.
3494 for (const User
*U
: I
.users()) {
3495 if (const GetElementPtrInst
*GEPInst
= dyn_cast
<GetElementPtrInst
>(U
)) {
3496 Considerable
= true;
3497 // A getelementptr is considered as "complex" if it has more than 2
3498 // operands. We will promote a SExt used in such complex GEP as we
3499 // expect some computation to be merged if they are done on 64 bits.
3500 if (GEPInst
->getNumOperands() > 2) {
3501 AllowPromotionWithoutCommonHeader
= true;
3506 return Considerable
;
3509 bool AArch64TTIImpl::isLegalToVectorizeReduction(
3510 const RecurrenceDescriptor
&RdxDesc
, ElementCount VF
) const {
3511 if (!VF
.isScalable())
3514 Type
*Ty
= RdxDesc
.getRecurrenceType();
3515 if (Ty
->isBFloatTy() || !isElementTypeLegalForScalableVector(Ty
))
3518 switch (RdxDesc
.getRecurrenceKind()) {
3519 case RecurKind::Add
:
3520 case RecurKind::FAdd
:
3521 case RecurKind::And
:
3523 case RecurKind::Xor
:
3524 case RecurKind::SMin
:
3525 case RecurKind::SMax
:
3526 case RecurKind::UMin
:
3527 case RecurKind::UMax
:
3528 case RecurKind::FMin
:
3529 case RecurKind::FMax
:
3530 case RecurKind::FMulAdd
:
3531 case RecurKind::IAnyOf
:
3532 case RecurKind::FAnyOf
:
3540 AArch64TTIImpl::getMinMaxReductionCost(Intrinsic::ID IID
, VectorType
*Ty
,
3542 TTI::TargetCostKind CostKind
) {
3543 std::pair
<InstructionCost
, MVT
> LT
= getTypeLegalizationCost(Ty
);
3545 if (LT
.second
.getScalarType() == MVT::f16
&& !ST
->hasFullFP16())
3546 return BaseT::getMinMaxReductionCost(IID
, Ty
, FMF
, CostKind
);
3548 InstructionCost LegalizationCost
= 0;
3550 Type
*LegalVTy
= EVT(LT
.second
).getTypeForEVT(Ty
->getContext());
3551 IntrinsicCostAttributes
Attrs(IID
, LegalVTy
, {LegalVTy
, LegalVTy
}, FMF
);
3552 LegalizationCost
= getIntrinsicInstrCost(Attrs
, CostKind
) * (LT
.first
- 1);
3555 return LegalizationCost
+ /*Cost of horizontal reduction*/ 2;
3558 InstructionCost
AArch64TTIImpl::getArithmeticReductionCostSVE(
3559 unsigned Opcode
, VectorType
*ValTy
, TTI::TargetCostKind CostKind
) {
3560 std::pair
<InstructionCost
, MVT
> LT
= getTypeLegalizationCost(ValTy
);
3561 InstructionCost LegalizationCost
= 0;
3563 Type
*LegalVTy
= EVT(LT
.second
).getTypeForEVT(ValTy
->getContext());
3564 LegalizationCost
= getArithmeticInstrCost(Opcode
, LegalVTy
, CostKind
);
3565 LegalizationCost
*= LT
.first
- 1;
3568 int ISD
= TLI
->InstructionOpcodeToISD(Opcode
);
3569 assert(ISD
&& "Invalid opcode");
3570 // Add the final reduction cost for the legal horizontal reduction
3577 return LegalizationCost
+ 2;
3579 return InstructionCost::getInvalid();
3584 AArch64TTIImpl::getArithmeticReductionCost(unsigned Opcode
, VectorType
*ValTy
,
3585 std::optional
<FastMathFlags
> FMF
,
3586 TTI::TargetCostKind CostKind
) {
3587 if (TTI::requiresOrderedReduction(FMF
)) {
3588 if (auto *FixedVTy
= dyn_cast
<FixedVectorType
>(ValTy
)) {
3589 InstructionCost BaseCost
=
3590 BaseT::getArithmeticReductionCost(Opcode
, ValTy
, FMF
, CostKind
);
3591 // Add on extra cost to reflect the extra overhead on some CPUs. We still
3592 // end up vectorizing for more computationally intensive loops.
3593 return BaseCost
+ FixedVTy
->getNumElements();
3596 if (Opcode
!= Instruction::FAdd
)
3597 return InstructionCost::getInvalid();
3599 auto *VTy
= cast
<ScalableVectorType
>(ValTy
);
3600 InstructionCost Cost
=
3601 getArithmeticInstrCost(Opcode
, VTy
->getScalarType(), CostKind
);
3602 Cost
*= getMaxNumElements(VTy
->getElementCount());
3606 if (isa
<ScalableVectorType
>(ValTy
))
3607 return getArithmeticReductionCostSVE(Opcode
, ValTy
, CostKind
);
3609 std::pair
<InstructionCost
, MVT
> LT
= getTypeLegalizationCost(ValTy
);
3610 MVT MTy
= LT
.second
;
3611 int ISD
= TLI
->InstructionOpcodeToISD(Opcode
);
3612 assert(ISD
&& "Invalid opcode");
3614 // Horizontal adds can use the 'addv' instruction. We model the cost of these
3615 // instructions as twice a normal vector add, plus 1 for each legalization
3616 // step (LT.first). This is the only arithmetic vector reduction operation for
3617 // which we have an instruction.
3618 // OR, XOR and AND costs should match the codegen from:
3619 // OR: llvm/test/CodeGen/AArch64/reduce-or.ll
3620 // XOR: llvm/test/CodeGen/AArch64/reduce-xor.ll
3621 // AND: llvm/test/CodeGen/AArch64/reduce-and.ll
3622 static const CostTblEntry CostTblNoPairwise
[]{
3623 {ISD::ADD
, MVT::v8i8
, 2},
3624 {ISD::ADD
, MVT::v16i8
, 2},
3625 {ISD::ADD
, MVT::v4i16
, 2},
3626 {ISD::ADD
, MVT::v8i16
, 2},
3627 {ISD::ADD
, MVT::v4i32
, 2},
3628 {ISD::ADD
, MVT::v2i64
, 2},
3629 {ISD::OR
, MVT::v8i8
, 15},
3630 {ISD::OR
, MVT::v16i8
, 17},
3631 {ISD::OR
, MVT::v4i16
, 7},
3632 {ISD::OR
, MVT::v8i16
, 9},
3633 {ISD::OR
, MVT::v2i32
, 3},
3634 {ISD::OR
, MVT::v4i32
, 5},
3635 {ISD::OR
, MVT::v2i64
, 3},
3636 {ISD::XOR
, MVT::v8i8
, 15},
3637 {ISD::XOR
, MVT::v16i8
, 17},
3638 {ISD::XOR
, MVT::v4i16
, 7},
3639 {ISD::XOR
, MVT::v8i16
, 9},
3640 {ISD::XOR
, MVT::v2i32
, 3},
3641 {ISD::XOR
, MVT::v4i32
, 5},
3642 {ISD::XOR
, MVT::v2i64
, 3},
3643 {ISD::AND
, MVT::v8i8
, 15},
3644 {ISD::AND
, MVT::v16i8
, 17},
3645 {ISD::AND
, MVT::v4i16
, 7},
3646 {ISD::AND
, MVT::v8i16
, 9},
3647 {ISD::AND
, MVT::v2i32
, 3},
3648 {ISD::AND
, MVT::v4i32
, 5},
3649 {ISD::AND
, MVT::v2i64
, 3},
3655 if (const auto *Entry
= CostTableLookup(CostTblNoPairwise
, ISD
, MTy
))
3656 return (LT
.first
- 1) + Entry
->Cost
;
3661 const auto *Entry
= CostTableLookup(CostTblNoPairwise
, ISD
, MTy
);
3664 auto *ValVTy
= cast
<FixedVectorType
>(ValTy
);
3665 if (MTy
.getVectorNumElements() <= ValVTy
->getNumElements() &&
3666 isPowerOf2_32(ValVTy
->getNumElements())) {
3667 InstructionCost ExtraCost
= 0;
3668 if (LT
.first
!= 1) {
3669 // Type needs to be split, so there is an extra cost of LT.first - 1
3671 auto *Ty
= FixedVectorType::get(ValTy
->getElementType(),
3672 MTy
.getVectorNumElements());
3673 ExtraCost
= getArithmeticInstrCost(Opcode
, Ty
, CostKind
);
3674 ExtraCost
*= LT
.first
- 1;
3676 // All and/or/xor of i1 will be lowered with maxv/minv/addv + fmov
3677 auto Cost
= ValVTy
->getElementType()->isIntegerTy(1) ? 2 : Entry
->Cost
;
3678 return Cost
+ ExtraCost
;
3682 return BaseT::getArithmeticReductionCost(Opcode
, ValTy
, FMF
, CostKind
);
3685 InstructionCost
AArch64TTIImpl::getSpliceCost(VectorType
*Tp
, int Index
) {
3686 static const CostTblEntry ShuffleTbl
[] = {
3687 { TTI::SK_Splice
, MVT::nxv16i8
, 1 },
3688 { TTI::SK_Splice
, MVT::nxv8i16
, 1 },
3689 { TTI::SK_Splice
, MVT::nxv4i32
, 1 },
3690 { TTI::SK_Splice
, MVT::nxv2i64
, 1 },
3691 { TTI::SK_Splice
, MVT::nxv2f16
, 1 },
3692 { TTI::SK_Splice
, MVT::nxv4f16
, 1 },
3693 { TTI::SK_Splice
, MVT::nxv8f16
, 1 },
3694 { TTI::SK_Splice
, MVT::nxv2bf16
, 1 },
3695 { TTI::SK_Splice
, MVT::nxv4bf16
, 1 },
3696 { TTI::SK_Splice
, MVT::nxv8bf16
, 1 },
3697 { TTI::SK_Splice
, MVT::nxv2f32
, 1 },
3698 { TTI::SK_Splice
, MVT::nxv4f32
, 1 },
3699 { TTI::SK_Splice
, MVT::nxv2f64
, 1 },
3702 // The code-generator is currently not able to handle scalable vectors
3703 // of <vscale x 1 x eltty> yet, so return an invalid cost to avoid selecting
3704 // it. This change will be removed when code-generation for these types is
3705 // sufficiently reliable.
3706 if (Tp
->getElementCount() == ElementCount::getScalable(1))
3707 return InstructionCost::getInvalid();
3709 std::pair
<InstructionCost
, MVT
> LT
= getTypeLegalizationCost(Tp
);
3710 Type
*LegalVTy
= EVT(LT
.second
).getTypeForEVT(Tp
->getContext());
3711 TTI::TargetCostKind CostKind
= TTI::TCK_RecipThroughput
;
3712 EVT PromotedVT
= LT
.second
.getScalarType() == MVT::i1
3713 ? TLI
->getPromotedVTForPredicate(EVT(LT
.second
))
3715 Type
*PromotedVTy
= EVT(PromotedVT
).getTypeForEVT(Tp
->getContext());
3716 InstructionCost LegalizationCost
= 0;
3719 getCmpSelInstrCost(Instruction::ICmp
, PromotedVTy
, PromotedVTy
,
3720 CmpInst::BAD_ICMP_PREDICATE
, CostKind
) +
3721 getCmpSelInstrCost(Instruction::Select
, PromotedVTy
, LegalVTy
,
3722 CmpInst::BAD_ICMP_PREDICATE
, CostKind
);
3725 // Predicated splice are promoted when lowering. See AArch64ISelLowering.cpp
3726 // Cost performed on a promoted type.
3727 if (LT
.second
.getScalarType() == MVT::i1
) {
3729 getCastInstrCost(Instruction::ZExt
, PromotedVTy
, LegalVTy
,
3730 TTI::CastContextHint::None
, CostKind
) +
3731 getCastInstrCost(Instruction::Trunc
, LegalVTy
, PromotedVTy
,
3732 TTI::CastContextHint::None
, CostKind
);
3735 CostTableLookup(ShuffleTbl
, TTI::SK_Splice
, PromotedVT
.getSimpleVT());
3736 assert(Entry
&& "Illegal Type for Splice");
3737 LegalizationCost
+= Entry
->Cost
;
3738 return LegalizationCost
* LT
.first
;
3741 InstructionCost
AArch64TTIImpl::getShuffleCost(TTI::ShuffleKind Kind
,
3744 TTI::TargetCostKind CostKind
,
3745 int Index
, VectorType
*SubTp
,
3746 ArrayRef
<const Value
*> Args
) {
3747 std::pair
<InstructionCost
, MVT
> LT
= getTypeLegalizationCost(Tp
);
3748 // If we have a Mask, and the LT is being legalized somehow, split the Mask
3749 // into smaller vectors and sum the cost of each shuffle.
3750 if (!Mask
.empty() && isa
<FixedVectorType
>(Tp
) && LT
.second
.isVector() &&
3751 Tp
->getScalarSizeInBits() == LT
.second
.getScalarSizeInBits() &&
3752 Mask
.size() > LT
.second
.getVectorNumElements() && !Index
&& !SubTp
) {
3753 unsigned TpNumElts
= Mask
.size();
3754 unsigned LTNumElts
= LT
.second
.getVectorNumElements();
3755 unsigned NumVecs
= (TpNumElts
+ LTNumElts
- 1) / LTNumElts
;
3757 VectorType::get(Tp
->getScalarType(), LT
.second
.getVectorElementCount());
3758 InstructionCost Cost
;
3759 for (unsigned N
= 0; N
< NumVecs
; N
++) {
3760 SmallVector
<int> NMask
;
3761 // Split the existing mask into chunks of size LTNumElts. Track the source
3762 // sub-vectors to ensure the result has at most 2 inputs.
3763 unsigned Source1
, Source2
;
3764 unsigned NumSources
= 0;
3765 for (unsigned E
= 0; E
< LTNumElts
; E
++) {
3766 int MaskElt
= (N
* LTNumElts
+ E
< TpNumElts
) ? Mask
[N
* LTNumElts
+ E
]
3769 NMask
.push_back(PoisonMaskElem
);
3773 // Calculate which source from the input this comes from and whether it
3775 unsigned Source
= MaskElt
/ LTNumElts
;
3776 if (NumSources
== 0) {
3779 } else if (NumSources
== 1 && Source
!= Source1
) {
3782 } else if (NumSources
>= 2 && Source
!= Source1
&& Source
!= Source2
) {
3786 // Add to the new mask. For the NumSources>2 case these are not correct,
3787 // but are only used for the modular lane number.
3788 if (Source
== Source1
)
3789 NMask
.push_back(MaskElt
% LTNumElts
);
3790 else if (Source
== Source2
)
3791 NMask
.push_back(MaskElt
% LTNumElts
+ LTNumElts
);
3793 NMask
.push_back(MaskElt
% LTNumElts
);
3795 // If the sub-mask has at most 2 input sub-vectors then re-cost it using
3796 // getShuffleCost. If not then cost it using the worst case.
3797 if (NumSources
<= 2)
3798 Cost
+= getShuffleCost(NumSources
<= 1 ? TTI::SK_PermuteSingleSrc
3799 : TTI::SK_PermuteTwoSrc
,
3800 NTp
, NMask
, CostKind
, 0, nullptr, Args
);
3801 else if (any_of(enumerate(NMask
), [&](const auto &ME
) {
3802 return ME
.value() % LTNumElts
== ME
.index();
3804 Cost
+= LTNumElts
- 1;
3811 Kind
= improveShuffleKindFromMask(Kind
, Mask
, Tp
, Index
, SubTp
);
3813 // Check for broadcast loads, which are supported by the LD1R instruction.
3814 // In terms of code-size, the shuffle vector is free when a load + dup get
3815 // folded into a LD1R. That's what we check and return here. For performance
3816 // and reciprocal throughput, a LD1R is not completely free. In this case, we
3817 // return the cost for the broadcast below (i.e. 1 for most/all types), so
3818 // that we model the load + dup sequence slightly higher because LD1R is a
3819 // high latency instruction.
3820 if (CostKind
== TTI::TCK_CodeSize
&& Kind
== TTI::SK_Broadcast
) {
3821 bool IsLoad
= !Args
.empty() && isa
<LoadInst
>(Args
[0]);
3822 if (IsLoad
&& LT
.second
.isVector() &&
3823 isLegalBroadcastLoad(Tp
->getElementType(),
3824 LT
.second
.getVectorElementCount()))
3828 // If we have 4 elements for the shuffle and a Mask, get the cost straight
3829 // from the perfect shuffle tables.
3830 if (Mask
.size() == 4 && Tp
->getElementCount() == ElementCount::getFixed(4) &&
3831 (Tp
->getScalarSizeInBits() == 16 || Tp
->getScalarSizeInBits() == 32) &&
3832 all_of(Mask
, [](int E
) { return E
< 8; }))
3833 return getPerfectShuffleCost(Mask
);
3835 if (Kind
== TTI::SK_Broadcast
|| Kind
== TTI::SK_Transpose
||
3836 Kind
== TTI::SK_Select
|| Kind
== TTI::SK_PermuteSingleSrc
||
3837 Kind
== TTI::SK_Reverse
|| Kind
== TTI::SK_Splice
) {
3838 static const CostTblEntry ShuffleTbl
[] = {
3839 // Broadcast shuffle kinds can be performed with 'dup'.
3840 {TTI::SK_Broadcast
, MVT::v8i8
, 1},
3841 {TTI::SK_Broadcast
, MVT::v16i8
, 1},
3842 {TTI::SK_Broadcast
, MVT::v4i16
, 1},
3843 {TTI::SK_Broadcast
, MVT::v8i16
, 1},
3844 {TTI::SK_Broadcast
, MVT::v2i32
, 1},
3845 {TTI::SK_Broadcast
, MVT::v4i32
, 1},
3846 {TTI::SK_Broadcast
, MVT::v2i64
, 1},
3847 {TTI::SK_Broadcast
, MVT::v4f16
, 1},
3848 {TTI::SK_Broadcast
, MVT::v8f16
, 1},
3849 {TTI::SK_Broadcast
, MVT::v2f32
, 1},
3850 {TTI::SK_Broadcast
, MVT::v4f32
, 1},
3851 {TTI::SK_Broadcast
, MVT::v2f64
, 1},
3852 // Transpose shuffle kinds can be performed with 'trn1/trn2' and
3853 // 'zip1/zip2' instructions.
3854 {TTI::SK_Transpose
, MVT::v8i8
, 1},
3855 {TTI::SK_Transpose
, MVT::v16i8
, 1},
3856 {TTI::SK_Transpose
, MVT::v4i16
, 1},
3857 {TTI::SK_Transpose
, MVT::v8i16
, 1},
3858 {TTI::SK_Transpose
, MVT::v2i32
, 1},
3859 {TTI::SK_Transpose
, MVT::v4i32
, 1},
3860 {TTI::SK_Transpose
, MVT::v2i64
, 1},
3861 {TTI::SK_Transpose
, MVT::v4f16
, 1},
3862 {TTI::SK_Transpose
, MVT::v8f16
, 1},
3863 {TTI::SK_Transpose
, MVT::v2f32
, 1},
3864 {TTI::SK_Transpose
, MVT::v4f32
, 1},
3865 {TTI::SK_Transpose
, MVT::v2f64
, 1},
3866 // Select shuffle kinds.
3867 // TODO: handle vXi8/vXi16.
3868 {TTI::SK_Select
, MVT::v2i32
, 1}, // mov.
3869 {TTI::SK_Select
, MVT::v4i32
, 2}, // rev+trn (or similar).
3870 {TTI::SK_Select
, MVT::v2i64
, 1}, // mov.
3871 {TTI::SK_Select
, MVT::v2f32
, 1}, // mov.
3872 {TTI::SK_Select
, MVT::v4f32
, 2}, // rev+trn (or similar).
3873 {TTI::SK_Select
, MVT::v2f64
, 1}, // mov.
3874 // PermuteSingleSrc shuffle kinds.
3875 {TTI::SK_PermuteSingleSrc
, MVT::v2i32
, 1}, // mov.
3876 {TTI::SK_PermuteSingleSrc
, MVT::v4i32
, 3}, // perfectshuffle worst case.
3877 {TTI::SK_PermuteSingleSrc
, MVT::v2i64
, 1}, // mov.
3878 {TTI::SK_PermuteSingleSrc
, MVT::v2f32
, 1}, // mov.
3879 {TTI::SK_PermuteSingleSrc
, MVT::v4f32
, 3}, // perfectshuffle worst case.
3880 {TTI::SK_PermuteSingleSrc
, MVT::v2f64
, 1}, // mov.
3881 {TTI::SK_PermuteSingleSrc
, MVT::v4i16
, 3}, // perfectshuffle worst case.
3882 {TTI::SK_PermuteSingleSrc
, MVT::v4f16
, 3}, // perfectshuffle worst case.
3883 {TTI::SK_PermuteSingleSrc
, MVT::v4bf16
, 3}, // same
3884 {TTI::SK_PermuteSingleSrc
, MVT::v8i16
, 8}, // constpool + load + tbl
3885 {TTI::SK_PermuteSingleSrc
, MVT::v8f16
, 8}, // constpool + load + tbl
3886 {TTI::SK_PermuteSingleSrc
, MVT::v8bf16
, 8}, // constpool + load + tbl
3887 {TTI::SK_PermuteSingleSrc
, MVT::v8i8
, 8}, // constpool + load + tbl
3888 {TTI::SK_PermuteSingleSrc
, MVT::v16i8
, 8}, // constpool + load + tbl
3889 // Reverse can be lowered with `rev`.
3890 {TTI::SK_Reverse
, MVT::v2i32
, 1}, // REV64
3891 {TTI::SK_Reverse
, MVT::v4i32
, 2}, // REV64; EXT
3892 {TTI::SK_Reverse
, MVT::v2i64
, 1}, // EXT
3893 {TTI::SK_Reverse
, MVT::v2f32
, 1}, // REV64
3894 {TTI::SK_Reverse
, MVT::v4f32
, 2}, // REV64; EXT
3895 {TTI::SK_Reverse
, MVT::v2f64
, 1}, // EXT
3896 {TTI::SK_Reverse
, MVT::v8f16
, 2}, // REV64; EXT
3897 {TTI::SK_Reverse
, MVT::v8i16
, 2}, // REV64; EXT
3898 {TTI::SK_Reverse
, MVT::v16i8
, 2}, // REV64; EXT
3899 {TTI::SK_Reverse
, MVT::v4f16
, 1}, // REV64
3900 {TTI::SK_Reverse
, MVT::v4i16
, 1}, // REV64
3901 {TTI::SK_Reverse
, MVT::v8i8
, 1}, // REV64
3902 // Splice can all be lowered as `ext`.
3903 {TTI::SK_Splice
, MVT::v2i32
, 1},
3904 {TTI::SK_Splice
, MVT::v4i32
, 1},
3905 {TTI::SK_Splice
, MVT::v2i64
, 1},
3906 {TTI::SK_Splice
, MVT::v2f32
, 1},
3907 {TTI::SK_Splice
, MVT::v4f32
, 1},
3908 {TTI::SK_Splice
, MVT::v2f64
, 1},
3909 {TTI::SK_Splice
, MVT::v8f16
, 1},
3910 {TTI::SK_Splice
, MVT::v8bf16
, 1},
3911 {TTI::SK_Splice
, MVT::v8i16
, 1},
3912 {TTI::SK_Splice
, MVT::v16i8
, 1},
3913 {TTI::SK_Splice
, MVT::v4bf16
, 1},
3914 {TTI::SK_Splice
, MVT::v4f16
, 1},
3915 {TTI::SK_Splice
, MVT::v4i16
, 1},
3916 {TTI::SK_Splice
, MVT::v8i8
, 1},
3917 // Broadcast shuffle kinds for scalable vectors
3918 {TTI::SK_Broadcast
, MVT::nxv16i8
, 1},
3919 {TTI::SK_Broadcast
, MVT::nxv8i16
, 1},
3920 {TTI::SK_Broadcast
, MVT::nxv4i32
, 1},
3921 {TTI::SK_Broadcast
, MVT::nxv2i64
, 1},
3922 {TTI::SK_Broadcast
, MVT::nxv2f16
, 1},
3923 {TTI::SK_Broadcast
, MVT::nxv4f16
, 1},
3924 {TTI::SK_Broadcast
, MVT::nxv8f16
, 1},
3925 {TTI::SK_Broadcast
, MVT::nxv2bf16
, 1},
3926 {TTI::SK_Broadcast
, MVT::nxv4bf16
, 1},
3927 {TTI::SK_Broadcast
, MVT::nxv8bf16
, 1},
3928 {TTI::SK_Broadcast
, MVT::nxv2f32
, 1},
3929 {TTI::SK_Broadcast
, MVT::nxv4f32
, 1},
3930 {TTI::SK_Broadcast
, MVT::nxv2f64
, 1},
3931 {TTI::SK_Broadcast
, MVT::nxv16i1
, 1},
3932 {TTI::SK_Broadcast
, MVT::nxv8i1
, 1},
3933 {TTI::SK_Broadcast
, MVT::nxv4i1
, 1},
3934 {TTI::SK_Broadcast
, MVT::nxv2i1
, 1},
3935 // Handle the cases for vector.reverse with scalable vectors
3936 {TTI::SK_Reverse
, MVT::nxv16i8
, 1},
3937 {TTI::SK_Reverse
, MVT::nxv8i16
, 1},
3938 {TTI::SK_Reverse
, MVT::nxv4i32
, 1},
3939 {TTI::SK_Reverse
, MVT::nxv2i64
, 1},
3940 {TTI::SK_Reverse
, MVT::nxv2f16
, 1},
3941 {TTI::SK_Reverse
, MVT::nxv4f16
, 1},
3942 {TTI::SK_Reverse
, MVT::nxv8f16
, 1},
3943 {TTI::SK_Reverse
, MVT::nxv2bf16
, 1},
3944 {TTI::SK_Reverse
, MVT::nxv4bf16
, 1},
3945 {TTI::SK_Reverse
, MVT::nxv8bf16
, 1},
3946 {TTI::SK_Reverse
, MVT::nxv2f32
, 1},
3947 {TTI::SK_Reverse
, MVT::nxv4f32
, 1},
3948 {TTI::SK_Reverse
, MVT::nxv2f64
, 1},
3949 {TTI::SK_Reverse
, MVT::nxv16i1
, 1},
3950 {TTI::SK_Reverse
, MVT::nxv8i1
, 1},
3951 {TTI::SK_Reverse
, MVT::nxv4i1
, 1},
3952 {TTI::SK_Reverse
, MVT::nxv2i1
, 1},
3954 if (const auto *Entry
= CostTableLookup(ShuffleTbl
, Kind
, LT
.second
))
3955 return LT
.first
* Entry
->Cost
;
3958 if (Kind
== TTI::SK_Splice
&& isa
<ScalableVectorType
>(Tp
))
3959 return getSpliceCost(Tp
, Index
);
3961 // Inserting a subvector can often be done with either a D, S or H register
3962 // move, so long as the inserted vector is "aligned".
3963 if (Kind
== TTI::SK_InsertSubvector
&& LT
.second
.isFixedLengthVector() &&
3964 LT
.second
.getSizeInBits() <= 128 && SubTp
) {
3965 std::pair
<InstructionCost
, MVT
> SubLT
= getTypeLegalizationCost(SubTp
);
3966 if (SubLT
.second
.isVector()) {
3967 int NumElts
= LT
.second
.getVectorNumElements();
3968 int NumSubElts
= SubLT
.second
.getVectorNumElements();
3969 if ((Index
% NumSubElts
) == 0 && (NumElts
% NumSubElts
) == 0)
3974 return BaseT::getShuffleCost(Kind
, Tp
, Mask
, CostKind
, Index
, SubTp
);
3977 static bool containsDecreasingPointers(Loop
*TheLoop
,
3978 PredicatedScalarEvolution
*PSE
) {
3979 const auto &Strides
= DenseMap
<Value
*, const SCEV
*>();
3980 for (BasicBlock
*BB
: TheLoop
->blocks()) {
3981 // Scan the instructions in the block and look for addresses that are
3982 // consecutive and decreasing.
3983 for (Instruction
&I
: *BB
) {
3984 if (isa
<LoadInst
>(&I
) || isa
<StoreInst
>(&I
)) {
3985 Value
*Ptr
= getLoadStorePointerOperand(&I
);
3986 Type
*AccessTy
= getLoadStoreType(&I
);
3987 if (getPtrStride(*PSE
, AccessTy
, Ptr
, TheLoop
, Strides
, /*Assume=*/true,
3988 /*ShouldCheckWrap=*/false)
3997 bool AArch64TTIImpl::preferPredicateOverEpilogue(TailFoldingInfo
*TFI
) {
4001 // We don't currently support vectorisation with interleaving for SVE - with
4002 // such loops we're better off not using tail-folding. This gives us a chance
4003 // to fall back on fixed-width vectorisation using NEON's ld2/st2/etc.
4004 if (TFI
->IAI
->hasGroups())
4007 TailFoldingOpts Required
= TailFoldingOpts::Disabled
;
4008 if (TFI
->LVL
->getReductionVars().size())
4009 Required
|= TailFoldingOpts::Reductions
;
4010 if (TFI
->LVL
->getFixedOrderRecurrences().size())
4011 Required
|= TailFoldingOpts::Recurrences
;
4013 // We call this to discover whether any load/store pointers in the loop have
4014 // negative strides. This will require extra work to reverse the loop
4015 // predicate, which may be expensive.
4016 if (containsDecreasingPointers(TFI
->LVL
->getLoop(),
4017 TFI
->LVL
->getPredicatedScalarEvolution()))
4018 Required
|= TailFoldingOpts::Reverse
;
4019 if (Required
== TailFoldingOpts::Disabled
)
4020 Required
|= TailFoldingOpts::Simple
;
4022 if (!TailFoldingOptionLoc
.satisfies(ST
->getSVETailFoldingDefaultOpts(),
4026 // Don't tail-fold for tight loops where we would be better off interleaving
4027 // with an unpredicated loop.
4028 unsigned NumInsns
= 0;
4029 for (BasicBlock
*BB
: TFI
->LVL
->getLoop()->blocks()) {
4030 NumInsns
+= BB
->sizeWithoutDebug();
4033 // We expect 4 of these to be a IV PHI, IV add, IV compare and branch.
4034 return NumInsns
>= SVETailFoldInsnThreshold
;
4038 AArch64TTIImpl::getScalingFactorCost(Type
*Ty
, GlobalValue
*BaseGV
,
4039 int64_t BaseOffset
, bool HasBaseReg
,
4040 int64_t Scale
, unsigned AddrSpace
) const {
4041 // Scaling factors are not free at all.
4042 // Operands | Rt Latency
4043 // -------------------------------------------
4045 // -------------------------------------------
4046 // Rt, [Xn, Xm, lsl #imm] | Rn: 4 Rm: 5
4047 // Rt, [Xn, Wm, <extend> #imm] |
4048 TargetLoweringBase::AddrMode AM
;
4050 AM
.BaseOffs
= BaseOffset
;
4051 AM
.HasBaseReg
= HasBaseReg
;
4053 if (getTLI()->isLegalAddressingMode(DL
, AM
, Ty
, AddrSpace
))
4054 // Scale represents reg2 * scale, thus account for 1 if
4055 // it is not equal to 0 or 1.
4056 return AM
.Scale
!= 0 && AM
.Scale
!= 1;
4060 bool AArch64TTIImpl::shouldTreatInstructionLikeSelect(const Instruction
*I
) {
4061 // For the binary operators (e.g. or) we need to be more careful than
4062 // selects, here we only transform them if they are already at a natural
4063 // break point in the code - the end of a block with an unconditional
4065 if (EnableOrLikeSelectOpt
&& I
->getOpcode() == Instruction::Or
&&
4066 isa
<BranchInst
>(I
->getNextNode()) &&
4067 cast
<BranchInst
>(I
->getNextNode())->isUnconditional())
4069 return BaseT::shouldTreatInstructionLikeSelect(I
);