LLVM 24.0.0git
AArch64ISelLowering.cpp
Go to the documentation of this file.
1//===-- AArch64ISelLowering.cpp - AArch64 DAG Lowering Implementation ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the AArch64TargetLowering class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "AArch64ISelLowering.h"
15#include "AArch64ExpandImm.h"
18#include "AArch64RegisterInfo.h"
20#include "AArch64Subtarget.h"
24#include "llvm/ADT/APFloat.h"
25#include "llvm/ADT/APInt.h"
26#include "llvm/ADT/ArrayRef.h"
27#include "llvm/ADT/STLExtras.h"
28#include "llvm/ADT/SmallSet.h"
31#include "llvm/ADT/Statistic.h"
32#include "llvm/ADT/StringRef.h"
34#include "llvm/ADT/Twine.h"
63#include "llvm/IR/Attributes.h"
64#include "llvm/IR/Constants.h"
65#include "llvm/IR/DataLayout.h"
66#include "llvm/IR/DebugLoc.h"
68#include "llvm/IR/Function.h"
70#include "llvm/IR/GlobalValue.h"
71#include "llvm/IR/IRBuilder.h"
72#include "llvm/IR/Instruction.h"
75#include "llvm/IR/Intrinsics.h"
76#include "llvm/IR/IntrinsicsAArch64.h"
77#include "llvm/IR/Module.h"
79#include "llvm/IR/Type.h"
80#include "llvm/IR/Use.h"
81#include "llvm/IR/Value.h"
86#include "llvm/Support/Debug.h"
96#include <algorithm>
97#include <bitset>
98#include <cassert>
99#include <cctype>
100#include <cstdint>
101#include <cstdlib>
102#include <iterator>
103#include <limits>
104#include <optional>
105#include <tuple>
106#include <utility>
107#include <vector>
108
109using namespace llvm;
110
111#define DEBUG_TYPE "aarch64-lower"
112
113STATISTIC(NumTailCalls, "Number of tail calls");
114STATISTIC(NumOptimizedImms, "Number of times immediates were optimized");
115
116// FIXME: The necessary dtprel relocations don't seem to be supported
117// well in the GNU bfd and gold linkers at the moment. Therefore, by
118// default, for now, fall back to GeneralDynamic code generation.
120 "aarch64-elf-ldtls-generation", cl::Hidden,
121 cl::desc("Allow AArch64 Local Dynamic TLS code generation"),
122 cl::init(false));
123
124static cl::opt<bool>
125EnableOptimizeLogicalImm("aarch64-enable-logical-imm", cl::Hidden,
126 cl::desc("Enable AArch64 logical imm instruction "
127 "optimization"),
128 cl::init(true));
129
130// Temporary option added for the purpose of testing functionality added
131// to DAGCombiner.cpp in D92230. It is expected that this can be removed
132// in future when both implementations will be based off MGATHER rather
133// than the GLD1 nodes added for the SVE gather load intrinsics.
134static cl::opt<bool>
135EnableCombineMGatherIntrinsics("aarch64-enable-mgather-combine", cl::Hidden,
136 cl::desc("Combine extends of AArch64 masked "
137 "gather intrinsics"),
138 cl::init(true));
139
140static cl::opt<bool> EnableExtToTBL("aarch64-enable-ext-to-tbl", cl::Hidden,
141 cl::desc("Combine ext and trunc to TBL"),
142 cl::init(true));
143
144// All of the XOR, OR and CMP use ALU ports, and data dependency will become the
145// bottleneck after this transform on high end CPU. So this max leaf node
146// limitation is guard cmp+ccmp will be profitable.
147static cl::opt<unsigned> MaxXors("aarch64-max-xors", cl::init(16), cl::Hidden,
148 cl::desc("Maximum of xors"));
149
150// By turning this on, we will not fallback to DAG ISel when encountering
151// scalable vector types for all instruction, even if SVE is not yet supported
152// with some instructions.
153// See [AArch64TargetLowering::fallbackToDAGISel] for implementation details.
155 "aarch64-enable-gisel-sve", cl::Hidden,
156 cl::desc("Enable / disable SVE scalable vectors in Global ISel"),
157 cl::init(false));
158
160 "aarch64-br-merging-base-cost", cl::init(2),
161 cl::desc(
162 "Cost threshold for merging multiple conditionals into one branch "
163 "versus splitting into multiple branches: conditionals are merged when "
164 "their instruction cost is below this limit and split above it. Set to "
165 "-1 to never merge branches."),
166 cl::Hidden);
167
169 "aarch64-br-merging-ccmp-bias", cl::init(6),
170 cl::desc("Increases 'aarch64-br-merging-base-cost' to account for the "
171 "CCMP instruction, which is always available on AArch64 and "
172 "makes merging branch conditions cheaper."),
173 cl::Hidden);
174
176 "aarch64-br-merging-cbz-tbnz-bias", cl::init(6),
177 cl::desc("Decreases 'aarch64-br-merging-base-cost' when a condition can "
178 "lower to a single CBZ/CBNZ or TBZ/TBNZ compare-and-branch, to "
179 "bias toward splitting. Set to 0 to disable."),
180 cl::Hidden);
181
183 "aarch64-br-merging-likely-bias", cl::init(0),
184 cl::desc("Increases 'aarch64-br-merging-base-cost' when all conditionals "
185 "are likely to be executed, biasing toward merging. Set to -1 to "
186 "never merge likely branches."),
187 cl::Hidden);
188
190 "aarch64-br-merging-unlikely-bias", cl::init(-1),
191 cl::desc(
192 "Decreases 'aarch64-br-merging-base-cost' when all conditionals are "
193 "unlikely to be executed, biasing toward splitting. Set to -1 to never "
194 "merge unlikely branches."),
195 cl::Hidden);
196
197// TODO: This option should be removed once we switch to always using PTRADD in
198// the SelectionDAG.
200 "aarch64-use-featcpa-codegen", cl::Hidden,
201 cl::desc("Generate ISD::PTRADD nodes for pointer arithmetic in "
202 "SelectionDAG for FEAT_CPA"),
203 cl::init(false));
204
205// FPMR writes might be a synchronization barrier and thus carry a significant
206// cost. Give users the option to skip writes when the requested value is
207// already set.
209 "aarch64-use-conditional-fpmr-write", cl::Hidden,
210 cl::desc("Only write FPMR when the requested value differs from the "
211 "current value"),
212 cl::init(false));
213
214// Development flag to allow incremental bring up. Will be removed once the
215// implementation is complete.
217 "aarch64-sve-vls-bfloat-support", cl::Hidden,
218 cl::desc("Use SVE for fixed-length vector bfloat operations"),
219 cl::init(false));
220
221/// Value type used for condition codes.
222constexpr MVT CondCodeVT = MVT::i32;
223
224/// Value type used for NZCV flags.
225constexpr MVT FlagsVT = MVT::i32;
226
227static const MCPhysReg GPRArgRegs[] = {AArch64::X0, AArch64::X1, AArch64::X2,
228 AArch64::X3, AArch64::X4, AArch64::X5,
229 AArch64::X6, AArch64::X7};
230static const MCPhysReg FPRArgRegs[] = {AArch64::Q0, AArch64::Q1, AArch64::Q2,
231 AArch64::Q3, AArch64::Q4, AArch64::Q5,
232 AArch64::Q6, AArch64::Q7};
233
235
237
238static inline EVT getPackedSVEVectorVT(EVT VT) {
239 switch (VT.getSimpleVT().SimpleTy) {
240 default:
241 llvm_unreachable("unexpected element type for vector");
242 case MVT::i8:
243 return MVT::nxv16i8;
244 case MVT::i16:
245 return MVT::nxv8i16;
246 case MVT::i32:
247 return MVT::nxv4i32;
248 case MVT::i64:
249 return MVT::nxv2i64;
250 case MVT::f16:
251 return MVT::nxv8f16;
252 case MVT::f32:
253 return MVT::nxv4f32;
254 case MVT::f64:
255 return MVT::nxv2f64;
256 case MVT::bf16:
257 return MVT::nxv8bf16;
258 }
259}
260
261// NOTE: Currently there's only a need to return integer vector types. If this
262// changes then just add an extra "type" parameter.
264 switch (EC.getKnownMinValue()) {
265 default:
266 llvm_unreachable("unexpected element count for vector");
267 case 16:
268 return MVT::nxv16i8;
269 case 8:
270 return MVT::nxv8i16;
271 case 4:
272 return MVT::nxv4i32;
273 case 2:
274 return MVT::nxv2i64;
275 }
276}
277
279 assert(VT.isScalableVectorOf(MVT::i1) &&
280 "Expected scalable predicate vector type!");
281 switch (VT.getVectorMinNumElements()) {
282 default:
283 llvm_unreachable("unexpected element count for vector");
284 case 2:
285 return MVT::nxv2i64;
286 case 4:
287 return MVT::nxv4i32;
288 case 8:
289 return MVT::nxv8i16;
290 case 16:
291 return MVT::nxv16i8;
292 }
293}
294
295/// Returns true if VT's elements occupy the lowest bit positions of its
296/// associated register class without any intervening space.
297///
298/// For example, nxv2f16, nxv4f16 and nxv8f16 are legal types that belong to the
299/// same register class, but only nxv8f16 can be treated as a packed vector.
300static inline bool isPackedVectorType(EVT VT, SelectionDAG &DAG) {
302 "Expected legal vector type!");
303 return VT.isFixedLengthVector() ||
305}
306
307static inline bool isPackedPredicateType(EVT VT, SelectionDAG &DAG) {
309 "Expected legal type!");
310 return VT == MVT::nxv16i1;
311}
312
313/// Returns true if the conceptual representation for \p VT does not map
314/// directly to its physical register representation, meaning there are gaps
315/// between elements in the register. In practice, the vector elements will be
316/// strided by a power of two and placed starting from lane 0. For example,
317/// nxv8i1 or nxv2f32 are unpacked types.
318///
319///\pre VT is a legal type.
320static inline bool isUnpackedType(EVT VT, SelectionDAG &DAG) {
321 bool Res = !isPackedVectorType(VT, DAG) && !isPackedPredicateType(VT, DAG);
322 assert((!Res || VT.isScalableVector()) &&
323 "Unexpected fixed-size unpacked type.");
324 return Res;
325}
326
327// Returns true for ####_MERGE_PASSTHRU opcodes, whose operands have a leading
328// predicate and end with a passthru value matching the result type.
329static bool isMergePassthruOpcode(unsigned Opc) {
330 switch (Opc) {
331 default:
332 return false;
333 case AArch64ISD::BITREVERSE_MERGE_PASSTHRU:
334 case AArch64ISD::BSWAP_MERGE_PASSTHRU:
335 case AArch64ISD::REVH_MERGE_PASSTHRU:
336 case AArch64ISD::REVW_MERGE_PASSTHRU:
337 case AArch64ISD::REVD_MERGE_PASSTHRU:
338 case AArch64ISD::CTLZ_MERGE_PASSTHRU:
339 case AArch64ISD::CTPOP_MERGE_PASSTHRU:
340 case AArch64ISD::DUP_MERGE_PASSTHRU:
341 case AArch64ISD::ABS_MERGE_PASSTHRU:
342 case AArch64ISD::NEG_MERGE_PASSTHRU:
343 case AArch64ISD::FNEG_MERGE_PASSTHRU:
344 case AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU:
345 case AArch64ISD::ZERO_EXTEND_INREG_MERGE_PASSTHRU:
346 case AArch64ISD::FCEIL_MERGE_PASSTHRU:
347 case AArch64ISD::FFLOOR_MERGE_PASSTHRU:
348 case AArch64ISD::FNEARBYINT_MERGE_PASSTHRU:
349 case AArch64ISD::FRINT_MERGE_PASSTHRU:
350 case AArch64ISD::FRINT32_MERGE_PASSTHRU:
351 case AArch64ISD::FRINT64_MERGE_PASSTHRU:
352 case AArch64ISD::FROUND_MERGE_PASSTHRU:
353 case AArch64ISD::FROUNDEVEN_MERGE_PASSTHRU:
354 case AArch64ISD::FTRUNC_MERGE_PASSTHRU:
355 case AArch64ISD::FTRUNC32_MERGE_PASSTHRU:
356 case AArch64ISD::FTRUNC64_MERGE_PASSTHRU:
357 case AArch64ISD::FP_ROUND_MERGE_PASSTHRU:
358 case AArch64ISD::FP_EXTEND_MERGE_PASSTHRU:
359 case AArch64ISD::SINT_TO_FP_MERGE_PASSTHRU:
360 case AArch64ISD::UINT_TO_FP_MERGE_PASSTHRU:
361 case AArch64ISD::FCVTX_MERGE_PASSTHRU:
362 case AArch64ISD::FCVTZU_MERGE_PASSTHRU:
363 case AArch64ISD::FCVTZS_MERGE_PASSTHRU:
364 case AArch64ISD::FSQRT_MERGE_PASSTHRU:
365 case AArch64ISD::FRECPX_MERGE_PASSTHRU:
366 case AArch64ISD::FABS_MERGE_PASSTHRU:
367 case AArch64ISD::STRICT_FCEIL_MERGE_PASSTHRU:
368 case AArch64ISD::STRICT_FFLOOR_MERGE_PASSTHRU:
369 case AArch64ISD::STRICT_FNEARBYINT_MERGE_PASSTHRU:
370 case AArch64ISD::STRICT_FROUND_MERGE_PASSTHRU:
371 case AArch64ISD::STRICT_FROUNDEVEN_MERGE_PASSTHRU:
372 case AArch64ISD::STRICT_FTRUNC_MERGE_PASSTHRU:
373 case AArch64ISD::STRICT_FSQRT_MERGE_PASSTHRU:
374 return true;
375 }
376}
377
378// Returns true if inactive lanes are known to be zeroed by construction.
380 switch (Op.getOpcode()) {
381 default:
382 return false;
383 // We guarantee i1 splat_vectors to zero the other lanes
386 case AArch64ISD::PTRUE:
387 case AArch64ISD::SETCC_MERGE_ZERO:
388 return true;
390 switch (Op.getConstantOperandVal(0)) {
391 default:
392 return false;
393 case Intrinsic::aarch64_sve_ptrue:
394 case Intrinsic::aarch64_sve_pnext:
395 case Intrinsic::aarch64_sve_cmpeq:
396 case Intrinsic::aarch64_sve_cmpne:
397 case Intrinsic::aarch64_sve_cmpge:
398 case Intrinsic::aarch64_sve_cmpgt:
399 case Intrinsic::aarch64_sve_cmphs:
400 case Intrinsic::aarch64_sve_cmphi:
401 case Intrinsic::aarch64_sve_cmpeq_wide:
402 case Intrinsic::aarch64_sve_cmpne_wide:
403 case Intrinsic::aarch64_sve_cmpge_wide:
404 case Intrinsic::aarch64_sve_cmpgt_wide:
405 case Intrinsic::aarch64_sve_cmplt_wide:
406 case Intrinsic::aarch64_sve_cmple_wide:
407 case Intrinsic::aarch64_sve_cmphs_wide:
408 case Intrinsic::aarch64_sve_cmphi_wide:
409 case Intrinsic::aarch64_sve_cmplo_wide:
410 case Intrinsic::aarch64_sve_cmpls_wide:
411 case Intrinsic::aarch64_sve_fcmpeq:
412 case Intrinsic::aarch64_sve_fcmpne:
413 case Intrinsic::aarch64_sve_fcmpge:
414 case Intrinsic::aarch64_sve_fcmpgt:
415 case Intrinsic::aarch64_sve_fcmpuo:
416 case Intrinsic::aarch64_sve_facgt:
417 case Intrinsic::aarch64_sve_facge:
418 case Intrinsic::aarch64_sve_whilege:
419 case Intrinsic::aarch64_sve_whilegt:
420 case Intrinsic::aarch64_sve_whilehi:
421 case Intrinsic::aarch64_sve_whilehs:
422 case Intrinsic::aarch64_sve_whilele:
423 case Intrinsic::aarch64_sve_whilelo:
424 case Intrinsic::aarch64_sve_whilels:
425 case Intrinsic::aarch64_sve_whilelt:
426 case Intrinsic::aarch64_sve_match:
427 case Intrinsic::aarch64_sve_nmatch:
428 case Intrinsic::aarch64_sve_whilege_x2:
429 case Intrinsic::aarch64_sve_whilegt_x2:
430 case Intrinsic::aarch64_sve_whilehi_x2:
431 case Intrinsic::aarch64_sve_whilehs_x2:
432 case Intrinsic::aarch64_sve_whilele_x2:
433 case Intrinsic::aarch64_sve_whilelo_x2:
434 case Intrinsic::aarch64_sve_whilels_x2:
435 case Intrinsic::aarch64_sve_whilelt_x2:
436 return true;
437 }
438 }
439}
440
441static std::tuple<SDValue, SDValue>
443 SDLoc DL(Disc);
444 SDValue AddrDisc;
445 SDValue ConstDisc;
446
447 // If this is a blend, remember the constant and address discriminators.
448 // Otherwise, it's either a constant discriminator, or a non-blended
449 // address discriminator.
450 if (Disc->getOpcode() == ISD::INTRINSIC_WO_CHAIN &&
451 Disc->getConstantOperandVal(0) == Intrinsic::ptrauth_blend) {
452 AddrDisc = Disc->getOperand(1);
453 ConstDisc = Disc->getOperand(2);
454 } else {
455 ConstDisc = Disc;
456 }
457
458 // If the constant discriminator (either the blend RHS, or the entire
459 // discriminator value) isn't a 16-bit constant, bail out, and let the
460 // discriminator be computed separately.
461 const auto *ConstDiscN = dyn_cast<ConstantSDNode>(ConstDisc);
462 if (!ConstDiscN || !isUInt<16>(ConstDiscN->getZExtValue()))
463 return std::make_tuple(DAG->getTargetConstant(0, DL, MVT::i64), Disc);
464
465 // If there's no address discriminator, use NoRegister, which we'll later
466 // replace with XZR, or directly use a Z variant of the inst. when available.
467 if (!AddrDisc)
468 AddrDisc = DAG->getRegister(AArch64::NoRegister, MVT::i64);
469
470 return std::make_tuple(
471 DAG->getTargetConstant(ConstDiscN->getZExtValue(), DL, MVT::i64),
472 AddrDisc);
473}
474
476 const AArch64Subtarget &STI)
477 : TargetLowering(TM, STI), Subtarget(&STI) {
478 // AArch64 doesn't have comparisons which set GPRs or setcc instructions, so
479 // we have to make something up. Arbitrarily, choose ZeroOrOne.
481 // When comparing vectors the result sets the different elements in the
482 // vector to all-one or all-zero.
484
485 // Set up the register classes.
486 addRegisterClass(MVT::i32, &AArch64::GPR32allRegClass);
487 addRegisterClass(MVT::i64, &AArch64::GPR64allRegClass);
488
489 if (Subtarget->hasLS64()) {
490 addRegisterClass(MVT::i64x8, &AArch64::GPR64x8ClassRegClass);
491 setOperationAction(ISD::LOAD, MVT::i64x8, Custom);
493 }
494
495 if (Subtarget->hasFPARMv8()) {
496 addRegisterClass(MVT::aarch64mfp8, &AArch64::FPR8RegClass);
497 addRegisterClass(MVT::f16, &AArch64::FPR16RegClass);
498 addRegisterClass(MVT::bf16, &AArch64::FPR16RegClass);
499 addRegisterClass(MVT::f32, &AArch64::FPR32RegClass);
500 addRegisterClass(MVT::f64, &AArch64::FPR64RegClass);
501 addRegisterClass(MVT::f128, &AArch64::FPR128RegClass);
502 }
503
504 if (Subtarget->hasNEON()) {
505 addRegisterClass(MVT::v16i8, &AArch64::FPR8RegClass);
506 addRegisterClass(MVT::v8i16, &AArch64::FPR16RegClass);
507
508 addDRType(MVT::v2f32);
509 addDRType(MVT::v8i8);
510 addDRType(MVT::v4i16);
511 addDRType(MVT::v2i32);
512 addDRType(MVT::v1i64);
513 addDRType(MVT::v1f64);
514 addDRType(MVT::v4f16);
515 addDRType(MVT::v4bf16);
516
517 addQRType(MVT::v4f32);
518 addQRType(MVT::v2f64);
519 addQRType(MVT::v16i8);
520 addQRType(MVT::v8i16);
521 addQRType(MVT::v4i32);
522 addQRType(MVT::v2i64);
523 addQRType(MVT::v8f16);
524 addQRType(MVT::v8bf16);
525 }
526
527 if (Subtarget->isSVEorStreamingSVEAvailable()) {
528 // Add legal sve predicate types
529 addRegisterClass(MVT::nxv1i1, &AArch64::PPRRegClass);
530 addRegisterClass(MVT::nxv2i1, &AArch64::PPRRegClass);
531 addRegisterClass(MVT::nxv4i1, &AArch64::PPRRegClass);
532 addRegisterClass(MVT::nxv8i1, &AArch64::PPRRegClass);
533 addRegisterClass(MVT::nxv16i1, &AArch64::PPRRegClass);
534
535 // Add sve predicate as counter type
536 addRegisterClass(MVT::aarch64svcount, &AArch64::PNRRegClass);
537
538 // Add legal sve data types
539 addRegisterClass(MVT::nxv16i8, &AArch64::ZPRRegClass);
540 addRegisterClass(MVT::nxv8i16, &AArch64::ZPRRegClass);
541 addRegisterClass(MVT::nxv4i32, &AArch64::ZPRRegClass);
542 addRegisterClass(MVT::nxv2i64, &AArch64::ZPRRegClass);
543
544 addRegisterClass(MVT::nxv2f16, &AArch64::ZPRRegClass);
545 addRegisterClass(MVT::nxv4f16, &AArch64::ZPRRegClass);
546 addRegisterClass(MVT::nxv8f16, &AArch64::ZPRRegClass);
547 addRegisterClass(MVT::nxv2f32, &AArch64::ZPRRegClass);
548 addRegisterClass(MVT::nxv4f32, &AArch64::ZPRRegClass);
549 addRegisterClass(MVT::nxv2f64, &AArch64::ZPRRegClass);
550
551 addRegisterClass(MVT::nxv2bf16, &AArch64::ZPRRegClass);
552 addRegisterClass(MVT::nxv4bf16, &AArch64::ZPRRegClass);
553 addRegisterClass(MVT::nxv8bf16, &AArch64::ZPRRegClass);
554
555 if (Subtarget->useSVEForFixedLengthVectors()) {
558 addRegisterClass(VT, &AArch64::ZPRRegClass);
559
562 addRegisterClass(VT, &AArch64::ZPRRegClass);
563 }
564 }
565
566 // Compute derived properties from the register classes
567 computeRegisterProperties(Subtarget->getRegisterInfo());
568
569 // Provide all sorts of operation actions
597 if (Subtarget->hasFPARMv8()) {
600 }
613
615
619
622
624
625 // Custom lowering hooks are needed for XOR
626 // to fold it into CSINC/CSINV.
629
632
633 // Virtually no operation on f128 is legal, but LLVM can't expand them when
634 // there's a valid register class, so we need custom operations in most cases.
659 // FIXME: f128 FMINIMUM and FMAXIMUM (including STRICT versions) currently
660 // aren't handled.
661
662 // Lowering for many of the conversions is actually specified by the non-f128
663 // type. The LowerXXX function will be trivial when f128 isn't involved.
688 if (Subtarget->hasFPARMv8()) {
691 }
694 if (Subtarget->hasFPARMv8()) {
697 }
700
705
706 // Variable arguments.
711
712 // Variable-sized objects.
715
716 // Lowering Funnel Shifts to EXTR
721
723
724 // Constant pool entries
726
727 // BlockAddress
729
730 // AArch64 lacks both left-rotate and popcount instructions.
736 }
737
738 // AArch64 doesn't have i32 MULH{S|U}.
741
742 // AArch64 doesn't have {U|S}MUL_LOHI.
747
748 if (Subtarget->hasCSSC()) {
752
754
758
761
766
771 } else {
775
778
781 }
782
788 }
795
796 // Custom lower Add/Sub/Mul with overflow.
809
818
827 if (Subtarget->hasFullFP16()) {
830 } else {
833 }
834
835 for (auto Op : {ISD::FREM, ISD::FPOW, ISD::FPOWI,
849 setOperationAction(Op, MVT::f16, Promote);
850 setOperationAction(Op, MVT::v4f16, Expand);
851 setOperationAction(Op, MVT::v8f16, Expand);
852 setOperationAction(Op, MVT::bf16, Promote);
853 setOperationAction(Op, MVT::v4bf16, Expand);
854 setOperationAction(Op, MVT::v8bf16, Expand);
855 }
856
857 // Legalize fcanonicalize to circumvent default expansion
858 setOperationAction(ISD::FCANONICALIZE, {MVT::f32, MVT::f64}, Legal);
859 if (Subtarget->hasFullFP16()) {
861 }
862
863 // fpextend from f16 or bf16 to f32 is legal
868 // fpextend from bf16 to f64 needs to be split into two fpextends
871
872 auto LegalizeNarrowFP = [this](MVT ScalarVT) {
873 for (auto Op : {
877 ISD::FADD,
878 ISD::FSUB,
879 ISD::FMUL,
880 ISD::FDIV,
881 ISD::FMA,
914 })
915 setOperationAction(Op, ScalarVT, Promote);
916
917 for (auto Op : {ISD::FNEG, ISD::FABS})
918 setOperationAction(Op, ScalarVT, Legal);
919
920 // Round-to-integer need custom lowering for fp16, as Promote doesn't work
921 // because the result type is integer.
925 setOperationAction(Op, ScalarVT, Custom);
926
927 // promote v4f16 to v4f32 when that is known to be safe.
928 auto V4Narrow = MVT::getVectorVT(ScalarVT, 4);
929 setOperationPromotedToType(ISD::FADD, V4Narrow, MVT::v4f32);
930 setOperationPromotedToType(ISD::FSUB, V4Narrow, MVT::v4f32);
931 setOperationPromotedToType(ISD::FMUL, V4Narrow, MVT::v4f32);
932 setOperationPromotedToType(ISD::FDIV, V4Narrow, MVT::v4f32);
933 setOperationPromotedToType(ISD::FCEIL, V4Narrow, MVT::v4f32);
934 setOperationPromotedToType(ISD::FFLOOR, V4Narrow, MVT::v4f32);
935 setOperationPromotedToType(ISD::FROUND, V4Narrow, MVT::v4f32);
936 setOperationPromotedToType(ISD::FTRUNC, V4Narrow, MVT::v4f32);
937 setOperationPromotedToType(ISD::FROUNDEVEN, V4Narrow, MVT::v4f32);
938 setOperationPromotedToType(ISD::FRINT, V4Narrow, MVT::v4f32);
939 setOperationPromotedToType(ISD::FNEARBYINT, V4Narrow, MVT::v4f32);
940 setOperationPromotedToType(ISD::FCANONICALIZE, V4Narrow, MVT::v4f32);
941 setOperationPromotedToType(ISD::SETCC, V4Narrow, MVT::v4f32);
942
951
952 auto V8Narrow = MVT::getVectorVT(ScalarVT, 8);
953 setOperationPromotedToType(ISD::FCANONICALIZE, V8Narrow, MVT::v8f32);
954 setOperationPromotedToType(ISD::SETCC, V8Narrow, MVT::v8f32);
955 setOperationPromotedToType(ISD::VECREDUCE_FADD, V8Narrow, MVT::v8f32);
956 setOperationPromotedToType(ISD::VECREDUCE_FMUL, V8Narrow, MVT::v8f32);
957
978 };
979
980 if (!Subtarget->hasFullFP16()) {
981 LegalizeNarrowFP(MVT::f16);
982 }
983 LegalizeNarrowFP(MVT::bf16);
986
987 // AArch64 has implementations of a lot of rounding-like FP operations.
988 // clang-format off
989 for (auto Op :
1001 for (MVT Ty : {MVT::f32, MVT::f64})
1003 if (Subtarget->hasFullFP16())
1004 setOperationAction(Op, MVT::f16, Legal);
1005 }
1006 // clang-format on
1007
1008 // Basic strict FP operations are legal
1011 for (MVT Ty : {MVT::f32, MVT::f64})
1013 if (Subtarget->hasFullFP16())
1014 setOperationAction(Op, MVT::f16, Legal);
1015 }
1016
1018
1024
1026 if (!Subtarget->hasLSE() && !Subtarget->outlineAtomics()) {
1029 } else {
1032 }
1035
1036 // Generate outline atomics library calls only if LSE was not specified for
1037 // subtarget
1038 if (Subtarget->outlineAtomics() && !Subtarget->hasLSE()) {
1064 }
1065
1066 if (Subtarget->hasLSE128()) {
1067 // Custom lowering because i128 is not legal. Must be replaced by 2x64
1068 // values. ATOMIC_LOAD_AND also needs op legalisation to emit LDCLRP.
1072 }
1073
1074 // 128-bit loads and stores can be done without expanding
1075 setOperationAction(ISD::LOAD, MVT::i128, Custom);
1077
1078 // Aligned 128-bit loads and stores are single-copy atomic according to the
1079 // v8.4a spec. LRCPC3 introduces 128-bit STILP/LDIAPP but still requires LSE2.
1080 if (Subtarget->hasLSE2()) {
1083 }
1084
1085 // 256 bit non-temporal stores can be lowered to STNP. Do this as part of the
1086 // custom lowering, as there are no un-paired non-temporal stores and
1087 // legalization will break up 256 bit inputs.
1088 setOperationAction(ISD::STORE, MVT::v32i8, Custom);
1089 setOperationAction(ISD::STORE, MVT::v16i16, Custom);
1090 setOperationAction(ISD::STORE, MVT::v16f16, Custom);
1091 setOperationAction(ISD::STORE, MVT::v16bf16, Custom);
1092 setOperationAction(ISD::STORE, MVT::v8i32, Custom);
1093 setOperationAction(ISD::STORE, MVT::v8f32, Custom);
1094 setOperationAction(ISD::STORE, MVT::v4f64, Custom);
1095 setOperationAction(ISD::STORE, MVT::v4i64, Custom);
1096
1097 // 256 bit non-temporal loads can be lowered to LDNP. This is done using
1098 // custom lowering, as there are no un-paired non-temporal loads legalization
1099 // will break up 256 bit inputs.
1100 setOperationAction(ISD::LOAD, MVT::v32i8, Custom);
1101 setOperationAction(ISD::LOAD, MVT::v16i16, Custom);
1102 setOperationAction(ISD::LOAD, MVT::v16f16, Custom);
1103 setOperationAction(ISD::LOAD, MVT::v16bf16, Custom);
1104 setOperationAction(ISD::LOAD, MVT::v8i32, Custom);
1105 setOperationAction(ISD::LOAD, MVT::v8f32, Custom);
1106 setOperationAction(ISD::LOAD, MVT::v4f64, Custom);
1107 setOperationAction(ISD::LOAD, MVT::v4i64, Custom);
1108
1109 // Lower READCYCLECOUNTER using an mrs from CNTVCT_EL0.
1111
1112 // Issue __sincos_stret if available.
1115
1116 // Make floating-point constants legal for the large code model, so they don't
1117 // become loads from the constant pool.
1118 if (Subtarget->isTargetMachO() && TM.getCodeModel() == CodeModel::Large) {
1121 }
1122
1123 // AArch64 does not have floating-point extending loads, i1 sign-extending
1124 // load, floating-point truncating stores, or v2i32->v2i16 truncating store.
1125 for (MVT VT : MVT::fp_valuetypes()) {
1126 setLoadExtAction(ISD::EXTLOAD, VT, MVT::bf16, Expand);
1127 setLoadExtAction(ISD::EXTLOAD, VT, MVT::f16, Expand);
1128 setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand);
1129 setLoadExtAction(ISD::EXTLOAD, VT, MVT::f64, Expand);
1130 setLoadExtAction(ISD::EXTLOAD, VT, MVT::f80, Expand);
1131 }
1132 for (MVT VT : MVT::integer_valuetypes())
1133 setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Expand);
1134
1135 for (MVT WideVT : MVT::fp_valuetypes()) {
1136 for (MVT NarrowVT : MVT::fp_valuetypes()) {
1137 if (WideVT.getScalarSizeInBits() > NarrowVT.getScalarSizeInBits()) {
1138 setTruncStoreAction(WideVT, NarrowVT, Expand);
1139 }
1140 }
1141 }
1142
1143 if (Subtarget->hasFPARMv8()) {
1147 }
1148
1149 // Indexed loads and stores are supported.
1150 for (unsigned im = (unsigned)ISD::PRE_INC;
1152 setIndexedLoadAction(im, MVT::i8, Legal);
1153 setIndexedLoadAction(im, MVT::i16, Legal);
1154 setIndexedLoadAction(im, MVT::i32, Legal);
1155 setIndexedLoadAction(im, MVT::i64, Legal);
1156 setIndexedLoadAction(im, MVT::f64, Legal);
1157 setIndexedLoadAction(im, MVT::f32, Legal);
1158 setIndexedLoadAction(im, MVT::f16, Legal);
1159 setIndexedLoadAction(im, MVT::bf16, Legal);
1160 setIndexedStoreAction(im, MVT::i8, Legal);
1161 setIndexedStoreAction(im, MVT::i16, Legal);
1162 setIndexedStoreAction(im, MVT::i32, Legal);
1163 setIndexedStoreAction(im, MVT::i64, Legal);
1164 setIndexedStoreAction(im, MVT::f64, Legal);
1165 setIndexedStoreAction(im, MVT::f32, Legal);
1166 setIndexedStoreAction(im, MVT::f16, Legal);
1167 setIndexedStoreAction(im, MVT::bf16, Legal);
1168 }
1169
1170 // Trap.
1171 setOperationAction(ISD::TRAP, MVT::Other, Legal);
1174
1175 // We combine OR nodes for ccmp operations.
1177 // Try to create BICs for vector ANDs.
1179
1180 // llvm.init.trampoline and llvm.adjust.trampoline
1183
1184 // Vector add and sub nodes may conceal a high-half opportunity.
1185 // Also, try to fold ADD into CSINC/CSINV..
1188
1191
1192 // Try and combine setcc/select_cc with csel and bool-vector bitcasts.
1196
1198
1206
1208
1210
1212
1216
1219
1221
1223
1226
1228
1234
1236
1240
1241 if (Subtarget->isSVEorStreamingSVEAvailable())
1243
1244 // In case of strict alignment, avoid an excessive number of byte wide stores.
1247 Subtarget->requiresStrictAlign() ? MaxStoresPerMemsetOptSize : 32;
1248
1252 Subtarget->requiresStrictAlign() ? MaxStoresPerMemcpyOptSize : 16;
1253
1256 Subtarget->requiresStrictAlign() ? MaxStoresPerMemmoveOptSize : 16;
1257
1260 Subtarget->requiresStrictAlign() ? MaxLoadsPerMemcmpOptSize : 8;
1261
1263
1265
1266 EnableExtLdPromotion = true;
1267
1268 // Set required alignment.
1270 // Set preferred alignments.
1271
1272 // Don't align loops on Windows. The SEH unwind info generation needs to
1273 // know the exact length of functions before the alignments have been
1274 // expanded.
1275 if (!Subtarget->isTargetWindows())
1279
1280 // Only change the limit for entries in a jump table if specified by
1281 // the sub target, but not at the command line.
1282 unsigned MaxJT = STI.getMaximumJumpTableSize();
1283 if (MaxJT && getMaximumJumpTableSize() == UINT_MAX)
1285
1287
1289
1291 if (Subtarget->hasSME())
1293
1294 if (Subtarget->isNeonAvailable()) {
1295 // FIXME: v1f64 shouldn't be legal if we can avoid it, because it leads to
1296 // silliness like this:
1297 // clang-format off
1298 for (auto Op :
1319 setOperationAction(Op, MVT::v1f64, Expand);
1320 // clang-format on
1321
1322 for (auto Op :
1327 setOperationAction(Op, MVT::v1i64, Expand);
1328
1329 // AArch64 doesn't have a direct vector ->f32 conversion instructions for
1330 // elements smaller than i32, so promote the input to i32 first.
1331 setOperationPromotedToType(ISD::UINT_TO_FP, MVT::v4i8, MVT::v4i32);
1332 setOperationPromotedToType(ISD::SINT_TO_FP, MVT::v4i8, MVT::v4i32);
1333
1334 // Similarly, there is no direct i32 -> f64 vector conversion instruction.
1335 // Or, direct i32 -> f16 vector conversion. Set it so custom, so the
1336 // conversion happens in two steps: v4i32 -> v4f32 -> v4f16
1339 for (auto VT : {MVT::v2i32, MVT::v2i64, MVT::v4i32})
1341
1342 if (Subtarget->hasFullFP16()) {
1345
1354 } else {
1355 // when AArch64 doesn't have fullfp16 support, promote the input
1356 // to i32 first.
1357 setOperationPromotedToType(ISD::SINT_TO_FP, MVT::v8i8, MVT::v8i32);
1358 setOperationPromotedToType(ISD::UINT_TO_FP, MVT::v8i8, MVT::v8i32);
1359 setOperationPromotedToType(ISD::UINT_TO_FP, MVT::v16i8, MVT::v16i32);
1360 setOperationPromotedToType(ISD::SINT_TO_FP, MVT::v16i8, MVT::v16i32);
1361 setOperationPromotedToType(ISD::UINT_TO_FP, MVT::v4i16, MVT::v4i32);
1362 setOperationPromotedToType(ISD::SINT_TO_FP, MVT::v4i16, MVT::v4i32);
1363 setOperationPromotedToType(ISD::SINT_TO_FP, MVT::v8i16, MVT::v8i32);
1364 setOperationPromotedToType(ISD::UINT_TO_FP, MVT::v8i16, MVT::v8i32);
1365 }
1366
1367 setOperationAction(ISD::CTLZ, MVT::v1i64, Expand);
1368 setOperationAction(ISD::CTLZ, MVT::v2i64, Expand);
1369 // CTLS (Count Leading Sign bits) - Legal for BHS types (8/16/32-bit
1370 // elements) No hardware support for 64-bit element vectors
1371 for (auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
1372 MVT::v4i32})
1380 for (auto VT : {MVT::v1i64, MVT::v2i64}) {
1385 }
1386
1387 // Custom handling for some quad-vector types to detect MULL.
1388 setOperationAction(ISD::MUL, MVT::v8i16, Custom);
1389 setOperationAction(ISD::MUL, MVT::v4i32, Custom);
1390 setOperationAction(ISD::MUL, MVT::v2i64, Custom);
1391 setOperationAction(ISD::MUL, MVT::v4i16, Custom);
1392 setOperationAction(ISD::MUL, MVT::v2i32, Custom);
1393 setOperationAction(ISD::MUL, MVT::v1i64, Custom);
1394
1395 // Saturates
1396 for (MVT VT : { MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v1i64,
1397 MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64 }) {
1402 }
1403
1404 for (MVT VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
1405 MVT::v4i32}) {
1412 }
1413
1414 // Vector reductions
1415 for (MVT VT : { MVT::v4f16, MVT::v2f32,
1416 MVT::v8f16, MVT::v4f32, MVT::v2f64 }) {
1417 if (VT.getVectorElementType() != MVT::f16 || Subtarget->hasFullFP16()) {
1422
1424 }
1425 }
1426 if (Subtarget->hasFullFP16())
1428
1429 for (MVT VT : { MVT::v8i8, MVT::v4i16, MVT::v2i32,
1430 MVT::v16i8, MVT::v8i16, MVT::v4i32 }) {
1439 }
1444
1445 for (MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v2i32, MVT::v4i32})
1447
1449 setTruncStoreAction(MVT::v2i32, MVT::v2i16, Expand);
1450 // Likewise, narrowing and extending vector loads/stores aren't handled
1451 // directly.
1454
1455 if (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32) {
1458 } else {
1461 }
1464
1465 if (VT == MVT::v4i16 || VT == MVT::v8i16 || VT == MVT::v2i32 ||
1466 VT == MVT::v4i32 || VT == MVT::v2i64)
1468 else
1470
1471 if (VT == MVT::v8i8 || VT == MVT::v16i8 || VT == MVT::v8i16 ||
1472 VT == MVT::v4i16 || VT == MVT::v2i32 || VT == MVT::v4i32)
1474 else
1476
1477 for (MVT InnerVT : MVT::fixedlen_vector_valuetypes()) {
1478 setTruncStoreAction(VT, InnerVT, Expand);
1479 setLoadExtAction(ISD::SEXTLOAD, VT, InnerVT, Expand);
1480 setLoadExtAction(ISD::ZEXTLOAD, VT, InnerVT, Expand);
1481 setLoadExtAction(ISD::EXTLOAD, VT, InnerVT, Expand);
1482 }
1483 }
1484
1485 for (auto Op :
1491 for (MVT Ty : {MVT::v2f32, MVT::v4f32, MVT::v2f64})
1493 if (Subtarget->hasFullFP16())
1494 for (MVT Ty : {MVT::v4f16, MVT::v8f16})
1496 }
1497
1498 // LRINT and LLRINT.
1499 for (auto Op : {ISD::LRINT, ISD::LLRINT}) {
1500 for (MVT Ty : {MVT::v2f32, MVT::v4f32, MVT::v2f64})
1502 if (Subtarget->hasFullFP16())
1503 for (MVT Ty : {MVT::v4f16, MVT::v8f16})
1505 }
1506
1507 setTruncStoreAction(MVT::v4i16, MVT::v4i8, Custom);
1508
1513
1517
1518 setLoadExtAction(ISD::EXTLOAD, MVT::v2i32, MVT::v2i8, Custom);
1519 setLoadExtAction(ISD::SEXTLOAD, MVT::v2i32, MVT::v2i8, Custom);
1520 setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i32, MVT::v2i8, Custom);
1521 setLoadExtAction(ISD::EXTLOAD, MVT::v2i64, MVT::v2i8, Custom);
1522 setLoadExtAction(ISD::SEXTLOAD, MVT::v2i64, MVT::v2i8, Custom);
1523 setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i64, MVT::v2i8, Custom);
1524 setLoadExtAction(ISD::EXTLOAD, MVT::v4i16, MVT::v4i8, Custom);
1525 setLoadExtAction(ISD::SEXTLOAD, MVT::v4i16, MVT::v4i8, Custom);
1526 setLoadExtAction(ISD::ZEXTLOAD, MVT::v4i16, MVT::v4i8, Custom);
1527 setLoadExtAction(ISD::EXTLOAD, MVT::v4i32, MVT::v4i8, Custom);
1528 setLoadExtAction(ISD::SEXTLOAD, MVT::v4i32, MVT::v4i8, Custom);
1529 setLoadExtAction(ISD::ZEXTLOAD, MVT::v4i32, MVT::v4i8, Custom);
1530 setLoadExtAction(ISD::EXTLOAD, MVT::v2i32, MVT::v2i16, Custom);
1531 setLoadExtAction(ISD::SEXTLOAD, MVT::v2i32, MVT::v2i16, Custom);
1532 setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i32, MVT::v2i16, Custom);
1533 setLoadExtAction(ISD::EXTLOAD, MVT::v2i64, MVT::v2i16, Custom);
1534 setLoadExtAction(ISD::SEXTLOAD, MVT::v2i64, MVT::v2i16, Custom);
1535 setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i64, MVT::v2i16, Custom);
1536
1537 // ADDP custom lowering
1538 for (MVT VT : { MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64 })
1540 // FADDP custom lowering
1541 for (MVT VT : { MVT::v16f16, MVT::v8f32, MVT::v4f64 })
1543
1544 // Two-way integer ``pure'' add reductions lower to a [SU]ADALP.
1545 {
1546 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
1548 setPartialReduceMLAAction(MLAOps, MVT::v4i16, MVT::v8i8, Custom);
1549 setPartialReduceMLAAction(MLAOps, MVT::v2i32, MVT::v4i16, Custom);
1550 setPartialReduceMLAAction(MLAOps, MVT::v1i64, MVT::v2i32, Custom);
1551 setPartialReduceMLAAction(MLAOps, MVT::v8i16, MVT::v16i8, Custom);
1552 setPartialReduceMLAAction(MLAOps, MVT::v4i32, MVT::v8i16, Custom);
1553 setPartialReduceMLAAction(MLAOps, MVT::v2i64, MVT::v4i32, Custom);
1554 }
1555
1556 if (Subtarget->hasDotProd()) {
1557 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
1559
1560 setPartialReduceMLAAction(MLAOps, MVT::v4i32, MVT::v16i8, Legal);
1561 setPartialReduceMLAAction(MLAOps, MVT::v2i32, MVT::v8i8, Legal);
1562 setPartialReduceMLAAction(MLAOps, MVT::v2i32, MVT::v16i8, Custom);
1563 setPartialReduceMLAAction(MLAOps, MVT::v2i64, MVT::v16i8, Custom);
1564
1565 // v2i64/v16i8 SUMLA always reduces to v4i32 SUMLA via
1566 // LowerPARTIAL_REDUCE_MLA, regardless of i8mm; v2i32/v16i8 SUMLA goes
1567 // through the same widen-to-v4i32 path as the SMLA/UMLA cases above.
1569 MVT::v16i8, Custom);
1571 MVT::v16i8, Custom);
1572
1573 if (Subtarget->hasMatMulInt8()) {
1575 MVT::v16i8, Legal);
1577 MVT::v8i8, Legal);
1578 } else {
1579 // Native dotprod without i8mm: lower SUMLA to two UDOT products in
1580 // LowerPARTIAL_REDUCE_MLA.
1582 MVT::v16i8, Custom);
1584 MVT::v8i8, Custom);
1585 }
1586 }
1587
1588 if (Subtarget->hasF16F32DOT() || Subtarget->hasFP16FML()) {
1590 MVT::v4f16, Legal);
1592 MVT::v8f16, Legal);
1593 }
1594
1595 if (Subtarget->hasBF16())
1597 MVT::v8bf16, Legal);
1598
1600 setOperationAction(ISD::CLMUL, {MVT::v8i8, MVT::v16i8}, Legal);
1601 if (Subtarget->hasAES()) {
1602 setOperationAction(ISD::CLMUL, {MVT::i16, MVT::i32, MVT::i64, MVT::v4i32},
1603 Custom);
1604 setOperationAction(ISD::CLMUL, {MVT::v1i64, MVT::v2i64}, Legal);
1605 setOperationAction(ISD::CLMULH, {MVT::v1i64, MVT::v2i64}, Legal);
1606 }
1607
1608 } else /* !isNeonAvailable */ {
1610 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op)
1612
1613 if (VT.is128BitVector() || VT.is64BitVector()) {
1617 Subtarget->isLittleEndian() ? Legal : Expand);
1618 }
1619 for (MVT InnerVT : MVT::fixedlen_vector_valuetypes()) {
1620 setTruncStoreAction(VT, InnerVT, Expand);
1621 setLoadExtAction(ISD::SEXTLOAD, VT, InnerVT, Expand);
1622 setLoadExtAction(ISD::ZEXTLOAD, VT, InnerVT, Expand);
1623 setLoadExtAction(ISD::EXTLOAD, VT, InnerVT, Expand);
1624 }
1625 }
1626 }
1627
1628 for (MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
1632 }
1633
1635
1636 // FIXME: Move lowering for more nodes here if those are common between
1637 // SVE and SME.
1638 if (Subtarget->isSVEorStreamingSVEAvailable()) {
1639 for (auto VT :
1640 {MVT::nxv16i1, MVT::nxv8i1, MVT::nxv4i1, MVT::nxv2i1, MVT::nxv1i1}) {
1645 }
1646 for (auto VT : {MVT::nxv16i1, MVT::nxv8i1, MVT::nxv4i1, MVT::nxv2i1}) {
1648 Custom);
1651 }
1652
1653 if (Subtarget->hasSVE2() && Subtarget->isSVEAvailable()) {
1654 for (MVT VT : {MVT::nxv16i1, MVT::nxv8i1})
1656
1657 for (MVT VT : {MVT::v16i1, MVT::v8i1, MVT::v16i8, MVT::v8i8})
1659 }
1660
1662
1663 if (Subtarget->isSVEorStreamingSVEAvailable() &&
1664 (Subtarget->hasSVE2p1() || Subtarget->hasSME2()))
1666
1667 for (auto VT : {MVT::v16i8, MVT::v8i8, MVT::v4i16, MVT::v2i32})
1669
1670 for (auto VT : {MVT::v8f16, MVT::v4f32, MVT::v2f64})
1672 }
1673
1674 if (Subtarget->isSVEorStreamingSVEAvailable()) {
1675 for (auto VT : {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32, MVT::nxv2i64}) {
1721
1727
1736
1741
1745
1746 if (!Subtarget->isLittleEndian())
1748
1749 if (Subtarget->hasSVE2() ||
1750 (Subtarget->hasSME() && Subtarget->isStreaming()))
1751 // For SLI/SRI.
1753 }
1754
1755 for (auto VT : {MVT::nxv4i32, MVT::nxv2i64}) {
1758 }
1759
1760 // Illegal unpacked integer vector types.
1761 for (auto VT : {MVT::nxv8i8, MVT::nxv4i16, MVT::nxv2i32}) {
1764 }
1765
1766 // Type legalize unpacked bitcasts.
1767 for (auto VT : {MVT::nxv2i16, MVT::nxv4i16, MVT::nxv2i32})
1769
1770 for (auto VT :
1771 { MVT::nxv2i8, MVT::nxv2i16, MVT::nxv2i32, MVT::nxv2i64, MVT::nxv4i8,
1772 MVT::nxv4i16, MVT::nxv4i32, MVT::nxv8i8, MVT::nxv8i16 })
1774
1775 // Promote predicate as counter load/stores to standard predicates.
1776 setOperationPromotedToType(ISD::LOAD, MVT::aarch64svcount, MVT::nxv16i1);
1777 setOperationPromotedToType(ISD::STORE, MVT::aarch64svcount, MVT::nxv16i1);
1778
1779 // Predicate as counter legalization actions.
1780 setOperationAction(ISD::SELECT, MVT::aarch64svcount, Custom);
1781 setOperationAction(ISD::SELECT_CC, MVT::aarch64svcount, Expand);
1782
1783 for (auto VT :
1784 {MVT::nxv16i1, MVT::nxv8i1, MVT::nxv4i1, MVT::nxv2i1, MVT::nxv1i1}) {
1792
1796
1797 // There are no legal MVT::nxv16f## based types.
1798 if (VT != MVT::nxv16i1) {
1803 }
1804 }
1805
1806 // NEON doesn't support masked loads/stores, but SME and SVE do.
1807 for (auto VT :
1808 {MVT::v4f16, MVT::v8f16, MVT::v4bf16, MVT::v8bf16, MVT::v2f32,
1809 MVT::v4f32, MVT::v1f64, MVT::v2f64, MVT::v8i8, MVT::v16i8, MVT::v4i16,
1810 MVT::v8i16, MVT::v2i32, MVT::v4i32, MVT::v1i64, MVT::v2i64}) {
1813 }
1814
1815 // Firstly, exclude all scalable vector extending loads/truncating stores,
1816 // include both integer and floating scalable vector.
1818 for (MVT InnerVT : MVT::scalable_vector_valuetypes()) {
1819 setTruncStoreAction(VT, InnerVT, Expand);
1820 setLoadExtAction(ISD::SEXTLOAD, VT, InnerVT, Expand);
1821 setLoadExtAction(ISD::ZEXTLOAD, VT, InnerVT, Expand);
1822 setLoadExtAction(ISD::EXTLOAD, VT, InnerVT, Expand);
1823 }
1824 }
1825
1826 // Then, selectively enable those which we directly support.
1827 setTruncStoreAction(MVT::nxv2i64, MVT::nxv2i8, Legal);
1828 setTruncStoreAction(MVT::nxv2i64, MVT::nxv2i16, Legal);
1829 setTruncStoreAction(MVT::nxv2i64, MVT::nxv2i32, Legal);
1830 setTruncStoreAction(MVT::nxv4i32, MVT::nxv4i8, Legal);
1831 setTruncStoreAction(MVT::nxv4i32, MVT::nxv4i16, Legal);
1832 setTruncStoreAction(MVT::nxv8i16, MVT::nxv8i8, Legal);
1833 for (auto Op : {ISD::ZEXTLOAD, ISD::SEXTLOAD, ISD::EXTLOAD}) {
1834 setLoadExtAction(Op, MVT::nxv2i64, MVT::nxv2i8, Legal);
1835 setLoadExtAction(Op, MVT::nxv2i64, MVT::nxv2i16, Legal);
1836 setLoadExtAction(Op, MVT::nxv2i64, MVT::nxv2i32, Legal);
1837 setLoadExtAction(Op, MVT::nxv4i32, MVT::nxv4i8, Legal);
1838 setLoadExtAction(Op, MVT::nxv4i32, MVT::nxv4i16, Legal);
1839 setLoadExtAction(Op, MVT::nxv8i16, MVT::nxv8i8, Legal);
1840 }
1841
1842 // SVE supports truncating stores of 64 and 128-bit vectors
1843 setTruncStoreAction(MVT::v2i64, MVT::v2i8, Custom);
1844 setTruncStoreAction(MVT::v2i64, MVT::v2i16, Custom);
1845 setTruncStoreAction(MVT::v2i32, MVT::v2i8, Custom);
1846 setTruncStoreAction(MVT::v2i32, MVT::v2i16, Custom);
1847
1848 for (auto VT : {MVT::nxv2f16, MVT::nxv4f16, MVT::nxv8f16, MVT::nxv2f32,
1849 MVT::nxv4f32, MVT::nxv2f64}) {
1894
1917
1918 // TODO: These require custom lowering.
1935
1947 }
1948
1949 for (auto VT : {MVT::nxv2bf16, MVT::nxv4bf16, MVT::nxv8bf16}) {
1966 }
1967
1968 if (Subtarget->hasSVEB16B16() &&
1969 Subtarget->isNonStreamingSVEorSME2Available()) {
1970 // Note: Use SVE for bfloat16 operations when +sve-b16b16 is available.
1971 for (auto VT : {MVT::v4bf16, MVT::v8bf16, MVT::nxv2bf16, MVT::nxv4bf16,
1972 MVT::nxv8bf16}) {
1981 }
1982 }
1983
1984 for (auto Opcode :
1989 setOperationPromotedToType(Opcode, MVT::nxv2bf16, MVT::nxv2f32);
1990 setOperationPromotedToType(Opcode, MVT::nxv4bf16, MVT::nxv4f32);
1991 setOperationPromotedToType(Opcode, MVT::nxv8bf16, MVT::nxv8f32);
1992 }
1993
1994 if (!Subtarget->hasSVEB16B16() ||
1995 !Subtarget->isNonStreamingSVEorSME2Available()) {
1996 for (MVT VT : {MVT::nxv2bf16, MVT::nxv4bf16, MVT::nxv8bf16}) {
1997 MVT PromotedVT = VT.changeVectorElementType(MVT::f32);
1998 setOperationPromotedToType(ISD::FADD, VT, PromotedVT);
1999 setOperationPromotedToType(ISD::FMA, VT, PromotedVT);
2004 setOperationPromotedToType(ISD::FSUB, VT, PromotedVT);
2005
2006 if (VT != MVT::nxv2bf16 && Subtarget->hasBF16())
2008 else
2009 setOperationPromotedToType(ISD::FMUL, VT, PromotedVT);
2010 }
2011
2012 if (Subtarget->hasBF16() && Subtarget->isNeonAvailable())
2013 setOperationAction(ISD::FMUL, MVT::v8bf16, Custom);
2014 }
2015
2018
2019 // A number of operations like MULH and integer divides are not supported by
2020 // NEON but are available in SVE.
2021 for (auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
2022 MVT::v4i32, MVT::v1i64, MVT::v2i64}) {
2029 }
2030
2031 for (auto VT : {MVT::v4i16, MVT::v8i16, MVT::v2i32, MVT::v4i32, MVT::v1i64,
2032 MVT::v2i64})
2034
2035 // NEON doesn't support 64-bit vector integer muls, but SVE does.
2036 setOperationAction(ISD::MUL, MVT::v1i64, Custom);
2037 setOperationAction(ISD::MUL, MVT::v2i64, Custom);
2038
2039 // NEON doesn't support 128-bit [s|u][min|max] operations, but SVE does.
2044
2045 for (auto VT : {MVT::v1i64, MVT::v2i64}) {
2048 }
2049
2050 // NOTE: Currently this has to happen after computeRegisterProperties rather
2051 // than the preferred option of combining it with the addRegisterClass call.
2052 if (Subtarget->useSVEForFixedLengthVectors()) {
2055 VT, /*OverrideNEON=*/!Subtarget->isNeonAvailable()))
2056 addTypeForFixedLengthSVE(VT);
2057 }
2060 VT, /*OverrideNEON=*/!Subtarget->isNeonAvailable()))
2061 addTypeForFixedLengthSVE(VT);
2062 }
2063
2064 // 64bit results can mean a bigger than NEON input.
2065 for (auto VT : {MVT::v8i8, MVT::v4i16})
2068
2069 // 128bit results imply a bigger than NEON input.
2070 for (auto VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
2072 for (auto VT : {MVT::v8f16, MVT::v4f32, MVT::v8bf16})
2074
2075 // These operations are not supported on NEON but SVE can do them.
2076 setOperationAction(ISD::SMAX, MVT::v1i64, Custom);
2077 setOperationAction(ISD::SMAX, MVT::v2i64, Custom);
2078 setOperationAction(ISD::SMIN, MVT::v1i64, Custom);
2079 setOperationAction(ISD::SMIN, MVT::v2i64, Custom);
2080 setOperationAction(ISD::UMAX, MVT::v1i64, Custom);
2081 setOperationAction(ISD::UMAX, MVT::v2i64, Custom);
2082 setOperationAction(ISD::UMIN, MVT::v1i64, Custom);
2083 setOperationAction(ISD::UMIN, MVT::v2i64, Custom);
2088
2089 // Int operations with no NEON support.
2090 for (auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
2091 MVT::v4i32, MVT::v2i64}) {
2095 }
2096
2097 // Use SVE for vectors with more than 2 elements.
2098 for (auto VT : {MVT::v4f16, MVT::v8f16, MVT::v4f32})
2100 }
2101
2103 MVT::nxv2i64);
2105 MVT::nxv2i64);
2107 MVT::nxv4i32);
2109 MVT::nxv4i32);
2111 MVT::nxv8i16);
2113 MVT::nxv8i16);
2115 MVT::nxv16i8);
2117 MVT::nxv16i8);
2118
2120
2121 for (auto VT : {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1})
2124 VT, Custom);
2125
2126 // Without SubReg Liveness the multi-vector instructions can introduce
2127 // unnecessary COPY and/or MOVPFRX instructions.
2128 if (Subtarget->enableSubRegLiveness() &&
2129 (Subtarget->hasSVE2p1() ||
2130 (Subtarget->hasSME2() && Subtarget->isStreaming()))) {
2131
2132 for (unsigned Opcode : {ISD::LOAD, ISD::STORE}) {
2133 // 2x multi-vector load/stores
2134 setOperationAction(Opcode, MVT::nxv32i8, Custom);
2135 setOperationAction(Opcode, MVT::nxv16i16, Custom);
2136 setOperationAction(Opcode, MVT::nxv8i32, Custom);
2137 setOperationAction(Opcode, MVT::nxv4i64, Custom);
2138 setOperationAction(Opcode, MVT::nxv16f16, Custom);
2139 setOperationAction(Opcode, MVT::nxv8f32, Custom);
2140 setOperationAction(Opcode, MVT::nxv4f64, Custom);
2141 setOperationAction(Opcode, MVT::nxv16bf16, Custom);
2142
2143 // 4x multi-vector load/stores
2144 setOperationAction(Opcode, MVT::nxv64i8, Custom);
2145 setOperationAction(Opcode, MVT::nxv32i16, Custom);
2146 setOperationAction(Opcode, MVT::nxv16i32, Custom);
2147 setOperationAction(Opcode, MVT::nxv8i64, Custom);
2148 setOperationAction(Opcode, MVT::nxv32f16, Custom);
2149 setOperationAction(Opcode, MVT::nxv16f32, Custom);
2150 setOperationAction(Opcode, MVT::nxv8f64, Custom);
2151 setOperationAction(Opcode, MVT::nxv32bf16, Custom);
2152 }
2153 }
2154 }
2155
2156 // Handle partial reduction operations
2157 if (Subtarget->isSVEorStreamingSVEAvailable()) {
2158 // Mark known legal pairs as 'Legal' (these will expand to UDOT or SDOT).
2159 // Other pairs will default to 'Expand'.
2160 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
2162 setPartialReduceMLAAction(MLAOps, MVT::nxv2i64, MVT::nxv8i16, Legal);
2163 setPartialReduceMLAAction(MLAOps, MVT::nxv4i32, MVT::nxv16i8, Legal);
2164
2165 setPartialReduceMLAAction(MLAOps, MVT::nxv2i64, MVT::nxv16i8, Custom);
2166
2167 if (Subtarget->hasMatMulInt8()) {
2169 MVT::nxv16i8, Legal);
2171 MVT::nxv16i8, Custom);
2172 }
2173
2174 if (Subtarget->hasSVE2() || Subtarget->hasSME()) {
2175 // Wide add types
2176 setPartialReduceMLAAction(MLAOps, MVT::nxv2i64, MVT::nxv4i32, Legal);
2177 setPartialReduceMLAAction(MLAOps, MVT::nxv4i32, MVT::nxv8i16, Legal);
2178 setPartialReduceMLAAction(MLAOps, MVT::nxv8i16, MVT::nxv16i8, Legal);
2179
2180 setOperationAction(ISD::CLMUL, {MVT::nxv16i8, MVT::nxv4i32}, Legal);
2181 setOperationAction(ISD::CLMUL, MVT::nxv8i16, Custom);
2182
2184 MVT::nxv8f16, Legal);
2185
2186 // We can use SVE2p1 fdot or SVE2 fmlalb/t to emulate the fixed-length
2187 // variant (unless NEON fdot is natively available).
2188 if (!Subtarget->isNeonAvailable() ||
2189 (!Subtarget->hasF16F32DOT() && !Subtarget->hasFP16FML())) {
2191 MVT::v8f16, Custom);
2193 MVT::v4f16, Custom);
2194 }
2195 }
2196
2197 // Map generic PEXT/PDEP to SVE2 bitperm BEXT/BDEP instructions.
2198 if (Subtarget->hasSVEBitPerm() &&
2199 (Subtarget->isSVEAvailable() ||
2200 (Subtarget->isSVEorStreamingSVEAvailable() &&
2201 Subtarget->hasSSVE_BitPerm()))) {
2202 for (auto VT : {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32, MVT::nxv2i64}) {
2204 }
2207 }
2208
2209 if (Subtarget->hasBF16())
2211 MVT::nxv8bf16, Legal);
2212 setOperationAction(ISD::CLMUL, MVT::nxv2i64, Custom);
2213 }
2214
2215 if (Subtarget->isSVEAvailable() ||
2216 (Subtarget->isSVEorStreamingSVEAvailable() && Subtarget->hasSME2p2())) {
2217 // We can lower types that have <vscale x {2|4}> elements to compact.
2218 for (auto VT :
2219 {MVT::nxv4i32, MVT::nxv2i64, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv2f64})
2221
2222 // If we have SVE, we can use SVE logic for legal NEON vectors in the lowest
2223 // bits of the SVE register.
2224 for (auto VT : {MVT::v2i32, MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32,
2225 MVT::v2f64})
2227
2228 if (Subtarget->hasSVE2p2() || Subtarget->hasSME2p2()) {
2229 // With +sve2p2/+sme2p2 the full range of vector types are supported.
2230 for (auto VT : {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv8f16, MVT::nxv8bf16})
2232
2233 for (auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v4f16,
2234 MVT::v8f16, MVT::v4bf16, MVT::v8bf16})
2236 } else {
2237 // Promote v4i16/f16 to v4i32/f32 as the SVE container for v4i16 is nxv8,
2238 // which is not supported with for compact (with only +sve).
2239 setOperationPromotedToType(ISD::VECTOR_COMPRESS, MVT::v4bf16, MVT::v4i16);
2240 setOperationPromotedToType(ISD::VECTOR_COMPRESS, MVT::v4f16, MVT::v4i16);
2241 setOperationPromotedToType(ISD::VECTOR_COMPRESS, MVT::v4i16, MVT::v4i32);
2242 }
2243 }
2244
2245 // Handle non-aliasing elements mask
2246 if (Subtarget->hasSVE2() ||
2247 (Subtarget->hasSME() && Subtarget->isStreaming())) {
2248 // FIXME: Support wider fixed-length types when msve-vector-bits is used.
2249 for (auto VT : {MVT::v2i32, MVT::v4i16, MVT::v8i8, MVT::v16i8}) {
2252 }
2253 for (auto VT : {MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1, MVT::nxv16i1}) {
2256 }
2257 }
2258
2259 // Handle operations that are only available in non-streaming SVE mode.
2260 if (Subtarget->isSVEAvailable()) {
2261 for (auto VT : {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32, MVT::nxv2i64,
2262 MVT::nxv2f16, MVT::nxv4f16, MVT::nxv8f16, MVT::nxv2f32,
2263 MVT::nxv4f32, MVT::nxv2f64, MVT::nxv2bf16, MVT::nxv4bf16,
2264 MVT::nxv8bf16, MVT::v4f16, MVT::v8f16, MVT::v4bf16,
2265 MVT::v8bf16, MVT::v2f32, MVT::v4f32, MVT::v1f64,
2266 MVT::v2f64, MVT::v8i8, MVT::v16i8, MVT::v4i16,
2267 MVT::v8i16, MVT::v2i32, MVT::v4i32, MVT::v1i64,
2268 MVT::v2i64}) {
2271 }
2272
2273 for (auto VT : {MVT::nxv2f16, MVT::nxv4f16, MVT::nxv8f16, MVT::nxv2f32,
2274 MVT::nxv4f32, MVT::nxv2f64, MVT::v4f16, MVT::v8f16,
2275 MVT::v2f32, MVT::v4f32, MVT::v2f64})
2277
2278 for (auto VT : {MVT::nxv2i8, MVT::nxv2i16, MVT::nxv2i32, MVT::nxv2i64,
2279 MVT::nxv2f32, MVT::nxv2f64, MVT::nxv4i8, MVT::nxv4i16,
2280 MVT::nxv4i32, MVT::nxv4f32}) {
2281 // Use a custom lowering for masked stores that could be a supported
2282 // compressing store. Note: These types still use the normal (Legal)
2283 // lowering for non-compressing masked stores.
2285 }
2286
2287 // Histcnt is SVE2 only
2288 if (Subtarget->hasSVE2()) {
2290 Custom);
2292 Custom);
2293
2294 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
2296 // Must be lowered to SVE instructions.
2297 setPartialReduceMLAAction(MLAOps, MVT::v2i64, MVT::v4i32, Custom);
2298 setPartialReduceMLAAction(MLAOps, MVT::v2i64, MVT::v8i16, Custom);
2299 setPartialReduceMLAAction(MLAOps, MVT::v2i64, MVT::v16i8, Custom);
2300 setPartialReduceMLAAction(MLAOps, MVT::v4i32, MVT::v8i16, Custom);
2301 setPartialReduceMLAAction(MLAOps, MVT::v4i32, MVT::v16i8, Custom);
2302 setPartialReduceMLAAction(MLAOps, MVT::v8i16, MVT::v16i8, Custom);
2303 }
2304 }
2305
2306 if (Subtarget->hasMOPS() && Subtarget->hasMTE()) {
2307 // Only required for llvm.aarch64.mops.memset.tag
2309 }
2310
2312
2313 if (Subtarget->hasSVE()) {
2318 }
2319
2320 PredictableSelectIsExpensive = Subtarget->predictableSelectIsExpensive();
2321
2322 IsStrictFPEnabled = true;
2324
2325 // On MSVC, both 32-bit and 64-bit, ldexpf(f32) is not defined. MinGW has
2326 // it, but it's just a wrapper around ldexp.
2327 if (Subtarget->isTargetWindows()) {
2329 if (isOperationExpand(Op, MVT::f32))
2330 setOperationAction(Op, MVT::f32, Promote);
2331 }
2332
2333 // LegalizeDAG currently can't expand fp16/bf16 LDEXP/FREXP on targets where
2334 // i16 isn't legal.
2336 if (isOperationExpand(Op, MVT::f16))
2337 setOperationAction(Op, MVT::f16, Promote);
2338 if (isOperationExpand(Op, MVT::bf16))
2339 setOperationAction(Op, MVT::bf16, Promote);
2340 }
2341}
2342
2344 return static_cast<const AArch64TargetMachine &>(getTargetMachine());
2345}
2346
2347void AArch64TargetLowering::addTypeForNEON(MVT VT) {
2348 assert(VT.isVector() && "VT should be a vector type");
2349
2350 if (VT.isFloatingPoint()) {
2352 setOperationPromotedToType(ISD::LOAD, VT, PromoteTo);
2353 setOperationPromotedToType(ISD::STORE, VT, PromoteTo);
2354 }
2355
2356 // Mark vector float intrinsics as expand.
2357 if (VT == MVT::v2f32 || VT == MVT::v4f32 || VT == MVT::v2f64) {
2376 }
2377
2378 // But we do support custom-lowering for FCOPYSIGN.
2379 if (VT == MVT::v2f32 || VT == MVT::v4f32 || VT == MVT::v2f64 ||
2380 ((VT == MVT::v4bf16 || VT == MVT::v8bf16 || VT == MVT::v4f16 ||
2381 VT == MVT::v8f16) &&
2382 Subtarget->hasFullFP16()))
2384
2399
2403 for (MVT InnerVT : MVT::all_valuetypes())
2404 setLoadExtAction(ISD::EXTLOAD, InnerVT, VT, Expand);
2405
2406 // CNT supports only B element sizes, then use UADDLP to widen.
2407 if (VT != MVT::v8i8 && VT != MVT::v16i8)
2409
2415
2416 for (unsigned Opcode :
2419 setOperationAction(Opcode, VT, Custom);
2420
2421 if (!VT.isFloatingPoint())
2423
2424 // [SU][MIN|MAX] are available for all NEON types apart from i64.
2425 if (!VT.isFloatingPoint() && VT != MVT::v2i64 && VT != MVT::v1i64)
2426 for (unsigned Opcode : {ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX})
2427 setOperationAction(Opcode, VT, Legal);
2428
2429 // F[MIN|MAX][NUM|NAN] and simple strict operations are available for all FP
2430 // NEON types.
2431 if (VT.isFloatingPoint() &&
2432 VT.getVectorElementType() != MVT::bf16 &&
2433 (VT.getVectorElementType() != MVT::f16 || Subtarget->hasFullFP16()))
2434 for (unsigned Opcode :
2440 setOperationAction(Opcode, VT, Legal);
2441
2442 // Strict fp extend and trunc are legal
2443 if (VT.isFloatingPoint() && VT.getScalarSizeInBits() != 16)
2445 if (VT.isFloatingPoint() && VT.getScalarSizeInBits() != 64)
2447
2448 // FIXME: We could potentially make use of the vector comparison instructions
2449 // for STRICT_FSETCC and STRICT_FSETCSS, but there's a number of
2450 // complications:
2451 // * FCMPEQ/NE are quiet comparisons, the rest are signalling comparisons,
2452 // so we would need to expand when the condition code doesn't match the
2453 // kind of comparison.
2454 // * Some kinds of comparison require more than one FCMXY instruction so
2455 // would need to be expanded instead.
2456 // * The lowering of the non-strict versions involves target-specific ISD
2457 // nodes so we would likely need to add strict versions of all of them and
2458 // handle them appropriately.
2461
2462 // When little-endian we can use ordinary d and q register loads/stores for
2463 // vector types, but when big-endian we need to use structure load/store which
2464 // only allow post-index addressing.
2465 // With +strict-align, we also need to use LD1/ST1 when the alignment is
2466 // less than the vector size, but we can still use LDR/STR for more-aligned
2467 // accesses, so these are marked as legal here, and the invalid cases are
2468 // rejected in getIndexedAddressParts.
2469 if (Subtarget->isLittleEndian()) {
2470 for (unsigned im = (unsigned)ISD::PRE_INC;
2471 im != (unsigned)ISD::LAST_INDEXED_MODE; ++im) {
2474 }
2475 } else {
2478 }
2479
2480 if (Subtarget->hasD128()) {
2483 }
2484
2485 if (VT.isInteger()) {
2486 // Let common code emit inverted variants of compares we do support.
2492 }
2493}
2494
2496 EVT OpVT) const {
2497 // Only SVE has a 1:1 mapping from intrinsic -> instruction (whilelo).
2498 if (!Subtarget->isSVEorStreamingSVEAvailable() ||
2499 ResVT.getVectorElementType() != MVT::i1)
2500 return true;
2501
2502 // Expand 1 length fixed length vector.
2503 if (ResVT.isFixedLengthVector() && ResVT.getVectorNumElements() == 1)
2504 return true;
2505
2506 // 32 & 64 bit operands are supported. We can promote anything < 64 bits,
2507 // but anything larger should be expanded.
2508 if (OpVT.getFixedSizeInBits() > 64)
2509 return true;
2510
2511 return false;
2512}
2513
2514void AArch64TargetLowering::addTypeForFixedLengthSVE(MVT VT) {
2515 assert(VT.isFixedLengthVector() && "Expected fixed length vector type!");
2516
2517 // By default everything must be expanded.
2518 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op)
2520
2521 if (VT.isFloatingPoint()) {
2531 }
2532
2534 VT == MVT::v1f64 ? Expand : Custom;
2535
2536 // Mark integer truncating stores/extending loads as having custom lowering
2537 if (VT.isInteger()) {
2538 MVT InnerVT = VT.changeVectorElementType(MVT::i8);
2539 while (InnerVT != VT) {
2540 setTruncStoreAction(VT, InnerVT, Default);
2541 setLoadExtAction(ISD::ZEXTLOAD, VT, InnerVT, Default);
2542 setLoadExtAction(ISD::SEXTLOAD, VT, InnerVT, Default);
2543 setLoadExtAction(ISD::EXTLOAD, VT, InnerVT, Default);
2544 InnerVT = InnerVT.changeVectorElementType(
2545 MVT::getIntegerVT(2 * InnerVT.getScalarSizeInBits()));
2546 }
2547 }
2548
2549 // Mark floating-point truncating stores/extending loads as having custom
2550 // lowering
2551 if (VT.getScalarType() == MVT::f32 || VT.getScalarType() == MVT::f64) {
2552 MVT InnerVT = VT.changeVectorElementType(MVT::f16);
2553 while (InnerVT != VT) {
2554 setTruncStoreAction(VT, InnerVT, Custom);
2555 setLoadExtAction(ISD::EXTLOAD, VT, InnerVT, Default);
2556 InnerVT = InnerVT.changeVectorElementType(
2558 }
2559 }
2560
2561 bool PreferNEON = VT.is64BitVector() || VT.is128BitVector();
2562 bool PreferSVE = !PreferNEON && Subtarget->isSVEAvailable();
2563
2564 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
2566 unsigned NumElts = VT.getVectorNumElements();
2567 if (VT.getVectorElementType() == MVT::i64) {
2568 setPartialReduceMLAAction(MLAOps, VT,
2569 MVT::getVectorVT(MVT::i8, NumElts * 8), Custom);
2570 setPartialReduceMLAAction(MLAOps, VT,
2571 MVT::getVectorVT(MVT::i16, NumElts * 4), Custom);
2572 setPartialReduceMLAAction(MLAOps, VT,
2573 MVT::getVectorVT(MVT::i32, NumElts * 2), Custom);
2574 } else if (VT.getVectorElementType() == MVT::i32) {
2575 setPartialReduceMLAAction(MLAOps, VT,
2576 MVT::getVectorVT(MVT::i8, NumElts * 4), Custom);
2577 setPartialReduceMLAAction(MLAOps, VT,
2578 MVT::getVectorVT(MVT::i16, NumElts * 2), Custom);
2579 } else if (VT.getVectorElementType() == MVT::i16) {
2580 setPartialReduceMLAAction(MLAOps, VT,
2581 MVT::getVectorVT(MVT::i8, NumElts * 2), Custom);
2582 }
2583 if (Subtarget->hasMatMulInt8()) {
2584 if (VT.getVectorElementType() == MVT::i32)
2586 MVT::getVectorVT(MVT::i8, NumElts * 4), Custom);
2587 else if (VT.getVectorElementType() == MVT::i64)
2589 MVT::getVectorVT(MVT::i8, NumElts * 8), Custom);
2590 }
2591
2592 if (Subtarget->hasSVE2p1() && VT.getVectorElementType() == MVT::f32) {
2594 MVT::getVectorVT(MVT::f16, NumElts * 2), Custom);
2595 }
2596
2597 // Lower fixed length vector operations to scalable equivalents.
2604 setOperationAction(ISD::BITCAST, VT, PreferNEON ? Legal : Default);
2647 setOperationAction(ISD::LOAD, VT, PreferNEON ? Legal : Default);
2650 setOperationAction(ISD::MGATHER, VT, PreferSVE ? Default : Expand);
2652 setOperationAction(ISD::MSCATTER, VT, PreferSVE ? Default : Expand);
2671 setOperationAction(ISD::STORE, VT, PreferNEON ? Legal : Default);
2698}
2699
2700void AArch64TargetLowering::addDRType(MVT VT) {
2701 addRegisterClass(VT, &AArch64::FPR64RegClass);
2702 if (Subtarget->isNeonAvailable())
2703 addTypeForNEON(VT);
2704}
2705
2706void AArch64TargetLowering::addQRType(MVT VT) {
2707 addRegisterClass(VT, &AArch64::FPR128RegClass);
2708 if (Subtarget->isNeonAvailable())
2709 addTypeForNEON(VT);
2710}
2711
2713 LLVMContext &C, EVT VT) const {
2714 if (!VT.isVector())
2715 return MVT::i32;
2716 if (VT.isScalableVector())
2717 return EVT::getVectorVT(C, MVT::i1, VT.getVectorElementCount());
2719}
2720
2721// isIntImmediate - This method tests to see if the node is a constant
2722// operand. If so Imm will receive the value.
2723static bool isIntImmediate(const SDNode *N, uint64_t &Imm) {
2725 Imm = C->getZExtValue();
2726 return true;
2727 }
2728 return false;
2729}
2730
2731static bool isVectorizedBinOp(unsigned Opcode) {
2732 switch (Opcode) {
2733 case AArch64ISD::SQDMULH:
2734 return true;
2735 default:
2736 return false;
2737 }
2738}
2739
2740// isOpcWithIntImmediate - This method tests to see if the node is a specific
2741// opcode and that it has a immediate integer right operand.
2742// If so Imm will receive the value.
2743static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc,
2744 uint64_t &Imm) {
2745 return N->getOpcode() == Opc &&
2746 isIntImmediate(N->getOperand(1).getNode(), Imm);
2747}
2748
2750 const APInt &Demanded,
2752 unsigned NewOpc) {
2753 uint64_t OldImm = Imm, NewImm, Enc;
2754 uint64_t Mask = ((uint64_t)(-1LL) >> (64 - Size)), OrigMask = Mask;
2755
2756 // Return if the immediate is already all zeros, all ones, a bimm32 or a
2757 // bimm64.
2758 if (Imm == 0 || Imm == Mask ||
2760 return false;
2761
2762 unsigned EltSize = Size;
2763 uint64_t DemandedBits = Demanded.getZExtValue();
2764
2765 // Clear bits that are not demanded.
2766 Imm &= DemandedBits;
2767
2768 while (true) {
2769 // The goal here is to set the non-demanded bits in a way that minimizes
2770 // the number of switching between 0 and 1. In order to achieve this goal,
2771 // we set the non-demanded bits to the value of the preceding demanded bits.
2772 // For example, if we have an immediate 0bx10xx0x1 ('x' indicates a
2773 // non-demanded bit), we copy bit0 (1) to the least significant 'x',
2774 // bit2 (0) to 'xx', and bit6 (1) to the most significant 'x'.
2775 // The final result is 0b11000011.
2776 uint64_t NonDemandedBits = ~DemandedBits;
2777 uint64_t InvertedImm = ~Imm & DemandedBits;
2778 uint64_t RotatedImm =
2779 ((InvertedImm << 1) | (InvertedImm >> (EltSize - 1) & 1)) &
2780 NonDemandedBits;
2781 uint64_t Sum = RotatedImm + NonDemandedBits;
2782 bool Carry = NonDemandedBits & ~Sum & (1ULL << (EltSize - 1));
2783 uint64_t Ones = (Sum + Carry) & NonDemandedBits;
2784 NewImm = (Imm | Ones) & Mask;
2785
2786 // If NewImm or its bitwise NOT is a shifted mask, it is a bitmask immediate
2787 // or all-ones or all-zeros, in which case we can stop searching. Otherwise,
2788 // we halve the element size and continue the search.
2789 if (isShiftedMask_64(NewImm) || isShiftedMask_64(~(NewImm | ~Mask)))
2790 break;
2791
2792 // We cannot shrink the element size any further if it is 2-bits.
2793 if (EltSize == 2)
2794 return false;
2795
2796 EltSize /= 2;
2797 Mask >>= EltSize;
2798 uint64_t Hi = Imm >> EltSize, DemandedBitsHi = DemandedBits >> EltSize;
2799
2800 // Return if there is mismatch in any of the demanded bits of Imm and Hi.
2801 if (((Imm ^ Hi) & (DemandedBits & DemandedBitsHi) & Mask) != 0)
2802 return false;
2803
2804 // Merge the upper and lower halves of Imm and DemandedBits.
2805 Imm |= Hi;
2806 DemandedBits |= DemandedBitsHi;
2807 }
2808
2809 ++NumOptimizedImms;
2810
2811 // Replicate the element across the register width.
2812 while (EltSize < Size) {
2813 NewImm |= NewImm << EltSize;
2814 EltSize *= 2;
2815 }
2816
2817 (void)OldImm;
2818 assert(((OldImm ^ NewImm) & Demanded.getZExtValue()) == 0 &&
2819 "demanded bits should never be altered");
2820 assert(OldImm != NewImm && "the new imm shouldn't be equal to the old imm");
2821
2822 // Create the new constant immediate node.
2823 EVT VT = Op.getValueType();
2824 SDLoc DL(Op);
2825 SDValue New;
2826
2827 // If the new constant immediate is all-zeros or all-ones, let the target
2828 // independent DAG combine optimize this node.
2829 if (NewImm == 0 || NewImm == OrigMask) {
2830 New = TLO.DAG.getNode(Op.getOpcode(), DL, VT, Op.getOperand(0),
2831 TLO.DAG.getConstant(NewImm, DL, VT));
2832 // Otherwise, create a machine node so that target independent DAG combine
2833 // doesn't undo this optimization.
2834 } else {
2836 SDValue EncConst = TLO.DAG.getTargetConstant(Enc, DL, VT);
2837 New = SDValue(
2838 TLO.DAG.getMachineNode(NewOpc, DL, VT, Op.getOperand(0), EncConst), 0);
2839 }
2840
2841 return TLO.CombineTo(Op, New);
2842}
2843
2845 SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts,
2846 TargetLoweringOpt &TLO) const {
2847 // Delay this optimization to as late as possible.
2848 if (!TLO.LegalOps)
2849 return false;
2850
2852 return false;
2853
2854 EVT VT = Op.getValueType();
2855 if (VT.isVector())
2856 return false;
2857
2858 unsigned Size = VT.getSizeInBits();
2859
2860 if (Size != 32 && Size != 64)
2861 return false;
2862
2863 // Exit early if we demand all bits.
2864 if (DemandedBits.isAllOnes())
2865 return false;
2866
2867 unsigned NewOpc;
2868 switch (Op.getOpcode()) {
2869 default:
2870 return false;
2871 case ISD::AND:
2872 NewOpc = Size == 32 ? AArch64::ANDWri : AArch64::ANDXri;
2873 break;
2874 case ISD::OR:
2875 NewOpc = Size == 32 ? AArch64::ORRWri : AArch64::ORRXri;
2876 break;
2877 case ISD::XOR:
2878 NewOpc = Size == 32 ? AArch64::EORWri : AArch64::EORXri;
2879 break;
2880 }
2881 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
2882 if (!C)
2883 return false;
2884 uint64_t Imm = C->getZExtValue();
2885 return optimizeLogicalImm(Op, Size, Imm, DemandedBits, TLO, NewOpc);
2886}
2887
2888/// computeKnownBitsForTargetNode - Determine which of the bits specified in
2889/// Mask are known to be either zero or one and return them Known.
2891 const SDValue Op, KnownBits &Known, const APInt &DemandedElts,
2892 const SelectionDAG &DAG, unsigned Depth) const {
2893 switch (Op.getOpcode()) {
2894 default:
2895 break;
2896 case AArch64ISD::DUP: {
2897 SDValue SrcOp = Op.getOperand(0);
2898 Known = DAG.computeKnownBits(SrcOp, Depth + 1);
2899 if (SrcOp.getValueSizeInBits() != Op.getScalarValueSizeInBits()) {
2900 assert(SrcOp.getValueSizeInBits() > Op.getScalarValueSizeInBits() &&
2901 "Expected DUP implicit truncation");
2902 Known = Known.trunc(Op.getScalarValueSizeInBits());
2903 }
2904 break;
2905 }
2906 case AArch64ISD::CSEL: {
2907 KnownBits Known2;
2908 Known = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
2909 Known2 = DAG.computeKnownBits(Op->getOperand(1), Depth + 1);
2910 Known = Known.intersectWith(Known2);
2911 break;
2912 }
2913 case AArch64ISD::CSNEG:
2914 case AArch64ISD::CSINC:
2915 case AArch64ISD::CSINV: {
2916 KnownBits KnownOp0 = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
2917 KnownBits KnownOp1 = DAG.computeKnownBits(Op->getOperand(1), Depth + 1);
2918
2919 // The result is either:
2920 // CSINC: KnownOp0 or KnownOp1 + 1
2921 // CSINV: KnownOp0 or ~KnownOp1
2922 // CSNEG: KnownOp0 or KnownOp1 * -1
2923 if (Op.getOpcode() == AArch64ISD::CSINC)
2924 KnownOp1 = KnownBits::add(
2925 KnownOp1,
2926 KnownBits::makeConstant(APInt(Op.getScalarValueSizeInBits(), 1)));
2927 else if (Op.getOpcode() == AArch64ISD::CSINV)
2928 std::swap(KnownOp1.Zero, KnownOp1.One);
2929 else if (Op.getOpcode() == AArch64ISD::CSNEG)
2930 KnownOp1 =
2932 Op.getScalarValueSizeInBits())));
2933
2934 Known = KnownOp0.intersectWith(KnownOp1);
2935 break;
2936 }
2937 case AArch64ISD::BICi: {
2938 // Compute the bit cleared value.
2939 APInt Mask =
2940 ~(Op->getConstantOperandAPInt(1) << Op->getConstantOperandAPInt(2))
2941 .trunc(Known.getBitWidth());
2942 Known = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
2944 break;
2945 }
2946 case AArch64ISD::VLSHR: {
2947 KnownBits Known2;
2948 Known = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
2949 Known2 = DAG.computeKnownBits(Op->getOperand(1), Depth + 1);
2950 Known = KnownBits::lshr(Known, Known2);
2951 break;
2952 }
2953 case AArch64ISD::VASHR: {
2954 KnownBits Known2;
2955 Known = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
2956 Known2 = DAG.computeKnownBits(Op->getOperand(1), Depth + 1);
2957 Known = KnownBits::ashr(Known, Known2);
2958 break;
2959 }
2960 case AArch64ISD::VSHL: {
2961 KnownBits Known2;
2962 Known = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
2963 Known2 = DAG.computeKnownBits(Op->getOperand(1), Depth + 1);
2964 Known = KnownBits::shl(Known, Known2);
2965 break;
2966 }
2967 case AArch64ISD::MOVI: {
2969 APInt(Known.getBitWidth(), Op->getConstantOperandVal(0)));
2970 break;
2971 }
2972 case AArch64ISD::MOVIshift: {
2974 APInt(Known.getBitWidth(), Op->getConstantOperandVal(0)
2975 << Op->getConstantOperandVal(1)));
2976 break;
2977 }
2978 case AArch64ISD::MOVImsl: {
2979 unsigned ShiftAmt = AArch64_AM::getShiftValue(Op->getConstantOperandVal(1));
2981 Known.getBitWidth(), ~(~Op->getConstantOperandVal(0) << ShiftAmt)));
2982 break;
2983 }
2984 case AArch64ISD::MOVIedit: {
2986 Known.getBitWidth(),
2987 AArch64_AM::decodeAdvSIMDModImmType10(Op->getConstantOperandVal(0))));
2988 break;
2989 }
2990 case AArch64ISD::MVNIshift: {
2992 APInt(Known.getBitWidth(),
2993 ~(Op->getConstantOperandVal(0) << Op->getConstantOperandVal(1)),
2994 /*isSigned*/ false, /*implicitTrunc*/ true));
2995 break;
2996 }
2997 case AArch64ISD::MVNImsl: {
2998 unsigned ShiftAmt = AArch64_AM::getShiftValue(Op->getConstantOperandVal(1));
3000 APInt(Known.getBitWidth(), (~Op->getConstantOperandVal(0) << ShiftAmt),
3001 /*isSigned*/ false, /*implicitTrunc*/ true));
3002 break;
3003 }
3004 case AArch64ISD::LOADgot:
3005 case AArch64ISD::ADDlow: {
3006 if (!Subtarget->isTargetILP32())
3007 break;
3008 // In ILP32 mode all valid pointers are in the low 4GB of the address-space.
3009 Known.Zero = APInt::getHighBitsSet(64, 32);
3010 break;
3011 }
3012 case AArch64ISD::ASSERT_ZEXT_BOOL: {
3013 Known = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
3014 Known.Zero |= APInt(Known.getBitWidth(), 0xFE);
3015 break;
3016 }
3018 Intrinsic::ID IntID =
3019 static_cast<Intrinsic::ID>(Op->getConstantOperandVal(1));
3020 switch (IntID) {
3021 default: return;
3022 case Intrinsic::aarch64_ldaxr:
3023 case Intrinsic::aarch64_ldxr: {
3024 unsigned BitWidth = Known.getBitWidth();
3025 EVT VT = cast<MemIntrinsicSDNode>(Op)->getMemoryVT();
3026 unsigned MemBits = VT.getScalarSizeInBits();
3027 Known.Zero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits);
3028 return;
3029 }
3030 }
3031 break;
3032 }
3033 case AArch64ISD::SHL_PRED:
3034 case AArch64ISD::SRL_PRED:
3035 case AArch64ISD::SRA_PRED: {
3036 SDValue Pg = Op->getOperand(0);
3037 if (!isAllActivePredicate(DAG, Pg))
3038 break;
3039
3040 KnownBits KnownVal =
3041 DAG.computeKnownBits(Op->getOperand(1), DemandedElts, Depth + 1);
3042 KnownBits KnownAmt =
3043 DAG.computeKnownBits(Op->getOperand(2), DemandedElts, Depth + 1);
3044
3045 if (Op.getOpcode() == AArch64ISD::SHL_PRED)
3046 Known = KnownBits::shl(KnownVal, KnownAmt);
3047 else if (Op.getOpcode() == AArch64ISD::SRL_PRED)
3048 Known = KnownBits::lshr(KnownVal, KnownAmt);
3049 else
3050 Known = KnownBits::ashr(KnownVal, KnownAmt);
3051 break;
3052 }
3054 case ISD::INTRINSIC_VOID: {
3055 unsigned IntNo = Op.getConstantOperandVal(0);
3056 switch (IntNo) {
3057 default:
3058 break;
3059 case Intrinsic::aarch64_neon_uaddlv: {
3060 MVT VT = Op.getOperand(1).getValueType().getSimpleVT();
3061 unsigned BitWidth = Known.getBitWidth();
3062 if (VT == MVT::v8i8 || VT == MVT::v16i8) {
3063 unsigned Bound = (VT == MVT::v8i8) ? 11 : 12;
3064 assert(BitWidth >= Bound && "Unexpected width!");
3066 Known.Zero |= Mask;
3067 }
3068 break;
3069 }
3070 case Intrinsic::aarch64_neon_umaxv:
3071 case Intrinsic::aarch64_neon_uminv: {
3072 // Figure out the datatype of the vector operand. The UMINV instruction
3073 // will zero extend the result, so we can mark as known zero all the
3074 // bits larger than the element datatype. 32-bit or larget doesn't need
3075 // this as those are legal types and will be handled by isel directly.
3076 MVT VT = Op.getOperand(1).getValueType().getSimpleVT();
3077 unsigned BitWidth = Known.getBitWidth();
3078 if (VT == MVT::v8i8 || VT == MVT::v16i8) {
3079 assert(BitWidth >= 8 && "Unexpected width!");
3081 Known.Zero |= Mask;
3082 } else if (VT == MVT::v4i16 || VT == MVT::v8i16) {
3083 assert(BitWidth >= 16 && "Unexpected width!");
3085 Known.Zero |= Mask;
3086 }
3087 break;
3088 } break;
3089 }
3090 }
3091 }
3092}
3093
3095 SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG,
3096 unsigned Depth) const {
3097 EVT VT = Op.getValueType();
3098 unsigned VTBits = VT.getScalarSizeInBits();
3099 unsigned Opcode = Op.getOpcode();
3100 switch (Opcode) {
3101 case AArch64ISD::FCMEQ:
3102 case AArch64ISD::FCMGE:
3103 case AArch64ISD::FCMGT:
3104 // Compares return either 0 or all-ones
3105 return VTBits;
3106 case AArch64ISD::VASHR: {
3107 unsigned Tmp =
3108 DAG.ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);
3109 return std::min<uint64_t>(Tmp + Op.getConstantOperandVal(1), VTBits);
3110 }
3111 }
3112
3113 return 1;
3114}
3115
3117 GISelValueTracking &Analysis, Register R, const APInt &DemandedElts,
3118 const MachineRegisterInfo &MRI, unsigned Depth) const {
3119 const MachineInstr *MI = MRI.getVRegDef(R);
3120 if (!MI)
3121 return 1;
3122
3123 switch (MI->getOpcode()) {
3124 case AArch64::G_FCMEQ:
3125 case AArch64::G_FCMGE:
3126 case AArch64::G_FCMGT: {
3127 LLT VT = MRI.getType(R);
3128 return VT.getScalarSizeInBits();
3129 }
3130 case AArch64::G_VASHR: {
3131 unsigned Tmp = Analysis.computeNumSignBits(MI->getOperand(1).getReg(),
3132 DemandedElts, Depth + 1);
3133 LLT VT = MRI.getType(R);
3134 return std::min<uint64_t>(Tmp + MI->getOperand(2).getImm(),
3135 VT.getScalarSizeInBits());
3136 }
3137 default:
3138 return 1;
3139 }
3140}
3141
3143 EVT) const {
3144 return MVT::i64;
3145}
3146
3148 EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,
3149 unsigned *Fast) const {
3150
3151 // Allow SVE loads/stores where the alignment >= the size of the element type,
3152 // even with +strict-align. Predicated SVE loads/stores (e.g. ld1/st1), used
3153 // for stores that come from IR, only require element-size alignment (even if
3154 // unaligned accesses are disabled). Without this, these will be forced to
3155 // have 16-byte alignment with +strict-align (and fail to lower as we don't
3156 // yet support TLI.expandUnalignedLoad() and TLI.expandUnalignedStore()).
3157 //
3158 // For NEON in strict-align mode, we need to use LD1/ST1 when the alignment
3159 // is less than the size of the vector, but greater than or equal to the size
3160 // of the elements.
3161 bool UseNEONLd1 = Subtarget->requiresStrictAlign() &&
3162 VT.isFixedLengthVector() &&
3163 (VT.getSizeInBits() == 64 || VT.getSizeInBits() == 128);
3164 if (VT.isScalableVector() || UseNEONLd1) {
3165 unsigned ElementSizeBits = VT.getScalarSizeInBits();
3166 if (ElementSizeBits % 8 == 0 && Alignment >= Align(ElementSizeBits / 8))
3167 return true;
3168 }
3169
3170 if (Subtarget->requiresStrictAlign())
3171 return false;
3172
3173 if (Fast) {
3174 // Some CPUs are fine with unaligned stores except for 128-bit ones.
3175 *Fast = !Subtarget->isMisaligned128StoreSlow() || VT.getStoreSize() != 16 ||
3176 // See comments in performSTORECombine() for more details about
3177 // these conditions.
3178
3179 // Code that uses clang vector extensions can mark that it
3180 // wants unaligned accesses to be treated as fast by
3181 // underspecifying alignment to be 1 or 2.
3182 Alignment <= 2 ||
3183
3184 // Disregard v2i64. Memcpy lowering produces those and splitting
3185 // them regresses performance on micro-benchmarks and olden/bh.
3186 VT == MVT::v2i64;
3187 }
3188 return true;
3189}
3190
3191// Same as above but handling LLTs instead.
3193 LLT Ty, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,
3194 unsigned *Fast) const {
3195 if (Subtarget->requiresStrictAlign())
3196 return false;
3197
3198 if (Fast) {
3199 // Some CPUs are fine with unaligned stores except for 128-bit ones.
3200 *Fast = !Subtarget->isMisaligned128StoreSlow() ||
3201 Ty.getSizeInBytes() != 16 ||
3202 // See comments in performSTORECombine() for more details about
3203 // these conditions.
3204
3205 // Code that uses clang vector extensions can mark that it
3206 // wants unaligned accesses to be treated as fast by
3207 // underspecifying alignment to be 1 or 2.
3208 Alignment <= 2 ||
3209
3210 // Disregard v2i64. Memcpy lowering produces those and splitting
3211 // them regresses performance on micro-benchmarks and olden/bh.
3212 Ty == LLT::fixed_vector(2, 64);
3213 }
3214 return true;
3215}
3216
3218 FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo,
3219 const LibcallLoweringInfo *libcallLowering) const {
3220 return AArch64::createFastISel(funcInfo, libInfo, libcallLowering);
3221}
3222
3225 MachineBasicBlock *MBB) const {
3226 // We materialise the F128CSEL pseudo-instruction as some control flow and a
3227 // phi node:
3228
3229 // OrigBB:
3230 // [... previous instrs leading to comparison ...]
3231 // b.ne TrueBB
3232 // b EndBB
3233 // TrueBB:
3234 // ; Fallthrough
3235 // EndBB:
3236 // Dest = PHI [IfTrue, TrueBB], [IfFalse, OrigBB]
3237
3238 MachineFunction *MF = MBB->getParent();
3239 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3240 const BasicBlock *LLVM_BB = MBB->getBasicBlock();
3241 DebugLoc DL = MI.getDebugLoc();
3242 MachineFunction::iterator It = ++MBB->getIterator();
3243
3244 Register DestReg = MI.getOperand(0).getReg();
3245 Register IfTrueReg = MI.getOperand(1).getReg();
3246 Register IfFalseReg = MI.getOperand(2).getReg();
3247 unsigned CondCode = MI.getOperand(3).getImm();
3248 bool NZCVKilled = MI.getOperand(4).isKill();
3249
3250 MachineBasicBlock *TrueBB = MF->CreateMachineBasicBlock(LLVM_BB);
3251 MachineBasicBlock *EndBB = MF->CreateMachineBasicBlock(LLVM_BB);
3252 MF->insert(It, TrueBB);
3253 MF->insert(It, EndBB);
3254
3255 // Transfer rest of current basic-block to EndBB
3256 EndBB->splice(EndBB->begin(), MBB, std::next(MachineBasicBlock::iterator(MI)),
3257 MBB->end());
3259
3260 BuildMI(MBB, DL, TII->get(AArch64::Bcc)).addImm(CondCode).addMBB(TrueBB);
3261 BuildMI(MBB, DL, TII->get(AArch64::B)).addMBB(EndBB);
3262 MBB->addSuccessor(TrueBB);
3263 MBB->addSuccessor(EndBB);
3264
3265 // TrueBB falls through to the end.
3266 TrueBB->addSuccessor(EndBB);
3267
3268 if (!NZCVKilled) {
3269 TrueBB->addLiveIn(AArch64::NZCV);
3270 EndBB->addLiveIn(AArch64::NZCV);
3271 }
3272
3273 BuildMI(*EndBB, EndBB->begin(), DL, TII->get(AArch64::PHI), DestReg)
3274 .addReg(IfTrueReg)
3275 .addMBB(TrueBB)
3276 .addReg(IfFalseReg)
3277 .addMBB(MBB);
3278
3279 MI.eraseFromParent();
3280 return EndBB;
3281}
3282
3290
3293 MachineBasicBlock *MBB) const {
3294 MachineFunction *MF = MBB->getParent();
3295 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3296 DebugLoc DL = MI.getDebugLoc();
3297
3299 BuildMI(*MBB, MI, DL, TII->get(AArch64::MSR))
3300 .addImm(0xda22)
3301 .add(MI.getOperand(0))
3302 .addDef(AArch64::FPMR, RegState::Implicit);
3303 MI.eraseFromParent();
3304 return MBB;
3305 }
3306
3307 Register NewFpmrVal = MI.getOperand(0).getReg();
3308 const BasicBlock *LLVM_BB = MBB->getBasicBlock();
3309 MachineBasicBlock *MsrBB = MF->CreateMachineBasicBlock(LLVM_BB);
3310 MachineBasicBlock *EndBB = MBB->splitAt(MI);
3311 MF->insert(++MBB->getIterator(), MsrBB);
3312
3313 Register CurrentFpmrVal =
3314 MF->getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
3315 BuildMI(*MBB, MI, DL, TII->get(AArch64::MRS), CurrentFpmrVal)
3316 .addImm(0xda22)
3317 .addUse(AArch64::FPMR, RegState::Implicit);
3318 BuildMI(*MBB, MI, DL, TII->get(AArch64::SUBSXrs), AArch64::XZR)
3319 .addReg(CurrentFpmrVal, RegState::Kill)
3320 .addReg(NewFpmrVal)
3321 .addImm(0);
3322 BuildMI(*MBB, MI, DL, TII->get(AArch64::Bcc))
3324 .addMBB(EndBB);
3325 BuildMI(*MsrBB, MsrBB->begin(), DL, TII->get(AArch64::MSR))
3326 .addImm(0xda22)
3327 .addReg(NewFpmrVal, getKillRegState(MI.getOperand(0).isDead()))
3328 .addDef(AArch64::FPMR, RegState::Implicit);
3329
3330 MBB->addSuccessor(MsrBB);
3331 MsrBB->addSuccessor(EndBB);
3332
3333 MI.eraseFromParent();
3334 return EndBB;
3335}
3336
3339 MachineBasicBlock *MBB) const {
3340 MachineFunction &MF = *MBB->getParent();
3341 MachineBasicBlock::iterator MBBI = MI.getIterator();
3342 const AArch64InstrInfo &TII =
3343 *MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
3344 Register TargetReg = MI.getOperand(0).getReg();
3346 TII.probedStackAlloc(MBBI, TargetReg, false);
3347
3348 MI.eraseFromParent();
3349 return NextInst->getParent();
3350}
3351
3354 MachineBasicBlock *MBB) const {
3355 MachineFunction *MF = MBB->getParent();
3356 MachineRegisterInfo &MRI = MF->getRegInfo();
3357
3358 const TargetRegisterClass *RC_GPR = &AArch64::GPR64RegClass;
3359 const TargetRegisterClass *RC_GPRsp = &AArch64::GPR64spRegClass;
3360
3361 Register RegVL_GPR = MRI.createVirtualRegister(RC_GPR);
3362 Register RegVL_GPRsp = MRI.createVirtualRegister(RC_GPRsp); // for ADDSVL src
3363 Register RegSVL_GPR = MRI.createVirtualRegister(RC_GPR);
3364 Register RegSVL_GPRsp = MRI.createVirtualRegister(RC_GPRsp); // for ADDSVL dst
3365
3366 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3367 DebugLoc DL = MI.getDebugLoc();
3368
3369 // RDVL requires GPR64, ADDSVL requires GPR64sp
3370 // We need to insert COPY instructions, these will later be removed by the
3371 // RegisterCoalescer
3372 BuildMI(*MBB, MI, DL, TII->get(AArch64::RDVLI_XI), RegVL_GPR).addImm(1);
3373 BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY), RegVL_GPRsp)
3374 .addReg(RegVL_GPR);
3375
3376 BuildMI(*MBB, MI, DL, TII->get(AArch64::ADDSVL_XXI), RegSVL_GPRsp)
3377 .addReg(RegVL_GPRsp)
3378 .addImm(-1);
3379 BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY), RegSVL_GPR)
3380 .addReg(RegSVL_GPRsp);
3381
3382 const BasicBlock *LLVM_BB = MBB->getBasicBlock();
3383 MachineFunction::iterator It = ++MBB->getIterator();
3384 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock(LLVM_BB);
3385 MachineBasicBlock *PassBB = MF->CreateMachineBasicBlock(LLVM_BB);
3386 MF->insert(It, TrapBB);
3387 MF->insert(It, PassBB);
3388
3389 // Continue if vector lengths match
3390 BuildMI(*MBB, MI, DL, TII->get(AArch64::CBZX))
3391 .addReg(RegSVL_GPR)
3392 .addMBB(PassBB);
3393
3394 // Transfer rest of current BB to PassBB
3395 PassBB->splice(PassBB->begin(), MBB,
3396 std::next(MachineBasicBlock::iterator(MI)), MBB->end());
3398
3399 // Trap if vector lengths mismatch
3400 BuildMI(TrapBB, DL, TII->get(AArch64::BRK)).addImm(1);
3401
3402 MBB->addSuccessor(TrapBB);
3403 MBB->addSuccessor(PassBB);
3404
3405 MI.eraseFromParent();
3406 return PassBB;
3407}
3408
3410AArch64TargetLowering::EmitTileLoad(unsigned Opc, unsigned BaseReg,
3412 MachineBasicBlock *BB) const {
3413 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3414 MachineInstrBuilder MIB = BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Opc));
3415
3416 MIB.addReg(BaseReg + MI.getOperand(0).getImm(), RegState::Define);
3417 MIB.add(MI.getOperand(1)); // slice index register
3418 MIB.add(MI.getOperand(2)); // slice index offset
3419 MIB.add(MI.getOperand(3)); // pg
3420 MIB.add(MI.getOperand(4)); // base
3421 MIB.add(MI.getOperand(5)); // offset
3422
3423 MI.eraseFromParent(); // The pseudo is gone now.
3424 return BB;
3425}
3426
3429 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3431 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(AArch64::LDR_ZA));
3432
3433 MIB.addReg(AArch64::ZA, RegState::Define);
3434 MIB.add(MI.getOperand(0)); // Vector select register
3435 MIB.add(MI.getOperand(1)); // Vector select offset
3436 MIB.add(MI.getOperand(2)); // Base
3437 MIB.add(MI.getOperand(1)); // Offset, same as vector select offset
3438
3439 MI.eraseFromParent(); // The pseudo is gone now.
3440 return BB;
3441}
3442
3445 unsigned Opcode,
3446 bool Op0IsDef) const {
3447 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3449
3450 MIB = BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Opcode))
3451 .addReg(MI.getOperand(0).getReg(), getDefRegState(Op0IsDef));
3452 for (unsigned I = 1; I < MI.getNumOperands(); ++I)
3453 MIB.add(MI.getOperand(I));
3454
3455 MI.eraseFromParent(); // The pseudo is gone now.
3456 return BB;
3457}
3458
3460AArch64TargetLowering::EmitZAInstr(unsigned Opc, unsigned BaseReg,
3462 MachineBasicBlock *BB) const {
3463 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3464 MachineInstrBuilder MIB = BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Opc));
3465 unsigned StartIdx = 0;
3466
3467 bool HasTile = BaseReg != AArch64::ZA;
3468 bool HasZPROut = HasTile && MI.getOperand(0).isReg();
3469 if (HasZPROut) {
3470 MIB.add(MI.getOperand(StartIdx)); // Output ZPR
3471 ++StartIdx;
3472 }
3473 if (HasTile) {
3474 MIB.addReg(BaseReg + MI.getOperand(StartIdx).getImm(),
3475 RegState::Define); // Output ZA Tile
3476 MIB.addReg(BaseReg + MI.getOperand(StartIdx).getImm()); // Input Za Tile
3477 StartIdx++;
3478 } else {
3479 // Avoids all instructions with mnemonic za.<sz>[Reg, Imm,
3480 if (MI.getOperand(0).isReg() && !MI.getOperand(1).isImm()) {
3481 MIB.add(MI.getOperand(StartIdx)); // Output ZPR
3482 ++StartIdx;
3483 }
3484 MIB.addReg(BaseReg, RegState::Define).addReg(BaseReg);
3485 }
3486 for (unsigned I = StartIdx; I < MI.getNumOperands(); ++I)
3487 MIB.add(MI.getOperand(I));
3488
3489 MI.eraseFromParent(); // The pseudo is gone now.
3490 return BB;
3491}
3492
3495 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3497 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(AArch64::ZERO_M));
3498 MIB.add(MI.getOperand(0)); // Mask
3499
3500 unsigned Mask = MI.getOperand(0).getImm();
3501 for (unsigned I = 0; I < 8; I++) {
3502 if (Mask & (1 << I))
3503 MIB.addDef(AArch64::ZAD0 + I, RegState::ImplicitDefine);
3504 }
3505
3506 MI.eraseFromParent(); // The pseudo is gone now.
3507 return BB;
3508}
3509
3512 MachineBasicBlock *BB) const {
3513 MachineFunction *MF = BB->getParent();
3514 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3515 const DebugLoc &DL = MI.getDebugLoc();
3516 Register ResultReg = MI.getOperand(0).getReg();
3517 if (MF->getRegInfo().use_empty(ResultReg)) {
3518 // Nothing to do. Pseudo erased below.
3519 } else if (Subtarget->hasSME()) {
3520 BuildMI(*BB, MI, DL, TII->get(AArch64::MRS), ResultReg)
3521 .addImm(AArch64SysReg::SVCR)
3522 .addReg(AArch64::VG, RegState::Implicit);
3523 } else {
3524 RTLIB::Libcall LC = RTLIB::SMEABI_SME_STATE;
3525 const AArch64RegisterInfo *TRI = Subtarget->getRegisterInfo();
3526 BuildMI(*BB, MI, DL, TII->get(AArch64::BL))
3528 .addReg(AArch64::X0, RegState::ImplicitDefine)
3529 .addRegMask(TRI->getCallPreservedMask(*MF, getLibcallCallingConv(LC)));
3530 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::COPY), ResultReg)
3531 .addReg(AArch64::X0);
3532 }
3533 MI.eraseFromParent();
3534 return BB;
3535}
3536
3537// Helper function to find the instruction that defined a virtual register.
3538// If unable to find such instruction, returns nullptr.
3540 Register Reg) {
3541 while (Reg.isVirtual()) {
3543 assert(DefMI && "Virtual register definition not found");
3544 unsigned Opcode = DefMI->getOpcode();
3545
3546 if (Opcode == AArch64::COPY) {
3547 Reg = DefMI->getOperand(1).getReg();
3548 // Vreg is defined by copying from physreg.
3549 if (Reg.isPhysical())
3550 return DefMI;
3551 continue;
3552 }
3553 if (Opcode == AArch64::SUBREG_TO_REG) {
3554 Reg = DefMI->getOperand(1).getReg();
3555 continue;
3556 }
3557
3558 return DefMI;
3559 }
3560 return nullptr;
3561}
3562
3565 MachineOperand &AddrDiscOp, const TargetRegisterClass *AddrDiscRC) const {
3566 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3567 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
3568 const DebugLoc &DL = MI.getDebugLoc();
3569
3570 Register AddrDisc = AddrDiscOp.getReg();
3571 int64_t IntDisc = IntDiscOp.getImm();
3572 assert(IntDisc == 0 && "Blend components are already expanded");
3573
3574 const MachineInstr *DiscMI = stripVRegCopies(MRI, AddrDisc);
3575 if (DiscMI) {
3576 switch (DiscMI->getOpcode()) {
3577 case AArch64::MOVKXi:
3578 // blend(addr, imm) which is lowered as "MOVK addr, #imm, #48".
3579 // #imm should be an immediate and not a global symbol, for example.
3580 if (DiscMI->getOperand(2).isImm() &&
3581 DiscMI->getOperand(3).getImm() == 48) {
3582 AddrDisc = DiscMI->getOperand(1).getReg();
3583 IntDisc = DiscMI->getOperand(2).getImm();
3584 }
3585 break;
3586 case AArch64::MOVi32imm:
3587 case AArch64::MOVi64imm:
3588 // Small immediate integer constant passed via VReg.
3589 if (DiscMI->getOperand(1).isImm() &&
3590 isUInt<16>(DiscMI->getOperand(1).getImm())) {
3591 AddrDisc = AArch64::NoRegister;
3592 IntDisc = DiscMI->getOperand(1).getImm();
3593 }
3594 break;
3595 }
3596 }
3597
3598 // For uniformity, always use NoRegister, as XZR is not necessarily contained
3599 // in the requested register class.
3600 if (AddrDisc == AArch64::XZR)
3601 AddrDisc = AArch64::NoRegister;
3602
3603 // Make sure AddrDisc operand respects the register class imposed by MI.
3604 if (AddrDisc && MRI.getRegClass(AddrDisc) != AddrDiscRC) {
3605 Register TmpReg = MRI.createVirtualRegister(AddrDiscRC);
3606 BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), TmpReg).addReg(AddrDisc);
3607 AddrDisc = TmpReg;
3608 }
3609
3610 if (AddrDiscOp.getReg() != AddrDisc)
3611 AddrDiscOp.setIsKill(false);
3612
3613 AddrDiscOp.setReg(AddrDisc);
3614 IntDiscOp.setImm(IntDisc);
3615}
3616
3618 MachineInstr &MI, MachineBasicBlock *BB) const {
3619
3620 int SMEOrigInstr = AArch64::getSMEPseudoMap(MI.getOpcode());
3621 if (SMEOrigInstr != -1) {
3622 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3623 uint64_t SMEMatrixType =
3624 TII->get(MI.getOpcode()).TSFlags & AArch64::SMEMatrixTypeMask;
3625 switch (SMEMatrixType) {
3627 return EmitZAInstr(SMEOrigInstr, AArch64::ZA, MI, BB);
3629 return EmitZAInstr(SMEOrigInstr, AArch64::ZAB0, MI, BB);
3631 return EmitZAInstr(SMEOrigInstr, AArch64::ZAH0, MI, BB);
3633 return EmitZAInstr(SMEOrigInstr, AArch64::ZAS0, MI, BB);
3635 return EmitZAInstr(SMEOrigInstr, AArch64::ZAD0, MI, BB);
3637 return EmitZAInstr(SMEOrigInstr, AArch64::ZAQ0, MI, BB);
3638 }
3639 }
3640
3641 switch (MI.getOpcode()) {
3642 default:
3643#ifndef NDEBUG
3644 MI.dump();
3645#endif
3646 llvm_unreachable("Unexpected instruction for custom inserter!");
3647 case AArch64::EntryPStateSM:
3648 return EmitEntryPStateSM(MI, BB);
3649 case AArch64::F128CSEL:
3650 return EmitF128CSEL(MI, BB);
3651 case TargetOpcode::STATEPOINT:
3652 // STATEPOINT is a pseudo instruction which has no implicit defs/uses
3653 // while bl call instruction (where statepoint will be lowered at the end)
3654 // has implicit def. This def is early-clobber as it will be set at
3655 // the moment of the call and earlier than any use is read.
3656 // Add this implicit dead def here as a workaround.
3657 MI.addOperand(*MI.getMF(),
3659 AArch64::LR, /*isDef*/ true,
3660 /*isImp*/ true, /*isKill*/ false, /*isDead*/ true,
3661 /*isUndef*/ false, /*isEarlyClobber*/ true));
3662 [[fallthrough]];
3663 case TargetOpcode::STACKMAP:
3664 case TargetOpcode::PATCHPOINT:
3665 return emitPatchPoint(MI, BB);
3666
3667 case TargetOpcode::PATCHABLE_EVENT_CALL:
3668 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3669 return BB;
3670
3671 case AArch64::CATCHRET:
3672 return EmitLoweredCatchRet(MI, BB);
3673
3674 case AArch64::PROBED_STACKALLOC_DYN:
3675 return EmitDynamicProbedAlloc(MI, BB);
3676
3677 case AArch64::CHECK_MATCHING_VL_PSEUDO:
3678 return EmitCheckMatchingVL(MI, BB);
3679
3680 case AArch64::LD1_MXIPXX_H_PSEUDO_B:
3681 return EmitTileLoad(AArch64::LD1_MXIPXX_H_B, AArch64::ZAB0, MI, BB);
3682 case AArch64::LD1_MXIPXX_H_PSEUDO_H:
3683 return EmitTileLoad(AArch64::LD1_MXIPXX_H_H, AArch64::ZAH0, MI, BB);
3684 case AArch64::LD1_MXIPXX_H_PSEUDO_S:
3685 return EmitTileLoad(AArch64::LD1_MXIPXX_H_S, AArch64::ZAS0, MI, BB);
3686 case AArch64::LD1_MXIPXX_H_PSEUDO_D:
3687 return EmitTileLoad(AArch64::LD1_MXIPXX_H_D, AArch64::ZAD0, MI, BB);
3688 case AArch64::LD1_MXIPXX_H_PSEUDO_Q:
3689 return EmitTileLoad(AArch64::LD1_MXIPXX_H_Q, AArch64::ZAQ0, MI, BB);
3690 case AArch64::LD1_MXIPXX_V_PSEUDO_B:
3691 return EmitTileLoad(AArch64::LD1_MXIPXX_V_B, AArch64::ZAB0, MI, BB);
3692 case AArch64::LD1_MXIPXX_V_PSEUDO_H:
3693 return EmitTileLoad(AArch64::LD1_MXIPXX_V_H, AArch64::ZAH0, MI, BB);
3694 case AArch64::LD1_MXIPXX_V_PSEUDO_S:
3695 return EmitTileLoad(AArch64::LD1_MXIPXX_V_S, AArch64::ZAS0, MI, BB);
3696 case AArch64::LD1_MXIPXX_V_PSEUDO_D:
3697 return EmitTileLoad(AArch64::LD1_MXIPXX_V_D, AArch64::ZAD0, MI, BB);
3698 case AArch64::LD1_MXIPXX_V_PSEUDO_Q:
3699 return EmitTileLoad(AArch64::LD1_MXIPXX_V_Q, AArch64::ZAQ0, MI, BB);
3700 case AArch64::LDR_ZA_PSEUDO:
3701 return EmitFill(MI, BB);
3702 case AArch64::LDR_TX_PSEUDO:
3703 return EmitZTInstr(MI, BB, AArch64::LDR_TX, /*Op0IsDef=*/true);
3704 case AArch64::STR_TX_PSEUDO:
3705 return EmitZTInstr(MI, BB, AArch64::STR_TX, /*Op0IsDef=*/false);
3706 case AArch64::ZERO_M_PSEUDO:
3707 return EmitZero(MI, BB);
3708 case AArch64::ZERO_T_PSEUDO:
3709 return EmitZTInstr(MI, BB, AArch64::ZERO_T, /*Op0IsDef=*/true);
3710 case AArch64::MOVT_TIZ_PSEUDO:
3711 return EmitZTInstr(MI, BB, AArch64::MOVT_TIZ, /*Op0IsDef=*/true);
3712 case AArch64::MSR_FPMR:
3713 return EmitLoweredSetFpmr(MI, BB);
3714
3715 case AArch64::PAC:
3716 fixupPtrauthDiscriminator(MI, BB, MI.getOperand(3), MI.getOperand(4),
3717 &AArch64::GPR64noipRegClass);
3718 return BB;
3719 }
3720}
3721
3722//===----------------------------------------------------------------------===//
3723// AArch64 Lowering private implementation.
3724//===----------------------------------------------------------------------===//
3725
3726//===----------------------------------------------------------------------===//
3727// Lowering Code
3728//===----------------------------------------------------------------------===//
3729
3730// Forward declarations of SVE fixed length lowering helpers
3735 SelectionDAG &DAG);
3738 EVT VT);
3740 EVT VT);
3742
3743/// isZerosVector - Check whether SDNode N is a zero-filled vector.
3744static bool isZerosVector(const SDNode *N) {
3745 // Look through a bit convert.
3746 while (N->getOpcode() == ISD::BITCAST)
3747 N = N->getOperand(0).getNode();
3748
3750 return true;
3751
3752 if (N->getOpcode() != AArch64ISD::DUP)
3753 return false;
3754
3755 auto Opnd0 = N->getOperand(0);
3756 return isNullConstant(Opnd0) || isNullFPConstant(Opnd0);
3757}
3758
3759static bool isOneVector(SDValue V) {
3760 return isOneOrOneSplat(V) ||
3761 (V.getOpcode() == AArch64ISD::DUP && isOneConstant(V.getOperand(0)));
3762}
3763
3764/// changeIntCCToAArch64CC - Convert a DAG integer condition code to an AArch64
3765/// CC
3767 SDValue RHS = {}) {
3768 switch (CC) {
3769 default:
3770 llvm_unreachable("Unknown condition code!");
3771 case ISD::SETNE:
3772 return AArch64CC::NE;
3773 case ISD::SETEQ:
3774 return AArch64CC::EQ;
3775 case ISD::SETGT:
3776 return AArch64CC::GT;
3777 case ISD::SETGE:
3779 case ISD::SETLT:
3781 case ISD::SETLE:
3782 return AArch64CC::LE;
3783 case ISD::SETUGT:
3784 return AArch64CC::HI;
3785 case ISD::SETUGE:
3786 return AArch64CC::HS;
3787 case ISD::SETULT:
3788 return AArch64CC::LO;
3789 case ISD::SETULE:
3790 return AArch64CC::LS;
3791 }
3792}
3793
3794/// changeFPCCToAArch64CC - Convert a DAG fp condition code to an AArch64 CC.
3796 AArch64CC::CondCode &CondCode,
3797 AArch64CC::CondCode &CondCode2) {
3798 CondCode2 = AArch64CC::AL;
3799 switch (CC) {
3800 default:
3801 llvm_unreachable("Unknown FP condition!");
3802 case ISD::SETEQ:
3803 case ISD::SETOEQ:
3804 CondCode = AArch64CC::EQ;
3805 break;
3806 case ISD::SETGT:
3807 case ISD::SETOGT:
3808 CondCode = AArch64CC::GT;
3809 break;
3810 case ISD::SETGE:
3811 case ISD::SETOGE:
3812 CondCode = AArch64CC::GE;
3813 break;
3814 case ISD::SETOLT:
3815 CondCode = AArch64CC::MI;
3816 break;
3817 case ISD::SETOLE:
3818 CondCode = AArch64CC::LS;
3819 break;
3820 case ISD::SETONE:
3821 CondCode = AArch64CC::MI;
3822 CondCode2 = AArch64CC::GT;
3823 break;
3824 case ISD::SETO:
3825 CondCode = AArch64CC::VC;
3826 break;
3827 case ISD::SETUO:
3828 CondCode = AArch64CC::VS;
3829 break;
3830 case ISD::SETUEQ:
3831 CondCode = AArch64CC::EQ;
3832 CondCode2 = AArch64CC::VS;
3833 break;
3834 case ISD::SETUGT:
3835 CondCode = AArch64CC::HI;
3836 break;
3837 case ISD::SETUGE:
3838 CondCode = AArch64CC::PL;
3839 break;
3840 case ISD::SETLT:
3841 case ISD::SETULT:
3842 CondCode = AArch64CC::LT;
3843 break;
3844 case ISD::SETLE:
3845 case ISD::SETULE:
3846 CondCode = AArch64CC::LE;
3847 break;
3848 case ISD::SETNE:
3849 case ISD::SETUNE:
3850 CondCode = AArch64CC::NE;
3851 break;
3852 }
3853}
3854
3855/// Convert a DAG fp condition code to an AArch64 CC.
3856/// This differs from changeFPCCToAArch64CC in that it returns cond codes that
3857/// should be AND'ed instead of OR'ed.
3859 AArch64CC::CondCode &CondCode,
3860 AArch64CC::CondCode &CondCode2) {
3861 CondCode2 = AArch64CC::AL;
3862 switch (CC) {
3863 default:
3864 changeFPCCToAArch64CC(CC, CondCode, CondCode2);
3865 assert(CondCode2 == AArch64CC::AL);
3866 break;
3867 case ISD::SETONE:
3868 // (a one b)
3869 // == ((a olt b) || (a ogt b))
3870 // == ((a ord b) && (a une b))
3871 CondCode = AArch64CC::VC;
3872 CondCode2 = AArch64CC::NE;
3873 break;
3874 case ISD::SETUEQ:
3875 // (a ueq b)
3876 // == ((a uno b) || (a oeq b))
3877 // == ((a ule b) && (a uge b))
3878 CondCode = AArch64CC::PL;
3879 CondCode2 = AArch64CC::LE;
3880 break;
3881 }
3882}
3883
3884/// changeVectorFPCCToAArch64CC - Convert a DAG fp condition code to an AArch64
3885/// CC usable with the vector instructions. Fewer operations are available
3886/// without a real NZCV register, so we have to use less efficient combinations
3887/// to get the same effect.
3889 AArch64CC::CondCode &CondCode,
3890 AArch64CC::CondCode &CondCode2,
3891 bool &Invert) {
3892 Invert = false;
3893 switch (CC) {
3894 default:
3895 // Mostly the scalar mappings work fine.
3896 changeFPCCToAArch64CC(CC, CondCode, CondCode2);
3897 break;
3898 case ISD::SETUO:
3899 Invert = true;
3900 [[fallthrough]];
3901 case ISD::SETO:
3902 CondCode = AArch64CC::MI;
3903 CondCode2 = AArch64CC::GE;
3904 break;
3905 case ISD::SETLE:
3906 CondCode = AArch64CC::LS;
3907 CondCode2 = AArch64CC::AL;
3908 break;
3909 case ISD::SETLT:
3910 CondCode = AArch64CC::MI;
3911 CondCode2 = AArch64CC::AL;
3912 break;
3913 case ISD::SETUEQ:
3914 case ISD::SETULT:
3915 case ISD::SETULE:
3916 case ISD::SETUGT:
3917 case ISD::SETUGE:
3918 // All of the compare-mask comparisons are ordered, but we can switch
3919 // between the two by a double inversion. E.g. ULE == !OGT.
3920 Invert = true;
3921 changeFPCCToAArch64CC(getSetCCInverse(CC, /* FP inverse */ MVT::f32),
3922 CondCode, CondCode2);
3923 break;
3924 }
3925}
3926
3927/// Like SelectionDAG::getCondCode(), but for AArch64 condition codes.
3929 // TODO: Should be TargetConstant (need to s/imm/timm in patterns).
3930 return DAG.getConstant(CC, SDLoc(), CondCodeVT);
3931}
3932
3933static unsigned numberOfInstrToLoadImm(const APInt &C) {
3934 uint64_t Imm = C.getZExtValue();
3936 AArch64_IMM::expandMOVImm(Imm, 32, Insn);
3937 return Insn.size();
3938}
3939
3941 // 0 - INT_MIN sign wraps, so no signed wrap means cmn is safe.
3942 if (Op->getFlags().hasNoSignedWrap())
3943 return true;
3944
3945 // We can still figure out if the second operand is safe to use
3946 // in a CMN instruction by checking if it is known to be not the minimum
3947 // signed value. If it is not, then we can safely use CMN.
3948 // Note: We can eventually remove this check and simply rely on
3949 // Op->getFlags().hasNoSignedWrap() once SelectionDAG/ISelLowering
3950 // consistently sets them appropriately when making said nodes.
3951
3952 KnownBits KnownSrc = DAG.computeKnownBits(Op.getOperand(1));
3953 return !KnownSrc.getSignedMinValue().isMinSignedValue();
3954}
3955
3956// Can a (CMP op1, (sub 0, op2) be turned into a CMN instruction on
3957// the grounds that "op1 - (-op2) == op1 + op2" ? Not always, the C and V flags
3958// can be set differently by this operation. It comes down to whether
3959// "SInt(~op2)+1 == SInt(~op2+1)" (and the same for UInt). If they are then
3960// everything is fine. If not then the optimization is wrong. Thus general
3961// comparisons are only valid if op2 != 0 and op2 != INT_MIN.
3962//
3963// So, finally, the only LLVM-native comparisons that don't mention C or V
3964// are the ones that aren't unsigned comparisons. They're the only ones we can
3965// safely use CMN for in the absence of information about op2.
3967 return Op.getOpcode() == ISD::SUB && isNullConstant(Op.getOperand(0)) &&
3968 (isIntEqualitySetCC(CC) ||
3969 (isUnsignedIntSetCC(CC) && DAG.isKnownNeverZero(Op.getOperand(1))) ||
3970 (isSignedIntSetCC(CC) && isSafeSignedCMN(Op, DAG)));
3971}
3972
3974 SelectionDAG &DAG, SDValue Chain,
3975 bool IsSignaling) {
3976 EVT VT = LHS.getValueType();
3977 assert(VT != MVT::f128);
3978
3979 const bool FullFP16 = DAG.getSubtarget<AArch64Subtarget>().hasFullFP16();
3980
3981 if ((VT == MVT::f16 && !FullFP16) || VT == MVT::bf16) {
3982 LHS = DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {MVT::f32, MVT::Other},
3983 {Chain, LHS});
3984 RHS = DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {MVT::f32, MVT::Other},
3985 {LHS.getValue(1), RHS});
3986 Chain = RHS.getValue(1);
3987 }
3988 unsigned Opcode =
3989 IsSignaling ? AArch64ISD::STRICT_FCMPE : AArch64ISD::STRICT_FCMP;
3990 return DAG.getNode(Opcode, DL, {FlagsVT, MVT::Other}, {Chain, LHS, RHS});
3991}
3992
3994 const SDLoc &DL, SelectionDAG &DAG) {
3995 EVT VT = LHS.getValueType();
3996 const bool FullFP16 = DAG.getSubtarget<AArch64Subtarget>().hasFullFP16();
3997
3998 if (VT.isFloatingPoint()) {
3999 assert(VT != MVT::f128);
4000 if ((VT == MVT::f16 && !FullFP16) || VT == MVT::bf16) {
4001 LHS = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, LHS);
4002 RHS = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, RHS);
4003 }
4004 return DAG.getNode(AArch64ISD::FCMP, DL, FlagsVT, LHS, RHS);
4005 }
4006
4007 // The CMP instruction is just an alias for SUBS, and representing it as
4008 // SUBS means that it's possible to get CSE with subtract operations.
4009 // A later phase can perform the optimization of setting the destination
4010 // register to WZR/XZR if it ends up being unused.
4011 unsigned Opcode = AArch64ISD::SUBS;
4012
4013 if (isCMN(RHS, CC, DAG)) {
4014 // Can we combine a (CMP op1, (sub 0, op2) into a CMN instruction ?
4015 Opcode = AArch64ISD::ADDS;
4016 RHS = RHS.getOperand(1);
4017 } else if (LHS.getOpcode() == ISD::SUB && isNullConstant(LHS.getOperand(0)) &&
4018 isIntEqualitySetCC(CC)) {
4019 // As we are looking for EQ/NE compares, the operands can be commuted ; can
4020 // we combine a (CMP (sub 0, op1), op2) into a CMN instruction ?
4021 Opcode = AArch64ISD::ADDS;
4022 LHS = LHS.getOperand(1);
4023 } else if (isNullConstant(RHS) && !isUnsignedIntSetCC(CC)) {
4024 if (LHS.getOpcode() == ISD::AND) {
4025 // Similarly, (CMP (and X, Y), 0) can be implemented with a TST
4026 // (a.k.a. ANDS) except that the flags are only guaranteed to work for one
4027 // of the signed comparisons.
4028 const SDValue ANDSNode =
4029 DAG.getNode(AArch64ISD::ANDS, DL, DAG.getVTList(VT, FlagsVT),
4030 LHS.getOperand(0), LHS.getOperand(1));
4031 // Replace all users of (and X, Y) with newly generated (ands X, Y)
4032 DAG.ReplaceAllUsesWith(LHS, ANDSNode);
4033 return ANDSNode.getValue(1);
4034 } else if (LHS.getOpcode() == AArch64ISD::ANDS) {
4035 // Use result of ANDS
4036 return LHS.getValue(1);
4037 }
4038 }
4039
4040 return DAG.getNode(Opcode, DL, DAG.getVTList(VT, FlagsVT), LHS, RHS)
4041 .getValue(1);
4042}
4043
4044/// \defgroup AArch64CCMP CMP;CCMP matching
4045///
4046/// These functions deal with the formation of CMP;CCMP;... sequences.
4047/// The CCMP/CCMN/FCCMP/FCCMPE instructions allow the conditional execution of
4048/// a comparison. They set the NZCV flags to a predefined value if their
4049/// predicate is false. This allows to express arbitrary conjunctions, for
4050/// example "cmp 0 (and (setCA (cmp A)) (setCB (cmp B)))"
4051/// expressed as:
4052/// cmp A
4053/// ccmp B, inv(CB), CA
4054/// check for CB flags
4055///
4056/// This naturally lets us implement chains of AND operations with SETCC
4057/// operands. And we can even implement some other situations by transforming
4058/// them:
4059/// - We can implement (NEG SETCC) i.e. negating a single comparison by
4060/// negating the flags used in a CCMP/FCCMP operations.
4061/// - We can negate the result of a whole chain of CMP/CCMP/FCCMP operations
4062/// by negating the flags we test for afterwards. i.e.
4063/// NEG (CMP CCMP CCCMP ...) can be implemented.
4064/// - Note that we can only ever negate all previously processed results.
4065/// What we can not implement by flipping the flags to test is a negation
4066/// of two sub-trees (because the negation affects all sub-trees emitted so
4067/// far, so the 2nd sub-tree we emit would also affect the first).
4068/// With those tools we can implement some OR operations:
4069/// - (OR (SETCC A) (SETCC B)) can be implemented via:
4070/// NEG (AND (NEG (SETCC A)) (NEG (SETCC B)))
4071/// - After transforming OR to NEG/AND combinations we may be able to use NEG
4072/// elimination rules from earlier to implement the whole thing as a
4073/// CCMP/FCCMP chain.
4074///
4075/// As complete example:
4076/// or (or (setCA (cmp A)) (setCB (cmp B)))
4077/// (and (setCC (cmp C)) (setCD (cmp D)))"
4078/// can be reassociated to:
4079/// or (and (setCC (cmp C)) setCD (cmp D))
4080// (or (setCA (cmp A)) (setCB (cmp B)))
4081/// can be transformed to:
4082/// not (and (not (and (setCC (cmp C)) (setCD (cmp D))))
4083/// (and (not (setCA (cmp A)) (not (setCB (cmp B))))))"
4084/// which can be implemented as:
4085/// cmp C
4086/// ccmp D, inv(CD), CC
4087/// ccmp A, CA, inv(CD)
4088/// ccmp B, CB, inv(CA)
4089/// check for CB flags
4090///
4091/// A counterexample is "or (and A B) (and C D)" which translates to
4092/// not (and (not (and (not A) (not B))) (not (and (not C) (not D)))), we
4093/// can only implement 1 of the inner (not) operations, but not both!
4094/// @{
4095
4096/// Create a conditional comparison; Use CCMP, CCMN or FCCMP as appropriate.
4098 ISD::CondCode CC, SDValue CCOp,
4100 AArch64CC::CondCode OutCC,
4101 const SDLoc &DL, SelectionDAG &DAG) {
4102 unsigned Opcode = 0;
4103 const bool FullFP16 = DAG.getSubtarget<AArch64Subtarget>().hasFullFP16();
4104
4105 if (LHS.getValueType().isFloatingPoint()) {
4106 assert(LHS.getValueType() != MVT::f128);
4107 if ((LHS.getValueType() == MVT::f16 && !FullFP16) ||
4108 LHS.getValueType() == MVT::bf16) {
4109 LHS = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, LHS);
4110 RHS = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, RHS);
4111 }
4112 Opcode = AArch64ISD::FCCMP;
4113 } else if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(RHS)) {
4114 APInt Imm = Const->getAPIntValue();
4115 if (Imm.isNegative() && Imm.sgt(-32)) {
4116 Opcode = AArch64ISD::CCMN;
4117 RHS = DAG.getConstant(Imm.abs(), DL, Const->getValueType(0));
4118 }
4119 } else if (isCMN(RHS, CC, DAG)) {
4120 Opcode = AArch64ISD::CCMN;
4121 RHS = RHS.getOperand(1);
4122 } else if (LHS.getOpcode() == ISD::SUB && isNullConstant(LHS.getOperand(0)) &&
4123 isIntEqualitySetCC(CC)) {
4124 // As we are looking for EQ/NE compares, the operands can be commuted ; can
4125 // we combine a (CCMP (sub 0, op1), op2) into a CCMN instruction ?
4126 Opcode = AArch64ISD::CCMN;
4127 LHS = LHS.getOperand(1);
4128 }
4129 if (Opcode == 0)
4130 Opcode = AArch64ISD::CCMP;
4131
4132 SDValue Condition = getCondCode(DAG, Predicate);
4134 unsigned NZCV = AArch64CC::getNZCVToSatisfyCondCode(InvOutCC);
4135 SDValue NZCVOp = DAG.getConstant(NZCV, DL, MVT::i32);
4136 return DAG.getNode(Opcode, DL, FlagsVT, LHS, RHS, NZCVOp, Condition, CCOp);
4137}
4138
4139/// Returns true if @p Val is a tree of AND/OR/SETCC operations that can be
4140/// expressed as a conjunction. See \ref AArch64CCMP.
4141/// \param CanNegate Set to true if we can negate the whole sub-tree just by
4142/// changing the conditions on the SETCC tests.
4143/// (this means we can call emitConjunctionRec() with
4144/// Negate==true on this sub-tree)
4145/// \param MustBeFirst Set to true if this subtree needs to be negated and we
4146/// cannot do the negation naturally. We are required to
4147/// emit the subtree first in this case.
4148/// \param PreferFirst Set to true if processing this subtree first may
4149/// result in more efficient code.
4150/// \param WillNegate Is true if are called when the result of this
4151/// subexpression must be negated. This happens when the
4152/// outer expression is an OR. We can use this fact to know
4153/// that we have a double negation (or (or ...) ...) that
4154/// can be implemented for free.
4155static bool canEmitConjunction(SelectionDAG &DAG, const SDValue Val,
4156 bool &CanNegate, bool &MustBeFirst,
4157 bool &PreferFirst, bool WillNegate,
4158 unsigned Depth = 0) {
4159 if (!Val.hasOneUse())
4160 return false;
4161 unsigned Opcode = Val->getOpcode();
4162 if (Opcode == ISD::SETCC) {
4163 EVT VT = Val->getOperand(0).getValueType();
4164 if (VT == MVT::f128)
4165 return false;
4166 CanNegate = true;
4167 MustBeFirst = false;
4168 // Designate this operation as a preferred first operation if the result
4169 // of a SUB operation can be reused.
4170 PreferFirst = DAG.doesNodeExist(ISD::SUB, DAG.getVTList(VT),
4171 {Val->getOperand(0), Val->getOperand(1)});
4172 return true;
4173 }
4174 // Protect against exponential runtime and stack overflow.
4175 if (Depth > 6)
4176 return false;
4177 if (Opcode == ISD::AND || Opcode == ISD::OR) {
4178 bool IsOR = Opcode == ISD::OR;
4179 SDValue O0 = Val->getOperand(0);
4180 SDValue O1 = Val->getOperand(1);
4181 bool CanNegateL;
4182 bool MustBeFirstL;
4183 bool PreferFirstL;
4184 if (!canEmitConjunction(DAG, O0, CanNegateL, MustBeFirstL, PreferFirstL,
4185 IsOR, Depth + 1))
4186 return false;
4187 bool CanNegateR;
4188 bool MustBeFirstR;
4189 bool PreferFirstR;
4190 if (!canEmitConjunction(DAG, O1, CanNegateR, MustBeFirstR, PreferFirstR,
4191 IsOR, Depth + 1))
4192 return false;
4193
4194 if (MustBeFirstL && MustBeFirstR)
4195 return false;
4196
4197 if (IsOR) {
4198 // For an OR expression we need to be able to naturally negate at least
4199 // one side or we cannot do the transformation at all.
4200 if (!CanNegateL && !CanNegateR)
4201 return false;
4202 // If we the result of the OR will be negated and we can naturally negate
4203 // the leaves, then this sub-tree as a whole negates naturally.
4204 CanNegate = WillNegate && CanNegateL && CanNegateR;
4205 // If we cannot naturally negate the whole sub-tree, then this must be
4206 // emitted first.
4207 MustBeFirst = !CanNegate;
4208 } else {
4209 assert(Opcode == ISD::AND && "Must be OR or AND");
4210 // We cannot naturally negate an AND operation.
4211 CanNegate = false;
4212 MustBeFirst = MustBeFirstL || MustBeFirstR;
4213 }
4214 PreferFirst = PreferFirstL || PreferFirstR;
4215 return true;
4216 }
4217 return false;
4218}
4219
4220/// Emit conjunction or disjunction tree with the CMP/FCMP followed by a chain
4221/// of CCMP/CFCMP ops. See @ref AArch64CCMP.
4222/// Tries to transform the given i1 producing node @p Val to a series compare
4223/// and conditional compare operations. @returns an NZCV flags producing node
4224/// and sets @p OutCC to the flags that should be tested or returns SDValue() if
4225/// transformation was not possible.
4226/// \p Negate is true if we want this sub-tree being negated just by changing
4227/// SETCC conditions.
4229 AArch64CC::CondCode &OutCC, bool Negate, SDValue CCOp,
4231 // We're at a tree leaf, produce a conditional comparison operation.
4232 unsigned Opcode = Val->getOpcode();
4233 if (Opcode == ISD::SETCC) {
4234 SDValue LHS = Val->getOperand(0);
4235 SDValue RHS = Val->getOperand(1);
4236 ISD::CondCode CC = cast<CondCodeSDNode>(Val->getOperand(2))->get();
4237 bool isInteger = LHS.getValueType().isInteger();
4238 if (Negate)
4239 CC = getSetCCInverse(CC, LHS.getValueType());
4240 SDLoc DL(Val);
4241 // Determine OutCC and handle FP special case.
4242 if (isInteger) {
4243 OutCC = changeIntCCToAArch64CC(CC, RHS);
4244 } else {
4245 assert(LHS.getValueType().isFloatingPoint());
4246 AArch64CC::CondCode ExtraCC;
4247 changeFPCCToANDAArch64CC(CC, OutCC, ExtraCC);
4248 // Some floating point conditions can't be tested with a single condition
4249 // code. Construct an additional comparison in this case.
4250 if (ExtraCC != AArch64CC::AL) {
4251 SDValue ExtraCmp;
4252 if (!CCOp.getNode())
4253 ExtraCmp = emitComparison(LHS, RHS, CC, DL, DAG);
4254 else
4255 ExtraCmp = emitConditionalComparison(LHS, RHS, CC, CCOp, Predicate,
4256 ExtraCC, DL, DAG);
4257 CCOp = ExtraCmp;
4258 Predicate = ExtraCC;
4259 }
4260 }
4261
4262 // Produce a normal comparison if we are first in the chain
4263 if (!CCOp)
4264 return emitComparison(LHS, RHS, CC, DL, DAG);
4265 // Otherwise produce a ccmp.
4266 return emitConditionalComparison(LHS, RHS, CC, CCOp, Predicate, OutCC, DL,
4267 DAG);
4268 }
4269 assert(Val->hasOneUse() && "Valid conjunction/disjunction tree");
4270
4271 bool IsOR = Opcode == ISD::OR;
4272
4273 SDValue LHS = Val->getOperand(0);
4274 bool CanNegateL;
4275 bool MustBeFirstL;
4276 bool PreferFirstL;
4277 bool ValidL = canEmitConjunction(DAG, LHS, CanNegateL, MustBeFirstL,
4278 PreferFirstL, IsOR);
4279 assert(ValidL && "Valid conjunction/disjunction tree");
4280 (void)ValidL;
4281
4282 SDValue RHS = Val->getOperand(1);
4283 bool CanNegateR;
4284 bool MustBeFirstR;
4285 bool PreferFirstR;
4286 bool ValidR = canEmitConjunction(DAG, RHS, CanNegateR, MustBeFirstR,
4287 PreferFirstR, IsOR);
4288 assert(ValidR && "Valid conjunction/disjunction tree");
4289 (void)ValidR;
4290
4291 bool ShouldFirstL = PreferFirstL && !PreferFirstR && !MustBeFirstR;
4292
4293 // Swap sub-tree that must or should come first to the right side.
4294 if (MustBeFirstL || ShouldFirstL) {
4295 assert(!MustBeFirstR && "Valid conjunction/disjunction tree");
4296 std::swap(LHS, RHS);
4297 std::swap(CanNegateL, CanNegateR);
4298 std::swap(MustBeFirstL, MustBeFirstR);
4299 }
4300
4301 bool NegateR;
4302 bool NegateAfterR;
4303 bool NegateL;
4304 bool NegateAfterAll;
4305 if (Opcode == ISD::OR) {
4306 // Swap the sub-tree that we can negate naturally to the left.
4307 if (!CanNegateL) {
4308 assert(CanNegateR && "at least one side must be negatable");
4309 assert(!MustBeFirstR && "invalid conjunction/disjunction tree");
4310 assert(!Negate);
4311 std::swap(LHS, RHS);
4312 NegateR = false;
4313 NegateAfterR = true;
4314 } else {
4315 // Negate the left sub-tree if possible, otherwise negate the result.
4316 NegateR = CanNegateR;
4317 NegateAfterR = !CanNegateR;
4318 }
4319 NegateL = true;
4320 NegateAfterAll = !Negate;
4321 } else {
4322 assert(Opcode == ISD::AND && "Valid conjunction/disjunction tree");
4323 assert(!Negate && "Valid conjunction/disjunction tree");
4324
4325 NegateL = false;
4326 NegateR = false;
4327 NegateAfterR = false;
4328 NegateAfterAll = false;
4329 }
4330
4331 // Emit sub-trees.
4332 AArch64CC::CondCode RHSCC;
4333 SDValue CmpR = emitConjunctionRec(DAG, RHS, RHSCC, NegateR, CCOp, Predicate);
4334 if (NegateAfterR)
4335 RHSCC = AArch64CC::getInvertedCondCode(RHSCC);
4336 SDValue CmpL = emitConjunctionRec(DAG, LHS, OutCC, NegateL, CmpR, RHSCC);
4337 if (NegateAfterAll)
4338 OutCC = AArch64CC::getInvertedCondCode(OutCC);
4339 return CmpL;
4340}
4341
4342/// Emit expression as a conjunction (a series of CCMP/CFCMP ops).
4343/// In some cases this is even possible with OR operations in the expression.
4344/// See \ref AArch64CCMP.
4345/// \see emitConjunctionRec().
4347 AArch64CC::CondCode &OutCC) {
4348 bool DummyCanNegate;
4349 bool DummyMustBeFirst;
4350 bool DummyPreferFirst;
4351 if (!canEmitConjunction(DAG, Val, DummyCanNegate, DummyMustBeFirst,
4352 DummyPreferFirst, false))
4353 return SDValue();
4354
4355 return emitConjunctionRec(DAG, Val, OutCC, false, SDValue(), AArch64CC::AL);
4356}
4357
4358/// @}
4359
4361 if (V.getOpcode() == ISD::SIGN_EXTEND_INREG)
4362 return true;
4363
4364 if (V.getOpcode() == ISD::AND)
4365 if (ConstantSDNode *MaskCst = dyn_cast<ConstantSDNode>(V.getOperand(1))) {
4366 uint64_t Mask = MaskCst->getZExtValue();
4367 return (Mask == 0xFF || Mask == 0xFFFF || Mask == 0xFFFFFFFF);
4368 }
4369 return false;
4370}
4371
4372/// Returns how profitable it is to fold a comparison's operand's shift and/or
4373/// extension operations.
4374static unsigned getCmpOperandFoldingProfit(SDValue Op, bool AllowExtend) {
4375 if (!Op.hasOneUse())
4376 return 0;
4377
4378 if (AllowExtend && isSupportedExtend(Op))
4379 return 1;
4380
4381 unsigned Opc = Op.getOpcode();
4382 if (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA)
4383 if (ConstantSDNode *ShiftCst = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
4384 uint64_t Shift = ShiftCst->getZExtValue();
4385 if (AllowExtend && isSupportedExtend(Op.getOperand(0)))
4386 return (Shift <= 4) ? 2 : 1;
4387 EVT VT = Op.getValueType();
4388 if ((VT == MVT::i32 && Shift <= 31) || (VT == MVT::i64 && Shift <= 63))
4389 return 1;
4390 }
4391
4392 return 0;
4393}
4394
4396 SelectionDAG &DAG) {
4397 if (isCMN(Op, CC, DAG))
4398 return getCmpOperandFoldingProfit(Op.getOperand(1), true) + 1;
4399 return getCmpOperandFoldingProfit(Op, true);
4400}
4401
4402// emitComparison() converts comparison with one or negative one to comparison
4403// with 0. Note that this only works for signed comparisons because of how ANDS
4404// works.
4406 ISD::CondCode &CC) {
4407 // Only works for ANDS and AND.
4408 if (LHS.getOpcode() != ISD::AND && LHS.getOpcode() != AArch64ISD::ANDS)
4409 return false;
4410
4411 if (C.isOne() && (CC == ISD::SETLT || CC == ISD::SETGE)) {
4412 CC = (CC == ISD::SETLT) ? ISD::SETLE : ISD::SETGT;
4413 return true;
4414 }
4415
4416 if (C.isAllOnes() && (CC == ISD::SETLE || CC == ISD::SETGT)) {
4417 CC = (CC == ISD::SETLE) ? ISD::SETLT : ISD::SETGE;
4418 return true;
4419 }
4420
4421 return false;
4422}
4423
4425 SDValue &AArch64cc, SelectionDAG &DAG,
4426 const SDLoc &DL) {
4427 if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS.getNode())) {
4428 EVT VT = RHS.getValueType();
4429 APInt C = RHSC->getAPIntValue();
4430 // shouldBeAdjustedToZero is a special case to better fold with
4431 // emitComparison().
4432 if (shouldBeAdjustedToZero(LHS, C, CC)) {
4433 // Adjust the constant to zero.
4434 // CC has already been adjusted.
4435 RHS = DAG.getConstant(0, DL, VT);
4436 } else if (!AArch64_AM::isLegalCmpImmed(C)) {
4437 unsigned NumImmForC = numberOfInstrToLoadImm(C);
4438 // Constant does not fit, try adjusting it by one?
4439 switch (CC) {
4440 default:
4441 break;
4442 case ISD::SETLT:
4443 case ISD::SETGE:
4444 if (!C.isMinSignedValue()) {
4445 APInt CMinusOne = C - 1;
4446 if (AArch64_AM::isLegalCmpImmed(CMinusOne) ||
4447 (NumImmForC > numberOfInstrToLoadImm(CMinusOne))) {
4448 CC = (CC == ISD::SETLT) ? ISD::SETLE : ISD::SETGT;
4449 RHS = DAG.getConstant(CMinusOne, DL, VT);
4450 }
4451 }
4452 break;
4453 case ISD::SETULT:
4454 case ISD::SETUGE: {
4455 // C is not 0 because it is a legal immediate.
4456 assert(!C.isZero() && "C should not be zero here");
4457 APInt CMinusOne = C - 1;
4458 if (AArch64_AM::isLegalCmpImmed(CMinusOne) ||
4459 (NumImmForC > numberOfInstrToLoadImm(CMinusOne))) {
4460 CC = (CC == ISD::SETULT) ? ISD::SETULE : ISD::SETUGT;
4461 RHS = DAG.getConstant(CMinusOne, DL, VT);
4462 }
4463 break;
4464 }
4465 case ISD::SETLE:
4466 case ISD::SETGT:
4467 if (!C.isMaxSignedValue()) {
4468 APInt CPlusOne = C + 1;
4469 if (AArch64_AM::isLegalCmpImmed(CPlusOne) ||
4470 (NumImmForC > numberOfInstrToLoadImm(CPlusOne))) {
4471 CC = (CC == ISD::SETLE) ? ISD::SETLT : ISD::SETGE;
4472 RHS = DAG.getConstant(CPlusOne, DL, VT);
4473 }
4474 }
4475 break;
4476 case ISD::SETULE:
4477 case ISD::SETUGT:
4478 if (!C.isAllOnes()) {
4479 APInt CPlusOne = C + 1;
4480 if (AArch64_AM::isLegalCmpImmed(CPlusOne) ||
4481 (NumImmForC > numberOfInstrToLoadImm(CPlusOne))) {
4482 CC = (CC == ISD::SETULE) ? ISD::SETULT : ISD::SETUGE;
4483 RHS = DAG.getConstant(CPlusOne, DL, VT);
4484 }
4485 }
4486 break;
4487 }
4488 } else if (C.isZero() && getCmpOperandFoldingProfit(LHS, false) != 0) {
4489 // Fold into CMP WZR, reg, shift #amount
4490 std::swap(LHS, RHS);
4492 }
4493 }
4494
4495 // Comparisons are canonicalized so that the RHS operand is simpler than the
4496 // LHS one, the extreme case being when RHS is an immediate. However, AArch64
4497 // can fold some shift+extend operations on the RHS operand, so swap the
4498 // operands if that can be done.
4499 //
4500 // For example:
4501 // lsl w13, w11, #1
4502 // cmp w13, w12
4503 // can be turned into:
4504 // cmp w12, w11, lsl #1
4505 if (!isa<ConstantSDNode>(RHS) ||
4506 !AArch64_AM::isLegalCmpImmed(RHS->getAsAPIntVal())) {
4507 if (getCmpOrCmnOperandFoldingProfit(LHS, CC, DAG) >
4509 std::swap(LHS, RHS);
4511 }
4512 }
4513
4514 SDValue Cmp;
4516 if (isIntEqualitySetCC(CC) && isa<ConstantSDNode>(RHS)) {
4518
4519 // The imm operand of ADDS is an unsigned immediate, in the range 0 to 4095.
4520 // For the i8 operand, the largest immediate is 255, so this can be easily
4521 // encoded in the compare instruction. For the i16 operand, however, the
4522 // largest immediate cannot be encoded in the compare.
4523 // Therefore, use a sign extending load and cmn to avoid materializing the
4524 // -1 constant. For example,
4525 // movz w1, #65535
4526 // ldrh w0, [x0, #0]
4527 // cmp w0, w1
4528 // >
4529 // ldrsh w0, [x0, #0]
4530 // cmn w0, #1
4531 // Fundamental, we're relying on the property that (zext LHS) == (zext RHS)
4532 // if and only if (sext LHS) == (sext RHS). The checks are in place to
4533 // ensure both the LHS and RHS are truly zero extended and to make sure the
4534 // transformation is profitable.
4535 if ((RHSC->getZExtValue() >> 16 == 0) && isa<LoadSDNode>(LHS) &&
4536 cast<LoadSDNode>(LHS)->getExtensionType() == ISD::ZEXTLOAD &&
4537 cast<LoadSDNode>(LHS)->getMemoryVT() == MVT::i16 &&
4538 LHS->hasNUsesOfValue(1, 0)) {
4539 int16_t ValueofRHS = RHS->getAsZExtVal();
4540 if (ValueofRHS < 0 && AArch64_AM::isLegalArithImmed(-ValueofRHS)) {
4541 SDValue SExt =
4542 DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, LHS.getValueType(), LHS,
4543 DAG.getValueType(MVT::i16));
4544 Cmp = emitComparison(
4545 SExt, DAG.getSignedConstant(ValueofRHS, DL, RHS.getValueType()), CC,
4546 DL, DAG);
4548 }
4549 }
4550
4551 if (!Cmp && (RHSC->isZero() || RHSC->isOne())) {
4552 if ((Cmp = emitConjunction(DAG, LHS, AArch64CC))) {
4553 if ((CC == ISD::SETNE) ^ RHSC->isZero())
4555 }
4556 }
4557 }
4558
4559 if (!Cmp) {
4560 Cmp = emitComparison(LHS, RHS, CC, DL, DAG);
4562 }
4563 AArch64cc = getCondCode(DAG, AArch64CC);
4564 return Cmp;
4565}
4566
4567static std::pair<SDValue, SDValue>
4569 assert((Op.getValueType() == MVT::i32 || Op.getValueType() == MVT::i64) &&
4570 "Unsupported value type");
4571 SDValue Value, Overflow;
4572 SDLoc DL(Op);
4573 SDValue LHS = Op.getOperand(0);
4574 SDValue RHS = Op.getOperand(1);
4575 unsigned Opc = 0;
4576 switch (Op.getOpcode()) {
4577 default:
4578 llvm_unreachable("Unknown overflow instruction!");
4579 case ISD::SADDO:
4580 Opc = AArch64ISD::ADDS;
4581 CC = AArch64CC::VS;
4582 break;
4583 case ISD::UADDO:
4584 Opc = AArch64ISD::ADDS;
4585 CC = AArch64CC::HS;
4586 break;
4587 case ISD::SSUBO:
4588 Opc = AArch64ISD::SUBS;
4589 CC = AArch64CC::VS;
4590 break;
4591 case ISD::USUBO:
4592 Opc = AArch64ISD::SUBS;
4593 CC = AArch64CC::LO;
4594 break;
4595 // Multiply needs a little bit extra work.
4596 case ISD::SMULO:
4597 case ISD::UMULO: {
4598 CC = AArch64CC::NE;
4599 bool IsSigned = Op.getOpcode() == ISD::SMULO;
4600 if (Op.getValueType() == MVT::i32) {
4601 // Extend to 64-bits, then perform a 64-bit multiply.
4602 unsigned ExtendOpc = IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
4603 LHS = DAG.getNode(ExtendOpc, DL, MVT::i64, LHS);
4604 RHS = DAG.getNode(ExtendOpc, DL, MVT::i64, RHS);
4605 SDValue Mul = DAG.getNode(ISD::MUL, DL, MVT::i64, LHS, RHS);
4606 Value = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Mul);
4607
4608 // Check that the result fits into a 32-bit integer.
4609 SDVTList VTs = DAG.getVTList(MVT::i64, FlagsVT);
4610 if (IsSigned) {
4611 // cmp xreg, wreg, sxtw
4612 SDValue SExtMul = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, Value);
4613 Overflow =
4614 DAG.getNode(AArch64ISD::SUBS, DL, VTs, Mul, SExtMul).getValue(1);
4615 } else {
4616 // tst xreg, #0xffffffff00000000
4617 SDValue UpperBits = DAG.getConstant(0xFFFFFFFF00000000, DL, MVT::i64);
4618 Overflow =
4619 DAG.getNode(AArch64ISD::ANDS, DL, VTs, Mul, UpperBits).getValue(1);
4620 }
4621 break;
4622 }
4623 assert(Op.getValueType() == MVT::i64 && "Expected an i64 value type");
4624 // For the 64 bit multiply
4625 Value = DAG.getNode(ISD::MUL, DL, MVT::i64, LHS, RHS);
4626 if (IsSigned) {
4627 SDValue UpperBits = DAG.getNode(ISD::MULHS, DL, MVT::i64, LHS, RHS);
4628 SDValue LowerBits = DAG.getNode(ISD::SRA, DL, MVT::i64, Value,
4629 DAG.getConstant(63, DL, MVT::i64));
4630 // It is important that LowerBits is last, otherwise the arithmetic
4631 // shift will not be folded into the compare (SUBS).
4632 SDVTList VTs = DAG.getVTList(MVT::i64, FlagsVT);
4633 Overflow = DAG.getNode(AArch64ISD::SUBS, DL, VTs, UpperBits, LowerBits)
4634 .getValue(1);
4635 } else {
4636 SDValue UpperBits = DAG.getNode(ISD::MULHU, DL, MVT::i64, LHS, RHS);
4637 SDVTList VTs = DAG.getVTList(MVT::i64, FlagsVT);
4638 Overflow =
4639 DAG.getNode(AArch64ISD::SUBS, DL, VTs,
4640 DAG.getConstant(0, DL, MVT::i64),
4641 UpperBits).getValue(1);
4642 }
4643 break;
4644 }
4645 } // switch (...)
4646
4647 if (Opc) {
4648 SDVTList VTs = DAG.getVTList(Op->getValueType(0), FlagsVT);
4649
4650 // Emit the AArch64 operation with overflow check.
4651 Value = DAG.getNode(Opc, DL, VTs, LHS, RHS);
4652 Overflow = Value.getValue(1);
4653 }
4654 return std::make_pair(Value, Overflow);
4655}
4656
4657SDValue AArch64TargetLowering::LowerXOR(SDValue Op, SelectionDAG &DAG) const {
4658 if (useSVEForFixedLengthVectorVT(Op.getValueType(),
4659 !Subtarget->isNeonAvailable()))
4660 return LowerToScalableOp(Op, DAG);
4661
4662 SDValue Sel = Op.getOperand(0);
4663 SDValue Other = Op.getOperand(1);
4664 SDLoc DL(Sel);
4665
4666 // If the operand is an overflow checking operation, invert the condition
4667 // code and kill the Not operation. I.e., transform:
4668 // (xor (overflow_op_bool, 1))
4669 // -->
4670 // (csel 1, 0, invert(cc), overflow_op_bool)
4671 // ... which later gets transformed to just a cset instruction with an
4672 // inverted condition code, rather than a cset + eor sequence.
4674 // Only lower legal XALUO ops.
4676 return SDValue();
4677
4678 SDValue TVal = DAG.getConstant(1, DL, MVT::i32);
4679 SDValue FVal = DAG.getConstant(0, DL, MVT::i32);
4681 SDValue Value, Overflow;
4682 std::tie(Value, Overflow) = getAArch64XALUOOp(CC, Sel.getValue(0), DAG);
4683 SDValue CCVal = getCondCode(DAG, getInvertedCondCode(CC));
4684 return DAG.getNode(AArch64ISD::CSEL, DL, Op.getValueType(), TVal, FVal,
4685 CCVal, Overflow);
4686 }
4687 // If neither operand is a SELECT_CC, give up.
4688 if (Sel.getOpcode() != ISD::SELECT_CC)
4689 std::swap(Sel, Other);
4690 if (Sel.getOpcode() != ISD::SELECT_CC)
4691 return Op;
4692
4693 // The folding we want to perform is:
4694 // (xor x, (select_cc a, b, cc, 0, -1) )
4695 // -->
4696 // (csel x, (xor x, -1), cc ...)
4697 //
4698 // The latter will get matched to a CSINV instruction.
4699
4700 ISD::CondCode CC = cast<CondCodeSDNode>(Sel.getOperand(4))->get();
4701 SDValue LHS = Sel.getOperand(0);
4702 SDValue RHS = Sel.getOperand(1);
4703 SDValue TVal = Sel.getOperand(2);
4704 SDValue FVal = Sel.getOperand(3);
4705
4706 // FIXME: This could be generalized to non-integer comparisons.
4707 if (LHS.getValueType() != MVT::i32 && LHS.getValueType() != MVT::i64)
4708 return Op;
4709
4710 ConstantSDNode *CFVal = dyn_cast<ConstantSDNode>(FVal);
4711 ConstantSDNode *CTVal = dyn_cast<ConstantSDNode>(TVal);
4712
4713 // The values aren't constants, this isn't the pattern we're looking for.
4714 if (!CFVal || !CTVal)
4715 return Op;
4716
4717 // We can commute the SELECT_CC by inverting the condition. This
4718 // might be needed to make this fit into a CSINV pattern.
4719 if (CTVal->isAllOnes() && CFVal->isZero()) {
4720 std::swap(TVal, FVal);
4721 std::swap(CTVal, CFVal);
4722 CC = ISD::getSetCCInverse(CC, LHS.getValueType());
4723 }
4724
4725 // If the constants line up, perform the transform!
4726 if (CTVal->isZero() && CFVal->isAllOnes()) {
4727 SDValue CCVal;
4728 SDValue Cmp = getAArch64Cmp(LHS, RHS, CC, CCVal, DAG, DL);
4729
4730 FVal = Other;
4731 TVal = DAG.getNode(ISD::XOR, DL, Other.getValueType(), Other,
4732 DAG.getAllOnesConstant(DL, Other.getValueType()));
4733
4734 return DAG.getNode(AArch64ISD::CSEL, DL, Sel.getValueType(), FVal, TVal,
4735 CCVal, Cmp);
4736 }
4737
4738 return Op;
4739}
4740
4741// If Invert is false, sets 'C' bit of NZCV to 0 if value is 0, else sets 'C'
4742// bit to 1. If Invert is true, sets 'C' bit of NZCV to 1 if value is 0, else
4743// sets 'C' bit to 0.
4745 SDLoc DL(Value);
4746 EVT VT = Value.getValueType();
4747 SDValue Op0 = Invert ? DAG.getConstant(0, DL, VT) : Value;
4748 SDValue Op1 = Invert ? Value : DAG.getConstant(1, DL, VT);
4749 SDValue Cmp =
4750 DAG.getNode(AArch64ISD::SUBS, DL, DAG.getVTList(VT, FlagsVT), Op0, Op1);
4751 return Cmp.getValue(1);
4752}
4753
4754// If Invert is false, value is 1 if 'C' bit of NZCV is 1, else 0.
4755// If Invert is true, value is 0 if 'C' bit of NZCV is 1, else 1.
4757 bool Invert) {
4758 assert(Glue.getResNo() == 1);
4759 SDLoc DL(Glue);
4760 SDValue Zero = DAG.getConstant(0, DL, VT);
4761 SDValue One = DAG.getConstant(1, DL, VT);
4763 SDValue CC = getCondCode(DAG, Cond);
4764 return DAG.getNode(AArch64ISD::CSEL, DL, VT, One, Zero, CC, Glue);
4765}
4766
4767// Value is 1 if 'V' bit of NZCV is 1, else 0
4769 assert(Glue.getResNo() == 1);
4770 SDLoc DL(Glue);
4771 SDValue Zero = DAG.getConstant(0, DL, VT);
4772 SDValue One = DAG.getConstant(1, DL, VT);
4774 return DAG.getNode(AArch64ISD::CSEL, DL, VT, One, Zero, CC, Glue);
4775}
4776
4777// This lowering is inefficient, but it will get cleaned up by
4778// `foldOverflowCheck`
4780 unsigned Opcode, bool IsSigned) {
4781 EVT VT0 = Op.getValue(0).getValueType();
4782 EVT VT1 = Op.getValue(1).getValueType();
4783
4784 if (VT0 != MVT::i32 && VT0 != MVT::i64)
4785 return SDValue();
4786
4787 bool InvertCarry = Opcode == AArch64ISD::SBCS;
4788 SDValue OpLHS = Op.getOperand(0);
4789 SDValue OpRHS = Op.getOperand(1);
4790 SDValue OpCarryIn = valueToCarryFlag(Op.getOperand(2), DAG, InvertCarry);
4791
4792 SDLoc DL(Op);
4793
4794 SDValue Sum = DAG.getNode(Opcode, DL, DAG.getVTList(VT0, FlagsVT), OpLHS,
4795 OpRHS, OpCarryIn);
4796
4797 SDValue OutFlag =
4798 IsSigned ? overflowFlagToValue(Sum.getValue(1), VT1, DAG)
4799 : carryFlagToValue(Sum.getValue(1), VT1, DAG, InvertCarry);
4800
4801 return DAG.getMergeValues({Sum, OutFlag}, DL);
4802}
4803
4804static SDValue lowerIntNeonIntrinsic(SDValue Op, unsigned Opcode,
4805 SelectionDAG &DAG,
4806 bool LastOperandIsImm = false) {
4807 if (Op.getValueType().isVector())
4808 return SDValue();
4809
4810 SDLoc DL(Op);
4812 const unsigned NumOperands = Op.getNumOperands();
4813 auto getFloatVT = [](EVT VT) {
4814 assert((VT == MVT::i32 || VT == MVT::i64) && "Unexpected VT");
4815 return VT == MVT::i32 ? MVT::f32 : MVT::f64;
4816 };
4817 auto bitcastToFloat = [&](SDValue Val) {
4818 return DAG.getBitcast(getFloatVT(Val.getValueType()), Val);
4819 };
4820
4821 // Skip first operand as it is intrinsic ID.
4822 for (unsigned I = 1; I < NumOperands; ++I) {
4823 SDValue Val = Op.getOperand(I);
4824 const bool KeepInt = LastOperandIsImm && (I == NumOperands - 1);
4825 NewOps.push_back(KeepInt ? Val : bitcastToFloat(Val));
4826 }
4827 EVT OrigVT = Op.getValueType();
4828 SDValue OpNode = DAG.getNode(Opcode, DL, getFloatVT(OrigVT), NewOps);
4829 return DAG.getBitcast(OrigVT, OpNode);
4830}
4831
4833 // Let legalize expand this if it isn't a legal type yet.
4834 if (!DAG.getTargetLoweringInfo().isTypeLegal(Op.getValueType()))
4835 return SDValue();
4836
4837 SDLoc DL(Op);
4839 // The actual operation that sets the overflow or carry flag.
4840 SDValue Value, Overflow;
4841 std::tie(Value, Overflow) = getAArch64XALUOOp(CC, Op, DAG);
4842
4843 // We use 0 and 1 as false and true values.
4844 SDValue TVal = DAG.getConstant(1, DL, MVT::i32);
4845 SDValue FVal = DAG.getConstant(0, DL, MVT::i32);
4846
4847 // We use an inverted condition, because the conditional select is inverted
4848 // too. This will allow it to be selected to a single instruction:
4849 // CSINC Wd, WZR, WZR, invert(cond).
4850 SDValue CCVal = getCondCode(DAG, getInvertedCondCode(CC));
4851 Overflow =
4852 DAG.getNode(AArch64ISD::CSEL, DL, MVT::i32, FVal, TVal, CCVal, Overflow);
4853
4854 return DAG.getMergeValues({Value, Overflow}, DL);
4855}
4856
4857// Prefetch operands are:
4858// 1: Address to prefetch
4859// 2: bool isWrite
4860// 3: int locality (0 = no locality ... 3 = extreme locality)
4861// 4: bool isDataCache
4863 SDLoc DL(Op);
4864 unsigned IsWrite = Op.getConstantOperandVal(2);
4865 unsigned Locality = Op.getConstantOperandVal(3);
4866 unsigned IsData = Op.getConstantOperandVal(4);
4867
4868 bool IsStream = !Locality;
4869 // When the locality number is set
4870 if (Locality) {
4871 // The front-end should have filtered out the out-of-range values
4872 assert(Locality <= 3 && "Prefetch locality out-of-range");
4873 // The locality degree is the opposite of the cache speed.
4874 // Put the number the other way around.
4875 // The encoding starts at 0 for level 1
4876 Locality = 3 - Locality;
4877 }
4878
4879 // built the mask value encoding the expected behavior.
4880 unsigned PrfOp = (IsWrite << 4) | // Load/Store bit
4881 (!IsData << 3) | // IsDataCache bit
4882 (Locality << 1) | // Cache level bits
4883 (unsigned)IsStream; // Stream bit
4884 return DAG.getNode(AArch64ISD::PREFETCH, DL, MVT::Other, Op.getOperand(0),
4885 DAG.getTargetConstant(PrfOp, DL, MVT::i32),
4886 Op.getOperand(1));
4887}
4888
4889// Converts SETCC (AND X Y) Z ULT -> SETCC (AND X (Y & ~(Z - 1)) 0 EQ when Y is
4890// a power of 2. This is then lowered to ANDS X (Y & ~(Z - 1)) instead of SUBS
4891// (AND X Y) Z which produces a better opt with EmitComparison
4893 SelectionDAG &DAG, const SDLoc DL) {
4894 if (CC == ISD::SETULT && LHS.getOpcode() == ISD::AND && LHS->hasOneUse()) {
4895 ConstantSDNode *LHSConstOp = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
4897 if (LHSConstOp && RHSConst) {
4898 uint64_t LHSConstValue = LHSConstOp->getZExtValue();
4899 uint64_t RHSConstant = RHSConst->getZExtValue();
4900 if (isPowerOf2_64(RHSConstant)) {
4901 uint64_t NewMaskValue = LHSConstValue & ~(RHSConstant - 1);
4902 LHS =
4903 DAG.getNode(ISD::AND, DL, LHS.getValueType(), LHS.getOperand(0),
4904 DAG.getConstant(NewMaskValue, DL, LHS.getValueType()));
4905 RHS = DAG.getConstant(0, DL, RHS.getValueType());
4906 CC = ISD::SETEQ;
4907 }
4908 }
4909 }
4910}
4911
4912SDValue AArch64TargetLowering::LowerFP_EXTEND(SDValue Op,
4913 SelectionDAG &DAG) const {
4914 EVT VT = Op.getValueType();
4915 if (VT.isScalableVector()) {
4916 SDValue SrcVal = Op.getOperand(0);
4917
4918 if (VT == MVT::nxv2f64 && SrcVal.getValueType() == MVT::nxv2bf16) {
4919 // Break conversion in two with the first part converting to f32 and the
4920 // second using native f32->VT instructions.
4921 SDLoc DL(Op);
4922 return DAG.getNode(ISD::FP_EXTEND, DL, VT,
4923 DAG.getNode(ISD::FP_EXTEND, DL, MVT::nxv2f32, SrcVal));
4924 }
4925
4926 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FP_EXTEND_MERGE_PASSTHRU);
4927 }
4928
4929 if (useSVEForFixedLengthVectorVT(VT, !Subtarget->isNeonAvailable()))
4930 return LowerFixedLengthFPExtendToSVE(Op, DAG);
4931
4932 bool IsStrict = Op->isStrictFPOpcode();
4933 SDValue Op0 = Op.getOperand(IsStrict ? 1 : 0);
4934 EVT Op0VT = Op0.getValueType();
4935 if (VT == MVT::f64) {
4936 // FP16->FP32 extends are legal for v32 and v4f32.
4937 if (Op0VT == MVT::f32 || Op0VT == MVT::f16)
4938 return Op;
4939 // Split bf16->f64 extends into two fpextends.
4940 if (Op0VT == MVT::bf16 && IsStrict) {
4941 SDValue Ext1 =
4942 DAG.getNode(ISD::STRICT_FP_EXTEND, SDLoc(Op), {MVT::f32, MVT::Other},
4943 {Op0, Op.getOperand(0)});
4944 return DAG.getNode(ISD::STRICT_FP_EXTEND, SDLoc(Op), {VT, MVT::Other},
4945 {Ext1, Ext1.getValue(1)});
4946 }
4947 if (Op0VT == MVT::bf16)
4948 return DAG.getNode(ISD::FP_EXTEND, SDLoc(Op), VT,
4949 DAG.getNode(ISD::FP_EXTEND, SDLoc(Op), MVT::f32, Op0));
4950 return SDValue();
4951 }
4952
4953 assert(Op.getValueType() == MVT::f128 && "Unexpected lowering");
4954 return SDValue();
4955}
4956
4957SDValue AArch64TargetLowering::LowerFP_ROUND(SDValue Op,
4958 SelectionDAG &DAG) const {
4959 EVT VT = Op.getValueType();
4960 bool IsStrict = Op->isStrictFPOpcode();
4961 SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
4962 EVT SrcVT = SrcVal.getValueType();
4963 bool Trunc = Op.getConstantOperandVal(IsStrict ? 2 : 1) == 1;
4964 SDNodeFlags Flags = Op->getFlags();
4965
4966 if (VT.isScalableVector()) {
4967 // Let common code split the operation.
4968 if (SrcVT == MVT::nxv8f32)
4969 return Op;
4970
4971 if (VT.getScalarType() != MVT::bf16)
4972 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FP_ROUND_MERGE_PASSTHRU);
4973
4974 SDLoc DL(Op);
4975 constexpr EVT I32 = MVT::nxv4i32;
4976 auto ImmV = [&](int I) -> SDValue { return DAG.getConstant(I, DL, I32); };
4977
4978 SDValue NaN;
4979 SDValue Narrow;
4980
4981 if (SrcVT == MVT::nxv2f32 || SrcVT == MVT::nxv4f32) {
4982 if (Subtarget->hasBF16())
4983 return LowerToPredicatedOp(Op, DAG,
4984 AArch64ISD::FP_ROUND_MERGE_PASSTHRU);
4985
4986 Narrow = getSVESafeBitCast(I32, SrcVal, DAG);
4987
4988 // Set the quiet bit.
4989 if (!DAG.isKnownNeverSNaN(SrcVal) && !Flags.hasNoNaNs())
4990 NaN = DAG.getNode(ISD::OR, DL, I32, Narrow, ImmV(0x400000));
4991 } else if (SrcVT == MVT::nxv2f64 &&
4992 (Subtarget->hasSVE2() || Subtarget->isStreamingSVEAvailable())) {
4993 // Round to float without introducing rounding errors and try again.
4994 SDValue Pg = getPredicateForVector(DAG, DL, MVT::nxv2f32);
4995 Narrow = DAG.getNode(AArch64ISD::FCVTX_MERGE_PASSTHRU, DL, MVT::nxv2f32,
4996 Pg, SrcVal, DAG.getPOISON(MVT::nxv2f32));
4997
4999 if (IsStrict)
5000 NewOps.push_back(Op.getOperand(0));
5001 NewOps.push_back(Narrow);
5002 NewOps.push_back(Op.getOperand(IsStrict ? 2 : 1));
5003 return DAG.getNode(Op.getOpcode(), DL, VT, NewOps, Op->getFlags());
5004 } else
5005 return SDValue();
5006
5007 if (!Trunc) {
5008 SDValue Lsb = DAG.getNode(ISD::SRL, DL, I32, Narrow, ImmV(16));
5009 Lsb = DAG.getNode(ISD::AND, DL, I32, Lsb, ImmV(1));
5010 SDValue RoundingBias = DAG.getNode(ISD::ADD, DL, I32, Lsb, ImmV(0x7fff));
5011 Narrow = DAG.getNode(ISD::ADD, DL, I32, Narrow, RoundingBias);
5012 }
5013
5014 // Don't round if we had a NaN, we don't want to turn 0x7fffffff into
5015 // 0x80000000.
5016 if (NaN) {
5017 EVT I1 = I32.changeElementType(*DAG.getContext(), MVT::i1);
5018 EVT CondVT = VT.changeElementType(*DAG.getContext(), MVT::i1);
5019 SDValue IsNaN = DAG.getSetCC(DL, CondVT, SrcVal, SrcVal, ISD::SETUO);
5020 IsNaN = DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, I1, IsNaN);
5021 Narrow = DAG.getSelect(DL, I32, IsNaN, NaN, Narrow);
5022 }
5023
5024 // Now that we have rounded, shift the bits into position.
5025 Narrow = DAG.getNode(ISD::SRL, DL, I32, Narrow, ImmV(16));
5026 return getSVESafeBitCast(VT, Narrow, DAG);
5027 }
5028
5029 if (useSVEForFixedLengthVectorVT(SrcVT, !Subtarget->isNeonAvailable()))
5030 return LowerFixedLengthFPRoundToSVE(Op, DAG);
5031
5032 // Expand cases where the result type is BF16 but we don't have hardware
5033 // instructions to lower it.
5034 if (VT.getScalarType() == MVT::bf16 &&
5035 !((Subtarget->hasNEON() || Subtarget->hasSME()) &&
5036 Subtarget->hasBF16())) {
5037 SDLoc DL(Op);
5038 SDValue Narrow = SrcVal;
5039 SDValue NaN;
5040 EVT I32 = SrcVT.changeElementType(*DAG.getContext(), MVT::i32);
5041 EVT F32 = SrcVT.changeElementType(*DAG.getContext(), MVT::f32);
5042 if (SrcVT.getScalarType() == MVT::f32) {
5043 bool NeverSNaN = DAG.isKnownNeverSNaN(Narrow);
5044 Narrow = DAG.getNode(ISD::BITCAST, DL, I32, Narrow);
5045 if (!NeverSNaN) {
5046 // Set the quiet bit.
5047 NaN = DAG.getNode(ISD::OR, DL, I32, Narrow,
5048 DAG.getConstant(0x400000, DL, I32));
5049 }
5050 } else if (SrcVT.getScalarType() == MVT::f64) {
5051 Narrow = DAG.getNode(AArch64ISD::FCVTXN, DL, F32, Narrow);
5052 Narrow = DAG.getNode(ISD::BITCAST, DL, I32, Narrow);
5053 } else {
5054 return SDValue();
5055 }
5056 if (!Trunc) {
5057 SDValue One = DAG.getConstant(1, DL, I32);
5058 SDValue Lsb = DAG.getNode(ISD::SRL, DL, I32, Narrow,
5059 DAG.getShiftAmountConstant(16, I32, DL));
5060 Lsb = DAG.getNode(ISD::AND, DL, I32, Lsb, One);
5061 SDValue RoundingBias =
5062 DAG.getNode(ISD::ADD, DL, I32, DAG.getConstant(0x7fff, DL, I32), Lsb);
5063 Narrow = DAG.getNode(ISD::ADD, DL, I32, Narrow, RoundingBias);
5064 }
5065
5066 // Don't round if we had a NaN, we don't want to turn 0x7fffffff into
5067 // 0x80000000.
5068 if (NaN) {
5069 SDValue IsNaN = DAG.getSetCC(
5070 DL, getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), SrcVT),
5071 SrcVal, SrcVal, ISD::SETUO);
5072 Narrow = DAG.getSelect(DL, I32, IsNaN, NaN, Narrow);
5073 }
5074
5075 // Now that we have rounded, shift the bits into position.
5076 Narrow = DAG.getNode(ISD::SRL, DL, I32, Narrow,
5077 DAG.getShiftAmountConstant(16, I32, DL));
5078 if (VT.isVector()) {
5079 EVT I16 = I32.changeVectorElementType(*DAG.getContext(), MVT::i16);
5080 Narrow = DAG.getNode(ISD::TRUNCATE, DL, I16, Narrow);
5081 return DAG.getNode(ISD::BITCAST, DL, VT, Narrow);
5082 }
5083 Narrow = DAG.getNode(ISD::BITCAST, DL, F32, Narrow);
5084 SDValue Result = DAG.getTargetExtractSubreg(AArch64::hsub, DL, VT, Narrow);
5085 return IsStrict ? DAG.getMergeValues({Result, Op.getOperand(0)}, DL)
5086 : Result;
5087 }
5088
5089 if (SrcVT != MVT::f128) {
5090 // Expand cases where the input is a vector bigger than NEON.
5092 return SDValue();
5093
5094 // It's legal except when f128 is involved
5095 return Op;
5096 }
5097
5098 return SDValue();
5099}
5100
5101SDValue AArch64TargetLowering::LowerVectorFP_TO_INT(SDValue Op,
5102 SelectionDAG &DAG) const {
5103 // Warning: We maintain cost tables in AArch64TargetTransformInfo.cpp.
5104 // Any additional optimization in this function should be recorded
5105 // in the cost tables.
5106 bool IsStrict = Op->isStrictFPOpcode();
5107 EVT InVT = Op.getOperand(IsStrict ? 1 : 0).getValueType();
5108 EVT VT = Op.getValueType();
5109
5110 assert(!(IsStrict && VT.isScalableVector()) &&
5111 "Unimplemented SVE support for STRICT_FP_to_INT!");
5112
5113 // f16 conversions are promoted to f32 when full fp16 is not supported.
5114 if ((InVT.getVectorElementType() == MVT::f16 && !Subtarget->hasFullFP16()) ||
5115 InVT.getVectorElementType() == MVT::bf16) {
5116 EVT NewVT = VT.changeElementType(*DAG.getContext(), MVT::f32);
5117 SDLoc DL(Op);
5118 if (IsStrict) {
5119 SDValue Ext = DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {NewVT, MVT::Other},
5120 {Op.getOperand(0), Op.getOperand(1)});
5121 return DAG.getNode(Op.getOpcode(), DL, {VT, MVT::Other},
5122 {Ext.getValue(1), Ext.getValue(0)});
5123 }
5124 return DAG.getNode(
5125 Op.getOpcode(), DL, Op.getValueType(),
5126 DAG.getNode(ISD::FP_EXTEND, DL, NewVT, Op.getOperand(0)));
5127 }
5128
5129 if (SDValue Res = LowerFPToIntToSVE(Op, DAG))
5130 return Res;
5131
5132 uint64_t VTSize = VT.getFixedSizeInBits();
5133 uint64_t InVTSize = InVT.getFixedSizeInBits();
5134 if (VTSize < InVTSize) {
5135 SDLoc DL(Op);
5136 if (IsStrict) {
5138 SDValue Cv = DAG.getNode(Op.getOpcode(), DL, {InVT, MVT::Other},
5139 {Op.getOperand(0), Op.getOperand(1)});
5140 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, VT, Cv);
5141 return DAG.getMergeValues({Trunc, Cv.getValue(1)}, DL);
5142 }
5143 SDValue Cv =
5144 DAG.getNode(Op.getOpcode(), DL, InVT.changeVectorElementTypeToInteger(),
5145 Op.getOperand(0));
5146 return DAG.getNode(ISD::TRUNCATE, DL, VT, Cv);
5147 }
5148
5149 if (VTSize > InVTSize) {
5150 SDLoc DL(Op);
5151 MVT ExtVT =
5154 if (IsStrict) {
5155 SDValue Ext = DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {ExtVT, MVT::Other},
5156 {Op.getOperand(0), Op.getOperand(1)});
5157 return DAG.getNode(Op.getOpcode(), DL, {VT, MVT::Other},
5158 {Ext.getValue(1), Ext.getValue(0)});
5159 }
5160 SDValue Ext = DAG.getNode(ISD::FP_EXTEND, DL, ExtVT, Op.getOperand(0));
5161 return DAG.getNode(Op.getOpcode(), DL, VT, Ext);
5162 }
5163
5164 // Use a scalar operation for conversions between single-element vectors of
5165 // the same size.
5166 if (InVT.getVectorNumElements() == 1) {
5167 SDLoc DL(Op);
5168 SDValue Extract = DAG.getNode(
5170 Op.getOperand(IsStrict ? 1 : 0), DAG.getConstant(0, DL, MVT::i64));
5171 EVT ScalarVT = VT.getScalarType();
5172 if (IsStrict)
5173 return DAG.getNode(Op.getOpcode(), DL, {ScalarVT, MVT::Other},
5174 {Op.getOperand(0), Extract});
5175 return DAG.getNode(Op.getOpcode(), DL, ScalarVT, Extract);
5176 }
5177
5178 // Type changing conversions are illegal.
5179 return Op;
5180}
5181
5182SDValue AArch64TargetLowering::LowerFP_TO_INT(SDValue Op,
5183 SelectionDAG &DAG) const {
5184 bool IsStrict = Op->isStrictFPOpcode();
5185 SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
5186
5187 if (SrcVal.getValueType().isVector())
5188 return LowerVectorFP_TO_INT(Op, DAG);
5189
5190 // f16 conversions are promoted to f32 when full fp16 is not supported.
5191 if ((SrcVal.getValueType() == MVT::f16 && !Subtarget->hasFullFP16()) ||
5192 SrcVal.getValueType() == MVT::bf16) {
5193 SDLoc DL(Op);
5194 if (IsStrict) {
5195 SDValue Ext =
5196 DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {MVT::f32, MVT::Other},
5197 {Op.getOperand(0), SrcVal});
5198 return DAG.getNode(Op.getOpcode(), DL, {Op.getValueType(), MVT::Other},
5199 {Ext.getValue(1), Ext.getValue(0)});
5200 }
5201 return DAG.getNode(Op.getOpcode(), DL, Op.getValueType(),
5202 DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, SrcVal));
5203 }
5204
5205 if (SrcVal.getValueType() != MVT::f128) {
5206 // It's legal except when f128 is involved
5207 return Op;
5208 }
5209
5210 return SDValue();
5211}
5212
5213SDValue
5214AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue Op,
5215 SelectionDAG &DAG) const {
5216 // AArch64 FP-to-int conversions saturate to the destination element size, so
5217 // we can lower common saturating conversions to simple instructions.
5218 SDValue SrcVal = Op.getOperand(0);
5219 const EVT SrcVT = SrcVal.getValueType();
5220 const EVT DstVT = Op.getValueType();
5221 const EVT DstElementVT = DstVT.getVectorElementType();
5222 const EVT SatVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
5223
5224 [[maybe_unused]] const uint64_t DstElementWidth = DstVT.getScalarSizeInBits();
5225 const uint64_t SrcElementWidth = SrcVT.getScalarSizeInBits();
5226 const uint64_t SatWidth = SatVT.getScalarSizeInBits();
5227 assert(SatWidth <= DstElementWidth &&
5228 "Saturation width cannot exceed result width");
5229
5230 const EVT SrcElementVT = SrcVT.getVectorElementType();
5231 if (SrcElementVT != MVT::f64 && SrcElementVT != MVT::f32 &&
5232 SrcElementVT != MVT::f16 && SrcElementVT != MVT::bf16)
5233 return SDValue();
5234
5235 if (SDValue Res = LowerFPToIntToSVE(Op, DAG))
5236 return Res;
5237
5238 // Returns true if the operation can be matched by an isel pattern directly.
5239 auto CanHandleNatively = [&DstVT, &SatWidth](EVT SrcVT) -> bool {
5240 return SrcVT.getScalarSizeInBits() == DstVT.getScalarSizeInBits() &&
5241 SrcVT.getScalarSizeInBits() == SatWidth;
5242 };
5243
5244 // Returns true if the operation is best expanded.
5245 auto Expand = [&SatWidth, &CanHandleNatively](EVT SrcVT) -> bool {
5246 return !CanHandleNatively(SrcVT) &&
5247 (SrcVT.getScalarSizeInBits() < SatWidth ||
5248 // NEON has no vector MIN/MAX for i64, so it's simpler to scalarize
5249 // (at least until sqxtn is selected).
5250 (SrcVT == MVT::v1f64 || SrcVT == MVT::v2f64));
5251 };
5252
5253 // Try to promote the operation to a wider type if SrcVT < DstVT,
5254 // or if type is bf16 or if the target has no +fullfp16.
5255 std::optional<EVT> PromVT;
5256 switch (SrcElementVT.getSimpleVT().SimpleTy) {
5257 case MVT::f16:
5258 case MVT::bf16:
5259 if (DstElementVT == MVT::i32 || SrcElementVT == MVT::bf16 ||
5260 !Subtarget->hasFullFP16()) {
5261 PromVT = MVT::getVectorVT(MVT::f32, SrcVT.getVectorElementCount());
5262 break;
5263 }
5264 [[fallthrough]];
5265 case MVT::f32:
5266 // Promote to f64
5267 if (DstElementVT == MVT::i64) {
5268 PromVT = MVT::getVectorVT(MVT::f64, SrcVT.getVectorElementCount());
5269 break;
5270 }
5271 [[fallthrough]];
5272 default:
5273 break;
5274 }
5275
5276 SDLoc DL(Op);
5277 unsigned Opc = Op.getOpcode();
5278 if (PromVT && !Expand(*PromVT)) {
5279 // When promoting the input type, SatWidth stays unchanged.
5280 SrcVal = DAG.getNode(ISD::FP_EXTEND, DL, *PromVT, SrcVal);
5281 if (*PromVT != MVT::v8f32 || isTypeLegal(MVT::v8f32))
5282 return DAG.getNode(Op.getOpcode(), DL, DstVT, SrcVal, Op.getOperand(1));
5283
5284 // If we are extending to a wider type (e.g. v8f16 -> v8f32) due to lack
5285 // of fp16 support, then it's more efficient to split the operation
5286 // into two v4f32 to produce legal types.
5287 auto [SrcValLo, SrcValHi] = DAG.SplitVector(SrcVal, DL);
5288 SDValue Lo = DAG.getNode(Opc, DL, MVT::v4i32, SrcValLo, Op.getOperand(1));
5289 SDValue Hi = DAG.getNode(Opc, DL, MVT::v4i32, SrcValHi, Op.getOperand(1));
5290 Lo = DAG.getNode(ISD::TRUNCATE, DL, MVT::v4i16, Lo);
5291 Hi = DAG.getNode(ISD::TRUNCATE, DL, MVT::v4i16, Hi);
5292 return DAG.getNode(ISD::CONCAT_VECTORS, DL, DstVT, Lo, Hi);
5293 }
5294
5295 // Cases that we can emit directly.
5296 if (CanHandleNatively(SrcVT)) {
5297 assert(isTypeLegal(SrcVT) && "Expected SrcVT to be a legal type");
5298 return DAG.getNode(Opc, DL, DstVT, SrcVal,
5299 DAG.getValueType(DstVT.getScalarType()));
5300 } else if (Expand(SrcVT)) {
5301 return SDValue();
5302 }
5303
5304 assert((SrcElementWidth > DstElementWidth) ||
5305 (SrcElementWidth == DstElementWidth && SatWidth < DstElementWidth));
5306
5307 EVT IntVT = SrcVT.changeVectorElementTypeToInteger();
5308 SDValue NativeCvt = DAG.getNode(Opc, DL, IntVT, SrcVal,
5309 DAG.getValueType(IntVT.getScalarType()));
5310 SDValue Sat;
5311 if (Opc == ISD::FP_TO_SINT_SAT) {
5312 SDValue MinC = DAG.getConstant(
5313 APInt::getSignedMaxValue(SatWidth).sext(SrcElementWidth), DL, IntVT);
5314 SDValue Min = DAG.getNode(ISD::SMIN, DL, IntVT, NativeCvt, MinC);
5315 SDValue MaxC = DAG.getConstant(
5316 APInt::getSignedMinValue(SatWidth).sext(SrcElementWidth), DL, IntVT);
5317 Sat = DAG.getNode(ISD::SMAX, DL, IntVT, Min, MaxC);
5318 } else {
5319 SDValue MinC = DAG.getConstant(
5320 APInt::getAllOnes(SatWidth).zext(SrcElementWidth), DL, IntVT);
5321 Sat = DAG.getNode(ISD::UMIN, DL, IntVT, NativeCvt, MinC);
5322 }
5323
5324 return DAG.getNode(ISD::TRUNCATE, DL, DstVT, Sat);
5325}
5326
5327SDValue AArch64TargetLowering::LowerFP_TO_INT_SAT(SDValue Op,
5328 SelectionDAG &DAG) const {
5329 // AArch64 FP-to-int conversions saturate to the destination register size, so
5330 // we can lower common saturating conversions to simple instructions.
5331 SDValue SrcVal = Op.getOperand(0);
5332 EVT SrcVT = SrcVal.getValueType();
5333
5334 if (SrcVT.isVector())
5335 return LowerVectorFP_TO_INT_SAT(Op, DAG);
5336
5337 EVT DstVT = Op.getValueType();
5338 EVT SatVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
5339 uint64_t SatWidth = SatVT.getScalarSizeInBits();
5340 uint64_t DstWidth = DstVT.getScalarSizeInBits();
5341 assert(SatWidth <= DstWidth && "Saturation width cannot exceed result width");
5342
5343 // In the absence of FP16 support, promote f16 to f32 and saturate the result.
5344 if ((SrcVT == MVT::f16 && !Subtarget->hasFullFP16()) || SrcVT == MVT::bf16) {
5345 SrcVal = DAG.getNode(ISD::FP_EXTEND, SDLoc(Op), MVT::f32, SrcVal);
5346 SrcVT = MVT::f32;
5347 } else if (SrcVT != MVT::f64 && SrcVT != MVT::f32 && SrcVT != MVT::f16 &&
5348 SrcVT != MVT::bf16)
5349 return SDValue();
5350
5351 SDLoc DL(Op);
5352 // Cases that we can emit directly.
5353 if ((SrcVT == MVT::f64 || SrcVT == MVT::f32 ||
5354 (SrcVT == MVT::f16 && Subtarget->hasFullFP16())) &&
5355 DstVT == SatVT && (DstVT == MVT::i64 || DstVT == MVT::i32))
5356 return DAG.getNode(Op.getOpcode(), DL, DstVT, SrcVal,
5357 DAG.getValueType(DstVT));
5358
5359 // Otherwise we emit a cvt that saturates to a higher BW, and saturate the
5360 // result. This is only valid if the legal cvt is larger than the saturate
5361 // width.
5362 if (DstWidth < SatWidth)
5363 return SDValue();
5364
5365 if (SrcVT == MVT::f16 && SatVT == MVT::i16 && DstVT == MVT::i32) {
5366 if (Op.getOpcode() == ISD::FP_TO_SINT_SAT) {
5367 SDValue CVTf32 =
5368 DAG.getNode(AArch64ISD::FCVTZS_HALF, DL, MVT::f32, SrcVal);
5369 SDValue Bitcast = DAG.getBitcast(DstVT, CVTf32);
5370 return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, DstVT, Bitcast,
5371 DAG.getValueType(SatVT));
5372 }
5373 SDValue CVTf32 = DAG.getNode(AArch64ISD::FCVTZU_HALF, DL, MVT::f32, SrcVal);
5374 return DAG.getBitcast(DstVT, CVTf32);
5375 }
5376
5377 SDValue NativeCvt =
5378 DAG.getNode(Op.getOpcode(), DL, DstVT, SrcVal, DAG.getValueType(DstVT));
5379 SDValue Sat;
5380 if (Op.getOpcode() == ISD::FP_TO_SINT_SAT) {
5381 SDValue MinC = DAG.getConstant(
5382 APInt::getSignedMaxValue(SatWidth).sext(DstWidth), DL, DstVT);
5383 SDValue Min = DAG.getNode(ISD::SMIN, DL, DstVT, NativeCvt, MinC);
5384 SDValue MaxC = DAG.getConstant(
5385 APInt::getSignedMinValue(SatWidth).sext(DstWidth), DL, DstVT);
5386 Sat = DAG.getNode(ISD::SMAX, DL, DstVT, Min, MaxC);
5387 } else {
5388 SDValue MinC = DAG.getConstant(
5389 APInt::getAllOnes(SatWidth).zext(DstWidth), DL, DstVT);
5390 Sat = DAG.getNode(ISD::UMIN, DL, DstVT, NativeCvt, MinC);
5391 }
5392
5393 return DAG.getNode(ISD::TRUNCATE, DL, DstVT, Sat);
5394}
5395
5396SDValue AArch64TargetLowering::LowerVectorXRINT(SDValue Op,
5397 SelectionDAG &DAG) const {
5398 EVT VT = Op.getValueType();
5399 SDValue Src = Op.getOperand(0);
5400 SDLoc DL(Op);
5401
5402 assert(VT.isVector() && "Expected vector type");
5403
5404 EVT CastVT = VT.changeVectorElementType(
5405 *DAG.getContext(), Src.getValueType().getVectorElementType());
5406
5407 // Round the floating-point value into a floating-point register with the
5408 // current rounding mode.
5409 SDValue FOp = DAG.getNode(ISD::FRINT, DL, CastVT, Src);
5410
5411 // Truncate the rounded floating point to an integer.
5412 return DAG.getNode(ISD::FP_TO_SINT_SAT, DL, VT, FOp,
5414}
5415
5416SDValue AArch64TargetLowering::LowerVectorINT_TO_FP(SDValue Op,
5417 SelectionDAG &DAG) const {
5418 // Warning: We maintain cost tables in AArch64TargetTransformInfo.cpp.
5419 // Any additional optimization in this function should be recorded
5420 // in the cost tables.
5421 bool IsStrict = Op->isStrictFPOpcode();
5422 EVT VT = Op.getValueType();
5423 SDLoc DL(Op);
5424 SDValue In = Op.getOperand(IsStrict ? 1 : 0);
5425 EVT InVT = In.getValueType();
5426 unsigned Opc = Op.getOpcode();
5427 bool IsSigned = Opc == ISD::SINT_TO_FP || Opc == ISD::STRICT_SINT_TO_FP;
5428
5429 assert(!(IsStrict && VT.isScalableVector()) &&
5430 "Unimplemented SVE support for ISD:::STRICT_INT_TO_FP!");
5431
5432 // NOTE: i1->bf16 does not require promotion to f32.
5433 if (VT.isScalableVector() && InVT.getVectorElementType() == MVT::i1) {
5434 SDValue FalseVal = DAG.getConstantFP(0.0, DL, VT);
5435 SDValue TrueVal = IsSigned ? DAG.getConstantFP(-1.0, DL, VT)
5436 : DAG.getConstantFP(1.0, DL, VT);
5437 return DAG.getNode(ISD::VSELECT, DL, VT, In, TrueVal, FalseVal);
5438 }
5439
5440 // Promote bf16 conversions to f32.
5441 if (VT.getVectorElementType() == MVT::bf16) {
5442 EVT F32 = VT.changeElementType(*DAG.getContext(), MVT::f32);
5443 if (IsStrict) {
5444 SDValue Val = DAG.getNode(Op.getOpcode(), DL, {F32, MVT::Other},
5445 {Op.getOperand(0), In});
5446 return DAG.getNode(ISD::STRICT_FP_ROUND, DL,
5447 {Op.getValueType(), MVT::Other},
5448 {Val.getValue(1), Val.getValue(0),
5449 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)});
5450 }
5451 return DAG.getNode(ISD::FP_ROUND, DL, Op.getValueType(),
5452 DAG.getNode(Op.getOpcode(), DL, F32, In),
5453 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
5454 }
5455
5456 if (VT.isScalableVector()) {
5457 // Let common code split the operation.
5458 if (VT == MVT::nxv8f32)
5459 return Op;
5460
5461 unsigned Opcode = IsSigned ? AArch64ISD::SINT_TO_FP_MERGE_PASSTHRU
5462 : AArch64ISD::UINT_TO_FP_MERGE_PASSTHRU;
5463 return LowerToPredicatedOp(Op, DAG, Opcode);
5464 }
5465
5466 if (useSVEForFixedLengthVectorVT(VT, !Subtarget->isNeonAvailable()) ||
5467 useSVEForFixedLengthVectorVT(InVT, !Subtarget->isNeonAvailable()))
5468 return LowerFixedLengthIntToFPToSVE(Op, DAG);
5469
5470 uint64_t VTSize = VT.getFixedSizeInBits();
5471 uint64_t InVTSize = InVT.getFixedSizeInBits();
5472 if (VTSize < InVTSize) {
5473 // AArch64 doesn't have a direct vector instruction to convert
5474 // fixed point to floating point AND narrow it at the same time.
5475 // Additional rounding when the target is f32/f64 causes double
5476 // rounding issues. Conversion to f16 is fine due to narrow width.
5477 bool IsTargetf32 = VT.getVectorElementType() == MVT::f32;
5478 bool IsTargetf16 = false;
5479 if (Op.hasOneUse() &&
5480 Op->user_begin()->getOpcode() == ISD::CONCAT_VECTORS) {
5481 // Some vector types are split during legalization into half, followed by
5482 // concatenation, followed by rounding to the original vector type. If we
5483 // end up resolving to f16 type, we shouldn't worry about rounding errors.
5484 SDNode *U = *Op->user_begin();
5485 if (U->hasOneUse() && U->user_begin()->getOpcode() == ISD::FP_ROUND) {
5486 EVT TmpVT = U->user_begin()->getValueType(0);
5487 if (TmpVT.getScalarType() == MVT::f16)
5488 IsTargetf16 = true;
5489 }
5490 }
5491
5492 if (IsTargetf32 && !IsTargetf16) {
5493 return !IsStrict ? DAG.UnrollVectorOp(Op.getNode()) : SDValue();
5494 }
5495
5496 MVT CastVT =
5498 InVT.getVectorNumElements());
5499 if (IsStrict) {
5500 In = DAG.getNode(Opc, DL, {CastVT, MVT::Other}, {Op.getOperand(0), In});
5501 return DAG.getNode(ISD::STRICT_FP_ROUND, DL, {VT, MVT::Other},
5502 {In.getValue(1), In.getValue(0),
5503 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)});
5504 }
5505 In = DAG.getNode(Opc, DL, CastVT, In);
5506 return DAG.getNode(ISD::FP_ROUND, DL, VT, In,
5507 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
5508 }
5509
5510 if (VTSize > InVTSize) {
5511 unsigned CastOpc = IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
5512 EVT CastVT = VT.changeVectorElementTypeToInteger();
5513 In = DAG.getNode(CastOpc, DL, CastVT, In);
5514 if (IsStrict)
5515 return DAG.getNode(Opc, DL, {VT, MVT::Other}, {Op.getOperand(0), In});
5516 return DAG.getNode(Opc, DL, VT, In);
5517 }
5518
5519 // Use a scalar operation for conversions between single-element vectors of
5520 // the same size.
5521 if (VT.getVectorNumElements() == 1) {
5522 SDValue Extract =
5524 DAG.getConstant(0, DL, MVT::i64));
5525 EVT ScalarVT = VT.getScalarType();
5526 if (IsStrict)
5527 return DAG.getNode(Op.getOpcode(), DL, {ScalarVT, MVT::Other},
5528 {Op.getOperand(0), Extract});
5529 return DAG.getNode(Op.getOpcode(), DL, ScalarVT, Extract);
5530 }
5531
5532 return Op;
5533}
5534
5535SDValue AArch64TargetLowering::LowerINT_TO_FP(SDValue Op,
5536 SelectionDAG &DAG) const {
5537 if (Op.getValueType().isVector())
5538 return LowerVectorINT_TO_FP(Op, DAG);
5539
5540 bool IsStrict = Op->isStrictFPOpcode();
5541 SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
5542
5543 bool IsSigned = Op->getOpcode() == ISD::STRICT_SINT_TO_FP ||
5544 Op->getOpcode() == ISD::SINT_TO_FP;
5545
5546 auto IntToFpViaPromotion = [&](EVT PromoteVT) {
5547 SDLoc DL(Op);
5548 if (IsStrict) {
5549 SDValue Val = DAG.getNode(Op.getOpcode(), DL, {PromoteVT, MVT::Other},
5550 {Op.getOperand(0), SrcVal});
5551 return DAG.getNode(ISD::STRICT_FP_ROUND, DL,
5552 {Op.getValueType(), MVT::Other},
5553 {Val.getValue(1), Val.getValue(0),
5554 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)});
5555 }
5556 return DAG.getNode(ISD::FP_ROUND, DL, Op.getValueType(),
5557 DAG.getNode(Op.getOpcode(), DL, PromoteVT, SrcVal),
5558 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
5559 };
5560
5561 if (Op.getValueType() == MVT::bf16) {
5562 unsigned MaxWidth = IsSigned
5563 ? DAG.ComputeMaxSignificantBits(SrcVal)
5564 : DAG.computeKnownBits(SrcVal).countMaxActiveBits();
5565 // bf16 conversions are promoted to f32 when converting from i16.
5566 if (MaxWidth <= 24) {
5567 return IntToFpViaPromotion(MVT::f32);
5568 }
5569
5570 // bf16 conversions are promoted to f64 when converting from i32.
5571 if (MaxWidth <= 53) {
5572 return IntToFpViaPromotion(MVT::f64);
5573 }
5574
5575 // We need to be careful about i64 -> bf16.
5576 // Consider an i32 22216703.
5577 // This number cannot be represented exactly as an f32 and so a itofp will
5578 // turn it into 22216704.0 fptrunc to bf16 will turn this into 22282240.0
5579 // However, the correct bf16 was supposed to be 22151168.0
5580 // We need to use sticky rounding to get this correct.
5581 if (SrcVal.getValueType() == MVT::i64) {
5582 SDLoc DL(Op);
5583 // This algorithm is equivalent to the following:
5584 // uint64_t SrcHi = SrcVal & ~0xfffull;
5585 // uint64_t SrcLo = SrcVal & 0xfffull;
5586 // uint64_t Highest = SrcVal >> 53;
5587 // bool HasHighest = Highest != 0;
5588 // uint64_t ToRound = HasHighest ? SrcHi : SrcVal;
5589 // double Rounded = static_cast<double>(ToRound);
5590 // uint64_t RoundedBits = std::bit_cast<uint64_t>(Rounded);
5591 // uint64_t HasLo = SrcLo != 0;
5592 // bool NeedsAdjustment = HasHighest & HasLo;
5593 // uint64_t AdjustedBits = RoundedBits | uint64_t{NeedsAdjustment};
5594 // double Adjusted = std::bit_cast<double>(AdjustedBits);
5595 // return static_cast<__bf16>(Adjusted);
5596 //
5597 // Essentially, what happens is that SrcVal either fits perfectly in a
5598 // double-precision value or it is too big. If it is sufficiently small,
5599 // we should just go u64 -> double -> bf16 in a naive way. Otherwise, we
5600 // ensure that u64 -> double has no rounding error by only using the 52
5601 // MSB of the input. The low order bits will get merged into a sticky bit
5602 // which will avoid issues incurred by double rounding.
5603
5604 // Signed conversion is more or less like so:
5605 // copysign((__bf16)abs(SrcVal), SrcVal)
5606 SDValue SignBit;
5607 if (IsSigned) {
5608 SignBit = DAG.getNode(ISD::AND, DL, MVT::i64, SrcVal,
5609 DAG.getConstant(1ull << 63, DL, MVT::i64));
5610 SrcVal = DAG.getNode(ISD::ABS, DL, MVT::i64, SrcVal);
5611 }
5612 SDValue SrcHi = DAG.getNode(ISD::AND, DL, MVT::i64, SrcVal,
5613 DAG.getConstant(~0xfffull, DL, MVT::i64));
5614 SDValue SrcLo = DAG.getNode(ISD::AND, DL, MVT::i64, SrcVal,
5615 DAG.getConstant(0xfffull, DL, MVT::i64));
5616 SDValue Highest =
5617 DAG.getNode(ISD::SRL, DL, MVT::i64, SrcVal,
5618 DAG.getShiftAmountConstant(53, MVT::i64, DL));
5619 SDValue Zero64 = DAG.getConstant(0, DL, MVT::i64);
5620 SDValue ToRound =
5621 DAG.getSelectCC(DL, Highest, Zero64, SrcHi, SrcVal, ISD::SETNE);
5622 SDValue Rounded =
5623 IsStrict ? DAG.getNode(Op.getOpcode(), DL, {MVT::f64, MVT::Other},
5624 {Op.getOperand(0), ToRound})
5625 : DAG.getNode(Op.getOpcode(), DL, MVT::f64, ToRound);
5626
5627 SDValue RoundedBits = DAG.getNode(ISD::BITCAST, DL, MVT::i64, Rounded);
5628 if (SignBit) {
5629 RoundedBits = DAG.getNode(ISD::OR, DL, MVT::i64, RoundedBits, SignBit);
5630 }
5631
5632 SDValue HasHighest = DAG.getSetCC(
5633 DL,
5634 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::i64),
5635 Highest, Zero64, ISD::SETNE);
5636
5637 SDValue HasLo = DAG.getSetCC(
5638 DL,
5639 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::i64),
5640 SrcLo, Zero64, ISD::SETNE);
5641
5642 SDValue NeedsAdjustment =
5643 DAG.getNode(ISD::AND, DL, HasLo.getValueType(), HasHighest, HasLo);
5644 NeedsAdjustment = DAG.getZExtOrTrunc(NeedsAdjustment, DL, MVT::i64);
5645
5646 SDValue AdjustedBits =
5647 DAG.getNode(ISD::OR, DL, MVT::i64, RoundedBits, NeedsAdjustment);
5648 SDValue Adjusted = DAG.getNode(ISD::BITCAST, DL, MVT::f64, AdjustedBits);
5649 return IsStrict
5650 ? DAG.getNode(
5652 {Op.getValueType(), MVT::Other},
5653 {Rounded.getValue(1), Adjusted,
5654 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)})
5655 : DAG.getNode(ISD::FP_ROUND, DL, Op.getValueType(), Adjusted,
5656 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
5657 }
5658 }
5659
5660 // f16 conversions are promoted to f32 when full fp16 is not supported.
5661 if (Op.getValueType() == MVT::f16 && !Subtarget->hasFullFP16()) {
5662 return IntToFpViaPromotion(MVT::f32);
5663 }
5664
5665 // i128 conversions are libcalls.
5666 if (SrcVal.getValueType() == MVT::i128)
5667 return SDValue();
5668
5669 // Other conversions are legal, unless it's to the completely software-based
5670 // fp128.
5671 if (Op.getValueType() != MVT::f128)
5672 return Op;
5673 return SDValue();
5674}
5675
5676static MVT getSVEContainerType(EVT ContentTy);
5677
5678SDValue
5679AArch64TargetLowering::LowerLOOP_DEPENDENCE_MASK(SDValue Op,
5680 SelectionDAG &DAG) const {
5681 assert((Subtarget->hasSVE2() ||
5682 (Subtarget->hasSME() && Subtarget->isStreaming())) &&
5683 "Lowering loop_dependence_raw_mask or loop_dependence_war_mask "
5684 "requires SVE or SME");
5685
5686 SDLoc DL(Op);
5687 EVT VT = Op.getValueType();
5688 unsigned LaneOffset = Op.getConstantOperandVal(3);
5689 unsigned NumElements = VT.getVectorMinNumElements();
5690 uint64_t EltSizeInBytes = Op.getConstantOperandVal(2);
5691 EVT AddrTy = Op->getOperand(0).getValueType();
5692
5693 // Lane offsets and other element sizes are not supported by whilewr/rw.
5694 if (LaneOffset != 0 || !is_contained({1u, 2u, 4u, 8u}, EltSizeInBytes))
5695 return SDValue();
5696
5697 EVT EltVT = MVT::getIntegerVT(EltSizeInBytes * 8);
5698 EVT PredVT =
5699 getPackedSVEVectorVT(EltVT).changeElementType(*DAG.getContext(), MVT::i1);
5700
5701 if (PredVT == VT) {
5702 // Legal whilewr/rw (lowered by tablegen matcher).
5703 if (AddrTy == MVT::i64)
5704 return Op;
5705
5706 // Almost legal whilewr/rw (addresses must be promoted to i64).
5707 assert(AddrTy == MVT::i32 && "Only expected i32 to be legal!");
5708 return DAG.getNode(
5709 Op.getOpcode(), DL, VT,
5710 DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Op->getOperand(0)),
5711 DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Op->getOperand(1)),
5712 DAG.getConstant(EltSizeInBytes, DL, MVT::i64), Op->getOperand(3));
5713 }
5714
5715 // Expand if this mask needs splitting (this will produce a whilelo).
5716 if (NumElements > PredVT.getVectorMinNumElements())
5717 return SDValue();
5718
5719 SDValue Mask =
5720 DAG.getNode(Op.getOpcode(), DL, PredVT, to_vector(Op->op_values()));
5721
5722 if (VT.isFixedLengthVector()) {
5723 EVT WidePredVT =
5724 PredVT.changeElementType(*DAG.getContext(), VT.getScalarType());
5725 SDValue MaskAsInt = DAG.getNode(ISD::SIGN_EXTEND, DL, WidePredVT, Mask);
5726 return convertFromScalableVector(DAG, VT, MaskAsInt);
5727 }
5728
5729 return DAG.getExtractSubvector(DL, VT, Mask, 0);
5730}
5731
5732SDValue AArch64TargetLowering::LowerBITCAST(SDValue Op,
5733 SelectionDAG &DAG) const {
5734 EVT OpVT = Op.getValueType();
5735 EVT ArgVT = Op.getOperand(0).getValueType();
5736
5738 return LowerFixedLengthBitcastToSVE(Op, DAG);
5739
5740 if (OpVT.isScalableVector()) {
5741 assert(isTypeLegal(OpVT) && "Unexpected result type!");
5742
5743 // Handle type legalisation first.
5744 if (!isTypeLegal(ArgVT)) {
5745 assert(OpVT.isFloatingPoint() && !ArgVT.isFloatingPoint() &&
5746 "Expected int->fp bitcast!");
5747
5748 // Bitcasting between unpacked vector types of different element counts is
5749 // not a NOP because the live elements are laid out differently.
5750 // 01234567
5751 // e.g. nxv2i32 = XX??XX??
5752 // nxv4f16 = X?X?X?X?
5753 if (OpVT.getVectorElementCount() != ArgVT.getVectorElementCount())
5754 return SDValue();
5755
5756 SDValue ExtResult =
5757 DAG.getNode(ISD::ANY_EXTEND, SDLoc(Op), getSVEContainerType(ArgVT),
5758 Op.getOperand(0));
5759 return getSVESafeBitCast(OpVT, ExtResult, DAG);
5760 }
5761
5762 // Bitcasts between legal types with the same element count are legal.
5763 if (OpVT.getVectorElementCount() == ArgVT.getVectorElementCount())
5764 return Op;
5765
5766 // getSVESafeBitCast does not support casting between unpacked types.
5767 if (!isPackedVectorType(OpVT, DAG))
5768 return SDValue();
5769
5770 return getSVESafeBitCast(OpVT, Op.getOperand(0), DAG);
5771 }
5772
5773 if (OpVT != MVT::f16 && OpVT != MVT::bf16)
5774 return SDValue();
5775
5776 // Bitcasts between f16 and bf16 are legal.
5777 if (ArgVT == MVT::f16 || ArgVT == MVT::bf16)
5778 return Op;
5779
5780 SDValue Src = Op.getOperand(0);
5781 SDLoc DL(Op);
5782 if (ArgVT.isVector() && ArgVT.getSizeInBits() == 16) {
5783 Src = DAG.getNode(ISD::BITCAST, DL, MVT::i16, Src);
5784 ArgVT = MVT::i16;
5785 }
5786
5787 assert(ArgVT == MVT::i16);
5788
5789 // If the input from a vector, extract directly from it.
5790 if (Src.getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
5791 Op = DAG.getNode(ISD::BITCAST, DL,
5792 Src.getOperand(0).getValueType().changeElementType(
5793 *DAG.getContext(), OpVT),
5794 Src.getOperand(0));
5795 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, OpVT, Op,
5796 Src.getOperand(1));
5797 }
5798
5799 Op = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v8i16, Src);
5800 Op = DAG.getNode(ISD::BITCAST, DL,
5801 EVT::getVectorVT(*DAG.getContext(), OpVT, 8), Op);
5802 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, OpVT, Op,
5803 DAG.getConstant(0, DL, MVT::i64));
5804}
5805
5806// Returns lane if Op extracts from a two-element vector and lane is constant
5807// (i.e., extractelt(<2 x Ty> %v, ConstantLane)), and std::nullopt otherwise.
5808static std::optional<uint64_t>
5810 SDNode *OpNode = Op.getNode();
5811 if (OpNode->getOpcode() != ISD::EXTRACT_VECTOR_ELT)
5812 return std::nullopt;
5813
5814 EVT VT = OpNode->getOperand(0).getValueType();
5816 if (!VT.isFixedLengthVector() || VT.getVectorNumElements() != 2 || !C)
5817 return std::nullopt;
5818
5819 return C->getZExtValue();
5820}
5821
5823 bool isSigned) {
5824 EVT VT = N.getValueType();
5825
5826 if (N.getOpcode() != ISD::BUILD_VECTOR)
5827 return false;
5828
5829 for (const SDValue &Elt : N->op_values()) {
5831 unsigned EltSize = VT.getScalarSizeInBits();
5832 unsigned HalfSize = EltSize / 2;
5833 if (isSigned) {
5834 if (!isIntN(HalfSize, C->getSExtValue()))
5835 return false;
5836 } else {
5837 if (!isUIntN(HalfSize, C->getZExtValue()))
5838 return false;
5839 }
5840 continue;
5841 }
5842 return false;
5843 }
5844
5845 return true;
5846}
5847
5849 EVT VT = N.getValueType();
5850 assert(VT.is128BitVector() && "Unexpected vector MULL size");
5851 EVT HalfVT = EVT::getVectorVT(
5852 *DAG.getContext(),
5855 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), HalfVT, N);
5856}
5857
5859 return N.getOpcode() == ISD::SIGN_EXTEND ||
5860 N.getOpcode() == ISD::ANY_EXTEND ||
5861 isExtendedBUILD_VECTOR(N, DAG, true);
5862}
5863
5865 return N.getOpcode() == ISD::ZERO_EXTEND ||
5866 N.getOpcode() == ISD::ANY_EXTEND ||
5867 isExtendedBUILD_VECTOR(N, DAG, false);
5868}
5869
5871 unsigned Opcode = N.getOpcode();
5872 if (Opcode == ISD::ADD || Opcode == ISD::SUB) {
5873 SDValue N0 = N.getOperand(0);
5874 SDValue N1 = N.getOperand(1);
5875 return N0->hasOneUse() && N1->hasOneUse() &&
5876 isSignExtended(N0, DAG) && isSignExtended(N1, DAG);
5877 }
5878 return false;
5879}
5880
5882 unsigned Opcode = N.getOpcode();
5883 if (Opcode == ISD::ADD || Opcode == ISD::SUB) {
5884 SDValue N0 = N.getOperand(0);
5885 SDValue N1 = N.getOperand(1);
5886 return N0->hasOneUse() && N1->hasOneUse() &&
5887 isZeroExtended(N0, DAG) && isZeroExtended(N1, DAG);
5888 }
5889 return false;
5890}
5891
5892SDValue AArch64TargetLowering::LowerGET_ROUNDING(SDValue Op,
5893 SelectionDAG &DAG) const {
5894 // The rounding mode is in bits 23:22 of the FPCR.
5895 // The ARM rounding mode value to FLT_ROUNDS mapping is 0->1, 1->2, 2->3, 3->0
5896 // The formula we use to implement this is (((FPCR + (1 << 22)) >> 22) & 3)
5897 // so that the shift + and get folded into a bitfield extract.
5898 SDLoc DL(Op);
5899
5900 SDValue Chain = Op.getOperand(0);
5901 SDValue FPCR_64 =
5902 DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, {MVT::i64, MVT::Other},
5903 {Chain, DAG.getTargetConstant(Intrinsic::aarch64_get_fpcr, DL,
5904 MVT::i64)});
5905 Chain = FPCR_64.getValue(1);
5906 SDValue FPCR_32 = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, FPCR_64);
5907 SDValue FltRounds = DAG.getNode(ISD::ADD, DL, MVT::i32, FPCR_32,
5908 DAG.getConstant(1U << 22, DL, MVT::i32));
5909 SDValue RMODE = DAG.getNode(ISD::SRL, DL, MVT::i32, FltRounds,
5910 DAG.getConstant(22, DL, MVT::i32));
5911 SDValue AND = DAG.getNode(ISD::AND, DL, MVT::i32, RMODE,
5912 DAG.getConstant(3, DL, MVT::i32));
5913 return DAG.getMergeValues({AND, Chain}, DL);
5914}
5915
5916SDValue AArch64TargetLowering::LowerSET_ROUNDING(SDValue Op,
5917 SelectionDAG &DAG) const {
5918 SDLoc DL(Op);
5919 SDValue Chain = Op->getOperand(0);
5920 SDValue RMValue = Op->getOperand(1);
5921
5922 // The rounding mode is in bits 23:22 of the FPCR.
5923 // The llvm.set.rounding argument value to the rounding mode in FPCR mapping
5924 // is 0->3, 1->0, 2->1, 3->2. The formula we use to implement this is
5925 // ((arg - 1) & 3) << 22).
5926 //
5927 // The argument of llvm.set.rounding must be within the segment [0, 3], so
5928 // NearestTiesToAway (4) is not handled here. It is responsibility of the code
5929 // generated llvm.set.rounding to ensure this condition.
5930
5931 // Calculate new value of FPCR[23:22].
5932 RMValue = DAG.getNode(ISD::SUB, DL, MVT::i32, RMValue,
5933 DAG.getConstant(1, DL, MVT::i32));
5934 RMValue = DAG.getNode(ISD::AND, DL, MVT::i32, RMValue,
5935 DAG.getConstant(0x3, DL, MVT::i32));
5936 RMValue =
5937 DAG.getNode(ISD::SHL, DL, MVT::i32, RMValue,
5938 DAG.getConstant(AArch64::RoundingBitsPos, DL, MVT::i32));
5939 RMValue = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, RMValue);
5940
5941 // Get current value of FPCR.
5942 SDValue Ops[] = {
5943 Chain, DAG.getTargetConstant(Intrinsic::aarch64_get_fpcr, DL, MVT::i64)};
5944 SDValue FPCR =
5945 DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, {MVT::i64, MVT::Other}, Ops);
5946 Chain = FPCR.getValue(1);
5947 FPCR = FPCR.getValue(0);
5948
5949 // Put new rounding mode into FPCR[23:22].
5950 const int RMMask = ~(AArch64::Rounding::rmMask << AArch64::RoundingBitsPos);
5951 FPCR = DAG.getNode(ISD::AND, DL, MVT::i64, FPCR,
5952 DAG.getConstant(RMMask, DL, MVT::i64));
5953 FPCR = DAG.getNode(ISD::OR, DL, MVT::i64, FPCR, RMValue);
5954 SDValue Ops2[] = {
5955 Chain, DAG.getTargetConstant(Intrinsic::aarch64_set_fpcr, DL, MVT::i64),
5956 FPCR};
5957 return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops2);
5958}
5959
5960SDValue AArch64TargetLowering::LowerGET_FPMODE(SDValue Op,
5961 SelectionDAG &DAG) const {
5962 SDLoc DL(Op);
5963 SDValue Chain = Op->getOperand(0);
5964
5965 // Get current value of FPCR.
5966 SDValue Ops[] = {
5967 Chain, DAG.getTargetConstant(Intrinsic::aarch64_get_fpcr, DL, MVT::i64)};
5968 SDValue FPCR =
5969 DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, {MVT::i64, MVT::Other}, Ops);
5970 Chain = FPCR.getValue(1);
5971 FPCR = FPCR.getValue(0);
5972
5973 // Truncate FPCR to 32 bits.
5974 SDValue Result = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, FPCR);
5975
5976 return DAG.getMergeValues({Result, Chain}, DL);
5977}
5978
5979SDValue AArch64TargetLowering::LowerSET_FPMODE(SDValue Op,
5980 SelectionDAG &DAG) const {
5981 SDLoc DL(Op);
5982 SDValue Chain = Op->getOperand(0);
5983 SDValue Mode = Op->getOperand(1);
5984
5985 // Extend the specified value to 64 bits.
5986 SDValue FPCR = DAG.getZExtOrTrunc(Mode, DL, MVT::i64);
5987
5988 // Set new value of FPCR.
5989 SDValue Ops2[] = {
5990 Chain, DAG.getTargetConstant(Intrinsic::aarch64_set_fpcr, DL, MVT::i64),
5991 FPCR};
5992 return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops2);
5993}
5994
5995SDValue AArch64TargetLowering::LowerRESET_FPMODE(SDValue Op,
5996 SelectionDAG &DAG) const {
5997 SDLoc DL(Op);
5998 SDValue Chain = Op->getOperand(0);
5999
6000 // Get current value of FPCR.
6001 SDValue Ops[] = {
6002 Chain, DAG.getTargetConstant(Intrinsic::aarch64_get_fpcr, DL, MVT::i64)};
6003 SDValue FPCR =
6004 DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, {MVT::i64, MVT::Other}, Ops);
6005 Chain = FPCR.getValue(1);
6006 FPCR = FPCR.getValue(0);
6007
6008 // Clear bits that are not reserved.
6009 SDValue FPCRMasked = DAG.getNode(
6010 ISD::AND, DL, MVT::i64, FPCR,
6012
6013 // Set new value of FPCR.
6014 SDValue Ops2[] = {
6015 Chain, DAG.getTargetConstant(Intrinsic::aarch64_set_fpcr, DL, MVT::i64),
6016 FPCRMasked};
6017 return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops2);
6018}
6019
6020static unsigned selectUmullSmull(SDValue &N0, SDValue &N1, SelectionDAG &DAG,
6021 SDLoc DL, bool &IsMLA) {
6022 bool IsN0SExt = isSignExtended(N0, DAG);
6023 bool IsN1SExt = isSignExtended(N1, DAG);
6024 if (IsN0SExt && IsN1SExt)
6025 return AArch64ISD::SMULL;
6026
6027 bool IsN0ZExt = isZeroExtended(N0, DAG);
6028 bool IsN1ZExt = isZeroExtended(N1, DAG);
6029
6030 if (IsN0ZExt && IsN1ZExt)
6031 return AArch64ISD::UMULL;
6032
6033 // Select UMULL if we can replace the other operand with an extend.
6034 EVT VT = N0.getValueType();
6035 unsigned EltSize = VT.getScalarSizeInBits();
6036 APInt Mask = APInt::getHighBitsSet(EltSize, EltSize / 2);
6037 if (IsN0ZExt || IsN1ZExt) {
6038 if (DAG.MaskedValueIsZero(IsN0ZExt ? N1 : N0, Mask))
6039 return AArch64ISD::UMULL;
6040 } else if (VT == MVT::v2i64 && DAG.MaskedValueIsZero(N0, Mask) &&
6041 DAG.MaskedValueIsZero(N1, Mask)) {
6042 // For v2i64 we look more aggressively at both operands being zero, to avoid
6043 // scalarization.
6044 return AArch64ISD::UMULL;
6045 }
6046
6047 if (IsN0SExt || IsN1SExt) {
6048 if (DAG.ComputeNumSignBits(IsN0SExt ? N1 : N0) > EltSize / 2)
6049 return AArch64ISD::SMULL;
6050 } else if (VT == MVT::v2i64 && DAG.ComputeNumSignBits(N0) > EltSize / 2 &&
6051 DAG.ComputeNumSignBits(N1) > EltSize / 2) {
6052 return AArch64ISD::SMULL;
6053 }
6054
6055 if (!IsN1SExt && !IsN1ZExt)
6056 return 0;
6057
6058 // Look for (s/zext A + s/zext B) * (s/zext C). We want to turn these
6059 // into (s/zext A * s/zext C) + (s/zext B * s/zext C)
6060 if (IsN1SExt && isAddSubSExt(N0, DAG)) {
6061 IsMLA = true;
6062 return AArch64ISD::SMULL;
6063 }
6064 if (IsN1ZExt && isAddSubZExt(N0, DAG)) {
6065 IsMLA = true;
6066 return AArch64ISD::UMULL;
6067 }
6068 if (IsN0ZExt && isAddSubZExt(N1, DAG)) {
6069 std::swap(N0, N1);
6070 IsMLA = true;
6071 return AArch64ISD::UMULL;
6072 }
6073 return 0;
6074}
6075
6076// Transform mul<v2i64, splat(const)> into a SHL and ADD/SUB
6077// (1) multiply-by-(power-of-2 +/- 1) into shift and add/sub.
6078// mul x, (2^N + 1) --> add (shl x, N), x
6079// mul x, (2^N - 1) --> sub (shl x, N), x
6080// Examples: x * 33 --> (x << 5) + x
6081// x * 15 --> (x << 4) - x
6082// x * -33 --> -((x << 5) + x)
6083// x * -15 --> -((x << 4) - x) ; this reduces --> x - (x << 4)
6084// (2) multiply-by-(power-of-2 +/- power-of-2) into shifts and add/sub.
6085// mul x, (2^N + 2^M) --> (add (shl x, N), (shl x, M))
6086// mul x, (2^N - 2^M) --> (sub (shl x, N), (shl x, M))
6087// Examples: x * 0x8800 --> (x << 15) + (x << 11)
6088// x * 0xf800 --> (x << 16) - (x << 11)
6089// x * -0x8800 --> -((x << 15) + (x << 11))
6090// x * -0xf800 --> -((x << 16) - (x << 11)) ; (x << 11) - (x << 16)
6092 const SDNode *Operand = N->getOperand(1).getNode();
6093 APInt SplatValue;
6094
6095 // Not a constant splat so should just stay as a multiplication operation
6096 if (!ISD::isConstantSplatVector(Operand, SplatValue) ||
6097 !SplatValue.getBoolValue())
6098 return SDValue();
6099
6100 bool IsNegative = SplatValue.isNegative();
6101 SplatValue = SplatValue.abs();
6102 // Placeholder for MathOp
6103 unsigned MathOp = ISD::DELETED_NODE;
6104 unsigned TZeros = SplatValue.countr_zero();
6105
6106 // Shift the splat value by all the zeros, this won't affect the parity
6107 // this will help us find the first and second multiple to use.
6108 SplatValue.lshrInPlace(TZeros);
6109
6110 if ((SplatValue - 1).isPowerOf2())
6111 MathOp = ISD::ADD;
6112 else if ((SplatValue + 1).isPowerOf2())
6113 MathOp = ISD::SUB;
6114
6115 // If the constant is not (2^n + 1) or (2^n - 1), it would require
6116 // more than one addition/subtraction. For v2i64, the cost of
6117 // multiple vector adds/shifts often exceeds the cost of
6118 // scalarization (moving to GPRs to use a single MUL).
6119 if (MathOp != ISD::DELETED_NODE) {
6120 SDLoc DL(N);
6121 EVT VT = N->getValueType(0);
6122 SDValue LHS = N->getOperand(0);
6123
6124 unsigned ShiftAmt = MathOp == ISD::ADD ? (SplatValue - 1).logBase2()
6125 : (SplatValue + 1).logBase2();
6126 ShiftAmt += TZeros;
6127
6128 SDValue Shl =
6129 DAG.getNode(ISD::SHL, DL, VT, LHS, DAG.getConstant(ShiftAmt, DL, VT));
6130
6131 SDValue NewLHS = TZeros ? DAG.getNode(ISD::SHL, DL, VT, LHS,
6132 DAG.getConstant(TZeros, DL, VT))
6133 : LHS;
6134 SDValue Combined = DAG.getNode(MathOp, DL, VT, Shl, NewLHS);
6135 if (IsNegative)
6136 Combined = DAG.getNegative(Combined, DL, VT);
6137 return Combined;
6138 }
6139 return SDValue();
6140}
6141
6142SDValue AArch64TargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
6143 EVT VT = Op.getValueType();
6144
6145 bool OverrideNEON = !Subtarget->isNeonAvailable();
6146 if (VT.isScalableVector() || useSVEForFixedLengthVectorVT(VT, OverrideNEON))
6147 return LowerToPredicatedOp(Op, DAG, AArch64ISD::MUL_PRED);
6148
6149 // Multiplications are only custom-lowered for 128-bit and 64-bit vectors so
6150 // that VMULL can be detected. Otherwise v2i64 multiplications are not legal.
6151 assert((VT.is128BitVector() || VT.is64BitVector()) && VT.isInteger() &&
6152 "unexpected type for custom-lowering ISD::MUL");
6153 SDValue N0 = Op.getOperand(0);
6154 SDValue N1 = Op.getOperand(1);
6155 bool isMLA = false;
6156 EVT OVT = VT;
6157 if (VT.is64BitVector()) {
6158 if (N0.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
6159 isNullConstant(N0.getOperand(1)) &&
6162 isNullConstant(N1.getOperand(1)) &&
6164 N0 = N0.getOperand(0);
6165 N1 = N1.getOperand(0);
6166 VT = N0.getValueType();
6167 } else {
6168 if (VT == MVT::v1i64) {
6169 if (Subtarget->hasSVE())
6170 return LowerToPredicatedOp(Op, DAG, AArch64ISD::MUL_PRED);
6171 // Fall through to expand this. It is not legal.
6172 return SDValue();
6173 } else
6174 // Other vector multiplications are legal.
6175 return Op;
6176 }
6177 }
6178
6179 SDLoc DL(Op);
6180 unsigned NewOpc = selectUmullSmull(N0, N1, DAG, DL, isMLA);
6181
6182 if (!NewOpc) {
6183 if (VT.getVectorElementType() == MVT::i64) {
6184 // If SVE is available then i64 vector multiplications can also be made
6185 // legal.
6186 if (Subtarget->hasSVE())
6187 return LowerToPredicatedOp(Op, DAG, AArch64ISD::MUL_PRED);
6188 // Try to optimize the mul to a shift left and add instead of scalarizing.
6189 if (SDValue ShlAdd = convertMulToShlAdd(Op.getNode(), DAG))
6190 return ShlAdd;
6191 // Fall through to expanding as the mul is not legal.
6192 return SDValue();
6193 } else
6194 // Other vector multiplications are legal.
6195 return Op;
6196 }
6197
6198 // Legalize to a S/UMULL instruction
6199 SDValue Op0;
6200 SDValue Op1 = skipExtensionForVectorMULL(N1, DAG);
6201 if (!isMLA) {
6202 Op0 = skipExtensionForVectorMULL(N0, DAG);
6204 Op1.getValueType().is64BitVector() &&
6205 "unexpected types for extended operands to VMULL");
6206 return DAG.getExtractSubvector(DL, OVT,
6207 DAG.getNode(NewOpc, DL, VT, Op0, Op1), 0);
6208 }
6209 // Optimizing (zext A + zext B) * C, to (S/UMULL A, C) + (S/UMULL B, C) during
6210 // isel lowering to take advantage of no-stall back to back s/umul + s/umla.
6211 // This is true for CPUs with accumulate forwarding such as Cortex-A53/A57
6214 EVT Op1VT = Op1.getValueType();
6215 return DAG.getNode(
6217 DAG.getNode(N0.getOpcode(), DL, VT,
6218 DAG.getNode(NewOpc, DL, VT,
6219 DAG.getNode(ISD::BITCAST, DL, Op1VT, N00), Op1),
6220 DAG.getNode(NewOpc, DL, VT,
6221 DAG.getNode(ISD::BITCAST, DL, Op1VT, N01), Op1)),
6222 DAG.getConstant(0, DL, MVT::i64));
6223}
6224
6225static inline SDValue getPTrue(SelectionDAG &DAG, SDLoc DL, EVT VT,
6226 int Pattern) {
6227 if (Pattern == AArch64SVEPredPattern::all)
6228 return DAG.getConstant(1, DL, VT);
6229
6230 // When the number of active elements of a pattern matches the scalable vector
6231 // length, we can upgrade the pattern to ALL and emit a splat instead.
6232 if (unsigned PatNumElts = getNumElementsFromSVEPredPattern(Pattern)) {
6233 const AArch64Subtarget &Subtarget = DAG.getSubtarget<AArch64Subtarget>();
6234 unsigned NumElts = VT.getVectorMinNumElements();
6235 unsigned VScale = Subtarget.getSVEVectorSizeInBits() / 128;
6236 if (PatNumElts == (NumElts * VScale))
6237 return DAG.getConstant(1, DL, VT);
6238 }
6239
6240 return DAG.getNode(AArch64ISD::PTRUE, DL, VT,
6241 DAG.getTargetConstant(Pattern, DL, MVT::i32));
6242}
6243
6245 Intrinsic::ID IID;
6246
6247 switch (VT.getScalarSizeInBits()) {
6248 default:
6249 llvm_unreachable("unsupported predicate element size");
6250 case 8:
6251 IID = Intrinsic::aarch64_sve_ptrue_c8;
6252 break;
6253 case 16:
6254 IID = Intrinsic::aarch64_sve_ptrue_c16;
6255 break;
6256 case 32:
6257 IID = Intrinsic::aarch64_sve_ptrue_c32;
6258 break;
6259 case 64:
6260 IID = Intrinsic::aarch64_sve_ptrue_c64;
6261 break;
6262 }
6263
6264 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::aarch64svcount,
6265 DAG.getConstant(IID, DL, MVT::i64));
6266}
6267
6269 bool IsSigned, bool IsEqual) {
6270 unsigned Op0 = N->getOpcode() == ISD::INTRINSIC_WO_CHAIN ? 1 : 0;
6271 unsigned Op1 = N->getOpcode() == ISD::INTRINSIC_WO_CHAIN ? 2 : 1;
6272
6273 if (!N->getValueType(0).isScalableVector() ||
6274 !isa<ConstantSDNode>(N->getOperand(Op1)))
6275 return SDValue();
6276
6277 SDLoc DL(N);
6278 APInt Y = N->getConstantOperandAPInt(Op1);
6279
6280 // When the second operand is the maximum value, comparisons that include
6281 // equality can never fail and thus we can return an all active predicate.
6282 if (IsEqual)
6283 if (IsSigned ? Y.isMaxSignedValue() : Y.isMaxValue())
6284 return DAG.getConstant(1, DL, N->getValueType(0));
6285
6286 if (!isa<ConstantSDNode>(N->getOperand(Op0)))
6287 return SDValue();
6288
6289 APInt X = N->getConstantOperandAPInt(Op0);
6290
6291 bool Overflow;
6292 APInt NumActiveElems =
6293 IsSigned ? Y.ssub_ov(X, Overflow) : Y.usub_ov(X, Overflow);
6294
6295 if (Overflow)
6296 return SDValue();
6297
6298 if (IsEqual) {
6299 APInt One(NumActiveElems.getBitWidth(), 1, IsSigned);
6300 NumActiveElems = IsSigned ? NumActiveElems.sadd_ov(One, Overflow)
6301 : NumActiveElems.uadd_ov(One, Overflow);
6302 if (Overflow)
6303 return SDValue();
6304 }
6305
6306 std::optional<unsigned> PredPattern =
6308 unsigned MinSVEVectorSize = std::max(
6310 unsigned ElementSize = 128 / N->getValueType(0).getVectorMinNumElements();
6311 if (PredPattern != std::nullopt &&
6312 NumActiveElems.getZExtValue() <= (MinSVEVectorSize / ElementSize))
6313 return getPTrue(DAG, DL, N->getValueType(0), *PredPattern);
6314
6315 return SDValue();
6316}
6317
6318// Match get.active.lane.mask(0, cttz.elts(x)) -> brkb(x)
6319// Match get.active.lane.mask(0, add(cttz.elts(x), 1)) -> brka(x)
6321 SDLoc DL(N);
6322 EVT VT = N->getValueType(0);
6323 // Lower bound must be 0.
6324 if (!isZeroOrZeroSplat(N->getOperand(0)))
6325 return SDValue();
6326
6327 SDValue Upper = N->getOperand(1);
6328
6329 // Default to brkb, switch to brka if we find a +1.
6330 unsigned BrkID = Intrinsic::aarch64_sve_brkb_z;
6331 if (Upper->getOpcode() == ISD::ADD && isOneOrOneSplat(Upper.getOperand(1))) {
6332 Upper = Upper.getOperand(0);
6333 BrkID = Intrinsic::aarch64_sve_brka_z;
6334 }
6335
6336 // We're looking for an upper bound based on CTTZ_ELTS; this would be selected
6337 // as a cntp(brk(Pg, Mask)), but if we're just going to make a whilelo based
6338 // on that then we just need the brk.
6339 if (Upper.getOpcode() != AArch64ISD::CTTZ_ELTS || !VT.isScalableVector() ||
6340 Upper.getOperand(0).getValueType() != VT)
6341 return SDValue();
6342
6343 SDValue Pg = Upper->getOperand(0);
6344 SDValue Mask = Upper->getOperand(1);
6345
6346 // brk{a,b} only support .b forms, so cast to make sure all our p regs match.
6347 Pg = getSVEPredicateBitCast(MVT::nxv16i1, Pg, DAG);
6348 SDValue MaskR =
6349 DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, MVT::nxv16i1, Mask);
6350 SDValue ID = DAG.getTargetConstant(BrkID, DL, MVT::i64);
6351 SDValue Brk =
6352 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::nxv16i1, ID, Pg, MaskR);
6353 return DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, VT, Brk);
6354}
6355
6356// Returns a safe bitcast between two scalable vector predicates, where
6357// any newly created lanes from a widening bitcast are defined as zero.
6359 SDLoc DL(Op);
6360 EVT InVT = Op.getValueType();
6361
6362 assert(InVT.getVectorElementType() == MVT::i1 &&
6363 VT.getVectorElementType() == MVT::i1 &&
6364 "Expected a predicate-to-predicate bitcast");
6366 InVT.isScalableVector() &&
6367 DAG.getTargetLoweringInfo().isTypeLegal(InVT) &&
6368 "Only expect to cast between legal scalable predicate types!");
6369
6370 // Return the operand if the cast isn't changing type,
6371 if (InVT == VT)
6372 return Op;
6373
6374 // Look through casts to <vscale x 16 x i1> when their input has more lanes
6375 // than VT. This will increase the chances of removing casts that introduce
6376 // new lanes, which have to be explicitly zero'd.
6377 if (Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN &&
6378 Op.getConstantOperandVal(0) == Intrinsic::aarch64_sve_convert_to_svbool &&
6379 Op.getOperand(1).getValueType().bitsGT(VT))
6380 Op = Op.getOperand(1);
6381
6382 SDValue Reinterpret = DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, VT, Op);
6383
6384 // We only have to zero the lanes if new lanes are being defined, e.g. when
6385 // casting from <vscale x 2 x i1> to <vscale x 16 x i1>. If this is not the
6386 // case (e.g. when casting from <vscale x 16 x i1> -> <vscale x 2 x i1>) then
6387 // we can return here.
6388 if (InVT.bitsGT(VT))
6389 return Reinterpret;
6390
6391 // Check if the other lanes are already known to be zeroed by
6392 // construction.
6394 return Reinterpret;
6395
6396 // Zero the newly introduced lanes.
6397 SDValue Mask = DAG.getConstant(1, DL, InVT);
6398 Mask = DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, VT, Mask);
6399 return DAG.getNode(ISD::AND, DL, VT, Reinterpret, Mask);
6400}
6401
6402SDValue AArch64TargetLowering::getRuntimePStateSM(SelectionDAG &DAG,
6403 SDValue Chain, SDLoc DL,
6404 EVT VT) const {
6405 RTLIB::Libcall LC = RTLIB::SMEABI_SME_STATE;
6406 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
6407 SDValue Callee =
6408 DAG.getExternalSymbol(LCImpl, getPointerTy(DAG.getDataLayout()));
6409 Type *Int64Ty = Type::getInt64Ty(*DAG.getContext());
6410 Type *RetTy = StructType::get(Int64Ty, Int64Ty);
6411 TargetLowering::CallLoweringInfo CLI(DAG);
6413 CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
6414 DAG.getLibcalls().getLibcallImplCallingConv(LCImpl), RetTy, Callee,
6415 std::move(Args));
6416 std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
6417 SDValue Mask = DAG.getConstant(/*PSTATE.SM*/ 1, DL, MVT::i64);
6418 return DAG.getNode(ISD::AND, DL, MVT::i64, CallResult.first.getOperand(0),
6419 Mask);
6420}
6421
6422// Lower an SME LDR/STR ZA intrinsic
6423// Case 1: If the vector number (vecnum) is an immediate in range, it gets
6424// folded into the instruction
6425// ldr(%tileslice, %ptr, 11) -> ldr [%tileslice, 11], [%ptr, 11]
6426// Case 2: If the vecnum is not an immediate, then it is used to modify the base
6427// and tile slice registers
6428// ldr(%tileslice, %ptr, %vecnum)
6429// ->
6430// %svl = rdsvl
6431// %ptr2 = %ptr + %svl * %vecnum
6432// %tileslice2 = %tileslice + %vecnum
6433// ldr [%tileslice2, 0], [%ptr2, 0]
6434// Case 3: If the vecnum is an immediate out of range, then the same is done as
6435// case 2, but the base and slice registers are modified by the greatest
6436// multiple of 15 lower than the vecnum and the remainder is folded into the
6437// instruction. This means that successive loads and stores that are offset from
6438// each other can share the same base and slice register updates.
6439// ldr(%tileslice, %ptr, 22)
6440// ldr(%tileslice, %ptr, 23)
6441// ->
6442// %svl = rdsvl
6443// %ptr2 = %ptr + %svl * 15
6444// %tileslice2 = %tileslice + 15
6445// ldr [%tileslice2, 7], [%ptr2, 7]
6446// ldr [%tileslice2, 8], [%ptr2, 8]
6447// Case 4: If the vecnum is an add of an immediate, then the non-immediate
6448// operand and the immediate can be folded into the instruction, like case 2.
6449// ldr(%tileslice, %ptr, %vecnum + 7)
6450// ldr(%tileslice, %ptr, %vecnum + 8)
6451// ->
6452// %svl = rdsvl
6453// %ptr2 = %ptr + %svl * %vecnum
6454// %tileslice2 = %tileslice + %vecnum
6455// ldr [%tileslice2, 7], [%ptr2, 7]
6456// ldr [%tileslice2, 8], [%ptr2, 8]
6457// Case 5: The vecnum being an add of an immediate out of range is also handled,
6458// in which case the same remainder logic as case 3 is used.
6459static SDValue LowerSMELdrStr(SDValue N, SelectionDAG &DAG, bool IsLoad) {
6460 SDLoc DL(N);
6461
6462 SDValue TileSlice = N->getOperand(2);
6463 SDValue Base = N->getOperand(3);
6464 SDValue VecNum = N->getOperand(4);
6465 int32_t ConstAddend = 0;
6466 SDValue VarAddend = VecNum;
6467
6468 // If the vnum is an add of an immediate, we can fold it into the instruction
6469 if (VecNum.getOpcode() == ISD::ADD &&
6470 isa<ConstantSDNode>(VecNum.getOperand(1))) {
6471 ConstAddend = cast<ConstantSDNode>(VecNum.getOperand(1))->getSExtValue();
6472 VarAddend = VecNum.getOperand(0);
6473 } else if (auto ImmNode = dyn_cast<ConstantSDNode>(VecNum)) {
6474 ConstAddend = ImmNode->getSExtValue();
6475 VarAddend = SDValue();
6476 }
6477
6478 int32_t ImmAddend = ConstAddend % 16;
6479 if (int32_t C = (ConstAddend - ImmAddend)) {
6480 SDValue CVal = DAG.getTargetConstant(C, DL, MVT::i32);
6481 VarAddend = VarAddend
6482 ? DAG.getNode(ISD::ADD, DL, MVT::i32, {VarAddend, CVal})
6483 : CVal;
6484 }
6485
6486 if (VarAddend) {
6487 // Get the vector length that will be multiplied by vnum
6488 auto SVL = DAG.getNode(AArch64ISD::RDSVL, DL, MVT::i64,
6489 DAG.getConstant(1, DL, MVT::i32));
6490
6491 // Multiply SVL and vnum then add it to the base
6492 SDValue Mul = DAG.getNode(
6493 ISD::MUL, DL, MVT::i64,
6494 {SVL, DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, VarAddend)});
6495 Base = DAG.getNode(ISD::ADD, DL, MVT::i64, {Base, Mul});
6496 // Just add vnum to the tileslice
6497 TileSlice = DAG.getNode(ISD::ADD, DL, MVT::i32, {TileSlice, VarAddend});
6498 }
6499
6500 return DAG.getNode(IsLoad ? AArch64ISD::SME_ZA_LDR : AArch64ISD::SME_ZA_STR,
6501 DL, MVT::Other,
6502 {/*Chain=*/N.getOperand(0), TileSlice, Base,
6503 DAG.getTargetConstant(ImmAddend, DL, MVT::i32)});
6504}
6505
6507 SDLoc DL(Op);
6508 auto Op1 = Op.getOperand(0);
6509 auto Op2 = Op.getOperand(1);
6510 auto Mask = Op.getOperand(2);
6511
6512 EVT Op1VT = Op1.getValueType();
6513 EVT Op2VT = Op2.getValueType();
6514 EVT ResVT = Op.getValueType();
6515
6516 assert((Op1VT.getVectorElementType() == MVT::i8 ||
6517 Op1VT.getVectorElementType() == MVT::i16) &&
6518 "Expected 8-bit or 16-bit characters.");
6519
6520 SDValue ID =
6521 DAG.getTargetConstant(Intrinsic::aarch64_sve_match, DL, MVT::i64);
6522
6523 // Scalable vector type used to wrap operands.
6524 // A single container is enough for both operands because ultimately the
6525 // operands will have to be wrapped to the same type (nxv16i8 or nxv8i16).
6526 EVT OpContainerVT = Op1VT.isScalableVector()
6527 ? Op1VT
6529
6530 if (Op2VT.is128BitVector()) {
6531 // If Op2 is a full 128-bit vector, wrap it trivially in a scalable vector.
6532 Op2 = convertToScalableVector(DAG, OpContainerVT, Op2);
6533 // Further, if the result is scalable, broadcast Op2 to a full SVE register.
6534 if (ResVT.isScalableVector())
6535 Op2 = DAG.getNode(AArch64ISD::DUPLANE128, DL, OpContainerVT, Op2,
6536 DAG.getTargetConstant(0, DL, MVT::i64));
6537 } else {
6538 // If Op2 is not a full 128-bit vector, we always need to broadcast it.
6539 unsigned Op2BitWidth = Op2VT.getFixedSizeInBits();
6540 MVT Op2IntVT = MVT::getIntegerVT(Op2BitWidth);
6541 EVT Op2PromotedVT = getPackedSVEVectorVT(Op2IntVT);
6542 Op2 = DAG.getBitcast(MVT::getVectorVT(Op2IntVT, 1), Op2);
6543 Op2 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, Op2IntVT, Op2,
6544 DAG.getConstant(0, DL, MVT::i64));
6545 Op2 = DAG.getSplatVector(Op2PromotedVT, DL, Op2);
6546 Op2 = DAG.getBitcast(OpContainerVT, Op2);
6547 }
6548
6549 // If the result is scalable, we just need to carry out the MATCH.
6550 if (ResVT.isScalableVector())
6551 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, ResVT, ID, Mask, Op1, Op2);
6552
6553 // If the result is fixed, we can still use MATCH but we need to wrap the
6554 // first operand and the mask in scalable vectors before doing so.
6555
6556 // Wrap the operands.
6557 Op1 = convertToScalableVector(DAG, OpContainerVT, Op1);
6558 Mask = DAG.getNode(ISD::SIGN_EXTEND, DL, Op1VT, Mask);
6559 Mask = convertFixedMaskToScalableVector(Mask, DAG);
6560
6561 // Carry out the match.
6562 SDValue Match = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, Mask.getValueType(),
6563 ID, Mask, Op1, Op2);
6564
6565 // Extract and promote the match result (nxv16i1/nxv8i1) to ResVT
6566 // (v16i8/v8i8).
6567 Match = DAG.getNode(ISD::SIGN_EXTEND, DL, OpContainerVT, Match);
6568 Match = convertFromScalableVector(DAG, Op1VT, Match);
6569 return DAG.getNode(ISD::TRUNCATE, DL, ResVT, Match);
6570}
6571
6572SDValue AArch64TargetLowering::LowerINTRINSIC_VOID(SDValue Op,
6573 SelectionDAG &DAG) const {
6574 unsigned IntNo = Op.getConstantOperandVal(1);
6575 SDLoc DL(Op);
6576 switch (IntNo) {
6577 default:
6578 return SDValue(); // Don't custom lower most intrinsics.
6579 case Intrinsic::aarch64_prefetch: {
6580 SDValue Chain = Op.getOperand(0);
6581 SDValue Addr = Op.getOperand(2);
6582
6583 unsigned IsWrite = Op.getConstantOperandVal(3);
6584 unsigned Locality = Op.getConstantOperandVal(4);
6585 unsigned IsStream = Op.getConstantOperandVal(5);
6586 unsigned IsData = Op.getConstantOperandVal(6);
6587 unsigned PrfOp = (IsWrite << 4) | // Load/Store bit
6588 (!IsData << 3) | // IsDataCache bit
6589 (Locality << 1) | // Cache level bits
6590 (unsigned)IsStream; // Stream bit
6591
6592 return DAG.getNode(AArch64ISD::PREFETCH, DL, MVT::Other, Chain,
6593 DAG.getTargetConstant(PrfOp, DL, MVT::i32), Addr);
6594 }
6595 case Intrinsic::aarch64_range_prefetch: {
6596 SDValue Chain = Op.getOperand(0);
6597 SDValue Addr = Op.getOperand(2);
6598
6599 unsigned IsWrite = Op.getConstantOperandVal(3);
6600 unsigned IsStream = Op.getConstantOperandVal(4);
6601 unsigned PrfOp = (IsStream << 2) | IsWrite;
6602
6603 SDValue Metadata = Op.getOperand(5);
6604 return DAG.getNode(AArch64ISD::RANGE_PREFETCH, DL, MVT::Other, Chain,
6605 DAG.getTargetConstant(PrfOp, DL, MVT::i32), Addr,
6606 Metadata);
6607 }
6608 case Intrinsic::aarch64_prefetch_ir:
6609 return DAG.getNode(AArch64ISD::PREFETCH, DL, MVT::Other,
6610 Op.getOperand(0), // Chain
6611 DAG.getTargetConstant(24, DL, MVT::i32), // Rt
6612 Op.getOperand(2)); // Addr
6613 case Intrinsic::aarch64_sme_str:
6614 case Intrinsic::aarch64_sme_ldr: {
6615 return LowerSMELdrStr(Op, DAG, IntNo == Intrinsic::aarch64_sme_ldr);
6616 }
6617 case Intrinsic::aarch64_sme_za_enable:
6618 return DAG.getNode(
6619 AArch64ISD::SMSTART, DL, DAG.getVTList(MVT::Other, MVT::Glue),
6620 Op->getOperand(0), // Chain
6621 DAG.getTargetConstant((int32_t)(AArch64SVCR::SVCRZA), DL, MVT::i32));
6622 case Intrinsic::aarch64_sme_za_disable:
6623 return DAG.getNode(
6624 AArch64ISD::SMSTOP, DL, DAG.getVTList(MVT::Other, MVT::Glue),
6625 Op->getOperand(0), // Chain
6626 DAG.getTargetConstant((int32_t)(AArch64SVCR::SVCRZA), DL, MVT::i32));
6627 }
6628}
6629
6630SDValue AArch64TargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op,
6631 SelectionDAG &DAG) const {
6632 unsigned IntNo = Op.getConstantOperandVal(1);
6633 SDLoc DL(Op);
6634 switch (IntNo) {
6635 default:
6636 return SDValue(); // Don't custom lower most intrinsics.
6637 case Intrinsic::aarch64_svc:
6638 case Intrinsic::aarch64_hvc: {
6639 // The MSVC __svc/__hvc intrinsic takes the 16-bit instruction immediate as
6640 // their first operand and four further operands passed in X0-X3 (an unused
6641 // argument is passed as poison) and returns the value left in X0. Matching
6642 // MSVC, the instruction is not treated as clobbering the caller-saved
6643 // registers; only X0 (the result) is defined.
6644 SDValue Chain = Op.getOperand(0);
6645 unsigned Imm = Op.getConstantOperandVal(2);
6646
6647 static const MCPhysReg ArgGPRs[] = {AArch64::X0, AArch64::X1, AArch64::X2,
6648 AArch64::X3};
6649
6650 SDValue Glue;
6652 for (unsigned I = 0; I < std::size(ArgGPRs); ++I) {
6653 SDValue Arg = Op.getOperand(3 + I);
6654 if (Arg.isUndef())
6655 continue;
6656 Chain = DAG.getCopyToReg(Chain, DL, ArgGPRs[I], Arg, Glue);
6657 Glue = Chain.getValue(1);
6658 RegOps.push_back(DAG.getRegister(ArgGPRs[I], MVT::i64));
6659 }
6660
6662 Ops.push_back(Chain);
6663 Ops.push_back(DAG.getTargetConstant(Imm, DL, MVT::i32));
6664 Ops.append(RegOps.begin(), RegOps.end());
6665 if (Glue.getNode())
6666 Ops.push_back(Glue);
6667
6668 unsigned Opc =
6669 IntNo == Intrinsic::aarch64_svc ? AArch64ISD::SVC : AArch64ISD::HVC;
6670 SDValue Node =
6671 DAG.getNode(Opc, DL, DAG.getVTList(MVT::Other, MVT::Glue), Ops);
6672 Chain = Node.getValue(0);
6673 Glue = Node.getValue(1);
6674
6675 SDValue Result = DAG.getCopyFromReg(Chain, DL, AArch64::X0, MVT::i64, Glue);
6676 return DAG.getMergeValues({Result.getValue(0), Result.getValue(1)}, DL);
6677 }
6678 case Intrinsic::aarch64_mops_memset_tag: {
6679 auto Node = cast<MemIntrinsicSDNode>(Op.getNode());
6680 SDValue Chain = Node->getChain();
6681 SDValue Dst = Op.getOperand(2);
6682 SDValue Val = Op.getOperand(3);
6683 Val = DAG.getAnyExtOrTrunc(Val, DL, MVT::i64);
6684 SDValue Size = Op.getOperand(4);
6685 auto Alignment = Node->getMemOperand()->getAlign();
6686 bool IsVol = Node->isVolatile();
6687 auto DstPtrInfo = Node->getPointerInfo();
6688
6689 const auto &SDI =
6690 static_cast<const AArch64SelectionDAGInfo &>(DAG.getSelectionDAGInfo());
6691 SDValue MS = SDI.EmitMOPS(AArch64::MOPSMemorySetTaggingPseudo, DAG, DL,
6692 Chain, Dst, Val, Size, Alignment, Alignment,
6693 IsVol, DstPtrInfo, MachinePointerInfo{});
6694
6695 // MOPS_MEMSET_TAGGING has 3 results (DstWb, SizeWb, Chain) whereas the
6696 // intrinsic has 2. So hide SizeWb using MERGE_VALUES. Otherwise
6697 // LowerOperationWrapper will complain that the number of results has
6698 // changed.
6699 return DAG.getMergeValues({MS.getValue(0), MS.getValue(2)}, DL);
6700 }
6701 }
6702}
6703
6704SDValue AArch64TargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
6705 SelectionDAG &DAG) const {
6706 unsigned IntNo = Op.getConstantOperandVal(0);
6707 SDLoc DL(Op);
6708 switch (IntNo) {
6709 default: return SDValue(); // Don't custom lower most intrinsics.
6710 case Intrinsic::thread_pointer: {
6711 EVT PtrVT = getPointerTy(DAG.getDataLayout());
6712 return DAG.getNode(AArch64ISD::THREAD_POINTER, DL, PtrVT);
6713 }
6714 case Intrinsic::aarch64_sve_whilewr_b:
6715 return DAG.getNode(ISD::LOOP_DEPENDENCE_WAR_MASK, DL, Op.getValueType(),
6716 Op.getOperand(1), Op.getOperand(2),
6717 DAG.getConstant(1, DL, MVT::i64),
6718 DAG.getConstant(0, DL, MVT::i64));
6719 case Intrinsic::aarch64_sve_whilewr_h:
6720 return DAG.getNode(ISD::LOOP_DEPENDENCE_WAR_MASK, DL, Op.getValueType(),
6721 Op.getOperand(1), Op.getOperand(2),
6722 DAG.getConstant(2, DL, MVT::i64),
6723 DAG.getConstant(0, DL, MVT::i64));
6724 case Intrinsic::aarch64_sve_whilewr_s:
6725 return DAG.getNode(ISD::LOOP_DEPENDENCE_WAR_MASK, DL, Op.getValueType(),
6726 Op.getOperand(1), Op.getOperand(2),
6727 DAG.getConstant(4, DL, MVT::i64),
6728 DAG.getConstant(0, DL, MVT::i64));
6729 case Intrinsic::aarch64_sve_whilewr_d:
6730 return DAG.getNode(ISD::LOOP_DEPENDENCE_WAR_MASK, DL, Op.getValueType(),
6731 Op.getOperand(1), Op.getOperand(2),
6732 DAG.getConstant(8, DL, MVT::i64),
6733 DAG.getConstant(0, DL, MVT::i64));
6734 case Intrinsic::aarch64_sve_whilerw_b:
6735 return DAG.getNode(ISD::LOOP_DEPENDENCE_RAW_MASK, DL, Op.getValueType(),
6736 Op.getOperand(1), Op.getOperand(2),
6737 DAG.getConstant(1, DL, MVT::i64),
6738 DAG.getConstant(0, DL, MVT::i64));
6739 case Intrinsic::aarch64_sve_whilerw_h:
6740 return DAG.getNode(ISD::LOOP_DEPENDENCE_RAW_MASK, DL, Op.getValueType(),
6741 Op.getOperand(1), Op.getOperand(2),
6742 DAG.getConstant(2, DL, MVT::i64),
6743 DAG.getConstant(0, DL, MVT::i64));
6744 case Intrinsic::aarch64_sve_whilerw_s:
6745 return DAG.getNode(ISD::LOOP_DEPENDENCE_RAW_MASK, DL, Op.getValueType(),
6746 Op.getOperand(1), Op.getOperand(2),
6747 DAG.getConstant(4, DL, MVT::i64),
6748 DAG.getConstant(0, DL, MVT::i64));
6749 case Intrinsic::aarch64_sve_whilerw_d:
6750 return DAG.getNode(ISD::LOOP_DEPENDENCE_RAW_MASK, DL, Op.getValueType(),
6751 Op.getOperand(1), Op.getOperand(2),
6752 DAG.getConstant(8, DL, MVT::i64),
6753 DAG.getConstant(0, DL, MVT::i64));
6754 case Intrinsic::aarch64_neon_abs: {
6755 EVT Ty = Op.getValueType();
6756 if (Ty == MVT::i64) {
6757 SDValue Result =
6758 DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v1i64, Op.getOperand(1));
6759 Result = DAG.getNode(ISD::ABS, DL, MVT::v1i64, Result);
6760 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i64, Result,
6761 DAG.getConstant(0, DL, MVT::i64));
6762 } else if (Ty.isVector() && Ty.isInteger() && isTypeLegal(Ty)) {
6763 return DAG.getNode(ISD::ABS, DL, Ty, Op.getOperand(1));
6764 } else {
6765 report_fatal_error("Unexpected type for AArch64 NEON intrinsic");
6766 }
6767 }
6768 case Intrinsic::aarch64_neon_addhn: {
6769 return DAG.getNode(AArch64ISD::ADDHN, DL, Op.getValueType(),
6770 Op.getOperand(1), Op.getOperand(2));
6771 }
6772 case Intrinsic::aarch64_neon_pmull64: {
6773 SDValue LHS = Op.getOperand(1);
6774 SDValue RHS = Op.getOperand(2);
6775
6776 std::optional<uint64_t> LHSLane =
6778 std::optional<uint64_t> RHSLane =
6780
6781 assert((!LHSLane || *LHSLane < 2) && "Expect lane to be None or 0 or 1");
6782 assert((!RHSLane || *RHSLane < 2) && "Expect lane to be None or 0 or 1");
6783
6784 // 'aarch64_neon_pmull64' takes i64 parameters; while pmull/pmull2
6785 // instructions execute on SIMD registers. So canonicalize i64 to v1i64,
6786 // which ISel recognizes better. For example, generate a ldr into d*
6787 // registers as opposed to a GPR load followed by a fmov.
6788 auto TryVectorizeOperand = [](SDValue N, std::optional<uint64_t> NLane,
6789 std::optional<uint64_t> OtherLane,
6790 const SDLoc &DL,
6791 SelectionDAG &DAG) -> SDValue {
6792 // If the operand is an higher half itself, rewrite it to
6793 // extract_high_v2i64; this way aarch64_neon_pmull64 could
6794 // re-use the dag-combiner function with aarch64_neon_{pmull,smull,umull}.
6795 if (NLane == 1)
6796 return DAG.getExtractSubvector(DL, MVT::v1i64, N.getOperand(0), 1);
6797
6798 // Operand N is not a higher half but the other operand is.
6799 if (OtherLane == 1) {
6800 // If this operand is a lower half, rewrite it to
6801 // extract_high_v2i64(duplane(<2 x Ty>, 0)). This saves a roundtrip to
6802 // align lanes of two operands. A roundtrip sequence (to move from lane
6803 // 1 to lane 0) is like this:
6804 // mov x8, v0.d[1]
6805 // fmov d0, x8
6806 if (NLane == 0)
6807 return DAG.getExtractSubvector(
6808 DL, MVT::v1i64,
6809 DAG.getNode(AArch64ISD::DUPLANE64, DL, MVT::v2i64,
6810 N.getOperand(0), DAG.getConstant(0, DL, MVT::i64)),
6811 1);
6812
6813 // Otherwise just dup from main to all lanes.
6814 return DAG.getNode(AArch64ISD::DUP, DL, MVT::v1i64, N);
6815 }
6816
6817 // Neither operand is an extract of higher half, so codegen may just use
6818 // the non-high version of PMULL instruction. Use v1i64 to represent i64.
6819 assert(N.getValueType() == MVT::i64 &&
6820 "Intrinsic aarch64_neon_pmull64 requires i64 parameters");
6821 return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v1i64, N);
6822 };
6823
6824 LHS = TryVectorizeOperand(LHS, LHSLane, RHSLane, DL, DAG);
6825 RHS = TryVectorizeOperand(RHS, RHSLane, LHSLane, DL, DAG);
6826
6827 return DAG.getNode(AArch64ISD::PMULL, DL, Op.getValueType(), LHS, RHS);
6828 }
6829 case Intrinsic::aarch64_neon_smax:
6830 return DAG.getNode(ISD::SMAX, DL, Op.getValueType(), Op.getOperand(1),
6831 Op.getOperand(2));
6832 case Intrinsic::aarch64_neon_umax:
6833 return DAG.getNode(ISD::UMAX, DL, Op.getValueType(), Op.getOperand(1),
6834 Op.getOperand(2));
6835 case Intrinsic::aarch64_neon_smin:
6836 return DAG.getNode(ISD::SMIN, DL, Op.getValueType(), Op.getOperand(1),
6837 Op.getOperand(2));
6838 case Intrinsic::aarch64_neon_umin:
6839 return DAG.getNode(ISD::UMIN, DL, Op.getValueType(), Op.getOperand(1),
6840 Op.getOperand(2));
6841 case Intrinsic::aarch64_neon_scalar_sqxtn:
6842 case Intrinsic::aarch64_neon_scalar_sqxtun:
6843 case Intrinsic::aarch64_neon_scalar_uqxtn: {
6844 assert(Op.getValueType() == MVT::i32 || Op.getValueType() == MVT::f32);
6845 if (Op.getValueType() == MVT::i32)
6846 return DAG.getNode(ISD::BITCAST, DL, MVT::i32,
6847 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::f32,
6848 Op.getOperand(0),
6849 DAG.getNode(ISD::BITCAST, DL, MVT::f64,
6850 Op.getOperand(1))));
6851 return SDValue();
6852 }
6853 case Intrinsic::aarch64_neon_sqxtn:
6854 return DAG.getNode(ISD::TRUNCATE_SSAT_S, DL, Op.getValueType(),
6855 Op.getOperand(1));
6856 case Intrinsic::aarch64_neon_sqxtun:
6857 return DAG.getNode(ISD::TRUNCATE_SSAT_U, DL, Op.getValueType(),
6858 Op.getOperand(1));
6859 case Intrinsic::aarch64_neon_uqxtn:
6860 return DAG.getNode(ISD::TRUNCATE_USAT_U, DL, Op.getValueType(),
6861 Op.getOperand(1));
6862 case Intrinsic::aarch64_neon_sqshrn:
6863 if (Op.getValueType().isVector())
6864 return DAG.getNode(ISD::TRUNCATE_SSAT_S, DL, Op.getValueType(),
6865 DAG.getNode(AArch64ISD::VASHR, DL,
6866 Op.getOperand(1).getValueType(),
6867 Op.getOperand(1), Op.getOperand(2)));
6868 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQSHRN, DAG,
6869 /*LastOperandIsImm=*/true);
6870 case Intrinsic::aarch64_neon_sqshrun:
6871 if (Op.getValueType().isVector())
6872 return DAG.getNode(ISD::TRUNCATE_SSAT_U, DL, Op.getValueType(),
6873 DAG.getNode(AArch64ISD::VASHR, DL,
6874 Op.getOperand(1).getValueType(),
6875 Op.getOperand(1), Op.getOperand(2)));
6876 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQSHRUN, DAG,
6877 /*LastOperandIsImm=*/true);
6878 case Intrinsic::aarch64_neon_uqshrn:
6879 if (Op.getValueType().isVector())
6880 return DAG.getNode(ISD::TRUNCATE_USAT_U, DL, Op.getValueType(),
6881 DAG.getNode(AArch64ISD::VLSHR, DL,
6882 Op.getOperand(1).getValueType(),
6883 Op.getOperand(1), Op.getOperand(2)));
6884 return lowerIntNeonIntrinsic(Op, AArch64ISD::UQSHRN, DAG,
6885 /*LastOperandIsImm=*/true);
6886 case Intrinsic::aarch64_neon_sqrshrn:
6887 if (Op.getValueType().isVector())
6888 return DAG.getNode(ISD::TRUNCATE_SSAT_S, DL, Op.getValueType(),
6889 DAG.getNode(AArch64ISD::SRSHR_I, DL,
6890 Op.getOperand(1).getValueType(),
6891 Op.getOperand(1), Op.getOperand(2)));
6892 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQRSHRN, DAG,
6893 /*LastOperandIsImm=*/true);
6894 case Intrinsic::aarch64_neon_sqrshrun:
6895 if (Op.getValueType().isVector())
6896 return DAG.getNode(ISD::TRUNCATE_SSAT_U, DL, Op.getValueType(),
6897 DAG.getNode(AArch64ISD::SRSHR_I, DL,
6898 Op.getOperand(1).getValueType(),
6899 Op.getOperand(1), Op.getOperand(2)));
6900 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQRSHRUN, DAG,
6901 /*LastOperandIsImm=*/true);
6902 case Intrinsic::aarch64_neon_uqrshrn:
6903 if (Op.getValueType().isVector())
6904 return DAG.getNode(ISD::TRUNCATE_USAT_U, DL, Op.getValueType(),
6905 DAG.getNode(AArch64ISD::URSHR_I, DL,
6906 Op.getOperand(1).getValueType(),
6907 Op.getOperand(1), Op.getOperand(2)));
6908 return lowerIntNeonIntrinsic(Op, AArch64ISD::UQRSHRN, DAG,
6909 /*LastOperandIsImm=*/true);
6910 case Intrinsic::aarch64_neon_sqdmulh:
6911 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQDMULH, DAG);
6912 case Intrinsic::aarch64_neon_sqrdmulh:
6913 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQRDMULH, DAG);
6914 case Intrinsic::aarch64_neon_sqrdmlah:
6915 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQRDMLAH, DAG);
6916 case Intrinsic::aarch64_neon_sqrdmlsh:
6917 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQRDMLSH, DAG);
6918 case Intrinsic::aarch64_neon_sqrshl:
6919 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQRSHL, DAG);
6920 case Intrinsic::aarch64_neon_sqshl:
6921 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQSHL, DAG);
6922 case Intrinsic::aarch64_neon_uqrshl:
6923 return lowerIntNeonIntrinsic(Op, AArch64ISD::UQRSHL, DAG);
6924 case Intrinsic::aarch64_neon_uqshl:
6925 return lowerIntNeonIntrinsic(Op, AArch64ISD::UQSHL, DAG);
6926 case Intrinsic::aarch64_neon_sqadd:
6927 if (Op.getValueType().isVector())
6928 return DAG.getNode(ISD::SADDSAT, DL, Op.getValueType(), Op.getOperand(1),
6929 Op.getOperand(2));
6930 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQADD, DAG);
6931
6932 case Intrinsic::aarch64_neon_sqsub:
6933 if (Op.getValueType().isVector())
6934 return DAG.getNode(ISD::SSUBSAT, DL, Op.getValueType(), Op.getOperand(1),
6935 Op.getOperand(2));
6936 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQSUB, DAG);
6937
6938 case Intrinsic::aarch64_neon_uqadd:
6939 if (Op.getValueType().isVector())
6940 return DAG.getNode(ISD::UADDSAT, DL, Op.getValueType(), Op.getOperand(1),
6941 Op.getOperand(2));
6942 return lowerIntNeonIntrinsic(Op, AArch64ISD::UQADD, DAG);
6943 case Intrinsic::aarch64_neon_suqadd:
6944 return lowerIntNeonIntrinsic(Op, AArch64ISD::SUQADD, DAG);
6945 case Intrinsic::aarch64_neon_usqadd:
6946 return lowerIntNeonIntrinsic(Op, AArch64ISD::USQADD, DAG);
6947 case Intrinsic::aarch64_neon_uqsub:
6948 if (Op.getValueType().isVector())
6949 return DAG.getNode(ISD::USUBSAT, DL, Op.getValueType(), Op.getOperand(1),
6950 Op.getOperand(2));
6951 return lowerIntNeonIntrinsic(Op, AArch64ISD::UQSUB, DAG);
6952 case Intrinsic::aarch64_neon_sqdmulls_scalar:
6953 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQDMULL, DAG);
6954 case Intrinsic::aarch64_neon_sqabs:
6955 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQABS, DAG);
6956 case Intrinsic::aarch64_neon_sqneg:
6957 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQNEG, DAG);
6958 case Intrinsic::aarch64_sve_whilelt:
6959 return optimizeIncrementingWhile(Op.getNode(), DAG, /*IsSigned=*/true,
6960 /*IsEqual=*/false);
6961 case Intrinsic::aarch64_sve_whilels:
6962 return optimizeIncrementingWhile(Op.getNode(), DAG, /*IsSigned=*/false,
6963 /*IsEqual=*/true);
6964 case Intrinsic::aarch64_sve_whilele:
6965 return optimizeIncrementingWhile(Op.getNode(), DAG, /*IsSigned=*/true,
6966 /*IsEqual=*/true);
6967 case Intrinsic::aarch64_sve_sunpkhi:
6968 return DAG.getNode(AArch64ISD::SUNPKHI, DL, Op.getValueType(),
6969 Op.getOperand(1));
6970 case Intrinsic::aarch64_sve_sunpklo:
6971 return DAG.getNode(AArch64ISD::SUNPKLO, DL, Op.getValueType(),
6972 Op.getOperand(1));
6973 case Intrinsic::aarch64_sve_uunpkhi:
6974 return DAG.getNode(AArch64ISD::UUNPKHI, DL, Op.getValueType(),
6975 Op.getOperand(1));
6976 case Intrinsic::aarch64_sve_uunpklo:
6977 return DAG.getNode(AArch64ISD::UUNPKLO, DL, Op.getValueType(),
6978 Op.getOperand(1));
6979 case Intrinsic::aarch64_sve_clasta_n:
6980 return DAG.getNode(AArch64ISD::CLASTA_N, DL, Op.getValueType(),
6981 Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
6982 case Intrinsic::aarch64_sve_clastb_n:
6983 return DAG.getNode(AArch64ISD::CLASTB_N, DL, Op.getValueType(),
6984 Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
6985 case Intrinsic::aarch64_sve_lasta:
6986 return DAG.getNode(AArch64ISD::LASTA, DL, Op.getValueType(),
6987 Op.getOperand(1), Op.getOperand(2));
6988 case Intrinsic::aarch64_sve_lastb:
6989 return DAG.getNode(AArch64ISD::LASTB, DL, Op.getValueType(),
6990 Op.getOperand(1), Op.getOperand(2));
6991 case Intrinsic::aarch64_sve_tbl:
6992 return DAG.getNode(AArch64ISD::TBL, DL, Op.getValueType(), Op.getOperand(1),
6993 Op.getOperand(2));
6994 case Intrinsic::aarch64_sve_trn1:
6995 return DAG.getNode(AArch64ISD::TRN1, DL, Op.getValueType(),
6996 Op.getOperand(1), Op.getOperand(2));
6997 case Intrinsic::aarch64_sve_trn2:
6998 return DAG.getNode(AArch64ISD::TRN2, DL, Op.getValueType(),
6999 Op.getOperand(1), Op.getOperand(2));
7000 case Intrinsic::aarch64_sve_uzp1:
7001 return DAG.getNode(AArch64ISD::UZP1, DL, Op.getValueType(),
7002 Op.getOperand(1), Op.getOperand(2));
7003 case Intrinsic::aarch64_sve_uzp2:
7004 return DAG.getNode(AArch64ISD::UZP2, DL, Op.getValueType(),
7005 Op.getOperand(1), Op.getOperand(2));
7006 case Intrinsic::aarch64_sve_zip1:
7007 return DAG.getNode(AArch64ISD::ZIP1, DL, Op.getValueType(),
7008 Op.getOperand(1), Op.getOperand(2));
7009 case Intrinsic::aarch64_sve_zip2:
7010 return DAG.getNode(AArch64ISD::ZIP2, DL, Op.getValueType(),
7011 Op.getOperand(1), Op.getOperand(2));
7012 case Intrinsic::aarch64_sve_splice:
7013 return DAG.getNode(AArch64ISD::SPLICE, DL, Op.getValueType(),
7014 Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
7015 case Intrinsic::aarch64_sve_ptrue:
7016 return getPTrue(DAG, DL, Op.getValueType(), Op.getConstantOperandVal(1));
7017 case Intrinsic::aarch64_sve_clz:
7018 return DAG.getNode(AArch64ISD::CTLZ_MERGE_PASSTHRU, DL, Op.getValueType(),
7019 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7020 case Intrinsic::aarch64_sme_cntsd: {
7021 SDValue Bytes = DAG.getNode(AArch64ISD::RDSVL, DL, Op.getValueType(),
7022 DAG.getConstant(1, DL, MVT::i32));
7023 return DAG.getNode(ISD::SRL, DL, Op.getValueType(), Bytes,
7024 DAG.getConstant(3, DL, MVT::i32), SDNodeFlags::Exact);
7025 }
7026 case Intrinsic::aarch64_sve_cnt: {
7027 SDValue Data = Op.getOperand(3);
7028 // CTPOP only supports integer operands.
7029 if (Data.getValueType().isFloatingPoint())
7030 Data = DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Data);
7031 return DAG.getNode(AArch64ISD::CTPOP_MERGE_PASSTHRU, DL, Op.getValueType(),
7032 Op.getOperand(2), Data, Op.getOperand(1));
7033 }
7034 case Intrinsic::aarch64_sve_dupq_lane:
7035 return LowerDUPQLane(Op, DAG);
7036 case Intrinsic::aarch64_sve_convert_from_svbool:
7037 return getSVEPredicateBitCast(Op.getValueType(), Op.getOperand(1), DAG);
7038 case Intrinsic::aarch64_sve_convert_to_svbool:
7039 return getSVEPredicateBitCast(MVT::nxv16i1, Op.getOperand(1), DAG);
7040 case Intrinsic::aarch64_sve_convert_from_svcount:
7041 case Intrinsic::aarch64_sve_convert_to_svcount:
7042 return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Op.getOperand(1));
7043 case Intrinsic::aarch64_sve_fneg:
7044 return DAG.getNode(AArch64ISD::FNEG_MERGE_PASSTHRU, DL, Op.getValueType(),
7045 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7046 case Intrinsic::aarch64_sve_frintp:
7047 return DAG.getNode(AArch64ISD::FCEIL_MERGE_PASSTHRU, DL, Op.getValueType(),
7048 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7049 case Intrinsic::aarch64_sve_frintm:
7050 return DAG.getNode(AArch64ISD::FFLOOR_MERGE_PASSTHRU, DL, Op.getValueType(),
7051 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7052 case Intrinsic::aarch64_sve_frinti:
7053 return DAG.getNode(AArch64ISD::FNEARBYINT_MERGE_PASSTHRU, DL,
7054 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7055 Op.getOperand(1));
7056 case Intrinsic::aarch64_sve_frintx:
7057 return DAG.getNode(AArch64ISD::FRINT_MERGE_PASSTHRU, DL, Op.getValueType(),
7058 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7059 case Intrinsic::aarch64_sve_frint32x:
7060 return DAG.getNode(AArch64ISD::FRINT32_MERGE_PASSTHRU, DL,
7061 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7062 Op.getOperand(1));
7063 case Intrinsic::aarch64_sve_frint64x:
7064 return DAG.getNode(AArch64ISD::FRINT64_MERGE_PASSTHRU, DL,
7065 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7066 Op.getOperand(1));
7067 case Intrinsic::aarch64_sve_frinta:
7068 return DAG.getNode(AArch64ISD::FROUND_MERGE_PASSTHRU, DL, Op.getValueType(),
7069 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7070 case Intrinsic::aarch64_sve_frintn:
7071 return DAG.getNode(AArch64ISD::FROUNDEVEN_MERGE_PASSTHRU, DL,
7072 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7073 Op.getOperand(1));
7074 case Intrinsic::aarch64_sve_frintz:
7075 return DAG.getNode(AArch64ISD::FTRUNC_MERGE_PASSTHRU, DL, Op.getValueType(),
7076 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7077 case Intrinsic::aarch64_sve_frint32z:
7078 return DAG.getNode(AArch64ISD::FTRUNC32_MERGE_PASSTHRU, DL,
7079 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7080 Op.getOperand(1));
7081 case Intrinsic::aarch64_sve_frint64z:
7082 return DAG.getNode(AArch64ISD::FTRUNC64_MERGE_PASSTHRU, DL,
7083 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7084 Op.getOperand(1));
7085 case Intrinsic::aarch64_sve_ucvtf:
7086 return DAG.getNode(AArch64ISD::UINT_TO_FP_MERGE_PASSTHRU, DL,
7087 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7088 Op.getOperand(1));
7089 case Intrinsic::aarch64_sve_scvtf:
7090 return DAG.getNode(AArch64ISD::SINT_TO_FP_MERGE_PASSTHRU, DL,
7091 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7092 Op.getOperand(1));
7093 case Intrinsic::aarch64_sve_fcvtzu:
7094 return DAG.getNode(AArch64ISD::FCVTZU_MERGE_PASSTHRU, DL, Op.getValueType(),
7095 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7096 case Intrinsic::aarch64_sve_fcvtzs:
7097 return DAG.getNode(AArch64ISD::FCVTZS_MERGE_PASSTHRU, DL, Op.getValueType(),
7098 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7099 case Intrinsic::aarch64_sve_fsqrt:
7100 return DAG.getNode(AArch64ISD::FSQRT_MERGE_PASSTHRU, DL, Op.getValueType(),
7101 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7102 case Intrinsic::aarch64_sve_frecpx:
7103 return DAG.getNode(AArch64ISD::FRECPX_MERGE_PASSTHRU, DL, Op.getValueType(),
7104 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7105 case Intrinsic::aarch64_sve_frecpe_x:
7106 return DAG.getNode(AArch64ISD::FRECPE, DL, Op.getValueType(),
7107 Op.getOperand(1));
7108 case Intrinsic::aarch64_sve_frecps_x:
7109 return DAG.getNode(AArch64ISD::FRECPS, DL, Op.getValueType(),
7110 Op.getOperand(1), Op.getOperand(2));
7111 case Intrinsic::aarch64_sve_frsqrte_x:
7112 return DAG.getNode(AArch64ISD::FRSQRTE, DL, Op.getValueType(),
7113 Op.getOperand(1));
7114 case Intrinsic::aarch64_sve_frsqrts_x:
7115 return DAG.getNode(AArch64ISD::FRSQRTS, DL, Op.getValueType(),
7116 Op.getOperand(1), Op.getOperand(2));
7117 case Intrinsic::aarch64_sve_fabs:
7118 return DAG.getNode(AArch64ISD::FABS_MERGE_PASSTHRU, DL, Op.getValueType(),
7119 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7120 case Intrinsic::aarch64_sve_abs:
7121 return DAG.getNode(AArch64ISD::ABS_MERGE_PASSTHRU, DL, Op.getValueType(),
7122 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7123 case Intrinsic::aarch64_sve_neg:
7124 return DAG.getNode(AArch64ISD::NEG_MERGE_PASSTHRU, DL, Op.getValueType(),
7125 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7126 case Intrinsic::aarch64_sve_insr: {
7127 SDValue Scalar = Op.getOperand(2);
7128 EVT ScalarTy = Scalar.getValueType();
7129 if ((ScalarTy == MVT::i8) || (ScalarTy == MVT::i16))
7130 Scalar = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Scalar);
7131
7132 return DAG.getNode(AArch64ISD::INSR, DL, Op.getValueType(),
7133 Op.getOperand(1), Scalar);
7134 }
7135 case Intrinsic::aarch64_sve_rbit:
7136 return DAG.getNode(AArch64ISD::BITREVERSE_MERGE_PASSTHRU, DL,
7137 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7138 Op.getOperand(1));
7139 case Intrinsic::aarch64_sve_revb:
7140 return DAG.getNode(AArch64ISD::BSWAP_MERGE_PASSTHRU, DL, Op.getValueType(),
7141 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7142 case Intrinsic::aarch64_sve_revh:
7143 return DAG.getNode(AArch64ISD::REVH_MERGE_PASSTHRU, DL, Op.getValueType(),
7144 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7145 case Intrinsic::aarch64_sve_revw:
7146 return DAG.getNode(AArch64ISD::REVW_MERGE_PASSTHRU, DL, Op.getValueType(),
7147 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7148 case Intrinsic::aarch64_sve_revd:
7149 return DAG.getNode(AArch64ISD::REVD_MERGE_PASSTHRU, DL, Op.getValueType(),
7150 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7151 case Intrinsic::aarch64_sve_sxtb:
7152 return DAG.getNode(
7153 AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU, DL, Op.getValueType(),
7154 Op.getOperand(2), Op.getOperand(3),
7155 DAG.getValueType(Op.getValueType().changeVectorElementType(
7156 *DAG.getContext(), MVT::i8)),
7157 Op.getOperand(1));
7158 case Intrinsic::aarch64_sve_sxth:
7159 return DAG.getNode(
7160 AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU, DL, Op.getValueType(),
7161 Op.getOperand(2), Op.getOperand(3),
7162 DAG.getValueType(Op.getValueType().changeVectorElementType(
7163 *DAG.getContext(), MVT::i16)),
7164 Op.getOperand(1));
7165 case Intrinsic::aarch64_sve_sxtw:
7166 return DAG.getNode(
7167 AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU, DL, Op.getValueType(),
7168 Op.getOperand(2), Op.getOperand(3),
7169 DAG.getValueType(Op.getValueType().changeVectorElementType(
7170 *DAG.getContext(), MVT::i32)),
7171 Op.getOperand(1));
7172 case Intrinsic::aarch64_sve_uxtb:
7173 return DAG.getNode(
7174 AArch64ISD::ZERO_EXTEND_INREG_MERGE_PASSTHRU, DL, Op.getValueType(),
7175 Op.getOperand(2), Op.getOperand(3),
7176 DAG.getValueType(Op.getValueType().changeVectorElementType(
7177 *DAG.getContext(), MVT::i8)),
7178 Op.getOperand(1));
7179 case Intrinsic::aarch64_sve_uxth:
7180 return DAG.getNode(
7181 AArch64ISD::ZERO_EXTEND_INREG_MERGE_PASSTHRU, DL, Op.getValueType(),
7182 Op.getOperand(2), Op.getOperand(3),
7183 DAG.getValueType(Op.getValueType().changeVectorElementType(
7184 *DAG.getContext(), MVT::i16)),
7185 Op.getOperand(1));
7186 case Intrinsic::aarch64_sve_uxtw:
7187 return DAG.getNode(
7188 AArch64ISD::ZERO_EXTEND_INREG_MERGE_PASSTHRU, DL, Op.getValueType(),
7189 Op.getOperand(2), Op.getOperand(3),
7190 DAG.getValueType(Op.getValueType().changeVectorElementType(
7191 *DAG.getContext(), MVT::i32)),
7192 Op.getOperand(1));
7193 case Intrinsic::localaddress: {
7194 const auto &MF = DAG.getMachineFunction();
7195 const auto *RegInfo = Subtarget->getRegisterInfo();
7196 unsigned Reg = RegInfo->getLocalAddressRegister(MF);
7197 return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg,
7198 Op.getSimpleValueType());
7199 }
7200
7201 case Intrinsic::eh_recoverfp: {
7202 // FIXME: This needs to be implemented to correctly handle highly aligned
7203 // stack objects. For now we simply return the incoming FP. Refer D53541
7204 // for more details.
7205 SDValue FnOp = Op.getOperand(1);
7206 SDValue IncomingFPOp = Op.getOperand(2);
7207 GlobalAddressSDNode *GSD = dyn_cast<GlobalAddressSDNode>(FnOp);
7208 auto *Fn = dyn_cast_or_null<Function>(GSD ? GSD->getGlobal() : nullptr);
7209 if (!Fn)
7211 "llvm.eh.recoverfp must take a function as the first argument");
7212 return IncomingFPOp;
7213 }
7214 case Intrinsic::aarch64_neon_vsri:
7215 case Intrinsic::aarch64_neon_vsli:
7216 case Intrinsic::aarch64_sve_sri:
7217 case Intrinsic::aarch64_sve_sli: {
7218 EVT Ty = Op.getValueType();
7219
7220 if (!Ty.isVector())
7221 report_fatal_error("Unexpected type for aarch64_neon_vsli");
7222
7223 assert(Op.getConstantOperandVal(3) <= Ty.getScalarSizeInBits());
7224
7225 bool IsShiftRight = IntNo == Intrinsic::aarch64_neon_vsri ||
7226 IntNo == Intrinsic::aarch64_sve_sri;
7227 unsigned Opcode = IsShiftRight ? AArch64ISD::VSRI : AArch64ISD::VSLI;
7228 return DAG.getNode(Opcode, DL, Ty, Op.getOperand(1), Op.getOperand(2),
7229 Op.getOperand(3));
7230 }
7231
7232 case Intrinsic::aarch64_neon_srhadd:
7233 case Intrinsic::aarch64_neon_urhadd:
7234 case Intrinsic::aarch64_neon_shadd:
7235 case Intrinsic::aarch64_neon_uhadd: {
7236 bool IsSignedAdd = (IntNo == Intrinsic::aarch64_neon_srhadd ||
7237 IntNo == Intrinsic::aarch64_neon_shadd);
7238 bool IsRoundingAdd = (IntNo == Intrinsic::aarch64_neon_srhadd ||
7239 IntNo == Intrinsic::aarch64_neon_urhadd);
7240 unsigned Opcode = IsSignedAdd
7241 ? (IsRoundingAdd ? ISD::AVGCEILS : ISD::AVGFLOORS)
7242 : (IsRoundingAdd ? ISD::AVGCEILU : ISD::AVGFLOORU);
7243 return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(1),
7244 Op.getOperand(2));
7245 }
7246 case Intrinsic::aarch64_neon_saddlp:
7247 case Intrinsic::aarch64_neon_uaddlp: {
7248 unsigned Opcode = IntNo == Intrinsic::aarch64_neon_uaddlp
7249 ? AArch64ISD::UADDLP
7250 : AArch64ISD::SADDLP;
7251 return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(1));
7252 }
7253 case Intrinsic::aarch64_neon_sdot:
7254 case Intrinsic::aarch64_neon_udot:
7255 case Intrinsic::aarch64_sve_sdot:
7256 case Intrinsic::aarch64_sve_udot: {
7257 unsigned Opcode = (IntNo == Intrinsic::aarch64_neon_udot ||
7258 IntNo == Intrinsic::aarch64_sve_udot)
7259 ? AArch64ISD::UDOT
7260 : AArch64ISD::SDOT;
7261 return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(1),
7262 Op.getOperand(2), Op.getOperand(3));
7263 }
7264 case Intrinsic::aarch64_neon_usdot:
7265 case Intrinsic::aarch64_sve_usdot: {
7266 return DAG.getNode(AArch64ISD::USDOT, DL, Op.getValueType(),
7267 Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
7268 }
7269 case Intrinsic::aarch64_neon_saddlv:
7270 case Intrinsic::aarch64_neon_uaddlv: {
7271 EVT OpVT = Op.getOperand(1).getValueType();
7272 EVT ResVT = Op.getValueType();
7273 assert(
7274 ((ResVT == MVT::i32 && (OpVT == MVT::v8i8 || OpVT == MVT::v16i8 ||
7275 OpVT == MVT::v8i16 || OpVT == MVT::v4i16)) ||
7276 (ResVT == MVT::i64 && (OpVT == MVT::v4i32 || OpVT == MVT::v2i32))) &&
7277 "Unexpected aarch64_neon_u/saddlv type");
7278 (void)OpVT;
7279 // In order to avoid insert_subvector, use v4i32 rather than v2i32.
7280 SDValue ADDLV = DAG.getNode(
7281 IntNo == Intrinsic::aarch64_neon_uaddlv ? AArch64ISD::UADDLV
7282 : AArch64ISD::SADDLV,
7283 DL, ResVT == MVT::i32 ? MVT::v4i32 : MVT::v2i64, Op.getOperand(1));
7284 SDValue EXTRACT_VEC_ELT = DAG.getNode(
7285 ISD::EXTRACT_VECTOR_ELT, DL, ResVT == MVT::i32 ? MVT::i32 : MVT::i64,
7286 ADDLV, DAG.getConstant(0, DL, MVT::i64));
7287 return EXTRACT_VEC_ELT;
7288 }
7289 case Intrinsic::aarch64_cls:
7290 case Intrinsic::aarch64_cls64: {
7291 SDValue Res = DAG.getNode(ISD::CTLS, DL, Op.getOperand(1).getValueType(),
7292 Op.getOperand(1));
7293 return DAG.getNode(ISD::TRUNCATE, DL, Op.getValueType(), Res);
7294 }
7295 case Intrinsic::aarch64_neon_cls: {
7296 // Lower NEON CLS intrinsic to ISD::CTLS
7297 return DAG.getNode(ISD::CTLS, DL, Op.getValueType(), Op.getOperand(1));
7298 }
7299 case Intrinsic::aarch64_sve_pmul:
7300 case Intrinsic::aarch64_neon_pmul:
7301 return DAG.getNode(ISD::CLMUL, DL, Op.getValueType(), Op.getOperand(1),
7302 Op.getOperand(2));
7303 case Intrinsic::aarch64_sve_psel: {
7304 if (Op.getValueType() != MVT::aarch64svcount)
7305 return Op;
7306 // Lower predicate-as-counter variants to reuse normal predicate isel.
7307 SmallVector<SDValue> Ops(Op->ops());
7308 Ops[1] = DAG.getNode(ISD::BITCAST, DL, MVT::nxv16i1, Ops[1]);
7309 SDValue PSel = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::nxv16i1, Ops);
7310 return DAG.getNode(ISD::BITCAST, DL, MVT::aarch64svcount, PSel);
7311 }
7312 }
7313}
7314
7315bool AArch64TargetLowering::shouldExtendGSIndex(EVT VT, EVT &EltTy) const {
7316 if (VT.getVectorElementType() == MVT::i8 ||
7317 VT.getVectorElementType() == MVT::i16) {
7318 EltTy = MVT::i32;
7319 return true;
7320 }
7321 return false;
7322}
7323
7324bool AArch64TargetLowering::shouldRemoveExtendFromGSIndex(SDValue Extend,
7325 EVT DataVT) const {
7326 const EVT IndexVT = Extend.getOperand(0).getValueType();
7327 // SVE only supports implicit extension of 32-bit indices.
7328 if (!Subtarget->hasSVE() || IndexVT.getVectorElementType() != MVT::i32)
7329 return false;
7330
7331 // Indices cannot be smaller than the main data type.
7332 if (IndexVT.getScalarSizeInBits() < DataVT.getScalarSizeInBits())
7333 return false;
7334
7335 // Scalable vectors with "vscale * 2" or fewer elements sit within a 64-bit
7336 // element container type, which would violate the previous clause.
7337 return DataVT.isFixedLengthVector() || DataVT.getVectorMinNumElements() > 2;
7338}
7339
7340/// Helper function to check if a small vector load can be optimized.
7342 const AArch64Subtarget &Subtarget) {
7343 if (!Subtarget.isNeonAvailable())
7344 return false;
7345 if (LD->isVolatile())
7346 return false;
7347
7348 EVT MemVT = LD->getMemoryVT();
7349 if (MemVT != MVT::v2i8 && MemVT != MVT::v4i8 && MemVT != MVT::v2i16)
7350 return false;
7351
7352 Align Alignment = LD->getAlign();
7353 Align RequiredAlignment = Align(MemVT.getStoreSize().getFixedValue());
7354 if (Subtarget.requiresStrictAlign() && Alignment < RequiredAlignment)
7355 return false;
7356
7357 return true;
7358}
7359
7360bool AArch64TargetLowering::isVectorLoadExtDesirable(SDValue ExtVal) const {
7361 EVT ExtVT = ExtVal.getValueType();
7362 // Small, illegal vectors can be extended inreg.
7363 if (auto *Load = dyn_cast<LoadSDNode>(ExtVal.getOperand(0))) {
7364 if (ExtVT.isFixedLengthVector() && ExtVT.getStoreSizeInBits() <= 128 &&
7366 return true;
7367 }
7368 if (!ExtVT.isScalableVector() && !Subtarget->useSVEForFixedLengthVectors())
7369 return false;
7370
7371 // It may be worth creating extending masked loads if there are multiple