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 for (MVT Ty : {MVT::f16, MVT::bf16, MVT::f32, MVT::f64})
1028 if (!Subtarget->hasLSE() && !Subtarget->outlineAtomics()) {
1031 } else {
1034 }
1037
1038 // Generate outline atomics library calls only if LSE was not specified for
1039 // subtarget
1040 if (Subtarget->outlineAtomics() && !Subtarget->hasLSE()) {
1066 }
1067
1068 if (Subtarget->hasLSE128()) {
1069 // Custom lowering because i128 is not legal. Must be replaced by 2x64
1070 // values. ATOMIC_LOAD_AND also needs op legalisation to emit LDCLRP.
1074 }
1075
1076 // 128-bit loads and stores can be done without expanding
1077 setOperationAction(ISD::LOAD, MVT::i128, Custom);
1079
1080 // Aligned 128-bit loads and stores are single-copy atomic according to the
1081 // v8.4a spec. LRCPC3 introduces 128-bit STILP/LDIAPP but still requires LSE2.
1082 if (Subtarget->hasLSE2()) {
1085 }
1086
1087 // 256 bit non-temporal stores can be lowered to STNP. Do this as part of the
1088 // custom lowering, as there are no un-paired non-temporal stores and
1089 // legalization will break up 256 bit inputs.
1090 setOperationAction(ISD::STORE, MVT::v32i8, Custom);
1091 setOperationAction(ISD::STORE, MVT::v16i16, Custom);
1092 setOperationAction(ISD::STORE, MVT::v16f16, Custom);
1093 setOperationAction(ISD::STORE, MVT::v16bf16, Custom);
1094 setOperationAction(ISD::STORE, MVT::v8i32, Custom);
1095 setOperationAction(ISD::STORE, MVT::v8f32, Custom);
1096 setOperationAction(ISD::STORE, MVT::v4f64, Custom);
1097 setOperationAction(ISD::STORE, MVT::v4i64, Custom);
1098
1099 // 256 bit non-temporal loads can be lowered to LDNP. This is done using
1100 // custom lowering, as there are no un-paired non-temporal loads legalization
1101 // will break up 256 bit inputs.
1102 setOperationAction(ISD::LOAD, MVT::v32i8, Custom);
1103 setOperationAction(ISD::LOAD, MVT::v16i16, Custom);
1104 setOperationAction(ISD::LOAD, MVT::v16f16, Custom);
1105 setOperationAction(ISD::LOAD, MVT::v16bf16, Custom);
1106 setOperationAction(ISD::LOAD, MVT::v8i32, Custom);
1107 setOperationAction(ISD::LOAD, MVT::v8f32, Custom);
1108 setOperationAction(ISD::LOAD, MVT::v4f64, Custom);
1109 setOperationAction(ISD::LOAD, MVT::v4i64, Custom);
1110
1111 // Lower READCYCLECOUNTER using an mrs from CNTVCT_EL0.
1113
1114 // Issue __sincos_stret if available.
1117
1118 // Make floating-point constants legal for the large code model, so they don't
1119 // become loads from the constant pool.
1120 if (Subtarget->isTargetMachO() && TM.getCodeModel() == CodeModel::Large) {
1123 }
1124
1125 // AArch64 does not have floating-point extending loads, i1 sign-extending
1126 // load, floating-point truncating stores, or v2i32->v2i16 truncating store.
1127 for (MVT VT : MVT::fp_valuetypes()) {
1128 setLoadExtAction(ISD::EXTLOAD, VT, MVT::bf16, Expand);
1129 setLoadExtAction(ISD::EXTLOAD, VT, MVT::f16, Expand);
1130 setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand);
1131 setLoadExtAction(ISD::EXTLOAD, VT, MVT::f64, Expand);
1132 setLoadExtAction(ISD::EXTLOAD, VT, MVT::f80, Expand);
1133 }
1134 for (MVT VT : MVT::integer_valuetypes())
1135 setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Expand);
1136
1137 for (MVT WideVT : MVT::fp_valuetypes()) {
1138 for (MVT NarrowVT : MVT::fp_valuetypes()) {
1139 if (WideVT.getScalarSizeInBits() > NarrowVT.getScalarSizeInBits()) {
1140 setTruncStoreAction(WideVT, NarrowVT, Expand);
1141 }
1142 }
1143 }
1144
1145 if (Subtarget->hasFPARMv8()) {
1149 }
1150
1151 // Indexed loads and stores are supported.
1152 for (unsigned im = (unsigned)ISD::PRE_INC;
1154 setIndexedLoadAction(im, MVT::i8, Legal);
1155 setIndexedLoadAction(im, MVT::i16, Legal);
1156 setIndexedLoadAction(im, MVT::i32, Legal);
1157 setIndexedLoadAction(im, MVT::i64, Legal);
1158 setIndexedLoadAction(im, MVT::f64, Legal);
1159 setIndexedLoadAction(im, MVT::f32, Legal);
1160 setIndexedLoadAction(im, MVT::f16, Legal);
1161 setIndexedLoadAction(im, MVT::bf16, Legal);
1162 setIndexedStoreAction(im, MVT::i8, Legal);
1163 setIndexedStoreAction(im, MVT::i16, Legal);
1164 setIndexedStoreAction(im, MVT::i32, Legal);
1165 setIndexedStoreAction(im, MVT::i64, Legal);
1166 setIndexedStoreAction(im, MVT::f64, Legal);
1167 setIndexedStoreAction(im, MVT::f32, Legal);
1168 setIndexedStoreAction(im, MVT::f16, Legal);
1169 setIndexedStoreAction(im, MVT::bf16, Legal);
1170 }
1171
1172 // Trap.
1173 setOperationAction(ISD::TRAP, MVT::Other, Legal);
1176
1177 // We combine OR nodes for ccmp operations.
1179 // Try to create BICs for vector ANDs.
1181
1182 // llvm.init.trampoline and llvm.adjust.trampoline
1185
1186 // Vector add and sub nodes may conceal a high-half opportunity.
1187 // Also, try to fold ADD into CSINC/CSINV..
1190
1193
1194 // Try and combine setcc/select_cc with csel and bool-vector bitcasts.
1198
1200
1208
1210
1212
1214
1218
1221
1223
1225
1228
1230
1236
1238
1242
1243 if (Subtarget->isSVEorStreamingSVEAvailable())
1245
1246 // In case of strict alignment, avoid an excessive number of byte wide stores.
1249 Subtarget->requiresStrictAlign() ? MaxStoresPerMemsetOptSize : 32;
1250
1254 Subtarget->requiresStrictAlign() ? MaxStoresPerMemcpyOptSize : 16;
1255
1258 Subtarget->requiresStrictAlign() ? MaxStoresPerMemmoveOptSize : 16;
1259
1262 Subtarget->requiresStrictAlign() ? MaxLoadsPerMemcmpOptSize : 8;
1263
1265
1267
1268 EnableExtLdPromotion = true;
1269
1270 // Set required alignment.
1272 // Set preferred alignments.
1273
1274 // Don't align loops on Windows. The SEH unwind info generation needs to
1275 // know the exact length of functions before the alignments have been
1276 // expanded.
1277 if (!Subtarget->isTargetWindows())
1281
1282 // Only change the limit for entries in a jump table if specified by
1283 // the sub target, but not at the command line.
1284 unsigned MaxJT = STI.getMaximumJumpTableSize();
1285 if (MaxJT && getMaximumJumpTableSize() == UINT_MAX)
1287
1289
1291
1293 if (Subtarget->hasSME())
1295
1296 if (Subtarget->isNeonAvailable()) {
1297 // FIXME: v1f64 shouldn't be legal if we can avoid it, because it leads to
1298 // silliness like this:
1299 // clang-format off
1300 for (auto Op :
1321 setOperationAction(Op, MVT::v1f64, Expand);
1322 // clang-format on
1323
1324 for (auto Op :
1329 setOperationAction(Op, MVT::v1i64, Expand);
1330
1331 // AArch64 doesn't have a direct vector ->f32 conversion instructions for
1332 // elements smaller than i32, so promote the input to i32 first.
1333 setOperationPromotedToType(ISD::UINT_TO_FP, MVT::v4i8, MVT::v4i32);
1334 setOperationPromotedToType(ISD::SINT_TO_FP, MVT::v4i8, MVT::v4i32);
1335
1336 // Similarly, there is no direct i32 -> f64 vector conversion instruction.
1337 // Or, direct i32 -> f16 vector conversion. Set it so custom, so the
1338 // conversion happens in two steps: v4i32 -> v4f32 -> v4f16
1341 for (auto VT : {MVT::v2i32, MVT::v2i64, MVT::v4i32})
1343
1344 if (Subtarget->hasFullFP16()) {
1347
1356 } else {
1357 // when AArch64 doesn't have fullfp16 support, promote the input
1358 // to i32 first.
1359 setOperationPromotedToType(ISD::SINT_TO_FP, MVT::v8i8, MVT::v8i32);
1360 setOperationPromotedToType(ISD::UINT_TO_FP, MVT::v8i8, MVT::v8i32);
1361 setOperationPromotedToType(ISD::UINT_TO_FP, MVT::v16i8, MVT::v16i32);
1362 setOperationPromotedToType(ISD::SINT_TO_FP, MVT::v16i8, MVT::v16i32);
1363 setOperationPromotedToType(ISD::UINT_TO_FP, MVT::v4i16, MVT::v4i32);
1364 setOperationPromotedToType(ISD::SINT_TO_FP, MVT::v4i16, MVT::v4i32);
1365 setOperationPromotedToType(ISD::SINT_TO_FP, MVT::v8i16, MVT::v8i32);
1366 setOperationPromotedToType(ISD::UINT_TO_FP, MVT::v8i16, MVT::v8i32);
1367 }
1368
1369 setOperationAction(ISD::CTLZ, MVT::v1i64, Expand);
1370 setOperationAction(ISD::CTLZ, MVT::v2i64, Expand);
1371 // CTLS (Count Leading Sign bits) - Legal for BHS types (8/16/32-bit
1372 // elements) No hardware support for 64-bit element vectors
1373 for (auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
1374 MVT::v4i32})
1382 for (auto VT : {MVT::v1i64, MVT::v2i64}) {
1387 }
1388
1389 // Custom handling for some quad-vector types to detect MULL.
1390 setOperationAction(ISD::MUL, MVT::v8i16, Custom);
1391 setOperationAction(ISD::MUL, MVT::v4i32, Custom);
1392 setOperationAction(ISD::MUL, MVT::v2i64, Custom);
1393 setOperationAction(ISD::MUL, MVT::v4i16, Custom);
1394 setOperationAction(ISD::MUL, MVT::v2i32, Custom);
1395 setOperationAction(ISD::MUL, MVT::v1i64, Custom);
1396
1397 // Saturates
1398 for (MVT VT : { MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v1i64,
1399 MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64 }) {
1404 }
1405
1406 for (MVT VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
1407 MVT::v4i32}) {
1414 }
1415
1416 // Vector reductions
1417 for (MVT VT : { MVT::v4f16, MVT::v2f32,
1418 MVT::v8f16, MVT::v4f32, MVT::v2f64 }) {
1419 if (VT.getVectorElementType() != MVT::f16 || Subtarget->hasFullFP16()) {
1424
1426 }
1427 }
1428 if (Subtarget->hasFullFP16())
1430
1431 for (MVT VT : { MVT::v8i8, MVT::v4i16, MVT::v2i32,
1432 MVT::v16i8, MVT::v8i16, MVT::v4i32 }) {
1441 }
1446
1447 for (MVT VT : {MVT::v4i16, MVT::v8i16, MVT::v2i32, MVT::v4i32})
1449
1451 setTruncStoreAction(MVT::v2i32, MVT::v2i16, Expand);
1452 // Likewise, narrowing and extending vector loads/stores aren't handled
1453 // directly.
1456
1457 if (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32) {
1460 } else {
1463 }
1466
1467 if (VT == MVT::v4i16 || VT == MVT::v8i16 || VT == MVT::v2i32 ||
1468 VT == MVT::v4i32 || VT == MVT::v2i64)
1470 else
1472
1473 if (VT == MVT::v8i8 || VT == MVT::v16i8 || VT == MVT::v8i16 ||
1474 VT == MVT::v4i16 || VT == MVT::v2i32 || VT == MVT::v4i32)
1476 else
1478
1479 for (MVT InnerVT : MVT::fixedlen_vector_valuetypes()) {
1480 setTruncStoreAction(VT, InnerVT, Expand);
1481 setLoadExtAction(ISD::SEXTLOAD, VT, InnerVT, Expand);
1482 setLoadExtAction(ISD::ZEXTLOAD, VT, InnerVT, Expand);
1483 setLoadExtAction(ISD::EXTLOAD, VT, InnerVT, Expand);
1484 }
1485 }
1486
1487 for (auto Op :
1493 for (MVT Ty : {MVT::v2f32, MVT::v4f32, MVT::v2f64})
1495 if (Subtarget->hasFullFP16())
1496 for (MVT Ty : {MVT::v4f16, MVT::v8f16})
1498 }
1499
1500 // LRINT and LLRINT.
1501 for (auto Op : {ISD::LRINT, ISD::LLRINT}) {
1502 for (MVT Ty : {MVT::v2f32, MVT::v4f32, MVT::v2f64})
1504 if (Subtarget->hasFullFP16())
1505 for (MVT Ty : {MVT::v4f16, MVT::v8f16})
1507 }
1508
1509 setTruncStoreAction(MVT::v4i16, MVT::v4i8, Custom);
1510
1515
1519
1520 setLoadExtAction(ISD::EXTLOAD, MVT::v2i32, MVT::v2i8, Custom);
1521 setLoadExtAction(ISD::SEXTLOAD, MVT::v2i32, MVT::v2i8, Custom);
1522 setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i32, MVT::v2i8, Custom);
1523 setLoadExtAction(ISD::EXTLOAD, MVT::v2i64, MVT::v2i8, Custom);
1524 setLoadExtAction(ISD::SEXTLOAD, MVT::v2i64, MVT::v2i8, Custom);
1525 setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i64, MVT::v2i8, Custom);
1526 setLoadExtAction(ISD::EXTLOAD, MVT::v4i16, MVT::v4i8, Custom);
1527 setLoadExtAction(ISD::SEXTLOAD, MVT::v4i16, MVT::v4i8, Custom);
1528 setLoadExtAction(ISD::ZEXTLOAD, MVT::v4i16, MVT::v4i8, Custom);
1529 setLoadExtAction(ISD::EXTLOAD, MVT::v4i32, MVT::v4i8, Custom);
1530 setLoadExtAction(ISD::SEXTLOAD, MVT::v4i32, MVT::v4i8, Custom);
1531 setLoadExtAction(ISD::ZEXTLOAD, MVT::v4i32, MVT::v4i8, Custom);
1532 setLoadExtAction(ISD::EXTLOAD, MVT::v2i32, MVT::v2i16, Custom);
1533 setLoadExtAction(ISD::SEXTLOAD, MVT::v2i32, MVT::v2i16, Custom);
1534 setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i32, MVT::v2i16, Custom);
1535 setLoadExtAction(ISD::EXTLOAD, MVT::v2i64, MVT::v2i16, Custom);
1536 setLoadExtAction(ISD::SEXTLOAD, MVT::v2i64, MVT::v2i16, Custom);
1537 setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i64, MVT::v2i16, Custom);
1538
1539 // ADDP custom lowering
1540 for (MVT VT : { MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64 })
1542 // FADDP custom lowering
1543 for (MVT VT : { MVT::v16f16, MVT::v8f32, MVT::v4f64 })
1545
1546 // Two-way integer ``pure'' add reductions lower to a [SU]ADALP.
1547 {
1548 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
1550 setPartialReduceMLAAction(MLAOps, MVT::v4i16, MVT::v8i8, Custom);
1551 setPartialReduceMLAAction(MLAOps, MVT::v2i32, MVT::v4i16, Custom);
1552 setPartialReduceMLAAction(MLAOps, MVT::v1i64, MVT::v2i32, Custom);
1553 setPartialReduceMLAAction(MLAOps, MVT::v8i16, MVT::v16i8, Custom);
1554 setPartialReduceMLAAction(MLAOps, MVT::v4i32, MVT::v8i16, Custom);
1555 setPartialReduceMLAAction(MLAOps, MVT::v2i64, MVT::v4i32, Custom);
1556
1557 // Wider reductions are built from a ladder of the rungs above.
1558 setPartialReduceMLAAction(MLAOps, MVT::v2i32, MVT::v8i8, Custom);
1559 setPartialReduceMLAAction(MLAOps, MVT::v1i64, MVT::v4i16, Custom);
1560 setPartialReduceMLAAction(MLAOps, MVT::v1i64, MVT::v8i8, Custom);
1561 setPartialReduceMLAAction(MLAOps, MVT::v4i32, MVT::v16i8, Custom);
1562 setPartialReduceMLAAction(MLAOps, MVT::v2i64, MVT::v8i16, Custom);
1563 setPartialReduceMLAAction(MLAOps, MVT::v2i64, MVT::v16i8, Custom);
1564 }
1565
1566 if (Subtarget->hasDotProd()) {
1567 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
1569
1570 setPartialReduceMLAAction(MLAOps, MVT::v4i32, MVT::v16i8, Legal);
1571 setPartialReduceMLAAction(MLAOps, MVT::v2i32, MVT::v8i8, Legal);
1572 setPartialReduceMLAAction(MLAOps, MVT::v2i32, MVT::v16i8, Custom);
1573 setPartialReduceMLAAction(MLAOps, MVT::v2i64, MVT::v16i8, Custom);
1574
1575 // v2i64/v16i8 SUMLA always reduces to v4i32 SUMLA via
1576 // LowerPARTIAL_REDUCE_MLA, regardless of i8mm; v2i32/v16i8 SUMLA goes
1577 // through the same widen-to-v4i32 path as the SMLA/UMLA cases above.
1579 MVT::v16i8, Custom);
1581 MVT::v16i8, Custom);
1582
1583 if (Subtarget->hasMatMulInt8()) {
1585 MVT::v16i8, Legal);
1587 MVT::v8i8, Legal);
1588 } else {
1589 // Native dotprod without i8mm: lower SUMLA to two UDOT products in
1590 // LowerPARTIAL_REDUCE_MLA.
1592 MVT::v16i8, Custom);
1594 MVT::v8i8, Custom);
1595 }
1596 }
1597
1598 if (Subtarget->hasF16F32DOT() || Subtarget->hasFP16FML()) {
1600 MVT::v4f16, Legal);
1602 MVT::v8f16, Legal);
1603 }
1604
1605 if (Subtarget->hasBF16())
1607 MVT::v8bf16, Legal);
1608
1610 setOperationAction(ISD::CLMUL, {MVT::v8i8, MVT::v16i8}, Legal);
1611 if (Subtarget->hasAES()) {
1612 setOperationAction(ISD::CLMUL, {MVT::i16, MVT::i32, MVT::i64, MVT::v4i32},
1613 Custom);
1614 setOperationAction(ISD::CLMUL, {MVT::v1i64, MVT::v2i64}, Legal);
1615 setOperationAction(ISD::CLMULH, {MVT::v1i64, MVT::v2i64}, Legal);
1616 }
1617
1618 } else /* !isNeonAvailable */ {
1620 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op)
1622
1623 if (VT.is128BitVector() || VT.is64BitVector()) {
1627 Subtarget->isLittleEndian() ? Legal : Expand);
1628 }
1629 for (MVT InnerVT : MVT::fixedlen_vector_valuetypes()) {
1630 setTruncStoreAction(VT, InnerVT, Expand);
1631 setLoadExtAction(ISD::SEXTLOAD, VT, InnerVT, Expand);
1632 setLoadExtAction(ISD::ZEXTLOAD, VT, InnerVT, Expand);
1633 setLoadExtAction(ISD::EXTLOAD, VT, InnerVT, Expand);
1634 }
1635 }
1636 }
1637
1638 for (MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64}) {
1642 }
1643
1645
1646 // FIXME: Move lowering for more nodes here if those are common between
1647 // SVE and SME.
1648 if (Subtarget->isSVEorStreamingSVEAvailable()) {
1649 for (auto VT :
1650 {MVT::nxv16i1, MVT::nxv8i1, MVT::nxv4i1, MVT::nxv2i1, MVT::nxv1i1}) {
1655 Custom);
1656 }
1657 for (auto VT : {MVT::nxv16i1, MVT::nxv8i1, MVT::nxv4i1, MVT::nxv2i1}) {
1659 Custom);
1662 }
1663
1664 if (Subtarget->hasSVE2() && Subtarget->isSVEAvailable()) {
1665 for (MVT VT : {MVT::nxv16i1, MVT::nxv8i1})
1667
1668 for (MVT VT :
1669 {MVT::v16i1, MVT::v8i1, MVT::v16i8, MVT::v8i8, MVT::v3i8, MVT::v4i8})
1671 }
1672
1674
1675 if (Subtarget->isSVEorStreamingSVEAvailable() &&
1676 (Subtarget->hasSVE2p1() || Subtarget->hasSME2()))
1678
1679 for (auto VT : {MVT::v16i8, MVT::v8i8, MVT::v4i16, MVT::v2i32})
1681
1682 for (auto VT : {MVT::v8f16, MVT::v4f32, MVT::v2f64})
1684 }
1685
1686 if (Subtarget->isSVEorStreamingSVEAvailable()) {
1687 for (auto VT : {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32, MVT::nxv2i64}) {
1733 Custom);
1734 if (Subtarget->hasSME2() && Subtarget->isStreaming())
1737 Custom);
1738
1744
1753
1758
1762
1763 if (!Subtarget->isLittleEndian())
1765
1766 if (Subtarget->hasSVE2() ||
1767 (Subtarget->hasSME() && Subtarget->isStreaming()))
1768 // For SLI/SRI.
1770 }
1771
1772 for (auto VT : {MVT::nxv4i32, MVT::nxv2i64}) {
1775 }
1776
1777 // Illegal unpacked integer vector types.
1778 for (auto VT : {MVT::nxv8i8, MVT::nxv4i16, MVT::nxv2i32}) {
1781 }
1782
1783 // Type legalize unpacked bitcasts.
1784 for (auto VT : {MVT::nxv2i16, MVT::nxv4i16, MVT::nxv2i32})
1786
1787 for (auto VT :
1788 { MVT::nxv2i8, MVT::nxv2i16, MVT::nxv2i32, MVT::nxv2i64, MVT::nxv4i8,
1789 MVT::nxv4i16, MVT::nxv4i32, MVT::nxv8i8, MVT::nxv8i16 })
1791
1792 // Promote predicate as counter load/stores to standard predicates.
1793 setOperationPromotedToType(ISD::LOAD, MVT::aarch64svcount, MVT::nxv16i1);
1794 setOperationPromotedToType(ISD::STORE, MVT::aarch64svcount, MVT::nxv16i1);
1795
1796 // Predicate as counter legalization actions.
1797 setOperationAction(ISD::SELECT, MVT::aarch64svcount, Custom);
1798 setOperationAction(ISD::SELECT_CC, MVT::aarch64svcount, Expand);
1799
1800 for (auto VT :
1801 {MVT::nxv16i1, MVT::nxv8i1, MVT::nxv4i1, MVT::nxv2i1, MVT::nxv1i1}) {
1809
1813
1814 // There are no legal MVT::nxv16f## based types.
1815 if (VT != MVT::nxv16i1) {
1820 }
1821 }
1822
1823 // NEON doesn't support masked loads/stores, but SME and SVE do.
1824 for (auto VT :
1825 {MVT::v4f16, MVT::v8f16, MVT::v4bf16, MVT::v8bf16, MVT::v2f32,
1826 MVT::v4f32, MVT::v1f64, MVT::v2f64, MVT::v8i8, MVT::v16i8, MVT::v4i16,
1827 MVT::v8i16, MVT::v2i32, MVT::v4i32, MVT::v1i64, MVT::v2i64}) {
1830 }
1831
1832 // Firstly, exclude all scalable vector extending loads/truncating stores,
1833 // include both integer and floating scalable vector.
1835 for (MVT InnerVT : MVT::scalable_vector_valuetypes()) {
1836 setTruncStoreAction(VT, InnerVT, Expand);
1837 setLoadExtAction(ISD::SEXTLOAD, VT, InnerVT, Expand);
1838 setLoadExtAction(ISD::ZEXTLOAD, VT, InnerVT, Expand);
1839 setLoadExtAction(ISD::EXTLOAD, VT, InnerVT, Expand);
1840 }
1841 }
1842
1843 // Then, selectively enable those which we directly support.
1844 setTruncStoreAction(MVT::nxv2i64, MVT::nxv2i8, Legal);
1845 setTruncStoreAction(MVT::nxv2i64, MVT::nxv2i16, Legal);
1846 setTruncStoreAction(MVT::nxv2i64, MVT::nxv2i32, Legal);
1847 setTruncStoreAction(MVT::nxv4i32, MVT::nxv4i8, Legal);
1848 setTruncStoreAction(MVT::nxv4i32, MVT::nxv4i16, Legal);
1849 setTruncStoreAction(MVT::nxv8i16, MVT::nxv8i8, Legal);
1850 for (auto Op : {ISD::ZEXTLOAD, ISD::SEXTLOAD, ISD::EXTLOAD}) {
1851 setLoadExtAction(Op, MVT::nxv2i64, MVT::nxv2i8, Legal);
1852 setLoadExtAction(Op, MVT::nxv2i64, MVT::nxv2i16, Legal);
1853 setLoadExtAction(Op, MVT::nxv2i64, MVT::nxv2i32, Legal);
1854 setLoadExtAction(Op, MVT::nxv4i32, MVT::nxv4i8, Legal);
1855 setLoadExtAction(Op, MVT::nxv4i32, MVT::nxv4i16, Legal);
1856 setLoadExtAction(Op, MVT::nxv8i16, MVT::nxv8i8, Legal);
1857 }
1858
1859 // SVE supports truncating stores of 64 and 128-bit vectors
1860 setTruncStoreAction(MVT::v2i64, MVT::v2i8, Custom);
1861 setTruncStoreAction(MVT::v2i64, MVT::v2i16, Custom);
1862 setTruncStoreAction(MVT::v2i32, MVT::v2i8, Custom);
1863 setTruncStoreAction(MVT::v2i32, MVT::v2i16, Custom);
1864
1865 for (auto VT : {MVT::nxv2f16, MVT::nxv4f16, MVT::nxv8f16, MVT::nxv2f32,
1866 MVT::nxv4f32, MVT::nxv2f64}) {
1911 Custom);
1912 if (Subtarget->hasSME2() && Subtarget->isStreaming())
1915 Custom);
1916
1939
1940 // TODO: These require custom lowering.
1957
1969 }
1970
1971 for (auto VT : {MVT::nxv2bf16, MVT::nxv4bf16, MVT::nxv8bf16}) {
1986 Custom);
1987 if (Subtarget->hasSME2() && Subtarget->isStreaming())
1990 Custom);
1993 }
1994
1995 if (Subtarget->hasSVEB16B16() &&
1996 Subtarget->isNonStreamingSVEorSME2Available()) {
1997 // Note: Use SVE for bfloat16 operations when +sve-b16b16 is available.
1998 for (auto VT : {MVT::v4bf16, MVT::v8bf16, MVT::nxv2bf16, MVT::nxv4bf16,
1999 MVT::nxv8bf16}) {
2008 }
2009 }
2010
2011 for (auto Opcode :
2016 setOperationPromotedToType(Opcode, MVT::nxv2bf16, MVT::nxv2f32);
2017 setOperationPromotedToType(Opcode, MVT::nxv4bf16, MVT::nxv4f32);
2018 setOperationPromotedToType(Opcode, MVT::nxv8bf16, MVT::nxv8f32);
2019 }
2020
2021 if (!Subtarget->hasSVEB16B16() ||
2022 !Subtarget->isNonStreamingSVEorSME2Available()) {
2023 for (MVT VT : {MVT::nxv2bf16, MVT::nxv4bf16, MVT::nxv8bf16}) {
2024 MVT PromotedVT = VT.changeVectorElementType(MVT::f32);
2025 setOperationPromotedToType(ISD::FADD, VT, PromotedVT);
2026 setOperationPromotedToType(ISD::FMA, VT, PromotedVT);
2031 setOperationPromotedToType(ISD::FSUB, VT, PromotedVT);
2032
2033 if (VT != MVT::nxv2bf16 && Subtarget->hasBF16())
2035 else
2036 setOperationPromotedToType(ISD::FMUL, VT, PromotedVT);
2037 }
2038
2039 if (Subtarget->hasBF16() && Subtarget->isNeonAvailable())
2040 setOperationAction(ISD::FMUL, MVT::v8bf16, Custom);
2041 }
2042
2045
2046 // A number of operations like MULH and integer divides are not supported by
2047 // NEON but are available in SVE.
2048 for (auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
2049 MVT::v4i32, MVT::v1i64, MVT::v2i64}) {
2056 }
2057
2058 for (auto VT : {MVT::v4i16, MVT::v8i16, MVT::v2i32, MVT::v4i32, MVT::v1i64,
2059 MVT::v2i64})
2061
2062 // NEON doesn't support 64-bit vector integer muls, but SVE does.
2063 setOperationAction(ISD::MUL, MVT::v1i64, Custom);
2064 setOperationAction(ISD::MUL, MVT::v2i64, Custom);
2065
2066 // NEON doesn't support 128-bit [s|u][min|max] operations, but SVE does.
2071
2072 for (auto VT : {MVT::v1i64, MVT::v2i64}) {
2075 }
2076
2077 // NOTE: Currently this has to happen after computeRegisterProperties rather
2078 // than the preferred option of combining it with the addRegisterClass call.
2079 if (Subtarget->useSVEForFixedLengthVectors()) {
2082 VT, /*OverrideNEON=*/!Subtarget->isNeonAvailable()))
2083 addTypeForFixedLengthSVE(VT);
2084 }
2087 VT, /*OverrideNEON=*/!Subtarget->isNeonAvailable()))
2088 addTypeForFixedLengthSVE(VT);
2089 }
2090
2091 // 64bit results can mean a bigger than NEON input.
2092 for (auto VT : {MVT::v8i8, MVT::v4i16})
2095
2096 // 128bit results imply a bigger than NEON input.
2097 for (auto VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
2099 for (auto VT : {MVT::v8f16, MVT::v4f32, MVT::v8bf16})
2101
2102 // These operations are not supported on NEON but SVE can do them.
2103 setOperationAction(ISD::SMAX, MVT::v1i64, Custom);
2104 setOperationAction(ISD::SMAX, MVT::v2i64, Custom);
2105 setOperationAction(ISD::SMIN, MVT::v1i64, Custom);
2106 setOperationAction(ISD::SMIN, MVT::v2i64, Custom);
2107 setOperationAction(ISD::UMAX, MVT::v1i64, Custom);
2108 setOperationAction(ISD::UMAX, MVT::v2i64, Custom);
2109 setOperationAction(ISD::UMIN, MVT::v1i64, Custom);
2110 setOperationAction(ISD::UMIN, MVT::v2i64, Custom);
2115
2116 // Int operations with no NEON support.
2117 for (auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
2118 MVT::v4i32, MVT::v2i64}) {
2122 }
2123
2124 // Use SVE for vectors with more than 2 elements.
2125 for (auto VT : {MVT::v4f16, MVT::v8f16, MVT::v4f32})
2127 }
2128
2130 MVT::nxv2i64);
2132 MVT::nxv2i64);
2134 MVT::nxv4i32);
2136 MVT::nxv4i32);
2138 MVT::nxv8i16);
2140 MVT::nxv8i16);
2142 MVT::nxv16i8);
2144 MVT::nxv16i8);
2145
2147
2148 for (auto VT : {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1})
2151 VT, Custom);
2152
2153 // Without SubReg Liveness the multi-vector instructions can introduce
2154 // unnecessary COPY and/or MOVPFRX instructions.
2155 if (Subtarget->enableSubRegLiveness() &&
2156 (Subtarget->hasSVE2p1() ||
2157 (Subtarget->hasSME2() && Subtarget->isStreaming()))) {
2158
2159 for (unsigned Opcode : {ISD::LOAD, ISD::STORE}) {
2160 // 2x multi-vector load/stores
2161 setOperationAction(Opcode, MVT::nxv32i8, Custom);
2162 setOperationAction(Opcode, MVT::nxv16i16, Custom);
2163 setOperationAction(Opcode, MVT::nxv8i32, Custom);
2164 setOperationAction(Opcode, MVT::nxv4i64, Custom);
2165 setOperationAction(Opcode, MVT::nxv16f16, Custom);
2166 setOperationAction(Opcode, MVT::nxv8f32, Custom);
2167 setOperationAction(Opcode, MVT::nxv4f64, Custom);
2168 setOperationAction(Opcode, MVT::nxv16bf16, Custom);
2169
2170 // 4x multi-vector load/stores
2171 setOperationAction(Opcode, MVT::nxv64i8, Custom);
2172 setOperationAction(Opcode, MVT::nxv32i16, Custom);
2173 setOperationAction(Opcode, MVT::nxv16i32, Custom);
2174 setOperationAction(Opcode, MVT::nxv8i64, Custom);
2175 setOperationAction(Opcode, MVT::nxv32f16, Custom);
2176 setOperationAction(Opcode, MVT::nxv16f32, Custom);
2177 setOperationAction(Opcode, MVT::nxv8f64, Custom);
2178 setOperationAction(Opcode, MVT::nxv32bf16, Custom);
2179 }
2180 }
2181 }
2182
2183 // Handle partial reduction operations
2184 if (Subtarget->isSVEorStreamingSVEAvailable()) {
2185 // Mark known legal pairs as 'Legal' (these will expand to UDOT or SDOT).
2186 // Other pairs will default to 'Expand'.
2187 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
2189 setPartialReduceMLAAction(MLAOps, MVT::nxv2i64, MVT::nxv8i16, Legal);
2190 setPartialReduceMLAAction(MLAOps, MVT::nxv4i32, MVT::nxv16i8, Legal);
2191
2192 setPartialReduceMLAAction(MLAOps, MVT::nxv2i64, MVT::nxv16i8, Custom);
2193
2194 if (Subtarget->hasMatMulInt8()) {
2196 MVT::nxv16i8, Legal);
2198 MVT::nxv16i8, Custom);
2199 }
2200
2201 if (Subtarget->hasSVE2() || Subtarget->hasSME()) {
2202 // Wide add types
2203 setPartialReduceMLAAction(MLAOps, MVT::nxv2i64, MVT::nxv4i32, Legal);
2204 setPartialReduceMLAAction(MLAOps, MVT::nxv4i32, MVT::nxv8i16, Legal);
2205 setPartialReduceMLAAction(MLAOps, MVT::nxv8i16, MVT::nxv16i8, Legal);
2206
2207 setOperationAction(ISD::CLMUL, {MVT::nxv16i8, MVT::nxv4i32}, Legal);
2208 setOperationAction(ISD::CLMUL, MVT::nxv8i16, Custom);
2209
2211 MVT::nxv8f16, Legal);
2212
2213 // We can use SVE2p1 fdot or SVE2 fmlalb/t to emulate the fixed-length
2214 // variant (unless NEON fdot is natively available).
2215 if (!Subtarget->isNeonAvailable() ||
2216 (!Subtarget->hasF16F32DOT() && !Subtarget->hasFP16FML())) {
2218 MVT::v8f16, Custom);
2220 MVT::v4f16, Custom);
2221 }
2222 }
2223
2224 // Map generic PEXT/PDEP to SVE2 bitperm BEXT/BDEP instructions.
2225 if (Subtarget->hasSVEBitPerm() &&
2226 (Subtarget->isSVEAvailable() ||
2227 (Subtarget->isSVEorStreamingSVEAvailable() &&
2228 Subtarget->hasSSVE_BitPerm()))) {
2229 for (auto VT : {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32, MVT::nxv2i64}) {
2231 }
2234 }
2235
2236 if (Subtarget->hasBF16())
2238 MVT::nxv8bf16, Legal);
2239 setOperationAction(ISD::CLMUL, MVT::nxv2i64, Custom);
2240 }
2241
2242 if (Subtarget->isSVEAvailable() ||
2243 (Subtarget->isSVEorStreamingSVEAvailable() && Subtarget->hasSME2p2())) {
2244 // We can lower types that have <vscale x {2|4}> elements to compact.
2245 for (auto VT :
2246 {MVT::nxv4i32, MVT::nxv2i64, MVT::nxv2f32, MVT::nxv4f32, MVT::nxv2f64})
2248 for (auto VT : {MVT::nxv2i8, MVT::nxv2i16, MVT::nxv2i32, MVT::nxv2i64,
2249 MVT::nxv2f32, MVT::nxv2f64, MVT::nxv4i8, MVT::nxv4i16,
2250 MVT::nxv4i32, MVT::nxv4f32}) {
2251 // Use a custom lowering for masked stores that could be a supported
2252 // compressing store. Note: These types still use the normal (Legal)
2253 // lowering for non-compressing masked stores.
2255 }
2256
2257 // If we have SVE, we can use SVE logic for legal NEON vectors in the lowest
2258 // bits of the SVE register.
2259 for (auto VT : {MVT::v2i32, MVT::v4i32, MVT::v2i64, MVT::v2f32, MVT::v4f32,
2260 MVT::v2f64}) {
2263 }
2264
2265 // Promote nxv4<f16|bf16> to nxv4i32.
2267 MVT::nxv4i16);
2269 MVT::nxv4i16);
2271 MVT::nxv4i32);
2272
2273 // Promote nxv2<f16|bf16> to nxv2i64.
2275 MVT::nxv2i16);
2277 MVT::nxv2i16);
2279 MVT::nxv2i64);
2280
2281 if (Subtarget->hasSVE2p2() || Subtarget->hasSME2p2()) {
2282 // With +sve2p2/+sme2p2 the full range of vector types are supported.
2283 for (auto VT :
2284 {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv8f16, MVT::nxv8bf16}) {
2285 // Use custom lowering for MSTORE so we can handle compressstore (using
2286 // VECTOR_COMPRESS).
2289 }
2290
2291 for (auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v4f16,
2292 MVT::v8f16, MVT::v4bf16, MVT::v8bf16})
2294 } else {
2295 // Promote v4i16/f16 to v4i32/f32 as the SVE container for v4i16 is nxv8,
2296 // which is not supported with for compact (with only +sve).
2297 setOperationPromotedToType(ISD::VECTOR_COMPRESS, MVT::v4bf16, MVT::v4i16);
2298 setOperationPromotedToType(ISD::VECTOR_COMPRESS, MVT::v4f16, MVT::v4i16);
2299 setOperationPromotedToType(ISD::VECTOR_COMPRESS, MVT::v4i16, MVT::v4i32);
2300 }
2301 }
2302
2303 // Handle non-aliasing elements mask
2304 if (Subtarget->hasSVE2() ||
2305 (Subtarget->hasSME() && Subtarget->isStreaming())) {
2306 // FIXME: Support wider fixed-length types when msve-vector-bits is used.
2307 for (auto VT : {MVT::v2i32, MVT::v4i16, MVT::v8i8, MVT::v16i8}) {
2310 }
2311 for (auto VT : {MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1, MVT::nxv16i1}) {
2314 }
2315 }
2316
2317 // Handle operations that are only available in non-streaming SVE mode.
2318 if (Subtarget->isSVEAvailable()) {
2319 for (auto VT : {MVT::nxv16i8, MVT::nxv8i16, MVT::nxv4i32, MVT::nxv2i64,
2320 MVT::nxv2f16, MVT::nxv4f16, MVT::nxv8f16, MVT::nxv2f32,
2321 MVT::nxv4f32, MVT::nxv2f64, MVT::nxv2bf16, MVT::nxv4bf16,
2322 MVT::nxv8bf16, MVT::v4f16, MVT::v8f16, MVT::v4bf16,
2323 MVT::v8bf16, MVT::v2f32, MVT::v4f32, MVT::v1f64,
2324 MVT::v2f64, MVT::v8i8, MVT::v16i8, MVT::v4i16,
2325 MVT::v8i16, MVT::v2i32, MVT::v4i32, MVT::v1i64,
2326 MVT::v2i64}) {
2329 }
2330
2331 for (auto VT : {MVT::nxv2f16, MVT::nxv4f16, MVT::nxv8f16, MVT::nxv2f32,
2332 MVT::nxv4f32, MVT::nxv2f64, MVT::v4f16, MVT::v8f16,
2333 MVT::v2f32, MVT::v4f32, MVT::v2f64})
2335
2336 // Histcnt is SVE2 only
2337 if (Subtarget->hasSVE2()) {
2339 Custom);
2341 Custom);
2342
2343 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
2345 // Must be lowered to SVE instructions.
2346 setPartialReduceMLAAction(MLAOps, MVT::v2i64, MVT::v4i32, Custom);
2347 setPartialReduceMLAAction(MLAOps, MVT::v2i64, MVT::v8i16, Custom);
2348 setPartialReduceMLAAction(MLAOps, MVT::v2i64, MVT::v16i8, Custom);
2349 setPartialReduceMLAAction(MLAOps, MVT::v4i32, MVT::v8i16, Custom);
2350 setPartialReduceMLAAction(MLAOps, MVT::v4i32, MVT::v16i8, Custom);
2351 setPartialReduceMLAAction(MLAOps, MVT::v8i16, MVT::v16i8, Custom);
2352 }
2353 }
2354
2355 if (Subtarget->hasMOPS() && Subtarget->hasMTE()) {
2356 // Only required for llvm.aarch64.mops.memset.tag
2358 }
2359
2361
2362 if (Subtarget->hasSVE()) {
2367 }
2368
2369 PredictableSelectIsExpensive = Subtarget->predictableSelectIsExpensive();
2370
2371 IsStrictFPEnabled = true;
2373
2374 // On MSVC, both 32-bit and 64-bit, ldexpf(f32) is not defined. MinGW has
2375 // it, but it's just a wrapper around ldexp.
2376 if (Subtarget->isTargetWindows()) {
2378 if (isOperationExpand(Op, MVT::f32))
2379 setOperationAction(Op, MVT::f32, Promote);
2380 }
2381
2382 // LegalizeDAG currently can't expand fp16/bf16 LDEXP/FREXP on targets where
2383 // i16 isn't legal.
2385 if (isOperationExpand(Op, MVT::f16))
2386 setOperationAction(Op, MVT::f16, Promote);
2387 if (isOperationExpand(Op, MVT::bf16))
2388 setOperationAction(Op, MVT::bf16, Promote);
2389 }
2390}
2391
2393 return static_cast<const AArch64TargetMachine &>(getTargetMachine());
2394}
2395
2396void AArch64TargetLowering::addTypeForNEON(MVT VT) {
2397 assert(VT.isVector() && "VT should be a vector type");
2398
2399 if (VT.isFloatingPoint()) {
2401 setOperationPromotedToType(ISD::LOAD, VT, PromoteTo);
2402 setOperationPromotedToType(ISD::STORE, VT, PromoteTo);
2403 }
2404
2405 // Mark vector float intrinsics as expand.
2406 if (VT == MVT::v2f32 || VT == MVT::v4f32 || VT == MVT::v2f64) {
2425 }
2426
2427 // But we do support custom-lowering for FCOPYSIGN.
2428 if (VT == MVT::v2f32 || VT == MVT::v4f32 || VT == MVT::v2f64 ||
2429 ((VT == MVT::v4bf16 || VT == MVT::v8bf16 || VT == MVT::v4f16 ||
2430 VT == MVT::v8f16) &&
2431 Subtarget->hasFullFP16()))
2433
2439 {2, 3}, VT, Custom);
2448
2452 for (MVT InnerVT : MVT::all_valuetypes())
2453 setLoadExtAction(ISD::EXTLOAD, InnerVT, VT, Expand);
2454
2455 // CNT supports only B element sizes, then use UADDLP to widen.
2456 if (VT != MVT::v8i8 && VT != MVT::v16i8)
2458
2464
2465 for (unsigned Opcode :
2468 setOperationAction(Opcode, VT, Custom);
2469
2470 if (!VT.isFloatingPoint())
2472
2473 // [SU][MIN|MAX] are available for all NEON types apart from i64.
2474 if (!VT.isFloatingPoint() && VT != MVT::v2i64 && VT != MVT::v1i64)
2475 for (unsigned Opcode : {ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX})
2476 setOperationAction(Opcode, VT, Legal);
2477
2478 // F[MIN|MAX][NUM|NAN] and simple strict operations are available for all FP
2479 // NEON types.
2480 if (VT.isFloatingPoint() &&
2481 VT.getVectorElementType() != MVT::bf16 &&
2482 (VT.getVectorElementType() != MVT::f16 || Subtarget->hasFullFP16()))
2483 for (unsigned Opcode :
2489 setOperationAction(Opcode, VT, Legal);
2490
2491 // Strict fp extend and trunc are legal
2492 if (VT.isFloatingPoint() && VT.getScalarSizeInBits() != 16)
2494 if (VT.isFloatingPoint() && VT.getScalarSizeInBits() != 64)
2496
2497 // FIXME: We could potentially make use of the vector comparison instructions
2498 // for STRICT_FSETCC and STRICT_FSETCSS, but there's a number of
2499 // complications:
2500 // * FCMPEQ/NE are quiet comparisons, the rest are signalling comparisons,
2501 // so we would need to expand when the condition code doesn't match the
2502 // kind of comparison.
2503 // * Some kinds of comparison require more than one FCMXY instruction so
2504 // would need to be expanded instead.
2505 // * The lowering of the non-strict versions involves target-specific ISD
2506 // nodes so we would likely need to add strict versions of all of them and
2507 // handle them appropriately.
2510
2511 // When little-endian we can use ordinary d and q register loads/stores for
2512 // vector types, but when big-endian we need to use structure load/store which
2513 // only allow post-index addressing.
2514 // With +strict-align, we also need to use LD1/ST1 when the alignment is
2515 // less than the vector size, but we can still use LDR/STR for more-aligned
2516 // accesses, so these are marked as legal here, and the invalid cases are
2517 // rejected in getIndexedAddressParts.
2518 if (Subtarget->isLittleEndian()) {
2519 for (unsigned im = (unsigned)ISD::PRE_INC;
2520 im != (unsigned)ISD::LAST_INDEXED_MODE; ++im) {
2523 }
2524 } else {
2527 }
2528
2529 if (Subtarget->hasD128()) {
2532 }
2533
2534 if (VT.isInteger()) {
2535 // Let common code emit inverted variants of compares we do support.
2541 }
2542}
2543
2545 EVT OpVT) const {
2546 // Only SVE has a 1:1 mapping from intrinsic -> instruction (whilelo).
2547 if (!Subtarget->isSVEorStreamingSVEAvailable() ||
2548 ResVT.getVectorElementType() != MVT::i1)
2549 return true;
2550
2551 // Expand 1 length fixed length vector.
2552 if (ResVT.isFixedLengthVector() && ResVT.getVectorNumElements() == 1)
2553 return true;
2554
2555 // 32 & 64 bit operands are supported. We can promote anything < 64 bits,
2556 // but anything larger should be expanded.
2557 if (OpVT.getFixedSizeInBits() > 64)
2558 return true;
2559
2560 return false;
2561}
2562
2563void AArch64TargetLowering::addTypeForFixedLengthSVE(MVT VT) {
2564 assert(VT.isFixedLengthVector() && "Expected fixed length vector type!");
2565
2566 // By default everything must be expanded.
2567 for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op)
2569
2570 if (VT.isFloatingPoint()) {
2580 }
2581
2583 VT == MVT::v1f64 ? Expand : Custom;
2584
2585 // Mark integer truncating stores/extending loads as having custom lowering
2586 if (VT.isInteger()) {
2587 MVT InnerVT = VT.changeVectorElementType(MVT::i8);
2588 while (InnerVT != VT) {
2589 setTruncStoreAction(VT, InnerVT, Default);
2590 setLoadExtAction(ISD::ZEXTLOAD, VT, InnerVT, Default);
2591 setLoadExtAction(ISD::SEXTLOAD, VT, InnerVT, Default);
2592 setLoadExtAction(ISD::EXTLOAD, VT, InnerVT, Default);
2593 InnerVT = InnerVT.changeVectorElementType(
2594 MVT::getIntegerVT(2 * InnerVT.getScalarSizeInBits()));
2595 }
2596 }
2597
2598 // Mark floating-point truncating stores/extending loads as having custom
2599 // lowering
2600 if (VT.getScalarType() == MVT::f32 || VT.getScalarType() == MVT::f64) {
2601 MVT InnerVT = VT.changeVectorElementType(MVT::f16);
2602 while (InnerVT != VT) {
2603 setTruncStoreAction(VT, InnerVT, Custom);
2604 setLoadExtAction(ISD::EXTLOAD, VT, InnerVT, Default);
2605 InnerVT = InnerVT.changeVectorElementType(
2607 }
2608 }
2609
2610 bool PreferNEON = VT.is64BitVector() || VT.is128BitVector();
2611 bool PreferSVE = !PreferNEON && Subtarget->isSVEAvailable();
2612
2613 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
2615 unsigned NumElts = VT.getVectorNumElements();
2616 if (VT.getVectorElementType() == MVT::i64) {
2617 setPartialReduceMLAAction(MLAOps, VT,
2618 MVT::getVectorVT(MVT::i8, NumElts * 8), Custom);
2619 setPartialReduceMLAAction(MLAOps, VT,
2620 MVT::getVectorVT(MVT::i16, NumElts * 4), Custom);
2621 setPartialReduceMLAAction(MLAOps, VT,
2622 MVT::getVectorVT(MVT::i32, NumElts * 2), Custom);
2623 } else if (VT.getVectorElementType() == MVT::i32) {
2624 setPartialReduceMLAAction(MLAOps, VT,
2625 MVT::getVectorVT(MVT::i8, NumElts * 4), Custom);
2626 setPartialReduceMLAAction(MLAOps, VT,
2627 MVT::getVectorVT(MVT::i16, NumElts * 2), Custom);
2628 } else if (VT.getVectorElementType() == MVT::i16) {
2629 setPartialReduceMLAAction(MLAOps, VT,
2630 MVT::getVectorVT(MVT::i8, NumElts * 2), Custom);
2631 }
2632 if (Subtarget->hasMatMulInt8()) {
2633 if (VT.getVectorElementType() == MVT::i32)
2635 MVT::getVectorVT(MVT::i8, NumElts * 4), Custom);
2636 else if (VT.getVectorElementType() == MVT::i64)
2638 MVT::getVectorVT(MVT::i8, NumElts * 8), Custom);
2639 }
2640
2641 if (Subtarget->hasSVE2p1() && VT.getVectorElementType() == MVT::f32) {
2643 MVT::getVectorVT(MVT::f16, NumElts * 2), Custom);
2644 }
2645
2646 // Lower fixed length vector operations to scalable equivalents.
2653 setOperationAction(ISD::BITCAST, VT, PreferNEON ? Legal : Default);
2696 setOperationAction(ISD::LOAD, VT, PreferNEON ? Legal : Default);
2699 setOperationAction(ISD::MGATHER, VT, PreferSVE ? Default : Expand);
2701 setOperationAction(ISD::MSCATTER, VT, PreferSVE ? Default : Expand);
2720 setOperationAction(ISD::STORE, VT, PreferNEON ? Legal : Default);
2747}
2748
2749void AArch64TargetLowering::addDRType(MVT VT) {
2750 addRegisterClass(VT, &AArch64::FPR64RegClass);
2751 if (Subtarget->isNeonAvailable())
2752 addTypeForNEON(VT);
2753}
2754
2755void AArch64TargetLowering::addQRType(MVT VT) {
2756 addRegisterClass(VT, &AArch64::FPR128RegClass);
2757 if (Subtarget->isNeonAvailable())
2758 addTypeForNEON(VT);
2759}
2760
2762 LLVMContext &C, EVT VT) const {
2763 if (!VT.isVector())
2764 return MVT::i32;
2765 if (VT.isScalableVector())
2766 return EVT::getVectorVT(C, MVT::i1, VT.getVectorElementCount());
2768}
2769
2770// isIntImmediate - This method tests to see if the node is a constant
2771// operand. If so Imm will receive the value.
2772static bool isIntImmediate(const SDNode *N, uint64_t &Imm) {
2774 Imm = C->getZExtValue();
2775 return true;
2776 }
2777 return false;
2778}
2779
2780static bool isVectorizedBinOp(unsigned Opcode) {
2781 switch (Opcode) {
2782 case AArch64ISD::SQDMULH:
2783 return true;
2784 default:
2785 return false;
2786 }
2787}
2788
2789// isOpcWithIntImmediate - This method tests to see if the node is a specific
2790// opcode and that it has a immediate integer right operand.
2791// If so Imm will receive the value.
2792static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc,
2793 uint64_t &Imm) {
2794 return N->getOpcode() == Opc &&
2795 isIntImmediate(N->getOperand(1).getNode(), Imm);
2796}
2797
2799 const APInt &Demanded,
2801 unsigned NewOpc) {
2802 uint64_t OldImm = Imm, NewImm, Enc;
2803 uint64_t Mask = ((uint64_t)(-1LL) >> (64 - Size)), OrigMask = Mask;
2804
2805 // Return if the immediate is already all zeros, all ones, a bimm32 or a
2806 // bimm64.
2807 if (Imm == 0 || Imm == Mask ||
2809 return false;
2810
2811 unsigned EltSize = Size;
2812 uint64_t DemandedBits = Demanded.getZExtValue();
2813
2814 // Clear bits that are not demanded.
2815 Imm &= DemandedBits;
2816
2817 while (true) {
2818 // The goal here is to set the non-demanded bits in a way that minimizes
2819 // the number of switching between 0 and 1. In order to achieve this goal,
2820 // we set the non-demanded bits to the value of the preceding demanded bits.
2821 // For example, if we have an immediate 0bx10xx0x1 ('x' indicates a
2822 // non-demanded bit), we copy bit0 (1) to the least significant 'x',
2823 // bit2 (0) to 'xx', and bit6 (1) to the most significant 'x'.
2824 // The final result is 0b11000011.
2825 uint64_t NonDemandedBits = ~DemandedBits;
2826 uint64_t InvertedImm = ~Imm & DemandedBits;
2827 uint64_t RotatedImm =
2828 ((InvertedImm << 1) | (InvertedImm >> (EltSize - 1) & 1)) &
2829 NonDemandedBits;
2830 uint64_t Sum = RotatedImm + NonDemandedBits;
2831 bool Carry = NonDemandedBits & ~Sum & (1ULL << (EltSize - 1));
2832 uint64_t Ones = (Sum + Carry) & NonDemandedBits;
2833 NewImm = (Imm | Ones) & Mask;
2834
2835 // If NewImm or its bitwise NOT is a shifted mask, it is a bitmask immediate
2836 // or all-ones or all-zeros, in which case we can stop searching. Otherwise,
2837 // we halve the element size and continue the search.
2838 if (isShiftedMask_64(NewImm) || isShiftedMask_64(~(NewImm | ~Mask)))
2839 break;
2840
2841 // We cannot shrink the element size any further if it is 2-bits.
2842 if (EltSize == 2)
2843 return false;
2844
2845 EltSize /= 2;
2846 Mask >>= EltSize;
2847 uint64_t Hi = Imm >> EltSize, DemandedBitsHi = DemandedBits >> EltSize;
2848
2849 // Return if there is mismatch in any of the demanded bits of Imm and Hi.
2850 if (((Imm ^ Hi) & (DemandedBits & DemandedBitsHi) & Mask) != 0)
2851 return false;
2852
2853 // Merge the upper and lower halves of Imm and DemandedBits.
2854 Imm |= Hi;
2855 DemandedBits |= DemandedBitsHi;
2856 }
2857
2858 ++NumOptimizedImms;
2859
2860 // Replicate the element across the register width.
2861 while (EltSize < Size) {
2862 NewImm |= NewImm << EltSize;
2863 EltSize *= 2;
2864 }
2865
2866 (void)OldImm;
2867 assert(((OldImm ^ NewImm) & Demanded.getZExtValue()) == 0 &&
2868 "demanded bits should never be altered");
2869 assert(OldImm != NewImm && "the new imm shouldn't be equal to the old imm");
2870
2871 // Create the new constant immediate node.
2872 EVT VT = Op.getValueType();
2873 SDLoc DL(Op);
2874 SDValue New;
2875
2876 // If the new constant immediate is all-zeros or all-ones, let the target
2877 // independent DAG combine optimize this node.
2878 if (NewImm == 0 || NewImm == OrigMask) {
2879 New = TLO.DAG.getNode(Op.getOpcode(), DL, VT, Op.getOperand(0),
2880 TLO.DAG.getConstant(NewImm, DL, VT));
2881 // Otherwise, create a machine node so that target independent DAG combine
2882 // doesn't undo this optimization.
2883 } else {
2885 SDValue EncConst = TLO.DAG.getTargetConstant(Enc, DL, VT);
2886 New = SDValue(
2887 TLO.DAG.getMachineNode(NewOpc, DL, VT, Op.getOperand(0), EncConst), 0);
2888 }
2889
2890 return TLO.CombineTo(Op, New);
2891}
2892
2894 SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts,
2895 TargetLoweringOpt &TLO) const {
2896 // Delay this optimization to as late as possible.
2897 if (!TLO.LegalOps)
2898 return false;
2899
2901 return false;
2902
2903 EVT VT = Op.getValueType();
2904 if (VT.isVector())
2905 return false;
2906
2907 unsigned Size = VT.getSizeInBits();
2908
2909 if (Size != 32 && Size != 64)
2910 return false;
2911
2912 // Exit early if we demand all bits.
2913 if (DemandedBits.isAllOnes())
2914 return false;
2915
2916 unsigned NewOpc;
2917 switch (Op.getOpcode()) {
2918 default:
2919 return false;
2920 case ISD::AND:
2921 NewOpc = Size == 32 ? AArch64::ANDWri : AArch64::ANDXri;
2922 break;
2923 case ISD::OR:
2924 NewOpc = Size == 32 ? AArch64::ORRWri : AArch64::ORRXri;
2925 break;
2926 case ISD::XOR:
2927 NewOpc = Size == 32 ? AArch64::EORWri : AArch64::EORXri;
2928 break;
2929 }
2930 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
2931 if (!C)
2932 return false;
2933 uint64_t Imm = C->getZExtValue();
2934 return optimizeLogicalImm(Op, Size, Imm, DemandedBits, TLO, NewOpc);
2935}
2936
2937/// computeKnownBitsForTargetNode - Determine which of the bits specified in
2938/// Mask are known to be either zero or one and return them Known.
2940 const SDValue Op, KnownBits &Known, const APInt &DemandedElts,
2941 const SelectionDAG &DAG, unsigned Depth) const {
2942 switch (Op.getOpcode()) {
2943 default:
2944 break;
2945 case AArch64ISD::DUP: {
2946 SDValue SrcOp = Op.getOperand(0);
2947 Known = DAG.computeKnownBits(SrcOp, Depth + 1);
2948 if (SrcOp.getValueSizeInBits() != Op.getScalarValueSizeInBits()) {
2949 assert(SrcOp.getValueSizeInBits() > Op.getScalarValueSizeInBits() &&
2950 "Expected DUP implicit truncation");
2951 Known = Known.trunc(Op.getScalarValueSizeInBits());
2952 }
2953 break;
2954 }
2955 case AArch64ISD::CSEL: {
2956 KnownBits Known2;
2957 Known = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
2958 Known2 = DAG.computeKnownBits(Op->getOperand(1), Depth + 1);
2959 Known = Known.intersectWith(Known2);
2960 break;
2961 }
2962 case AArch64ISD::CSNEG:
2963 case AArch64ISD::CSINC:
2964 case AArch64ISD::CSINV: {
2965 KnownBits KnownOp0 = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
2966 KnownBits KnownOp1 = DAG.computeKnownBits(Op->getOperand(1), Depth + 1);
2967
2968 // The result is either:
2969 // CSINC: KnownOp0 or KnownOp1 + 1
2970 // CSINV: KnownOp0 or ~KnownOp1
2971 // CSNEG: KnownOp0 or KnownOp1 * -1
2972 if (Op.getOpcode() == AArch64ISD::CSINC)
2973 KnownOp1 = KnownBits::add(
2974 KnownOp1,
2975 KnownBits::makeConstant(APInt(Op.getScalarValueSizeInBits(), 1)));
2976 else if (Op.getOpcode() == AArch64ISD::CSINV)
2977 std::swap(KnownOp1.Zero, KnownOp1.One);
2978 else if (Op.getOpcode() == AArch64ISD::CSNEG)
2979 KnownOp1 =
2981 Op.getScalarValueSizeInBits())));
2982
2983 Known = KnownOp0.intersectWith(KnownOp1);
2984 break;
2985 }
2986 case AArch64ISD::BICi: {
2987 // Compute the bit cleared value.
2988 APInt Mask =
2989 ~(Op->getConstantOperandAPInt(1) << Op->getConstantOperandAPInt(2))
2990 .trunc(Known.getBitWidth());
2991 Known = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
2993 break;
2994 }
2995 case AArch64ISD::VLSHR: {
2996 KnownBits Known2;
2997 Known = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
2998 Known2 = DAG.computeKnownBits(Op->getOperand(1), Depth + 1);
2999 Known = KnownBits::lshr(Known, Known2);
3000 break;
3001 }
3002 case AArch64ISD::VASHR: {
3003 KnownBits Known2;
3004 Known = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
3005 Known2 = DAG.computeKnownBits(Op->getOperand(1), Depth + 1);
3006 Known = KnownBits::ashr(Known, Known2);
3007 break;
3008 }
3009 case AArch64ISD::VSHL: {
3010 KnownBits Known2;
3011 Known = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
3012 Known2 = DAG.computeKnownBits(Op->getOperand(1), Depth + 1);
3013 Known = KnownBits::shl(Known, Known2);
3014 break;
3015 }
3016 case AArch64ISD::MOVI: {
3018 APInt(Known.getBitWidth(), Op->getConstantOperandVal(0)));
3019 break;
3020 }
3021 case AArch64ISD::MOVIshift: {
3023 APInt(Known.getBitWidth(), Op->getConstantOperandVal(0)
3024 << Op->getConstantOperandVal(1)));
3025 break;
3026 }
3027 case AArch64ISD::MOVImsl: {
3028 unsigned ShiftAmt = AArch64_AM::getShiftValue(Op->getConstantOperandVal(1));
3030 Known.getBitWidth(), ~(~Op->getConstantOperandVal(0) << ShiftAmt)));
3031 break;
3032 }
3033 case AArch64ISD::MOVIedit: {
3035 Known.getBitWidth(),
3036 AArch64_AM::decodeAdvSIMDModImmType10(Op->getConstantOperandVal(0))));
3037 break;
3038 }
3039 case AArch64ISD::MVNIshift: {
3041 APInt(Known.getBitWidth(),
3042 ~(Op->getConstantOperandVal(0) << Op->getConstantOperandVal(1)),
3043 /*isSigned*/ false, /*implicitTrunc*/ true));
3044 break;
3045 }
3046 case AArch64ISD::MVNImsl: {
3047 unsigned ShiftAmt = AArch64_AM::getShiftValue(Op->getConstantOperandVal(1));
3049 APInt(Known.getBitWidth(), (~Op->getConstantOperandVal(0) << ShiftAmt),
3050 /*isSigned*/ false, /*implicitTrunc*/ true));
3051 break;
3052 }
3053 case AArch64ISD::LOADgot:
3054 case AArch64ISD::ADDlow: {
3055 if (!Subtarget->isTargetILP32())
3056 break;
3057 // In ILP32 mode all valid pointers are in the low 4GB of the address-space.
3058 Known.Zero = APInt::getHighBitsSet(64, 32);
3059 break;
3060 }
3061 case AArch64ISD::ASSERT_ZEXT_BOOL: {
3062 Known = DAG.computeKnownBits(Op->getOperand(0), Depth + 1);
3063 Known.Zero |= APInt(Known.getBitWidth(), 0xFE);
3064 break;
3065 }
3067 Intrinsic::ID IntID =
3068 static_cast<Intrinsic::ID>(Op->getConstantOperandVal(1));
3069 switch (IntID) {
3070 default: return;
3071 case Intrinsic::aarch64_ldaxr:
3072 case Intrinsic::aarch64_ldxr: {
3073 unsigned BitWidth = Known.getBitWidth();
3074 EVT VT = cast<MemIntrinsicSDNode>(Op)->getMemoryVT();
3075 unsigned MemBits = VT.getScalarSizeInBits();
3076 Known.Zero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits);
3077 return;
3078 }
3079 }
3080 break;
3081 }
3082 case AArch64ISD::SHL_PRED:
3083 case AArch64ISD::SRL_PRED:
3084 case AArch64ISD::SRA_PRED: {
3085 SDValue Pg = Op->getOperand(0);
3086 if (!isAllActivePredicate(DAG, Pg))
3087 break;
3088
3089 KnownBits KnownVal =
3090 DAG.computeKnownBits(Op->getOperand(1), DemandedElts, Depth + 1);
3091 KnownBits KnownAmt =
3092 DAG.computeKnownBits(Op->getOperand(2), DemandedElts, Depth + 1);
3093
3094 if (Op.getOpcode() == AArch64ISD::SHL_PRED)
3095 Known = KnownBits::shl(KnownVal, KnownAmt);
3096 else if (Op.getOpcode() == AArch64ISD::SRL_PRED)
3097 Known = KnownBits::lshr(KnownVal, KnownAmt);
3098 else
3099 Known = KnownBits::ashr(KnownVal, KnownAmt);
3100 break;
3101 }
3103 case ISD::INTRINSIC_VOID: {
3104 unsigned IntNo = Op.getConstantOperandVal(0);
3105 switch (IntNo) {
3106 default:
3107 break;
3108 case Intrinsic::aarch64_neon_uaddlv: {
3109 MVT VT = Op.getOperand(1).getValueType().getSimpleVT();
3110 unsigned BitWidth = Known.getBitWidth();
3111 if (VT == MVT::v8i8 || VT == MVT::v16i8) {
3112 unsigned Bound = (VT == MVT::v8i8) ? 11 : 12;
3113 assert(BitWidth >= Bound && "Unexpected width!");
3115 Known.Zero |= Mask;
3116 }
3117 break;
3118 }
3119 case Intrinsic::aarch64_neon_umaxv:
3120 case Intrinsic::aarch64_neon_uminv: {
3121 // Figure out the datatype of the vector operand. The UMINV instruction
3122 // will zero extend the result, so we can mark as known zero all the
3123 // bits larger than the element datatype. 32-bit or larget doesn't need
3124 // this as those are legal types and will be handled by isel directly.
3125 MVT VT = Op.getOperand(1).getValueType().getSimpleVT();
3126 unsigned BitWidth = Known.getBitWidth();
3127 if (VT == MVT::v8i8 || VT == MVT::v16i8) {
3128 assert(BitWidth >= 8 && "Unexpected width!");
3130 Known.Zero |= Mask;
3131 } else if (VT == MVT::v4i16 || VT == MVT::v8i16) {
3132 assert(BitWidth >= 16 && "Unexpected width!");
3134 Known.Zero |= Mask;
3135 }
3136 break;
3137 } break;
3138 }
3139 }
3140 }
3141}
3142
3144 SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG,
3145 unsigned Depth) const {
3146 EVT VT = Op.getValueType();
3147 unsigned VTBits = VT.getScalarSizeInBits();
3148 unsigned Opcode = Op.getOpcode();
3149 switch (Opcode) {
3150 case AArch64ISD::FCMEQ:
3151 case AArch64ISD::FCMGE:
3152 case AArch64ISD::FCMGT:
3153 // Compares return either 0 or all-ones
3154 return VTBits;
3155 case AArch64ISD::VASHR: {
3156 unsigned Tmp =
3157 DAG.ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);
3158 return std::min<uint64_t>(Tmp + Op.getConstantOperandVal(1), VTBits);
3159 }
3160 }
3161
3162 return 1;
3163}
3164
3166 GISelValueTracking &Analysis, Register R, const APInt &DemandedElts,
3167 const MachineRegisterInfo &MRI, unsigned Depth) const {
3168 const MachineInstr *MI = MRI.getVRegDef(R);
3169 if (!MI)
3170 return 1;
3171
3172 switch (MI->getOpcode()) {
3173 case AArch64::G_FCMEQ:
3174 case AArch64::G_FCMGE:
3175 case AArch64::G_FCMGT: {
3176 LLT VT = MRI.getType(R);
3177 return VT.getScalarSizeInBits();
3178 }
3179 case AArch64::G_VASHR: {
3180 unsigned Tmp = Analysis.computeNumSignBits(MI->getOperand(1).getReg(),
3181 DemandedElts, Depth + 1);
3182 LLT VT = MRI.getType(R);
3183 return std::min<uint64_t>(Tmp + MI->getOperand(2).getImm(),
3184 VT.getScalarSizeInBits());
3185 }
3186 default:
3187 return 1;
3188 }
3189}
3190
3192 EVT) const {
3193 return MVT::i64;
3194}
3195
3197 EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,
3198 unsigned *Fast) const {
3199
3200 // Allow SVE loads/stores where the alignment >= the size of the element type,
3201 // even with +strict-align. Predicated SVE loads/stores (e.g. ld1/st1), used
3202 // for stores that come from IR, only require element-size alignment (even if
3203 // unaligned accesses are disabled). Without this, these will be forced to
3204 // have 16-byte alignment with +strict-align (and fail to lower as we don't
3205 // yet support TLI.expandUnalignedLoad() and TLI.expandUnalignedStore()).
3206 //
3207 // For NEON in strict-align mode, we need to use LD1/ST1 when the alignment
3208 // is less than the size of the vector, but greater than or equal to the size
3209 // of the elements.
3210 bool UseNEONLd1 = Subtarget->requiresStrictAlign() &&
3211 VT.isFixedLengthVector() &&
3212 (VT.getSizeInBits() == 64 || VT.getSizeInBits() == 128);
3213 if (VT.isScalableVector() || UseNEONLd1) {
3214 unsigned ElementSizeBits = VT.getScalarSizeInBits();
3215 if (ElementSizeBits % 8 == 0 && Alignment >= Align(ElementSizeBits / 8))
3216 return true;
3217 }
3218
3219 if (Subtarget->requiresStrictAlign())
3220 return false;
3221
3222 if (Fast) {
3223 // Some CPUs are fine with unaligned stores except for 128-bit ones.
3224 *Fast = !Subtarget->isMisaligned128StoreSlow() || VT.getStoreSize() != 16 ||
3225 // See comments in performSTORECombine() for more details about
3226 // these conditions.
3227
3228 // Code that uses clang vector extensions can mark that it
3229 // wants unaligned accesses to be treated as fast by
3230 // underspecifying alignment to be 1 or 2.
3231 Alignment <= 2 ||
3232
3233 // Disregard v2i64. Memcpy lowering produces those and splitting
3234 // them regresses performance on micro-benchmarks and olden/bh.
3235 VT == MVT::v2i64;
3236 }
3237 return true;
3238}
3239
3240// Same as above but handling LLTs instead.
3242 LLT Ty, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,
3243 unsigned *Fast) const {
3244 if (Subtarget->requiresStrictAlign())
3245 return false;
3246
3247 if (Fast) {
3248 // Some CPUs are fine with unaligned stores except for 128-bit ones.
3249 *Fast = !Subtarget->isMisaligned128StoreSlow() ||
3250 Ty.getSizeInBytes() != 16 ||
3251 // See comments in performSTORECombine() for more details about
3252 // these conditions.
3253
3254 // Code that uses clang vector extensions can mark that it
3255 // wants unaligned accesses to be treated as fast by
3256 // underspecifying alignment to be 1 or 2.
3257 Alignment <= 2 ||
3258
3259 // Disregard v2i64. Memcpy lowering produces those and splitting
3260 // them regresses performance on micro-benchmarks and olden/bh.
3261 Ty == LLT::fixed_vector(2, 64);
3262 }
3263 return true;
3264}
3265
3267 FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo,
3268 const LibcallLoweringInfo *libcallLowering) const {
3269 return AArch64::createFastISel(funcInfo, libInfo, libcallLowering);
3270}
3271
3274 MachineBasicBlock *MBB) const {
3275 // We materialise the F128CSEL pseudo-instruction as some control flow and a
3276 // phi node:
3277
3278 // OrigBB:
3279 // [... previous instrs leading to comparison ...]
3280 // b.ne TrueBB
3281 // b EndBB
3282 // TrueBB:
3283 // ; Fallthrough
3284 // EndBB:
3285 // Dest = PHI [IfTrue, TrueBB], [IfFalse, OrigBB]
3286
3287 MachineFunction *MF = MBB->getParent();
3288 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3289 const BasicBlock *LLVM_BB = MBB->getBasicBlock();
3290 DebugLoc DL = MI.getDebugLoc();
3291 MachineFunction::iterator It = ++MBB->getIterator();
3292
3293 Register DestReg = MI.getOperand(0).getReg();
3294 Register IfTrueReg = MI.getOperand(1).getReg();
3295 Register IfFalseReg = MI.getOperand(2).getReg();
3296 unsigned CondCode = MI.getOperand(3).getImm();
3297 bool NZCVKilled = MI.getOperand(4).isKill();
3298
3299 MachineBasicBlock *TrueBB = MF->CreateMachineBasicBlock(LLVM_BB);
3300 MachineBasicBlock *EndBB = MF->CreateMachineBasicBlock(LLVM_BB);
3301 MF->insert(It, TrueBB);
3302 MF->insert(It, EndBB);
3303
3304 // Transfer rest of current basic-block to EndBB
3305 EndBB->splice(EndBB->begin(), MBB, std::next(MachineBasicBlock::iterator(MI)),
3306 MBB->end());
3308
3309 BuildMI(MBB, DL, TII->get(AArch64::Bcc)).addImm(CondCode).addMBB(TrueBB);
3310 BuildMI(MBB, DL, TII->get(AArch64::B)).addMBB(EndBB);
3311 MBB->addSuccessor(TrueBB);
3312 MBB->addSuccessor(EndBB);
3313
3314 // TrueBB falls through to the end.
3315 TrueBB->addSuccessor(EndBB);
3316
3317 if (!NZCVKilled) {
3318 TrueBB->addLiveIn(AArch64::NZCV);
3319 EndBB->addLiveIn(AArch64::NZCV);
3320 }
3321
3322 BuildMI(*EndBB, EndBB->begin(), DL, TII->get(AArch64::PHI), DestReg)
3323 .addReg(IfTrueReg)
3324 .addMBB(TrueBB)
3325 .addReg(IfFalseReg)
3326 .addMBB(MBB);
3327
3328 MI.eraseFromParent();
3329 return EndBB;
3330}
3331
3339
3342 MachineBasicBlock *MBB) const {
3343 MachineFunction *MF = MBB->getParent();
3344 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3345 DebugLoc DL = MI.getDebugLoc();
3346
3348 BuildMI(*MBB, MI, DL, TII->get(AArch64::MSR))
3349 .addImm(0xda22)
3350 .add(MI.getOperand(0))
3351 .addDef(AArch64::FPMR, RegState::Implicit);
3352 MI.eraseFromParent();
3353 return MBB;
3354 }
3355
3356 Register NewFpmrVal = MI.getOperand(0).getReg();
3357 const BasicBlock *LLVM_BB = MBB->getBasicBlock();
3358 MachineBasicBlock *MsrBB = MF->CreateMachineBasicBlock(LLVM_BB);
3359 MachineBasicBlock *EndBB = MBB->splitAt(MI);
3360 MF->insert(++MBB->getIterator(), MsrBB);
3361
3362 Register CurrentFpmrVal =
3363 MF->getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
3364 BuildMI(*MBB, MI, DL, TII->get(AArch64::MRS), CurrentFpmrVal)
3365 .addImm(0xda22)
3366 .addUse(AArch64::FPMR, RegState::Implicit);
3367 BuildMI(*MBB, MI, DL, TII->get(AArch64::SUBSXrs), AArch64::XZR)
3368 .addReg(CurrentFpmrVal, RegState::Kill)
3369 .addReg(NewFpmrVal)
3370 .addImm(0);
3371 BuildMI(*MBB, MI, DL, TII->get(AArch64::Bcc))
3373 .addMBB(EndBB);
3374 BuildMI(*MsrBB, MsrBB->begin(), DL, TII->get(AArch64::MSR))
3375 .addImm(0xda22)
3376 .addReg(NewFpmrVal, getKillRegState(MI.getOperand(0).isDead()))
3377 .addDef(AArch64::FPMR, RegState::Implicit);
3378
3379 MBB->addSuccessor(MsrBB);
3380 MsrBB->addSuccessor(EndBB);
3381
3382 MI.eraseFromParent();
3383 return EndBB;
3384}
3385
3388 MachineBasicBlock *MBB) const {
3389 MachineFunction &MF = *MBB->getParent();
3390 MachineBasicBlock::iterator MBBI = MI.getIterator();
3391 const AArch64InstrInfo &TII =
3392 *MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
3393 Register TargetReg = MI.getOperand(0).getReg();
3395 TII.probedStackAlloc(MBBI, TargetReg, false);
3396
3397 MI.eraseFromParent();
3398 return NextInst->getParent();
3399}
3400
3403 MachineBasicBlock *MBB) const {
3404 MachineFunction *MF = MBB->getParent();
3405 MachineRegisterInfo &MRI = MF->getRegInfo();
3406
3407 const TargetRegisterClass *RC_GPR = &AArch64::GPR64RegClass;
3408 const TargetRegisterClass *RC_GPRsp = &AArch64::GPR64spRegClass;
3409
3410 Register RegVL_GPR = MRI.createVirtualRegister(RC_GPR);
3411 Register RegVL_GPRsp = MRI.createVirtualRegister(RC_GPRsp); // for ADDSVL src
3412 Register RegSVL_GPR = MRI.createVirtualRegister(RC_GPR);
3413 Register RegSVL_GPRsp = MRI.createVirtualRegister(RC_GPRsp); // for ADDSVL dst
3414
3415 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3416 DebugLoc DL = MI.getDebugLoc();
3417
3418 // RDVL requires GPR64, ADDSVL requires GPR64sp
3419 // We need to insert COPY instructions, these will later be removed by the
3420 // RegisterCoalescer
3421 BuildMI(*MBB, MI, DL, TII->get(AArch64::RDVLI_XI), RegVL_GPR).addImm(1);
3422 BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY), RegVL_GPRsp)
3423 .addReg(RegVL_GPR);
3424
3425 BuildMI(*MBB, MI, DL, TII->get(AArch64::ADDSVL_XXI), RegSVL_GPRsp)
3426 .addReg(RegVL_GPRsp)
3427 .addImm(-1);
3428 BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY), RegSVL_GPR)
3429 .addReg(RegSVL_GPRsp);
3430
3431 const BasicBlock *LLVM_BB = MBB->getBasicBlock();
3432 MachineFunction::iterator It = ++MBB->getIterator();
3433 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock(LLVM_BB);
3434 MachineBasicBlock *PassBB = MF->CreateMachineBasicBlock(LLVM_BB);
3435 MF->insert(It, TrapBB);
3436 MF->insert(It, PassBB);
3437
3438 // Continue if vector lengths match
3439 BuildMI(*MBB, MI, DL, TII->get(AArch64::CBZX))
3440 .addReg(RegSVL_GPR)
3441 .addMBB(PassBB);
3442
3443 // Transfer rest of current BB to PassBB
3444 PassBB->splice(PassBB->begin(), MBB,
3445 std::next(MachineBasicBlock::iterator(MI)), MBB->end());
3447
3448 // Trap if vector lengths mismatch
3449 BuildMI(TrapBB, DL, TII->get(AArch64::BRK)).addImm(1);
3450
3451 MBB->addSuccessor(TrapBB);
3452 MBB->addSuccessor(PassBB);
3453
3454 MI.eraseFromParent();
3455 return PassBB;
3456}
3457
3459AArch64TargetLowering::EmitTileLoad(unsigned Opc, unsigned BaseReg,
3461 MachineBasicBlock *BB) const {
3462 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3463 MachineInstrBuilder MIB = BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Opc));
3464
3465 MIB.addReg(BaseReg + MI.getOperand(0).getImm(), RegState::Define);
3466 MIB.add(MI.getOperand(1)); // slice index register
3467 MIB.add(MI.getOperand(2)); // slice index offset
3468 MIB.add(MI.getOperand(3)); // pg
3469 MIB.add(MI.getOperand(4)); // base
3470 MIB.add(MI.getOperand(5)); // offset
3471
3472 MI.eraseFromParent(); // The pseudo is gone now.
3473 return BB;
3474}
3475
3478 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3480 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(AArch64::LDR_ZA));
3481
3482 MIB.addReg(AArch64::ZA, RegState::Define);
3483 MIB.add(MI.getOperand(0)); // Vector select register
3484 MIB.add(MI.getOperand(1)); // Vector select offset
3485 MIB.add(MI.getOperand(2)); // Base
3486 MIB.add(MI.getOperand(1)); // Offset, same as vector select offset
3487
3488 MI.eraseFromParent(); // The pseudo is gone now.
3489 return BB;
3490}
3491
3494 unsigned Opcode,
3495 bool Op0IsDef) const {
3496 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3498
3499 MIB = BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Opcode))
3500 .addReg(MI.getOperand(0).getReg(), getDefRegState(Op0IsDef));
3501 for (unsigned I = 1; I < MI.getNumOperands(); ++I)
3502 MIB.add(MI.getOperand(I));
3503
3504 MI.eraseFromParent(); // The pseudo is gone now.
3505 return BB;
3506}
3507
3509AArch64TargetLowering::EmitZAInstr(unsigned Opc, unsigned BaseReg,
3511 MachineBasicBlock *BB) const {
3512 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3513 MachineInstrBuilder MIB = BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Opc));
3514 unsigned StartIdx = 0;
3515
3516 bool HasTile = BaseReg != AArch64::ZA;
3517 bool HasZPROut = HasTile && MI.getOperand(0).isReg();
3518 if (HasZPROut) {
3519 MIB.add(MI.getOperand(StartIdx)); // Output ZPR
3520 ++StartIdx;
3521 }
3522 if (HasTile) {
3523 MIB.addReg(BaseReg + MI.getOperand(StartIdx).getImm(),
3524 RegState::Define); // Output ZA Tile
3525 MIB.addReg(BaseReg + MI.getOperand(StartIdx).getImm()); // Input Za Tile
3526 StartIdx++;
3527 } else {
3528 // Avoids all instructions with mnemonic za.<sz>[Reg, Imm,
3529 if (MI.getOperand(0).isReg() && !MI.getOperand(1).isImm()) {
3530 MIB.add(MI.getOperand(StartIdx)); // Output ZPR
3531 ++StartIdx;
3532 }
3533 MIB.addReg(BaseReg, RegState::Define).addReg(BaseReg);
3534 }
3535 for (unsigned I = StartIdx; I < MI.getNumOperands(); ++I)
3536 MIB.add(MI.getOperand(I));
3537
3538 MI.eraseFromParent(); // The pseudo is gone now.
3539 return BB;
3540}
3541
3544 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3546 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(AArch64::ZERO_M));
3547 MIB.add(MI.getOperand(0)); // Mask
3548
3549 unsigned Mask = MI.getOperand(0).getImm();
3550 for (unsigned I = 0; I < 8; I++) {
3551 if (Mask & (1 << I))
3552 MIB.addDef(AArch64::ZAD0 + I, RegState::ImplicitDefine);
3553 }
3554
3555 MI.eraseFromParent(); // The pseudo is gone now.
3556 return BB;
3557}
3558
3561 MachineBasicBlock *BB) const {
3562 MachineFunction *MF = BB->getParent();
3563 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3564 const DebugLoc &DL = MI.getDebugLoc();
3565 Register ResultReg = MI.getOperand(0).getReg();
3566 if (MF->getRegInfo().use_empty(ResultReg)) {
3567 // Nothing to do. Pseudo erased below.
3568 } else if (Subtarget->hasSME()) {
3569 BuildMI(*BB, MI, DL, TII->get(AArch64::MRS), ResultReg)
3570 .addImm(AArch64SysReg::SVCR)
3571 .addReg(AArch64::VG, RegState::Implicit);
3572 } else {
3573 RTLIB::Libcall LC = RTLIB::SMEABI_SME_STATE;
3574 const AArch64RegisterInfo *TRI = Subtarget->getRegisterInfo();
3575 BuildMI(*BB, MI, DL, TII->get(AArch64::BL))
3577 .addReg(AArch64::X0, RegState::ImplicitDefine)
3578 .addRegMask(TRI->getCallPreservedMask(*MF, getLibcallCallingConv(LC)));
3579 BuildMI(*BB, MI, DL, TII->get(TargetOpcode::COPY), ResultReg)
3580 .addReg(AArch64::X0);
3581 }
3582 MI.eraseFromParent();
3583 return BB;
3584}
3585
3586// Helper function to find the instruction that defined a virtual register.
3587// If unable to find such instruction, returns nullptr.
3589 Register Reg) {
3590 while (Reg.isVirtual()) {
3592 assert(DefMI && "Virtual register definition not found");
3593 unsigned Opcode = DefMI->getOpcode();
3594
3595 if (Opcode == AArch64::COPY) {
3596 Reg = DefMI->getOperand(1).getReg();
3597 // Vreg is defined by copying from physreg.
3598 if (Reg.isPhysical())
3599 return DefMI;
3600 continue;
3601 }
3602 if (Opcode == AArch64::SUBREG_TO_REG) {
3603 Reg = DefMI->getOperand(1).getReg();
3604 continue;
3605 }
3606
3607 return DefMI;
3608 }
3609 return nullptr;
3610}
3611
3614 MachineOperand &AddrDiscOp, const TargetRegisterClass *AddrDiscRC) const {
3615 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3616 MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
3617 const DebugLoc &DL = MI.getDebugLoc();
3618
3619 Register AddrDisc = AddrDiscOp.getReg();
3620 int64_t IntDisc = IntDiscOp.getImm();
3621 assert(IntDisc == 0 && "Blend components are already expanded");
3622
3623 const MachineInstr *DiscMI = stripVRegCopies(MRI, AddrDisc);
3624 if (DiscMI) {
3625 switch (DiscMI->getOpcode()) {
3626 case AArch64::MOVKXi:
3627 // blend(addr, imm) which is lowered as "MOVK addr, #imm, #48".
3628 // #imm should be an immediate and not a global symbol, for example.
3629 if (DiscMI->getOperand(2).isImm() &&
3630 DiscMI->getOperand(3).getImm() == 48) {
3631 AddrDisc = DiscMI->getOperand(1).getReg();
3632 IntDisc = DiscMI->getOperand(2).getImm();
3633 }
3634 break;
3635 case AArch64::MOVi32imm:
3636 case AArch64::MOVi64imm:
3637 // Small immediate integer constant passed via VReg.
3638 if (DiscMI->getOperand(1).isImm() &&
3639 isUInt<16>(DiscMI->getOperand(1).getImm())) {
3640 AddrDisc = AArch64::NoRegister;
3641 IntDisc = DiscMI->getOperand(1).getImm();
3642 }
3643 break;
3644 }
3645 }
3646
3647 // For uniformity, always use NoRegister, as XZR is not necessarily contained
3648 // in the requested register class.
3649 if (AddrDisc == AArch64::XZR)
3650 AddrDisc = AArch64::NoRegister;
3651
3652 // Make sure AddrDisc operand respects the register class imposed by MI.
3653 if (AddrDisc && MRI.getRegClass(AddrDisc) != AddrDiscRC) {
3654 Register TmpReg = MRI.createVirtualRegister(AddrDiscRC);
3655 BuildMI(*BB, MI, DL, TII->get(AArch64::COPY), TmpReg).addReg(AddrDisc);
3656 AddrDisc = TmpReg;
3657 }
3658
3659 if (AddrDiscOp.getReg() != AddrDisc)
3660 AddrDiscOp.setIsKill(false);
3661
3662 AddrDiscOp.setReg(AddrDisc);
3663 IntDiscOp.setImm(IntDisc);
3664}
3665
3667 MachineInstr &MI, MachineBasicBlock *BB) const {
3668
3669 int SMEOrigInstr = AArch64::getSMEPseudoMap(MI.getOpcode());
3670 if (SMEOrigInstr != -1) {
3671 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
3672 uint64_t SMEMatrixType =
3673 TII->get(MI.getOpcode()).TSFlags & AArch64::SMEMatrixTypeMask;
3674 switch (SMEMatrixType) {
3676 return EmitZAInstr(SMEOrigInstr, AArch64::ZA, MI, BB);
3678 return EmitZAInstr(SMEOrigInstr, AArch64::ZAB0, MI, BB);
3680 return EmitZAInstr(SMEOrigInstr, AArch64::ZAH0, MI, BB);
3682 return EmitZAInstr(SMEOrigInstr, AArch64::ZAS0, MI, BB);
3684 return EmitZAInstr(SMEOrigInstr, AArch64::ZAD0, MI, BB);
3686 return EmitZAInstr(SMEOrigInstr, AArch64::ZAQ0, MI, BB);
3687 }
3688 }
3689
3690 switch (MI.getOpcode()) {
3691 default:
3692#ifndef NDEBUG
3693 MI.dump();
3694#endif
3695 llvm_unreachable("Unexpected instruction for custom inserter!");
3696 case AArch64::EntryPStateSM:
3697 return EmitEntryPStateSM(MI, BB);
3698 case AArch64::F128CSEL:
3699 return EmitF128CSEL(MI, BB);
3700 case TargetOpcode::STATEPOINT:
3701 // STATEPOINT is a pseudo instruction which has no implicit defs/uses
3702 // while bl call instruction (where statepoint will be lowered at the end)
3703 // has implicit def. This def is early-clobber as it will be set at
3704 // the moment of the call and earlier than any use is read.
3705 // Add this implicit dead def here as a workaround.
3706 MI.addOperand(*MI.getMF(),
3708 AArch64::LR, /*isDef*/ true,
3709 /*isImp*/ true, /*isKill*/ false, /*isDead*/ true,
3710 /*isUndef*/ false, /*isEarlyClobber*/ true));
3711 [[fallthrough]];
3712 case TargetOpcode::STACKMAP:
3713 case TargetOpcode::PATCHPOINT:
3714 return emitPatchPoint(MI, BB);
3715
3716 case TargetOpcode::PATCHABLE_EVENT_CALL:
3717 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3718 return BB;
3719
3720 case AArch64::CATCHRET:
3721 return EmitLoweredCatchRet(MI, BB);
3722
3723 case AArch64::PROBED_STACKALLOC_DYN:
3724 return EmitDynamicProbedAlloc(MI, BB);
3725
3726 case AArch64::CHECK_MATCHING_VL_PSEUDO:
3727 return EmitCheckMatchingVL(MI, BB);
3728
3729 case AArch64::LD1_MXIPXX_H_PSEUDO_B:
3730 return EmitTileLoad(AArch64::LD1_MXIPXX_H_B, AArch64::ZAB0, MI, BB);
3731 case AArch64::LD1_MXIPXX_H_PSEUDO_H:
3732 return EmitTileLoad(AArch64::LD1_MXIPXX_H_H, AArch64::ZAH0, MI, BB);
3733 case AArch64::LD1_MXIPXX_H_PSEUDO_S:
3734 return EmitTileLoad(AArch64::LD1_MXIPXX_H_S, AArch64::ZAS0, MI, BB);
3735 case AArch64::LD1_MXIPXX_H_PSEUDO_D:
3736 return EmitTileLoad(AArch64::LD1_MXIPXX_H_D, AArch64::ZAD0, MI, BB);
3737 case AArch64::LD1_MXIPXX_H_PSEUDO_Q:
3738 return EmitTileLoad(AArch64::LD1_MXIPXX_H_Q, AArch64::ZAQ0, MI, BB);
3739 case AArch64::LD1_MXIPXX_V_PSEUDO_B:
3740 return EmitTileLoad(AArch64::LD1_MXIPXX_V_B, AArch64::ZAB0, MI, BB);
3741 case AArch64::LD1_MXIPXX_V_PSEUDO_H:
3742 return EmitTileLoad(AArch64::LD1_MXIPXX_V_H, AArch64::ZAH0, MI, BB);
3743 case AArch64::LD1_MXIPXX_V_PSEUDO_S:
3744 return EmitTileLoad(AArch64::LD1_MXIPXX_V_S, AArch64::ZAS0, MI, BB);
3745 case AArch64::LD1_MXIPXX_V_PSEUDO_D:
3746 return EmitTileLoad(AArch64::LD1_MXIPXX_V_D, AArch64::ZAD0, MI, BB);
3747 case AArch64::LD1_MXIPXX_V_PSEUDO_Q:
3748 return EmitTileLoad(AArch64::LD1_MXIPXX_V_Q, AArch64::ZAQ0, MI, BB);
3749 case AArch64::LDR_ZA_PSEUDO:
3750 return EmitFill(MI, BB);
3751 case AArch64::LDR_TX_PSEUDO:
3752 return EmitZTInstr(MI, BB, AArch64::LDR_TX, /*Op0IsDef=*/true);
3753 case AArch64::STR_TX_PSEUDO:
3754 return EmitZTInstr(MI, BB, AArch64::STR_TX, /*Op0IsDef=*/false);
3755 case AArch64::ZERO_M_PSEUDO:
3756 return EmitZero(MI, BB);
3757 case AArch64::ZERO_T_PSEUDO:
3758 return EmitZTInstr(MI, BB, AArch64::ZERO_T, /*Op0IsDef=*/true);
3759 case AArch64::MOVT_TIZ_PSEUDO:
3760 return EmitZTInstr(MI, BB, AArch64::MOVT_TIZ, /*Op0IsDef=*/true);
3761 case AArch64::MSR_FPMR:
3762 return EmitLoweredSetFpmr(MI, BB);
3763
3764 case AArch64::PAC:
3765 fixupPtrauthDiscriminator(MI, BB, MI.getOperand(3), MI.getOperand(4),
3766 &AArch64::GPR64noipRegClass);
3767 return BB;
3768 }
3769}
3770
3771//===----------------------------------------------------------------------===//
3772// AArch64 Lowering private implementation.
3773//===----------------------------------------------------------------------===//
3774
3775//===----------------------------------------------------------------------===//
3776// Lowering Code
3777//===----------------------------------------------------------------------===//
3778
3779// Forward declarations of SVE fixed length lowering helpers
3784 SelectionDAG &DAG);
3787 EVT VT);
3789 EVT VT);
3791
3792/// isZerosVector - Check whether SDNode N is a zero-filled vector.
3793static bool isZerosVector(const SDNode *N) {
3794 // Look through a bit convert.
3795 while (N->getOpcode() == ISD::BITCAST)
3796 N = N->getOperand(0).getNode();
3797
3799 return true;
3800
3801 if (N->getOpcode() != AArch64ISD::DUP)
3802 return false;
3803
3804 auto Opnd0 = N->getOperand(0);
3805 return isNullConstant(Opnd0) || isNullFPConstant(Opnd0);
3806}
3807
3808static bool isOneVector(SDValue V) {
3809 return isOneOrOneSplat(V) ||
3810 (V.getOpcode() == AArch64ISD::DUP && isOneConstant(V.getOperand(0)));
3811}
3812
3813/// changeIntCCToAArch64CC - Convert a DAG integer condition code to an AArch64
3814/// CC
3816 SDValue RHS = {}) {
3817 switch (CC) {
3818 default:
3819 llvm_unreachable("Unknown condition code!");
3820 case ISD::SETNE:
3821 return AArch64CC::NE;
3822 case ISD::SETEQ:
3823 return AArch64CC::EQ;
3824 case ISD::SETGT:
3825 return AArch64CC::GT;
3826 case ISD::SETGE:
3828 case ISD::SETLT:
3830 case ISD::SETLE:
3831 return AArch64CC::LE;
3832 case ISD::SETUGT:
3833 return AArch64CC::HI;
3834 case ISD::SETUGE:
3835 return AArch64CC::HS;
3836 case ISD::SETULT:
3837 return AArch64CC::LO;
3838 case ISD::SETULE:
3839 return AArch64CC::LS;
3840 }
3841}
3842
3843/// changeFPCCToAArch64CC - Convert a DAG fp condition code to an AArch64 CC.
3845 AArch64CC::CondCode &CondCode,
3846 AArch64CC::CondCode &CondCode2) {
3847 CondCode2 = AArch64CC::AL;
3848 switch (CC) {
3849 default:
3850 llvm_unreachable("Unknown FP condition!");
3851 case ISD::SETEQ:
3852 case ISD::SETOEQ:
3853 CondCode = AArch64CC::EQ;
3854 break;
3855 case ISD::SETGT:
3856 case ISD::SETOGT:
3857 CondCode = AArch64CC::GT;
3858 break;
3859 case ISD::SETGE:
3860 case ISD::SETOGE:
3861 CondCode = AArch64CC::GE;
3862 break;
3863 case ISD::SETOLT:
3864 CondCode = AArch64CC::MI;
3865 break;
3866 case ISD::SETOLE:
3867 CondCode = AArch64CC::LS;
3868 break;
3869 case ISD::SETONE:
3870 CondCode = AArch64CC::MI;
3871 CondCode2 = AArch64CC::GT;
3872 break;
3873 case ISD::SETO:
3874 CondCode = AArch64CC::VC;
3875 break;
3876 case ISD::SETUO:
3877 CondCode = AArch64CC::VS;
3878 break;
3879 case ISD::SETUEQ:
3880 CondCode = AArch64CC::EQ;
3881 CondCode2 = AArch64CC::VS;
3882 break;
3883 case ISD::SETUGT:
3884 CondCode = AArch64CC::HI;
3885 break;
3886 case ISD::SETUGE:
3887 CondCode = AArch64CC::PL;
3888 break;
3889 case ISD::SETLT:
3890 case ISD::SETULT:
3891 CondCode = AArch64CC::LT;
3892 break;
3893 case ISD::SETLE:
3894 case ISD::SETULE:
3895 CondCode = AArch64CC::LE;
3896 break;
3897 case ISD::SETNE:
3898 case ISD::SETUNE:
3899 CondCode = AArch64CC::NE;
3900 break;
3901 }
3902}
3903
3904/// Convert a DAG fp condition code to an AArch64 CC.
3905/// This differs from changeFPCCToAArch64CC in that it returns cond codes that
3906/// should be AND'ed instead of OR'ed.
3908 AArch64CC::CondCode &CondCode,
3909 AArch64CC::CondCode &CondCode2) {
3910 CondCode2 = AArch64CC::AL;
3911 switch (CC) {
3912 default:
3913 changeFPCCToAArch64CC(CC, CondCode, CondCode2);
3914 assert(CondCode2 == AArch64CC::AL);
3915 break;
3916 case ISD::SETONE:
3917 // (a one b)
3918 // == ((a olt b) || (a ogt b))
3919 // == ((a ord b) && (a une b))
3920 CondCode = AArch64CC::VC;
3921 CondCode2 = AArch64CC::NE;
3922 break;
3923 case ISD::SETUEQ:
3924 // (a ueq b)
3925 // == ((a uno b) || (a oeq b))
3926 // == ((a ule b) && (a uge b))
3927 CondCode = AArch64CC::PL;
3928 CondCode2 = AArch64CC::LE;
3929 break;
3930 }
3931}
3932
3933/// changeVectorFPCCToAArch64CC - Convert a DAG fp condition code to an AArch64
3934/// CC usable with the vector instructions. Fewer operations are available
3935/// without a real NZCV register, so we have to use less efficient combinations
3936/// to get the same effect.
3938 AArch64CC::CondCode &CondCode,
3939 AArch64CC::CondCode &CondCode2,
3940 bool &Invert) {
3941 Invert = false;
3942 switch (CC) {
3943 default:
3944 // Mostly the scalar mappings work fine.
3945 changeFPCCToAArch64CC(CC, CondCode, CondCode2);
3946 break;
3947 case ISD::SETUO:
3948 Invert = true;
3949 [[fallthrough]];
3950 case ISD::SETO:
3951 CondCode = AArch64CC::MI;
3952 CondCode2 = AArch64CC::GE;
3953 break;
3954 case ISD::SETLE:
3955 CondCode = AArch64CC::LS;
3956 CondCode2 = AArch64CC::AL;
3957 break;
3958 case ISD::SETLT:
3959 CondCode = AArch64CC::MI;
3960 CondCode2 = AArch64CC::AL;
3961 break;
3962 case ISD::SETUEQ:
3963 case ISD::SETULT:
3964 case ISD::SETULE:
3965 case ISD::SETUGT:
3966 case ISD::SETUGE:
3967 // All of the compare-mask comparisons are ordered, but we can switch
3968 // between the two by a double inversion. E.g. ULE == !OGT.
3969 Invert = true;
3970 changeFPCCToAArch64CC(getSetCCInverse(CC, /* FP inverse */ MVT::f32),
3971 CondCode, CondCode2);
3972 break;
3973 }
3974}
3975
3976/// Like SelectionDAG::getCondCode(), but for AArch64 condition codes.
3978 // TODO: Should be TargetConstant (need to s/imm/timm in patterns).
3979 return DAG.getConstant(CC, SDLoc(), CondCodeVT);
3980}
3981
3982static unsigned numberOfInstrToLoadImm(const APInt &C) {
3983 uint64_t Imm = C.getZExtValue();
3985 AArch64_IMM::expandMOVImm(Imm, 32, Insn);
3986 return Insn.size();
3987}
3988
3990 // 0 - INT_MIN sign wraps, so no signed wrap means cmn is safe.
3991 if (Op->getFlags().hasNoSignedWrap())
3992 return true;
3993
3994 // We can still figure out if the second operand is safe to use
3995 // in a CMN instruction by checking if it is known to be not the minimum
3996 // signed value. If it is not, then we can safely use CMN.
3997 // Note: We can eventually remove this check and simply rely on
3998 // Op->getFlags().hasNoSignedWrap() once SelectionDAG/ISelLowering
3999 // consistently sets them appropriately when making said nodes.
4000
4001 KnownBits KnownSrc = DAG.computeKnownBits(Op.getOperand(1));
4002 return !KnownSrc.getSignedMinValue().isMinSignedValue();
4003}
4004
4005// Can a (CMP op1, (sub 0, op2) be turned into a CMN instruction on
4006// the grounds that "op1 - (-op2) == op1 + op2" ? Not always, the C and V flags
4007// can be set differently by this operation. It comes down to whether
4008// "SInt(~op2)+1 == SInt(~op2+1)" (and the same for UInt). If they are then
4009// everything is fine. If not then the optimization is wrong. Thus general
4010// comparisons are only valid if op2 != 0 and op2 != INT_MIN.
4011//
4012// So, finally, the only LLVM-native comparisons that don't mention C or V
4013// are the ones that aren't unsigned comparisons. They're the only ones we can
4014// safely use CMN for in the absence of information about op2.
4016 return Op.getOpcode() == ISD::SUB && isNullConstant(Op.getOperand(0)) &&
4017 (isIntEqualitySetCC(CC) ||
4018 (isUnsignedIntSetCC(CC) && DAG.isKnownNeverZero(Op.getOperand(1))) ||
4019 (isSignedIntSetCC(CC) && isSafeSignedCMN(Op, DAG)));
4020}
4021
4023 SelectionDAG &DAG, SDValue Chain,
4024 bool IsSignaling) {
4025 EVT VT = LHS.getValueType();
4026 assert(VT != MVT::f128);
4027
4028 const bool FullFP16 = DAG.getSubtarget<AArch64Subtarget>().hasFullFP16();
4029
4030 if ((VT == MVT::f16 && !FullFP16) || VT == MVT::bf16) {
4031 LHS = DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {MVT::f32, MVT::Other},
4032 {Chain, LHS});
4033 RHS = DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {MVT::f32, MVT::Other},
4034 {LHS.getValue(1), RHS});
4035 Chain = RHS.getValue(1);
4036 }
4037 unsigned Opcode =
4038 IsSignaling ? AArch64ISD::STRICT_FCMPE : AArch64ISD::STRICT_FCMP;
4039 return DAG.getNode(Opcode, DL, {FlagsVT, MVT::Other}, {Chain, LHS, RHS});
4040}
4041
4043 const SDLoc &DL, SelectionDAG &DAG) {
4044 EVT VT = LHS.getValueType();
4045 const bool FullFP16 = DAG.getSubtarget<AArch64Subtarget>().hasFullFP16();
4046
4047 if (VT.isFloatingPoint()) {
4048 assert(VT != MVT::f128);
4049 if ((VT == MVT::f16 && !FullFP16) || VT == MVT::bf16) {
4050 LHS = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, LHS);
4051 RHS = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, RHS);
4052 }
4053 return DAG.getNode(AArch64ISD::FCMP, DL, FlagsVT, LHS, RHS);
4054 }
4055
4056 // The CMP instruction is just an alias for SUBS, and representing it as
4057 // SUBS means that it's possible to get CSE with subtract operations.
4058 // A later phase can perform the optimization of setting the destination
4059 // register to WZR/XZR if it ends up being unused.
4060 unsigned Opcode = AArch64ISD::SUBS;
4061
4062 if (isCMN(RHS, CC, DAG)) {
4063 // Can we combine a (CMP op1, (sub 0, op2) into a CMN instruction ?
4064 Opcode = AArch64ISD::ADDS;
4065 RHS = RHS.getOperand(1);
4066 } else if (LHS.getOpcode() == ISD::SUB && isNullConstant(LHS.getOperand(0)) &&
4067 isIntEqualitySetCC(CC)) {
4068 // As we are looking for EQ/NE compares, the operands can be commuted ; can
4069 // we combine a (CMP (sub 0, op1), op2) into a CMN instruction ?
4070 Opcode = AArch64ISD::ADDS;
4071 LHS = LHS.getOperand(1);
4072 } else if (isNullConstant(RHS) && !isUnsignedIntSetCC(CC)) {
4073 if (LHS.getOpcode() == ISD::AND) {
4074 // Similarly, (CMP (and X, Y), 0) can be implemented with a TST
4075 // (a.k.a. ANDS) except that the flags are only guaranteed to work for one
4076 // of the signed comparisons.
4077 const SDValue ANDSNode =
4078 DAG.getNode(AArch64ISD::ANDS, DL, DAG.getVTList(VT, FlagsVT),
4079 LHS.getOperand(0), LHS.getOperand(1));
4080 // Replace all users of (and X, Y) with newly generated (ands X, Y)
4081 DAG.ReplaceAllUsesWith(LHS, ANDSNode);
4082 return ANDSNode.getValue(1);
4083 } else if (LHS.getOpcode() == AArch64ISD::ANDS) {
4084 // Use result of ANDS
4085 return LHS.getValue(1);
4086 }
4087 }
4088
4089 return DAG.getNode(Opcode, DL, DAG.getVTList(VT, FlagsVT), LHS, RHS)
4090 .getValue(1);
4091}
4092
4093/// \defgroup AArch64CCMP CMP;CCMP matching
4094///
4095/// These functions deal with the formation of CMP;CCMP;... sequences.
4096/// The CCMP/CCMN/FCCMP/FCCMPE instructions allow the conditional execution of
4097/// a comparison. They set the NZCV flags to a predefined value if their
4098/// predicate is false. This allows to express arbitrary conjunctions, for
4099/// example "cmp 0 (and (setCA (cmp A)) (setCB (cmp B)))"
4100/// expressed as:
4101/// cmp A
4102/// ccmp B, inv(CB), CA
4103/// check for CB flags
4104///
4105/// This naturally lets us implement chains of AND operations with SETCC
4106/// operands. And we can even implement some other situations by transforming
4107/// them:
4108/// - We can implement (NEG SETCC) i.e. negating a single comparison by
4109/// negating the flags used in a CCMP/FCCMP operations.
4110/// - We can negate the result of a whole chain of CMP/CCMP/FCCMP operations
4111/// by negating the flags we test for afterwards. i.e.
4112/// NEG (CMP CCMP CCCMP ...) can be implemented.
4113/// - Note that we can only ever negate all previously processed results.
4114/// What we can not implement by flipping the flags to test is a negation
4115/// of two sub-trees (because the negation affects all sub-trees emitted so
4116/// far, so the 2nd sub-tree we emit would also affect the first).
4117/// With those tools we can implement some OR operations:
4118/// - (OR (SETCC A) (SETCC B)) can be implemented via:
4119/// NEG (AND (NEG (SETCC A)) (NEG (SETCC B)))
4120/// - After transforming OR to NEG/AND combinations we may be able to use NEG
4121/// elimination rules from earlier to implement the whole thing as a
4122/// CCMP/FCCMP chain.
4123///
4124/// As complete example:
4125/// or (or (setCA (cmp A)) (setCB (cmp B)))
4126/// (and (setCC (cmp C)) (setCD (cmp D)))"
4127/// can be reassociated to:
4128/// or (and (setCC (cmp C)) setCD (cmp D))
4129// (or (setCA (cmp A)) (setCB (cmp B)))
4130/// can be transformed to:
4131/// not (and (not (and (setCC (cmp C)) (setCD (cmp D))))
4132/// (and (not (setCA (cmp A)) (not (setCB (cmp B))))))"
4133/// which can be implemented as:
4134/// cmp C
4135/// ccmp D, inv(CD), CC
4136/// ccmp A, CA, inv(CD)
4137/// ccmp B, CB, inv(CA)
4138/// check for CB flags
4139///
4140/// A counterexample is "or (and A B) (and C D)" which translates to
4141/// not (and (not (and (not A) (not B))) (not (and (not C) (not D)))), we
4142/// can only implement 1 of the inner (not) operations, but not both!
4143/// @{
4144
4145/// Create a conditional comparison; Use CCMP, CCMN or FCCMP as appropriate.
4147 ISD::CondCode CC, SDValue CCOp,
4149 AArch64CC::CondCode OutCC,
4150 const SDLoc &DL, SelectionDAG &DAG) {
4151 unsigned Opcode = 0;
4152 const bool FullFP16 = DAG.getSubtarget<AArch64Subtarget>().hasFullFP16();
4153
4154 if (LHS.getValueType().isFloatingPoint()) {
4155 assert(LHS.getValueType() != MVT::f128);
4156 if ((LHS.getValueType() == MVT::f16 && !FullFP16) ||
4157 LHS.getValueType() == MVT::bf16) {
4158 LHS = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, LHS);
4159 RHS = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, RHS);
4160 }
4161 Opcode = AArch64ISD::FCCMP;
4162 } else if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(RHS)) {
4163 APInt Imm = Const->getAPIntValue();
4164 if (Imm.isNegative() && Imm.sgt(-32)) {
4165 Opcode = AArch64ISD::CCMN;
4166 RHS = DAG.getConstant(Imm.abs(), DL, Const->getValueType(0));
4167 }
4168 } else if (isCMN(RHS, CC, DAG)) {
4169 Opcode = AArch64ISD::CCMN;
4170 RHS = RHS.getOperand(1);
4171 } else if (LHS.getOpcode() == ISD::SUB && isNullConstant(LHS.getOperand(0)) &&
4172 isIntEqualitySetCC(CC)) {
4173 // As we are looking for EQ/NE compares, the operands can be commuted ; can
4174 // we combine a (CCMP (sub 0, op1), op2) into a CCMN instruction ?
4175 Opcode = AArch64ISD::CCMN;
4176 LHS = LHS.getOperand(1);
4177 }
4178 if (Opcode == 0)
4179 Opcode = AArch64ISD::CCMP;
4180
4181 SDValue Condition = getCondCode(DAG, Predicate);
4183 unsigned NZCV = AArch64CC::getNZCVToSatisfyCondCode(InvOutCC);
4184 SDValue NZCVOp = DAG.getConstant(NZCV, DL, MVT::i32);
4185 return DAG.getNode(Opcode, DL, FlagsVT, LHS, RHS, NZCVOp, Condition, CCOp);
4186}
4187
4188/// Returns true if @p Val is a tree of AND/OR/SETCC operations that can be
4189/// expressed as a conjunction. See \ref AArch64CCMP.
4190/// \param CanNegate Set to true if we can negate the whole sub-tree just by
4191/// changing the conditions on the SETCC tests.
4192/// (this means we can call emitConjunctionRec() with
4193/// Negate==true on this sub-tree)
4194/// \param MustBeFirst Set to true if this subtree needs to be negated and we
4195/// cannot do the negation naturally. We are required to
4196/// emit the subtree first in this case.
4197/// \param PreferFirst Set to true if processing this subtree first may
4198/// result in more efficient code.
4199/// \param WillNegate Is true if are called when the result of this
4200/// subexpression must be negated. This happens when the
4201/// outer expression is an OR. We can use this fact to know
4202/// that we have a double negation (or (or ...) ...) that
4203/// can be implemented for free.
4204static bool canEmitConjunction(SelectionDAG &DAG, const SDValue Val,
4205 bool &CanNegate, bool &MustBeFirst,
4206 bool &PreferFirst, bool WillNegate,
4207 unsigned Depth = 0) {
4208 if (!Val.hasOneUse())
4209 return false;
4210 unsigned Opcode = Val->getOpcode();
4211 if (Opcode == ISD::SETCC) {
4212 EVT VT = Val->getOperand(0).getValueType();
4213 if (VT == MVT::f128)
4214 return false;
4215 CanNegate = true;
4216 MustBeFirst = false;
4217 // Designate this operation as a preferred first operation if the result
4218 // of a SUB operation can be reused.
4219 PreferFirst = DAG.doesNodeExist(ISD::SUB, DAG.getVTList(VT),
4220 {Val->getOperand(0), Val->getOperand(1)});
4221 return true;
4222 }
4223 // Protect against exponential runtime and stack overflow.
4224 if (Depth > 6)
4225 return false;
4226 if (Opcode == ISD::AND || Opcode == ISD::OR) {
4227 bool IsOR = Opcode == ISD::OR;
4228 SDValue O0 = Val->getOperand(0);
4229 SDValue O1 = Val->getOperand(1);
4230 bool CanNegateL;
4231 bool MustBeFirstL;
4232 bool PreferFirstL;
4233 if (!canEmitConjunction(DAG, O0, CanNegateL, MustBeFirstL, PreferFirstL,
4234 IsOR, Depth + 1))
4235 return false;
4236 bool CanNegateR;
4237 bool MustBeFirstR;
4238 bool PreferFirstR;
4239 if (!canEmitConjunction(DAG, O1, CanNegateR, MustBeFirstR, PreferFirstR,
4240 IsOR, Depth + 1))
4241 return false;
4242
4243 if (MustBeFirstL && MustBeFirstR)
4244 return false;
4245
4246 if (IsOR) {
4247 // For an OR expression we need to be able to naturally negate at least
4248 // one side or we cannot do the transformation at all.
4249 if (!CanNegateL && !CanNegateR)
4250 return false;
4251 // If we the result of the OR will be negated and we can naturally negate
4252 // the leaves, then this sub-tree as a whole negates naturally.
4253 CanNegate = WillNegate && CanNegateL && CanNegateR;
4254 // If we cannot naturally negate the whole sub-tree, then this must be
4255 // emitted first.
4256 MustBeFirst = !CanNegate;
4257 } else {
4258 assert(Opcode == ISD::AND && "Must be OR or AND");
4259 // We cannot naturally negate an AND operation.
4260 CanNegate = false;
4261 MustBeFirst = MustBeFirstL || MustBeFirstR;
4262 }
4263 PreferFirst = PreferFirstL || PreferFirstR;
4264 return true;
4265 }
4266 return false;
4267}
4268
4269/// Emit conjunction or disjunction tree with the CMP/FCMP followed by a chain
4270/// of CCMP/CFCMP ops. See @ref AArch64CCMP.
4271/// Tries to transform the given i1 producing node @p Val to a series compare
4272/// and conditional compare operations. @returns an NZCV flags producing node
4273/// and sets @p OutCC to the flags that should be tested or returns SDValue() if
4274/// transformation was not possible.
4275/// \p Negate is true if we want this sub-tree being negated just by changing
4276/// SETCC conditions.
4278 AArch64CC::CondCode &OutCC, bool Negate, SDValue CCOp,
4280 // We're at a tree leaf, produce a conditional comparison operation.
4281 unsigned Opcode = Val->getOpcode();
4282 if (Opcode == ISD::SETCC) {
4283 SDValue LHS = Val->getOperand(0);
4284 SDValue RHS = Val->getOperand(1);
4285 ISD::CondCode CC = cast<CondCodeSDNode>(Val->getOperand(2))->get();
4286 bool isInteger = LHS.getValueType().isInteger();
4287 if (Negate)
4288 CC = getSetCCInverse(CC, LHS.getValueType());
4289 SDLoc DL(Val);
4290 // Determine OutCC and handle FP special case.
4291 if (isInteger) {
4292 OutCC = changeIntCCToAArch64CC(CC, RHS);
4293 } else {
4294 assert(LHS.getValueType().isFloatingPoint());
4295 AArch64CC::CondCode ExtraCC;
4296 changeFPCCToANDAArch64CC(CC, OutCC, ExtraCC);
4297 // Some floating point conditions can't be tested with a single condition
4298 // code. Construct an additional comparison in this case.
4299 if (ExtraCC != AArch64CC::AL) {
4300 SDValue ExtraCmp;
4301 if (!CCOp.getNode())
4302 ExtraCmp = emitComparison(LHS, RHS, CC, DL, DAG);
4303 else
4304 ExtraCmp = emitConditionalComparison(LHS, RHS, CC, CCOp, Predicate,
4305 ExtraCC, DL, DAG);
4306 CCOp = ExtraCmp;
4307 Predicate = ExtraCC;
4308 }
4309 }
4310
4311 // Produce a normal comparison if we are first in the chain
4312 if (!CCOp)
4313 return emitComparison(LHS, RHS, CC, DL, DAG);
4314 // Otherwise produce a ccmp.
4315 return emitConditionalComparison(LHS, RHS, CC, CCOp, Predicate, OutCC, DL,
4316 DAG);
4317 }
4318 assert(Val->hasOneUse() && "Valid conjunction/disjunction tree");
4319
4320 bool IsOR = Opcode == ISD::OR;
4321
4322 SDValue LHS = Val->getOperand(0);
4323 bool CanNegateL;
4324 bool MustBeFirstL;
4325 bool PreferFirstL;
4326 bool ValidL = canEmitConjunction(DAG, LHS, CanNegateL, MustBeFirstL,
4327 PreferFirstL, IsOR);
4328 assert(ValidL && "Valid conjunction/disjunction tree");
4329 (void)ValidL;
4330
4331 SDValue RHS = Val->getOperand(1);
4332 bool CanNegateR;
4333 bool MustBeFirstR;
4334 bool PreferFirstR;
4335 bool ValidR = canEmitConjunction(DAG, RHS, CanNegateR, MustBeFirstR,
4336 PreferFirstR, IsOR);
4337 assert(ValidR && "Valid conjunction/disjunction tree");
4338 (void)ValidR;
4339
4340 bool ShouldFirstL = PreferFirstL && !PreferFirstR && !MustBeFirstR;
4341
4342 // Swap sub-tree that must or should come first to the right side.
4343 if (MustBeFirstL || ShouldFirstL) {
4344 assert(!MustBeFirstR && "Valid conjunction/disjunction tree");
4345 std::swap(LHS, RHS);
4346 std::swap(CanNegateL, CanNegateR);
4347 std::swap(MustBeFirstL, MustBeFirstR);
4348 }
4349
4350 bool NegateR;
4351 bool NegateAfterR;
4352 bool NegateL;
4353 bool NegateAfterAll;
4354 if (Opcode == ISD::OR) {
4355 // Swap the sub-tree that we can negate naturally to the left.
4356 if (!CanNegateL) {
4357 assert(CanNegateR && "at least one side must be negatable");
4358 assert(!MustBeFirstR && "invalid conjunction/disjunction tree");
4359 assert(!Negate);
4360 std::swap(LHS, RHS);
4361 NegateR = false;
4362 NegateAfterR = true;
4363 } else {
4364 // Negate the left sub-tree if possible, otherwise negate the result.
4365 NegateR = CanNegateR;
4366 NegateAfterR = !CanNegateR;
4367 }
4368 NegateL = true;
4369 NegateAfterAll = !Negate;
4370 } else {
4371 assert(Opcode == ISD::AND && "Valid conjunction/disjunction tree");
4372 assert(!Negate && "Valid conjunction/disjunction tree");
4373
4374 NegateL = false;
4375 NegateR = false;
4376 NegateAfterR = false;
4377 NegateAfterAll = false;
4378 }
4379
4380 // Emit sub-trees.
4381 AArch64CC::CondCode RHSCC;
4382 SDValue CmpR = emitConjunctionRec(DAG, RHS, RHSCC, NegateR, CCOp, Predicate);
4383 if (NegateAfterR)
4384 RHSCC = AArch64CC::getInvertedCondCode(RHSCC);
4385 SDValue CmpL = emitConjunctionRec(DAG, LHS, OutCC, NegateL, CmpR, RHSCC);
4386 if (NegateAfterAll)
4387 OutCC = AArch64CC::getInvertedCondCode(OutCC);
4388 return CmpL;
4389}
4390
4391/// Emit expression as a conjunction (a series of CCMP/CFCMP ops).
4392/// In some cases this is even possible with OR operations in the expression.
4393/// See \ref AArch64CCMP.
4394/// \see emitConjunctionRec().
4396 AArch64CC::CondCode &OutCC) {
4397 bool DummyCanNegate;
4398 bool DummyMustBeFirst;
4399 bool DummyPreferFirst;
4400 if (!canEmitConjunction(DAG, Val, DummyCanNegate, DummyMustBeFirst,
4401 DummyPreferFirst, false))
4402 return SDValue();
4403
4404 return emitConjunctionRec(DAG, Val, OutCC, false, SDValue(), AArch64CC::AL);
4405}
4406
4407/// @}
4408
4410 if (V.getOpcode() == ISD::SIGN_EXTEND_INREG)
4411 return true;
4412
4413 if (V.getOpcode() == ISD::AND)
4414 if (ConstantSDNode *MaskCst = dyn_cast<ConstantSDNode>(V.getOperand(1))) {
4415 uint64_t Mask = MaskCst->getZExtValue();
4416 return (Mask == 0xFF || Mask == 0xFFFF || Mask == 0xFFFFFFFF);
4417 }
4418 return false;
4419}
4420
4421/// Returns how profitable it is to fold a comparison's operand's shift and/or
4422/// extension operations.
4423static unsigned getCmpOperandFoldingProfit(SDValue Op, bool AllowExtend) {
4424 if (!Op.hasOneUse())
4425 return 0;
4426
4427 if (AllowExtend && isSupportedExtend(Op))
4428 return 1;
4429
4430 unsigned Opc = Op.getOpcode();
4431 if (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA)
4432 if (ConstantSDNode *ShiftCst = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
4433 uint64_t Shift = ShiftCst->getZExtValue();
4434 if (AllowExtend && isSupportedExtend(Op.getOperand(0)))
4435 return (Shift <= 4) ? 2 : 1;
4436 EVT VT = Op.getValueType();
4437 if ((VT == MVT::i32 && Shift <= 31) || (VT == MVT::i64 && Shift <= 63))
4438 return 1;
4439 }
4440
4441 return 0;
4442}
4443
4445 SelectionDAG &DAG) {
4446 if (isCMN(Op, CC, DAG))
4447 return getCmpOperandFoldingProfit(Op.getOperand(1), true) + 1;
4448 return getCmpOperandFoldingProfit(Op, true);
4449}
4450
4451// emitComparison() converts comparison with one or negative one to comparison
4452// with 0. Note that this only works for signed comparisons because of how ANDS
4453// works.
4455 ISD::CondCode &CC) {
4456 // Only works for ANDS and AND.
4457 if (LHS.getOpcode() != ISD::AND && LHS.getOpcode() != AArch64ISD::ANDS)
4458 return false;
4459
4460 if (C.isOne() && (CC == ISD::SETLT || CC == ISD::SETGE)) {
4461 CC = (CC == ISD::SETLT) ? ISD::SETLE : ISD::SETGT;
4462 return true;
4463 }
4464
4465 if (C.isAllOnes() && (CC == ISD::SETLE || CC == ISD::SETGT)) {
4466 CC = (CC == ISD::SETLE) ? ISD::SETLT : ISD::SETGE;
4467 return true;
4468 }
4469
4470 return false;
4471}
4472
4474 SDValue &AArch64cc, SelectionDAG &DAG,
4475 const SDLoc &DL) {
4476 if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS.getNode())) {
4477 EVT VT = RHS.getValueType();
4478 APInt C = RHSC->getAPIntValue();
4479 // shouldBeAdjustedToZero is a special case to better fold with
4480 // emitComparison().
4481 if (shouldBeAdjustedToZero(LHS, C, CC)) {
4482 // Adjust the constant to zero.
4483 // CC has already been adjusted.
4484 RHS = DAG.getConstant(0, DL, VT);
4485 } else if (!AArch64_AM::isLegalCmpImmed(C)) {
4486 unsigned NumImmForC = numberOfInstrToLoadImm(C);
4487 // Constant does not fit, try adjusting it by one?
4488 switch (CC) {
4489 default:
4490 break;
4491 case ISD::SETLT:
4492 case ISD::SETGE:
4493 if (!C.isMinSignedValue()) {
4494 APInt CMinusOne = C - 1;
4495 if (AArch64_AM::isLegalCmpImmed(CMinusOne) ||
4496 (NumImmForC > numberOfInstrToLoadImm(CMinusOne))) {
4497 CC = (CC == ISD::SETLT) ? ISD::SETLE : ISD::SETGT;
4498 RHS = DAG.getConstant(CMinusOne, DL, VT);
4499 }
4500 }
4501 break;
4502 case ISD::SETULT:
4503 case ISD::SETUGE: {
4504 // C is not 0 because it is a legal immediate.
4505 assert(!C.isZero() && "C should not be zero here");
4506 APInt CMinusOne = C - 1;
4507 if (AArch64_AM::isLegalCmpImmed(CMinusOne) ||
4508 (NumImmForC > numberOfInstrToLoadImm(CMinusOne))) {
4509 CC = (CC == ISD::SETULT) ? ISD::SETULE : ISD::SETUGT;
4510 RHS = DAG.getConstant(CMinusOne, DL, VT);
4511 }
4512 break;
4513 }
4514 case ISD::SETLE:
4515 case ISD::SETGT:
4516 if (!C.isMaxSignedValue()) {
4517 APInt CPlusOne = C + 1;
4518 if (AArch64_AM::isLegalCmpImmed(CPlusOne) ||
4519 (NumImmForC > numberOfInstrToLoadImm(CPlusOne))) {
4520 CC = (CC == ISD::SETLE) ? ISD::SETLT : ISD::SETGE;
4521 RHS = DAG.getConstant(CPlusOne, DL, VT);
4522 }
4523 }
4524 break;
4525 case ISD::SETULE:
4526 case ISD::SETUGT:
4527 if (!C.isAllOnes()) {
4528 APInt CPlusOne = C + 1;
4529 if (AArch64_AM::isLegalCmpImmed(CPlusOne) ||
4530 (NumImmForC > numberOfInstrToLoadImm(CPlusOne))) {
4531 CC = (CC == ISD::SETULE) ? ISD::SETULT : ISD::SETUGE;
4532 RHS = DAG.getConstant(CPlusOne, DL, VT);
4533 }
4534 }
4535 break;
4536 }
4537 } else if (C.isZero() && getCmpOperandFoldingProfit(LHS, false) != 0) {
4538 // Fold into CMP WZR, reg, shift #amount
4539 std::swap(LHS, RHS);
4541 }
4542 }
4543
4544 // Comparisons are canonicalized so that the RHS operand is simpler than the
4545 // LHS one, the extreme case being when RHS is an immediate. However, AArch64
4546 // can fold some shift+extend operations on the RHS operand, so swap the
4547 // operands if that can be done.
4548 //
4549 // For example:
4550 // lsl w13, w11, #1
4551 // cmp w13, w12
4552 // can be turned into:
4553 // cmp w12, w11, lsl #1
4554 if (!isa<ConstantSDNode>(RHS) ||
4555 !AArch64_AM::isLegalCmpImmed(RHS->getAsAPIntVal())) {
4556 if (getCmpOrCmnOperandFoldingProfit(LHS, CC, DAG) >
4558 std::swap(LHS, RHS);
4560 }
4561 }
4562
4563 SDValue Cmp;
4565 if (isIntEqualitySetCC(CC) && isa<ConstantSDNode>(RHS)) {
4567
4568 // The imm operand of ADDS is an unsigned immediate, in the range 0 to 4095.
4569 // For the i8 operand, the largest immediate is 255, so this can be easily
4570 // encoded in the compare instruction. For the i16 operand, however, the
4571 // largest immediate cannot be encoded in the compare.
4572 // Therefore, use a sign extending load and cmn to avoid materializing the
4573 // -1 constant. For example,
4574 // movz w1, #65535
4575 // ldrh w0, [x0, #0]
4576 // cmp w0, w1
4577 // >
4578 // ldrsh w0, [x0, #0]
4579 // cmn w0, #1
4580 // Fundamental, we're relying on the property that (zext LHS) == (zext RHS)
4581 // if and only if (sext LHS) == (sext RHS). The checks are in place to
4582 // ensure both the LHS and RHS are truly zero extended and to make sure the
4583 // transformation is profitable.
4584 if ((RHSC->getZExtValue() >> 16 == 0) && isa<LoadSDNode>(LHS) &&
4585 cast<LoadSDNode>(LHS)->getExtensionType() == ISD::ZEXTLOAD &&
4586 cast<LoadSDNode>(LHS)->getMemoryVT() == MVT::i16 &&
4587 LHS->hasNUsesOfValue(1, 0)) {
4588 int16_t ValueofRHS = RHS->getAsZExtVal();
4589 if (ValueofRHS < 0 && AArch64_AM::isLegalArithImmed(-ValueofRHS)) {
4590 SDValue SExt =
4591 DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, LHS.getValueType(), LHS,
4592 DAG.getValueType(MVT::i16));
4593 Cmp = emitComparison(
4594 SExt, DAG.getSignedConstant(ValueofRHS, DL, RHS.getValueType()), CC,
4595 DL, DAG);
4597 }
4598 }
4599
4600 if (!Cmp && (RHSC->isZero() || RHSC->isOne())) {
4601 if ((Cmp = emitConjunction(DAG, LHS, AArch64CC))) {
4602 if ((CC == ISD::SETNE) ^ RHSC->isZero())
4604 }
4605 }
4606 }
4607
4608 if (!Cmp) {
4609 Cmp = emitComparison(LHS, RHS, CC, DL, DAG);
4611 }
4612 AArch64cc = getCondCode(DAG, AArch64CC);
4613 return Cmp;
4614}
4615
4616static std::pair<SDValue, SDValue>
4618 assert((Op.getValueType() == MVT::i32 || Op.getValueType() == MVT::i64) &&
4619 "Unsupported value type");
4620 SDValue Value, Overflow;
4621 SDLoc DL(Op);
4622 SDValue LHS = Op.getOperand(0);
4623 SDValue RHS = Op.getOperand(1);
4624 unsigned Opc = 0;
4625 switch (Op.getOpcode()) {
4626 default:
4627 llvm_unreachable("Unknown overflow instruction!");
4628 case ISD::SADDO:
4629 Opc = AArch64ISD::ADDS;
4630 CC = AArch64CC::VS;
4631 break;
4632 case ISD::UADDO:
4633 Opc = AArch64ISD::ADDS;
4634 CC = AArch64CC::HS;
4635 break;
4636 case ISD::SSUBO:
4637 Opc = AArch64ISD::SUBS;
4638 CC = AArch64CC::VS;
4639 break;
4640 case ISD::USUBO:
4641 Opc = AArch64ISD::SUBS;
4642 CC = AArch64CC::LO;
4643 break;
4644 // Multiply needs a little bit extra work.
4645 case ISD::SMULO:
4646 case ISD::UMULO: {
4647 CC = AArch64CC::NE;
4648 bool IsSigned = Op.getOpcode() == ISD::SMULO;
4649 if (Op.getValueType() == MVT::i32) {
4650 // Extend to 64-bits, then perform a 64-bit multiply.
4651 unsigned ExtendOpc = IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
4652 LHS = DAG.getNode(ExtendOpc, DL, MVT::i64, LHS);
4653 RHS = DAG.getNode(ExtendOpc, DL, MVT::i64, RHS);
4654 SDValue Mul = DAG.getNode(ISD::MUL, DL, MVT::i64, LHS, RHS);
4655 Value = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Mul);
4656
4657 // Check that the result fits into a 32-bit integer.
4658 SDVTList VTs = DAG.getVTList(MVT::i64, FlagsVT);
4659 if (IsSigned) {
4660 // cmp xreg, wreg, sxtw
4661 SDValue SExtMul = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, Value);
4662 Overflow =
4663 DAG.getNode(AArch64ISD::SUBS, DL, VTs, Mul, SExtMul).getValue(1);
4664 } else {
4665 // tst xreg, #0xffffffff00000000
4666 SDValue UpperBits = DAG.getConstant(0xFFFFFFFF00000000, DL, MVT::i64);
4667 Overflow =
4668 DAG.getNode(AArch64ISD::ANDS, DL, VTs, Mul, UpperBits).getValue(1);
4669 }
4670 break;
4671 }
4672 assert(Op.getValueType() == MVT::i64 && "Expected an i64 value type");
4673 // For the 64 bit multiply
4674 Value = DAG.getNode(ISD::MUL, DL, MVT::i64, LHS, RHS);
4675 if (IsSigned) {
4676 SDValue UpperBits = DAG.getNode(ISD::MULHS, DL, MVT::i64, LHS, RHS);
4677 SDValue LowerBits = DAG.getNode(ISD::SRA, DL, MVT::i64, Value,
4678 DAG.getConstant(63, DL, MVT::i64));
4679 // It is important that LowerBits is last, otherwise the arithmetic
4680 // shift will not be folded into the compare (SUBS).
4681 SDVTList VTs = DAG.getVTList(MVT::i64, FlagsVT);
4682 Overflow = DAG.getNode(AArch64ISD::SUBS, DL, VTs, UpperBits, LowerBits)
4683 .getValue(1);
4684 } else {
4685 SDValue UpperBits = DAG.getNode(ISD::MULHU, DL, MVT::i64, LHS, RHS);
4686 SDVTList VTs = DAG.getVTList(MVT::i64, FlagsVT);
4687 Overflow =
4688 DAG.getNode(AArch64ISD::SUBS, DL, VTs,
4689 DAG.getConstant(0, DL, MVT::i64),
4690 UpperBits).getValue(1);
4691 }
4692 break;
4693 }
4694 } // switch (...)
4695
4696 if (Opc) {
4697 SDVTList VTs = DAG.getVTList(Op->getValueType(0), FlagsVT);
4698
4699 // Emit the AArch64 operation with overflow check.
4700 Value = DAG.getNode(Opc, DL, VTs, LHS, RHS);
4701 Overflow = Value.getValue(1);
4702 }
4703 return std::make_pair(Value, Overflow);
4704}
4705
4706SDValue AArch64TargetLowering::LowerXOR(SDValue Op, SelectionDAG &DAG) const {
4707 if (useSVEForFixedLengthVectorVT(Op.getValueType(),
4708 !Subtarget->isNeonAvailable()))
4709 return LowerToScalableOp(Op, DAG);
4710
4711 SDValue Sel = Op.getOperand(0);
4712 SDValue Other = Op.getOperand(1);
4713 SDLoc DL(Sel);
4714
4715 // If the operand is an overflow checking operation, invert the condition
4716 // code and kill the Not operation. I.e., transform:
4717 // (xor (overflow_op_bool, 1))
4718 // -->
4719 // (csel 1, 0, invert(cc), overflow_op_bool)
4720 // ... which later gets transformed to just a cset instruction with an
4721 // inverted condition code, rather than a cset + eor sequence.
4723 // Only lower legal XALUO ops.
4725 return SDValue();
4726
4727 SDValue TVal = DAG.getConstant(1, DL, MVT::i32);
4728 SDValue FVal = DAG.getConstant(0, DL, MVT::i32);
4730 SDValue Value, Overflow;
4731 std::tie(Value, Overflow) = getAArch64XALUOOp(CC, Sel.getValue(0), DAG);
4732 SDValue CCVal = getCondCode(DAG, getInvertedCondCode(CC));
4733 return DAG.getNode(AArch64ISD::CSEL, DL, Op.getValueType(), TVal, FVal,
4734 CCVal, Overflow);
4735 }
4736 // If neither operand is a SELECT_CC, give up.
4737 if (Sel.getOpcode() != ISD::SELECT_CC)
4738 std::swap(Sel, Other);
4739 if (Sel.getOpcode() != ISD::SELECT_CC)
4740 return Op;
4741
4742 // The folding we want to perform is:
4743 // (xor x, (select_cc a, b, cc, 0, -1) )
4744 // -->
4745 // (csel x, (xor x, -1), cc ...)
4746 //
4747 // The latter will get matched to a CSINV instruction.
4748
4749 ISD::CondCode CC = cast<CondCodeSDNode>(Sel.getOperand(4))->get();
4750 SDValue LHS = Sel.getOperand(0);
4751 SDValue RHS = Sel.getOperand(1);
4752 SDValue TVal = Sel.getOperand(2);
4753 SDValue FVal = Sel.getOperand(3);
4754
4755 // FIXME: This could be generalized to non-integer comparisons.
4756 if (LHS.getValueType() != MVT::i32 && LHS.getValueType() != MVT::i64)
4757 return Op;
4758
4759 ConstantSDNode *CFVal = dyn_cast<ConstantSDNode>(FVal);
4760 ConstantSDNode *CTVal = dyn_cast<ConstantSDNode>(TVal);
4761
4762 // The values aren't constants, this isn't the pattern we're looking for.
4763 if (!CFVal || !CTVal)
4764 return Op;
4765
4766 // We can commute the SELECT_CC by inverting the condition. This
4767 // might be needed to make this fit into a CSINV pattern.
4768 if (CTVal->isAllOnes() && CFVal->isZero()) {
4769 std::swap(TVal, FVal);
4770 std::swap(CTVal, CFVal);
4771 CC = ISD::getSetCCInverse(CC, LHS.getValueType());
4772 }
4773
4774 // If the constants line up, perform the transform!
4775 if (CTVal->isZero() && CFVal->isAllOnes()) {
4776 SDValue CCVal;
4777 SDValue Cmp = getAArch64Cmp(LHS, RHS, CC, CCVal, DAG, DL);
4778
4779 FVal = Other;
4780 TVal = DAG.getNode(ISD::XOR, DL, Other.getValueType(), Other,
4781 DAG.getAllOnesConstant(DL, Other.getValueType()));
4782
4783 return DAG.getNode(AArch64ISD::CSEL, DL, Sel.getValueType(), FVal, TVal,
4784 CCVal, Cmp);
4785 }
4786
4787 return Op;
4788}
4789
4790// If Invert is false, sets 'C' bit of NZCV to 0 if value is 0, else sets 'C'
4791// bit to 1. If Invert is true, sets 'C' bit of NZCV to 1 if value is 0, else
4792// sets 'C' bit to 0.
4794 SDLoc DL(Value);
4795 EVT VT = Value.getValueType();
4796 SDValue Op0 = Invert ? DAG.getConstant(0, DL, VT) : Value;
4797 SDValue Op1 = Invert ? Value : DAG.getConstant(1, DL, VT);
4798 SDValue Cmp =
4799 DAG.getNode(AArch64ISD::SUBS, DL, DAG.getVTList(VT, FlagsVT), Op0, Op1);
4800 return Cmp.getValue(1);
4801}
4802
4803// If Invert is false, value is 1 if 'C' bit of NZCV is 1, else 0.
4804// If Invert is true, value is 0 if 'C' bit of NZCV is 1, else 1.
4806 bool Invert) {
4807 assert(Glue.getResNo() == 1);
4808 SDLoc DL(Glue);
4809 SDValue Zero = DAG.getConstant(0, DL, VT);
4810 SDValue One = DAG.getConstant(1, DL, VT);
4812 SDValue CC = getCondCode(DAG, Cond);
4813 return DAG.getNode(AArch64ISD::CSEL, DL, VT, One, Zero, CC, Glue);
4814}
4815
4816// Value is 1 if 'V' bit of NZCV is 1, else 0
4818 assert(Glue.getResNo() == 1);
4819 SDLoc DL(Glue);
4820 SDValue Zero = DAG.getConstant(0, DL, VT);
4821 SDValue One = DAG.getConstant(1, DL, VT);
4823 return DAG.getNode(AArch64ISD::CSEL, DL, VT, One, Zero, CC, Glue);
4824}
4825
4826// This lowering is inefficient, but it will get cleaned up by
4827// `foldOverflowCheck`
4829 unsigned Opcode, bool IsSigned) {
4830 EVT VT0 = Op.getValue(0).getValueType();
4831 EVT VT1 = Op.getValue(1).getValueType();
4832
4833 if (VT0 != MVT::i32 && VT0 != MVT::i64)
4834 return SDValue();
4835
4836 bool InvertCarry = Opcode == AArch64ISD::SBCS;
4837 SDValue OpLHS = Op.getOperand(0);
4838 SDValue OpRHS = Op.getOperand(1);
4839 SDValue OpCarryIn = valueToCarryFlag(Op.getOperand(2), DAG, InvertCarry);
4840
4841 SDLoc DL(Op);
4842
4843 SDValue Sum = DAG.getNode(Opcode, DL, DAG.getVTList(VT0, FlagsVT), OpLHS,
4844 OpRHS, OpCarryIn);
4845
4846 SDValue OutFlag =
4847 IsSigned ? overflowFlagToValue(Sum.getValue(1), VT1, DAG)
4848 : carryFlagToValue(Sum.getValue(1), VT1, DAG, InvertCarry);
4849
4850 return DAG.getMergeValues({Sum, OutFlag}, DL);
4851}
4852
4853static SDValue lowerIntNeonIntrinsic(SDValue Op, unsigned Opcode,
4854 SelectionDAG &DAG,
4855 bool LastOperandIsImm = false) {
4856 if (Op.getValueType().isVector())
4857 return SDValue();
4858
4859 SDLoc DL(Op);
4861 const unsigned NumOperands = Op.getNumOperands();
4862 auto getFloatVT = [](EVT VT) {
4863 assert((VT == MVT::i32 || VT == MVT::i64) && "Unexpected VT");
4864 return VT == MVT::i32 ? MVT::f32 : MVT::f64;
4865 };
4866 auto bitcastToFloat = [&](SDValue Val) {
4867 return DAG.getBitcast(getFloatVT(Val.getValueType()), Val);
4868 };
4869
4870 // Skip first operand as it is intrinsic ID.
4871 for (unsigned I = 1; I < NumOperands; ++I) {
4872 SDValue Val = Op.getOperand(I);
4873 const bool KeepInt = LastOperandIsImm && (I == NumOperands - 1);
4874 NewOps.push_back(KeepInt ? Val : bitcastToFloat(Val));
4875 }
4876 EVT OrigVT = Op.getValueType();
4877 SDValue OpNode = DAG.getNode(Opcode, DL, getFloatVT(OrigVT), NewOps);
4878 return DAG.getBitcast(OrigVT, OpNode);
4879}
4880
4882 // Let legalize expand this if it isn't a legal type yet.
4883 if (!DAG.getTargetLoweringInfo().isTypeLegal(Op.getValueType()))
4884 return SDValue();
4885
4886 SDLoc DL(Op);
4888 // The actual operation that sets the overflow or carry flag.
4889 SDValue Value, Overflow;
4890 std::tie(Value, Overflow) = getAArch64XALUOOp(CC, Op, DAG);
4891
4892 // We use 0 and 1 as false and true values.
4893 SDValue TVal = DAG.getConstant(1, DL, MVT::i32);
4894 SDValue FVal = DAG.getConstant(0, DL, MVT::i32);
4895
4896 // We use an inverted condition, because the conditional select is inverted
4897 // too. This will allow it to be selected to a single instruction:
4898 // CSINC Wd, WZR, WZR, invert(cond).
4899 SDValue CCVal = getCondCode(DAG, getInvertedCondCode(CC));
4900 Overflow =
4901 DAG.getNode(AArch64ISD::CSEL, DL, MVT::i32, FVal, TVal, CCVal, Overflow);
4902
4903 return DAG.getMergeValues({Value, Overflow}, DL);
4904}
4905
4906// Prefetch operands are:
4907// 1: Address to prefetch
4908// 2: bool isWrite
4909// 3: int locality (0 = no locality ... 3 = extreme locality)
4910// 4: bool isDataCache
4912 SDLoc DL(Op);
4913 unsigned IsWrite = Op.getConstantOperandVal(2);
4914 unsigned Locality = Op.getConstantOperandVal(3);
4915 unsigned IsData = Op.getConstantOperandVal(4);
4916
4917 bool IsStream = !Locality;
4918 // When the locality number is set
4919 if (Locality) {
4920 // The front-end should have filtered out the out-of-range values
4921 assert(Locality <= 3 && "Prefetch locality out-of-range");
4922 // The locality degree is the opposite of the cache speed.
4923 // Put the number the other way around.
4924 // The encoding starts at 0 for level 1
4925 Locality = 3 - Locality;
4926 }
4927
4928 // built the mask value encoding the expected behavior.
4929 unsigned PrfOp = (IsWrite << 4) | // Load/Store bit
4930 (!IsData << 3) | // IsDataCache bit
4931 (Locality << 1) | // Cache level bits
4932 (unsigned)IsStream; // Stream bit
4933 return DAG.getNode(AArch64ISD::PREFETCH, DL, MVT::Other, Op.getOperand(0),
4934 DAG.getTargetConstant(PrfOp, DL, MVT::i32),
4935 Op.getOperand(1));
4936}
4937
4938// Converts SETCC (AND X Y) Z ULT -> SETCC (AND X (Y & ~(Z - 1)) 0 EQ when Y is
4939// a power of 2. This is then lowered to ANDS X (Y & ~(Z - 1)) instead of SUBS
4940// (AND X Y) Z which produces a better opt with EmitComparison
4942 SelectionDAG &DAG, const SDLoc DL) {
4943 if (CC == ISD::SETULT && LHS.getOpcode() == ISD::AND && LHS->hasOneUse()) {
4944 ConstantSDNode *LHSConstOp = dyn_cast<ConstantSDNode>(LHS.getOperand(1));
4946 if (LHSConstOp && RHSConst) {
4947 uint64_t LHSConstValue = LHSConstOp->getZExtValue();
4948 uint64_t RHSConstant = RHSConst->getZExtValue();
4949 if (isPowerOf2_64(RHSConstant)) {
4950 uint64_t NewMaskValue = LHSConstValue & ~(RHSConstant - 1);
4951 LHS =
4952 DAG.getNode(ISD::AND, DL, LHS.getValueType(), LHS.getOperand(0),
4953 DAG.getConstant(NewMaskValue, DL, LHS.getValueType()));
4954 RHS = DAG.getConstant(0, DL, RHS.getValueType());
4955 CC = ISD::SETEQ;
4956 }
4957 }
4958 }
4959}
4960
4961SDValue AArch64TargetLowering::LowerFP_EXTEND(SDValue Op,
4962 SelectionDAG &DAG) const {
4963 EVT VT = Op.getValueType();
4964 if (VT.isScalableVector()) {
4965 SDValue SrcVal = Op.getOperand(0);
4966
4967 if (VT == MVT::nxv2f64 && SrcVal.getValueType() == MVT::nxv2bf16) {
4968 // Break conversion in two with the first part converting to f32 and the
4969 // second using native f32->VT instructions.
4970 SDLoc DL(Op);
4971 return DAG.getNode(ISD::FP_EXTEND, DL, VT,
4972 DAG.getNode(ISD::FP_EXTEND, DL, MVT::nxv2f32, SrcVal));
4973 }
4974
4975 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FP_EXTEND_MERGE_PASSTHRU);
4976 }
4977
4978 if (useSVEForFixedLengthVectorVT(VT, !Subtarget->isNeonAvailable()))
4979 return LowerFixedLengthFPExtendToSVE(Op, DAG);
4980
4981 bool IsStrict = Op->isStrictFPOpcode();
4982 SDValue Op0 = Op.getOperand(IsStrict ? 1 : 0);
4983 EVT Op0VT = Op0.getValueType();
4984 if (VT == MVT::f64) {
4985 // FP16->FP32 extends are legal for v32 and v4f32.
4986 if (Op0VT == MVT::f32 || Op0VT == MVT::f16)
4987 return Op;
4988 // Split bf16->f64 extends into two fpextends.
4989 if (Op0VT == MVT::bf16 && IsStrict) {
4990 SDValue Ext1 =
4991 DAG.getNode(ISD::STRICT_FP_EXTEND, SDLoc(Op), {MVT::f32, MVT::Other},
4992 {Op.getOperand(0), Op0});
4993 return DAG.getNode(ISD::STRICT_FP_EXTEND, SDLoc(Op), {VT, MVT::Other},
4994 {Ext1.getValue(1), Ext1});
4995 }
4996 if (Op0VT == MVT::bf16)
4997 return DAG.getNode(ISD::FP_EXTEND, SDLoc(Op), VT,
4998 DAG.getNode(ISD::FP_EXTEND, SDLoc(Op), MVT::f32, Op0));
4999 return SDValue();
5000 }
5001
5002 assert(Op.getValueType() == MVT::f128 && "Unexpected lowering");
5003 return SDValue();
5004}
5005
5006SDValue AArch64TargetLowering::LowerFP_ROUND(SDValue Op,
5007 SelectionDAG &DAG) const {
5008 EVT VT = Op.getValueType();
5009 bool IsStrict = Op->isStrictFPOpcode();
5010 SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
5011 EVT SrcVT = SrcVal.getValueType();
5012 bool Trunc = Op.getConstantOperandVal(IsStrict ? 2 : 1) == 1;
5013 SDNodeFlags Flags = Op->getFlags();
5014
5015 if (VT.isScalableVector()) {
5016 // Let common code split the operation.
5017 if (SrcVT == MVT::nxv8f32)
5018 return Op;
5019
5020 if (VT.getScalarType() != MVT::bf16)
5021 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FP_ROUND_MERGE_PASSTHRU);
5022
5023 SDLoc DL(Op);
5024 constexpr EVT I32 = MVT::nxv4i32;
5025 auto ImmV = [&](int I) -> SDValue { return DAG.getConstant(I, DL, I32); };
5026
5027 SDValue NaN;
5028 SDValue Narrow;
5029
5030 if (SrcVT == MVT::nxv2f32 || SrcVT == MVT::nxv4f32) {
5031 if (Subtarget->hasBF16())
5032 return LowerToPredicatedOp(Op, DAG,
5033 AArch64ISD::FP_ROUND_MERGE_PASSTHRU);
5034
5035 Narrow = getSVESafeBitCast(I32, SrcVal, DAG);
5036
5037 // Set the quiet bit.
5038 if (!DAG.isKnownNeverSNaN(SrcVal) && !Flags.hasNoNaNs())
5039 NaN = DAG.getNode(ISD::OR, DL, I32, Narrow, ImmV(0x400000));
5040 } else if (SrcVT == MVT::nxv2f64 &&
5041 (Subtarget->hasSVE2() || Subtarget->isStreamingSVEAvailable())) {
5042 // Round to float without introducing rounding errors and try again.
5043 SDValue Pg = getPredicateForVector(DAG, DL, MVT::nxv2f32);
5044 Narrow = DAG.getNode(AArch64ISD::FCVTX_MERGE_PASSTHRU, DL, MVT::nxv2f32,
5045 Pg, SrcVal, DAG.getPOISON(MVT::nxv2f32));
5046
5048 if (IsStrict)
5049 NewOps.push_back(Op.getOperand(0));
5050 NewOps.push_back(Narrow);
5051 NewOps.push_back(Op.getOperand(IsStrict ? 2 : 1));
5052 return DAG.getNode(Op.getOpcode(), DL, VT, NewOps, Op->getFlags());
5053 } else
5054 return SDValue();
5055
5056 if (!Trunc) {
5057 SDValue Lsb = DAG.getNode(ISD::SRL, DL, I32, Narrow, ImmV(16));
5058 Lsb = DAG.getNode(ISD::AND, DL, I32, Lsb, ImmV(1));
5059 SDValue RoundingBias = DAG.getNode(ISD::ADD, DL, I32, Lsb, ImmV(0x7fff));
5060 Narrow = DAG.getNode(ISD::ADD, DL, I32, Narrow, RoundingBias);
5061 }
5062
5063 // Don't round if we had a NaN, we don't want to turn 0x7fffffff into
5064 // 0x80000000.
5065 if (NaN) {
5066 EVT I1 = I32.changeElementType(*DAG.getContext(), MVT::i1);
5067 EVT CondVT = VT.changeElementType(*DAG.getContext(), MVT::i1);
5068 SDValue IsNaN = DAG.getSetCC(DL, CondVT, SrcVal, SrcVal, ISD::SETUO);
5069 IsNaN = DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, I1, IsNaN);
5070 Narrow = DAG.getSelect(DL, I32, IsNaN, NaN, Narrow);
5071 }
5072
5073 // Now that we have rounded, shift the bits into position.
5074 Narrow = DAG.getNode(ISD::SRL, DL, I32, Narrow, ImmV(16));
5075 return getSVESafeBitCast(VT, Narrow, DAG);
5076 }
5077
5078 if (useSVEForFixedLengthVectorVT(SrcVT, !Subtarget->isNeonAvailable()))
5079 return LowerFixedLengthFPRoundToSVE(Op, DAG);
5080
5081 // Expand cases where the result type is BF16 but we don't have hardware
5082 // instructions to lower it.
5083 if (VT.getScalarType() == MVT::bf16 &&
5084 !((Subtarget->hasNEON() || Subtarget->hasSME()) &&
5085 Subtarget->hasBF16())) {
5086 SDLoc DL(Op);
5087 SDValue Narrow = SrcVal;
5088 SDValue NaN;
5089 EVT I32 = SrcVT.changeElementType(*DAG.getContext(), MVT::i32);
5090 EVT F32 = SrcVT.changeElementType(*DAG.getContext(), MVT::f32);
5091 if (SrcVT.getScalarType() == MVT::f32) {
5092 bool NeverSNaN = DAG.isKnownNeverSNaN(Narrow);
5093 Narrow = DAG.getNode(ISD::BITCAST, DL, I32, Narrow);
5094 if (!NeverSNaN) {
5095 // Set the quiet bit.
5096 NaN = DAG.getNode(ISD::OR, DL, I32, Narrow,
5097 DAG.getConstant(0x400000, DL, I32));
5098 }
5099 } else if (SrcVT.getScalarType() == MVT::f64) {
5100 Narrow = DAG.getNode(AArch64ISD::FCVTXN, DL, F32, Narrow);
5101 Narrow = DAG.getNode(ISD::BITCAST, DL, I32, Narrow);
5102 } else {
5103 return SDValue();
5104 }
5105 if (!Trunc) {
5106 SDValue One = DAG.getConstant(1, DL, I32);
5107 SDValue Lsb = DAG.getNode(ISD::SRL, DL, I32, Narrow,
5108 DAG.getShiftAmountConstant(16, I32, DL));
5109 Lsb = DAG.getNode(ISD::AND, DL, I32, Lsb, One);
5110 SDValue RoundingBias =
5111 DAG.getNode(ISD::ADD, DL, I32, DAG.getConstant(0x7fff, DL, I32), Lsb);
5112 Narrow = DAG.getNode(ISD::ADD, DL, I32, Narrow, RoundingBias);
5113 }
5114
5115 // Don't round if we had a NaN, we don't want to turn 0x7fffffff into
5116 // 0x80000000.
5117 if (NaN) {
5118 SDValue IsNaN = DAG.getSetCC(
5119 DL, getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), SrcVT),
5120 SrcVal, SrcVal, ISD::SETUO);
5121 Narrow = DAG.getSelect(DL, I32, IsNaN, NaN, Narrow);
5122 }
5123
5124 // Now that we have rounded, shift the bits into position.
5125 Narrow = DAG.getNode(ISD::SRL, DL, I32, Narrow,
5126 DAG.getShiftAmountConstant(16, I32, DL));
5127 if (VT.isVector()) {
5128 EVT I16 = I32.changeVectorElementType(*DAG.getContext(), MVT::i16);
5129 Narrow = DAG.getNode(ISD::TRUNCATE, DL, I16, Narrow);
5130 return DAG.getNode(ISD::BITCAST, DL, VT, Narrow);
5131 }
5132 Narrow = DAG.getNode(ISD::BITCAST, DL, F32, Narrow);
5133 SDValue Result = DAG.getTargetExtractSubreg(AArch64::hsub, DL, VT, Narrow);
5134 return IsStrict ? DAG.getMergeValues({Result, Op.getOperand(0)}, DL)
5135 : Result;
5136 }
5137
5138 if (SrcVT != MVT::f128) {
5139 // Expand cases where the input is a vector bigger than NEON.
5141 return SDValue();
5142
5143 // It's legal except when f128 is involved
5144 return Op;
5145 }
5146
5147 return SDValue();
5148}
5149
5150SDValue AArch64TargetLowering::LowerVectorFP_TO_INT(SDValue Op,
5151 SelectionDAG &DAG) const {
5152 // Warning: We maintain cost tables in AArch64TargetTransformInfo.cpp.
5153 // Any additional optimization in this function should be recorded
5154 // in the cost tables.
5155 bool IsStrict = Op->isStrictFPOpcode();
5156 EVT InVT = Op.getOperand(IsStrict ? 1 : 0).getValueType();
5157 EVT VT = Op.getValueType();
5158
5159 assert(!(IsStrict && VT.isScalableVector()) &&
5160 "Unimplemented SVE support for STRICT_FP_to_INT!");
5161
5162 // f16 conversions are promoted to f32 when full fp16 is not supported.
5163 if ((InVT.getVectorElementType() == MVT::f16 && !Subtarget->hasFullFP16()) ||
5164 InVT.getVectorElementType() == MVT::bf16) {
5165 EVT NewVT = VT.changeElementType(*DAG.getContext(), MVT::f32);
5166 SDLoc DL(Op);
5167 if (IsStrict) {
5168 SDValue Ext = DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {NewVT, MVT::Other},
5169 {Op.getOperand(0), Op.getOperand(1)});
5170 return DAG.getNode(Op.getOpcode(), DL, {VT, MVT::Other},
5171 {Ext.getValue(1), Ext.getValue(0)});
5172 }
5173 return DAG.getNode(
5174 Op.getOpcode(), DL, Op.getValueType(),
5175 DAG.getNode(ISD::FP_EXTEND, DL, NewVT, Op.getOperand(0)));
5176 }
5177
5178 if (SDValue Res = LowerFPToIntToSVE(Op, DAG))
5179 return Res;
5180
5181 uint64_t VTSize = VT.getFixedSizeInBits();
5182 uint64_t InVTSize = InVT.getFixedSizeInBits();
5183 if (VTSize < InVTSize) {
5184 SDLoc DL(Op);
5185 if (IsStrict) {
5187 SDValue Cv = DAG.getNode(Op.getOpcode(), DL, {InVT, MVT::Other},
5188 {Op.getOperand(0), Op.getOperand(1)});
5189 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, VT, Cv);
5190 return DAG.getMergeValues({Trunc, Cv.getValue(1)}, DL);
5191 }
5192 SDValue Cv =
5193 DAG.getNode(Op.getOpcode(), DL, InVT.changeVectorElementTypeToInteger(),
5194 Op.getOperand(0));
5195 return DAG.getNode(ISD::TRUNCATE, DL, VT, Cv);
5196 }
5197
5198 if (VTSize > InVTSize) {
5199 SDLoc DL(Op);
5200 MVT ExtVT =
5203 if (IsStrict) {
5204 SDValue Ext = DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {ExtVT, MVT::Other},
5205 {Op.getOperand(0), Op.getOperand(1)});
5206 return DAG.getNode(Op.getOpcode(), DL, {VT, MVT::Other},
5207 {Ext.getValue(1), Ext.getValue(0)});
5208 }
5209 SDValue Ext = DAG.getNode(ISD::FP_EXTEND, DL, ExtVT, Op.getOperand(0));
5210 return DAG.getNode(Op.getOpcode(), DL, VT, Ext);
5211 }
5212
5213 // Use a scalar operation for conversions between single-element vectors of
5214 // the same size.
5215 if (InVT.getVectorNumElements() == 1) {
5216 SDLoc DL(Op);
5217 SDValue Extract = DAG.getNode(
5219 Op.getOperand(IsStrict ? 1 : 0), DAG.getConstant(0, DL, MVT::i64));
5220 EVT ScalarVT = VT.getScalarType();
5221 if (IsStrict)
5222 return DAG.getNode(Op.getOpcode(), DL, {ScalarVT, MVT::Other},
5223 {Op.getOperand(0), Extract});
5224 return DAG.getNode(Op.getOpcode(), DL, ScalarVT, Extract);
5225 }
5226
5227 // Type changing conversions are illegal.
5228 return Op;
5229}
5230
5231SDValue AArch64TargetLowering::LowerFP_TO_INT(SDValue Op,
5232 SelectionDAG &DAG) const {
5233 bool IsStrict = Op->isStrictFPOpcode();
5234 SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
5235
5236 if (SrcVal.getValueType().isVector())
5237 return LowerVectorFP_TO_INT(Op, DAG);
5238
5239 // f16 conversions are promoted to f32 when full fp16 is not supported.
5240 if ((SrcVal.getValueType() == MVT::f16 && !Subtarget->hasFullFP16()) ||
5241 SrcVal.getValueType() == MVT::bf16) {
5242 SDLoc DL(Op);
5243 if (IsStrict) {
5244 SDValue Ext =
5245 DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {MVT::f32, MVT::Other},
5246 {Op.getOperand(0), SrcVal});
5247 return DAG.getNode(Op.getOpcode(), DL, {Op.getValueType(), MVT::Other},
5248 {Ext.getValue(1), Ext.getValue(0)});
5249 }
5250 return DAG.getNode(Op.getOpcode(), DL, Op.getValueType(),
5251 DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, SrcVal));
5252 }
5253
5254 if (SrcVal.getValueType() != MVT::f128) {
5255 // It's legal except when f128 is involved
5256 return Op;
5257 }
5258
5259 return SDValue();
5260}
5261
5262SDValue
5263AArch64TargetLowering::LowerVectorFP_TO_INT_SAT(SDValue Op,
5264 SelectionDAG &DAG) const {
5265 // AArch64 FP-to-int conversions saturate to the destination element size, so
5266 // we can lower common saturating conversions to simple instructions.
5267 SDValue SrcVal = Op.getOperand(0);
5268 const EVT SrcVT = SrcVal.getValueType();
5269 const EVT DstVT = Op.getValueType();
5270 const EVT DstElementVT = DstVT.getVectorElementType();
5271 const EVT SatVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
5272
5273 [[maybe_unused]] const uint64_t DstElementWidth = DstVT.getScalarSizeInBits();
5274 const uint64_t SrcElementWidth = SrcVT.getScalarSizeInBits();
5275 const uint64_t SatWidth = SatVT.getScalarSizeInBits();
5276 assert(SatWidth <= DstElementWidth &&
5277 "Saturation width cannot exceed result width");
5278
5279 const EVT SrcElementVT = SrcVT.getVectorElementType();
5280 if (SrcElementVT != MVT::f64 && SrcElementVT != MVT::f32 &&
5281 SrcElementVT != MVT::f16 && SrcElementVT != MVT::bf16)
5282 return SDValue();
5283
5284 if (SDValue Res = LowerFPToIntToSVE(Op, DAG))
5285 return Res;
5286
5287 // Returns true if the operation can be matched by an isel pattern directly.
5288 auto CanHandleNatively = [&DstVT, &SatWidth](EVT SrcVT) -> bool {
5289 return SrcVT.getScalarSizeInBits() == DstVT.getScalarSizeInBits() &&
5290 SrcVT.getScalarSizeInBits() == SatWidth;
5291 };
5292
5293 // Returns true if the operation is best expanded.
5294 auto Expand = [&SatWidth, &CanHandleNatively](EVT SrcVT) -> bool {
5295 return !CanHandleNatively(SrcVT) &&
5296 (SrcVT.getScalarSizeInBits() < SatWidth ||
5297 // NEON has no vector MIN/MAX for i64, so it's simpler to scalarize
5298 // (at least until sqxtn is selected).
5299 (SrcVT == MVT::v1f64 || SrcVT == MVT::v2f64));
5300 };
5301
5302 // Try to promote the operation to a wider type if SrcVT < DstVT,
5303 // or if type is bf16 or if the target has no +fullfp16.
5304 std::optional<EVT> PromVT;
5305 switch (SrcElementVT.getSimpleVT().SimpleTy) {
5306 case MVT::f16:
5307 case MVT::bf16:
5308 if (DstElementVT == MVT::i32 || SrcElementVT == MVT::bf16 ||
5309 !Subtarget->hasFullFP16()) {
5310 PromVT = MVT::getVectorVT(MVT::f32, SrcVT.getVectorElementCount());
5311 break;
5312 }
5313 [[fallthrough]];
5314 case MVT::f32:
5315 // Promote to f64
5316 if (DstElementVT == MVT::i64) {
5317 PromVT = MVT::getVectorVT(MVT::f64, SrcVT.getVectorElementCount());
5318 break;
5319 }
5320 [[fallthrough]];
5321 default:
5322 break;
5323 }
5324
5325 SDLoc DL(Op);
5326 unsigned Opc = Op.getOpcode();
5327 if (PromVT && !Expand(*PromVT)) {
5328 // When promoting the input type, SatWidth stays unchanged.
5329 SrcVal = DAG.getNode(ISD::FP_EXTEND, DL, *PromVT, SrcVal);
5330 if (*PromVT != MVT::v8f32 || isTypeLegal(MVT::v8f32))
5331 return DAG.getNode(Op.getOpcode(), DL, DstVT, SrcVal, Op.getOperand(1));
5332
5333 // If we are extending to a wider type (e.g. v8f16 -> v8f32) due to lack
5334 // of fp16 support, then it's more efficient to split the operation
5335 // into two v4f32 to produce legal types.
5336 auto [SrcValLo, SrcValHi] = DAG.SplitVector(SrcVal, DL);
5337 SDValue Lo = DAG.getNode(Opc, DL, MVT::v4i32, SrcValLo, Op.getOperand(1));
5338 SDValue Hi = DAG.getNode(Opc, DL, MVT::v4i32, SrcValHi, Op.getOperand(1));
5339 Lo = DAG.getNode(ISD::TRUNCATE, DL, MVT::v4i16, Lo);
5340 Hi = DAG.getNode(ISD::TRUNCATE, DL, MVT::v4i16, Hi);
5341 return DAG.getNode(ISD::CONCAT_VECTORS, DL, DstVT, Lo, Hi);
5342 }
5343
5344 // Cases that we can emit directly.
5345 if (CanHandleNatively(SrcVT)) {
5346 assert(isTypeLegal(SrcVT) && "Expected SrcVT to be a legal type");
5347 return DAG.getNode(Opc, DL, DstVT, SrcVal,
5348 DAG.getValueType(DstVT.getScalarType()));
5349 } else if (Expand(SrcVT)) {
5350 return SDValue();
5351 }
5352
5353 assert((SrcElementWidth > DstElementWidth) ||
5354 (SrcElementWidth == DstElementWidth && SatWidth < DstElementWidth));
5355
5356 EVT IntVT = SrcVT.changeVectorElementTypeToInteger();
5357 SDValue NativeCvt = DAG.getNode(Opc, DL, IntVT, SrcVal,
5358 DAG.getValueType(IntVT.getScalarType()));
5359 SDValue Sat;
5360 if (Opc == ISD::FP_TO_SINT_SAT) {
5361 SDValue MinC = DAG.getConstant(
5362 APInt::getSignedMaxValue(SatWidth).sext(SrcElementWidth), DL, IntVT);
5363 SDValue Min = DAG.getNode(ISD::SMIN, DL, IntVT, NativeCvt, MinC);
5364 SDValue MaxC = DAG.getConstant(
5365 APInt::getSignedMinValue(SatWidth).sext(SrcElementWidth), DL, IntVT);
5366 Sat = DAG.getNode(ISD::SMAX, DL, IntVT, Min, MaxC);
5367 } else {
5368 SDValue MinC = DAG.getConstant(
5369 APInt::getAllOnes(SatWidth).zext(SrcElementWidth), DL, IntVT);
5370 Sat = DAG.getNode(ISD::UMIN, DL, IntVT, NativeCvt, MinC);
5371 }
5372
5373 return DAG.getNode(ISD::TRUNCATE, DL, DstVT, Sat);
5374}
5375
5376SDValue AArch64TargetLowering::LowerFP_TO_INT_SAT(SDValue Op,
5377 SelectionDAG &DAG) const {
5378 // AArch64 FP-to-int conversions saturate to the destination register size, so
5379 // we can lower common saturating conversions to simple instructions.
5380 SDValue SrcVal = Op.getOperand(0);
5381 EVT SrcVT = SrcVal.getValueType();
5382
5383 if (SrcVT.isVector())
5384 return LowerVectorFP_TO_INT_SAT(Op, DAG);
5385
5386 EVT DstVT = Op.getValueType();
5387 EVT SatVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
5388 uint64_t SatWidth = SatVT.getScalarSizeInBits();
5389 uint64_t DstWidth = DstVT.getScalarSizeInBits();
5390 assert(SatWidth <= DstWidth && "Saturation width cannot exceed result width");
5391
5392 // In the absence of FP16 support, promote f16 to f32 and saturate the result.
5393 if ((SrcVT == MVT::f16 && !Subtarget->hasFullFP16()) || SrcVT == MVT::bf16) {
5394 SrcVal = DAG.getNode(ISD::FP_EXTEND, SDLoc(Op), MVT::f32, SrcVal);
5395 SrcVT = MVT::f32;
5396 } else if (SrcVT != MVT::f64 && SrcVT != MVT::f32 && SrcVT != MVT::f16 &&
5397 SrcVT != MVT::bf16)
5398 return SDValue();
5399
5400 SDLoc DL(Op);
5401 // Cases that we can emit directly.
5402 if ((SrcVT == MVT::f64 || SrcVT == MVT::f32 ||
5403 (SrcVT == MVT::f16 && Subtarget->hasFullFP16())) &&
5404 DstVT == SatVT && (DstVT == MVT::i64 || DstVT == MVT::i32))
5405 return DAG.getNode(Op.getOpcode(), DL, DstVT, SrcVal,
5406 DAG.getValueType(DstVT));
5407
5408 // Otherwise we emit a cvt that saturates to a higher BW, and saturate the
5409 // result. This is only valid if the legal cvt is larger than the saturate
5410 // width.
5411 if (DstWidth < SatWidth)
5412 return SDValue();
5413
5414 if (SrcVT == MVT::f16 && SatVT == MVT::i16 && DstVT == MVT::i32) {
5415 if (Op.getOpcode() == ISD::FP_TO_SINT_SAT) {
5416 SDValue CVTf32 =
5417 DAG.getNode(AArch64ISD::FCVTZS_HALF, DL, MVT::f32, SrcVal);
5418 SDValue Bitcast = DAG.getBitcast(DstVT, CVTf32);
5419 return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, DstVT, Bitcast,
5420 DAG.getValueType(SatVT));
5421 }
5422 SDValue CVTf32 = DAG.getNode(AArch64ISD::FCVTZU_HALF, DL, MVT::f32, SrcVal);
5423 return DAG.getBitcast(DstVT, CVTf32);
5424 }
5425
5426 SDValue NativeCvt =
5427 DAG.getNode(Op.getOpcode(), DL, DstVT, SrcVal, DAG.getValueType(DstVT));
5428 SDValue Sat;
5429 if (Op.getOpcode() == ISD::FP_TO_SINT_SAT) {
5430 SDValue MinC = DAG.getConstant(
5431 APInt::getSignedMaxValue(SatWidth).sext(DstWidth), DL, DstVT);
5432 SDValue Min = DAG.getNode(ISD::SMIN, DL, DstVT, NativeCvt, MinC);
5433 SDValue MaxC = DAG.getConstant(
5434 APInt::getSignedMinValue(SatWidth).sext(DstWidth), DL, DstVT);
5435 Sat = DAG.getNode(ISD::SMAX, DL, DstVT, Min, MaxC);
5436 } else {
5437 SDValue MinC = DAG.getConstant(
5438 APInt::getAllOnes(SatWidth).zext(DstWidth), DL, DstVT);
5439 Sat = DAG.getNode(ISD::UMIN, DL, DstVT, NativeCvt, MinC);
5440 }
5441
5442 return DAG.getNode(ISD::TRUNCATE, DL, DstVT, Sat);
5443}
5444
5445SDValue AArch64TargetLowering::LowerVectorXRINT(SDValue Op,
5446 SelectionDAG &DAG) const {
5447 EVT VT = Op.getValueType();
5448 SDValue Src = Op.getOperand(0);
5449 SDLoc DL(Op);
5450
5451 assert(VT.isVector() && "Expected vector type");
5452
5453 EVT CastVT = VT.changeVectorElementType(
5454 *DAG.getContext(), Src.getValueType().getVectorElementType());
5455
5456 // Round the floating-point value into a floating-point register with the
5457 // current rounding mode.
5458 SDValue FOp = DAG.getNode(ISD::FRINT, DL, CastVT, Src);
5459
5460 // Truncate the rounded floating point to an integer.
5461 return DAG.getNode(ISD::FP_TO_SINT_SAT, DL, VT, FOp,
5463}
5464
5465SDValue AArch64TargetLowering::LowerVectorINT_TO_FP(SDValue Op,
5466 SelectionDAG &DAG) const {
5467 // Warning: We maintain cost tables in AArch64TargetTransformInfo.cpp.
5468 // Any additional optimization in this function should be recorded
5469 // in the cost tables.
5470 bool IsStrict = Op->isStrictFPOpcode();
5471 EVT VT = Op.getValueType();
5472 SDLoc DL(Op);
5473 SDValue In = Op.getOperand(IsStrict ? 1 : 0);
5474 EVT InVT = In.getValueType();
5475 unsigned Opc = Op.getOpcode();
5476 bool IsSigned = Opc == ISD::SINT_TO_FP || Opc == ISD::STRICT_SINT_TO_FP;
5477
5478 assert(!(IsStrict && VT.isScalableVector()) &&
5479 "Unimplemented SVE support for ISD:::STRICT_INT_TO_FP!");
5480
5481 // NOTE: i1->bf16 does not require promotion to f32.
5482 if (VT.isScalableVector() && InVT.getVectorElementType() == MVT::i1) {
5483 SDValue FalseVal = DAG.getConstantFP(0.0, DL, VT);
5484 SDValue TrueVal = IsSigned ? DAG.getConstantFP(-1.0, DL, VT)
5485 : DAG.getConstantFP(1.0, DL, VT);
5486 return DAG.getNode(ISD::VSELECT, DL, VT, In, TrueVal, FalseVal);
5487 }
5488
5489 // Promote bf16 conversions to f32.
5490 if (VT.getVectorElementType() == MVT::bf16) {
5491 EVT F32 = VT.changeElementType(*DAG.getContext(), MVT::f32);
5492 if (IsStrict) {
5493 SDValue Val = DAG.getNode(Op.getOpcode(), DL, {F32, MVT::Other},
5494 {Op.getOperand(0), In});
5495 return DAG.getNode(ISD::STRICT_FP_ROUND, DL,
5496 {Op.getValueType(), MVT::Other},
5497 {Val.getValue(1), Val.getValue(0),
5498 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)});
5499 }
5500 return DAG.getNode(ISD::FP_ROUND, DL, Op.getValueType(),
5501 DAG.getNode(Op.getOpcode(), DL, F32, In),
5502 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
5503 }
5504
5505 if (VT.isScalableVector()) {
5506 // Let common code split the operation.
5507 if (VT == MVT::nxv8f32)
5508 return Op;
5509
5510 unsigned Opcode = IsSigned ? AArch64ISD::SINT_TO_FP_MERGE_PASSTHRU
5511 : AArch64ISD::UINT_TO_FP_MERGE_PASSTHRU;
5512 return LowerToPredicatedOp(Op, DAG, Opcode);
5513 }
5514
5515 if (useSVEForFixedLengthVectorVT(VT, !Subtarget->isNeonAvailable()) ||
5516 useSVEForFixedLengthVectorVT(InVT, !Subtarget->isNeonAvailable()))
5517 return LowerFixedLengthIntToFPToSVE(Op, DAG);
5518
5519 uint64_t VTSize = VT.getFixedSizeInBits();
5520 uint64_t InVTSize = InVT.getFixedSizeInBits();
5521 if (VTSize < InVTSize) {
5522 // AArch64 doesn't have a direct vector instruction to convert
5523 // fixed point to floating point AND narrow it at the same time.
5524 // Additional rounding when the target is f32/f64 causes double
5525 // rounding issues. Conversion to f16 is fine due to narrow width.
5526 bool IsTargetf32 = VT.getVectorElementType() == MVT::f32;
5527 bool IsTargetf16 = false;
5528 if (Op.hasOneUse() &&
5529 Op->user_begin()->getOpcode() == ISD::CONCAT_VECTORS) {
5530 // Some vector types are split during legalization into half, followed by
5531 // concatenation, followed by rounding to the original vector type. If we
5532 // end up resolving to f16 type, we shouldn't worry about rounding errors.
5533 SDNode *U = *Op->user_begin();
5534 if (U->hasOneUse() && U->user_begin()->getOpcode() == ISD::FP_ROUND) {
5535 EVT TmpVT = U->user_begin()->getValueType(0);
5536 if (TmpVT.getScalarType() == MVT::f16)
5537 IsTargetf16 = true;
5538 }
5539 }
5540
5541 if (IsTargetf32 && !IsTargetf16) {
5542 return !IsStrict ? DAG.UnrollVectorOp(Op.getNode()) : SDValue();
5543 }
5544
5545 MVT CastVT =
5547 InVT.getVectorNumElements());
5548 if (IsStrict) {
5549 In = DAG.getNode(Opc, DL, {CastVT, MVT::Other}, {Op.getOperand(0), In});
5550 return DAG.getNode(ISD::STRICT_FP_ROUND, DL, {VT, MVT::Other},
5551 {In.getValue(1), In.getValue(0),
5552 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)});
5553 }
5554 In = DAG.getNode(Opc, DL, CastVT, In);
5555 return DAG.getNode(ISD::FP_ROUND, DL, VT, In,
5556 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
5557 }
5558
5559 if (VTSize > InVTSize) {
5560 unsigned CastOpc = IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
5561 EVT CastVT = VT.changeVectorElementTypeToInteger();
5562 In = DAG.getNode(CastOpc, DL, CastVT, In);
5563 if (IsStrict)
5564 return DAG.getNode(Opc, DL, {VT, MVT::Other}, {Op.getOperand(0), In});
5565 return DAG.getNode(Opc, DL, VT, In);
5566 }
5567
5568 // Use a scalar operation for conversions between single-element vectors of
5569 // the same size.
5570 if (VT.getVectorNumElements() == 1) {
5571 SDValue Extract =
5573 DAG.getConstant(0, DL, MVT::i64));
5574 EVT ScalarVT = VT.getScalarType();
5575 if (IsStrict)
5576 return DAG.getNode(Op.getOpcode(), DL, {ScalarVT, MVT::Other},
5577 {Op.getOperand(0), Extract});
5578 return DAG.getNode(Op.getOpcode(), DL, ScalarVT, Extract);
5579 }
5580
5581 return Op;
5582}
5583
5584SDValue AArch64TargetLowering::LowerINT_TO_FP(SDValue Op,
5585 SelectionDAG &DAG) const {
5586 if (Op.getValueType().isVector())
5587 return LowerVectorINT_TO_FP(Op, DAG);
5588
5589 bool IsStrict = Op->isStrictFPOpcode();
5590 SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
5591
5592 bool IsSigned = Op->getOpcode() == ISD::STRICT_SINT_TO_FP ||
5593 Op->getOpcode() == ISD::SINT_TO_FP;
5594
5595 auto IntToFpViaPromotion = [&](EVT PromoteVT) {
5596 SDLoc DL(Op);
5597 if (IsStrict) {
5598 SDValue Val = DAG.getNode(Op.getOpcode(), DL, {PromoteVT, MVT::Other},
5599 {Op.getOperand(0), SrcVal});
5600 return DAG.getNode(ISD::STRICT_FP_ROUND, DL,
5601 {Op.getValueType(), MVT::Other},
5602 {Val.getValue(1), Val.getValue(0),
5603 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)});
5604 }
5605 return DAG.getNode(ISD::FP_ROUND, DL, Op.getValueType(),
5606 DAG.getNode(Op.getOpcode(), DL, PromoteVT, SrcVal),
5607 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
5608 };
5609
5610 if (Op.getValueType() == MVT::bf16) {
5611 unsigned MaxWidth = IsSigned
5612 ? DAG.ComputeMaxSignificantBits(SrcVal)
5613 : DAG.computeKnownBits(SrcVal).countMaxActiveBits();
5614 // bf16 conversions are promoted to f32 when converting from i16.
5615 if (MaxWidth <= 24) {
5616 return IntToFpViaPromotion(MVT::f32);
5617 }
5618
5619 // bf16 conversions are promoted to f64 when converting from i32.
5620 if (MaxWidth <= 53) {
5621 return IntToFpViaPromotion(MVT::f64);
5622 }
5623
5624 // We need to be careful about i64 -> bf16.
5625 // Consider an i32 22216703.
5626 // This number cannot be represented exactly as an f32 and so a itofp will
5627 // turn it into 22216704.0 fptrunc to bf16 will turn this into 22282240.0
5628 // However, the correct bf16 was supposed to be 22151168.0
5629 // We need to use sticky rounding to get this correct.
5630 if (SrcVal.getValueType() == MVT::i64) {
5631 SDLoc DL(Op);
5632 // This algorithm is equivalent to the following:
5633 // uint64_t SrcHi = SrcVal & ~0xfffull;
5634 // uint64_t SrcLo = SrcVal & 0xfffull;
5635 // uint64_t Highest = SrcVal >> 53;
5636 // bool HasHighest = Highest != 0;
5637 // uint64_t ToRound = HasHighest ? SrcHi : SrcVal;
5638 // double Rounded = static_cast<double>(ToRound);
5639 // uint64_t RoundedBits = std::bit_cast<uint64_t>(Rounded);
5640 // uint64_t HasLo = SrcLo != 0;
5641 // bool NeedsAdjustment = HasHighest & HasLo;
5642 // uint64_t AdjustedBits = RoundedBits | uint64_t{NeedsAdjustment};
5643 // double Adjusted = std::bit_cast<double>(AdjustedBits);
5644 // return static_cast<__bf16>(Adjusted);
5645 //
5646 // Essentially, what happens is that SrcVal either fits perfectly in a
5647 // double-precision value or it is too big. If it is sufficiently small,
5648 // we should just go u64 -> double -> bf16 in a naive way. Otherwise, we
5649 // ensure that u64 -> double has no rounding error by only using the 52
5650 // MSB of the input. The low order bits will get merged into a sticky bit
5651 // which will avoid issues incurred by double rounding.
5652
5653 // Signed conversion is more or less like so:
5654 // copysign((__bf16)abs(SrcVal), SrcVal)
5655 SDValue SignBit;
5656 if (IsSigned) {
5657 SignBit = DAG.getNode(ISD::AND, DL, MVT::i64, SrcVal,
5658 DAG.getConstant(1ull << 63, DL, MVT::i64));
5659 SrcVal = DAG.getNode(ISD::ABS, DL, MVT::i64, SrcVal);
5660 }
5661 SDValue SrcHi = DAG.getNode(ISD::AND, DL, MVT::i64, SrcVal,
5662 DAG.getConstant(~0xfffull, DL, MVT::i64));
5663 SDValue SrcLo = DAG.getNode(ISD::AND, DL, MVT::i64, SrcVal,
5664 DAG.getConstant(0xfffull, DL, MVT::i64));
5665 SDValue Highest =
5666 DAG.getNode(ISD::SRL, DL, MVT::i64, SrcVal,
5667 DAG.getShiftAmountConstant(53, MVT::i64, DL));
5668 SDValue Zero64 = DAG.getConstant(0, DL, MVT::i64);
5669 SDValue ToRound =
5670 DAG.getSelectCC(DL, Highest, Zero64, SrcHi, SrcVal, ISD::SETNE);
5671 SDValue Rounded =
5672 IsStrict ? DAG.getNode(Op.getOpcode(), DL, {MVT::f64, MVT::Other},
5673 {Op.getOperand(0), ToRound})
5674 : DAG.getNode(Op.getOpcode(), DL, MVT::f64, ToRound);
5675
5676 SDValue RoundedBits = DAG.getNode(ISD::BITCAST, DL, MVT::i64, Rounded);
5677 if (SignBit) {
5678 RoundedBits = DAG.getNode(ISD::OR, DL, MVT::i64, RoundedBits, SignBit);
5679 }
5680
5681 SDValue HasHighest = DAG.getSetCC(
5682 DL,
5683 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::i64),
5684 Highest, Zero64, ISD::SETNE);
5685
5686 SDValue HasLo = DAG.getSetCC(
5687 DL,
5688 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::i64),
5689 SrcLo, Zero64, ISD::SETNE);
5690
5691 SDValue NeedsAdjustment =
5692 DAG.getNode(ISD::AND, DL, HasLo.getValueType(), HasHighest, HasLo);
5693 NeedsAdjustment = DAG.getZExtOrTrunc(NeedsAdjustment, DL, MVT::i64);
5694
5695 SDValue AdjustedBits =
5696 DAG.getNode(ISD::OR, DL, MVT::i64, RoundedBits, NeedsAdjustment);
5697 SDValue Adjusted = DAG.getNode(ISD::BITCAST, DL, MVT::f64, AdjustedBits);
5698 return IsStrict
5699 ? DAG.getNode(
5701 {Op.getValueType(), MVT::Other},
5702 {Rounded.getValue(1), Adjusted,
5703 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true)})
5704 : DAG.getNode(ISD::FP_ROUND, DL, Op.getValueType(), Adjusted,
5705 DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
5706 }
5707 }
5708
5709 // f16 conversions are promoted to f32 when full fp16 is not supported.
5710 if (Op.getValueType() == MVT::f16 && !Subtarget->hasFullFP16()) {
5711 return IntToFpViaPromotion(MVT::f32);
5712 }
5713
5714 // i128 conversions are libcalls.
5715 if (SrcVal.getValueType() == MVT::i128)
5716 return SDValue();
5717
5718 // Other conversions are legal, unless it's to the completely software-based
5719 // fp128.
5720 if (Op.getValueType() != MVT::f128)
5721 return Op;
5722 return SDValue();
5723}
5724
5725static MVT getSVEContainerType(EVT ContentTy);
5726
5727SDValue
5728AArch64TargetLowering::LowerLOOP_DEPENDENCE_MASK(SDValue Op,
5729 SelectionDAG &DAG) const {
5730 assert((Subtarget->hasSVE2() ||
5731 (Subtarget->hasSME() && Subtarget->isStreaming())) &&
5732 "Lowering loop_dependence_raw_mask or loop_dependence_war_mask "
5733 "requires SVE or SME");
5734
5735 SDLoc DL(Op);
5736 EVT VT = Op.getValueType();
5737 unsigned LaneOffset = Op.getConstantOperandVal(3);
5738 unsigned NumElements = VT.getVectorMinNumElements();
5739 uint64_t EltSizeInBytes = Op.getConstantOperandVal(2);
5740 EVT AddrTy = Op->getOperand(0).getValueType();
5741
5742 // Lane offsets and other element sizes are not supported by whilewr/rw.
5743 if (LaneOffset != 0 || !is_contained({1u, 2u, 4u, 8u}, EltSizeInBytes))
5744 return SDValue();
5745
5746 EVT EltVT = MVT::getIntegerVT(EltSizeInBytes * 8);
5747 EVT PredVT =
5748 getPackedSVEVectorVT(EltVT).changeElementType(*DAG.getContext(), MVT::i1);
5749
5750 if (PredVT == VT) {
5751 // Legal whilewr/rw (lowered by tablegen matcher).
5752 if (AddrTy == MVT::i64)
5753 return Op;
5754
5755 // Almost legal whilewr/rw (addresses must be promoted to i64).
5756 assert(AddrTy == MVT::i32 && "Only expected i32 to be legal!");
5757 return DAG.getNode(
5758 Op.getOpcode(), DL, VT,
5759 DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Op->getOperand(0)),
5760 DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Op->getOperand(1)),
5761 DAG.getConstant(EltSizeInBytes, DL, MVT::i64), Op->getOperand(3));
5762 }
5763
5764 // Expand if this mask needs splitting (this will produce a whilelo).
5765 if (NumElements > PredVT.getVectorMinNumElements())
5766 return SDValue();
5767
5768 SDValue Mask =
5769 DAG.getNode(Op.getOpcode(), DL, PredVT, to_vector(Op->op_values()));
5770
5771 if (VT.isFixedLengthVector()) {
5772 EVT WidePredVT =
5773 PredVT.changeElementType(*DAG.getContext(), VT.getScalarType());
5774 SDValue MaskAsInt = DAG.getNode(ISD::SIGN_EXTEND, DL, WidePredVT, Mask);
5775 return convertFromScalableVector(DAG, VT, MaskAsInt);
5776 }
5777
5778 return DAG.getExtractSubvector(DL, VT, Mask, 0);
5779}
5780
5781SDValue AArch64TargetLowering::LowerBITCAST(SDValue Op,
5782 SelectionDAG &DAG) const {
5783 EVT OpVT = Op.getValueType();
5784 EVT ArgVT = Op.getOperand(0).getValueType();
5785
5787 return LowerFixedLengthBitcastToSVE(Op, DAG);
5788
5789 if (OpVT.isScalableVector()) {
5790 assert(isTypeLegal(OpVT) && "Unexpected result type!");
5791
5792 // Handle type legalisation first.
5793 if (!isTypeLegal(ArgVT)) {
5794 assert(OpVT.isFloatingPoint() && !ArgVT.isFloatingPoint() &&
5795 "Expected int->fp bitcast!");
5796
5797 // Bitcasting between unpacked vector types of different element counts is
5798 // not a NOP because the live elements are laid out differently.
5799 // 01234567
5800 // e.g. nxv2i32 = XX??XX??
5801 // nxv4f16 = X?X?X?X?
5802 if (OpVT.getVectorElementCount() != ArgVT.getVectorElementCount())
5803 return SDValue();
5804
5805 SDValue ExtResult =
5806 DAG.getNode(ISD::ANY_EXTEND, SDLoc(Op), getSVEContainerType(ArgVT),
5807 Op.getOperand(0));
5808 return getSVESafeBitCast(OpVT, ExtResult, DAG);
5809 }
5810
5811 // Bitcasts between legal types with the same element count are legal.
5812 if (OpVT.getVectorElementCount() == ArgVT.getVectorElementCount())
5813 return Op;
5814
5815 // getSVESafeBitCast does not support casting between unpacked types.
5816 if (!isPackedVectorType(OpVT, DAG))
5817 return SDValue();
5818
5819 return getSVESafeBitCast(OpVT, Op.getOperand(0), DAG);
5820 }
5821
5822 if (OpVT != MVT::f16 && OpVT != MVT::bf16)
5823 return SDValue();
5824
5825 // Bitcasts between f16 and bf16 are legal.
5826 if (ArgVT == MVT::f16 || ArgVT == MVT::bf16)
5827 return Op;
5828
5829 SDValue Src = Op.getOperand(0);
5830 SDLoc DL(Op);
5831 if (ArgVT.isVector() && ArgVT.getSizeInBits() == 16) {
5832 Src = DAG.getNode(ISD::BITCAST, DL, MVT::i16, Src);
5833 ArgVT = MVT::i16;
5834 }
5835
5836 assert(ArgVT == MVT::i16);
5837
5838 // If the input from a vector, extract directly from it.
5839 if (Src.getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
5840 Op = DAG.getNode(ISD::BITCAST, DL,
5841 Src.getOperand(0).getValueType().changeElementType(
5842 *DAG.getContext(), OpVT),
5843 Src.getOperand(0));
5844 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, OpVT, Op,
5845 Src.getOperand(1));
5846 }
5847
5848 Op = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v8i16, Src);
5849 Op = DAG.getNode(ISD::BITCAST, DL,
5850 EVT::getVectorVT(*DAG.getContext(), OpVT, 8), Op);
5851 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, OpVT, Op,
5852 DAG.getConstant(0, DL, MVT::i64));
5853}
5854
5855// Returns lane if Op extracts from a two-element vector and lane is constant
5856// (i.e., extractelt(<2 x Ty> %v, ConstantLane)), and std::nullopt otherwise.
5857static std::optional<uint64_t>
5859 SDNode *OpNode = Op.getNode();
5860 if (OpNode->getOpcode() != ISD::EXTRACT_VECTOR_ELT)
5861 return std::nullopt;
5862
5863 EVT VT = OpNode->getOperand(0).getValueType();
5865 if (!VT.isFixedLengthVector() || VT.getVectorNumElements() != 2 || !C)
5866 return std::nullopt;
5867
5868 return C->getZExtValue();
5869}
5870
5872 bool isSigned) {
5873 EVT VT = N.getValueType();
5874
5875 if (N.getOpcode() != ISD::BUILD_VECTOR)
5876 return false;
5877
5878 for (const SDValue &Elt : N->op_values()) {
5880 unsigned EltSize = VT.getScalarSizeInBits();
5881 unsigned HalfSize = EltSize / 2;
5882 if (isSigned) {
5883 if (!isIntN(HalfSize, C->getSExtValue()))
5884 return false;
5885 } else {
5886 if (!isUIntN(HalfSize, C->getZExtValue()))
5887 return false;
5888 }
5889 continue;
5890 }
5891 return false;
5892 }
5893
5894 return true;
5895}
5896
5898 EVT VT = N.getValueType();
5899 assert(VT.is128BitVector() && "Unexpected vector MULL size");
5900 EVT HalfVT = EVT::getVectorVT(
5901 *DAG.getContext(),
5904 return DAG.getNode(ISD::TRUNCATE, SDLoc(N), HalfVT, N);
5905}
5906
5908 return N.getOpcode() == ISD::SIGN_EXTEND ||
5909 N.getOpcode() == ISD::ANY_EXTEND ||
5910 isExtendedBUILD_VECTOR(N, DAG, true);
5911}
5912
5914 return N.getOpcode() == ISD::ZERO_EXTEND ||
5915 N.getOpcode() == ISD::ANY_EXTEND ||
5916 isExtendedBUILD_VECTOR(N, DAG, false);
5917}
5918
5920 unsigned Opcode = N.getOpcode();
5921 if (Opcode == ISD::ADD || Opcode == ISD::SUB) {
5922 SDValue N0 = N.getOperand(0);
5923 SDValue N1 = N.getOperand(1);
5924 return N0->hasOneUse() && N1->hasOneUse() &&
5925 isSignExtended(N0, DAG) && isSignExtended(N1, DAG);
5926 }
5927 return false;
5928}
5929
5931 unsigned Opcode = N.getOpcode();
5932 if (Opcode == ISD::ADD || Opcode == ISD::SUB) {
5933 SDValue N0 = N.getOperand(0);
5934 SDValue N1 = N.getOperand(1);
5935 return N0->hasOneUse() && N1->hasOneUse() &&
5936 isZeroExtended(N0, DAG) && isZeroExtended(N1, DAG);
5937 }
5938 return false;
5939}
5940
5941SDValue AArch64TargetLowering::LowerGET_ROUNDING(SDValue Op,
5942 SelectionDAG &DAG) const {
5943 // The rounding mode is in bits 23:22 of the FPCR.
5944 // The ARM rounding mode value to FLT_ROUNDS mapping is 0->1, 1->2, 2->3, 3->0
5945 // The formula we use to implement this is (((FPCR + (1 << 22)) >> 22) & 3)
5946 // so that the shift + and get folded into a bitfield extract.
5947 SDLoc DL(Op);
5948
5949 SDValue Chain = Op.getOperand(0);
5950 SDValue FPCR_64 =
5951 DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, {MVT::i64, MVT::Other},
5952 {Chain, DAG.getTargetConstant(Intrinsic::aarch64_get_fpcr, DL,
5953 MVT::i64)});
5954 Chain = FPCR_64.getValue(1);
5955 SDValue FPCR_32 = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, FPCR_64);
5956 SDValue FltRounds = DAG.getNode(ISD::ADD, DL, MVT::i32, FPCR_32,
5957 DAG.getConstant(1U << 22, DL, MVT::i32));
5958 SDValue RMODE = DAG.getNode(ISD::SRL, DL, MVT::i32, FltRounds,
5959 DAG.getConstant(22, DL, MVT::i32));
5960 SDValue AND = DAG.getNode(ISD::AND, DL, MVT::i32, RMODE,
5961 DAG.getConstant(3, DL, MVT::i32));
5962 return DAG.getMergeValues({AND, Chain}, DL);
5963}
5964
5965SDValue AArch64TargetLowering::LowerSET_ROUNDING(SDValue Op,
5966 SelectionDAG &DAG) const {
5967 SDLoc DL(Op);
5968 SDValue Chain = Op->getOperand(0);
5969 SDValue RMValue = Op->getOperand(1);
5970
5971 // The rounding mode is in bits 23:22 of the FPCR.
5972 // The llvm.set.rounding argument value to the rounding mode in FPCR mapping
5973 // is 0->3, 1->0, 2->1, 3->2. The formula we use to implement this is
5974 // ((arg - 1) & 3) << 22).
5975 //
5976 // The argument of llvm.set.rounding must be within the segment [0, 3], so
5977 // NearestTiesToAway (4) is not handled here. It is responsibility of the code
5978 // generated llvm.set.rounding to ensure this condition.
5979
5980 // Calculate new value of FPCR[23:22].
5981 RMValue = DAG.getNode(ISD::SUB, DL, MVT::i32, RMValue,
5982 DAG.getConstant(1, DL, MVT::i32));
5983 RMValue = DAG.getNode(ISD::AND, DL, MVT::i32, RMValue,
5984 DAG.getConstant(0x3, DL, MVT::i32));
5985 RMValue =
5986 DAG.getNode(ISD::SHL, DL, MVT::i32, RMValue,
5987 DAG.getConstant(AArch64::RoundingBitsPos, DL, MVT::i32));
5988 RMValue = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, RMValue);
5989
5990 // Get current value of FPCR.
5991 SDValue Ops[] = {
5992 Chain, DAG.getTargetConstant(Intrinsic::aarch64_get_fpcr, DL, MVT::i64)};
5993 SDValue FPCR =
5994 DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, {MVT::i64, MVT::Other}, Ops);
5995 Chain = FPCR.getValue(1);
5996 FPCR = FPCR.getValue(0);
5997
5998 // Put new rounding mode into FPCR[23:22].
5999 const int RMMask = ~(AArch64::Rounding::rmMask << AArch64::RoundingBitsPos);
6000 FPCR = DAG.getNode(ISD::AND, DL, MVT::i64, FPCR,
6001 DAG.getConstant(RMMask, DL, MVT::i64));
6002 FPCR = DAG.getNode(ISD::OR, DL, MVT::i64, FPCR, RMValue);
6003 SDValue Ops2[] = {
6004 Chain, DAG.getTargetConstant(Intrinsic::aarch64_set_fpcr, DL, MVT::i64),
6005 FPCR};
6006 return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops2);
6007}
6008
6009SDValue AArch64TargetLowering::LowerGET_FPMODE(SDValue Op,
6010 SelectionDAG &DAG) const {
6011 SDLoc DL(Op);
6012 SDValue Chain = Op->getOperand(0);
6013
6014 // Get current value of FPCR.
6015 SDValue Ops[] = {
6016 Chain, DAG.getTargetConstant(Intrinsic::aarch64_get_fpcr, DL, MVT::i64)};
6017 SDValue FPCR =
6018 DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, {MVT::i64, MVT::Other}, Ops);
6019 Chain = FPCR.getValue(1);
6020 FPCR = FPCR.getValue(0);
6021
6022 // Truncate FPCR to 32 bits.
6023 SDValue Result = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, FPCR);
6024
6025 return DAG.getMergeValues({Result, Chain}, DL);
6026}
6027
6028SDValue AArch64TargetLowering::LowerSET_FPMODE(SDValue Op,
6029 SelectionDAG &DAG) const {
6030 SDLoc DL(Op);
6031 SDValue Chain = Op->getOperand(0);
6032 SDValue Mode = Op->getOperand(1);
6033
6034 // Extend the specified value to 64 bits.
6035 SDValue FPCR = DAG.getZExtOrTrunc(Mode, DL, MVT::i64);
6036
6037 // Set new value of FPCR.
6038 SDValue Ops2[] = {
6039 Chain, DAG.getTargetConstant(Intrinsic::aarch64_set_fpcr, DL, MVT::i64),
6040 FPCR};
6041 return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops2);
6042}
6043
6044SDValue AArch64TargetLowering::LowerRESET_FPMODE(SDValue Op,
6045 SelectionDAG &DAG) const {
6046 SDLoc DL(Op);
6047 SDValue Chain = Op->getOperand(0);
6048
6049 // Get current value of FPCR.
6050 SDValue Ops[] = {
6051 Chain, DAG.getTargetConstant(Intrinsic::aarch64_get_fpcr, DL, MVT::i64)};
6052 SDValue FPCR =
6053 DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, {MVT::i64, MVT::Other}, Ops);
6054 Chain = FPCR.getValue(1);
6055 FPCR = FPCR.getValue(0);
6056
6057 // Clear bits that are not reserved.
6058 SDValue FPCRMasked = DAG.getNode(
6059 ISD::AND, DL, MVT::i64, FPCR,
6061
6062 // Set new value of FPCR.
6063 SDValue Ops2[] = {
6064 Chain, DAG.getTargetConstant(Intrinsic::aarch64_set_fpcr, DL, MVT::i64),
6065 FPCRMasked};
6066 return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops2);
6067}
6068
6069static unsigned selectUmullSmull(SDValue &N0, SDValue &N1, SelectionDAG &DAG,
6070 SDLoc DL, bool &IsMLA) {
6071 bool IsN0SExt = isSignExtended(N0, DAG);
6072 bool IsN1SExt = isSignExtended(N1, DAG);
6073 if (IsN0SExt && IsN1SExt)
6074 return AArch64ISD::SMULL;
6075
6076 bool IsN0ZExt = isZeroExtended(N0, DAG);
6077 bool IsN1ZExt = isZeroExtended(N1, DAG);
6078
6079 if (IsN0ZExt && IsN1ZExt)
6080 return AArch64ISD::UMULL;
6081
6082 // Select UMULL if we can replace the other operand with an extend.
6083 EVT VT = N0.getValueType();
6084 unsigned EltSize = VT.getScalarSizeInBits();
6085 APInt Mask = APInt::getHighBitsSet(EltSize, EltSize / 2);
6086 if (IsN0ZExt || IsN1ZExt) {
6087 if (DAG.MaskedValueIsZero(IsN0ZExt ? N1 : N0, Mask))
6088 return AArch64ISD::UMULL;
6089 } else if (VT == MVT::v2i64 && DAG.MaskedValueIsZero(N0, Mask) &&
6090 DAG.MaskedValueIsZero(N1, Mask)) {
6091 // For v2i64 we look more aggressively at both operands being zero, to avoid
6092 // scalarization.
6093 return AArch64ISD::UMULL;
6094 }
6095
6096 if (IsN0SExt || IsN1SExt) {
6097 if (DAG.ComputeNumSignBits(IsN0SExt ? N1 : N0) > EltSize / 2)
6098 return AArch64ISD::SMULL;
6099 } else if (VT == MVT::v2i64 && DAG.ComputeNumSignBits(N0) > EltSize / 2 &&
6100 DAG.ComputeNumSignBits(N1) > EltSize / 2) {
6101 return AArch64ISD::SMULL;
6102 }
6103
6104 if (!IsN1SExt && !IsN1ZExt)
6105 return 0;
6106
6107 // Look for (s/zext A + s/zext B) * (s/zext C). We want to turn these
6108 // into (s/zext A * s/zext C) + (s/zext B * s/zext C)
6109 if (IsN1SExt && isAddSubSExt(N0, DAG)) {
6110 IsMLA = true;
6111 return AArch64ISD::SMULL;
6112 }
6113 if (IsN1ZExt && isAddSubZExt(N0, DAG)) {
6114 IsMLA = true;
6115 return AArch64ISD::UMULL;
6116 }
6117 if (IsN0ZExt && isAddSubZExt(N1, DAG)) {
6118 std::swap(N0, N1);
6119 IsMLA = true;
6120 return AArch64ISD::UMULL;
6121 }
6122 return 0;
6123}
6124
6125// Transform mul<v2i64, splat(const)> into a SHL and ADD/SUB
6126// (1) multiply-by-(power-of-2 +/- 1) into shift and add/sub.
6127// mul x, (2^N + 1) --> add (shl x, N), x
6128// mul x, (2^N - 1) --> sub (shl x, N), x
6129// Examples: x * 33 --> (x << 5) + x
6130// x * 15 --> (x << 4) - x
6131// x * -33 --> -((x << 5) + x)
6132// x * -15 --> -((x << 4) - x) ; this reduces --> x - (x << 4)
6133// (2) multiply-by-(power-of-2 +/- power-of-2) into shifts and add/sub.
6134// mul x, (2^N + 2^M) --> (add (shl x, N), (shl x, M))
6135// mul x, (2^N - 2^M) --> (sub (shl x, N), (shl x, M))
6136// Examples: x * 0x8800 --> (x << 15) + (x << 11)
6137// x * 0xf800 --> (x << 16) - (x << 11)
6138// x * -0x8800 --> -((x << 15) + (x << 11))
6139// x * -0xf800 --> -((x << 16) - (x << 11)) ; (x << 11) - (x << 16)
6141 const SDNode *Operand = N->getOperand(1).getNode();
6142 APInt SplatValue;
6143
6144 // Not a constant splat so should just stay as a multiplication operation
6145 if (!ISD::isConstantSplatVector(Operand, SplatValue) ||
6146 !SplatValue.getBoolValue())
6147 return SDValue();
6148
6149 bool IsNegative = SplatValue.isNegative();
6150 SplatValue = SplatValue.abs();
6151 // Placeholder for MathOp
6152 unsigned MathOp = ISD::DELETED_NODE;
6153 unsigned TZeros = SplatValue.countr_zero();
6154
6155 // Shift the splat value by all the zeros, this won't affect the parity
6156 // this will help us find the first and second multiple to use.
6157 SplatValue.lshrInPlace(TZeros);
6158
6159 if ((SplatValue - 1).isPowerOf2())
6160 MathOp = ISD::ADD;
6161 else if ((SplatValue + 1).isPowerOf2())
6162 MathOp = ISD::SUB;
6163
6164 // If the constant is not (2^n + 1) or (2^n - 1), it would require
6165 // more than one addition/subtraction. For v2i64, the cost of
6166 // multiple vector adds/shifts often exceeds the cost of
6167 // scalarization (moving to GPRs to use a single MUL).
6168 if (MathOp != ISD::DELETED_NODE) {
6169 SDLoc DL(N);
6170 EVT VT = N->getValueType(0);
6171 SDValue LHS = N->getOperand(0);
6172
6173 unsigned ShiftAmt = MathOp == ISD::ADD ? (SplatValue - 1).logBase2()
6174 : (SplatValue + 1).logBase2();
6175 ShiftAmt += TZeros;
6176
6177 SDValue Shl =
6178 DAG.getNode(ISD::SHL, DL, VT, LHS, DAG.getConstant(ShiftAmt, DL, VT));
6179
6180 SDValue NewLHS = TZeros ? DAG.getNode(ISD::SHL, DL, VT, LHS,
6181 DAG.getConstant(TZeros, DL, VT))
6182 : LHS;
6183 SDValue Combined = DAG.getNode(MathOp, DL, VT, Shl, NewLHS);
6184 if (IsNegative)
6185 Combined = DAG.getNegative(Combined, DL, VT);
6186 return Combined;
6187 }
6188 return SDValue();
6189}
6190
6191SDValue AArch64TargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
6192 EVT VT = Op.getValueType();
6193
6194 bool OverrideNEON = !Subtarget->isNeonAvailable();
6195 if (VT.isScalableVector() || useSVEForFixedLengthVectorVT(VT, OverrideNEON))
6196 return LowerToPredicatedOp(Op, DAG, AArch64ISD::MUL_PRED);
6197
6198 // Multiplications are only custom-lowered for 128-bit and 64-bit vectors so
6199 // that VMULL can be detected. Otherwise v2i64 multiplications are not legal.
6200 assert((VT.is128BitVector() || VT.is64BitVector()) && VT.isInteger() &&
6201 "unexpected type for custom-lowering ISD::MUL");
6202 SDValue N0 = Op.getOperand(0);
6203 SDValue N1 = Op.getOperand(1);
6204 bool isMLA = false;
6205 EVT OVT = VT;
6206 if (VT.is64BitVector()) {
6207 if (N0.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
6208 isNullConstant(N0.getOperand(1)) &&
6211 isNullConstant(N1.getOperand(1)) &&
6213 N0 = N0.getOperand(0);
6214 N1 = N1.getOperand(0);
6215 VT = N0.getValueType();
6216 } else {
6217 if (VT == MVT::v1i64) {
6218 if (Subtarget->hasSVE())
6219 return LowerToPredicatedOp(Op, DAG, AArch64ISD::MUL_PRED);
6220 // Fall through to expand this. It is not legal.
6221 return SDValue();
6222 } else
6223 // Other vector multiplications are legal.
6224 return Op;
6225 }
6226 }
6227
6228 SDLoc DL(Op);
6229 unsigned NewOpc = selectUmullSmull(N0, N1, DAG, DL, isMLA);
6230
6231 if (!NewOpc) {
6232 if (VT.getVectorElementType() == MVT::i64) {
6233 // If SVE is available then i64 vector multiplications can also be made
6234 // legal.
6235 if (Subtarget->hasSVE())
6236 return LowerToPredicatedOp(Op, DAG, AArch64ISD::MUL_PRED);
6237 // Try to optimize the mul to a shift left and add instead of scalarizing.
6238 if (SDValue ShlAdd = convertMulToShlAdd(Op.getNode(), DAG))
6239 return ShlAdd;
6240 // Fall through to expanding as the mul is not legal.
6241 return SDValue();
6242 } else
6243 // Other vector multiplications are legal.
6244 return Op;
6245 }
6246
6247 // Legalize to a S/UMULL instruction
6248 SDValue Op0;
6249 SDValue Op1 = skipExtensionForVectorMULL(N1, DAG);
6250 if (!isMLA) {
6251 Op0 = skipExtensionForVectorMULL(N0, DAG);
6253 Op1.getValueType().is64BitVector() &&
6254 "unexpected types for extended operands to VMULL");
6255 return DAG.getExtractSubvector(DL, OVT,
6256 DAG.getNode(NewOpc, DL, VT, Op0, Op1), 0);
6257 }
6258 // Optimizing (zext A + zext B) * C, to (S/UMULL A, C) + (S/UMULL B, C) during
6259 // isel lowering to take advantage of no-stall back to back s/umul + s/umla.
6260 // This is true for CPUs with accumulate forwarding such as Cortex-A53/A57
6263 EVT Op1VT = Op1.getValueType();
6264 return DAG.getNode(
6266 DAG.getNode(N0.getOpcode(), DL, VT,
6267 DAG.getNode(NewOpc, DL, VT,
6268 DAG.getNode(ISD::BITCAST, DL, Op1VT, N00), Op1),
6269 DAG.getNode(NewOpc, DL, VT,
6270 DAG.getNode(ISD::BITCAST, DL, Op1VT, N01), Op1)),
6271 DAG.getConstant(0, DL, MVT::i64));
6272}
6273
6274static inline SDValue getPTrue(SelectionDAG &DAG, SDLoc DL, EVT VT,
6275 int Pattern) {
6276 if (Pattern == AArch64SVEPredPattern::all)
6277 return DAG.getConstant(1, DL, VT);
6278
6279 // When the number of active elements of a pattern matches the scalable vector
6280 // length, we can upgrade the pattern to ALL and emit a splat instead.
6281 if (unsigned PatNumElts = getNumElementsFromSVEPredPattern(Pattern)) {
6282 const AArch64Subtarget &Subtarget = DAG.getSubtarget<AArch64Subtarget>();
6283 unsigned NumElts = VT.getVectorMinNumElements();
6284 unsigned VScale = Subtarget.getSVEVectorSizeInBits() / 128;
6285 if (PatNumElts == (NumElts * VScale))
6286 return DAG.getConstant(1, DL, VT);
6287 }
6288
6289 return DAG.getNode(AArch64ISD::PTRUE, DL, VT,
6290 DAG.getTargetConstant(Pattern, DL, MVT::i32));
6291}
6292
6294 Intrinsic::ID IID;
6295
6296 switch (VT.getScalarSizeInBits()) {
6297 default:
6298 llvm_unreachable("unsupported predicate element size");
6299 case 8:
6300 IID = Intrinsic::aarch64_sve_ptrue_c8;
6301 break;
6302 case 16:
6303 IID = Intrinsic::aarch64_sve_ptrue_c16;
6304 break;
6305 case 32:
6306 IID = Intrinsic::aarch64_sve_ptrue_c32;
6307 break;
6308 case 64:
6309 IID = Intrinsic::aarch64_sve_ptrue_c64;
6310 break;
6311 }
6312
6313 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::aarch64svcount,
6314 DAG.getConstant(IID, DL, MVT::i64));
6315}
6316
6318 bool IsSigned, bool IsEqual) {
6319 unsigned Op0 = N->getOpcode() == ISD::INTRINSIC_WO_CHAIN ? 1 : 0;
6320 unsigned Op1 = N->getOpcode() == ISD::INTRINSIC_WO_CHAIN ? 2 : 1;
6321
6322 if (!N->getValueType(0).isScalableVector() ||
6323 !isa<ConstantSDNode>(N->getOperand(Op1)))
6324 return SDValue();
6325
6326 SDLoc DL(N);
6327 APInt Y = N->getConstantOperandAPInt(Op1);
6328
6329 // When the second operand is the maximum value, comparisons that include
6330 // equality can never fail and thus we can return an all active predicate.
6331 if (IsEqual)
6332 if (IsSigned ? Y.isMaxSignedValue() : Y.isMaxValue())
6333 return DAG.getConstant(1, DL, N->getValueType(0));
6334
6335 if (!isa<ConstantSDNode>(N->getOperand(Op0)))
6336 return SDValue();
6337
6338 APInt X = N->getConstantOperandAPInt(Op0);
6339
6340 bool Overflow;
6341 APInt NumActiveElems =
6342 IsSigned ? Y.ssub_ov(X, Overflow) : Y.usub_ov(X, Overflow);
6343
6344 if (Overflow)
6345 return SDValue();
6346
6347 if (IsEqual) {
6348 APInt One(NumActiveElems.getBitWidth(), 1, IsSigned);
6349 NumActiveElems = IsSigned ? NumActiveElems.sadd_ov(One, Overflow)
6350 : NumActiveElems.uadd_ov(One, Overflow);
6351 if (Overflow)
6352 return SDValue();
6353 }
6354
6355 std::optional<unsigned> PredPattern =
6357 unsigned MinSVEVectorSize = std::max(
6359 unsigned ElementSize = 128 / N->getValueType(0).getVectorMinNumElements();
6360 if (PredPattern != std::nullopt &&
6361 NumActiveElems.getZExtValue() <= (MinSVEVectorSize / ElementSize))
6362 return getPTrue(DAG, DL, N->getValueType(0), *PredPattern);
6363
6364 return SDValue();
6365}
6366
6367// Match get.active.lane.mask(0, cttz.elts(x)) -> brkb(x)
6368// Match get.active.lane.mask(0, add(cttz.elts(x), 1)) -> brka(x)
6370 SDLoc DL(N);
6371 EVT VT = N->getValueType(0);
6372 // Lower bound must be 0.
6373 if (!isZeroOrZeroSplat(N->getOperand(0)))
6374 return SDValue();
6375
6376 SDValue Upper = N->getOperand(1);
6377
6378 // Default to brkb, switch to brka if we find a +1.
6379 unsigned BrkID = Intrinsic::aarch64_sve_brkb_z;
6380 if (Upper->getOpcode() == ISD::ADD && isOneOrOneSplat(Upper.getOperand(1))) {
6381 Upper = Upper.getOperand(0);
6382 BrkID = Intrinsic::aarch64_sve_brka_z;
6383 }
6384
6385 // We're looking for an upper bound based on CTTZ_ELTS; this would be selected
6386 // as a cntp(brk(Pg, Mask)), but if we're just going to make a whilelo based
6387 // on that then we just need the brk.
6388 if (Upper.getOpcode() != AArch64ISD::CTTZ_ELTS || !VT.isScalableVector() ||
6389 Upper.getOperand(0).getValueType() != VT)
6390 return SDValue();
6391
6392 SDValue Pg = Upper->getOperand(0);
6393 SDValue Mask = Upper->getOperand(1);
6394
6395 // brk{a,b} only support .b forms, so cast to make sure all our p regs match.
6396 Pg = getSVEPredicateBitCast(MVT::nxv16i1, Pg, DAG);
6397 SDValue MaskR =
6398 DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, MVT::nxv16i1, Mask);
6399 SDValue ID = DAG.getTargetConstant(BrkID, DL, MVT::i64);
6400 SDValue Brk =
6401 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::nxv16i1, ID, Pg, MaskR);
6402 return DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, VT, Brk);
6403}
6404
6405// Returns a safe bitcast between two scalable vector predicates, where
6406// any newly created lanes from a widening bitcast are defined as zero.
6408 SDLoc DL(Op);
6409 EVT InVT = Op.getValueType();
6410
6411 assert(InVT.getVectorElementType() == MVT::i1 &&
6412 VT.getVectorElementType() == MVT::i1 &&
6413 "Expected a predicate-to-predicate bitcast");
6415 InVT.isScalableVector() &&
6416 DAG.getTargetLoweringInfo().isTypeLegal(InVT) &&
6417 "Only expect to cast between legal scalable predicate types!");
6418
6419 // Return the operand if the cast isn't changing type,
6420 if (InVT == VT)
6421 return Op;
6422
6423 // Look through casts to <vscale x 16 x i1> when their input has more lanes
6424 // than VT. This will increase the chances of removing casts that introduce
6425 // new lanes, which have to be explicitly zero'd.
6426 if (Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN &&
6427 Op.getConstantOperandVal(0) == Intrinsic::aarch64_sve_convert_to_svbool &&
6428 Op.getOperand(1).getValueType().bitsGT(VT))
6429 Op = Op.getOperand(1);
6430
6431 SDValue Reinterpret = DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, VT, Op);
6432
6433 // We only have to zero the lanes if new lanes are being defined, e.g. when
6434 // casting from <vscale x 2 x i1> to <vscale x 16 x i1>. If this is not the
6435 // case (e.g. when casting from <vscale x 16 x i1> -> <vscale x 2 x i1>) then
6436 // we can return here.
6437 if (InVT.bitsGT(VT))
6438 return Reinterpret;
6439
6440 // Check if the other lanes are already known to be zeroed by
6441 // construction.
6443 return Reinterpret;
6444
6445 // Zero the newly introduced lanes.
6446 SDValue Mask = DAG.getConstant(1, DL, InVT);
6447 Mask = DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, VT, Mask);
6448 return DAG.getNode(ISD::AND, DL, VT, Reinterpret, Mask);
6449}
6450
6451SDValue AArch64TargetLowering::getRuntimePStateSM(SelectionDAG &DAG,
6452 SDValue Chain, SDLoc DL,
6453 EVT VT) const {
6454 RTLIB::Libcall LC = RTLIB::SMEABI_SME_STATE;
6455 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
6456 SDValue Callee =
6457 DAG.getExternalSymbol(LCImpl, getPointerTy(DAG.getDataLayout()));
6458 Type *Int64Ty = Type::getInt64Ty(*DAG.getContext());
6459 Type *RetTy = StructType::get(Int64Ty, Int64Ty);
6460 TargetLowering::CallLoweringInfo CLI(DAG);
6462 CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
6463 DAG.getLibcalls().getLibcallImplCallingConv(LCImpl), RetTy, Callee,
6464 std::move(Args));
6465 std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
6466 SDValue Mask = DAG.getConstant(/*PSTATE.SM*/ 1, DL, MVT::i64);
6467 return DAG.getNode(ISD::AND, DL, MVT::i64, CallResult.first.getOperand(0),
6468 Mask);
6469}
6470
6471// Lower an SME LDR/STR ZA intrinsic
6472// Case 1: If the vector number (vecnum) is an immediate in range, it gets
6473// folded into the instruction
6474// ldr(%tileslice, %ptr, 11) -> ldr [%tileslice, 11], [%ptr, 11]
6475// Case 2: If the vecnum is not an immediate, then it is used to modify the base
6476// and tile slice registers
6477// ldr(%tileslice, %ptr, %vecnum)
6478// ->
6479// %svl = rdsvl
6480// %ptr2 = %ptr + %svl * %vecnum
6481// %tileslice2 = %tileslice + %vecnum
6482// ldr [%tileslice2, 0], [%ptr2, 0]
6483// Case 3: If the vecnum is an immediate out of range, then the same is done as
6484// case 2, but the base and slice registers are modified by the greatest
6485// multiple of 15 lower than the vecnum and the remainder is folded into the
6486// instruction. This means that successive loads and stores that are offset from
6487// each other can share the same base and slice register updates.
6488// ldr(%tileslice, %ptr, 22)
6489// ldr(%tileslice, %ptr, 23)
6490// ->
6491// %svl = rdsvl
6492// %ptr2 = %ptr + %svl * 15
6493// %tileslice2 = %tileslice + 15
6494// ldr [%tileslice2, 7], [%ptr2, 7]
6495// ldr [%tileslice2, 8], [%ptr2, 8]
6496// Case 4: If the vecnum is an add of an immediate, then the non-immediate
6497// operand and the immediate can be folded into the instruction, like case 2.
6498// ldr(%tileslice, %ptr, %vecnum + 7)
6499// ldr(%tileslice, %ptr, %vecnum + 8)
6500// ->
6501// %svl = rdsvl
6502// %ptr2 = %ptr + %svl * %vecnum
6503// %tileslice2 = %tileslice + %vecnum
6504// ldr [%tileslice2, 7], [%ptr2, 7]
6505// ldr [%tileslice2, 8], [%ptr2, 8]
6506// Case 5: The vecnum being an add of an immediate out of range is also handled,
6507// in which case the same remainder logic as case 3 is used.
6508static SDValue LowerSMELdrStr(SDValue N, SelectionDAG &DAG, bool IsLoad) {
6509 SDLoc DL(N);
6510
6511 SDValue TileSlice = N->getOperand(2);
6512 SDValue Base = N->getOperand(3);
6513 SDValue VecNum = N->getOperand(4);
6514 int32_t ConstAddend = 0;
6515 SDValue VarAddend = VecNum;
6516
6517 // If the vnum is an add of an immediate, we can fold it into the instruction
6518 if (VecNum.getOpcode() == ISD::ADD &&
6519 isa<ConstantSDNode>(VecNum.getOperand(1))) {
6520 ConstAddend = cast<ConstantSDNode>(VecNum.getOperand(1))->getSExtValue();
6521 VarAddend = VecNum.getOperand(0);
6522 } else if (auto ImmNode = dyn_cast<ConstantSDNode>(VecNum)) {
6523 ConstAddend = ImmNode->getSExtValue();
6524 VarAddend = SDValue();
6525 }
6526
6527 int32_t ImmAddend = ConstAddend % 16;
6528 if (int32_t C = (ConstAddend - ImmAddend)) {
6529 SDValue CVal = DAG.getTargetConstant(C, DL, MVT::i32);
6530 VarAddend = VarAddend
6531 ? DAG.getNode(ISD::ADD, DL, MVT::i32, {VarAddend, CVal})
6532 : CVal;
6533 }
6534
6535 if (VarAddend) {
6536 // Get the vector length that will be multiplied by vnum
6537 auto SVL = DAG.getNode(AArch64ISD::RDSVL, DL, MVT::i64,
6538 DAG.getConstant(1, DL, MVT::i32));
6539
6540 // Multiply SVL and vnum then add it to the base
6541 SDValue Mul = DAG.getNode(
6542 ISD::MUL, DL, MVT::i64,
6543 {SVL, DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, VarAddend)});
6544 Base = DAG.getNode(ISD::ADD, DL, MVT::i64, {Base, Mul});
6545 // Just add vnum to the tileslice
6546 TileSlice = DAG.getNode(ISD::ADD, DL, MVT::i32, {TileSlice, VarAddend});
6547 }
6548
6549 return DAG.getNode(IsLoad ? AArch64ISD::SME_ZA_LDR : AArch64ISD::SME_ZA_STR,
6550 DL, MVT::Other,
6551 {/*Chain=*/N.getOperand(0), TileSlice, Base,
6552 DAG.getTargetConstant(ImmAddend, DL, MVT::i32)});
6553}
6554
6556 SDLoc DL(Op);
6557 auto Op1 = Op.getOperand(0);
6558 auto Op2 = Op.getOperand(1);
6559 auto Mask = Op.getOperand(2);
6560
6561 EVT Op1VT = Op1.getValueType();
6562 EVT Op2VT = Op2.getValueType();
6563 EVT ResVT = Op.getValueType();
6564
6565 if ((Op2VT == MVT::v3i8 || Op2VT == MVT::v4i8)) {
6566 SDValue Needle = Op2;
6567 EVT NeedleVT = Op2VT;
6568
6569 if (NeedleVT == MVT::v3i8) {
6570 // Pad a v3i8 needle to v4i8.
6571 SDValue Pad = DAG.getExtractVectorElt(DL, MVT::i8, Needle, 0);
6572 Needle = DAG.getInsertSubvector(DL, DAG.getPOISON(MVT::v4i8), Needle, 0);
6573 Needle = DAG.getInsertVectorElt(DL, Needle, Pad, 3);
6574 }
6575
6576 // Extend the v4i8 needle to v16i8.
6577 Needle = DAG.getBitcast(MVT::v1i32, Needle);
6578 Needle = DAG.getExtractVectorElt(DL, MVT::i32, Needle, 0);
6579 Needle = DAG.getSplatVector(MVT::v4i32, DL, Needle);
6580 Needle = DAG.getBitcast(MVT::v16i8, Needle);
6581
6582 return DAG.getNode(ISD::VECTOR_MATCH, DL, Op.getValueType(), Op1, Needle,
6583 Mask);
6584 }
6585
6586 if (!DAG.getTargetLoweringInfo().isTypeLegal(ResVT) ||
6587 !DAG.getTargetLoweringInfo().isTypeLegal(Op1VT))
6588 return SDValue();
6589
6590 if (Op1VT.getVectorElementType() != MVT::i8 &&
6591 Op1VT.getVectorElementType() != MVT::i16)
6592 return SDValue();
6593
6594 if (Op2VT.getFixedSizeInBits() > 128) {
6595 // For VLS SVE fixed-vector types > 128-bit can be legal. These still need
6596 // splitting as `match` works per 128-bit segment.
6597 auto [NeedleLo, NeedleHi] = DAG.SplitVector(Op2, DL);
6598
6599 SDValue MatchLo =
6600 DAG.getNode(ISD::VECTOR_MATCH, DL, ResVT, Op1, NeedleLo, Mask);
6601 SDValue MatchHi =
6602 DAG.getNode(ISD::VECTOR_MATCH, DL, ResVT, Op1, NeedleHi, Mask);
6603
6604 return DAG.getNode(ISD::OR, DL, ResVT, MatchLo, MatchHi);
6605 }
6606
6607 // Scalable vector type used to wrap operands.
6608 // A single container is enough for both operands because ultimately the
6609 // operands will have to be wrapped to the same type (nxv16i8 or nxv8i16).
6610 EVT OpContainerVT = Op1VT.isScalableVector()
6611 ? Op1VT
6613
6614 if (Op2VT.is128BitVector()) {
6615 // If Op2 is a full 128-bit vector, wrap it trivially in a scalable vector.
6616 Op2 = convertToScalableVector(DAG, OpContainerVT, Op2);
6617 // Further, if the result is scalable, broadcast Op2 to a full SVE register.
6618 if (ResVT.isScalableVector())
6619 Op2 = DAG.getNode(AArch64ISD::DUPLANE128, DL, OpContainerVT, Op2,
6620 DAG.getTargetConstant(0, DL, MVT::i64));
6621 } else {
6622 // If Op2 is not a full 128-bit vector, we always need to broadcast it.
6623 unsigned Op2BitWidth = Op2VT.getFixedSizeInBits();
6624 MVT Op2IntVT = MVT::getIntegerVT(Op2BitWidth);
6625 EVT Op2PromotedVT = getPackedSVEVectorVT(Op2IntVT);
6626 Op2 = DAG.getBitcast(MVT::getVectorVT(Op2IntVT, 1), Op2);
6627 Op2 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, Op2IntVT, Op2,
6628 DAG.getConstant(0, DL, MVT::i64));
6629 Op2 = DAG.getSplatVector(Op2PromotedVT, DL, Op2);
6630 Op2 = DAG.getBitcast(OpContainerVT, Op2);
6631 }
6632
6633 SDValue ID =
6634 DAG.getTargetConstant(Intrinsic::aarch64_sve_match, DL, MVT::i64);
6635
6636 // If the result is scalable, we just need to carry out the MATCH.
6637 if (ResVT.isScalableVector())
6638 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, ResVT, ID, Mask, Op1, Op2);
6639
6640 // If the result is fixed, we can still use MATCH but we need to wrap the
6641 // first operand and the mask in scalable vectors before doing so.
6642
6643 // Wrap the operands.
6644 Op1 = convertToScalableVector(DAG, OpContainerVT, Op1);
6645 Mask = DAG.getNode(ISD::SIGN_EXTEND, DL, Op1VT, Mask);
6646 Mask = convertFixedMaskToScalableVector(Mask, DAG);
6647
6648 // Carry out the match.
6649 SDValue Match = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, Mask.getValueType(),
6650 ID, Mask, Op1, Op2);
6651
6652 // Extract and promote the match result (nxv16i1/nxv8i1) to ResVT
6653 // (v16i8/v8i8).
6654 Match = DAG.getNode(ISD::SIGN_EXTEND, DL, OpContainerVT, Match);
6655 Match = convertFromScalableVector(DAG, Op1VT, Match);
6656 return DAG.getNode(ISD::TRUNCATE, DL, ResVT, Match);
6657}
6658
6659SDValue AArch64TargetLowering::LowerINTRINSIC_VOID(SDValue Op,
6660 SelectionDAG &DAG) const {
6661 unsigned IntNo = Op.getConstantOperandVal(1);
6662 SDLoc DL(Op);
6663 switch (IntNo) {
6664 default:
6665 return SDValue(); // Don't custom lower most intrinsics.
6666 case Intrinsic::aarch64_prefetch: {
6667 SDValue Chain = Op.getOperand(0);
6668 SDValue Addr = Op.getOperand(2);
6669
6670 unsigned IsWrite = Op.getConstantOperandVal(3);
6671 unsigned Locality = Op.getConstantOperandVal(4);
6672 unsigned IsStream = Op.getConstantOperandVal(5);
6673 unsigned IsData = Op.getConstantOperandVal(6);
6674 unsigned PrfOp = (IsWrite << 4) | // Load/Store bit
6675 (!IsData << 3) | // IsDataCache bit
6676 (Locality << 1) | // Cache level bits
6677 (unsigned)IsStream; // Stream bit
6678
6679 return DAG.getNode(AArch64ISD::PREFETCH, DL, MVT::Other, Chain,
6680 DAG.getTargetConstant(PrfOp, DL, MVT::i32), Addr);
6681 }
6682 case Intrinsic::aarch64_range_prefetch: {
6683 SDValue Chain = Op.getOperand(0);
6684 SDValue Addr = Op.getOperand(2);
6685
6686 unsigned IsWrite = Op.getConstantOperandVal(3);
6687 unsigned IsStream = Op.getConstantOperandVal(4);
6688 unsigned PrfOp = (IsStream << 2) | IsWrite;
6689
6690 SDValue Metadata = Op.getOperand(5);
6691 return DAG.getNode(AArch64ISD::RANGE_PREFETCH, DL, MVT::Other, Chain,
6692 DAG.getTargetConstant(PrfOp, DL, MVT::i32), Addr,
6693 Metadata);
6694 }
6695 case Intrinsic::aarch64_prefetch_ir:
6696 return DAG.getNode(AArch64ISD::PREFETCH, DL, MVT::Other,
6697 Op.getOperand(0), // Chain
6698 DAG.getTargetConstant(24, DL, MVT::i32), // Rt
6699 Op.getOperand(2)); // Addr
6700 case Intrinsic::aarch64_sme_str:
6701 case Intrinsic::aarch64_sme_ldr: {
6702 return LowerSMELdrStr(Op, DAG, IntNo == Intrinsic::aarch64_sme_ldr);
6703 }
6704 case Intrinsic::aarch64_sme_za_enable:
6705 return DAG.getNode(
6706 AArch64ISD::SMSTART, DL, DAG.getVTList(MVT::Other, MVT::Glue),
6707 Op->getOperand(0), // Chain
6708 DAG.getTargetConstant((int32_t)(AArch64SVCR::SVCRZA), DL, MVT::i32));
6709 case Intrinsic::aarch64_sme_za_disable:
6710 return DAG.getNode(
6711 AArch64ISD::SMSTOP, DL, DAG.getVTList(MVT::Other, MVT::Glue),
6712 Op->getOperand(0), // Chain
6713 DAG.getTargetConstant((int32_t)(AArch64SVCR::SVCRZA), DL, MVT::i32));
6714 }
6715}
6716
6717SDValue AArch64TargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op,
6718 SelectionDAG &DAG) const {
6719 unsigned IntNo = Op.getConstantOperandVal(1);
6720 SDLoc DL(Op);
6721 switch (IntNo) {
6722 default:
6723 return SDValue(); // Don't custom lower most intrinsics.
6724 case Intrinsic::aarch64_svc:
6725 case Intrinsic::aarch64_hvc: {
6726 // The MSVC __svc/__hvc intrinsic takes the 16-bit instruction immediate as
6727 // their first operand and four further operands passed in X0-X3 (an unused
6728 // argument is passed as poison) and returns the value left in X0. Matching
6729 // MSVC, the instruction is not treated as clobbering the caller-saved
6730 // registers; only X0 (the result) is defined.
6731 SDValue Chain = Op.getOperand(0);
6732 unsigned Imm = Op.getConstantOperandVal(2);
6733
6734 static const MCPhysReg ArgGPRs[] = {AArch64::X0, AArch64::X1, AArch64::X2,
6735 AArch64::X3};
6736
6737 SDValue Glue;
6739 for (unsigned I = 0; I < std::size(ArgGPRs); ++I) {
6740 SDValue Arg = Op.getOperand(3 + I);
6741 if (Arg.isUndef())
6742 continue;
6743 Chain = DAG.getCopyToReg(Chain, DL, ArgGPRs[I], Arg, Glue);
6744 Glue = Chain.getValue(1);
6745 RegOps.push_back(DAG.getRegister(ArgGPRs[I], MVT::i64));
6746 }
6747
6749 Ops.push_back(Chain);
6750 Ops.push_back(DAG.getTargetConstant(Imm, DL, MVT::i32));
6751 Ops.append(RegOps.begin(), RegOps.end());
6752 if (Glue.getNode())
6753 Ops.push_back(Glue);
6754
6755 unsigned Opc =
6756 IntNo == Intrinsic::aarch64_svc ? AArch64ISD::SVC : AArch64ISD::HVC;
6757 SDValue Node =
6758 DAG.getNode(Opc, DL, DAG.getVTList(MVT::Other, MVT::Glue), Ops);
6759 Chain = Node.getValue(0);
6760 Glue = Node.getValue(1);
6761
6762 SDValue Result = DAG.getCopyFromReg(Chain, DL, AArch64::X0, MVT::i64, Glue);
6763 return DAG.getMergeValues({Result.getValue(0), Result.getValue(1)}, DL);
6764 }
6765 case Intrinsic::aarch64_mops_memset_tag: {
6766 auto Node = cast<MemIntrinsicSDNode>(Op.getNode());
6767 SDValue Chain = Node->getChain();
6768 SDValue Dst = Op.getOperand(2);
6769 SDValue Val = Op.getOperand(3);
6770 Val = DAG.getAnyExtOrTrunc(Val, DL, MVT::i64);
6771 SDValue Size = Op.getOperand(4);
6772 auto Alignment = Node->getMemOperand()->getAlign();
6773 bool IsVol = Node->isVolatile();
6774 auto DstPtrInfo = Node->getPointerInfo();
6775
6776 const auto &SDI =
6777 static_cast<const AArch64SelectionDAGInfo &>(DAG.getSelectionDAGInfo());
6778 SDValue MS = SDI.EmitMOPS(AArch64::MOPSMemorySetTaggingPseudo, DAG, DL,
6779 Chain, Dst, Val, Size, Alignment, Alignment,
6780 IsVol, DstPtrInfo, MachinePointerInfo{});
6781
6782 // MOPS_MEMSET_TAGGING has 3 results (DstWb, SizeWb, Chain) whereas the
6783 // intrinsic has 2. So hide SizeWb using MERGE_VALUES. Otherwise
6784 // LowerOperationWrapper will complain that the number of results has
6785 // changed.
6786 return DAG.getMergeValues({MS.getValue(0), MS.getValue(2)}, DL);
6787 }
6788 }
6789}
6790
6791SDValue AArch64TargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
6792 SelectionDAG &DAG) const {
6793 unsigned IntNo = Op.getConstantOperandVal(0);
6794 SDLoc DL(Op);
6795 switch (IntNo) {
6796 default: return SDValue(); // Don't custom lower most intrinsics.
6797 case Intrinsic::thread_pointer: {
6798 EVT PtrVT = getPointerTy(DAG.getDataLayout());
6799 return DAG.getNode(AArch64ISD::THREAD_POINTER, DL, PtrVT);
6800 }
6801 case Intrinsic::aarch64_sve_whilewr_b:
6802 return DAG.getNode(ISD::LOOP_DEPENDENCE_WAR_MASK, DL, Op.getValueType(),
6803 Op.getOperand(1), Op.getOperand(2),
6804 DAG.getConstant(1, DL, MVT::i64),
6805 DAG.getConstant(0, DL, MVT::i64));
6806 case Intrinsic::aarch64_sve_whilewr_h:
6807 return DAG.getNode(ISD::LOOP_DEPENDENCE_WAR_MASK, DL, Op.getValueType(),
6808 Op.getOperand(1), Op.getOperand(2),
6809 DAG.getConstant(2, DL, MVT::i64),
6810 DAG.getConstant(0, DL, MVT::i64));
6811 case Intrinsic::aarch64_sve_whilewr_s:
6812 return DAG.getNode(ISD::LOOP_DEPENDENCE_WAR_MASK, DL, Op.getValueType(),
6813 Op.getOperand(1), Op.getOperand(2),
6814 DAG.getConstant(4, DL, MVT::i64),
6815 DAG.getConstant(0, DL, MVT::i64));
6816 case Intrinsic::aarch64_sve_whilewr_d:
6817 return DAG.getNode(ISD::LOOP_DEPENDENCE_WAR_MASK, DL, Op.getValueType(),
6818 Op.getOperand(1), Op.getOperand(2),
6819 DAG.getConstant(8, DL, MVT::i64),
6820 DAG.getConstant(0, DL, MVT::i64));
6821 case Intrinsic::aarch64_sve_whilerw_b:
6822 return DAG.getNode(ISD::LOOP_DEPENDENCE_RAW_MASK, DL, Op.getValueType(),
6823 Op.getOperand(1), Op.getOperand(2),
6824 DAG.getConstant(1, DL, MVT::i64),
6825 DAG.getConstant(0, DL, MVT::i64));
6826 case Intrinsic::aarch64_sve_whilerw_h:
6827 return DAG.getNode(ISD::LOOP_DEPENDENCE_RAW_MASK, DL, Op.getValueType(),
6828 Op.getOperand(1), Op.getOperand(2),
6829 DAG.getConstant(2, DL, MVT::i64),
6830 DAG.getConstant(0, DL, MVT::i64));
6831 case Intrinsic::aarch64_sve_whilerw_s:
6832 return DAG.getNode(ISD::LOOP_DEPENDENCE_RAW_MASK, DL, Op.getValueType(),
6833 Op.getOperand(1), Op.getOperand(2),
6834 DAG.getConstant(4, DL, MVT::i64),
6835 DAG.getConstant(0, DL, MVT::i64));
6836 case Intrinsic::aarch64_sve_whilerw_d:
6837 return DAG.getNode(ISD::LOOP_DEPENDENCE_RAW_MASK, DL, Op.getValueType(),
6838 Op.getOperand(1), Op.getOperand(2),
6839 DAG.getConstant(8, DL, MVT::i64),
6840 DAG.getConstant(0, DL, MVT::i64));
6841 case Intrinsic::aarch64_neon_abs: {
6842 EVT Ty = Op.getValueType();
6843 if (Ty == MVT::i64) {
6844 SDValue Result =
6845 DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v1i64, Op.getOperand(1));
6846 Result = DAG.getNode(ISD::ABS, DL, MVT::v1i64, Result);
6847 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i64, Result,
6848 DAG.getConstant(0, DL, MVT::i64));
6849 } else if (Ty.isVector() && Ty.isInteger() && isTypeLegal(Ty)) {
6850 return DAG.getNode(ISD::ABS, DL, Ty, Op.getOperand(1));
6851 } else {
6852 report_fatal_error("Unexpected type for AArch64 NEON intrinsic");
6853 }
6854 }
6855 case Intrinsic::aarch64_neon_addhn: {
6856 return DAG.getNode(AArch64ISD::ADDHN, DL, Op.getValueType(),
6857 Op.getOperand(1), Op.getOperand(2));
6858 }
6859 case Intrinsic::aarch64_neon_pmull64: {
6860 SDValue LHS = Op.getOperand(1);
6861 SDValue RHS = Op.getOperand(2);
6862
6863 std::optional<uint64_t> LHSLane =
6865 std::optional<uint64_t> RHSLane =
6867
6868 assert((!LHSLane || *LHSLane < 2) && "Expect lane to be None or 0 or 1");
6869 assert((!RHSLane || *RHSLane < 2) && "Expect lane to be None or 0 or 1");
6870
6871 // 'aarch64_neon_pmull64' takes i64 parameters; while pmull/pmull2
6872 // instructions execute on SIMD registers. So canonicalize i64 to v1i64,
6873 // which ISel recognizes better. For example, generate a ldr into d*
6874 // registers as opposed to a GPR load followed by a fmov.
6875 auto TryVectorizeOperand = [](SDValue N, std::optional<uint64_t> NLane,
6876 std::optional<uint64_t> OtherLane,
6877 const SDLoc &DL,
6878 SelectionDAG &DAG) -> SDValue {
6879 // If the operand is an higher half itself, rewrite it to
6880 // extract_high_v2i64; this way aarch64_neon_pmull64 could
6881 // re-use the dag-combiner function with aarch64_neon_{pmull,smull,umull}.
6882 if (NLane == 1)
6883 return DAG.getExtractSubvector(DL, MVT::v1i64, N.getOperand(0), 1);
6884
6885 // Operand N is not a higher half but the other operand is.
6886 if (OtherLane == 1) {
6887 // If this operand is a lower half, rewrite it to
6888 // extract_high_v2i64(duplane(<2 x Ty>, 0)). This saves a roundtrip to
6889 // align lanes of two operands. A roundtrip sequence (to move from lane
6890 // 1 to lane 0) is like this:
6891 // mov x8, v0.d[1]
6892 // fmov d0, x8
6893 if (NLane == 0)
6894 return DAG.getExtractSubvector(
6895 DL, MVT::v1i64,
6896 DAG.getNode(AArch64ISD::DUPLANE64, DL, MVT::v2i64,
6897 N.getOperand(0), DAG.getConstant(0, DL, MVT::i64)),
6898 1);
6899
6900 // Otherwise just dup from main to all lanes.
6901 return DAG.getNode(AArch64ISD::DUP, DL, MVT::v1i64, N);
6902 }
6903
6904 // Neither operand is an extract of higher half, so codegen may just use
6905 // the non-high version of PMULL instruction. Use v1i64 to represent i64.
6906 assert(N.getValueType() == MVT::i64 &&
6907 "Intrinsic aarch64_neon_pmull64 requires i64 parameters");
6908 return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v1i64, N);
6909 };
6910
6911 LHS = TryVectorizeOperand(LHS, LHSLane, RHSLane, DL, DAG);
6912 RHS = TryVectorizeOperand(RHS, RHSLane, LHSLane, DL, DAG);
6913
6914 return DAG.getNode(AArch64ISD::PMULL, DL, Op.getValueType(), LHS, RHS);
6915 }
6916 case Intrinsic::aarch64_neon_smax:
6917 return DAG.getNode(ISD::SMAX, DL, Op.getValueType(), Op.getOperand(1),
6918 Op.getOperand(2));
6919 case Intrinsic::aarch64_neon_umax:
6920 return DAG.getNode(ISD::UMAX, DL, Op.getValueType(), Op.getOperand(1),
6921 Op.getOperand(2));
6922 case Intrinsic::aarch64_neon_smin:
6923 return DAG.getNode(ISD::SMIN, DL, Op.getValueType(), Op.getOperand(1),
6924 Op.getOperand(2));
6925 case Intrinsic::aarch64_neon_umin:
6926 return DAG.getNode(ISD::UMIN, DL, Op.getValueType(), Op.getOperand(1),
6927 Op.getOperand(2));
6928 case Intrinsic::aarch64_neon_scalar_sqxtn:
6929 case Intrinsic::aarch64_neon_scalar_sqxtun:
6930 case Intrinsic::aarch64_neon_scalar_uqxtn: {
6931 assert(Op.getValueType() == MVT::i32 || Op.getValueType() == MVT::f32);
6932 if (Op.getValueType() == MVT::i32)
6933 return DAG.getNode(ISD::BITCAST, DL, MVT::i32,
6934 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::f32,
6935 Op.getOperand(0),
6936 DAG.getNode(ISD::BITCAST, DL, MVT::f64,
6937 Op.getOperand(1))));
6938 return SDValue();
6939 }
6940 case Intrinsic::aarch64_neon_sqxtn:
6941 return DAG.getNode(ISD::TRUNCATE_SSAT_S, DL, Op.getValueType(),
6942 Op.getOperand(1));
6943 case Intrinsic::aarch64_neon_sqxtun:
6944 return DAG.getNode(ISD::TRUNCATE_SSAT_U, DL, Op.getValueType(),
6945 Op.getOperand(1));
6946 case Intrinsic::aarch64_neon_uqxtn:
6947 return DAG.getNode(ISD::TRUNCATE_USAT_U, DL, Op.getValueType(),
6948 Op.getOperand(1));
6949 case Intrinsic::aarch64_neon_sqshrn:
6950 if (Op.getValueType().isVector())
6951 return DAG.getNode(ISD::TRUNCATE_SSAT_S, DL, Op.getValueType(),
6952 DAG.getNode(AArch64ISD::VASHR, DL,
6953 Op.getOperand(1).getValueType(),
6954 Op.getOperand(1), Op.getOperand(2)));
6955 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQSHRN, DAG,
6956 /*LastOperandIsImm=*/true);
6957 case Intrinsic::aarch64_neon_sqshrun:
6958 if (Op.getValueType().isVector())
6959 return DAG.getNode(ISD::TRUNCATE_SSAT_U, DL, Op.getValueType(),
6960 DAG.getNode(AArch64ISD::VASHR, DL,
6961 Op.getOperand(1).getValueType(),
6962 Op.getOperand(1), Op.getOperand(2)));
6963 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQSHRUN, DAG,
6964 /*LastOperandIsImm=*/true);
6965 case Intrinsic::aarch64_neon_uqshrn:
6966 if (Op.getValueType().isVector())
6967 return DAG.getNode(ISD::TRUNCATE_USAT_U, DL, Op.getValueType(),
6968 DAG.getNode(AArch64ISD::VLSHR, DL,
6969 Op.getOperand(1).getValueType(),
6970 Op.getOperand(1), Op.getOperand(2)));
6971 return lowerIntNeonIntrinsic(Op, AArch64ISD::UQSHRN, DAG,
6972 /*LastOperandIsImm=*/true);
6973 case Intrinsic::aarch64_neon_sqrshrn:
6974 if (Op.getValueType().isVector())
6975 return DAG.getNode(ISD::TRUNCATE_SSAT_S, DL, Op.getValueType(),
6976 DAG.getNode(AArch64ISD::SRSHR_I, DL,
6977 Op.getOperand(1).getValueType(),
6978 Op.getOperand(1), Op.getOperand(2)));
6979 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQRSHRN, DAG,
6980 /*LastOperandIsImm=*/true);
6981 case Intrinsic::aarch64_neon_sqrshrun:
6982 if (Op.getValueType().isVector())
6983 return DAG.getNode(ISD::TRUNCATE_SSAT_U, DL, Op.getValueType(),
6984 DAG.getNode(AArch64ISD::SRSHR_I, DL,
6985 Op.getOperand(1).getValueType(),
6986 Op.getOperand(1), Op.getOperand(2)));
6987 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQRSHRUN, DAG,
6988 /*LastOperandIsImm=*/true);
6989 case Intrinsic::aarch64_neon_uqrshrn:
6990 if (Op.getValueType().isVector())
6991 return DAG.getNode(ISD::TRUNCATE_USAT_U, DL, Op.getValueType(),
6992 DAG.getNode(AArch64ISD::URSHR_I, DL,
6993 Op.getOperand(1).getValueType(),
6994 Op.getOperand(1), Op.getOperand(2)));
6995 return lowerIntNeonIntrinsic(Op, AArch64ISD::UQRSHRN, DAG,
6996 /*LastOperandIsImm=*/true);
6997 case Intrinsic::aarch64_neon_sqdmulh:
6998 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQDMULH, DAG);
6999 case Intrinsic::aarch64_neon_sqrdmulh:
7000 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQRDMULH, DAG);
7001 case Intrinsic::aarch64_neon_sqrdmlah:
7002 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQRDMLAH, DAG);
7003 case Intrinsic::aarch64_neon_sqrdmlsh:
7004 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQRDMLSH, DAG);
7005 case Intrinsic::aarch64_neon_sqrshl:
7006 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQRSHL, DAG);
7007 case Intrinsic::aarch64_neon_sqshl:
7008 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQSHL, DAG);
7009 case Intrinsic::aarch64_neon_uqrshl:
7010 return lowerIntNeonIntrinsic(Op, AArch64ISD::UQRSHL, DAG);
7011 case Intrinsic::aarch64_neon_uqshl:
7012 return lowerIntNeonIntrinsic(Op, AArch64ISD::UQSHL, DAG);
7013 case Intrinsic::aarch64_neon_sqadd:
7014 if (Op.getValueType().isVector())
7015 return DAG.getNode(ISD::SADDSAT, DL, Op.getValueType(), Op.getOperand(1),
7016 Op.getOperand(2));
7017 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQADD, DAG);
7018
7019 case Intrinsic::aarch64_neon_sqsub:
7020 if (Op.getValueType().isVector())
7021 return DAG.getNode(ISD::SSUBSAT, DL, Op.getValueType(), Op.getOperand(1),
7022 Op.getOperand(2));
7023 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQSUB, DAG);
7024
7025 case Intrinsic::aarch64_neon_uqadd:
7026 if (Op.getValueType().isVector())
7027 return DAG.getNode(ISD::UADDSAT, DL, Op.getValueType(), Op.getOperand(1),
7028 Op.getOperand(2));
7029 return lowerIntNeonIntrinsic(Op, AArch64ISD::UQADD, DAG);
7030 case Intrinsic::aarch64_neon_suqadd:
7031 return lowerIntNeonIntrinsic(Op, AArch64ISD::SUQADD, DAG);
7032 case Intrinsic::aarch64_neon_usqadd:
7033 return lowerIntNeonIntrinsic(Op, AArch64ISD::USQADD, DAG);
7034 case Intrinsic::aarch64_neon_uqsub:
7035 if (Op.getValueType().isVector())
7036 return DAG.getNode(ISD::USUBSAT, DL, Op.getValueType(), Op.getOperand(1),
7037 Op.getOperand(2));
7038 return lowerIntNeonIntrinsic(Op, AArch64ISD::UQSUB, DAG);
7039 case Intrinsic::aarch64_neon_sqdmulls_scalar:
7040 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQDMULL, DAG);
7041 case Intrinsic::aarch64_neon_sqabs:
7042 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQABS, DAG);
7043 case Intrinsic::aarch64_neon_sqneg:
7044 return lowerIntNeonIntrinsic(Op, AArch64ISD::SQNEG, DAG);
7045 case Intrinsic::aarch64_sve_whilelt:
7046 return optimizeIncrementingWhile(Op.getNode(), DAG, /*IsSigned=*/true,
7047 /*IsEqual=*/false);
7048 case Intrinsic::aarch64_sve_whilels:
7049 return optimizeIncrementingWhile(Op.getNode(), DAG, /*IsSigned=*/false,
7050 /*IsEqual=*/true);
7051 case Intrinsic::aarch64_sve_whilele:
7052 return optimizeIncrementingWhile(Op.getNode(), DAG, /*IsSigned=*/true,
7053 /*IsEqual=*/true);
7054 case Intrinsic::aarch64_sve_sunpkhi:
7055 return DAG.getNode(AArch64ISD::SUNPKHI, DL, Op.getValueType(),
7056 Op.getOperand(1));
7057 case Intrinsic::aarch64_sve_sunpklo:
7058 return DAG.getNode(AArch64ISD::SUNPKLO, DL, Op.getValueType(),
7059 Op.getOperand(1));
7060 case Intrinsic::aarch64_sve_uunpkhi:
7061 return DAG.getNode(AArch64ISD::UUNPKHI, DL, Op.getValueType(),
7062 Op.getOperand(1));
7063 case Intrinsic::aarch64_sve_uunpklo:
7064 return DAG.getNode(AArch64ISD::UUNPKLO, DL, Op.getValueType(),
7065 Op.getOperand(1));
7066 case Intrinsic::aarch64_sve_clasta_n:
7067 return DAG.getNode(AArch64ISD::CLASTA_N, DL, Op.getValueType(),
7068 Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
7069 case Intrinsic::aarch64_sve_clastb_n:
7070 return DAG.getNode(AArch64ISD::CLASTB_N, DL, Op.getValueType(),
7071 Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
7072 case Intrinsic::aarch64_sve_lasta:
7073 return DAG.getNode(AArch64ISD::LASTA, DL, Op.getValueType(),
7074 Op.getOperand(1), Op.getOperand(2));
7075 case Intrinsic::aarch64_sve_lastb:
7076 return DAG.getNode(AArch64ISD::LASTB, DL, Op.getValueType(),
7077 Op.getOperand(1), Op.getOperand(2));
7078 case Intrinsic::aarch64_sve_tbl:
7079 return DAG.getNode(AArch64ISD::TBL, DL, Op.getValueType(), Op.getOperand(1),
7080 Op.getOperand(2));
7081 case Intrinsic::aarch64_sve_trn1:
7082 return DAG.getNode(AArch64ISD::TRN1, DL, Op.getValueType(),
7083 Op.getOperand(1), Op.getOperand(2));
7084 case Intrinsic::aarch64_sve_trn2:
7085 return DAG.getNode(AArch64ISD::TRN2, DL, Op.getValueType(),
7086 Op.getOperand(1), Op.getOperand(2));
7087 case Intrinsic::aarch64_sve_uzp1:
7088 return DAG.getNode(AArch64ISD::UZP1, DL, Op.getValueType(),
7089 Op.getOperand(1), Op.getOperand(2));
7090 case Intrinsic::aarch64_sve_uzp2:
7091 return DAG.getNode(AArch64ISD::UZP2, DL, Op.getValueType(),
7092 Op.getOperand(1), Op.getOperand(2));
7093 case Intrinsic::aarch64_sve_zip1:
7094 return DAG.getNode(AArch64ISD::ZIP1, DL, Op.getValueType(),
7095 Op.getOperand(1), Op.getOperand(2));
7096 case Intrinsic::aarch64_sve_zip2:
7097 return DAG.getNode(AArch64ISD::ZIP2, DL, Op.getValueType(),
7098 Op.getOperand(1), Op.getOperand(2));
7099 case Intrinsic::aarch64_sve_splice:
7100 return DAG.getNode(AArch64ISD::SPLICE, DL, Op.getValueType(),
7101 Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
7102 case Intrinsic::aarch64_sve_ptrue:
7103 return getPTrue(DAG, DL, Op.getValueType(), Op.getConstantOperandVal(1));
7104 case Intrinsic::aarch64_sve_clz:
7105 return DAG.getNode(AArch64ISD::CTLZ_MERGE_PASSTHRU, DL, Op.getValueType(),
7106 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7107 case Intrinsic::aarch64_sme_cntsd: {
7108 SDValue Bytes = DAG.getNode(AArch64ISD::RDSVL, DL, Op.getValueType(),
7109 DAG.getConstant(1, DL, MVT::i32));
7110 return DAG.getNode(ISD::SRL, DL, Op.getValueType(), Bytes,
7111 DAG.getConstant(3, DL, MVT::i32), SDNodeFlags::Exact);
7112 }
7113 case Intrinsic::aarch64_sve_cnt: {
7114 SDValue Data = Op.getOperand(3);
7115 // CTPOP only supports integer operands.
7116 if (Data.getValueType().isFloatingPoint())
7117 Data = DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Data);
7118 return DAG.getNode(AArch64ISD::CTPOP_MERGE_PASSTHRU, DL, Op.getValueType(),
7119 Op.getOperand(2), Data, Op.getOperand(1));
7120 }
7121 case Intrinsic::aarch64_sve_dupq_lane:
7122 return LowerDUPQLane(Op, DAG);
7123 case Intrinsic::aarch64_sve_convert_from_svbool:
7124 return getSVEPredicateBitCast(Op.getValueType(), Op.getOperand(1), DAG);
7125 case Intrinsic::aarch64_sve_convert_to_svbool:
7126 return getSVEPredicateBitCast(MVT::nxv16i1, Op.getOperand(1), DAG);
7127 case Intrinsic::aarch64_sve_convert_from_svcount:
7128 case Intrinsic::aarch64_sve_convert_to_svcount:
7129 return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Op.getOperand(1));
7130 case Intrinsic::aarch64_sve_fneg:
7131 return DAG.getNode(AArch64ISD::FNEG_MERGE_PASSTHRU, DL, Op.getValueType(),
7132 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7133 case Intrinsic::aarch64_sve_frintp:
7134 return DAG.getNode(AArch64ISD::FCEIL_MERGE_PASSTHRU, DL, Op.getValueType(),
7135 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7136 case Intrinsic::aarch64_sve_frintm:
7137 return DAG.getNode(AArch64ISD::FFLOOR_MERGE_PASSTHRU, DL, Op.getValueType(),
7138 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7139 case Intrinsic::aarch64_sve_frinti:
7140 return DAG.getNode(AArch64ISD::FNEARBYINT_MERGE_PASSTHRU, DL,
7141 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7142 Op.getOperand(1));
7143 case Intrinsic::aarch64_sve_frintx:
7144 return DAG.getNode(AArch64ISD::FRINT_MERGE_PASSTHRU, DL, Op.getValueType(),
7145 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7146 case Intrinsic::aarch64_sve_frint32x:
7147 return DAG.getNode(AArch64ISD::FRINT32_MERGE_PASSTHRU, DL,
7148 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7149 Op.getOperand(1));
7150 case Intrinsic::aarch64_sve_frint64x:
7151 return DAG.getNode(AArch64ISD::FRINT64_MERGE_PASSTHRU, DL,
7152 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7153 Op.getOperand(1));
7154 case Intrinsic::aarch64_sve_frinta:
7155 return DAG.getNode(AArch64ISD::FROUND_MERGE_PASSTHRU, DL, Op.getValueType(),
7156 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7157 case Intrinsic::aarch64_sve_frintn:
7158 return DAG.getNode(AArch64ISD::FROUNDEVEN_MERGE_PASSTHRU, DL,
7159 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7160 Op.getOperand(1));
7161 case Intrinsic::aarch64_sve_frintz:
7162 return DAG.getNode(AArch64ISD::FTRUNC_MERGE_PASSTHRU, DL, Op.getValueType(),
7163 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7164 case Intrinsic::aarch64_sve_frint32z:
7165 return DAG.getNode(AArch64ISD::FTRUNC32_MERGE_PASSTHRU, DL,
7166 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7167 Op.getOperand(1));
7168 case Intrinsic::aarch64_sve_frint64z:
7169 return DAG.getNode(AArch64ISD::FTRUNC64_MERGE_PASSTHRU, DL,
7170 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7171 Op.getOperand(1));
7172 case Intrinsic::aarch64_sve_ucvtf:
7173 return DAG.getNode(AArch64ISD::UINT_TO_FP_MERGE_PASSTHRU, DL,
7174 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7175 Op.getOperand(1));
7176 case Intrinsic::aarch64_sve_scvtf:
7177 return DAG.getNode(AArch64ISD::SINT_TO_FP_MERGE_PASSTHRU, DL,
7178 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7179 Op.getOperand(1));
7180 case Intrinsic::aarch64_sve_fcvtzu:
7181 return DAG.getNode(AArch64ISD::FCVTZU_MERGE_PASSTHRU, DL, Op.getValueType(),
7182 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7183 case Intrinsic::aarch64_sve_fcvtzs:
7184 return DAG.getNode(AArch64ISD::FCVTZS_MERGE_PASSTHRU, DL, Op.getValueType(),
7185 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7186 case Intrinsic::aarch64_sve_fsqrt:
7187 return DAG.getNode(AArch64ISD::FSQRT_MERGE_PASSTHRU, DL, Op.getValueType(),
7188 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7189 case Intrinsic::aarch64_sve_frecpx:
7190 return DAG.getNode(AArch64ISD::FRECPX_MERGE_PASSTHRU, DL, Op.getValueType(),
7191 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7192 case Intrinsic::aarch64_sve_frecpe_x:
7193 return DAG.getNode(AArch64ISD::FRECPE, DL, Op.getValueType(),
7194 Op.getOperand(1));
7195 case Intrinsic::aarch64_sve_frecps_x:
7196 return DAG.getNode(AArch64ISD::FRECPS, DL, Op.getValueType(),
7197 Op.getOperand(1), Op.getOperand(2));
7198 case Intrinsic::aarch64_sve_frsqrte_x:
7199 return DAG.getNode(AArch64ISD::FRSQRTE, DL, Op.getValueType(),
7200 Op.getOperand(1));
7201 case Intrinsic::aarch64_sve_frsqrts_x:
7202 return DAG.getNode(AArch64ISD::FRSQRTS, DL, Op.getValueType(),
7203 Op.getOperand(1), Op.getOperand(2));
7204 case Intrinsic::aarch64_sve_fabs:
7205 return DAG.getNode(AArch64ISD::FABS_MERGE_PASSTHRU, DL, Op.getValueType(),
7206 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7207 case Intrinsic::aarch64_sve_abs:
7208 return DAG.getNode(AArch64ISD::ABS_MERGE_PASSTHRU, DL, Op.getValueType(),
7209 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7210 case Intrinsic::aarch64_sve_neg:
7211 return DAG.getNode(AArch64ISD::NEG_MERGE_PASSTHRU, DL, Op.getValueType(),
7212 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7213 case Intrinsic::aarch64_sve_insr: {
7214 SDValue Scalar = Op.getOperand(2);
7215 EVT ScalarTy = Scalar.getValueType();
7216 if ((ScalarTy == MVT::i8) || (ScalarTy == MVT::i16))
7217 Scalar = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Scalar);
7218
7219 return DAG.getNode(AArch64ISD::INSR, DL, Op.getValueType(),
7220 Op.getOperand(1), Scalar);
7221 }
7222 case Intrinsic::aarch64_sve_rbit:
7223 return DAG.getNode(AArch64ISD::BITREVERSE_MERGE_PASSTHRU, DL,
7224 Op.getValueType(), Op.getOperand(2), Op.getOperand(3),
7225 Op.getOperand(1));
7226 case Intrinsic::aarch64_sve_revb:
7227 return DAG.getNode(AArch64ISD::BSWAP_MERGE_PASSTHRU, DL, Op.getValueType(),
7228 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7229 case Intrinsic::aarch64_sve_revh:
7230 return DAG.getNode(AArch64ISD::REVH_MERGE_PASSTHRU, DL, Op.getValueType(),
7231 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7232 case Intrinsic::aarch64_sve_revw:
7233 return DAG.getNode(AArch64ISD::REVW_MERGE_PASSTHRU, DL, Op.getValueType(),
7234 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7235 case Intrinsic::aarch64_sve_revd:
7236 return DAG.getNode(AArch64ISD::REVD_MERGE_PASSTHRU, DL, Op.getValueType(),
7237 Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
7238 case Intrinsic::aarch64_sve_sxtb:
7239 return DAG.getNode(
7240 AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU, DL, Op.getValueType(),
7241 Op.getOperand(2), Op.getOperand(3),
7242 DAG.getValueType(Op.getValueType().changeVectorElementType(
7243 *DAG.getContext(), MVT::i8)),
7244 Op.getOperand(1));
7245 case Intrinsic::aarch64_sve_sxth:
7246 return DAG.getNode(
7247 AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU, DL, Op.getValueType(),
7248 Op.getOperand(2), Op.getOperand(3),
7249 DAG.getValueType(Op.getValueType().changeVectorElementType(
7250 *DAG.getContext(), MVT::i16)),
7251 Op.getOperand(1));
7252 case Intrinsic::aarch64_sve_sxtw:
7253 return DAG.getNode(
7254 AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU, DL, Op.getValueType(),
7255 Op.getOperand(2), Op.getOperand(3),
7256 DAG.getValueType(Op.getValueType().changeVectorElementType(
7257 *DAG.getContext(), MVT::i32)),
7258 Op.getOperand(1));
7259 case Intrinsic::aarch64_sve_uxtb:
7260 return DAG.getNode(
7261 AArch64ISD::ZERO_EXTEND_INREG_MERGE_PASSTHRU, DL, Op.getValueType(),
7262 Op.getOperand(2), Op.getOperand(3),
7263 DAG.getValueType(Op.getValueType().changeVectorElementType(
7264 *DAG.getContext(), MVT::i8)),
7265 Op.getOperand(1));
7266 case Intrinsic::aarch64_sve_uxth:
7267 return DAG.getNode(
7268 AArch64ISD::ZERO_EXTEND_INREG_MERGE_PASSTHRU, DL, Op.getValueType(),
7269 Op.getOperand(2), Op.getOperand(3),
7270 DAG.getValueType(Op.getValueType().changeVectorElementType(
7271 *DAG.getContext(), MVT::i16)),
7272 Op.getOperand(1));
7273 case Intrinsic::aarch64_sve_uxtw:
7274 return DAG.getNode(
7275 AArch64ISD::ZERO_EXTEND_INREG_MERGE_PASSTHRU, DL, Op.getValueType(),
7276 Op.getOperand(2), Op.getOperand(3),
7277 DAG.getValueType(Op.getValueType().changeVectorElementType(
7278 *DAG.getContext(), MVT::i32)),
7279 Op.getOperand(1));
7280 case Intrinsic::localaddress: {
7281 const auto &MF = DAG.getMachineFunction();
7282 const auto *RegInfo = Subtarget->getRegisterInfo();
7283 unsigned Reg = RegInfo->getLocalAddressRegister(MF);
7284 return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg,
7285 Op.getSimpleValueType());
7286 }
7287
7288 case Intrinsic::eh_recoverfp: {
7289 // FIXME: This needs to be implemented to correctly handle highly aligned
7290 // stack objects. For now we simply return the incoming FP. Refer D53541
7291 // for more details.
7292 SDValue FnOp = Op.getOperand(1);
7293 SDValue IncomingFPOp = Op.getOperand(2);
7294 GlobalAddressSDNode *GSD = dyn_cast<GlobalAddressSDNode>(FnOp);
7295 auto *Fn = dyn_cast_or_null<Function>(GSD ? GSD->getGlobal() : nullptr);
7296 if (!Fn)
7298 "llvm.eh.recoverfp must take a function as the first argument");
7299 return IncomingFPOp;
7300 }
7301 case Intrinsic::aarch64_neon_vsri:
7302 case Intrinsic::aarch64_neon_vsli:
7303 case Intrinsic::aarch64_sve_sri:
7304 case Intrinsic::aarch64_sve_sli: {
7305 EVT Ty = Op.getValueType();
7306
7307 if (!Ty.isVector())
7308 report_fatal_error("Unexpected type for aarch64_neon_vsli");
7309
7310 assert(Op.getConstantOperandVal(3) <= Ty.getScalarSizeInBits());
7311
7312 bool IsShiftRight = IntNo == Intrinsic::aarch64_neon_vsri ||
7313 IntNo == Intrinsic::aarch64_sve_sri;
7314 unsigned Opcode = IsShiftRight ? AArch64ISD::VSRI : AArch64ISD::VSLI;
7315 return DAG.getNode(Opcode, DL, Ty, Op.getOperand(1), Op.getOperand(2),
7316 Op.getOperand(3));
7317 }
7318
7319 case Intrinsic::aarch64_neon_srhadd:
7320 case Intrinsic::aarch64_neon_urhadd:
7321 case Intrinsic::aarch64_neon_shadd:
7322 case Intrinsic::aarch64_neon_uhadd: {
7323 bool IsSignedAdd = (IntNo == Intrinsic::aarch64_neon_srhadd ||
7324 IntNo == Intrinsic::aarch64_neon_shadd);
7325 bool IsRoundingAdd = (IntNo == Intrinsic::aarch64_neon_srhadd ||
7326 IntNo == Intrinsic::aarch64_neon_urhadd);
7327 unsigned Opcode = IsSignedAdd
7328 ? (IsRoundingAdd ? ISD::AVGCEILS : ISD::AVGFLOORS)
7329 : (IsRoundingAdd ? ISD::AVGCEILU : ISD::AVGFLOORU);
7330 return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(1),
7331 Op.getOperand(2));
7332 }
7333 case Intrinsic::aarch64_neon_saddlp:
7334 case Intrinsic::aarch64_neon_uaddlp: {
7335 unsigned Opcode = IntNo == Intrinsic::aarch64_neon_uaddlp
7336 ? AArch64ISD::UADDLP
7337 : AArch64ISD::SADDLP;
7338 return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(1));
7339 }
7340 case Intrinsic::aarch64_neon_sdot:
7341 case Intrinsic::aarch64_neon_udot:
7342 case Intrinsic::aarch64_sve_sdot:
7343 case Intrinsic::aarch64_sve_udot: {
7344 unsigned Opcode = (IntNo == Intrinsic::aarch64_neon_udot ||
7345 IntNo == Intrinsic::aarch64_sve_udot)
7346 ? AArch64ISD::UDOT
7347 : AArch64ISD::SDOT;
7348 return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(1),
7349 Op.getOperand(2), Op.getOperand(3));
7350 }
7351 case Intrinsic::aarch64_neon_usdot:
7352 case Intrinsic::aarch64_sve_usdot: {
7353 return DAG.getNode(AArch64ISD::USDOT, DL, Op.getValueType(),
7354 Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
7355 }
7356 case Intrinsic::aarch64_neon_saddlv:
7357 case Intrinsic::aarch64_neon_uaddlv: {
7358 EVT OpVT = Op.getOperand(1).getValueType();
7359 EVT ResVT = Op.getValueType();
7360 assert(
7361 ((ResVT == MVT::i32 && (OpVT == MVT::v8i8 || OpVT == MVT::v16i8 ||
7362 OpVT == MVT::v8i16 || OpVT == MVT::v4i16)) ||
7363 (ResVT == MVT::i64 && (OpVT == MVT::v4i32 || OpVT == MVT::v2i32))) &&
7364 "Unexpected aarch64_neon_u/saddlv type");
7365 (void)OpVT;
7366 // In order to avoid insert_subvector, use v4i32 rather than v2i32.
7367 SDValue ADDLV = DAG.getNode(
7368 IntNo == Intrinsic::aarch64_neon_uaddlv ? AArch64ISD::UADDLV
7369 : AArch64ISD::SADDLV,
7370 DL, ResVT == MVT::i32 ? MVT::v4i32 : MVT::v2i64, Op.getOperand(1));
7371 SDValue EXTRACT_VEC_ELT = DAG.getNode(
7372 ISD::EXTRACT_VECTOR_ELT, DL, ResVT == MVT::i32 ? MVT::i32 : MVT::i64,
7373 ADDLV, DAG.getConstant(0, DL, MVT::i64));
7374 return EXTRACT_VEC_ELT;
7375 }
7376 case Intrinsic::aarch64_cls:
7377 case Intrinsic::aarch64_cls64: {
7378 SDValue Res = DAG.getNode(ISD::CTLS, DL, Op.getOperand(1).getValueType(),
7379 Op.getOperand(1));
7380 return DAG.getNode(ISD::TRUNCATE, DL, Op.getValueType(), Res);
7381 }
7382 case Intrinsic::aarch64_neon_cls: {
7383 // Lower NEON CLS intrinsic to ISD::CTLS
7384 return DAG.getNode(ISD::CTLS, DL, Op.getValueType(), Op.getOperand(1));
7385 }
7386 case Intrinsic::aarch64_sve_pmul:
7387 case Intrinsic::aarch64_neon_pmul:
7388 return DAG.getNode(ISD::CLMUL, DL, Op.getValueType(), Op.getOperand(1),
7389 Op.getOperand(2));
7390 case Intrinsic::aarch64_sve_psel: {
7391 if (Op.getValueType() != MVT::aarch64svcount)
7392 return Op;
7393 // Lower predicate-as-counter variants to reuse normal predicate isel.
7394 SmallVector<SDValue> Ops(Op->ops());
7395 Ops[1] = DAG.getNode(ISD::BITCAST, DL, MVT::nxv16i1, Ops[1]);
7396 SDValue PSel = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::nxv16i1, Ops);
7397 return DAG.getNode(ISD::BITCAST, DL, MVT::aarch64svcount, PSel);
7398 }
7399 }
7400}
7401
7402bool AArch64TargetLowering::shouldExtendGSIndex(EVT VT, EVT &EltTy) const {
7403 if (VT.getVectorElementType() == MVT::i8 ||
7404 VT.getVectorElementType() == MVT::i16) {
7405 EltTy = MVT::i32;
7406 return true;
7407 }
7408 return false;
7409}
7410
7411bool AArch64TargetLowering::shouldRemoveExtendFromGSIndex(SDValue Extend,
7412 EVT DataVT) const {
7413 const EVT IndexVT = Extend.getOperand(0).getValueType();
7414 // SVE only supports implicit extension of 32-bit indices.
7415 if (!Subtarget->hasSVE() || IndexVT.getVectorElementType() != MVT::i32)
7416 return false;
7417
7418 // Indices cannot be smaller than the main data type.
7419 if (IndexVT.getScalarSizeInBits() < DataVT.getScalarSizeInBits())
7420 return false;
7421
7422 // Scalable vectors with "vscale * 2" or fewer elements sit within a 64-bit
7423 // element container type, which would violate the previous clause.
7424 return DataVT.isFixedLengthVector() || DataVT.getVectorMinNumElements() > 2;
7425}
7426
7427/// Helper function to check if a small vector load can be optimized.
7429 const AArch64Subtarget &Subtarget) {
7430 if (!Subtarget.isNeonAvailable())
7431 return false;
7432 if (LD->isVolatile())
7433 return false;
7434
7435 EVT MemVT = LD->getMemoryVT();
7436 if (MemVT != MVT::v2i8 && MemVT != MVT::v4i8 && MemVT != MVT::v2i16)
7437 return false;
7438
7439 Align Alignment = LD->getAlign();
7440 Align RequiredAlignment = Align(MemVT.getStoreSize().getFixedValue());
7441 if (Subtarget.requiresStrictAlign() && Alignment < RequiredAlignment)
7442 return false;
7443
7444 return true;
7445}
7446
7447bool AArch64TargetLowering::isVectorLoadExtDesirable(SDValue ExtVal) const {
7448 EVT ExtVT = ExtVal.getValueType();
7449 // Small, illegal vectors can be extended inreg.
7450 if (auto *Load = dyn_cast<LoadSDNode>(ExtVal.getOperand(0))) {
7451 if (ExtVT.isFixedLengthVector() && ExtVT.getStoreSizeInBits() <= 128 &&
7453 return true;
7454 }
7455 if (!ExtVT.isScalableVector() && !Subtarget->useSVEForFixedLengthVectors())
7456 return false;
7457
7458 // It may be worth creating extending masked loads if there are multiple
7459 // masked loads using the same predicate. That way we'll end up creating
7460 // extending masked loads that may then get split by the legaliser. This
7461 // results in just one set of predicate unpacks at the start, instead of
7462 // multiple sets of vector unpacks after each load.
7463 if (auto *Ld = dyn_cast<MaskedLoadSDNode>(ExtVal->getOperand(0))) {
7464 if (!isLoadLegalOrCustom(ExtVT, Ld->getValueType(0), Ld->getAlign(),
7465 Ld->getAddressSpace(), ISD::ZEXTLOAD, false)) {
7466 // Disable extending masked loads for fixed-width for now, since the code
7467 // quality doesn't look great.
7468 if (!ExtVT.isScalableVector())
7469 return false;
7470
7471 unsigned NumExtMaskedLoads = 0;
7472 for (auto *U : Ld->getMask()->users())
7473 if (isa<MaskedLoadSDNode>(U))
7474 NumExtMaskedLoads++;
7475
7476 if (NumExtMaskedLoads <= 1)
7477 return false;
7478 }
7479 }
7480
7481 EVT PreExtScalarVT = ExtVal->getOperand(0).getValueType().getScalarType();
7482 return PreExtScalarVT == MVT::i8 || PreExtScalarVT == MVT::i16 ||
7483 PreExtScalarVT == MVT::i32 || PreExtScalarVT == MVT::i64;
7484}
7485
7486static unsigned getGatherVecOpcode(bool IsScaled, bool IsSigned,
7487 bool NeedsExtend) {
7488 std::map<std::tuple<bool, bool, bool>, unsigned> AddrModes = {
7489 {std::make_tuple(/*Scaled*/ false, /*Signed*/ false, /*Extend*/ false),
7490 AArch64ISD::GLD1_MERGE_ZERO},
7491 {std::make_tuple(/*Scaled*/ false, /*Signed*/ false, /*Extend*/ true),
7492 AArch64ISD::GLD1_UXTW_MERGE_ZERO},
7493 {std::make_tuple(/*Scaled*/ false, /*Signed*/ true, /*Extend*/ false),
7494 AArch64ISD::GLD1_MERGE_ZERO},
7495 {std::make_tuple(/*Scaled*/ false, /*Signed*/ true, /*Extend*/ true),
7496 AArch64ISD::GLD1_SXTW_MERGE_ZERO},
7497 {std::make_tuple(/*Scaled*/ true, /*Signed*/ false, /*Extend*/ false),
7498 AArch64ISD::GLD1_SCALED_MERGE_ZERO},
7499 {std::make_tuple(/*Scaled*/ true, /*Signed*/ false, /*Extend*/ true),
7500 AArch64ISD::GLD1_UXTW_SCALED_MERGE_ZERO},
7501 {std::make_tuple(/*Scaled*/ true, /*Signed*/ true, /*Extend*/ false),
7502 AArch64ISD::GLD1_SCALED_MERGE_ZERO},
7503 {std::make_tuple(/*Scaled*/ true, /*Signed*/ true, /*Extend*/ true),
7504 AArch64ISD::GLD1_SXTW_SCALED_MERGE_ZERO},
7505 };
7506 auto Key = std::make_tuple(IsScaled, IsSigned, NeedsExtend);
7507 return AddrModes.find(Key)->second;
7508}
7509
7510static unsigned getSignExtendedGatherOpcode(unsigned Opcode) {
7511 switch (Opcode) {
7512 default:
7513 llvm_unreachable("unimplemented opcode");
7514 return Opcode;
7515 case AArch64ISD::GLD1_MERGE_ZERO:
7516 return AArch64ISD::GLD1S_MERGE_ZERO;
7517 case AArch64ISD::GLD1_IMM_MERGE_ZERO:
7518 return AArch64ISD::GLD1S_IMM_MERGE_ZERO;
7519 case AArch64ISD::GLD1_UXTW_MERGE_ZERO:
7520 return AArch64ISD::GLD1S_UXTW_MERGE_ZERO;
7521 case AArch64ISD::GLD1_SXTW_MERGE_ZERO:
7522 return AArch64ISD::GLD1S_SXTW_MERGE_ZERO;
7523 case AArch64ISD::GLD1_SCALED_MERGE_ZERO:
7524 return AArch64ISD::GLD1S_SCALED_MERGE_ZERO;
7525 case AArch64ISD::GLD1_UXTW_SCALED_MERGE_ZERO:
7526 return AArch64ISD::GLD1S_UXTW_SCALED_MERGE_ZERO;
7527 case AArch64ISD::GLD1_SXTW_SCALED_MERGE_ZERO:
7528 return AArch64ISD::GLD1S_SXTW_SCALED_MERGE_ZERO;
7529 }
7530}
7531
7532SDValue AArch64TargetLowering::LowerMGATHER(SDValue Op,
7533 SelectionDAG &DAG) const {
7534 MaskedGatherSDNode *MGT = cast<MaskedGatherSDNode>(Op);
7535
7536 SDLoc DL(Op);
7537 SDValue Chain = MGT->getChain();
7538 SDValue PassThru = MGT->getPassThru();
7539 SDValue Mask = MGT->getMask();
7540 SDValue BasePtr = MGT->getBasePtr();
7541 SDValue Index = MGT->getIndex();
7542 SDValue Scale = MGT->getScale();
7543 EVT VT = Op.getValueType();
7544 EVT MemVT = MGT->getMemoryVT();
7545 ISD::LoadExtType ExtType = MGT->getExtensionType();
7546 ISD::MemIndexType IndexType = MGT->getIndexType();
7547
7548 // SVE supports zero (and so undef) passthrough values only, everything else
7549 // must be handled manually by an explicit select on the load's output.
7550 if (!PassThru->isUndef() && !isZerosVector(PassThru.getNode())) {
7551 SDValue Ops[] = {Chain, DAG.getUNDEF(VT), Mask, BasePtr, Index, Scale};
7552 SDValue Load =
7553 DAG.getMaskedGather(MGT->getVTList(), MemVT, DL, Ops,
7554 MGT->getMemOperand(), IndexType, ExtType);
7555 SDValue Select = DAG.getSelect(DL, VT, Mask, Load, PassThru);
7556 return DAG.getMergeValues({Select, Load.getValue(1)}, DL);
7557 }
7558
7559 bool IsScaled = MGT->isIndexScaled();
7560 bool IsSigned = MGT->isIndexSigned();
7561
7562 // SVE supports an index scaled by sizeof(MemVT.elt) only, everything else
7563 // must be calculated before hand.
7564 uint64_t ScaleVal = Scale->getAsZExtVal();
7565 if (IsScaled && ScaleVal != MemVT.getScalarStoreSize()) {
7566 assert(isPowerOf2_64(ScaleVal) && "Expecting power-of-two types");
7567 EVT IndexVT = Index.getValueType();
7568 Index = DAG.getNode(ISD::SHL, DL, IndexVT, Index,
7569 DAG.getConstant(Log2_32(ScaleVal), DL, IndexVT));
7570 Scale = DAG.getTargetConstant(1, DL, Scale.getValueType());
7571
7572 SDValue Ops[] = {Chain, PassThru, Mask, BasePtr, Index, Scale};
7573 return DAG.getMaskedGather(MGT->getVTList(), MemVT, DL, Ops,
7574 MGT->getMemOperand(), IndexType, ExtType);
7575 }
7576
7577 // Lower fixed length gather to a scalable equivalent.
7578 if (VT.isFixedLengthVector()) {
7579 assert(Subtarget->useSVEForFixedLengthVectors() &&
7580 "Cannot lower when not using SVE for fixed vectors!");
7581
7582 // NOTE: Handle floating-point as if integer then bitcast the result.
7583 EVT DataVT = VT.changeVectorElementTypeToInteger();
7584 MemVT = MemVT.changeVectorElementTypeToInteger();
7585
7586 // Find the smallest integer fixed length vector we can use for the gather.
7587 EVT PromotedVT = VT.changeVectorElementType(*DAG.getContext(), MVT::i32);
7588 if (DataVT.getVectorElementType() == MVT::i64 ||
7589 Index.getValueType().getVectorElementType() == MVT::i64 ||
7590 Mask.getValueType().getVectorElementType() == MVT::i64)
7591 PromotedVT = VT.changeVectorElementType(*DAG.getContext(), MVT::i64);
7592
7593 // Promote vector operands except for passthrough, which we know is either
7594 // undef or zero, and thus best constructed directly.
7595 unsigned ExtOpcode = IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
7596 Index = DAG.getNode(ExtOpcode, DL, PromotedVT, Index);
7597 Mask = DAG.getNode(ISD::SIGN_EXTEND, DL, PromotedVT, Mask);
7598
7599 // A promoted result type forces the need for an extending load.
7600 if (PromotedVT != DataVT && ExtType == ISD::NON_EXTLOAD)
7601 ExtType = ISD::EXTLOAD;
7602
7603 EVT ContainerVT = getContainerForFixedLengthVector(DAG, PromotedVT);
7604
7605 // Convert fixed length vector operands to scalable.
7606 MemVT = ContainerVT.changeVectorElementType(*DAG.getContext(),
7607 MemVT.getVectorElementType());
7608 Index = convertToScalableVector(DAG, ContainerVT, Index);
7610 PassThru = PassThru->isUndef() ? DAG.getUNDEF(ContainerVT)
7611 : DAG.getConstant(0, DL, ContainerVT);
7612
7613 // Emit equivalent scalable vector gather.
7614 SDValue Ops[] = {Chain, PassThru, Mask, BasePtr, Index, Scale};
7615 SDValue Load =
7616 DAG.getMaskedGather(DAG.getVTList(ContainerVT, MVT::Other), MemVT, DL,
7617 Ops, MGT->getMemOperand(), IndexType, ExtType);
7618
7619 // Extract fixed length data then convert to the required result type.
7620 SDValue Result = convertFromScalableVector(DAG, PromotedVT, Load);
7621 Result = DAG.getNode(ISD::TRUNCATE, DL, DataVT, Result);
7622 if (VT.isFloatingPoint())
7623 Result = DAG.getNode(ISD::BITCAST, DL, VT, Result);
7624
7625 return DAG.getMergeValues({Result, Load.getValue(1)}, DL);
7626 }
7627
7628 // Everything else is legal.
7629 return Op;
7630}
7631
7632SDValue AArch64TargetLowering::LowerMSCATTER(SDValue Op,
7633 SelectionDAG &DAG) const {
7634 MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(Op);
7635
7636 SDLoc DL(Op);
7637 SDValue Chain = MSC->getChain();
7638 SDValue StoreVal = MSC->getValue();
7639 SDValue Mask = MSC->getMask();
7640 SDValue BasePtr = MSC->getBasePtr();
7641 SDValue Index = MSC->getIndex();
7642 SDValue Scale = MSC->getScale();
7643 EVT VT = StoreVal.getValueType();
7644 EVT MemVT = MSC->getMemoryVT();
7645 ISD::MemIndexType IndexType = MSC->getIndexType();
7646 bool Truncating = MSC->isTruncatingStore();
7647
7648 bool IsScaled = MSC->isIndexScaled();
7649 bool IsSigned = MSC->isIndexSigned();
7650
7651 // SVE supports an index scaled by sizeof(MemVT.elt) only, everything else
7652 // must be calculated before hand.
7653 uint64_t ScaleVal = Scale->getAsZExtVal();
7654 if (IsScaled && ScaleVal != MemVT.getScalarStoreSize()) {
7655 assert(isPowerOf2_64(ScaleVal) && "Expecting power-of-two types");
7656 EVT IndexVT = Index.getValueType();
7657 Index = DAG.getNode(ISD::SHL, DL, IndexVT, Index,
7658 DAG.getConstant(Log2_32(ScaleVal), DL, IndexVT));
7659 Scale = DAG.getTargetConstant(1, DL, Scale.getValueType());
7660
7661 SDValue Ops[] = {Chain, StoreVal, Mask, BasePtr, Index, Scale};
7662 return DAG.getMaskedScatter(MSC->getVTList(), MemVT, DL, Ops,
7663 MSC->getMemOperand(), IndexType, Truncating);
7664 }
7665
7666 // Lower fixed length scatter to a scalable equivalent.
7667 if (VT.isFixedLengthVector()) {
7668 assert(Subtarget->useSVEForFixedLengthVectors() &&
7669 "Cannot lower when not using SVE for fixed vectors!");
7670
7671 // Once bitcast we treat floating-point scatters as if integer.
7672 if (VT.isFloatingPoint()) {
7674 MemVT = MemVT.changeVectorElementTypeToInteger();
7675 StoreVal = DAG.getNode(ISD::BITCAST, DL, VT, StoreVal);
7676 }
7677
7678 // Find the smallest integer fixed length vector we can use for the scatter.
7679 EVT PromotedVT = VT.changeVectorElementType(*DAG.getContext(), MVT::i32);
7680 if (VT.getVectorElementType() == MVT::i64 ||
7681 Index.getValueType().getVectorElementType() == MVT::i64 ||
7682 Mask.getValueType().getVectorElementType() == MVT::i64)
7683 PromotedVT = VT.changeVectorElementType(*DAG.getContext(), MVT::i64);
7684
7685 // Promote vector operands.
7686 unsigned ExtOpcode = IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
7687 Index = DAG.getNode(ExtOpcode, DL, PromotedVT, Index);
7688 Mask = DAG.getNode(ISD::SIGN_EXTEND, DL, PromotedVT, Mask);
7689 StoreVal = DAG.getNode(ISD::ANY_EXTEND, DL, PromotedVT, StoreVal);
7690
7691 // A promoted value type forces the need for a truncating store.
7692 if (PromotedVT != VT)
7693 Truncating = true;
7694
7695 EVT ContainerVT = getContainerForFixedLengthVector(DAG, PromotedVT);
7696
7697 // Convert fixed length vector operands to scalable.
7698 MemVT = ContainerVT.changeVectorElementType(*DAG.getContext(),
7699 MemVT.getVectorElementType());
7700 Index = convertToScalableVector(DAG, ContainerVT, Index);
7702 StoreVal = convertToScalableVector(DAG, ContainerVT, StoreVal);
7703
7704 // Emit equivalent scalable vector scatter.
7705 SDValue Ops[] = {Chain, StoreVal, Mask, BasePtr, Index, Scale};
7706 return DAG.getMaskedScatter(MSC->getVTList(), MemVT, DL, Ops,
7707 MSC->getMemOperand(), IndexType, Truncating);
7708 }
7709
7710 // Everything else is legal.
7711 return Op;
7712}
7713
7714SDValue AArch64TargetLowering::LowerMLOAD(SDValue Op, SelectionDAG &DAG) const {
7715 SDLoc DL(Op);
7716 MaskedLoadSDNode *LoadNode = cast<MaskedLoadSDNode>(Op);
7717 assert(LoadNode && "Expected custom lowering of a masked load node");
7718 EVT VT = Op->getValueType(0);
7719
7720 if (VT.isFixedLengthVector() && Subtarget->isSVEorStreamingSVEAvailable())
7721 return LowerFixedLengthVectorMLoadToSVE(Op, DAG);
7722
7723 SDValue PassThru = LoadNode->getPassThru();
7724 SDValue Mask = LoadNode->getMask();
7725
7726 if (!LoadNode->isExpandingLoad()) {
7727 if (PassThru->isUndef() || isZerosVector(PassThru.getNode()))
7728 return Op;
7729
7731 VT, DL, LoadNode->getChain(), LoadNode->getBasePtr(),
7732 LoadNode->getOffset(), Mask, DAG.getUNDEF(VT), LoadNode->getMemoryVT(),
7733 LoadNode->getMemOperand(), LoadNode->getAddressingMode(),
7734 LoadNode->getExtensionType());
7735
7736 SDValue Result = DAG.getSelect(DL, VT, Mask, Load, PassThru);
7737 return DAG.getMergeValues({Result, Load.getValue(1)}, DL);
7738 }
7739
7740 // Return if EXPAND instruction is not available.
7741 if ((!Subtarget->isSVEAvailable() || !Subtarget->hasSVE2p2()) &&
7742 (!Subtarget->isSVEorStreamingSVEAvailable() || !Subtarget->hasSME2p2()))
7743 return SDValue();
7744
7745 // Create mask using the number of active lanes in the predicate.
7746 SDValue CntActive = DAG.getNode(
7747 ISD::INTRINSIC_WO_CHAIN, DL, MVT::i64,
7748 DAG.getTargetConstant(Intrinsic::aarch64_sve_cntp, DL, MVT::i64), Mask,
7749 Mask);
7750
7751 SDValue ActiveMask =
7752 DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, Mask->getValueType(0),
7753 DAG.getConstant(0, DL, MVT::i64), CntActive);
7754
7755 // Contiguous load of elements using the active lane mask above.
7757 VT, DL, LoadNode->getChain(), LoadNode->getBasePtr(),
7758 LoadNode->getOffset(), ActiveMask, DAG.getUNDEF(VT),
7759 LoadNode->getMemoryVT(), LoadNode->getMemOperand(),
7760 LoadNode->getAddressingMode(), LoadNode->getExtensionType());
7761
7762 // Expand instruction copies the low-numbered elements to active elements
7763 // in the original predicate and zeros all other lanes.
7764 SDValue Result = DAG.getNode(
7766 DAG.getTargetConstant(Intrinsic::aarch64_sve_expand, DL, MVT::i64), Mask,
7767 Load);
7768
7769 // Copy the passthrough value unless zero/undef.
7770 if (!PassThru->isUndef() && !isZerosVector(PassThru.getNode()))
7771 Result = DAG.getSelect(DL, VT, Mask, Result, PassThru);
7772
7773 return DAG.getMergeValues({Result, Load.getValue(1)}, DL);
7774}
7775
7776// Custom lower trunc store for v4i8 vectors, since it is promoted to v4i16.
7778 EVT VT, EVT MemVT,
7779 SelectionDAG &DAG) {
7780 assert(VT.isVector() && "VT should be a vector type");
7781 assert(MemVT == MVT::v4i8 && VT == MVT::v4i16);
7782
7783 SDValue Value = ST->getValue();
7784
7785 // It first extend the promoted v4i16 to v8i16, truncate to v8i8, and extract
7786 // the word lane which represent the v4i8 subvector. It optimizes the store
7787 // to:
7788 //
7789 // xtn v0.8b, v0.8h
7790 // str s0, [x0]
7791
7792 SDValue Poison = DAG.getPOISON(MVT::i16);
7793 SDValue PoisonVec =
7794 DAG.getBuildVector(MVT::v4i16, DL, {Poison, Poison, Poison, Poison});
7795
7796 SDValue TruncExt =
7797 DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v8i16, Value, PoisonVec);
7798 SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::v8i8, TruncExt);
7799
7800 Trunc = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, Trunc);
7801 SDValue ExtractTrunc = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32,
7802 Trunc, DAG.getConstant(0, DL, MVT::i64));
7803
7804 return DAG.getStore(ST->getChain(), DL, ExtractTrunc,
7805 ST->getBasePtr(), ST->getMemOperand());
7806}
7807
7809 SDLoc DL(Op);
7810 SDValue Src = Op.getOperand(0);
7811 MVT DestVT = Op.getSimpleValueType();
7812 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
7814
7815 unsigned SrcAS = N->getSrcAddressSpace();
7816 unsigned DestAS = N->getDestAddressSpace();
7817 assert(SrcAS != DestAS &&
7818 "addrspacecast must be between different address spaces");
7819 assert(TLI.getTargetMachine().getPointerSize(SrcAS) !=
7820 TLI.getTargetMachine().getPointerSize(DestAS) &&
7821 "addrspacecast must be between different ptr sizes");
7822 (void)TLI;
7823
7824 if (SrcAS == ARM64AS::PTR32_SPTR) {
7825 return DAG.getNode(ISD::SIGN_EXTEND, DL, DestVT, Src,
7826 DAG.getTargetConstant(0, DL, DestVT));
7827 } else if (SrcAS == ARM64AS::PTR32_UPTR) {
7828 return DAG.getNode(ISD::ZERO_EXTEND, DL, DestVT, Src,
7829 DAG.getTargetConstant(0, DL, DestVT));
7830 } else if ((DestAS == ARM64AS::PTR32_SPTR) ||
7831 (DestAS == ARM64AS::PTR32_UPTR)) {
7832 SDValue Ext = DAG.getAnyExtOrTrunc(Src, DL, DestVT);
7833 SDValue Trunc = DAG.getZeroExtendInReg(Ext, DL, DestVT);
7834 return Trunc;
7835 } else {
7836 return Src;
7837 }
7838}
7839
7840// Coordinated with STNP handling in
7841// `llvm/lib/Target/AArch64/AArch64InstrInfo.td` and
7842// `LowerNTStore`
7843static bool isLegalNTStore(Type *DataType, Align Alignment,
7844 const DataLayout &DL) {
7845 // Currently we only support NT stores lowering for little-endian targets.
7846 if (!DL.isLittleEndian())
7847 return false;
7848
7849 // The backend can lower to STNPWi in this case
7850 if (DataType->isIntegerTy(64))
7851 return true;
7852
7853 auto *DataTypeTy = dyn_cast<FixedVectorType>(DataType);
7854 if (!DataTypeTy)
7855 return false;
7856
7857 // Check fixed vector legality
7858 unsigned NumElements = DataTypeTy->getNumElements();
7859 unsigned EltSizeBits = DataTypeTy->getElementType()->getScalarSizeInBits();
7860
7861 // Currently only power-of-2 vectors are supported
7862 if (!isPowerOf2_64(NumElements) || !isPowerOf2_64(EltSizeBits))
7863 return false;
7864
7865 unsigned TotalSizeBits = DataTypeTy->getPrimitiveSizeInBits().getFixedValue();
7866
7867 // The backend can lower to STNPSi or STNPDi in this case
7868 // via `llvm/lib/Target/AArch64/AArch64InstrInfo.td`
7869 if (TotalSizeBits == 64u || TotalSizeBits == 128u)
7870 return true;
7871
7872 // The backend can lower to STNPQi in this case via `LowerNTStore`
7873 if (TotalSizeBits == 256u && (EltSizeBits == 8u || EltSizeBits == 16u ||
7874 EltSizeBits == 32u || EltSizeBits == 64u))
7875 return true;
7876
7877 return false;
7878}
7879
7880// Lower non-temporal stores that would otherwise be broken by legalization.
7881//
7882// Coordinated with STNP constraints in
7883// `llvm/lib/Target/AArch64/AArch64InstrInfo.td` and
7884// `isLegalNTStore`
7885static SDValue LowerNTStore(StoreSDNode *StoreNode, EVT VT, EVT MemVT,
7886 const SDLoc &DL, SelectionDAG &DAG) {
7887 assert(StoreNode && "Expected a store operation");
7888 assert(StoreNode->isNonTemporal() && "Expected a non-temporal store");
7889
7890 // Currently, STNP lowering can only either keep or increase code size, thus
7891 // we predicate it to not apply when optimizing for code size.
7892 if (DAG.shouldOptForSize())
7893 return SDValue();
7894
7895 // Currently we only support NT stores lowering for little-endian targets.
7896 if (!DAG.getDataLayout().isLittleEndian())
7897 return SDValue();
7898
7899 if (VT.isVector()) {
7900 // 256 bit non-temporal stores can be lowered to STNP. Do this as part of
7901 // the custom lowering, as there are no un-paired non-temporal stores and
7902 // legalization will break up 256 bit inputs.
7904 if (VT.isVector() && MemVT.getSizeInBits() == 256u && EC.isKnownEven() &&
7905 (MemVT.getScalarSizeInBits() == 8u ||
7906 MemVT.getScalarSizeInBits() == 16u ||
7907 MemVT.getScalarSizeInBits() == 32u ||
7908 MemVT.getScalarSizeInBits() == 64u)) {
7911 StoreNode->getValue(), 0);
7914 StoreNode->getValue(), EC.getKnownMinValue() / 2);
7915 SDValue Result = DAG.getMemIntrinsicNode(
7916 AArch64ISD::STNP, DL, DAG.getVTList(MVT::Other),
7917 {StoreNode->getChain(), DAG.getBitcast(MVT::v2i64, Lo),
7918 DAG.getBitcast(MVT::v2i64, Hi), StoreNode->getBasePtr()},
7919 StoreNode->getMemoryVT(), StoreNode->getMemOperand());
7921 StoreNode->getAlign(), DAG.getDataLayout()) &&
7922 "Lowering should be consistent with legality");
7923 return Result;
7924 }
7925 }
7926 return SDValue();
7927}
7928
7935
7937 SVEMultiVectorInfo Info;
7938
7940
7941 assert((Size == TypeSize::getScalable(2 * 128) ||
7942 Size == TypeSize::getScalable(4 * 128)) &&
7943 "invalid SVE multi-vector size");
7944
7946
7947 if (Size == TypeSize::getScalable(2 * 128)) {
7948 Info.LoadIntID = Intrinsic::aarch64_sve_ld1_pn_x2;
7949 Info.StoreIntID = Intrinsic::aarch64_sve_st1_pn_x2;
7950 Info.NumVecs = 2;
7951 } else {
7952 Info.LoadIntID = Intrinsic::aarch64_sve_ld1_pn_x4;
7953 Info.StoreIntID = Intrinsic::aarch64_sve_st1_pn_x4;
7954 Info.NumVecs = 4;
7955 }
7956
7957 return Info;
7958}
7959
7960static bool isSimpleScalableLoadOrStore(const LSBaseSDNode *LSNode, EVT VT) {
7961 return LSNode->isSimple() && LSNode->isUnindexed() &&
7962 LSNode->getOffset().isUndef() && VT.isScalableVector() &&
7963 VT.isSimple() && VT == LSNode->getMemoryVT();
7964}
7965
7966// Lower scalable vectors that are 2/4 times the width of a legal SVE type to
7967// multi-vector operations.
7969 SelectionDAG &DAG) {
7970 SDValue Value = StoreNode->getValue();
7971 EVT VT = Value.getValueType();
7972
7973 if (!isSimpleScalableLoadOrStore(StoreNode, VT))
7974 return SDValue();
7975
7976 if (Value->isUndef())
7977 return StoreNode->getChain();
7978
7979 MVT StoreVT = VT.getSimpleVT();
7980 SVEMultiVectorInfo MultiVecInfo = getSVEMultiVectorInfo(StoreVT);
7981
7982 SDLoc DL(StoreNode);
7983 SDValue PNg = getPTrueAsCounter(DAG, DL, VT);
7984
7986 Ops.push_back(StoreNode->getChain());
7987 Ops.push_back(DAG.getConstant(MultiVecInfo.StoreIntID, DL, MVT::i64));
7988
7989 unsigned RegElts = MultiVecInfo.RegVT.getVectorMinNumElements();
7990 for (unsigned i = 0; i != MultiVecInfo.NumVecs; ++i)
7991 Ops.push_back(
7992 DAG.getExtractSubvector(DL, MultiVecInfo.RegVT, Value, i * RegElts));
7993
7994 Ops.push_back(PNg);
7995 Ops.push_back(StoreNode->getBasePtr());
7996
7997 return DAG.getMemIntrinsicNode(
7998 ISD::INTRINSIC_VOID, DL, DAG.getVTList(MVT::Other), Ops,
7999 StoreNode->getMemoryVT(), StoreNode->getMemOperand());
8000}
8001
8004 SelectionDAG &DAG) {
8005 EVT VT = LoadNode->getValueType(0);
8006
8007 if (!isSimpleScalableLoadOrStore(LoadNode, VT))
8008 return false;
8009
8010 MVT LoadVT = VT.getSimpleVT();
8011 SVEMultiVectorInfo MultiVecInfo = getSVEMultiVectorInfo(LoadVT);
8012
8013 SDLoc DL(LoadNode);
8014 SDValue PNg = getPTrueAsCounter(DAG, DL, VT);
8015
8016 SmallVector<EVT, 5> ResultVTs(MultiVecInfo.NumVecs, MultiVecInfo.RegVT);
8017 ResultVTs.push_back(MVT::Other);
8018
8019 SDValue NewLoad =
8020 DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, ResultVTs,
8021 {LoadNode->getChain(),
8022 DAG.getConstant(MultiVecInfo.LoadIntID, DL, MVT::i64), PNg,
8023 LoadNode->getBasePtr()});
8024
8025 SmallVector<SDValue, 4> ResultOps;
8026 for (unsigned I = 0; I != MultiVecInfo.NumVecs; ++I)
8027 ResultOps.push_back(NewLoad.getValue(I));
8028 Results.push_back(DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, ResultOps));
8029 Results.push_back(NewLoad.getValue(MultiVecInfo.NumVecs) /* Chain */);
8030 return true;
8031}
8032
8033// Custom lowering for any store, vector or scalar and/or default or with
8034// a truncate operations. Currently only custom lower truncate operation
8035// from vector v4i16 to v4i8 or volatile stores of i128.
8036SDValue AArch64TargetLowering::LowerSTORE(SDValue Op,
8037 SelectionDAG &DAG) const {
8038 SDLoc Dl(Op);
8039 StoreSDNode *StoreNode = cast<StoreSDNode>(Op);
8040 assert (StoreNode && "Can only custom lower store nodes");
8041
8042 SDValue Value = StoreNode->getValue();
8043
8044 EVT VT = Value.getValueType();
8045 EVT MemVT = StoreNode->getMemoryVT();
8046
8047 if (StoreNode->isNonTemporal()) {
8048 if (auto MaybeSTNP = LowerNTStore(StoreNode, VT, MemVT, Dl, DAG))
8049 return MaybeSTNP;
8050 }
8051
8052 if (VT.isVector()) {
8053 if (SDValue Store = tryLowerMultiVectorStore(StoreNode, DAG))
8054 return Store;
8055
8057 VT,
8058 /*OverrideNEON=*/Subtarget->useSVEForFixedLengthVectors()))
8059 return LowerFixedLengthVectorStoreToSVE(Op, DAG);
8060
8061 unsigned AS = StoreNode->getAddressSpace();
8062 Align Alignment = StoreNode->getAlign();
8063 if (Alignment < MemVT.getStoreSize() &&
8064 !allowsMisalignedMemoryAccesses(MemVT, AS, Alignment,
8065 StoreNode->getMemOperand()->getFlags(),
8066 nullptr)) {
8067 return scalarizeVectorStore(StoreNode, DAG);
8068 }
8069
8070 if (StoreNode->isTruncatingStore() && VT == MVT::v4i16 &&
8071 MemVT == MVT::v4i8) {
8072 return LowerTruncateVectorStore(Dl, StoreNode, VT, MemVT, DAG);
8073 }
8074 } else if (MemVT == MVT::i128 && StoreNode->isVolatile()) {
8075 return LowerStore128(Op, DAG);
8076 } else if (MemVT == MVT::i64x8) {
8077 SDValue Value = StoreNode->getValue();
8078 assert(Value->getValueType(0) == MVT::i64x8);
8079 SDValue Chain = StoreNode->getChain();
8080 SDValue Base = StoreNode->getBasePtr();
8081 EVT PtrVT = Base.getValueType();
8082 for (unsigned i = 0; i < 8; i++) {
8083 SDValue Part = DAG.getNode(AArch64ISD::LS64_EXTRACT, Dl, MVT::i64, Value,
8084 DAG.getConstant(i, Dl, MVT::i32));
8085 SDValue Ptr = DAG.getNode(ISD::ADD, Dl, PtrVT, Base,
8086 DAG.getConstant(i * 8, Dl, PtrVT));
8087 Chain = DAG.getStore(Chain, Dl, Part, Ptr, StoreNode->getPointerInfo(),
8088 StoreNode->getBaseAlign());
8089 }
8090 return Chain;
8091 }
8092
8093 return SDValue();
8094}
8095
8096/// Lower atomic or volatile 128-bit stores to a single STP instruction.
8097SDValue AArch64TargetLowering::LowerStore128(SDValue Op,
8098 SelectionDAG &DAG) const {
8099 MemSDNode *StoreNode = cast<MemSDNode>(Op);
8100 assert(StoreNode->getMemoryVT() == MVT::i128);
8101 assert(StoreNode->isVolatile() || StoreNode->isAtomic());
8102
8103 bool IsStoreRelease =
8105 if (StoreNode->isAtomic())
8106 assert((Subtarget->hasFeature(AArch64::FeatureLSE2) &&
8107 Subtarget->hasFeature(AArch64::FeatureRCPC3) && IsStoreRelease) ||
8110
8111 SDValue Value = (StoreNode->getOpcode() == ISD::STORE ||
8112 StoreNode->getOpcode() == ISD::ATOMIC_STORE)
8113 ? StoreNode->getOperand(1)
8114 : StoreNode->getOperand(2);
8115 SDLoc DL(Op);
8116 auto StoreValue = DAG.SplitScalar(Value, DL, MVT::i64, MVT::i64);
8117 unsigned Opcode = IsStoreRelease ? AArch64ISD::STILP : AArch64ISD::STP;
8118 if (DAG.getDataLayout().isBigEndian())
8119 std::swap(StoreValue.first, StoreValue.second);
8121 Opcode, DL, DAG.getVTList(MVT::Other),
8122 {StoreNode->getChain(), StoreValue.first, StoreValue.second,
8123 StoreNode->getBasePtr()},
8124 StoreNode->getMemoryVT(), StoreNode->getMemOperand());
8125 return Result;
8126}
8127
8128/// Helper function to optimize loads of extended small vectors.
8129/// These patterns would otherwise get scalarized into inefficient sequences.
8131 const AArch64Subtarget &Subtarget = DAG.getSubtarget<AArch64Subtarget>();
8132 if (!isEligibleForSmallVectorLoadOpt(Load, Subtarget))
8133 return SDValue();
8134
8135 EVT MemVT = Load->getMemoryVT();
8136 EVT ResVT = Load->getValueType(0);
8137 unsigned NumElts = ResVT.getVectorNumElements();
8138 unsigned DstEltBits = ResVT.getScalarSizeInBits();
8139 unsigned SrcEltBits = MemVT.getScalarSizeInBits();
8140
8141 unsigned ExtOpcode;
8142 switch (Load->getExtensionType()) {
8143 case ISD::EXTLOAD:
8144 case ISD::ZEXTLOAD:
8145 ExtOpcode = ISD::ZERO_EXTEND;
8146 break;
8147 case ISD::SEXTLOAD:
8148 ExtOpcode = ISD::SIGN_EXTEND;
8149 break;
8150 case ISD::NON_EXTLOAD:
8151 return SDValue();
8152 }
8153
8154 SDLoc DL(Load);
8155 SDValue Chain = Load->getChain();
8156 SDValue BasePtr = Load->getBasePtr();
8157 const MachinePointerInfo &PtrInfo = Load->getPointerInfo();
8158 Align Alignment = Load->getAlign();
8159
8160 // Load the data as an FP scalar to avoid issues with integer loads.
8161 unsigned LoadBits = MemVT.getStoreSizeInBits();
8162 MVT ScalarLoadType = MVT::getFloatingPointVT(LoadBits);
8163 SDValue ScalarLoad =
8164 DAG.getLoad(ScalarLoadType, DL, Chain, BasePtr, PtrInfo, Alignment);
8165
8166 MVT ScalarToVecTy = MVT::getVectorVT(ScalarLoadType, 128 / LoadBits);
8167 SDValue ScalarToVec =
8168 DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, ScalarToVecTy, ScalarLoad);
8169 MVT BitcastTy =
8170 MVT::getVectorVT(MVT::getIntegerVT(SrcEltBits), 128 / SrcEltBits);
8171 SDValue Bitcast = DAG.getNode(ISD::BITCAST, DL, BitcastTy, ScalarToVec);
8172
8173 SDValue Res = Bitcast;
8174 unsigned CurrentEltBits = Res.getValueType().getScalarSizeInBits();
8175 unsigned CurrentNumElts = Res.getValueType().getVectorNumElements();
8176 while (CurrentEltBits < DstEltBits) {
8177 if (Res.getValueSizeInBits() >= 128) {
8178 CurrentNumElts = CurrentNumElts / 2;
8179 MVT ExtractVT =
8180 MVT::getVectorVT(MVT::getIntegerVT(CurrentEltBits), CurrentNumElts);
8181 Res = DAG.getExtractSubvector(DL, ExtractVT, Res, 0);
8182 }
8183 CurrentEltBits = CurrentEltBits * 2;
8184 MVT ExtVT =
8185 MVT::getVectorVT(MVT::getIntegerVT(CurrentEltBits), CurrentNumElts);
8186 Res = DAG.getNode(ExtOpcode, DL, ExtVT, Res);
8187 }
8188
8189 if (CurrentNumElts != NumElts) {
8190 MVT FinalVT = MVT::getVectorVT(MVT::getIntegerVT(CurrentEltBits), NumElts);
8191 Res = DAG.getExtractSubvector(DL, FinalVT, Res, 0);
8192 }
8193
8194 return DAG.getMergeValues({Res, ScalarLoad.getValue(1)}, DL);
8195}
8196
8197SDValue AArch64TargetLowering::LowerLOAD(SDValue Op,
8198 SelectionDAG &DAG) const {
8199 SDLoc DL(Op);
8200 LoadSDNode *LoadNode = cast<LoadSDNode>(Op);
8201 assert(LoadNode && "Expected custom lowering of a load node");
8202
8203 // Extending loads of v2i8 -> v2i32/v2i64 are better lowered using SVE's
8204 // extending load instructions as they otherwise require 2 or 3 instructions
8205 // to promote.
8206 bool OverrideNeon = !Subtarget->isNeonAvailable() ||
8207 cast<LoadSDNode>(Op)->getMemoryVT() == MVT::v2i8;
8208 if (useSVEForFixedLengthVectorVT(Op.getValueType(), OverrideNeon))
8209 return LowerFixedLengthVectorLoadToSVE(Op, DAG);
8210
8211 if (SDValue Result = tryLowerSmallVectorExtLoad(LoadNode, DAG))
8212 return Result;
8213
8214 if (LoadNode->getMemoryVT() == MVT::i64x8) {
8216 SDValue Base = LoadNode->getBasePtr();
8217 SDValue Chain = LoadNode->getChain();
8218 EVT PtrVT = Base.getValueType();
8219 for (unsigned i = 0; i < 8; i++) {
8220 SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Base,
8221 DAG.getConstant(i * 8, DL, PtrVT));
8222 SDValue Part =
8223 DAG.getLoad(MVT::i64, DL, Chain, Ptr, LoadNode->getPointerInfo(),
8224 LoadNode->getBaseAlign());
8225 Ops.push_back(Part);
8226 Chain = SDValue(Part.getNode(), 1);
8227 }
8228 SDValue Loaded = DAG.getNode(AArch64ISD::LS64_BUILD, DL, MVT::i64x8, Ops);
8229 return DAG.getMergeValues({Loaded, Chain}, DL);
8230 }
8231
8232 return SDValue();
8233}
8234
8235SDValue AArch64TargetLowering::LowerFixedLengthVectorCompressToSVE(
8236 SDValue Op, SelectionDAG &DAG) const {
8237 SDLoc DL(Op);
8238 EVT VT = Op.getValueType();
8239
8240 EVT ContainerVT = getContainerForFixedLengthVector(DAG, VT);
8241 SDValue Vec = convertToScalableVector(DAG, ContainerVT, Op.getOperand(0));
8242 SDValue Mask = convertFixedMaskToScalableVector(Op.getOperand(1), DAG);
8243 SDValue Passthru =
8244 convertToScalableVector(DAG, ContainerVT, Op.getOperand(2));
8245
8246 SDValue Result =
8247 DAG.getNode(ISD::VECTOR_COMPRESS, DL, ContainerVT, Vec, Mask, Passthru);
8248 return convertFromScalableVector(DAG, VT, Result);
8249}
8250
8251SDValue AArch64TargetLowering::LowerVECTOR_COMPRESS(SDValue Op,
8252 SelectionDAG &DAG) const {
8253 EVT VT = Op.getValueType();
8254 if (VT.isFixedLengthVector())
8255 return LowerFixedLengthVectorCompressToSVE(Op, DAG);
8256
8257 SDLoc DL(Op);
8258 SDValue Vec = Op.getOperand(0);
8259 SDValue Mask = Op.getOperand(1);
8260 SDValue Passthru = Op.getOperand(2);
8261 EVT MaskVT = Mask.getValueType();
8262
8263 SDValue Compressed = DAG.getNode(
8265 DAG.getTargetConstant(Intrinsic::aarch64_sve_compact, DL, MVT::i64), Mask,
8266 Vec);
8267
8268 // compact fills with 0s, so if our passthru is all 0s, do nothing here.
8269 if (Passthru.isUndef() ||
8271 return Compressed;
8272
8273 SDValue CntActive = DAG.getNode(
8274 ISD::INTRINSIC_WO_CHAIN, DL, MVT::i64,
8275 DAG.getTargetConstant(Intrinsic::aarch64_sve_cntp, DL, MVT::i64), Mask,
8276 Mask);
8277
8278 SDValue Zero = DAG.getConstant(0, DL, MVT::i64);
8279 SDValue CompressedMask =
8280 DAG.getNode(ISD::GET_ACTIVE_LANE_MASK, DL, MaskVT, Zero, CntActive);
8281
8282 return DAG.getNode(ISD::VSELECT, DL, VT, CompressedMask, Compressed,
8283 Passthru);
8284}
8285
8286SDValue AArch64TargetLowering::LowerSMULFIXSAT(SDValue Op,
8287 SelectionDAG &DAG) const {
8288 EVT VT = Op.getValueType();
8289 assert((VT == MVT::v4i16 || VT == MVT::v8i16 || VT == MVT::v2i32 ||
8290 VT == MVT::v4i32) &&
8291 "Unexpected type for SMULFIXSAT lowering");
8292
8293 unsigned Scale = Op.getConstantOperandVal(2);
8294 if (Scale != VT.getScalarSizeInBits() - 1)
8295 return SDValue();
8296
8297 return DAG.getNode(AArch64ISD::SQDMULH, SDLoc(Op), VT, Op.getOperand(0),
8298 Op.getOperand(1));
8299}
8300
8301// Generate SUBS and CSEL for integer abs.
8302SDValue AArch64TargetLowering::LowerABS(SDValue Op, SelectionDAG &DAG) const {
8303 MVT VT = Op.getSimpleValueType();
8304
8305 if (VT.isVector())
8306 return LowerToPredicatedOp(Op, DAG, AArch64ISD::ABS_MERGE_PASSTHRU);
8307
8308 SDLoc DL(Op);
8309 SDValue Neg = DAG.getNegative(Op.getOperand(0), DL, VT);
8310
8311 // Generate SUBS & CSEL.
8312 SDValue Cmp = DAG.getNode(AArch64ISD::SUBS, DL, DAG.getVTList(VT, FlagsVT),
8313 Op.getOperand(0), DAG.getConstant(0, DL, VT));
8314 return DAG.getNode(AArch64ISD::CSEL, DL, VT, Op.getOperand(0), Neg,
8315 getCondCode(DAG, AArch64CC::PL), Cmp.getValue(1));
8316}
8317
8319 SDValue Chain = Op.getOperand(0);
8320 SDValue Cond = Op.getOperand(1);
8321 SDValue Dest = Op.getOperand(2);
8322
8324 if (SDValue Cmp = emitConjunction(DAG, Cond, CC)) {
8325 SDLoc DL(Op);
8326 SDValue CCVal = getCondCode(DAG, CC);
8327 return DAG.getNode(AArch64ISD::BRCOND, DL, MVT::Other, Chain, Dest, CCVal,
8328 Cmp);
8329 }
8330
8331 return SDValue();
8332}
8333
8334// Treat FSHR with constant shifts as legal operation, otherwise it is expanded
8335// FSHL is converted to FSHR before deciding what to do with it
8337 SDValue Shifts = Op.getOperand(2);
8338 // Check if the shift amount is a constant and normalise to [0, SrcBitLen)
8339 // If opcode is FSHL, convert it to FSHR
8340 if (auto *ShiftNo = dyn_cast<ConstantSDNode>(Shifts)) {
8341 SDLoc DL(Op);
8342 MVT VT = Op.getSimpleValueType();
8343 unsigned int NewShiftNo = ShiftNo->getZExtValue() % VT.getFixedSizeInBits();
8344
8345 if (Op.getOpcode() == ISD::FSHL) {
8346 if (NewShiftNo == 0)
8347 return Op.getOperand(0);
8348
8349 NewShiftNo = VT.getFixedSizeInBits() - NewShiftNo;
8350 return DAG.getNode(
8351 ISD::FSHR, DL, VT, Op.getOperand(0), Op.getOperand(1),
8352 DAG.getConstant(NewShiftNo, DL, Shifts.getValueType()));
8353 }
8354
8355 if (Op.getOpcode() == ISD::FSHR) {
8356 if (NewShiftNo == 0)
8357 return Op.getOperand(1);
8358
8359 if (ShiftNo->getZExtValue() == NewShiftNo)
8360 return Op;
8361
8362 // Rewrite using the normalised shift amount.
8363 return DAG.getNode(
8364 ISD::FSHR, DL, VT, Op.getOperand(0), Op.getOperand(1),
8365 DAG.getConstant(NewShiftNo, DL, Shifts.getValueType()));
8366 }
8367 }
8368
8369 return SDValue();
8370}
8371
8373 SDValue X = Op.getOperand(0);
8374 EVT XScalarTy = X.getValueType();
8375 SDValue Exp = Op.getOperand(1);
8376
8377 SDLoc DL(Op);
8378 EVT XVT, ExpVT;
8379 switch (Op.getSimpleValueType().SimpleTy) {
8380 default:
8381 return SDValue();
8382 case MVT::bf16:
8383 case MVT::f16:
8384 X = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, X);
8385 [[fallthrough]];
8386 case MVT::f32:
8387 XVT = MVT::nxv4f32;
8388 ExpVT = MVT::nxv4i32;
8389 break;
8390 case MVT::f64:
8391 XVT = MVT::nxv2f64;
8392 ExpVT = MVT::nxv2i64;
8393 Exp = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, Exp);
8394 break;
8395 }
8396
8397 SDValue Zero = DAG.getConstant(0, DL, MVT::i64);
8398 SDValue VX =
8399 DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, XVT, DAG.getPOISON(XVT), X, Zero);
8400 SDValue VExp = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, ExpVT,
8401 DAG.getPOISON(ExpVT), Exp, Zero);
8402 SDValue VPg = DAG.getConstant(
8403 1, DL, XVT.changeVectorElementType(*DAG.getContext(), MVT::i1));
8404 SDValue FScale = DAG.getNode(
8406 DAG.getTargetConstant(Intrinsic::aarch64_sve_fscale, DL, MVT::i64), VPg,
8407 VX, VExp);
8408 SDValue Final =
8409 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, X.getValueType(), FScale, Zero);
8410 if (X.getValueType() != XScalarTy)
8411 Final = DAG.getNode(ISD::FP_ROUND, DL, XScalarTy, Final,
8412 DAG.getIntPtrConstant(1, SDLoc(Op), /*isTarget=*/true));
8413 return Final;
8414}
8415
8416SDValue AArch64TargetLowering::LowerADJUST_TRAMPOLINE(SDValue Op,
8417 SelectionDAG &DAG) const {
8418 return Op.getOperand(0);
8419}
8420
8421SDValue AArch64TargetLowering::LowerINIT_TRAMPOLINE(SDValue Op,
8422 SelectionDAG &DAG) const {
8423 SDValue Chain = Op.getOperand(0);
8424 SDValue Trmp = Op.getOperand(1); // trampoline, >=32 bytes
8425 SDValue FPtr = Op.getOperand(2); // nested function
8426 SDValue Nest = Op.getOperand(3); // 'nest' parameter value
8427
8428 const Value *TrmpAddr = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
8429
8430 // ldr NestReg, .+16
8431 // ldr x17, .+20
8432 // br x17
8433 // .word 0
8434 // .nest: .qword nest
8435 // .fptr: .qword fptr
8436 SDValue OutChains[5];
8437
8438 const Function *Func =
8439 cast<Function>(cast<SrcValueSDNode>(Op.getOperand(5))->getValue());
8440 CallingConv::ID CC = Func->getCallingConv();
8441 unsigned NestReg;
8442
8443 switch (CC) {
8444 default:
8445 NestReg = 0x0f; // X15
8446 break;
8448 // Must be kept in sync with AArch64CallingConv.td
8449 NestReg = 0x04; // X4
8450 break;
8451 }
8452
8453 const char FptrReg = 0x11; // X17
8454
8455 SDValue Addr = Trmp;
8456
8457 SDLoc DL(Op);
8458 OutChains[0] = DAG.getStore(
8459 Chain, DL, DAG.getConstant(0x58000080u | NestReg, DL, MVT::i32), Addr,
8460 MachinePointerInfo(TrmpAddr));
8461
8462 Addr = DAG.getNode(ISD::ADD, DL, MVT::i64, Trmp,
8463 DAG.getConstant(4, DL, MVT::i64));
8464 OutChains[1] = DAG.getStore(
8465 Chain, DL, DAG.getConstant(0x580000b0u | FptrReg, DL, MVT::i32), Addr,
8466 MachinePointerInfo(TrmpAddr, 4));
8467
8468 Addr = DAG.getNode(ISD::ADD, DL, MVT::i64, Trmp,
8469 DAG.getConstant(8, DL, MVT::i64));
8470 OutChains[2] =
8471 DAG.getStore(Chain, DL, DAG.getConstant(0xd61f0220u, DL, MVT::i32), Addr,
8472 MachinePointerInfo(TrmpAddr, 8));
8473
8474 Addr = DAG.getNode(ISD::ADD, DL, MVT::i64, Trmp,
8475 DAG.getConstant(16, DL, MVT::i64));
8476 OutChains[3] =
8477 DAG.getStore(Chain, DL, Nest, Addr, MachinePointerInfo(TrmpAddr, 16));
8478
8479 Addr = DAG.getNode(ISD::ADD, DL, MVT::i64, Trmp,
8480 DAG.getConstant(24, DL, MVT::i64));
8481 OutChains[4] =
8482 DAG.getStore(Chain, DL, FPtr, Addr, MachinePointerInfo(TrmpAddr, 24));
8483
8484 SDValue StoreToken = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
8485
8486 SDValue EndOfTrmp = DAG.getNode(ISD::ADD, DL, MVT::i64, Trmp,
8487 DAG.getConstant(12, DL, MVT::i64));
8488
8489 // Call clear cache on the trampoline instructions.
8490 return DAG.getNode(ISD::CLEAR_CACHE, DL, MVT::Other, StoreToken, Trmp,
8491 EndOfTrmp);
8492}
8493
8494SDValue AArch64TargetLowering::LowerFMUL(SDValue Op, SelectionDAG &DAG) const {
8495 SDLoc DL(Op);
8496 EVT VT = Op.getValueType();
8497 if (VT.getScalarType() != MVT::bf16 ||
8498 (Subtarget->hasSVEB16B16() &&
8499 Subtarget->isNonStreamingSVEorSME2Available()))
8500 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FMUL_PRED);
8501
8502 assert(Subtarget->hasBF16() && "Expected +bf16 for custom FMUL lowering");
8503 assert((VT == MVT::nxv4bf16 || VT == MVT::nxv8bf16 || VT == MVT::v8bf16) &&
8504 "Unexpected FMUL VT");
8505
8506 auto MakeGetIntrinsic = [&](Intrinsic::ID IID) {
8507 return [&, IID](EVT VT, auto... Ops) {
8508 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT,
8509 DAG.getConstant(IID, DL, MVT::i32), Ops...);
8510 };
8511 };
8512
8513 auto Reinterpret = [&](SDValue Value, EVT VT) {
8514 EVT SrcVT = Value.getValueType();
8515 if (VT == SrcVT)
8516 return Value;
8517 if (SrcVT.isFixedLengthVector())
8518 return convertToScalableVector(DAG, VT, Value);
8519 if (VT.isFixedLengthVector())
8520 return convertFromScalableVector(DAG, VT, Value);
8521 return DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, VT, Value);
8522 };
8523
8524 bool UseSVEBFMLAL = VT.isScalableVector();
8525 auto FCVT = MakeGetIntrinsic(Intrinsic::aarch64_sve_fcvt_bf16f32_v2);
8526 auto FCVTNT = MakeGetIntrinsic(Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2);
8527
8528 // Note: The NEON BFMLAL[BT] reads even/odd lanes like the SVE variant.
8529 // This does not match BFCVTN[2], so we use SVE to convert back to bf16.
8530 auto BFMLALB =
8531 MakeGetIntrinsic(UseSVEBFMLAL ? Intrinsic::aarch64_sve_bfmlalb
8532 : Intrinsic::aarch64_neon_bfmlalb);
8533 auto BFMLALT =
8534 MakeGetIntrinsic(UseSVEBFMLAL ? Intrinsic::aarch64_sve_bfmlalt
8535 : Intrinsic::aarch64_neon_bfmlalt);
8536
8537 EVT AccVT = UseSVEBFMLAL ? MVT::nxv4f32 : MVT::v4f32;
8538 bool IgnoreZeroSign = DAG.canIgnoreSignBitOfZero(Op);
8539 SDValue Zero = DAG.getConstantFP(IgnoreZeroSign ? +0.0F : -0.0F, DL, AccVT);
8540 SDValue Pg = getPredicateForVector(DAG, DL, AccVT);
8541
8542 // Lower bf16 FMUL as a pair (VT == [nx]v8bf16) of BFMLAL top/bottom
8543 // instructions. These result in two f32 vectors, which can be converted back
8544 // to bf16 with FCVT and FCVTNT.
8545 SDValue LHS = Op.getOperand(0);
8546 SDValue RHS = Op.getOperand(1);
8547
8548 // All SVE intrinsics expect to operate on full bf16 vector types.
8549 if (UseSVEBFMLAL) {
8550 LHS = Reinterpret(LHS, MVT::nxv8bf16);
8551 RHS = Reinterpret(RHS, MVT::nxv8bf16);
8552 }
8553
8554 SDValue BottomF32 = Reinterpret(BFMLALB(AccVT, Zero, LHS, RHS), MVT::nxv4f32);
8555 SDValue BottomBF16 =
8556 FCVT(MVT::nxv8bf16, DAG.getPOISON(MVT::nxv8bf16), Pg, BottomF32);
8557 // Note: nxv4bf16 only uses even lanes.
8558 if (VT == MVT::nxv4bf16)
8559 return Reinterpret(BottomBF16, VT);
8560
8561 SDValue TopF32 = Reinterpret(BFMLALT(AccVT, Zero, LHS, RHS), MVT::nxv4f32);
8562 SDValue TopBF16 = FCVTNT(MVT::nxv8bf16, BottomBF16, Pg, TopF32);
8563 return Reinterpret(TopBF16, VT);
8564}
8565
8566SDValue AArch64TargetLowering::LowerFMA(SDValue Op, SelectionDAG &DAG) const {
8567 SDValue OpA = Op->getOperand(0);
8568 SDValue OpB = Op->getOperand(1);
8569 SDValue OpC = Op->getOperand(2);
8570 EVT VT = Op.getValueType();
8571 SDLoc DL(Op);
8572
8573 assert(VT.isVector() && "Scalar fma lowering should be handled by patterns");
8574
8575 // Bail early if we're definitely not looking to merge FNEGs into the FMA.
8576 if (VT != MVT::v8f16 && VT != MVT::v4f32 && VT != MVT::v2f64)
8577 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FMA_PRED);
8578
8579 if (OpC.getOpcode() != ISD::FNEG)
8580 return useSVEForFixedLengthVectorVT(VT, !Subtarget->isNeonAvailable())
8581 ? LowerToPredicatedOp(Op, DAG, AArch64ISD::FMA_PRED)
8582 : Op; // Fallback to NEON lowering.
8583
8584 // Convert FMA/FNEG nodes to SVE to enable the following patterns:
8585 // fma(a, b, neg(c)) -> fnmls(a, b, c)
8586 // fma(neg(a), b, neg(c)) -> fnmla(a, b, c)
8587 // fma(a, neg(b), neg(c)) -> fnmla(a, b, c)
8588 SDValue Pg = getPredicateForVector(DAG, DL, VT);
8589 EVT ContainerVT = getContainerForFixedLengthVector(DAG, VT);
8590
8591 auto ConvertToScalableFnegMt = [&](SDValue Op) {
8592 if (Op.getOpcode() == ISD::FNEG)
8593 Op = LowerToPredicatedOp(Op, DAG, AArch64ISD::FNEG_MERGE_PASSTHRU);
8594 return convertToScalableVector(DAG, ContainerVT, Op);
8595 };
8596
8597 OpA = ConvertToScalableFnegMt(OpA);
8598 OpB = ConvertToScalableFnegMt(OpB);
8599 OpC = ConvertToScalableFnegMt(OpC);
8600
8601 SDValue ScalableRes =
8602 DAG.getNode(AArch64ISD::FMA_PRED, DL, ContainerVT, Pg, OpA, OpB, OpC);
8603 return convertFromScalableVector(DAG, VT, ScalableRes);
8604}
8605
8606// clmul.Tb(a, b) = xor(pmullb(a_lo, b_lo),
8607// lsl(xor(clmul(a_hi, b_lo),
8608// clmul(a_lo, b_hi)),
8609// sizeof(Tb/2)))
8610// Form adjacent byte pairs {a_hi, b_hi} and {b_lo, a_lo}. CLMUL then
8611// computes {a_hi * b_lo, b_hi * a_lo}, and EORBT xors those pairs.
8613 SelectionDAG &DAG, EVT VT) {
8614 SDValue LoBytes = DAG.getNode(AArch64ISD::TRN1, DL, VT, OpB, OpA);
8615 SDValue HiBytes = DAG.getNode(AArch64ISD::TRN2, DL, VT, OpA, OpB);
8616 SDValue CLMUL = DAG.getNode(ISD::CLMUL, DL, VT, HiBytes, LoBytes);
8617
8618 SDValue EORBT =
8619 DAG.getTargetConstant(Intrinsic::aarch64_sve_eorbt, DL, MVT::i64);
8620 EORBT =
8621 DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, EORBT, CLMUL, CLMUL, CLMUL);
8622
8623 SDValue PMULLB =
8624 DAG.getTargetConstant(Intrinsic::aarch64_sve_pmullb_pair, DL, MVT::i64);
8625 PMULLB = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, PMULLB, OpA, OpB);
8626
8627 SDValue EORTB =
8628 DAG.getTargetConstant(Intrinsic::aarch64_sve_eortb, DL, MVT::i64);
8629 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, EORTB, PMULLB, PMULLB,
8630 EORBT);
8631}
8632
8633SDValue AArch64TargetLowering::LowerCLMUL(SDValue Op, SelectionDAG &DAG) const {
8634 EVT VT = Op.getValueType();
8635 SDLoc DL(Op);
8636 assert((VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8 ||
8637 VT == MVT::v4i32 || VT == MVT::nxv8i16 || VT == MVT::nxv2i64) &&
8638 "Unexpected Type");
8639 uint64_t ScalarSize = VT.getScalarSizeInBits();
8640 APInt HiWordMask = APInt::getBitsSet(ScalarSize, ScalarSize / 2, ScalarSize);
8641
8642 if (VT == MVT::v4i32) {
8643 SDValue LoA = DAG.getExtractSubvector(DL, MVT::v2i32, Op.getOperand(0), 0);
8644 SDValue LoB = DAG.getExtractSubvector(DL, MVT::v2i32, Op.getOperand(1), 0);
8645 SDValue HiA = DAG.getExtractSubvector(DL, MVT::v2i32, Op.getOperand(0), 2);
8646 SDValue HiB = DAG.getExtractSubvector(DL, MVT::v2i32, Op.getOperand(1), 2);
8647 SDValue LoCLMUL = DAG.getNode(ISD::CLMUL, DL, MVT::v2i32, LoA, LoB);
8648 SDValue HiCLMUL = DAG.getNode(ISD::CLMUL, DL, MVT::v2i32, HiA, HiB);
8649 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, LoCLMUL, HiCLMUL);
8650 }
8651
8652 if (VT == MVT::nxv2i64) {
8653 SDValue OpA =
8654 DAG.getNode(AArch64ISD::NVCAST, DL, MVT::nxv4i32, Op.getOperand(0));
8655 SDValue OpB =
8656 DAG.getNode(AArch64ISD::NVCAST, DL, MVT::nxv4i32, Op.getOperand(1));
8657
8658 // Lower to (.d pmullb(.s, .s)) for clmul.nxv2i64(zext(nxv2i32),
8659 // zext(nxv2i32))
8660 if ((Subtarget->hasSVE2() || Subtarget->hasSME()) &&
8661 DAG.MaskedValueIsZero(Op.getOperand(0), HiWordMask) &&
8662 DAG.MaskedValueIsZero(Op.getOperand(1), HiWordMask)) {
8663 SDValue PMULLB = DAG.getTargetConstant(Intrinsic::aarch64_sve_pmullb_pair,
8664 DL, MVT::i64);
8665 PMULLB = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::nxv4i32, PMULLB,
8666 OpA, OpB);
8667 return DAG.getNode(AArch64ISD::NVCAST, DL, VT, PMULLB);
8668 }
8669 // Lower to (.q pmullb(.d, .d)) for clmul.nxv2i64(nxv2i64, nxv2i64)
8670 if (Subtarget->hasSVEAES() &&
8671 (Subtarget->isSVEAvailable() || Subtarget->hasSSVE_AES()))
8672 return Op;
8673
8674 if (Subtarget->hasSVE2() || Subtarget->hasSME()) {
8675 SDValue CrossCLMUL = DoCrossByteCLMUL(OpA, OpB, DL, DAG, MVT::nxv4i32);
8676 return DAG.getNode(AArch64ISD::NVCAST, DL, VT, CrossCLMUL);
8677 }
8678
8679 return SDValue();
8680 }
8681
8682 if (VT == MVT::nxv8i16) {
8683 SDValue OpA =
8684 DAG.getNode(AArch64ISD::NVCAST, DL, MVT::nxv16i8, Op.getOperand(0));
8685 SDValue OpB =
8686 DAG.getNode(AArch64ISD::NVCAST, DL, MVT::nxv16i8, Op.getOperand(1));
8687
8688 // Lower to (.h pmullb(.b, .b)) for clmul.nxv8i16(zext(nxv8i8),
8689 // zext(nxv8i8))
8690 if (DAG.MaskedValueIsZero(Op.getOperand(0), HiWordMask) &&
8691 DAG.MaskedValueIsZero(Op.getOperand(1), HiWordMask)) {
8692 SDValue PMULLB = DAG.getTargetConstant(Intrinsic::aarch64_sve_pmullb_pair,
8693 DL, MVT::i64);
8694 PMULLB = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::nxv16i8, PMULLB,
8695 OpA, OpB);
8696 return DAG.getNode(AArch64ISD::NVCAST, DL, VT, PMULLB);
8697 }
8698
8699 SDValue CrossCLMUL = DoCrossByteCLMUL(OpA, OpB, DL, DAG, MVT::nxv16i8);
8700 return DAG.getNode(AArch64ISD::NVCAST, DL, VT, CrossCLMUL);
8701 }
8702
8703 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), VT, 64 / VT.getSizeInBits());
8704 EVT CLMULTy = VT == MVT::i8 ? MVT::v8i8 : MVT::v1i64;
8705 EVT ExtractTy = VT == MVT::i64 ? MVT::i64 : MVT::i32;
8706 SDValue VecOp0 =
8707 DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VecVT, Op.getOperand(0));
8708 SDValue VecOp1 =
8709 DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VecVT, Op.getOperand(1));
8710
8711 if (VecVT != CLMULTy) {
8712 VecOp0 = DAG.getNode(ISD::BITCAST, DL, CLMULTy, VecOp0);
8713 VecOp1 = DAG.getNode(ISD::BITCAST, DL, CLMULTy, VecOp1);
8714 }
8715 SDValue CLMUL = DAG.getNode(ISD::CLMUL, DL, CLMULTy, VecOp0, VecOp1);
8716 if (ExtractTy == MVT::i32)
8717 CLMUL = DAG.getNode(ISD::BITCAST, DL, MVT::v2i32, CLMUL);
8718 SDValue ExtractVecElt =
8719 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, ExtractTy, CLMUL,
8720 DAG.getTargetConstant(0, DL, MVT::i64));
8721 if (ExtractTy != VT)
8722 ExtractVecElt = DAG.getNode(ISD::TRUNCATE, DL, VT, ExtractVecElt);
8723 return ExtractVecElt;
8724}
8725
8727 SelectionDAG &DAG) const {
8728 LLVM_DEBUG(dbgs() << "Custom lowering: ");
8729 LLVM_DEBUG(Op.dump());
8730
8731 switch (Op.getOpcode()) {
8732 default:
8733 llvm_unreachable("unimplemented operand");
8734 return SDValue();
8737 return LowerLOOP_DEPENDENCE_MASK(Op, DAG);
8738 case ISD::BITCAST:
8739 return LowerBITCAST(Op, DAG);
8740 case ISD::GlobalAddress:
8741 return LowerGlobalAddress(Op, DAG);
8743 return LowerGlobalTLSAddress(Op, DAG);
8745 return LowerPtrAuthGlobalAddress(Op, DAG);
8747 return LowerADJUST_TRAMPOLINE(Op, DAG);
8749 return LowerINIT_TRAMPOLINE(Op, DAG);
8750 case ISD::SETCC:
8751 case ISD::STRICT_FSETCC:
8753 return LowerSETCC(Op, DAG);
8754 case ISD::SETCCCARRY:
8755 return LowerSETCCCARRY(Op, DAG);
8756 case ISD::BRCOND:
8757 return LowerBRCOND(Op, DAG);
8758 case ISD::BR_CC:
8759 return LowerBR_CC(Op, DAG);
8760 case ISD::SELECT:
8761 return LowerSELECT(Op, DAG);
8762 case ISD::SELECT_CC:
8763 return LowerSELECT_CC(Op, DAG);
8764 case ISD::JumpTable:
8765 return LowerJumpTable(Op, DAG);
8766 case ISD::BR_JT:
8767 return LowerBR_JT(Op, DAG);
8768 case ISD::BRIND:
8769 return LowerBRIND(Op, DAG);
8770 case ISD::ConstantPool:
8771 return LowerConstantPool(Op, DAG);
8772 case ISD::BlockAddress:
8773 return LowerBlockAddress(Op, DAG);
8774 case ISD::VASTART:
8775 return LowerVASTART(Op, DAG);
8776 case ISD::VACOPY:
8777 return LowerVACOPY(Op, DAG);
8778 case ISD::VAARG:
8779 return LowerVAARG(Op, DAG);
8780 case ISD::UADDO_CARRY:
8781 return lowerADDSUBO_CARRY(Op, DAG, AArch64ISD::ADCS, false /*unsigned*/);
8782 case ISD::USUBO_CARRY:
8783 return lowerADDSUBO_CARRY(Op, DAG, AArch64ISD::SBCS, false /*unsigned*/);
8784 case ISD::SADDO_CARRY:
8785 return lowerADDSUBO_CARRY(Op, DAG, AArch64ISD::ADCS, true /*signed*/);
8786 case ISD::SSUBO_CARRY:
8787 return lowerADDSUBO_CARRY(Op, DAG, AArch64ISD::SBCS, true /*signed*/);
8788 case ISD::SADDO:
8789 case ISD::UADDO:
8790 case ISD::SSUBO:
8791 case ISD::USUBO:
8792 case ISD::SMULO:
8793 case ISD::UMULO:
8794 return LowerXALUO(Op, DAG);
8795 case ISD::FADD:
8796 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FADD_PRED);
8797 case ISD::STRICT_FADD:
8798 return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FADD_PRED);
8799 case ISD::FSUB:
8800 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FSUB_PRED);
8801 case ISD::STRICT_FSUB:
8802 return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FSUB_PRED);
8803 case ISD::FMUL:
8804 return LowerFMUL(Op, DAG);
8805 case ISD::STRICT_FMUL:
8806 return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FMUL_PRED);
8807 case ISD::FMA:
8808 return LowerFMA(Op, DAG);
8809 case ISD::STRICT_FMA:
8810 return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FMA_PRED);
8811 case ISD::FDIV:
8812 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FDIV_PRED);
8813 case ISD::STRICT_FDIV:
8814 return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FDIV_PRED);
8815 case ISD::FNEG:
8816 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FNEG_MERGE_PASSTHRU);
8817 case ISD::FCEIL:
8818 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FCEIL_MERGE_PASSTHRU);
8819 case ISD::STRICT_FCEIL:
8820 return LowerToPredicatedOp(Op, DAG,
8821 AArch64ISD::STRICT_FCEIL_MERGE_PASSTHRU);
8822 case ISD::FFLOOR:
8823 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FFLOOR_MERGE_PASSTHRU);
8824 case ISD::STRICT_FFLOOR:
8825 return LowerToPredicatedOp(Op, DAG,
8826 AArch64ISD::STRICT_FFLOOR_MERGE_PASSTHRU);
8827 case ISD::FNEARBYINT:
8828 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FNEARBYINT_MERGE_PASSTHRU);
8830 return LowerToPredicatedOp(Op, DAG,
8831 AArch64ISD::STRICT_FNEARBYINT_MERGE_PASSTHRU);
8832 case ISD::FRINT:
8833 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FRINT_MERGE_PASSTHRU);
8834 case ISD::FROUND:
8835 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FROUND_MERGE_PASSTHRU);
8836 case ISD::STRICT_FROUND:
8837 return LowerToPredicatedOp(Op, DAG,
8838 AArch64ISD::STRICT_FROUND_MERGE_PASSTHRU);
8839 case ISD::FROUNDEVEN:
8840 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FROUNDEVEN_MERGE_PASSTHRU);
8842 return LowerToPredicatedOp(Op, DAG,
8843 AArch64ISD::STRICT_FROUNDEVEN_MERGE_PASSTHRU);
8844 case ISD::FTRUNC:
8845 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FTRUNC_MERGE_PASSTHRU);
8846 case ISD::STRICT_FTRUNC:
8847 return LowerToPredicatedOp(Op, DAG,
8848 AArch64ISD::STRICT_FTRUNC_MERGE_PASSTHRU);
8849 case ISD::FSQRT:
8850 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FSQRT_MERGE_PASSTHRU);
8851 case ISD::STRICT_FSQRT:
8852 return LowerToPredicatedOp(Op, DAG,
8853 AArch64ISD::STRICT_FSQRT_MERGE_PASSTHRU);
8854 case ISD::FABS:
8855 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FABS_MERGE_PASSTHRU);
8856 case ISD::FP_ROUND:
8858 return LowerFP_ROUND(Op, DAG);
8859 case ISD::FP_EXTEND:
8861 return LowerFP_EXTEND(Op, DAG);
8862 case ISD::FRAMEADDR:
8863 return LowerFRAMEADDR(Op, DAG);
8864 case ISD::SPONENTRY:
8865 return LowerSPONENTRY(Op, DAG);
8866 case ISD::RETURNADDR:
8867 return LowerRETURNADDR(Op, DAG);
8869 return LowerADDROFRETURNADDR(Op, DAG);
8871 return LowerCONCAT_VECTORS(Op, DAG);
8873 return LowerINSERT_VECTOR_ELT(Op, DAG);
8875 return LowerEXTRACT_VECTOR_ELT(Op, DAG);
8876 case ISD::BUILD_VECTOR:
8877 return LowerBUILD_VECTOR(Op, DAG);
8880 return LowerEXTEND_VECTOR_INREG(Op, DAG);
8882 return LowerZERO_EXTEND_VECTOR_INREG(Op, DAG);
8884 return LowerVECTOR_SHUFFLE(Op, DAG);
8885 case ISD::SPLAT_VECTOR:
8886 return LowerSPLAT_VECTOR(Op, DAG);
8888 return LowerEXTRACT_SUBVECTOR(Op, DAG);
8890 return LowerINSERT_SUBVECTOR(Op, DAG);
8891 case ISD::MASKED_SDIV:
8892 case ISD::MASKED_UDIV:
8893 case ISD::SDIV:
8894 case ISD::UDIV:
8895 return LowerDIV(Op, DAG);
8896 case ISD::SMIN:
8897 case ISD::UMIN:
8898 case ISD::SMAX:
8899 case ISD::UMAX:
8900 return LowerMinMax(Op, DAG);
8901 case ISD::SRA:
8902 case ISD::SRL:
8903 case ISD::SHL:
8904 return LowerVectorSRA_SRL_SHL(Op, DAG);
8905 case ISD::SHL_PARTS:
8906 case ISD::SRL_PARTS:
8907 case ISD::SRA_PARTS:
8908 return LowerShiftParts(Op, DAG);
8909 case ISD::CTPOP:
8910 case ISD::PARITY:
8911 return LowerCTPOP_PARITY(Op, DAG);
8912 case ISD::FCOPYSIGN:
8913 return LowerFCOPYSIGN(Op, DAG);
8914 case ISD::OR:
8915 return LowerVectorOR(Op, DAG);
8916 case ISD::XOR:
8917 return LowerXOR(Op, DAG);
8918 case ISD::PREFETCH:
8919 return LowerPREFETCH(Op, DAG);
8920 case ISD::SINT_TO_FP:
8921 case ISD::UINT_TO_FP:
8924 return LowerINT_TO_FP(Op, DAG);
8925 case ISD::FP_TO_SINT:
8926 case ISD::FP_TO_UINT:
8929 return LowerFP_TO_INT(Op, DAG);
8932 return LowerFP_TO_INT_SAT(Op, DAG);
8933 case ISD::GET_ROUNDING:
8934 return LowerGET_ROUNDING(Op, DAG);
8935 case ISD::SET_ROUNDING:
8936 return LowerSET_ROUNDING(Op, DAG);
8937 case ISD::GET_FPMODE:
8938 return LowerGET_FPMODE(Op, DAG);
8939 case ISD::SET_FPMODE:
8940 return LowerSET_FPMODE(Op, DAG);
8941 case ISD::RESET_FPMODE:
8942 return LowerRESET_FPMODE(Op, DAG);
8943 case ISD::MUL:
8944 return LowerMUL(Op, DAG);
8945 case ISD::MULHS:
8946 return LowerToPredicatedOp(Op, DAG, AArch64ISD::MULHS_PRED);
8947 case ISD::MULHU:
8948 return LowerToPredicatedOp(Op, DAG, AArch64ISD::MULHU_PRED);
8950 return LowerINTRINSIC_W_CHAIN(Op, DAG);
8952 return LowerINTRINSIC_WO_CHAIN(Op, DAG);
8954 return LowerINTRINSIC_VOID(Op, DAG);
8955 case ISD::ATOMIC_STORE:
8956 if (cast<MemSDNode>(Op)->getMemoryVT() == MVT::i128) {
8957 assert(Subtarget->hasLSE2() || Subtarget->hasRCPC3());
8958 return LowerStore128(Op, DAG);
8959 }
8960 return SDValue();
8961 case ISD::STORE:
8962 return LowerSTORE(Op, DAG);
8963 case ISD::MSTORE:
8964 return LowerMSTORE(Op, DAG);
8965 case ISD::MGATHER:
8966 return LowerMGATHER(Op, DAG);
8967 case ISD::MSCATTER:
8968 return LowerMSCATTER(Op, DAG);
8970 return LowerVECREDUCE_SEQ_FADD(Op, DAG);
8971 case ISD::VECREDUCE_ADD:
8972 case ISD::VECREDUCE_AND:
8973 case ISD::VECREDUCE_OR:
8974 case ISD::VECREDUCE_XOR:
8984 return LowerVECREDUCE(Op, DAG);
8985 case ISD::VECREDUCE_MUL:
8987 return LowerVECREDUCE_MUL(Op, DAG);
8989 return LowerATOMIC_LOAD_AND(Op, DAG);
8991 return LowerDYNAMIC_STACKALLOC(Op, DAG);
8992 case ISD::VSCALE:
8993 return LowerVSCALE(Op, DAG);
8995 return LowerVECTOR_COMPRESS(Op, DAG);
8996 case ISD::ANY_EXTEND:
8997 case ISD::SIGN_EXTEND:
8998 case ISD::ZERO_EXTEND:
8999 return LowerFixedLengthVectorIntExtendToSVE(Op, DAG);
9000 case ISD::ADDRSPACECAST:
9001 return LowerADDRSPACECAST(Op, DAG);
9003 // Only custom lower when ExtraVT has a legal byte based element type.
9004 EVT ExtraVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
9005 EVT ExtraEltVT = ExtraVT.getVectorElementType();
9006 if ((ExtraEltVT != MVT::i8) && (ExtraEltVT != MVT::i16) &&
9007 (ExtraEltVT != MVT::i32) && (ExtraEltVT != MVT::i64))
9008 return SDValue();
9009
9010 return LowerToPredicatedOp(Op, DAG,
9011 AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU);
9012 }
9013 case ISD::TRUNCATE:
9014 return LowerTRUNCATE(Op, DAG);
9015 case ISD::MLOAD:
9016 return LowerMLOAD(Op, DAG);
9017 case ISD::LOAD:
9018 return LowerLOAD(Op, DAG);
9019 case ISD::ADD:
9020 case ISD::AND:
9021 case ISD::SUB:
9022 return LowerToScalableOp(Op, DAG);
9023 case ISD::FMAXIMUM:
9024 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FMAX_PRED);
9026 return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FMAX_PRED);
9027 case ISD::FMAXNUM:
9028 case ISD::FMAXNUM_IEEE:
9029 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FMAXNM_PRED);
9031 return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FMAXNM_PRED);
9032 case ISD::FMINIMUM:
9033 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FMIN_PRED);
9035 return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FMIN_PRED);
9036 case ISD::FMINNUM:
9037 case ISD::FMINNUM_IEEE:
9038 return LowerToPredicatedOp(Op, DAG, AArch64ISD::FMINNM_PRED);
9040 return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FMINNM_PRED);
9041 case ISD::VSELECT:
9042 return LowerFixedLengthVectorSelectToSVE(Op, DAG);
9043 case ISD::ABS:
9044 return LowerABS(Op, DAG);
9045 case ISD::SMULFIXSAT:
9046 return LowerSMULFIXSAT(Op, DAG);
9047 case ISD::ABDS:
9048 return LowerToPredicatedOp(Op, DAG, AArch64ISD::ABDS_PRED);
9049 case ISD::ABDU:
9050 return LowerToPredicatedOp(Op, DAG, AArch64ISD::ABDU_PRED);
9051 case ISD::AVGFLOORS:
9052 return LowerAVG(Op, DAG, AArch64ISD::HADDS_PRED);
9053 case ISD::AVGFLOORU:
9054 return LowerAVG(Op, DAG, AArch64ISD::HADDU_PRED);
9055 case ISD::AVGCEILS:
9056 return LowerAVG(Op, DAG, AArch64ISD::RHADDS_PRED);
9057 case ISD::AVGCEILU:
9058 return LowerAVG(Op, DAG, AArch64ISD::RHADDU_PRED);
9059 case ISD::BITREVERSE:
9060 return LowerBitreverse(Op, DAG);
9061 case ISD::BSWAP:
9062 return LowerToPredicatedOp(Op, DAG, AArch64ISD::BSWAP_MERGE_PASSTHRU);
9063 case ISD::CTLZ:
9064 return LowerToPredicatedOp(Op, DAG, AArch64ISD::CTLZ_MERGE_PASSTHRU);
9065 case ISD::CTTZ:
9066 return LowerCTTZ(Op, DAG);
9069 return LowerVECTOR_SPLICE(Op, DAG);
9071 return LowerVECTOR_DEINTERLEAVE(Op, DAG);
9073 return LowerVECTOR_INTERLEAVE(Op, DAG);
9075 return LowerGET_ACTIVE_LANE_MASK(Op, DAG);
9076 case ISD::VECTOR_MATCH:
9077 return LowerVectorMatch(Op, DAG);
9078 case ISD::LRINT:
9079 case ISD::LLRINT:
9080 if (Op.getValueType().isVector())
9081 return LowerVectorXRINT(Op, DAG);
9082 [[fallthrough]];
9083 case ISD::LROUND:
9084 case ISD::LLROUND: {
9085 assert((Op.getOperand(0).getValueType() == MVT::f16 ||
9086 Op.getOperand(0).getValueType() == MVT::bf16) &&
9087 "Expected custom lowering of rounding operations only for f16");
9088 SDLoc DL(Op);
9089 SDValue Ext = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Op.getOperand(0));
9090 return DAG.getNode(Op.getOpcode(), DL, Op.getValueType(), Ext);
9091 }
9092 case ISD::STRICT_LROUND:
9094 case ISD::STRICT_LRINT:
9095 case ISD::STRICT_LLRINT: {
9096 assert((Op.getOperand(1).getValueType() == MVT::f16 ||
9097 Op.getOperand(1).getValueType() == MVT::bf16) &&
9098 "Expected custom lowering of rounding operations only for f16");
9099 SDLoc DL(Op);
9100 SDValue Ext = DAG.getNode(ISD::STRICT_FP_EXTEND, DL, {MVT::f32, MVT::Other},
9101 {Op.getOperand(0), Op.getOperand(1)});
9102 return DAG.getNode(Op.getOpcode(), DL, {Op.getValueType(), MVT::Other},
9103 {Ext.getValue(1), Ext.getValue(0)});
9104 }
9105 case ISD::WRITE_REGISTER: {
9106 assert(Op.getOperand(2).getValueType() == MVT::i128 &&
9107 "WRITE_REGISTER custom lowering is only for 128-bit sysregs");
9108 SDLoc DL(Op);
9109
9110 SDValue Chain = Op.getOperand(0);
9111 SDValue SysRegName = Op.getOperand(1);
9112 std::pair<SDValue, SDValue> Pair =
9113 DAG.SplitScalar(Op.getOperand(2), DL, MVT::i64, MVT::i64);
9114
9115 // chain = MSRR(chain, sysregname, lo, hi)
9116 SDValue Result = DAG.getNode(AArch64ISD::MSRR, DL, MVT::Other, Chain,
9117 SysRegName, Pair.first, Pair.second);
9118
9119 return Result;
9120 }
9121 case ISD::FSHL:
9122 case ISD::FSHR:
9123 return LowerFunnelShift(Op, DAG);
9124 case ISD::FLDEXP:
9125 return LowerFLDEXP(Op, DAG);
9127 return LowerVECTOR_HISTOGRAM(Op, DAG);
9132 return LowerPARTIAL_REDUCE_MLA(Op, DAG);
9133 case ISD::CLMUL:
9134 return LowerCLMUL(Op, DAG);
9135 case ISD::PEXT:
9136 case ISD::PDEP: {
9137 // Lower generic PEXT/PDEP to SVE2 intrinsics.
9138 SDLoc DL(Op);
9139 EVT VT = Op.getValueType();
9140 unsigned IntrID = Op.getOpcode() == ISD::PEXT
9141 ? Intrinsic::aarch64_sve_bext_x
9142 : Intrinsic::aarch64_sve_bdep_x;
9143
9144 if (VT.isScalarInteger()) {
9145 assert((VT == MVT::i32 || VT == MVT::i64) && "Unexpected scalar type");
9146 EVT SveVT = VT == MVT::i64 ? MVT::nxv2i64 : MVT::nxv4i32;
9147 SDValue Z0 =
9148 DAG.getInsertVectorElt(DL, DAG.getPOISON(SveVT), Op.getOperand(0), 0);
9149 SDValue Z1 =
9150 DAG.getInsertVectorElt(DL, DAG.getPOISON(SveVT), Op.getOperand(1), 0);
9151 SDValue R =
9153 DAG.getTargetConstant(IntrID, DL, MVT::i32), Z0, Z1);
9154 return DAG.getExtractVectorElt(DL, VT, R, 0);
9155 }
9156
9157 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT,
9158 DAG.getTargetConstant(IntrID, DL, MVT::i32),
9159 Op.getOperand(0), Op.getOperand(1));
9160 }
9161 case ISD::FCANONICALIZE:
9162 return LowerFCANONICALIZE(Op, DAG);
9163 case ISD::CTTZ_ELTS:
9165 SDLoc DL(Op);
9166 SDValue CttzOp = Op.getOperand(0);
9167 EVT VT = CttzOp.getValueType();
9168 assert(VT.getVectorElementType() == MVT::i1 && "Expected MVT::i1");
9169
9170 if (VT.isFixedLengthVector()) {
9171 // We can use SVE instructions to lower this intrinsic by first creating
9172 // an SVE predicate register mask from the fixed-width vector.
9173 VT = getTypeToTransformTo(*DAG.getContext(), VT);
9174 SDValue Mask = DAG.getNode(ISD::SIGN_EXTEND, DL, VT, CttzOp);
9175 CttzOp = convertFixedMaskToScalableVector(Mask, DAG);
9176 }
9177
9178 SDValue Pg = getPredicateForVector(DAG, DL, VT);
9179 SDValue NewCttzElts =
9180 DAG.getNode(AArch64ISD::CTTZ_ELTS, DL, MVT::i64, Pg, CttzOp);
9181 return DAG.getZExtOrTrunc(NewCttzElts, DL, Op.getValueType());
9182 }
9183 }
9184}
9185
9187 return !Subtarget->useSVEForFixedLengthVectors();
9188}
9189
9191 EVT VT, bool OverrideNEON) const {
9192 if (!VT.isFixedLengthVector() || !VT.isSimple())
9193 return false;
9194
9195 // Don't use SVE for vectors we cannot scalarize if required.
9196 switch (VT.getVectorElementType().getSimpleVT().SimpleTy) {
9197 // Fixed length predicates should be promoted to i8.
9198 // NOTE: This is consistent with how NEON (and thus 64/128bit vectors) work.
9199 case MVT::i1:
9200 default:
9201 return false;
9202 case MVT::bf16:
9204 return false;
9205 break;
9206 case MVT::i8:
9207 case MVT::i16:
9208 case MVT::i32:
9209 case MVT::i64:
9210 case MVT::f16:
9211 case MVT::f32:
9212 case MVT::f64:
9213 break;
9214 }
9215
9216 // NEON-sized vectors can be emulated using SVE instructions.
9217 if (OverrideNEON && (VT.is128BitVector() || VT.is64BitVector()))
9218 return Subtarget->isSVEorStreamingSVEAvailable();
9219
9220 // Ensure NEON MVTs only belong to a single register class.
9221 if (VT.getFixedSizeInBits() <= 128)
9222 return false;
9223
9224 // Ensure wider than NEON code generation is enabled.
9225 if (!Subtarget->useSVEForFixedLengthVectors())
9226 return false;
9227
9228 // Don't use SVE for types that don't fit.
9229 if (VT.getFixedSizeInBits() > Subtarget->getMinSVEVectorSizeInBits())
9230 return false;
9231
9232 // TODO: Perhaps an artificial restriction, but worth having whilst getting
9233 // the base fixed length SVE support in place.
9234 if (!VT.isPow2VectorType())
9235 return false;
9236
9237 return true;
9238}
9239
9240//===----------------------------------------------------------------------===//
9241// Calling Convention Implementation
9242//===----------------------------------------------------------------------===//
9243
9244static unsigned getIntrinsicID(const SDNode *N) {
9245 unsigned Opcode = N->getOpcode();
9246 switch (Opcode) {
9247 default:
9250 unsigned IID = N->getConstantOperandVal(0);
9251 if (IID < Intrinsic::num_intrinsics)
9252 return IID;
9254 }
9255 }
9256}
9257
9259 SDValue N1) const {
9260 if (!N0.hasOneUse())
9261 return false;
9262
9263 unsigned IID = getIntrinsicID(N1.getNode());
9264 // Avoid reassociating expressions that can be lowered to smlal/umlal.
9265 if (IID == Intrinsic::aarch64_neon_umull ||
9266 N1.getOpcode() == AArch64ISD::UMULL ||
9267 IID == Intrinsic::aarch64_neon_smull ||
9268 N1.getOpcode() == AArch64ISD::SMULL)
9269 return N0.getOpcode() != ISD::ADD;
9270
9271 return true;
9272}
9273
9274/// Selects the correct CCAssignFn for a given CallingConvention value.
9276 bool IsVarArg) const {
9277 switch (CC) {
9278 default:
9279 reportFatalUsageError("unsupported calling convention");
9280 case CallingConv::GHC:
9281 return CC_AArch64_GHC;
9283 // The VarArg implementation makes assumptions about register
9284 // argument passing that do not hold for preserve_none, so we
9285 // instead fall back to C argument passing.
9286 // The non-vararg case is handled in the CC function itself.
9287 if (!IsVarArg)
9289 [[fallthrough]];
9290 case CallingConv::C:
9291 case CallingConv::Fast:
9295 case CallingConv::Swift:
9297 case CallingConv::Tail:
9298 case CallingConv::GRAAL:
9299 if (Subtarget->isTargetWindows()) {
9300 if (IsVarArg) {
9301 if (Subtarget->isWindowsArm64EC())
9304 }
9305 return CC_AArch64_Win64PCS;
9306 }
9307 if (!Subtarget->isTargetDarwin())
9308 return CC_AArch64_AAPCS;
9309 if (!IsVarArg)
9310 return CC_AArch64_DarwinPCS;
9311 return Subtarget->isTargetILP32() ? CC_AArch64_DarwinPCS_ILP32_VarArg
9313 case CallingConv::Win64:
9314 if (IsVarArg) {
9315 if (Subtarget->isWindowsArm64EC())
9318 }
9319 return CC_AArch64_Win64PCS;
9321 if (Subtarget->isWindowsArm64EC())
9329 return CC_AArch64_AAPCS;
9334 }
9335}
9336
9337CCAssignFn *
9339 switch (CC) {
9340 default:
9341 return RetCC_AArch64_AAPCS;
9345 if (Subtarget->isWindowsArm64EC())
9347 return RetCC_AArch64_AAPCS;
9348 }
9349}
9350
9351static bool isPassedInFPR(EVT VT) {
9352 return VT.isFixedLengthVector() ||
9353 (VT.isFloatingPoint() && !VT.isScalableVector());
9354}
9355
9356SDValue AArch64TargetLowering::lowerEHPadEntry(SDValue Chain, SDLoc const &DL,
9357 SelectionDAG &DAG) const {
9358 assert(Chain.getOpcode() == ISD::EntryToken && "Unexpected Chain value");
9359 SDValue Glue = Chain.getValue(1);
9360
9362 auto &FuncInfo = *MF.getInfo<AArch64FunctionInfo>();
9363
9364 SMEAttrs SMEFnAttrs = FuncInfo.getSMEFnAttrs();
9365
9366 // The following conditions are true on entry to an exception handler:
9367 // - PSTATE.SM is 0.
9368 // - PSTATE.ZA is 0.
9369 // - TPIDR2_EL0 is null.
9370 // See:
9371 // https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#exceptions
9372 //
9373 // Therefore, if the function that contains this exception handler is a
9374 // streaming[-compatible] function, we must re-enable streaming mode.
9375 //
9376 // These mode changes are usually optimized away in catch blocks as they
9377 // occur before the __cxa_begin_catch (which is a non-streaming function),
9378 // but are necessary in some cases (such as for cleanups).
9379 //
9380 // Additionally, if the function has ZA or ZT0 state, we must restore it.
9381
9382 // [COND_]SMSTART SM
9383 if (SMEFnAttrs.hasStreamingInterfaceOrBody())
9384 Chain = changeStreamingMode(DAG, DL, /*Enable=*/true, Chain,
9385 /*Glue*/ Glue, AArch64SME::Always);
9386 else if (SMEFnAttrs.hasStreamingCompatibleInterface())
9387 Chain = changeStreamingMode(DAG, DL, /*Enable=*/true, Chain, Glue,
9389 return Chain;
9390}
9391
9392SDValue AArch64TargetLowering::LowerFormalArguments(
9393 SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
9394 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
9395 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
9397 const Function &F = MF.getFunction();
9398 MachineFrameInfo &MFI = MF.getFrameInfo();
9399 bool IsWin64 =
9400 Subtarget->isCallingConvWin64(F.getCallingConv(), F.isVarArg());
9401 bool StackViaX4 = CallConv == CallingConv::ARM64EC_Thunk_X64 ||
9402 (isVarArg && Subtarget->isWindowsArm64EC());
9403 AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
9404
9406 GetReturnInfo(CallConv, F.getReturnType(), F.getAttributes(), Outs,
9408 if (any_of(Outs, [](ISD::OutputArg &Out){ return Out.VT.isScalableVector(); }))
9409 FuncInfo->setIsSVECC(true);
9410
9411 // Assign locations to all of the incoming arguments.
9413 CCState CCInfo(CallConv, isVarArg, MF, ArgLocs, *DAG.getContext());
9414
9415 // At this point, Ins[].VT may already be promoted to i32. To correctly
9416 // handle passing i8 as i8 instead of i32 on stack, we pass in both i32 and
9417 // i8 to CC_AArch64_AAPCS with i32 being ValVT and i8 being LocVT.
9418 // Since AnalyzeFormalArguments uses Ins[].VT for both ValVT and LocVT, here
9419 // we use a special version of AnalyzeFormalArguments to pass in ValVT and
9420 // LocVT.
9421 unsigned NumArgs = Ins.size();
9422 Function::const_arg_iterator CurOrigArg = F.arg_begin();
9423 unsigned CurArgIdx = 0;
9424 bool UseVarArgCC = false;
9425 if (IsWin64)
9426 UseVarArgCC = isVarArg;
9427
9428 CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, UseVarArgCC);
9429
9430 for (unsigned i = 0; i != NumArgs; ++i) {
9431 MVT ValVT = Ins[i].VT;
9432 if (Ins[i].isOrigArg()) {
9433 std::advance(CurOrigArg, Ins[i].getOrigArgIndex() - CurArgIdx);
9434 CurArgIdx = Ins[i].getOrigArgIndex();
9435
9436 // Get type of the original argument.
9437 EVT ActualVT = getValueType(DAG.getDataLayout(), CurOrigArg->getType(),
9438 /*AllowUnknown*/ true);
9439 MVT ActualMVT = ActualVT.isSimple() ? ActualVT.getSimpleVT() : MVT::Other;
9440 // If ActualMVT is i1/i8/i16, we should set LocVT to i8/i8/i16.
9441 if (ActualMVT == MVT::i1 || ActualMVT == MVT::i8)
9442 ValVT = MVT::i8;
9443 else if (ActualMVT == MVT::i16)
9444 ValVT = MVT::i16;
9445 }
9446 bool Res = AssignFn(i, ValVT, ValVT, CCValAssign::Full, Ins[i].Flags,
9447 Ins[i].OrigTy, CCInfo);
9448 assert(!Res && "Call operand has unhandled type");
9449 (void)Res;
9450 }
9451
9452 SMEAttrs Attrs = FuncInfo->getSMEFnAttrs();
9453 bool IsLocallyStreaming =
9454 !Attrs.hasStreamingInterface() && Attrs.hasStreamingBody();
9455 assert(Chain.getOpcode() == ISD::EntryToken && "Unexpected Chain value");
9456 SDValue Glue = Chain.getValue(1);
9457
9458 unsigned ExtraArgLocs = 0;
9459 for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
9460 CCValAssign &VA = ArgLocs[i - ExtraArgLocs];
9461
9462 if (Ins[i].Flags.isByVal()) {
9463 // Byval is used for HFAs in the PCS, but the system should work in a
9464 // non-compliant manner for larger structs.
9465 EVT PtrVT = getPointerTy(DAG.getDataLayout());
9466 int Size = Ins[i].Flags.getByValSize();
9467 unsigned NumRegs = (Size + 7) / 8;
9468
9469 // FIXME: This works on big-endian for composite byvals, which are the common
9470 // case. It should also work for fundamental types too.
9471 unsigned FrameIdx =
9472 MFI.CreateFixedObject(8 * NumRegs, VA.getLocMemOffset(), false);
9473 SDValue FrameIdxN = DAG.getFrameIndex(FrameIdx, PtrVT);
9474 InVals.push_back(FrameIdxN);
9475
9476 continue;
9477 }
9478
9479 if (Ins[i].Flags.isSwiftAsync())
9480 MF.getInfo<AArch64FunctionInfo>()->setHasSwiftAsyncContext(true);
9481
9482 SDValue ArgValue;
9483 if (VA.isRegLoc()) {
9484 // Arguments stored in registers.
9485 EVT RegVT = VA.getLocVT();
9486 const TargetRegisterClass *RC;
9487
9488 if (RegVT == MVT::i32)
9489 RC = &AArch64::GPR32RegClass;
9490 else if (RegVT == MVT::i64)
9491 RC = &AArch64::GPR64RegClass;
9492 else if (RegVT == MVT::f16 || RegVT == MVT::bf16)
9493 RC = &AArch64::FPR16RegClass;
9494 else if (RegVT == MVT::f32)
9495 RC = &AArch64::FPR32RegClass;
9496 else if (RegVT == MVT::f64 || RegVT.is64BitVector())
9497 RC = &AArch64::FPR64RegClass;
9498 else if (RegVT == MVT::f128 || RegVT.is128BitVector())
9499 RC = &AArch64::FPR128RegClass;
9500 else if (RegVT.isScalableVector() &&
9501 RegVT.getVectorElementType() == MVT::i1) {
9502 FuncInfo->setIsSVECC(true);
9503 RC = &AArch64::PPRRegClass;
9504 } else if (RegVT == MVT::aarch64svcount) {
9505 FuncInfo->setIsSVECC(true);
9506 RC = &AArch64::PPRRegClass;
9507 } else if (RegVT.isScalableVector()) {
9508 FuncInfo->setIsSVECC(true);
9509 RC = &AArch64::ZPRRegClass;
9510 } else
9511 llvm_unreachable("RegVT not supported by FORMAL_ARGUMENTS Lowering");
9512
9513 // Transform the arguments in physical registers into virtual ones.
9514 Register Reg = MF.addLiveIn(VA.getLocReg(), RC);
9515
9516 if (IsLocallyStreaming) {
9517 // LocallyStreamingFunctions must insert the SMSTART in the correct
9518 // position, so we use Glue to ensure no instructions can be scheduled
9519 // between the chain of:
9520 // t0: ch,glue = EntryNode
9521 // t1: res,ch,glue = CopyFromReg
9522 // ...
9523 // tn: res,ch,glue = CopyFromReg t(n-1), ..
9524 // t(n+1): ch, glue = SMSTART t0:0, ...., tn:2
9525 // ^^^^^^
9526 // This will be the new Chain/Root node.
9527 ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT, Glue);
9528 Glue = ArgValue.getValue(2);
9529 if (isPassedInFPR(ArgValue.getValueType())) {
9530 ArgValue =
9531 DAG.getNode(AArch64ISD::COALESCER_BARRIER, DL,
9532 DAG.getVTList(ArgValue.getValueType(), MVT::Glue),
9533 {ArgValue, Glue});
9534 Glue = ArgValue.getValue(1);
9535 }
9536 } else
9537 ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT);
9538
9539 // If this is an 8, 16 or 32-bit value, it is really passed promoted
9540 // to 64 bits. Insert an assert[sz]ext to capture this, then
9541 // truncate to the right size.
9542 switch (VA.getLocInfo()) {
9543 default:
9544 llvm_unreachable("Unknown loc info!");
9545 case CCValAssign::Full:
9546 break;
9548 assert(
9549 (VA.getValVT().isScalableVT() || Subtarget->isWindowsArm64EC()) &&
9550 "Indirect arguments should be scalable on most subtargets");
9551 break;
9552 case CCValAssign::BCvt:
9553 ArgValue = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), ArgValue);
9554 break;
9555 case CCValAssign::AExt:
9556 case CCValAssign::SExt:
9557 case CCValAssign::ZExt:
9558 break;
9560 ArgValue = DAG.getNode(ISD::SRL, DL, RegVT, ArgValue,
9561 DAG.getConstant(32, DL, RegVT));
9562 ArgValue = DAG.getZExtOrTrunc(ArgValue, DL, VA.getValVT());
9563 break;
9564 }
9565 } else { // VA.isRegLoc()
9566 assert(VA.isMemLoc() && "CCValAssign is neither reg nor mem");
9567 unsigned ArgOffset = VA.getLocMemOffset();
9568 unsigned ArgSize = (VA.getLocInfo() == CCValAssign::Indirect
9569 ? VA.getLocVT().getSizeInBits()
9570 : VA.getValVT().getSizeInBits()) / 8;
9571
9572 uint32_t BEAlign = 0;
9573 if (!Subtarget->isLittleEndian() && ArgSize < 8 &&
9574 !Ins[i].Flags.isInConsecutiveRegs())
9575 BEAlign = 8 - ArgSize;
9576
9577 SDValue FIN;
9578 MachinePointerInfo PtrInfo;
9579 if (StackViaX4) {
9580 // In both the ARM64EC varargs convention and the thunk convention,
9581 // arguments on the stack are accessed relative to x4, not sp. In
9582 // the thunk convention, there's an additional offset of 32 bytes
9583 // to account for the shadow store.
9584 unsigned ObjOffset = ArgOffset + BEAlign;
9585 if (CallConv == CallingConv::ARM64EC_Thunk_X64)
9586 ObjOffset += 32;
9587 Register VReg = MF.addLiveIn(AArch64::X4, &AArch64::GPR64RegClass);
9588 SDValue Val = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i64);
9589 FIN = DAG.getNode(ISD::ADD, DL, MVT::i64, Val,
9590 DAG.getConstant(ObjOffset, DL, MVT::i64));
9592 } else {
9593 int FI = MFI.CreateFixedObject(ArgSize, ArgOffset + BEAlign, true);
9594
9595 // Create load nodes to retrieve arguments from the stack.
9596 FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
9597 PtrInfo = MachinePointerInfo::getFixedStack(MF, FI);
9598 }
9599
9600 // For NON_EXTLOAD, generic code in getLoad assert(ValVT == MemVT)
9602 MVT MemVT = VA.getValVT();
9603
9604 switch (VA.getLocInfo()) {
9605 default:
9606 break;
9607 case CCValAssign::Trunc:
9608 case CCValAssign::BCvt:
9609 MemVT = VA.getLocVT();
9610 break;
9612 assert(
9613 (VA.getValVT().isScalableVT() || Subtarget->isWindowsArm64EC()) &&
9614 "Indirect arguments should be scalable on most subtargets");
9615 MemVT = VA.getLocVT();
9616 break;
9617 case CCValAssign::SExt:
9618 ExtType = ISD::SEXTLOAD;
9619 break;
9620 case CCValAssign::ZExt:
9621 ExtType = ISD::ZEXTLOAD;
9622 break;
9623 case CCValAssign::AExt:
9624 ExtType = ISD::EXTLOAD;
9625 break;
9626 }
9627
9628 ArgValue = DAG.getExtLoad(ExtType, DL, VA.getLocVT(), Chain, FIN, PtrInfo,
9629 MemVT);
9630 }
9631
9632 if (VA.getLocInfo() == CCValAssign::Indirect) {
9633 assert((VA.getValVT().isScalableVT() ||
9634 Subtarget->isWindowsArm64EC()) &&
9635 "Indirect arguments should be scalable on most subtargets");
9636
9637 TypeSize PartSize = VA.getValVT().getStoreSize();
9638 unsigned NumParts = 1;
9639 if (Ins[i].Flags.isInConsecutiveRegs()) {
9640 while (!Ins[i + NumParts - 1].Flags.isInConsecutiveRegsLast())
9641 ++NumParts;
9642 }
9643
9644 MVT PartLoad = VA.getValVT();
9645 SDValue Ptr = ArgValue;
9646
9647 // Ensure we generate all loads for each tuple part, whilst updating the
9648 // pointer after each load correctly using vscale.
9649 while (NumParts > 0) {
9650 ArgValue = DAG.getLoad(PartLoad, DL, Chain, Ptr, MachinePointerInfo());
9651 InVals.push_back(ArgValue);
9652 NumParts--;
9653 if (NumParts > 0) {
9654 SDValue BytesIncrement =
9655 DAG.getTypeSize(DL, Ptr.getValueType(), PartSize);
9656 Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr,
9657 BytesIncrement, SDNodeFlags::NoUnsignedWrap);
9658 ExtraArgLocs++;
9659 i++;
9660 }
9661 }
9662 } else {
9663 if (Subtarget->isTargetILP32() && Ins[i].Flags.isPointer())
9664 ArgValue = DAG.getNode(ISD::AssertZext, DL, ArgValue.getValueType(),
9665 ArgValue, DAG.getValueType(MVT::i32));
9666
9667 // i1 arguments are zero-extended to i8 by the caller. Emit a
9668 // hint to reflect this.
9669 if (Ins[i].isOrigArg()) {
9670 Argument *OrigArg = F.getArg(Ins[i].getOrigArgIndex());
9671 if (OrigArg->getType()->isIntegerTy(1)) {
9672 if (!Ins[i].Flags.isZExt()) {
9673 ArgValue = DAG.getNode(AArch64ISD::ASSERT_ZEXT_BOOL, DL,
9674 ArgValue.getValueType(), ArgValue);
9675 }
9676 }
9677 }
9678
9679 InVals.push_back(ArgValue);
9680 }
9681 }
9682 assert((ArgLocs.size() + ExtraArgLocs) == Ins.size());
9683
9684 if (Attrs.hasStreamingCompatibleInterface()) {
9685 SDValue EntryPStateSM =
9686 DAG.getNode(AArch64ISD::ENTRY_PSTATE_SM, DL,
9687 DAG.getVTList(MVT::i64, MVT::Other), {Chain});
9688
9689 // Copy the value to a virtual register, and save that in FuncInfo.
9690 Register EntryPStateSMReg =
9691 MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
9692 Chain = DAG.getCopyToReg(EntryPStateSM.getValue(1), DL, EntryPStateSMReg,
9693 EntryPStateSM);
9694 FuncInfo->setPStateSMReg(EntryPStateSMReg);
9695 }
9696
9697 // Insert the SMSTART if this is a locally streaming function and
9698 // make sure it is Glued to the last CopyFromReg value.
9699 if (IsLocallyStreaming) {
9700 if (Attrs.hasStreamingCompatibleInterface())
9701 Chain = changeStreamingMode(DAG, DL, /*Enable*/ true, Chain, Glue,
9703 else
9704 Chain = changeStreamingMode(DAG, DL, /*Enable*/ true, Chain, Glue,
9706
9707 // Ensure that the SMSTART happens after the CopyWithChain such that its
9708 // chain result is used.
9709 for (unsigned I=0; I<InVals.size(); ++I) {
9712 Chain = DAG.getCopyToReg(Chain, DL, Reg, InVals[I]);
9713 InVals[I] = DAG.getCopyFromReg(Chain, DL, Reg,
9714 InVals[I].getValueType());
9715 }
9716 }
9717
9718 // varargs
9719 if (isVarArg) {
9721 if (!Subtarget->isTargetDarwin() || IsWin64) {
9722 // The AAPCS variadic function ABI is identical to the non-variadic
9723 // one. As a result there may be more arguments in registers and we
9724 // should save them for future reference.
9725 // Win64 variadic functions also pass arguments in registers, but all
9726 // float arguments are passed in integer registers.
9727 saveVarArgRegisters(CCInfo, DAG, DL, Chain);
9728 }
9729
9730 // This will point to the next argument passed via stack.
9731 unsigned VarArgsOffset = CCInfo.getStackSize();
9732 // We currently pass all varargs at 8-byte alignment, or 4 for ILP32
9733 VarArgsOffset =
9734 alignTo(VarArgsOffset, Subtarget->isTargetILP32() ? 4 : 8);
9735 FuncInfo->setVarArgsStackOffset(VarArgsOffset);
9736 FuncInfo->setVarArgsStackIndex(
9737 MFI.CreateFixedObject(4, VarArgsOffset, true));
9738 }
9739
9740 if (MFI.hasMustTailInVarArgFunc()) {
9741 SmallVector<MVT, 2> RegParmTypes;
9742 RegParmTypes.push_back(MVT::i64);
9743 RegParmTypes.push_back(MVT::f128);
9744 // Compute the set of forwarded registers. The rest are scratch.
9745 SmallVectorImpl<ForwardedRegister> &Forwards =
9746 FuncInfo->getForwardedMustTailRegParms();
9747 CCInfo.analyzeMustTailForwardedRegisters(Forwards, RegParmTypes,
9749
9750 // Conservatively forward X8, since it might be used for aggregate return.
9751 if (!CCInfo.isAllocated(AArch64::X8)) {
9752 Register X8VReg = MF.addLiveIn(AArch64::X8, &AArch64::GPR64RegClass);
9753 Forwards.push_back(ForwardedRegister(X8VReg, AArch64::X8, MVT::i64));
9754 }
9755 }
9756 }
9757
9758 // On Windows, InReg pointers must be returned, so record the pointer in a
9759 // virtual register at the start of the function so it can be returned in the
9760 // epilogue.
9761 if (IsWin64 || F.getCallingConv() == CallingConv::ARM64EC_Thunk_X64) {
9762 for (unsigned I = 0, E = Ins.size(); I != E; ++I) {
9763 if ((F.getCallingConv() == CallingConv::ARM64EC_Thunk_X64 ||
9764 Ins[I].Flags.isInReg()) &&
9765 Ins[I].Flags.isSRet()) {
9766 assert(!FuncInfo->getSRetReturnReg());
9767
9768 MVT PtrTy = getPointerTy(DAG.getDataLayout());
9769 Register Reg =
9771 FuncInfo->setSRetReturnReg(Reg);
9772
9773 SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[I]);
9774 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain);
9775 break;
9776 }
9777 }
9778 }
9779
9780 unsigned StackArgSize = CCInfo.getStackSize();
9781 bool TailCallOpt = MF.getTarget().Options.GuaranteedTailCallOpt;
9782 if (DoesCalleeRestoreStack(CallConv, TailCallOpt)) {
9783 // This is a non-standard ABI so by fiat I say we're allowed to make full
9784 // use of the stack area to be popped, which must be aligned to 16 bytes in
9785 // any case:
9786 StackArgSize = alignTo(StackArgSize, 16);
9787
9788 // If we're expected to restore the stack (e.g. fastcc) then we'll be adding
9789 // a multiple of 16.
9790 FuncInfo->setArgumentStackToRestore(StackArgSize);
9791
9792 // This realignment carries over to the available bytes below. Our own
9793 // callers will guarantee the space is free by giving an aligned value to
9794 // CALLSEQ_START.
9795 }
9796 // Even if we're not expected to free up the space, it's useful to know how
9797 // much is there while considering tail calls (because we can reuse it).
9798 FuncInfo->setBytesInStackArgArea(StackArgSize);
9799
9800 if (Subtarget->hasCustomCallingConv())
9801 Subtarget->getRegisterInfo()->UpdateCustomCalleeSavedRegs(MF);
9802
9803 if (Subtarget->isTargetWindows() || hasInlineStackProbe(MF)) {
9804 SDValue Size;
9805 if (Attrs.hasZAState()) {
9806 SDValue SVL = DAG.getNode(AArch64ISD::RDSVL, DL, MVT::i64,
9807 DAG.getConstant(1, DL, MVT::i32));
9808 Size = DAG.getNode(ISD::MUL, DL, MVT::i64, SVL, SVL);
9809 } else if (Attrs.hasAgnosticZAInterface()) {
9810 RTLIB::Libcall LC = RTLIB::SMEABI_SME_STATE_SIZE;
9811 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
9812
9813 SDValue Callee =
9814 DAG.getExternalSymbol(LCImpl, getPointerTy(DAG.getDataLayout()));
9815 auto *RetTy = EVT(MVT::i64).getTypeForEVT(*DAG.getContext());
9816 TargetLowering::CallLoweringInfo CLI(DAG);
9817 CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
9818 DAG.getLibcalls().getLibcallImplCallingConv(LCImpl), RetTy, Callee,
9819 {});
9820 std::tie(Size, Chain) = LowerCallTo(CLI);
9821 }
9822 if (Size) {
9823 SDValue Buffer = DAG.getNode(
9824 ISD::DYNAMIC_STACKALLOC, DL, DAG.getVTList(MVT::i64, MVT::Other),
9825 {Chain, Size, DAG.getConstant(1, DL, MVT::i64)});
9826 Chain = Buffer.getValue(1);
9827
9828 Register BufferPtr =
9829 MF.getRegInfo().createVirtualRegister(&AArch64::GPR64RegClass);
9830 Chain = DAG.getCopyToReg(Chain, DL, BufferPtr, Buffer);
9831 Chain = DAG.getNode(AArch64ISD::SME_STATE_ALLOC, DL,
9832 DAG.getVTList(MVT::Other), Chain);
9833 FuncInfo->setEarlyAllocSMESaveBuffer(BufferPtr);
9834 MFI.CreateVariableSizedObject(Align(16), nullptr);
9835 }
9836 }
9837
9838 if (CallConv == CallingConv::PreserveNone) {
9839 for (const ISD::InputArg &I : Ins) {
9840 if (I.Flags.isSwiftSelf() || I.Flags.isSwiftError() ||
9841 I.Flags.isSwiftAsync()) {
9843 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
9844 MF.getFunction(),
9845 "Swift attributes can't be used with preserve_none",
9846 DL.getDebugLoc()));
9847 break;
9848 }
9849 }
9850 }
9851
9852 return Chain;
9853}
9854
9855void AArch64TargetLowering::saveVarArgRegisters(CCState &CCInfo,
9856 SelectionDAG &DAG,
9857 const SDLoc &DL,
9858 SDValue &Chain) const {
9860 MachineFrameInfo &MFI = MF.getFrameInfo();
9861 AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
9862 auto PtrVT = getPointerTy(DAG.getDataLayout());
9863 Function &F = MF.getFunction();
9864 bool IsWin64 =
9865 Subtarget->isCallingConvWin64(F.getCallingConv(), F.isVarArg());
9866
9868
9870 unsigned NumGPRArgRegs = GPRArgRegs.size();
9871 if (Subtarget->isWindowsArm64EC()) {
9872 // In the ARM64EC ABI, only x0-x3 are used to pass arguments to varargs
9873 // functions.
9874 NumGPRArgRegs = 4;
9875 }
9876 unsigned FirstVariadicGPR = CCInfo.getFirstUnallocated(GPRArgRegs);
9877
9878 unsigned GPRSaveSize = 8 * (NumGPRArgRegs - FirstVariadicGPR);
9879 int GPRIdx = 0;
9880 if (GPRSaveSize != 0) {
9881 if (IsWin64) {
9882 GPRIdx = MFI.CreateFixedObject(GPRSaveSize, -(int)GPRSaveSize, false);
9883 if (GPRSaveSize & 15)
9884 // The extra size here, if triggered, will always be 8.
9885 MFI.CreateFixedObject(16 - (GPRSaveSize & 15), -(int)alignTo(GPRSaveSize, 16), false);
9886 } else
9887 GPRIdx = MFI.CreateStackObject(GPRSaveSize, Align(8), false);
9888
9889 SDValue FIN;
9890 if (Subtarget->isWindowsArm64EC()) {
9891 // With the Arm64EC ABI, we reserve the save area as usual, but we
9892 // compute its address relative to x4. For a normal AArch64->AArch64
9893 // call, x4 == sp on entry, but calls from an entry thunk can pass in a
9894 // different address.
9895 Register VReg = MF.addLiveIn(AArch64::X4, &AArch64::GPR64RegClass);
9896 SDValue Val = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i64);
9897 FIN = DAG.getNode(ISD::SUB, DL, MVT::i64, Val,
9898 DAG.getConstant(GPRSaveSize, DL, MVT::i64));
9899 } else {
9900 FIN = DAG.getFrameIndex(GPRIdx, PtrVT);
9901 }
9902
9903 for (unsigned i = FirstVariadicGPR; i < NumGPRArgRegs; ++i) {
9904 Register VReg = MF.addLiveIn(GPRArgRegs[i], &AArch64::GPR64RegClass);
9905 SDValue Val = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i64);
9906 SDValue Store =
9907 DAG.getStore(Val.getValue(1), DL, Val, FIN,
9909 MF, GPRIdx, (i - FirstVariadicGPR) * 8)
9910 : MachinePointerInfo::getStack(MF, i * 8));
9911 MemOps.push_back(Store);
9912 FIN =
9913 DAG.getNode(ISD::ADD, DL, PtrVT, FIN, DAG.getConstant(8, DL, PtrVT));
9914 }
9915 }
9916 FuncInfo->setVarArgsGPRIndex(GPRIdx);
9917 FuncInfo->setVarArgsGPRSize(GPRSaveSize);
9918
9919 if (Subtarget->hasFPARMv8() && !IsWin64) {
9921 const unsigned NumFPRArgRegs = FPRArgRegs.size();
9922 unsigned FirstVariadicFPR = CCInfo.getFirstUnallocated(FPRArgRegs);
9923
9924 unsigned FPRSaveSize = 16 * (NumFPRArgRegs - FirstVariadicFPR);
9925 int FPRIdx = 0;
9926 if (FPRSaveSize != 0) {
9927 FPRIdx = MFI.CreateStackObject(FPRSaveSize, Align(16), false);
9928
9929 SDValue FIN = DAG.getFrameIndex(FPRIdx, PtrVT);
9930
9931 for (unsigned i = FirstVariadicFPR; i < NumFPRArgRegs; ++i) {
9932 Register VReg = MF.addLiveIn(FPRArgRegs[i], &AArch64::FPR128RegClass);
9933 SDValue Val = DAG.getCopyFromReg(Chain, DL, VReg, MVT::f128);
9934
9935 SDValue Store = DAG.getStore(Val.getValue(1), DL, Val, FIN,
9936 MachinePointerInfo::getStack(MF, i * 16));
9937 MemOps.push_back(Store);
9938 FIN = DAG.getNode(ISD::ADD, DL, PtrVT, FIN,
9939 DAG.getConstant(16, DL, PtrVT));
9940 }
9941 }
9942 FuncInfo->setVarArgsFPRIndex(FPRIdx);
9943 FuncInfo->setVarArgsFPRSize(FPRSaveSize);
9944 }
9945
9946 if (!MemOps.empty()) {
9947 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOps);
9948 }
9949}
9950
9951/// LowerCallResult - Lower the result values of a call into the
9952/// appropriate copies out of appropriate physical registers.
9953SDValue AArch64TargetLowering::LowerCallResult(
9954 SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
9955 const SmallVectorImpl<CCValAssign> &RVLocs, const SDLoc &DL,
9956 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals, bool isThisReturn,
9957 SDValue ThisVal, bool RequiresSMChange) const {
9958 DenseMap<unsigned, SDValue> CopiedRegs;
9959 // Copy all of the result registers out of their specified physreg.
9960 for (unsigned i = 0; i != RVLocs.size(); ++i) {
9961 CCValAssign VA = RVLocs[i];
9962
9963 // Pass 'this' value directly from the argument to return value, to avoid
9964 // reg unit interference
9965 if (i == 0 && isThisReturn) {
9966 assert(!VA.needsCustom() && VA.getLocVT() == MVT::i64 &&
9967 "unexpected return calling convention register assignment");
9968 InVals.push_back(ThisVal);
9969 continue;
9970 }
9971
9972 // Avoid copying a physreg twice since RegAllocFast is incompetent and only
9973 // allows one use of a physreg per block.
9974 SDValue Val = CopiedRegs.lookup(VA.getLocReg());
9975 if (!Val) {
9976 Val =
9977 DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), InGlue);
9978 Chain = Val.getValue(1);
9979 InGlue = Val.getValue(2);
9980 CopiedRegs[VA.getLocReg()] = Val;
9981 }
9982
9983 switch (VA.getLocInfo()) {
9984 default:
9985 llvm_unreachable("Unknown loc info!");
9986 case CCValAssign::Full:
9987 break;
9988 case CCValAssign::BCvt:
9989 Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
9990 break;
9992 Val = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), Val,
9993 DAG.getConstant(32, DL, VA.getLocVT()));
9994 [[fallthrough]];
9995 case CCValAssign::AExt:
9996 [[fallthrough]];
9997 case CCValAssign::ZExt:
9998 Val = DAG.getZExtOrTrunc(Val, DL, VA.getValVT());
9999 break;
10000 }
10001
10002 if (RequiresSMChange && isPassedInFPR(VA.getValVT()))
10003 Val = DAG.getNode(AArch64ISD::COALESCER_BARRIER, DL,
10004 DAG.getVTList(Val.getValueType(), MVT::Glue), Val);
10005
10006 InVals.push_back(Val);
10007 }
10008
10009 return Chain;
10010}
10011
10012/// Return true if the calling convention is one that we can guarantee TCO for.
10013static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls) {
10014 return (CC == CallingConv::Fast && GuaranteeTailCalls) ||
10016}
10017
10018/// Return true if we might ever do TCO for calls with this calling convention.
10020 switch (CC) {
10021 case CallingConv::C:
10026 case CallingConv::Swift:
10028 case CallingConv::Tail:
10029 case CallingConv::Fast:
10030 return true;
10031 default:
10032 return false;
10033 }
10034}
10035
10036/// Return true if the call convention supports varargs
10037/// Currently only those that pass varargs like the C
10038/// calling convention does are eligible
10039/// Calling conventions listed in this function must also
10040/// be properly handled in AArch64Subtarget::isCallingConvWin64
10042 switch (CC) {
10043 case CallingConv::C:
10045 // SVE vector call is only partially supported, but it should
10046 // support named arguments being passed. Any arguments being passed
10047 // as varargs, are still unsupported.
10049 return true;
10050 default:
10051 return false;
10052 }
10053}
10054
10056 const AArch64Subtarget *Subtarget,
10058 CCState &CCInfo) {
10059 const SelectionDAG &DAG = CLI.DAG;
10060 CallingConv::ID CalleeCC = CLI.CallConv;
10061 bool IsVarArg = CLI.IsVarArg;
10062 const SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs;
10063 bool IsCalleeWin64 = Subtarget->isCallingConvWin64(CalleeCC, IsVarArg);
10064
10065 // For Arm64EC thunks, allocate 32 extra bytes at the bottom of the stack
10066 // for the shadow store.
10067 if (CalleeCC == CallingConv::ARM64EC_Thunk_X64)
10068 CCInfo.AllocateStack(32, Align(16));
10069
10070 unsigned NumArgs = Outs.size();
10071
10072 // IsVarArg is only set on an ARM64EC_Thunk_X64 for exit thunks, so if set
10073 // we know we have a vararg exit thunk where x4 and x5 must be consumed in
10074 // this lowering (copying the data to the stack).
10075 bool IsArm64ECVarArgExitThunk = CalleeCC == CallingConv::ARM64EC_Thunk_X64 &&
10076 IsVarArg &&
10077 !(CLI.CB && CLI.CB->isMustTailCall());
10078 if (IsArm64ECVarArgExitThunk) {
10079 if (NumArgs < 2)
10080 report_fatal_error("variadic arm64ec_thunk_x64 call is missing the "
10081 "x4/x5 (pointer/length) arguments");
10082 NumArgs -= 2;
10083 }
10084
10085 for (unsigned i = 0; i != NumArgs; ++i) {
10086 MVT ArgVT = Outs[i].VT;
10087 ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
10088
10089 bool UseVarArgCC = false;
10090 if (IsVarArg) {
10091 // On Windows, the fixed arguments in a vararg call are passed in GPRs
10092 // too, so use the vararg CC to force them to integer registers.
10093 if (IsCalleeWin64) {
10094 UseVarArgCC = true;
10095 } else {
10096 UseVarArgCC = ArgFlags.isVarArg();
10097 }
10098 }
10099
10100 if (!UseVarArgCC) {
10101 // Get type of the original argument.
10102 EVT ActualVT =
10103 TLI.getValueType(DAG.getDataLayout(), CLI.Args[Outs[i].OrigArgIndex].Ty,
10104 /*AllowUnknown*/ true);
10105 MVT ActualMVT = ActualVT.isSimple() ? ActualVT.getSimpleVT() : ArgVT;
10106 // If ActualMVT is i1/i8/i16, we should set LocVT to i8/i8/i16.
10107 if (ActualMVT == MVT::i1 || ActualMVT == MVT::i8)
10108 ArgVT = MVT::i8;
10109 else if (ActualMVT == MVT::i16)
10110 ArgVT = MVT::i16;
10111 }
10112
10113 // FIXME: CCAssignFnForCall should be called once, for the call and not per
10114 // argument. This logic should exactly mirror LowerFormalArguments.
10115 CCAssignFn *AssignFn = TLI.CCAssignFnForCall(CalleeCC, UseVarArgCC);
10116 bool Res = AssignFn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags,
10117 Outs[i].OrigTy, CCInfo);
10118 assert(!Res && "Call operand has unhandled type");
10119 (void)Res;
10120 }
10121}
10122
10123static SMECallAttrs
10126 if (CLI.CB)
10127 return SMECallAttrs(*CLI.CB, &RTLCI);
10128 if (auto *ES = dyn_cast<ExternalSymbolSDNode>(CLI.Callee))
10129 return SMECallAttrs(SMEAttrs(Caller), SMEAttrs(ES->getSymbol(), RTLCI));
10131}
10132
10133bool AArch64TargetLowering::isEligibleForTailCallOptimization(
10134 const CallLoweringInfo &CLI) const {
10135 CallingConv::ID CalleeCC = CLI.CallConv;
10136 if (!mayTailCallThisCC(CalleeCC))
10137 return false;
10138
10139 SDValue Callee = CLI.Callee;
10140 bool IsVarArg = CLI.IsVarArg;
10141 const SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs;
10142 const SmallVector<SDValue, 32> &OutVals = CLI.OutVals;
10143 const SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins;
10144 const SelectionDAG &DAG = CLI.DAG;
10146 const Function &CallerF = MF.getFunction();
10147 CallingConv::ID CallerCC = CallerF.getCallingConv();
10148
10149 // SME Streaming functions are not eligible for TCO as they may require
10150 // the streaming mode or ZA/ZT0 to be restored after returning from the call.
10151 SMECallAttrs CallAttrs =
10152 getSMECallAttrs(CallerF, getRuntimeLibcallsInfo(), CLI);
10153 if (CallAttrs.requiresSMChange() || CallAttrs.requiresZASave() ||
10154 CallAttrs.requiresPreservingZT0() ||
10155 CallAttrs.caller().hasStreamingBody() || CallAttrs.caller().isNewZA() ||
10156 CallAttrs.caller().isNewZT0())
10157 return false;
10158
10159 // Functions using the C or Fast calling convention that have an SVE signature
10160 // preserve more registers and should assume the SVE_VectorCall CC.
10161 // The check for matching callee-saved regs will determine whether it is
10162 // eligible for TCO.
10163 if ((CallerCC == CallingConv::C || CallerCC == CallingConv::Fast) &&
10164 MF.getInfo<AArch64FunctionInfo>()->isSVECC())
10166
10167 bool CCMatch = CallerCC == CalleeCC;
10168
10169 // When using the Windows calling convention on a non-windows OS, we want
10170 // to back up and restore X18 in such functions; we can't do a tail call
10171 // from those functions.
10172 if (CallerCC == CallingConv::Win64 && !Subtarget->isTargetWindows() &&
10173 CalleeCC != CallingConv::Win64)
10174 return false;
10175
10176 // Byval parameters hand the function a pointer directly into the stack area
10177 // we want to reuse during a tail call. Working around this *is* possible (see
10178 // X86) but less efficient and uglier in LowerCall.
10179 for (Function::const_arg_iterator i = CallerF.arg_begin(),
10180 e = CallerF.arg_end();
10181 i != e; ++i) {
10182 if (i->hasByValAttr())
10183 return false;
10184
10185 // On Windows, "inreg" attributes signify non-aggregate indirect returns.
10186 // In this case, it is necessary to save X0/X1 in the callee and return it
10187 // in X0. Tail call opt may interfere with this, so we disable tail call
10188 // opt when the caller has an "inreg" attribute -- except if the callee
10189 // also has that attribute on the same argument, and the same value is
10190 // passed.
10191 if (i->hasInRegAttr()) {
10192 unsigned ArgIdx = i - CallerF.arg_begin();
10193 if (!CLI.CB || CLI.CB->arg_size() <= ArgIdx)
10194 return false;
10195 AttributeSet Attrs = CLI.CB->getParamAttributes(ArgIdx);
10196 if (!Attrs.hasAttribute(Attribute::InReg) ||
10197 !Attrs.hasAttribute(Attribute::StructRet) || !i->hasStructRetAttr() ||
10198 CLI.CB->getArgOperand(ArgIdx) != i) {
10199 return false;
10200 }
10201 }
10202 }
10203
10204 if (canGuaranteeTCO(CalleeCC, getTargetMachine().Options.GuaranteedTailCallOpt))
10205 return CCMatch;
10206
10207 // Externally-defined functions with weak linkage should not be
10208 // tail-called on AArch64 when the OS does not support dynamic
10209 // pre-emption of symbols, as the AAELF spec requires normal calls
10210 // to undefined weak functions to be replaced with a NOP or jump to the
10211 // next instruction. The behaviour of branch instructions in this
10212 // situation (as used for tail calls) is implementation-defined, so we
10213 // cannot rely on the linker replacing the tail call with a return.
10214 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
10215 const GlobalValue *GV = G->getGlobal();
10216 const Triple &TT = getTargetMachine().getTargetTriple();
10217 if (GV->hasExternalWeakLinkage() &&
10218 (!TT.isOSWindows() || TT.isOSBinFormatELF() || TT.isOSBinFormatMachO()))
10219 return false;
10220 }
10221
10222 // Now we search for cases where we can use a tail call without changing the
10223 // ABI. Sibcall is used in some places (particularly gcc) to refer to this
10224 // concept.
10225
10226 // I want anyone implementing a new calling convention to think long and hard
10227 // about this assert.
10228 if (IsVarArg && !callConvSupportsVarArgs(CalleeCC))
10229 report_fatal_error("Unsupported variadic calling convention");
10230
10231 LLVMContext &C = *DAG.getContext();
10232 // Check that the call results are passed in the same way.
10233 if (!CCState::resultsCompatible(CalleeCC, CallerCC, MF, C, Ins,
10234 CCAssignFnForCall(CalleeCC, IsVarArg),
10235 CCAssignFnForCall(CallerCC, IsVarArg)))
10236 return false;
10237 // The callee has to preserve all registers the caller needs to preserve.
10238 const AArch64RegisterInfo *TRI = Subtarget->getRegisterInfo();
10239 const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC);
10240 if (!CCMatch) {
10241 const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC);
10242 if (Subtarget->hasCustomCallingConv()) {
10243 TRI->UpdateCustomCallPreservedMask(MF, &CallerPreserved);
10244 TRI->UpdateCustomCallPreservedMask(MF, &CalleePreserved);
10245 }
10246 if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
10247 return false;
10248 }
10249
10250 // Nothing more to check if the callee is taking no arguments
10251 if (Outs.empty())
10252 return true;
10253
10255 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, C);
10256
10257 analyzeCallOperands(*this, Subtarget, CLI, CCInfo);
10258
10259 if (IsVarArg && !(CLI.CB && CLI.CB->isMustTailCall())) {
10260 // When we are musttail, additional checks have been done and we can safely ignore this check
10261 // At least two cases here: if caller is fastcc then we can't have any
10262 // memory arguments (we'd be expected to clean up the stack afterwards). If
10263 // caller is C then we could potentially use its argument area.
10264
10265 // FIXME: for now we take the most conservative of these in both cases:
10266 // disallow all variadic memory operands.
10267 for (const CCValAssign &ArgLoc : ArgLocs)
10268 if (!ArgLoc.isRegLoc())
10269 return false;
10270 }
10271
10272 const AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
10273
10274 // If any of the arguments is passed indirectly, it must be SVE, so the
10275 // 'getBytesInStackArgArea' is not sufficient to determine whether we need to
10276 // allocate space on the stack. That is why we determine this explicitly here
10277 // the call cannot be a tailcall.
10278 if (llvm::any_of(ArgLocs, [&](CCValAssign &A) {
10279 assert((A.getLocInfo() != CCValAssign::Indirect ||
10280 A.getValVT().isScalableVector() ||
10281 Subtarget->isWindowsArm64EC()) &&
10282 "Expected value to be scalable");
10283 return A.getLocInfo() == CCValAssign::Indirect;
10284 }))
10285 return false;
10286
10287 // If the stack arguments for this call do not fit into our own save area then
10288 // the call cannot be made tail.
10289 if (CCInfo.getStackSize() > FuncInfo->getBytesInStackArgArea())
10290 return false;
10291
10292 const MachineRegisterInfo &MRI = MF.getRegInfo();
10293 if (!parametersInCSRMatch(MRI, CallerPreserved, ArgLocs, OutVals))
10294 return false;
10295
10296 return true;
10297}
10298
10299SDValue AArch64TargetLowering::addTokenForArgument(SDValue Chain,
10300 SelectionDAG &DAG,
10301 MachineFrameInfo &MFI,
10302 int ClobberedFI) const {
10303 SmallVector<SDValue, 8> ArgChains;
10304 int64_t FirstByte = MFI.getObjectOffset(ClobberedFI);
10305 int64_t LastByte = FirstByte + MFI.getObjectSize(ClobberedFI) - 1;
10306
10307 // Include the original chain at the beginning of the list. When this is
10308 // used by target LowerCall hooks, this helps legalize find the
10309 // CALLSEQ_BEGIN node.
10310 ArgChains.push_back(Chain);
10311
10312 // Add a chain value for each stack argument corresponding
10313 for (SDNode *U : DAG.getEntryNode()->users())
10314 if (LoadSDNode *L = dyn_cast<LoadSDNode>(U))
10315 if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(L->getBasePtr()))
10316 if (FI->getIndex() < 0) {
10317 int64_t InFirstByte = MFI.getObjectOffset(FI->getIndex());
10318 int64_t InLastByte = InFirstByte;
10319 InLastByte += MFI.getObjectSize(FI->getIndex()) - 1;
10320
10321 if ((InFirstByte <= FirstByte && FirstByte <= InLastByte) ||
10322 (FirstByte <= InFirstByte && InFirstByte <= LastByte))
10323 ArgChains.push_back(SDValue(L, 1));
10324 }
10325
10326 // Build a tokenfactor for all the chains.
10327 return DAG.getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, ArgChains);
10328}
10329
10330bool AArch64TargetLowering::DoesCalleeRestoreStack(CallingConv::ID CallCC,
10331 bool TailCallOpt) const {
10332 return (CallCC == CallingConv::Fast && TailCallOpt) ||
10333 CallCC == CallingConv::Tail || CallCC == CallingConv::SwiftTail;
10334}
10335
10336// Check if the value is zero-extended from i1 to i8
10337static bool checkZExtBool(SDValue Arg, const SelectionDAG &DAG) {
10338 unsigned SizeInBits = Arg.getValueType().getSizeInBits();
10339 if (SizeInBits < 8)
10340 return false;
10341
10342 APInt RequiredZero(SizeInBits, 0xFE);
10343 KnownBits Bits = DAG.computeKnownBits(Arg, 4);
10344 bool ZExtBool = (Bits.Zero & RequiredZero) == RequiredZero;
10345 return ZExtBool;
10346}
10347
10348void AArch64TargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI,
10349 SDNode *Node) const {
10350 // Live-in physreg copies that are glued to SMSTART are applied as
10351 // implicit-def's in the InstrEmitter. Here we remove them, allowing the
10352 // register allocator to pass call args in callee saved regs, without extra
10353 // copies to avoid these fake clobbers of actually-preserved GPRs.
10354 if (MI.getOpcode() == AArch64::MSRpstatesvcrImm1 ||
10355 MI.getOpcode() == AArch64::MSRpstatePseudo) {
10356 for (unsigned I = MI.getNumOperands() - 1; I > 0; --I)
10357 if (MachineOperand &MO = MI.getOperand(I);
10358 MO.isReg() && MO.isImplicit() && MO.isDef() &&
10359 (AArch64::GPR32RegClass.contains(MO.getReg()) ||
10360 AArch64::GPR64RegClass.contains(MO.getReg())))
10361 MI.removeOperand(I);
10362
10363 // The SVE vector length can change when entering/leaving streaming mode.
10364 // FPMR is set to 0 when entering/leaving streaming mode.
10365 if (MI.getOperand(0).getImm() == AArch64SVCR::SVCRSM ||
10366 MI.getOperand(0).getImm() == AArch64SVCR::SVCRSMZA) {
10367 MI.addOperand(MachineOperand::CreateReg(AArch64::VG, /*IsDef=*/false,
10368 /*IsImplicit=*/true));
10369 MI.addOperand(MachineOperand::CreateReg(AArch64::VG, /*IsDef=*/true,
10370 /*IsImplicit=*/true));
10371 MI.addOperand(MachineOperand::CreateReg(AArch64::FPMR, /*IsDef=*/true,
10372 /*IsImplicit=*/true));
10373 }
10374 }
10375
10376 // Add an implicit use of 'VG' for ADDXri/SUBXri, which are instructions that
10377 // have nothing to do with VG, were it not that they are used to materialise a
10378 // frame-address. If they contain a frame-index to a scalable vector, this
10379 // will likely require an ADDVL instruction to materialise the address, thus
10380 // reading VG.
10381 const MachineFunction &MF = *MI.getMF();
10382 if (MF.getInfo<AArch64FunctionInfo>()->hasStreamingModeChanges() &&
10383 (MI.getOpcode() == AArch64::ADDXri ||
10384 MI.getOpcode() == AArch64::SUBXri)) {
10385 const MachineOperand &MO = MI.getOperand(1);
10386 if (MO.isFI() && MF.getFrameInfo().hasScalableStackID(MO.getIndex()))
10387 MI.addOperand(MachineOperand::CreateReg(AArch64::VG, /*IsDef=*/false,
10388 /*IsImplicit=*/true));
10389 }
10390}
10391
10393 SelectionDAG &DAG, SDLoc DL, bool Enable, SDValue Chain, SDValue InGlue,
10394 unsigned Condition, bool InsertVectorLengthCheck) const {
10397 FuncInfo->setHasStreamingModeChanges(true);
10398
10399 auto GetCheckVL = [&](SDValue Chain, SDValue InGlue = SDValue()) -> SDValue {
10400 SmallVector<SDValue, 2> Ops = {Chain};
10401 if (InGlue)
10402 Ops.push_back(InGlue);
10403 return DAG.getNode(AArch64ISD::CHECK_MATCHING_VL, DL,
10404 DAG.getVTList(MVT::Other, MVT::Glue), Ops);
10405 };
10406
10407 if (InsertVectorLengthCheck && Enable) {
10408 // Non-streaming -> Streaming
10409 // Insert vector length check before smstart
10410 SDValue CheckVL = GetCheckVL(Chain, InGlue);
10411 Chain = CheckVL.getValue(0);
10412 InGlue = CheckVL.getValue(1);
10413 }
10414
10415 const AArch64RegisterInfo *TRI = Subtarget->getRegisterInfo();
10416 SDValue RegMask = DAG.getRegisterMask(TRI->getSMStartStopCallPreservedMask());
10417 SDValue MSROp =
10418 DAG.getTargetConstant((int32_t)AArch64SVCR::SVCRSM, DL, MVT::i32);
10419 SmallVector<SDValue> Ops = {Chain, MSROp};
10420 unsigned Opcode;
10421 if (Condition != AArch64SME::Always) {
10422 Register PStateReg = FuncInfo->getPStateSMReg();
10423 assert(PStateReg.isValid() && "PStateSM Register is invalid");
10424 SDValue PStateSM =
10425 DAG.getCopyFromReg(Chain, DL, PStateReg, MVT::i64, InGlue);
10426 // Use chain and glue from the CopyFromReg.
10427 Ops[0] = PStateSM.getValue(1);
10428 InGlue = PStateSM.getValue(2);
10429 SDValue ConditionOp = DAG.getTargetConstant(Condition, DL, MVT::i64);
10430 Opcode = Enable ? AArch64ISD::COND_SMSTART : AArch64ISD::COND_SMSTOP;
10431 Ops.push_back(ConditionOp);
10432 Ops.push_back(PStateSM);
10433 } else {
10434 Opcode = Enable ? AArch64ISD::SMSTART : AArch64ISD::SMSTOP;
10435 }
10436 Ops.push_back(RegMask);
10437
10438 if (InGlue)
10439 Ops.push_back(InGlue);
10440
10441 SDValue SMChange =
10442 DAG.getNode(Opcode, DL, DAG.getVTList(MVT::Other, MVT::Glue), Ops);
10443
10444 if (!InsertVectorLengthCheck || Enable)
10445 return SMChange;
10446
10447 // Streaming -> Non-streaming
10448 // Insert vector length check after smstop since we cannot read VL
10449 // in streaming mode
10450 return GetCheckVL(SMChange.getValue(0), SMChange.getValue(1));
10451}
10452
10455 if (!CallAttrs.caller().hasStreamingCompatibleInterface() ||
10456 CallAttrs.caller().hasStreamingBody())
10457 return AArch64SME::Always;
10458 if (CallAttrs.callee().hasNonStreamingInterface())
10460 if (CallAttrs.callee().hasStreamingInterface())
10462
10463 llvm_unreachable("Unsupported attributes");
10464}
10465
10466/// Check whether a stack argument requires lowering in a tail call.
10468 const CCValAssign &VA, SDValue Arg,
10469 ISD::ArgFlagsTy Flags, int CallOffset) {
10470 // FIXME: We should be able to handle this case, but it's not clear how to.
10471 if (Flags.isZExt() || Flags.isSExt())
10472 return true;
10473
10474 for (;;) {
10475 // Look through nodes that don't alter the bits of the incoming value.
10476 unsigned Op = Arg.getOpcode();
10477 if (Op == ISD::ZERO_EXTEND || Op == ISD::ANY_EXTEND || Op == ISD::BITCAST ||
10478 Arg->isAssert() || Op == AArch64ISD::ASSERT_ZEXT_BOOL) {
10479 Arg = Arg.getOperand(0);
10480 continue;
10481 }
10482 break;
10483 }
10484
10485 // If the argument is a load from the same immutable stack slot, we can reuse
10486 // it.
10487 if (auto *LoadNode = dyn_cast<LoadSDNode>(Arg)) {
10488 if (auto *FINode = dyn_cast<FrameIndexSDNode>(LoadNode->getBasePtr())) {
10489 const MachineFrameInfo &MFI = MF.getFrameInfo();
10490 int FI = FINode->getIndex();
10491 if (!MFI.isImmutableObjectIndex(FI))
10492 return true;
10493 if (CallOffset != MFI.getObjectOffset(FI))
10494 return true;
10495 uint64_t SizeInBits = LoadNode->getMemoryVT().getFixedSizeInBits();
10496 if (SizeInBits != VA.getValVT().getSizeInBits())
10497 return true;
10498 return false;
10499 }
10500 }
10501
10502 return true;
10503}
10504
10505/// Returns the ZA state save/use marker node necessary for \p CallAttrs.
10506static std::optional<unsigned>
10508 if (CallAttrs.requiresZASave())
10509 return AArch64ISD::REQUIRES_ZA_SAVE;
10510 if (CallAttrs.requiresPreservingZT0())
10511 return AArch64ISD::REQUIRES_ZT0_SAVE;
10512 if (CallAttrs.caller().hasZAState() || CallAttrs.caller().hasZT0State())
10513 return AArch64ISD::INOUT_ZA_USE;
10514 return std::nullopt;
10515}
10516
10517/// LowerCall - Lower a call to a callseq_start + CALL + callseq_end chain,
10518/// and add input and output parameter nodes.
10519SDValue
10520AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
10521 SmallVectorImpl<SDValue> &InVals) const {
10522 SelectionDAG &DAG = CLI.DAG;
10523 SDLoc &DL = CLI.DL;
10524 SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs;
10525 SmallVector<SDValue, 32> &OutVals = CLI.OutVals;
10526 SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins;
10527 SDValue Chain = CLI.Chain;
10528 SDValue Callee = CLI.Callee;
10529 bool &IsTailCall = CLI.IsTailCall;
10530 CallingConv::ID &CallConv = CLI.CallConv;
10531 bool IsVarArg = CLI.IsVarArg;
10532 const CallBase *CB = CLI.CB;
10533
10535 MachineFunction::CallSiteInfo CSInfo;
10536 bool IsThisReturn = false;
10537
10538 AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
10539 bool TailCallOpt = MF.getTarget().Options.GuaranteedTailCallOpt;
10540 bool IsCFICall = CLI.CB && CLI.CB->isIndirectCall() && CLI.CFIType;
10541 bool IsSibCall = false;
10542 bool GuardWithBTI = false;
10543
10544 if (CLI.CB && CLI.CB->hasFnAttr(Attribute::ReturnsTwice) &&
10545 !Subtarget->noBTIAtReturnTwice()) {
10546 GuardWithBTI = FuncInfo->branchTargetEnforcement();
10547 }
10548
10549 // Analyze operands of the call, assigning locations to each operand.
10551 CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
10552
10553 if (IsVarArg) {
10554 unsigned NumArgs = Outs.size();
10555
10556 for (unsigned i = 0; i != NumArgs; ++i) {
10557 if (Outs[i].Flags.isVarArg() && Outs[i].VT.isScalableVector())
10558 report_fatal_error("Passing SVE types to variadic functions is "
10559 "currently not supported");
10560 }
10561 }
10562
10563 analyzeCallOperands(*this, Subtarget, CLI, CCInfo);
10564
10565 CCAssignFn *RetCC = CCAssignFnForReturn(CallConv);
10566 // Assign locations to each value returned by this call.
10568 CCState RetCCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
10569 *DAG.getContext());
10570 RetCCInfo.AnalyzeCallResult(Ins, RetCC);
10571
10572 // Set type id for call site info.
10573 setTypeIdForCallsiteInfo(CB, MF, CSInfo);
10574
10575 // Check callee args/returns for SVE registers and set calling convention
10576 // accordingly.
10577 if (CallConv == CallingConv::C || CallConv == CallingConv::Fast) {
10578 auto HasSVERegLoc = [](CCValAssign &Loc) {
10579 if (!Loc.isRegLoc())
10580 return false;
10581 return AArch64::ZPRRegClass.contains(Loc.getLocReg()) ||
10582 AArch64::PPRRegClass.contains(Loc.getLocReg());
10583 };
10584 if (any_of(RVLocs, HasSVERegLoc) || any_of(ArgLocs, HasSVERegLoc))
10586 }
10587
10588 // Determine whether we need any streaming mode changes.
10589 SMECallAttrs CallAttrs =
10591
10592 std::optional<unsigned> ZAMarkerNode = getZAMarkerForCall(CallAttrs);
10593
10594 if (IsTailCall) {
10595 // Check if it's really possible to do a tail call.
10596 IsTailCall = isEligibleForTailCallOptimization(CLI);
10597
10598 // A sibling call is one where we're under the usual C ABI and not planning
10599 // to change that but can still do a tail call:
10600 if (!ZAMarkerNode && !TailCallOpt && IsTailCall &&
10601 CallConv != CallingConv::Tail && CallConv != CallingConv::SwiftTail)
10602 IsSibCall = true;
10603
10604 if (IsTailCall)
10605 ++NumTailCalls;
10606 }
10607
10608 if (!IsTailCall && CLI.CB && CLI.CB->isMustTailCall())
10609 report_fatal_error("failed to perform tail call elimination on a call "
10610 "site marked musttail");
10611
10612 // Get a count of how many bytes are to be pushed on the stack.
10613 unsigned NumBytes = CCInfo.getStackSize();
10614
10615 if (IsSibCall) {
10616 // Since we're not changing the ABI to make this a tail call, the memory
10617 // operands are already available in the caller's incoming argument space.
10618 NumBytes = 0;
10619 }
10620
10621 // FPDiff is the byte offset of the call's argument area from the callee's.
10622 // Stores to callee stack arguments will be placed in FixedStackSlots offset
10623 // by this amount for a tail call. In a sibling call it must be 0 because the
10624 // caller will deallocate the entire stack and the callee still expects its
10625 // arguments to begin at SP+0. Completely unused for non-tail calls.
10626 int FPDiff = 0;
10627 const Align StackAlign = Subtarget->getFrameLowering()->getStackAlign();
10628
10629 if (IsTailCall && !IsSibCall) {
10630 unsigned NumReusableBytes = FuncInfo->getBytesInStackArgArea();
10631
10632 // FPDiff will be negative if this tail call requires more space than we
10633 // would automatically have in our incoming argument space. Positive if we
10634 // can actually shrink the stack.
10635 FPDiff = NumReusableBytes - NumBytes;
10636
10637 // Since callee will pop the argument stack as a tail call, we must keep the
10638 // popped size aligned to the stack alignment. Either or both of NumBytes
10639 // and NumReusableBytes may not have been aligned, so we further increase by
10640 // the amount needed to keep FPDiff aligned, and therefore preserve the
10641 // required alignment going into the callee.
10642 uint64_t Realign = offsetToAlignment(FPDiff, StackAlign);
10643 FPDiff -= Realign;
10644 NumBytes += Realign;
10645
10646 // Update the required reserved area if this is the tail call requiring the
10647 // most argument stack space.
10648 if (FPDiff < 0 && FuncInfo->getTailCallReservedStack() < (unsigned)-FPDiff)
10649 FuncInfo->setTailCallReservedStack(-FPDiff);
10650
10651 // The stack pointer must be 16-byte aligned at all times it's used for a
10652 // memory operation, which in practice means at *all* times and in
10653 // particular across call boundaries. Therefore our own arguments started at
10654 // a 16-byte aligned SP and the delta applied for the tail call should
10655 // satisfy the same constraint.
10656 assert(FPDiff % 16 == 0 && "unaligned stack on tail call");
10657 }
10658
10659 auto DescribeCallsite =
10660 [&](OptimizationRemarkAnalysis &R) -> OptimizationRemarkAnalysis & {
10661 R << "call from '" << ore::NV("Caller", MF.getName()) << "' to '";
10662 if (auto *ES = dyn_cast<ExternalSymbolSDNode>(CLI.Callee))
10663 R << ore::NV("Callee", ES->getSymbol());
10664 else if (CLI.CB && CLI.CB->getCalledFunction())
10665 R << ore::NV("Callee", CLI.CB->getCalledFunction()->getName());
10666 else
10667 R << "unknown callee";
10668 R << "'";
10669 return R;
10670 };
10671
10672 bool RequiresSMChange = CallAttrs.requiresSMChange();
10673 if (RequiresSMChange) {
10674 OptimizationRemarkEmitter ORE(&MF.getFunction());
10675 ORE.emit([&]() {
10676 auto R = CLI.CB ? OptimizationRemarkAnalysis("sme", "SMETransition",
10677 CLI.CB)
10678 : OptimizationRemarkAnalysis("sme", "SMETransition",
10679 &MF.getFunction());
10680 DescribeCallsite(R) << " requires a streaming mode transition";
10681 return R;
10682 });
10683 }
10684
10685 auto PtrVT = getPointerTy(DAG.getDataLayout());
10686 MachineFrameInfo &MFI = MF.getFrameInfo();
10687 // If we have a variadic Arm64EC exit thunk, we must lower the x4/x5
10688 // parameters (address and length of additional arguments) into an outgoing
10689 // stack area.
10690 bool IsArm64ECVarArgExitThunk = CallConv == CallingConv::ARM64EC_Thunk_X64 &&
10691 IsVarArg &&
10692 !(CLI.CB && CLI.CB->isMustTailCall());
10693 if (IsArm64ECVarArgExitThunk) {
10694 // Materialize an aligned outgoing stack area now
10695 // so the args described by x4 (pointer) and x5 (length) can be copied
10696 // into a real x64-style stack layout.
10697 if (Outs.size() < 2)
10698 report_fatal_error("variadic arm64ec_thunk_x64 call is missing the "
10699 "x4/x5 (pointer/length) arguments");
10700 if (IsTailCall)
10701 report_fatal_error("tail calls are not supported for variadic "
10702 "arm64ec_thunk_x64 calls");
10703
10704 SDValue ThunkVarArgSrc = OutVals[Outs.size() - 2];
10705 SDValue ThunkVarArgSize =
10706 DAG.getZExtOrTrunc(OutVals[Outs.size() - 1], DL, PtrVT);
10707 SDValue RoundedThunkVarArgSize = DAG.getNode(
10708 ISD::ADD, DL, PtrVT, ThunkVarArgSize, DAG.getConstant(15, DL, PtrVT));
10709 RoundedThunkVarArgSize =
10710 DAG.getNode(ISD::AND, DL, PtrVT, RoundedThunkVarArgSize,
10711 DAG.getSignedConstant(-16, DL, PtrVT));
10712 SDValue ThunkVarArgDst = DAG.getNode(
10713 ISD::DYNAMIC_STACKALLOC, DL, DAG.getVTList(PtrVT, MVT::Other),
10714 {Chain, RoundedThunkVarArgSize, DAG.getConstant(0, DL, PtrVT)});
10715 Chain = ThunkVarArgDst.getValue(1);
10716 MFI.CreateVariableSizedObject(Align(16), nullptr);
10717
10718 // The x64 shadow store for the final thunk call is allocated by the normal
10719 // CALLSEQ_START below. Copy the variadic stack arguments before that call
10720 // sequence starts so lowering the memcpy libcall cannot create nested
10721 // ADJCALLSTACKDOWN/ADJCALLSTACKUP pairs.
10722 Chain = DAG.getMemcpy(
10723 Chain, DL, ThunkVarArgDst, ThunkVarArgSrc, ThunkVarArgSize, Align(16),
10724 Align(1), /*isVol=*/false, /*AlwaysInline=*/false,
10725 /*CI=*/nullptr, std::nullopt, MachinePointerInfo::getUnknownStack(MF),
10726 MachinePointerInfo());
10727 }
10728
10729 // Adjust the stack pointer for the new arguments... and mark ZA uses.
10730 // These operations are automatically eliminated by the prolog/epilog pass
10731 assert((!IsSibCall || !ZAMarkerNode) && "ZA markers require CALLSEQ_START");
10732 if (!IsSibCall) {
10733 Chain = DAG.getCALLSEQ_START(Chain, IsTailCall ? 0 : NumBytes, 0, DL);
10734 if (ZAMarkerNode) {
10735 // Note: We need the CALLSEQ_START to glue the ZAMarkerNode to, simply
10736 // using a chain can result in incorrect scheduling. The markers refer to
10737 // the position just before the CALLSEQ_START (though occur after as
10738 // CALLSEQ_START lacks in-glue).
10739 Chain =
10740 DAG.getNode(*ZAMarkerNode, DL, DAG.getVTList(MVT::Other, MVT::Glue),
10741 {Chain, Chain.getValue(1)});
10742 }
10743 }
10744
10745 SDValue StackPtr = DAG.getCopyFromReg(Chain, DL, AArch64::SP,
10747
10749 SmallSet<unsigned, 8> RegsUsed;
10750 SmallVector<SDValue, 8> MemOpChains;
10751
10752 if (IsVarArg && CLI.CB && CLI.CB->isMustTailCall()) {
10753 const auto &Forwards = FuncInfo->getForwardedMustTailRegParms();
10754 for (const auto &F : Forwards) {
10755 SDValue Val = DAG.getCopyFromReg(Chain, DL, F.VReg, F.VT);
10756 RegsToPass.emplace_back(F.PReg, Val);
10757 }
10758 }
10759
10760 // Walk the register/memloc assignments, inserting copies/loads.
10761 unsigned ExtraArgLocs = 0;
10762 unsigned NumThunkVarArgOperands = IsArm64ECVarArgExitThunk ? 2 : 0;
10763 for (unsigned i = 0, e = Outs.size() - NumThunkVarArgOperands; i != e; ++i) {
10764 CCValAssign &VA = ArgLocs[i - ExtraArgLocs];
10765 SDValue Arg = OutVals[i];
10766 ISD::ArgFlagsTy Flags = Outs[i].Flags;
10767
10768 // Promote the value if needed.
10769 switch (VA.getLocInfo()) {
10770 default:
10771 llvm_unreachable("Unknown loc info!");
10772 case CCValAssign::Full:
10773 break;
10774 case CCValAssign::SExt:
10775 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
10776 break;
10777 case CCValAssign::ZExt:
10778 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
10779 break;
10780 case CCValAssign::AExt:
10781 if (Outs[i].ArgVT == MVT::i1) {
10782 // AAPCS requires i1 to be zero-extended to 8-bits by the caller.
10783 //
10784 // Check if we actually have to do this, because the value may
10785 // already be zero-extended.
10786 //
10787 // We cannot just emit a (zext i8 (trunc (assert-zext i8)))
10788 // and rely on DAGCombiner to fold this, because the following
10789 // (anyext i32) is combined with (zext i8) in DAG.getNode:
10790 //
10791 // (ext (zext x)) -> (zext x)
10792 //
10793 // This will give us (zext i32), which we cannot remove, so
10794 // try to check this beforehand.
10795 if (!checkZExtBool(Arg, DAG)) {
10796 Arg = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Arg);
10797 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i8, Arg);
10798 }
10799 }
10800 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
10801 break;
10803 assert(VA.getValVT() == MVT::i32 && "only expect 32 -> 64 upper bits");
10804 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
10805 Arg = DAG.getNode(ISD::SHL, DL, VA.getLocVT(), Arg,
10806 DAG.getConstant(32, DL, VA.getLocVT()));
10807 break;
10808 case CCValAssign::BCvt:
10809 Arg = DAG.getBitcast(VA.getLocVT(), Arg);
10810 break;
10811 case CCValAssign::Trunc:
10812 Arg = DAG.getZExtOrTrunc(Arg, DL, VA.getLocVT());
10813 break;
10814 case CCValAssign::FPExt:
10815 Arg = DAG.getNode(ISD::FP_EXTEND, DL, VA.getLocVT(), Arg);
10816 break;
10818 bool isScalable = VA.getValVT().isScalableVT();
10819 assert((isScalable || Subtarget->isWindowsArm64EC()) &&
10820 "Indirect arguments should be scalable on most subtargets");
10821
10822 TypeSize StoreSize = VA.getValVT().getStoreSize();
10823 TypeSize PartSize = StoreSize;
10824 unsigned NumParts = 1;
10825 if (Outs[i].Flags.isInConsecutiveRegs()) {
10826 while (!Outs[i + NumParts - 1].Flags.isInConsecutiveRegsLast())
10827 ++NumParts;
10828 StoreSize *= NumParts;
10829 }
10830
10831 Type *Ty = EVT(VA.getValVT()).getTypeForEVT(*DAG.getContext());
10833 MachineFrameInfo &MFI = MF.getFrameInfo();
10834 int FI =
10835 MFI.CreateStackObject(StoreSize.getKnownMinValue(), Alignment, false);
10836 if (isScalable) {
10837 bool IsPred = VA.getValVT() == MVT::aarch64svcount ||
10838 VA.getValVT().getVectorElementType() == MVT::i1;
10841 }
10842
10843 MachinePointerInfo MPI = MachinePointerInfo::getFixedStack(MF, FI);
10844 SDValue Ptr = DAG.getFrameIndex(
10846 SDValue SpillSlot = Ptr;
10847
10848 // Ensure we generate all stores for each tuple part, whilst updating the
10849 // pointer after each store correctly using vscale.
10850 while (NumParts) {
10851 SDValue Store = DAG.getStore(Chain, DL, OutVals[i], Ptr, MPI);
10852 MemOpChains.push_back(Store);
10853
10854 NumParts--;
10855 if (NumParts > 0) {
10856 SDValue BytesIncrement =
10857 DAG.getTypeSize(DL, Ptr.getValueType(), PartSize);
10858 MPI = MachinePointerInfo(MPI.getAddrSpace());
10859 Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr,
10860 BytesIncrement, SDNodeFlags::NoUnsignedWrap);
10861 ExtraArgLocs++;
10862 i++;
10863 }
10864 }
10865
10866 Arg = SpillSlot;
10867 break;
10868 }
10869
10870 if (VA.isRegLoc()) {
10871 if (i == 0 && Flags.isReturned() && !Flags.isSwiftSelf() &&
10872 Outs[0].VT == MVT::i64) {
10873 assert(VA.getLocVT() == MVT::i64 &&
10874 "unexpected calling convention register assignment");
10875 assert(!Ins.empty() && Ins[0].VT == MVT::i64 &&
10876 "unexpected use of 'returned'");
10877 IsThisReturn = true;
10878 }
10879 if (RegsUsed.count(VA.getLocReg())) {
10880 // If this register has already been used then we're trying to pack
10881 // parts of an [N x i32] into an X-register. The extension type will
10882 // take care of putting the two halves in the right place but we have to
10883 // combine them.
10884 SDValue &Bits =
10885 llvm::find_if(RegsToPass,
10886 [=](const std::pair<unsigned, SDValue> &Elt) {
10887 return Elt.first == VA.getLocReg();
10888 })
10889 ->second;
10890 Bits = DAG.getNode(ISD::OR, DL, Bits.getValueType(), Bits, Arg);
10891 // Call site info is used for function's parameter entry value
10892 // tracking. For now we track only simple cases when parameter
10893 // is transferred through whole register.
10895 [&VA](MachineFunction::ArgRegPair ArgReg) {
10896 return ArgReg.Reg == VA.getLocReg();
10897 });
10898 } else {
10899 // Add an extra level of indirection for streaming mode changes by
10900 // using a pseudo copy node that cannot be rematerialised between a
10901 // smstart/smstop and the call by the simple register coalescer.
10902 if (RequiresSMChange && isPassedInFPR(Arg.getValueType()))
10903 Arg = DAG.getNode(AArch64ISD::COALESCER_BARRIER, DL,
10904 DAG.getVTList(Arg.getValueType(), MVT::Glue), Arg);
10905 RegsToPass.emplace_back(VA.getLocReg(), Arg);
10906 RegsUsed.insert(VA.getLocReg());
10907 const TargetOptions &Options = DAG.getTarget().Options;
10908 if (Options.EmitCallSiteInfo)
10909 CSInfo.ArgRegPairs.emplace_back(VA.getLocReg(), i);
10910 if (IsArm64ECVarArgExitThunk) {
10912 switch (VA.getLocReg()) {
10913 case AArch64::X0:
10914 FPReg = AArch64::D0;
10915 break;
10916 case AArch64::X1:
10917 FPReg = AArch64::D1;
10918 break;
10919 case AArch64::X2:
10920 FPReg = AArch64::D2;
10921 break;
10922 case AArch64::X3:
10923 FPReg = AArch64::D3;
10924 break;
10925 }
10926 if (FPReg) {
10927 RegsToPass.emplace_back(FPReg, Arg);
10928 RegsUsed.insert(FPReg);
10929 }
10930 }
10931 }
10932 } else {
10933 assert(VA.isMemLoc());
10934
10935 SDValue DstAddr;
10936 MachinePointerInfo DstInfo;
10937
10938 // FIXME: This works on big-endian for composite byvals, which are the
10939 // common case. It should also work for fundamental types too.
10940 uint32_t BEAlign = 0;
10941 unsigned OpSize;
10942 if (VA.getLocInfo() == CCValAssign::Indirect ||
10944 OpSize = VA.getLocVT().getFixedSizeInBits();
10945 else
10946 OpSize = Flags.isByVal() ? Flags.getByValSize() * 8
10947 : VA.getValVT().getSizeInBits();
10948 OpSize = (OpSize + 7) / 8;
10949 if (!Subtarget->isLittleEndian() && !Flags.isByVal() &&
10950 !Flags.isInConsecutiveRegs()) {
10951 if (OpSize < 8)
10952 BEAlign = 8 - OpSize;
10953 }
10954 unsigned LocMemOffset = VA.getLocMemOffset();
10955 int32_t Offset = LocMemOffset + BEAlign;
10956
10957 if (IsTailCall) {
10958 // When the frame pointer is perfectly aligned for the tail call and the
10959 // same stack argument is passed down intact, we can reuse it.
10960 if (!FPDiff && !shouldLowerTailCallStackArg(MF, VA, Arg, Flags, Offset))
10961 continue;
10962
10963 Offset = Offset + FPDiff;
10964 int FI = MF.getFrameInfo().CreateFixedObject(OpSize, Offset, true);
10965
10966 DstAddr = DAG.getFrameIndex(FI, PtrVT);
10967 DstInfo = MachinePointerInfo::getFixedStack(MF, FI);
10968
10969 // Make sure any stack arguments overlapping with where we're storing
10970 // are loaded before this eventual operation. Otherwise they'll be
10971 // clobbered.
10972 Chain = addTokenForArgument(Chain, DAG, MF.getFrameInfo(), FI);
10973 } else {
10974 SDValue PtrOff = DAG.getIntPtrConstant(Offset, DL);
10975
10976 DstAddr = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, PtrOff);
10977 DstInfo = MachinePointerInfo::getStack(MF, LocMemOffset);
10978 }
10979
10980 if (Outs[i].Flags.isByVal()) {
10981 SDValue SizeNode =
10982 DAG.getConstant(Outs[i].Flags.getByValSize(), DL, MVT::i64);
10983 SDValue Cpy = DAG.getMemcpy(
10984 Chain, DL, DstAddr, Arg, SizeNode,
10985 Outs[i].Flags.getNonZeroByValAlign(),
10986 Outs[i].Flags.getNonZeroByValAlign(),
10987 /*isVol = */ false, /*AlwaysInline = */ false,
10988 /*CI=*/nullptr, std::nullopt, DstInfo, MachinePointerInfo());
10989
10990 MemOpChains.push_back(Cpy);
10991 } else {
10992 // Since we pass i1/i8/i16 as i1/i8/i16 on stack and Arg is already
10993 // promoted to a legal register type i32, we should truncate Arg back to
10994 // i1/i8/i16.
10995 if (VA.getValVT() == MVT::i1 || VA.getValVT() == MVT::i8 ||
10996 VA.getValVT() == MVT::i16)
10997 Arg = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Arg);
10998
10999 SDValue Store = DAG.getStore(Chain, DL, Arg, DstAddr, DstInfo);
11000 MemOpChains.push_back(Store);
11001 }
11002 }
11003 }
11004
11005 if (IsVarArg && Subtarget->isWindowsArm64EC() &&
11006 !(CLI.CB && CLI.CB->isMustTailCall()) && !IsArm64ECVarArgExitThunk) {
11007 SDValue ParamPtr = StackPtr;
11008 if (IsTailCall) {
11009 // Create a dummy object at the top of the stack that can be used to get
11010 // the SP after the epilogue
11011 int FI = MF.getFrameInfo().CreateFixedObject(1, FPDiff, true);
11012 ParamPtr = DAG.getFrameIndex(FI, PtrVT);
11013 }
11014
11015 // For vararg calls, the Arm64EC ABI requires values in x4 and x5
11016 // describing the argument list. x4 contains the address of the
11017 // first stack parameter. x5 contains the size in bytes of all parameters
11018 // passed on the stack.
11019 RegsToPass.emplace_back(AArch64::X4, ParamPtr);
11020 RegsToPass.emplace_back(AArch64::X5,
11021 DAG.getConstant(NumBytes, DL, MVT::i64));
11022 }
11023
11024 if (!MemOpChains.empty())
11025 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
11026
11027 SDValue InGlue;
11028 if (RequiresSMChange) {
11029 bool InsertVectorLengthCheck =
11031 Chain = changeStreamingMode(
11032 DAG, DL, CallAttrs.callee().hasStreamingInterface(), Chain, InGlue,
11033 getSMToggleCondition(CallAttrs), InsertVectorLengthCheck);
11034 InGlue = Chain.getValue(1);
11035 }
11036
11037 // Build a sequence of copy-to-reg nodes chained together with token chain
11038 // and flag operands which copy the outgoing args into the appropriate regs.
11039 for (auto &RegToPass : RegsToPass) {
11040 Chain = DAG.getCopyToReg(Chain, DL, RegToPass.first,
11041 RegToPass.second, InGlue);
11042 InGlue = Chain.getValue(1);
11043 }
11044
11045 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
11046 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
11047 // node so that legalize doesn't hack it.
11048 const GlobalValue *CalledGlobal = nullptr;
11049 unsigned OpFlags = 0;
11050 if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
11051 CalledGlobal = G->getGlobal();
11052 OpFlags = Subtarget->classifyGlobalFunctionReference(CalledGlobal,
11054 if (OpFlags & AArch64II::MO_GOT) {
11055 Callee = DAG.getTargetGlobalAddress(CalledGlobal, DL, PtrVT, 0, OpFlags);
11056 Callee = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, Callee);
11057 } else if (!CLI.PAI || !IsTailCall) {
11058 const GlobalValue *GV = G->getGlobal();
11059 Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, OpFlags);
11060 }
11061 } else if (auto *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
11062 bool UseGot = (getTargetMachine().getCodeModel() == CodeModel::Large &&
11063 Subtarget->isTargetMachO()) ||
11065 const char *Sym = S->getSymbol();
11066 if (UseGot) {
11068 Callee = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, Callee);
11069 } else {
11070 Callee = DAG.getTargetExternalSymbol(Sym, PtrVT, 0);
11071 }
11072 }
11073
11074 // We don't usually want to end the call-sequence here because we would tidy
11075 // the frame up *after* the call, however in the ABI-changing tail-call case
11076 // we've carefully laid out the parameters so that when sp is reset they'll be
11077 // in the correct location.
11078 if (IsTailCall && !IsSibCall) {
11079 Chain = DAG.getCALLSEQ_END(Chain, 0, 0, InGlue, DL);
11080 InGlue = Chain.getValue(1);
11081 }
11082
11083 unsigned Opc = IsTailCall ? AArch64ISD::TC_RETURN : AArch64ISD::CALL;
11084
11085 std::vector<SDValue> Ops;
11086 Ops.push_back(Chain);
11087 Ops.push_back(Callee);
11088
11089 // Calls with operand bundle "clang.arc.attachedcall" are special. They should
11090 // be expanded to the call, directly followed by a special marker sequence and
11091 // a call to an ObjC library function. Use CALL_RVMARKER to do that.
11092 if (CLI.CB && objcarc::hasAttachedCallOpBundle(CLI.CB)) {
11093 assert(!IsTailCall &&
11094 "tail calls cannot be marked with clang.arc.attachedcall");
11095 Opc = AArch64ISD::CALL_RVMARKER;
11096
11097 // Add a target global address for the retainRV/claimRV runtime function
11098 // just before the call target.
11099 Function *ARCFn = *objcarc::getAttachedARCFunction(CLI.CB);
11100 auto GA = DAG.getTargetGlobalAddress(ARCFn, DL, PtrVT);
11101 Ops.insert(Ops.begin() + 1, GA);
11102
11103 // We may or may not need to emit both the marker and the retain/claim call.
11104 // Tell the pseudo expansion using an additional boolean op.
11105 bool ShouldEmitMarker = objcarc::attachedCallOpBundleNeedsMarker(CLI.CB);
11106 SDValue DoEmitMarker =
11107 DAG.getTargetConstant(ShouldEmitMarker, DL, MVT::i32);
11108 Ops.insert(Ops.begin() + 2, DoEmitMarker);
11109 } else if (CallConv == CallingConv::ARM64EC_Thunk_X64) {
11110 Opc = AArch64ISD::CALL_ARM64EC_TO_X64;
11111 } else if (GuardWithBTI) {
11112 Opc = AArch64ISD::CALL_BTI;
11113 }
11114
11115 if (IsTailCall) {
11116 // Each tail call may have to adjust the stack by a different amount, so
11117 // this information must travel along with the operation for eventual
11118 // consumption by emitEpilogue.
11119 Ops.push_back(DAG.getSignedTargetConstant(FPDiff, DL, MVT::i32));
11120 }
11121
11122 if (CLI.PAI) {
11123 const uint64_t Key = CLI.PAI->Key;
11125 "Invalid auth call key");
11126
11127 // Split the discriminator into address/integer components.
11128 SDValue AddrDisc, IntDisc;
11129 std::tie(IntDisc, AddrDisc) =
11130 extractPtrauthBlendDiscriminators(CLI.PAI->Discriminator, &DAG);
11131
11132 if (Opc == AArch64ISD::CALL_RVMARKER)
11133 Opc = AArch64ISD::AUTH_CALL_RVMARKER;
11134 else
11135 Opc = IsTailCall ? AArch64ISD::AUTH_TC_RETURN : AArch64ISD::AUTH_CALL;
11136 Ops.push_back(DAG.getTargetConstant(Key, DL, MVT::i32));
11137 Ops.push_back(IntDisc);
11138 Ops.push_back(AddrDisc);
11139 }
11140
11141 // Add argument registers to the end of the list so that they are known live
11142 // into the call.
11143 for (auto &RegToPass : RegsToPass)
11144 Ops.push_back(DAG.getRegister(RegToPass.first,
11145 RegToPass.second.getValueType()));
11146
11147 // Add a register mask operand representing the call-preserved registers.
11148 const uint32_t *Mask;
11149 const AArch64RegisterInfo *TRI = Subtarget->getRegisterInfo();
11150 if (IsThisReturn) {
11151 // For 'this' returns, use the X0-preserving mask if applicable
11152 Mask = TRI->getThisReturnPreservedMask(MF, CallConv);
11153 if (!Mask) {
11154 IsThisReturn = false;
11155 Mask = TRI->getCallPreservedMask(MF, CallConv);
11156 }
11157 } else
11158 Mask = TRI->getCallPreservedMask(MF, CallConv);
11159
11160 if (Subtarget->hasCustomCallingConv())
11161 TRI->UpdateCustomCallPreservedMask(MF, &Mask);
11162
11163 if (TRI->isAnyArgRegReserved(MF))
11164 TRI->emitReservedArgRegCallError(MF);
11165
11166 assert(Mask && "Missing call preserved mask for calling convention");
11167 Ops.push_back(DAG.getRegisterMask(Mask));
11168
11169 if (InGlue.getNode())
11170 Ops.push_back(InGlue);
11171
11172 if (CLI.DeactivationSymbol)
11173 Ops.push_back(DAG.getDeactivationSymbol(CLI.DeactivationSymbol));
11174
11175 // If we're doing a tall call, use a TC_RETURN here rather than an
11176 // actual call instruction.
11177 if (IsTailCall) {
11179 SDValue Ret = DAG.getNode(Opc, DL, MVT::Other, Ops);
11180 if (IsCFICall)
11181 Ret->setCFIType(CLI.CFIType->getZExtValue());
11182
11183 DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge);
11184 DAG.addCallSiteInfo(Ret.getNode(), std::move(CSInfo));
11185 if (CalledGlobal &&
11186 MF.getFunction().getParent()->getModuleFlag("import-call-optimization"))
11187 DAG.addCalledGlobal(Ret.getNode(), CalledGlobal, OpFlags);
11188 return Ret;
11189 }
11190
11191 // Returns a chain and a flag for retval copy to use.
11192 Chain = DAG.getNode(Opc, DL, {MVT::Other, MVT::Glue}, Ops);
11193 if (IsCFICall)
11194 Chain->setCFIType(CLI.CFIType->getZExtValue());
11195
11196 DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
11197 InGlue = Chain.getValue(1);
11198 DAG.addCallSiteInfo(Chain.getNode(), std::move(CSInfo));
11199 if (CalledGlobal &&
11200 MF.getFunction().getParent()->getModuleFlag("import-call-optimization"))
11201 DAG.addCalledGlobal(Chain.getNode(), CalledGlobal, OpFlags);
11202
11203 uint64_t CalleePopBytes =
11204 DoesCalleeRestoreStack(CallConv, TailCallOpt) ? alignTo(NumBytes, 16) : 0;
11205
11206 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, DL);
11207 InGlue = Chain.getValue(1);
11208
11209 // Handle result values, copying them out of physregs into vregs that we
11210 // return.
11211 SDValue Result = LowerCallResult(
11212 Chain, InGlue, CallConv, IsVarArg, RVLocs, DL, DAG, InVals, IsThisReturn,
11213 IsThisReturn ? OutVals[0] : SDValue(), RequiresSMChange);
11214
11215 if (!Ins.empty())
11216 InGlue = Result.getValue(Result->getNumValues() - 1);
11217
11218 if (RequiresSMChange) {
11220 DAG, DL, !CallAttrs.callee().hasStreamingInterface(), Result, InGlue,
11222 }
11223
11224 if (RequiresSMChange) {
11225 for (unsigned I = 0; I < InVals.size(); ++I) {
11226 // The smstart/smstop is chained as part of the call, but when the
11227 // resulting chain is discarded (which happens when the call is not part
11228 // of a chain, e.g. a call to @llvm.cos()), we need to ensure the
11229 // smstart/smstop is chained to the result value. We can do that by doing
11230 // a vreg -> vreg copy.
11233 SDValue X = DAG.getCopyToReg(Result, DL, Reg, InVals[I]);
11234 InVals[I] = DAG.getCopyFromReg(X, DL, Reg,
11235 InVals[I].getValueType());
11236 }
11237 }
11238
11239 if (CallConv == CallingConv::PreserveNone) {
11240 for (const ISD::OutputArg &O : Outs) {
11241 if (O.Flags.isSwiftSelf() || O.Flags.isSwiftError() ||
11242 O.Flags.isSwiftAsync()) {
11244 DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
11245 MF.getFunction(),
11246 "Swift attributes can't be used with preserve_none",
11247 DL.getDebugLoc()));
11248 break;
11249 }
11250 }
11251 }
11252
11253 return Result;
11254}
11255
11256bool AArch64TargetLowering::CanLowerReturn(
11257 CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg,
11259 const Type *RetTy) const {
11260 CCAssignFn *RetCC = CCAssignFnForReturn(CallConv);
11262 CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
11263 return CCInfo.CheckReturn(Outs, RetCC);
11264}
11265
11266SDValue
11267AArch64TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
11268 bool isVarArg,
11270 const SmallVectorImpl<SDValue> &OutVals,
11271 const SDLoc &DL, SelectionDAG &DAG) const {
11272 auto &MF = DAG.getMachineFunction();
11273 auto *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
11274
11275 CCAssignFn *RetCC = CCAssignFnForReturn(CallConv);
11277 CCState CCInfo(CallConv, isVarArg, MF, RVLocs, *DAG.getContext());
11278 CCInfo.AnalyzeReturn(Outs, RetCC);
11279
11280 // Copy the result values into the output registers.
11281 SDValue Glue;
11283 SmallSet<unsigned, 4> RegsUsed;
11284 for (unsigned i = 0, realRVLocIdx = 0; i != RVLocs.size();
11285 ++i, ++realRVLocIdx) {
11286 CCValAssign &VA = RVLocs[i];
11287 assert(VA.isRegLoc() && "Can only return in registers!");
11288 SDValue Arg = OutVals[realRVLocIdx];
11289
11290 switch (VA.getLocInfo()) {
11291 default:
11292 llvm_unreachable("Unknown loc info!");
11293 case CCValAssign::Full:
11294 if (Outs[i].ArgVT == MVT::i1) {
11295 // AAPCS requires i1 to be zero-extended to i8 by the producer of the
11296 // value. This is strictly redundant on Darwin (which uses "zeroext
11297 // i1"), but will be optimised out before ISel.
11298 Arg = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Arg);
11299 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
11300 }
11301 break;
11302 case CCValAssign::BCvt:
11303 Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
11304 break;
11305 case CCValAssign::AExt:
11306 case CCValAssign::ZExt:
11307 Arg = DAG.getZExtOrTrunc(Arg, DL, VA.getLocVT());
11308 break;
11310 assert(VA.getValVT() == MVT::i32 && "only expect 32 -> 64 upper bits");
11311 Arg = DAG.getZExtOrTrunc(Arg, DL, VA.getLocVT());
11312 Arg = DAG.getNode(ISD::SHL, DL, VA.getLocVT(), Arg,
11313 DAG.getConstant(32, DL, VA.getLocVT()));
11314 break;
11315 }
11316
11317 if (RegsUsed.count(VA.getLocReg())) {
11318 SDValue &Bits =
11319 llvm::find_if(RetVals, [=](const std::pair<unsigned, SDValue> &Elt) {
11320 return Elt.first == VA.getLocReg();
11321 })->second;
11322 Bits = DAG.getNode(ISD::OR, DL, Bits.getValueType(), Bits, Arg);
11323 } else {
11324 RetVals.emplace_back(VA.getLocReg(), Arg);
11325 RegsUsed.insert(VA.getLocReg());
11326 }
11327 }
11328
11329 const AArch64RegisterInfo *TRI = Subtarget->getRegisterInfo();
11330
11331 // Emit SMSTOP before returning from a locally streaming function
11332 SMEAttrs FuncAttrs = FuncInfo->getSMEFnAttrs();
11333 if (FuncAttrs.hasStreamingBody() && !FuncAttrs.hasStreamingInterface()) {
11334 if (FuncAttrs.hasStreamingCompatibleInterface())
11335 Chain = changeStreamingMode(DAG, DL, /*Enable*/ false, Chain,
11336 /*Glue*/ SDValue(),
11338 else
11339 Chain = changeStreamingMode(DAG, DL, /*Enable*/ false, Chain,
11340 /*Glue*/ SDValue(), AArch64SME::Always);
11341 Glue = Chain.getValue(1);
11342 }
11343
11344 SmallVector<SDValue, 4> RetOps(1, Chain);
11345 for (auto &RetVal : RetVals) {
11346 if (FuncAttrs.hasStreamingBody() && !FuncAttrs.hasStreamingInterface() &&
11347 isPassedInFPR(RetVal.second.getValueType()))
11348 RetVal.second =
11349 DAG.getNode(AArch64ISD::COALESCER_BARRIER, DL,
11350 DAG.getVTList(RetVal.second.getValueType(), MVT::Glue),
11351 RetVal.second);
11352 Chain = DAG.getCopyToReg(Chain, DL, RetVal.first, RetVal.second, Glue);
11353 Glue = Chain.getValue(1);
11354 RetOps.push_back(
11355 DAG.getRegister(RetVal.first, RetVal.second.getValueType()));
11356 }
11357
11358 // Windows AArch64 ABIs require that for returning structs by value we copy
11359 // the sret argument into X0 for the return.
11360 // We saved the argument into a virtual register in the entry block,
11361 // so now we copy the value out and into X0.
11362 if (unsigned SRetReg = FuncInfo->getSRetReturnReg()) {
11363 SDValue Val = DAG.getCopyFromReg(RetOps[0], DL, SRetReg,
11365
11366 unsigned RetValReg = AArch64::X0;
11367 if (CallConv == CallingConv::ARM64EC_Thunk_X64)
11368 RetValReg = AArch64::X8;
11369 Chain = DAG.getCopyToReg(Chain, DL, RetValReg, Val, Glue);
11370 Glue = Chain.getValue(1);
11371
11372 RetOps.push_back(
11373 DAG.getRegister(RetValReg, getPointerTy(DAG.getDataLayout())));
11374 }
11375
11376 const MCPhysReg *I = TRI->getCalleeSavedRegsViaCopy(&MF);
11377 if (I) {
11378 for (; *I; ++I) {
11379 if (AArch64::GPR64RegClass.contains(*I))
11380 RetOps.push_back(DAG.getRegister(*I, MVT::i64));
11381 else if (AArch64::FPR64RegClass.contains(*I))
11382 RetOps.push_back(DAG.getRegister(*I, MVT::getFloatingPointVT(64)));
11383 else
11384 llvm_unreachable("Unexpected register class in CSRsViaCopy!");
11385 }
11386 }
11387
11388 RetOps[0] = Chain; // Update chain.
11389
11390 // Add the glue if we have it.
11391 if (Glue.getNode())
11392 RetOps.push_back(Glue);
11393
11394 if (CallConv == CallingConv::ARM64EC_Thunk_X64) {
11395 // ARM64EC entry thunks use a special return sequence: instead of a regular
11396 // "ret" instruction, they need to explicitly call the emulator.
11397 EVT PtrVT = getPointerTy(DAG.getDataLayout());
11398 SDValue Arm64ECRetDest =
11399 DAG.getExternalSymbol("__os_arm64x_dispatch_ret", PtrVT);
11400 Arm64ECRetDest =
11401 getAddr(cast<ExternalSymbolSDNode>(Arm64ECRetDest), DAG, 0);
11402 Arm64ECRetDest = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Arm64ECRetDest,
11403 MachinePointerInfo());
11404 RetOps.insert(RetOps.begin() + 1, Arm64ECRetDest);
11405 RetOps.insert(RetOps.begin() + 2, DAG.getTargetConstant(0, DL, MVT::i32));
11406 return DAG.getNode(AArch64ISD::TC_RETURN, DL, MVT::Other, RetOps);
11407 }
11408
11409 return DAG.getNode(AArch64ISD::RET_GLUE, DL, MVT::Other, RetOps);
11410}
11411
11412//===----------------------------------------------------------------------===//
11413// Other Lowering Code
11414//===----------------------------------------------------------------------===//
11415
11416SDValue AArch64TargetLowering::getTargetNode(GlobalAddressSDNode *N, EVT Ty,
11417 SelectionDAG &DAG,
11418 unsigned Flag) const {
11419 return DAG.getTargetGlobalAddress(N->getGlobal(), SDLoc(N), Ty,
11420 N->getOffset(), Flag);
11421}
11422
11423SDValue AArch64TargetLowering::getTargetNode(JumpTableSDNode *N, EVT Ty,
11424 SelectionDAG &DAG,
11425 unsigned Flag) const {
11426 return DAG.getTargetJumpTable(N->getIndex(), Ty, Flag);
11427}
11428
11429SDValue AArch64TargetLowering::getTargetNode(ConstantPoolSDNode *N, EVT Ty,
11430 SelectionDAG &DAG,
11431 unsigned Flag) const {
11432 return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(),
11433 N->getOffset(), Flag);
11434}
11435
11436SDValue AArch64TargetLowering::getTargetNode(BlockAddressSDNode* N, EVT Ty,
11437 SelectionDAG &DAG,
11438 unsigned Flag) const {
11439 return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, 0, Flag);
11440}
11441
11442SDValue AArch64TargetLowering::getTargetNode(ExternalSymbolSDNode *N, EVT Ty,
11443 SelectionDAG &DAG,
11444 unsigned Flag) const {
11445 return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flag);
11446}
11447
11448// (loadGOT sym)
11449template <class NodeTy>
11450SDValue AArch64TargetLowering::getGOT(NodeTy *N, SelectionDAG &DAG,
11451 unsigned Flags) const {
11452 LLVM_DEBUG(dbgs() << "AArch64TargetLowering::getGOT\n");
11453 SDLoc DL(N);
11454 EVT Ty = getPointerTy(DAG.getDataLayout());
11455 SDValue GotAddr = getTargetNode(N, Ty, DAG, AArch64II::MO_GOT | Flags);
11456 // FIXME: Once remat is capable of dealing with instructions with register
11457 // operands, expand this into two nodes instead of using a wrapper node.
11458 if (DAG.getMachineFunction()
11459 .getInfo<AArch64FunctionInfo>()
11460 ->hasELFSignedGOT())
11461 return SDValue(DAG.getMachineNode(AArch64::LOADgotAUTH, DL, Ty, GotAddr),
11462 0);
11463 return DAG.getNode(AArch64ISD::LOADgot, DL, Ty, GotAddr);
11464}
11465
11466// (wrapper %highest(sym), %higher(sym), %hi(sym), %lo(sym))
11467template <class NodeTy>
11468SDValue AArch64TargetLowering::getAddrLarge(NodeTy *N, SelectionDAG &DAG,
11469 unsigned Flags) const {
11470 LLVM_DEBUG(dbgs() << "AArch64TargetLowering::getAddrLarge\n");
11471 SDLoc DL(N);
11472 EVT Ty = getPointerTy(DAG.getDataLayout());
11473 const unsigned char MO_NC = AArch64II::MO_NC;
11474 return DAG.getNode(
11475 AArch64ISD::WrapperLarge, DL, Ty,
11476 getTargetNode(N, Ty, DAG, AArch64II::MO_G3 | Flags),
11477 getTargetNode(N, Ty, DAG, AArch64II::MO_G2 | MO_NC | Flags),
11478 getTargetNode(N, Ty, DAG, AArch64II::MO_G1 | MO_NC | Flags),
11479 getTargetNode(N, Ty, DAG, AArch64II::MO_G0 | MO_NC | Flags));
11480}
11481
11482// (addlow (adrp %hi(sym)) %lo(sym))
11483template <class NodeTy>
11484SDValue AArch64TargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
11485 unsigned Flags) const {
11486 LLVM_DEBUG(dbgs() << "AArch64TargetLowering::getAddr\n");
11487 SDLoc DL(N);
11488 EVT Ty = getPointerTy(DAG.getDataLayout());
11489 SDValue Hi = getTargetNode(N, Ty, DAG, AArch64II::MO_PAGE | Flags);
11490 SDValue Lo = getTargetNode(N, Ty, DAG,
11492 SDValue ADRP = DAG.getNode(AArch64ISD::ADRP, DL, Ty, Hi);
11493 return DAG.getNode(AArch64ISD::ADDlow, DL, Ty, ADRP, Lo);
11494}
11495
11496// (adr sym)
11497template <class NodeTy>
11498SDValue AArch64TargetLowering::getAddrTiny(NodeTy *N, SelectionDAG &DAG,
11499 unsigned Flags) const {
11500 LLVM_DEBUG(dbgs() << "AArch64TargetLowering::getAddrTiny\n");
11501 SDLoc DL(N);
11502 EVT Ty = getPointerTy(DAG.getDataLayout());
11503 SDValue Sym = getTargetNode(N, Ty, DAG, Flags);
11504 return DAG.getNode(AArch64ISD::ADR, DL, Ty, Sym);
11505}
11506
11507SDValue AArch64TargetLowering::LowerGlobalAddress(SDValue Op,
11508 SelectionDAG &DAG) const {
11509 GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);
11510 const GlobalValue *GV = GN->getGlobal();
11511 unsigned OpFlags = Subtarget->ClassifyGlobalReference(GV, getTargetMachine());
11512
11513 if (OpFlags != AArch64II::MO_NO_FLAG)
11515 "unexpected offset in global node");
11516
11517 // This also catches the large code model case for Darwin, and tiny code
11518 // model with got relocations.
11519 if ((OpFlags & AArch64II::MO_GOT) != 0) {
11520 return getGOT(GN, DAG, OpFlags);
11521 }
11522
11526 Result = getAddrLarge(GN, DAG, OpFlags);
11527 } else if (getTargetMachine().getCodeModel() == CodeModel::Tiny) {
11528 Result = getAddrTiny(GN, DAG, OpFlags);
11529 } else {
11530 Result = getAddr(GN, DAG, OpFlags);
11531 }
11532 EVT PtrVT = getPointerTy(DAG.getDataLayout());
11533 SDLoc DL(GN);
11535 Result = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Result,
11537 return Result;
11538}
11539
11540/// Convert a TLS address reference into the correct sequence of loads
11541/// and calls to compute the variable's address (for Darwin, currently) and
11542/// return an SDValue containing the final node.
11543
11544/// Darwin only has one TLS scheme which must be capable of dealing with the
11545/// fully general situation, in the worst case. This means:
11546/// + "extern __thread" declaration.
11547/// + Defined in a possibly unknown dynamic library.
11548///
11549/// The general system is that each __thread variable has a [3 x i64] descriptor
11550/// which contains information used by the runtime to calculate the address. The
11551/// only part of this the compiler needs to know about is the first xword, which
11552/// contains a function pointer that must be called with the address of the
11553/// entire descriptor in "x0".
11554///
11555/// Since this descriptor may be in a different unit, in general even the
11556/// descriptor must be accessed via an indirect load. The "ideal" code sequence
11557/// is:
11558/// adrp x0, _var@TLVPPAGE
11559/// ldr x0, [x0, _var@TLVPPAGEOFF] ; x0 now contains address of descriptor
11560/// ldr x1, [x0] ; x1 contains 1st entry of descriptor,
11561/// ; the function pointer
11562/// blr x1 ; Uses descriptor address in x0
11563/// ; Address of _var is now in x0.
11564///
11565/// If the address of _var's descriptor *is* known to the linker, then it can
11566/// change the first "ldr" instruction to an appropriate "add x0, x0, #imm" for
11567/// a slight efficiency gain.
11568SDValue
11569AArch64TargetLowering::LowerDarwinGlobalTLSAddress(SDValue Op,
11570 SelectionDAG &DAG) const {
11571 assert(Subtarget->isTargetDarwin() &&
11572 "This function expects a Darwin target");
11573
11574 SDLoc DL(Op);
11575 MVT PtrVT = getPointerTy(DAG.getDataLayout());
11576 MVT PtrMemVT = getPointerMemTy(DAG.getDataLayout());
11577 const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
11578
11579 SDValue TLVPAddr =
11580 DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, AArch64II::MO_TLS);
11581 SDValue DescAddr = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, TLVPAddr);
11582
11583 // The first entry in the descriptor is a function pointer that we must call
11584 // to obtain the address of the variable.
11585 SDValue Chain = DAG.getEntryNode();
11586 SDValue FuncTLVGet = DAG.getLoad(
11587 PtrMemVT, DL, Chain, DescAddr,
11589 Align(PtrMemVT.getSizeInBits() / 8),
11591 Chain = FuncTLVGet.getValue(1);
11592
11593 // Extend loaded pointer if necessary (i.e. if ILP32) to DAG pointer.
11594 FuncTLVGet = DAG.getZExtOrTrunc(FuncTLVGet, DL, PtrVT);
11595
11596 MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
11597 MFI.setAdjustsStack(true);
11598
11599 // TLS calls preserve all registers except those that absolutely must be
11600 // trashed: X0 (it takes an argument), LR (it's a call) and NZCV (let's not be
11601 // silly).
11602 const AArch64RegisterInfo *TRI = Subtarget->getRegisterInfo();
11603 const uint32_t *Mask = TRI->getTLSCallPreservedMask();
11604 if (Subtarget->hasCustomCallingConv())
11605 TRI->UpdateCustomCallPreservedMask(DAG.getMachineFunction(), &Mask);
11606
11607 // Finally, we can make the call. This is just a degenerate version of a
11608 // normal AArch64 call node: x0 takes the address of the descriptor, and
11609 // returns the address of the variable in this thread.
11610 Chain = DAG.getCopyToReg(Chain, DL, AArch64::X0, DescAddr, SDValue());
11611
11612 auto &MF = DAG.getMachineFunction();
11613 auto *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
11614
11615 SMECallAttrs TLSCallAttrs(FuncInfo->getSMEFnAttrs(), {}, SMEAttrs::Normal);
11616 bool RequiresSMChange = TLSCallAttrs.requiresSMChange();
11617
11618 if (RequiresSMChange)
11619 Chain =
11620 changeStreamingMode(DAG, DL, /*Enable=*/false, Chain, Chain.getValue(1),
11621 getSMToggleCondition(TLSCallAttrs));
11622
11623 unsigned Opcode = AArch64ISD::CALL;
11625 Ops.push_back(Chain);
11626 Ops.push_back(FuncTLVGet);
11627
11628 // With ptrauth-calls, the tlv access thunk pointer is authenticated (IA, 0).
11629 if (DAG.getMachineFunction().getFunction().hasFnAttribute("ptrauth-calls")) {
11630 Opcode = AArch64ISD::AUTH_CALL;
11631 Ops.push_back(DAG.getTargetConstant(AArch64PACKey::IA, DL, MVT::i32));
11632 Ops.push_back(DAG.getTargetConstant(0, DL, MVT::i64)); // Integer Disc.
11633 Ops.push_back(DAG.getRegister(AArch64::NoRegister, MVT::i64)); // Addr Disc.
11634 }
11635
11636 Ops.push_back(DAG.getRegister(AArch64::X0, MVT::i64));
11637 Ops.push_back(DAG.getRegisterMask(Mask));
11638 Ops.push_back(Chain.getValue(1));
11639 Chain = DAG.getNode(Opcode, DL, DAG.getVTList(MVT::Other, MVT::Glue), Ops);
11640
11641 if (std::optional<unsigned> ZAMarkerNode = getZAMarkerForCall(TLSCallAttrs))
11642 Chain = DAG.getNode(*ZAMarkerNode, DL, DAG.getVTList(MVT::Other, MVT::Glue),
11643 {Chain, Chain.getValue(1)});
11644
11645 if (RequiresSMChange)
11646 Chain =
11647 changeStreamingMode(DAG, DL, /*Enable=*/true, Chain, Chain.getValue(1),
11648 getSMToggleCondition(TLSCallAttrs));
11649
11650 return DAG.getCopyFromReg(Chain, DL, AArch64::X0, PtrVT, Chain.getValue(1));
11651}
11652
11653/// Convert a thread-local variable reference into a sequence of instructions to
11654/// compute the variable's address for the local exec TLS model of ELF targets.
11655/// The sequence depends on the maximum TLS area size.
11656SDValue AArch64TargetLowering::LowerELFTLSLocalExec(const GlobalValue *GV,
11657 SDValue ThreadBase,
11658 const SDLoc &DL,
11659 SelectionDAG &DAG) const {
11660 EVT PtrVT = getPointerTy(DAG.getDataLayout());
11661 SDValue TPOff, Addr;
11662
11663 switch (DAG.getTarget().Options.TLSSize) {
11664 default:
11665 llvm_unreachable("Unexpected TLS size");
11666
11667 case 12: {
11668 // mrs x0, TPIDR_EL0
11669 // add x0, x0, :tprel_lo12:a
11671 GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_PAGEOFF);
11672 return SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, ThreadBase,
11673 Var,
11674 DAG.getTargetConstant(0, DL, MVT::i32)),
11675 0);
11676 }
11677
11678 case 24: {
11679 // mrs x0, TPIDR_EL0
11680 // add x0, x0, :tprel_hi12:a
11681 // add x0, x0, :tprel_lo12_nc:a
11682 SDValue HiVar = DAG.getTargetGlobalAddress(
11683 GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_HI12);
11684 SDValue LoVar = DAG.getTargetGlobalAddress(
11685 GV, DL, PtrVT, 0,
11687 Addr = SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, ThreadBase,
11688 HiVar,
11689 DAG.getTargetConstant(0, DL, MVT::i32)),
11690 0);
11691 return SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, Addr, LoVar,
11692 DAG.getTargetConstant(0, DL, MVT::i32)),
11693 0);
11694 }
11695
11696 case 32: {
11697 // mrs x1, TPIDR_EL0
11698 // movz x0, #:tprel_g1:a
11699 // movk x0, #:tprel_g0_nc:a
11700 // add x0, x1, x0
11701 SDValue HiVar = DAG.getTargetGlobalAddress(
11702 GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_G1);
11703 SDValue LoVar = DAG.getTargetGlobalAddress(
11704 GV, DL, PtrVT, 0,
11706 TPOff = SDValue(DAG.getMachineNode(AArch64::MOVZXi, DL, PtrVT, HiVar,
11707 DAG.getTargetConstant(16, DL, MVT::i32)),
11708 0);
11709 TPOff = SDValue(DAG.getMachineNode(AArch64::MOVKXi, DL, PtrVT, TPOff, LoVar,
11710 DAG.getTargetConstant(0, DL, MVT::i32)),
11711 0);
11712 return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadBase, TPOff);
11713 }
11714
11715 case 48: {
11716 // mrs x1, TPIDR_EL0
11717 // movz x0, #:tprel_g2:a
11718 // movk x0, #:tprel_g1_nc:a
11719 // movk x0, #:tprel_g0_nc:a
11720 // add x0, x1, x0
11721 SDValue HiVar = DAG.getTargetGlobalAddress(
11722 GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_G2);
11723 SDValue MiVar = DAG.getTargetGlobalAddress(
11724 GV, DL, PtrVT, 0,
11726 SDValue LoVar = DAG.getTargetGlobalAddress(
11727 GV, DL, PtrVT, 0,
11729 TPOff = SDValue(DAG.getMachineNode(AArch64::MOVZXi, DL, PtrVT, HiVar,
11730 DAG.getTargetConstant(32, DL, MVT::i32)),
11731 0);
11732 TPOff = SDValue(DAG.getMachineNode(AArch64::MOVKXi, DL, PtrVT, TPOff, MiVar,
11733 DAG.getTargetConstant(16, DL, MVT::i32)),
11734 0);
11735 TPOff = SDValue(DAG.getMachineNode(AArch64::MOVKXi, DL, PtrVT, TPOff, LoVar,
11736 DAG.getTargetConstant(0, DL, MVT::i32)),
11737 0);
11738 return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadBase, TPOff);
11739 }
11740 }
11741}
11742
11743/// When accessing thread-local variables under either the general-dynamic or
11744/// local-dynamic system, we make a "TLS-descriptor" call. The variable will
11745/// have a descriptor, accessible via a PC-relative ADRP, and whose first entry
11746/// is a function pointer to carry out the resolution.
11747///
11748/// The sequence is:
11749/// adrp x0, :tlsdesc:var
11750/// ldr x1, [x0, #:tlsdesc_lo12:var]
11751/// add x0, x0, #:tlsdesc_lo12:var
11752/// .tlsdesccall var
11753/// blr x1
11754/// (TPIDR_EL0 offset now in x0)
11755///
11756/// The above sequence must be produced unscheduled, to enable the linker to
11757/// optimize/relax this sequence.
11758/// Therefore, a pseudo-instruction (TLSDESC_CALLSEQ) is used to represent the
11759/// above sequence, and expanded really late in the compilation flow, to ensure
11760/// the sequence is produced as per above.
11761SDValue AArch64TargetLowering::LowerELFTLSDescCallSeq(SDValue SymAddr,
11762 const SDLoc &DL,
11763 SelectionDAG &DAG) const {
11764 EVT PtrVT = getPointerTy(DAG.getDataLayout());
11765 auto &MF = DAG.getMachineFunction();
11766 auto *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
11767
11768 SDValue Glue;
11769 SDValue Chain = DAG.getEntryNode();
11770 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
11771
11772 SMECallAttrs TLSCallAttrs(FuncInfo->getSMEFnAttrs(), {}, SMEAttrs::Normal);
11773 std::optional<unsigned> ZAMarkerNode = getZAMarkerForCall(TLSCallAttrs);
11774 bool RequiresSMChange = TLSCallAttrs.requiresSMChange();
11775
11776 auto ChainAndGlue = [](SDValue Chain) -> std::pair<SDValue, SDValue> {
11777 return {Chain, Chain.getValue(1)};
11778 };
11779
11780 if (RequiresSMChange)
11781 std::tie(Chain, Glue) =
11782 ChainAndGlue(changeStreamingMode(DAG, DL, /*Enable=*/false, Chain, Glue,
11783 getSMToggleCondition(TLSCallAttrs)));
11784
11785 unsigned Opcode =
11786 DAG.getMachineFunction().getInfo<AArch64FunctionInfo>()->hasELFSignedGOT()
11787 ? AArch64ISD::TLSDESC_AUTH_CALLSEQ
11788 : AArch64ISD::TLSDESC_CALLSEQ;
11789 SDValue Ops[] = {Chain, SymAddr, Glue};
11790 std::tie(Chain, Glue) = ChainAndGlue(DAG.getNode(
11791 Opcode, DL, NodeTys, Glue ? ArrayRef(Ops) : ArrayRef(Ops).drop_back()));
11792
11793 if (ZAMarkerNode)
11794 std::tie(Chain, Glue) = ChainAndGlue(
11795 DAG.getNode(*ZAMarkerNode, DL, NodeTys, {Chain, Chain.getValue(1)}));
11796
11797 if (RequiresSMChange)
11798 std::tie(Chain, Glue) =
11799 ChainAndGlue(changeStreamingMode(DAG, DL, /*Enable=*/true, Chain, Glue,
11800 getSMToggleCondition(TLSCallAttrs)));
11801
11802 return DAG.getCopyFromReg(Chain, DL, AArch64::X0, PtrVT, Glue);
11803}
11804
11805SDValue
11806AArch64TargetLowering::LowerELFGlobalTLSAddress(SDValue Op,
11807 SelectionDAG &DAG) const {
11808 assert(Subtarget->isTargetELF() && "This function expects an ELF target");
11809
11810 const GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
11811 AArch64FunctionInfo *MFI =
11812 DAG.getMachineFunction().getInfo<AArch64FunctionInfo>();
11813
11817
11819 if (Model == TLSModel::LocalDynamic)
11821 }
11822
11824 Model != TLSModel::LocalExec)
11825 report_fatal_error("ELF TLS only supported in small memory model or "
11826 "in local exec TLS model");
11827 // Different choices can be made for the maximum size of the TLS area for a
11828 // module. For the small address model, the default TLS size is 16MiB and the
11829 // maximum TLS size is 4GiB.
11830 // FIXME: add tiny and large code model support for TLS access models other
11831 // than local exec. We currently generate the same code as small for tiny,
11832 // which may be larger than needed.
11833
11834 SDValue TPOff;
11835 EVT PtrVT = getPointerTy(DAG.getDataLayout());
11836 SDLoc DL(Op);
11837 const GlobalValue *GV = GA->getGlobal();
11838
11839 SDValue ThreadBase = DAG.getNode(AArch64ISD::THREAD_POINTER, DL, PtrVT);
11840
11841 if (Model == TLSModel::LocalExec) {
11842 return LowerELFTLSLocalExec(GV, ThreadBase, DL, DAG);
11843 } else if (Model == TLSModel::InitialExec) {
11844 TPOff = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, AArch64II::MO_TLS);
11845 TPOff = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, TPOff);
11846 } else if (Model == TLSModel::LocalDynamic) {
11847 // Local-dynamic accesses proceed in two phases. A general-dynamic TLS
11848 // descriptor call against the special symbol _TLS_MODULE_BASE_ to calculate
11849 // the beginning of the module's TLS region, followed by a DTPREL offset
11850 // calculation.
11851
11852 // These accesses will need deduplicating if there's more than one.
11854
11855 // The call needs a relocation too for linker relaxation. It doesn't make
11856 // sense to call it MO_PAGE or MO_PAGEOFF though so we need another copy of
11857 // the address.
11858 SDValue SymAddr = DAG.getTargetExternalSymbol("_TLS_MODULE_BASE_", PtrVT,
11860
11861 // Now we can calculate the offset from TPIDR_EL0 to this module's
11862 // thread-local area.
11863 TPOff = LowerELFTLSDescCallSeq(SymAddr, DL, DAG);
11864
11865 // Now use :dtprel_whatever: operations to calculate this variable's offset
11866 // in its thread-storage area.
11867 SDValue HiVar = DAG.getTargetGlobalAddress(
11868 GV, DL, MVT::i64, 0, AArch64II::MO_TLS | AArch64II::MO_HI12);
11869 SDValue LoVar = DAG.getTargetGlobalAddress(
11870 GV, DL, MVT::i64, 0,
11872
11873 TPOff = SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, TPOff, HiVar,
11874 DAG.getTargetConstant(0, DL, MVT::i32)),
11875 0);
11876 TPOff = SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, TPOff, LoVar,
11877 DAG.getTargetConstant(0, DL, MVT::i32)),
11878 0);
11879 } else if (Model == TLSModel::GeneralDynamic) {
11880 // The call needs a relocation too for linker relaxation. It doesn't make
11881 // sense to call it MO_PAGE or MO_PAGEOFF though so we need another copy of
11882 // the address.
11883 SDValue SymAddr =
11884 DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, AArch64II::MO_TLS);
11885
11886 // Finally we can make a call to calculate the offset from tpidr_el0.
11887 TPOff = LowerELFTLSDescCallSeq(SymAddr, DL, DAG);
11888 } else
11889 llvm_unreachable("Unsupported ELF TLS access model");
11890
11891 return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadBase, TPOff);
11892}
11893
11894SDValue
11895AArch64TargetLowering::LowerWindowsGlobalTLSAddress(SDValue Op,
11896 SelectionDAG &DAG) const {
11897 assert(Subtarget->isTargetWindows() && "Windows specific TLS lowering");
11898
11899 SDValue Chain = DAG.getEntryNode();
11900 EVT PtrVT = getPointerTy(DAG.getDataLayout());
11901 SDLoc DL(Op);
11902
11903 SDValue TEB = DAG.getRegister(AArch64::X18, MVT::i64);
11904
11905 // Load the ThreadLocalStoragePointer from the TEB
11906 // A pointer to the TLS array is located at offset 0x58 from the TEB.
11907 SDValue TLSArray =
11908 DAG.getNode(ISD::ADD, DL, PtrVT, TEB, DAG.getIntPtrConstant(0x58, DL));
11909 TLSArray = DAG.getLoad(PtrVT, DL, Chain, TLSArray, MachinePointerInfo());
11910 Chain = TLSArray.getValue(1);
11911
11912 // Load the TLS index from the C runtime;
11913 // This does the same as getAddr(), but without having a GlobalAddressSDNode.
11914 // This also does the same as LOADgot, but using a generic i32 load,
11915 // while LOADgot only loads i64.
11916 SDValue TLSIndexHi =
11917 DAG.getTargetExternalSymbol("_tls_index", PtrVT, AArch64II::MO_PAGE);
11918 SDValue TLSIndexLo = DAG.getTargetExternalSymbol(
11919 "_tls_index", PtrVT, AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
11920 SDValue ADRP = DAG.getNode(AArch64ISD::ADRP, DL, PtrVT, TLSIndexHi);
11921 SDValue TLSIndex =
11922 DAG.getNode(AArch64ISD::ADDlow, DL, PtrVT, ADRP, TLSIndexLo);
11923 TLSIndex = DAG.getLoad(MVT::i32, DL, Chain, TLSIndex, MachinePointerInfo());
11924 Chain = TLSIndex.getValue(1);
11925
11926 // The pointer to the thread's TLS data area is at the TLS Index scaled by 8
11927 // offset into the TLSArray.
11928 TLSIndex = DAG.getNode(ISD::ZERO_EXTEND, DL, PtrVT, TLSIndex);
11929 SDValue Slot = DAG.getNode(ISD::SHL, DL, PtrVT, TLSIndex,
11930 DAG.getConstant(3, DL, PtrVT));
11931 SDValue TLS = DAG.getLoad(PtrVT, DL, Chain,
11932 DAG.getNode(ISD::ADD, DL, PtrVT, TLSArray, Slot),
11933 MachinePointerInfo());
11934 Chain = TLS.getValue(1);
11935
11936 const GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
11937 const GlobalValue *GV = GA->getGlobal();
11938 SDValue TGAHi = DAG.getTargetGlobalAddress(
11939 GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_HI12);
11940 SDValue TGALo = DAG.getTargetGlobalAddress(
11941 GV, DL, PtrVT, 0,
11943
11944 // Add the offset from the start of the .tls section (section base).
11945 SDValue Addr =
11946 SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, TLS, TGAHi,
11947 DAG.getTargetConstant(0, DL, MVT::i32)),
11948 0);
11949 Addr = DAG.getNode(AArch64ISD::ADDlow, DL, PtrVT, Addr, TGALo);
11950 return Addr;
11951}
11952
11953SDValue AArch64TargetLowering::LowerGlobalTLSAddress(SDValue Op,
11954 SelectionDAG &DAG) const {
11955 const GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
11956 if (DAG.getTarget().useEmulatedTLS())
11957 return LowerToTLSEmulatedModel(GA, DAG);
11958
11959 if (Subtarget->isTargetDarwin())
11960 return LowerDarwinGlobalTLSAddress(Op, DAG);
11961 if (Subtarget->isTargetELF())
11962 return LowerELFGlobalTLSAddress(Op, DAG);
11963 if (Subtarget->isTargetWindows())
11964 return LowerWindowsGlobalTLSAddress(Op, DAG);
11965
11966 llvm_unreachable("Unexpected platform trying to use TLS");
11967}
11968
11969//===----------------------------------------------------------------------===//
11970// PtrAuthGlobalAddress lowering
11971//
11972// We have 3 lowering alternatives to choose from:
11973// - MOVaddrPAC: similar to MOVaddr, with added PAC.
11974// If the GV doesn't need a GOT load (i.e., is locally defined)
11975// materialize the pointer using adrp+add+pac. See LowerMOVaddrPAC.
11976//
11977// - LOADgotPAC: similar to LOADgot, with added PAC.
11978// If the GV needs a GOT load, materialize the pointer using the usual
11979// GOT adrp+ldr, +pac. Pointers in GOT are assumed to be not signed, the GOT
11980// section is assumed to be read-only (for example, via relro mechanism). See
11981// LowerMOVaddrPAC.
11982//
11983// - LOADauthptrstatic: similar to LOADgot, but use a
11984// special stub slot instead of a GOT slot.
11985// Load a signed pointer for symbol 'sym' from a stub slot named
11986// 'sym$auth_ptr$key$disc' filled by dynamic linker during relocation
11987// resolving. This usually lowers to adrp+ldr, but also emits an entry into
11988// .data with an @AUTH relocation. See LowerLOADauthptrstatic.
11989//
11990// All 3 are pseudos that are expand late to longer sequences: this lets us
11991// provide integrity guarantees on the to-be-signed intermediate values.
11992//
11993// LOADauthptrstatic is undesirable because it requires a large section filled
11994// with often similarly-signed pointers, making it a good harvesting target.
11995// Thus, it's only used for ptrauth references to extern_weak to avoid null
11996// checks.
11997
11999 SDValue TGA, SDLoc DL, EVT VT, AArch64PACKey::ID KeyC,
12000 SDValue Discriminator, SDValue AddrDiscriminator, SelectionDAG &DAG) {
12001 const auto *TGN = cast<GlobalAddressSDNode>(TGA.getNode());
12002 assert(TGN->getGlobal()->hasExternalWeakLinkage());
12003
12004 // Offsets and extern_weak don't mix well: ptrauth aside, you'd get the
12005 // offset alone as a pointer if the symbol wasn't available, which would
12006 // probably break null checks in users. Ptrauth complicates things further:
12007 // error out.
12008 if (TGN->getOffset() != 0)
12010 "unsupported non-zero offset in weak ptrauth global reference");
12011
12012 if (!isNullConstant(AddrDiscriminator))
12013 report_fatal_error("unsupported weak addr-div ptrauth global");
12014
12015 SDValue Key = DAG.getTargetConstant(KeyC, DL, MVT::i32);
12016 return SDValue(DAG.getMachineNode(AArch64::LOADauthptrstatic, DL, MVT::i64,
12017 {TGA, Key, Discriminator}),
12018 0);
12019}
12020
12021SDValue
12022AArch64TargetLowering::LowerPtrAuthGlobalAddress(SDValue Op,
12023 SelectionDAG &DAG) const {
12024 SDValue Ptr = Op.getOperand(0);
12025 uint64_t KeyC = Op.getConstantOperandVal(1);
12026 SDValue AddrDiscriminator = Op.getOperand(2);
12027 uint64_t DiscriminatorC = Op.getConstantOperandVal(3);
12028 EVT VT = Op.getValueType();
12029 SDLoc DL(Op);
12030
12031 if (KeyC > AArch64PACKey::LAST)
12032 report_fatal_error("key in ptrauth global out of range [0, " +
12033 Twine((int)AArch64PACKey::LAST) + "]");
12034
12035 // Blend only works if the integer discriminator is 16-bit wide.
12036 if (!isUInt<16>(DiscriminatorC))
12038 "constant discriminator in ptrauth global out of range [0, 0xffff]");
12039
12040 // Choosing between 3 lowering alternatives is target-specific.
12041 if (!Subtarget->isTargetELF() && !Subtarget->isTargetMachO())
12042 report_fatal_error("ptrauth global lowering only supported on MachO/ELF");
12043
12044 int64_t PtrOffsetC = 0;
12045 if (Ptr.getOpcode() == ISD::ADD) {
12046 PtrOffsetC = Ptr.getConstantOperandVal(1);
12047 Ptr = Ptr.getOperand(0);
12048 }
12049 const auto *PtrN = cast<GlobalAddressSDNode>(Ptr.getNode());
12050 const GlobalValue *PtrGV = PtrN->getGlobal();
12051
12052 // Classify the reference to determine whether it needs a GOT load.
12053 const unsigned OpFlags =
12054 Subtarget->ClassifyGlobalReference(PtrGV, getTargetMachine());
12055 const bool NeedsGOTLoad = ((OpFlags & AArch64II::MO_GOT) != 0);
12056 assert(((OpFlags & (~AArch64II::MO_GOT)) == 0) &&
12057 "unsupported non-GOT op flags on ptrauth global reference");
12058
12059 // Fold any offset into the GV; our pseudos expect it there.
12060 PtrOffsetC += PtrN->getOffset();
12061 SDValue TPtr = DAG.getTargetGlobalAddress(PtrGV, DL, VT, PtrOffsetC,
12062 /*TargetFlags=*/0);
12063 assert(PtrN->getTargetFlags() == 0 &&
12064 "unsupported target flags on ptrauth global");
12065
12066 SDValue Key = DAG.getTargetConstant(KeyC, DL, MVT::i32);
12067 SDValue Discriminator = DAG.getTargetConstant(DiscriminatorC, DL, MVT::i64);
12068 SDValue TAddrDiscriminator = !isNullConstant(AddrDiscriminator)
12069 ? AddrDiscriminator
12070 : DAG.getRegister(AArch64::XZR, MVT::i64);
12071
12072 // No GOT load needed -> MOVaddrPAC
12073 if (!NeedsGOTLoad) {
12074 assert(!PtrGV->hasExternalWeakLinkage() && "extern_weak should use GOT");
12075 return SDValue(
12076 DAG.getMachineNode(AArch64::MOVaddrPAC, DL, MVT::i64,
12077 {TPtr, Key, TAddrDiscriminator, Discriminator}),
12078 0);
12079 }
12080
12081 // GOT load -> LOADgotPAC
12082 // Note that we disallow extern_weak refs to avoid null checks later.
12083 if (!PtrGV->hasExternalWeakLinkage())
12084 return SDValue(
12085 DAG.getMachineNode(AArch64::LOADgotPAC, DL, MVT::i64,
12086 {TPtr, Key, TAddrDiscriminator, Discriminator}),
12087 0);
12088
12089 // extern_weak ref -> LOADauthptrstatic
12091 TPtr, DL, VT, (AArch64PACKey::ID)KeyC, Discriminator, AddrDiscriminator,
12092 DAG);
12093}
12094
12095// Looks through \param Val to determine the bit that can be used to
12096// check the sign of the value. It returns the unextended value and
12097// the sign bit position.
12098static std::pair<SDValue, uint64_t> lookThroughSignExtension(SDValue Val) {
12099 if (Val.getOpcode() == ISD::SIGN_EXTEND_INREG)
12100 return {Val.getOperand(0),
12101 cast<VTSDNode>(Val.getOperand(1))->getVT().getFixedSizeInBits() -
12102 1};
12103
12104 if (Val.getOpcode() == ISD::SIGN_EXTEND)
12105 return {Val.getOperand(0),
12106 Val.getOperand(0)->getValueType(0).getFixedSizeInBits() - 1};
12107
12108 return {Val, Val.getValueSizeInBits() - 1};
12109}
12110
12111// Op is an SDValue that is being compared to 0. If the comparison is a bit
12112// test, optimize it to a TBZ or TBNZ.
12114 SDValue Dest, unsigned Opcode,
12115 SelectionDAG &DAG) {
12116 if (Op.getOpcode() != ISD::AND)
12117 return SDValue();
12118
12119 // See if we can use a TBZ to fold in an AND as well.
12120 // TBZ has a smaller branch displacement than CBZ. If the offset is
12121 // out of bounds, a late MI-layer pass rewrites branches.
12122 // 403.gcc is an example that hits this case.
12123 if (isa<ConstantSDNode>(Op.getOperand(1)) &&
12124 isPowerOf2_64(Op.getConstantOperandVal(1))) {
12125 SDValue Test = Op.getOperand(0);
12126 uint64_t Mask = Op.getConstantOperandVal(1);
12127 return DAG.getNode(Opcode, DL, MVT::Other, Chain, Test,
12128 DAG.getConstant(Log2_64(Mask), DL, MVT::i64), Dest);
12129 }
12130
12131 if (Op.getOperand(0).getOpcode() == ISD::SHL) {
12132 auto Op00 = Op.getOperand(0).getOperand(0);
12133 if (isa<ConstantSDNode>(Op00) && Op00->getAsZExtVal() == 1) {
12134 auto Shr = DAG.getNode(ISD::SRL, DL, Op00.getValueType(),
12135 Op.getOperand(1), Op.getOperand(0).getOperand(1));
12136 return DAG.getNode(Opcode, DL, MVT::Other, Chain, Shr,
12137 DAG.getConstant(0, DL, MVT::i64), Dest);
12138 }
12139 }
12140
12141 return SDValue();
12142}
12143
12144SDValue AArch64TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
12145 SDValue Chain = Op.getOperand(0);
12146 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
12147 SDValue LHS = Op.getOperand(2);
12148 SDValue RHS = Op.getOperand(3);
12149 SDValue Dest = Op.getOperand(4);
12150 SDLoc DL(Op);
12151
12153 // Speculation tracking/SLH assumes that optimized TB(N)Z/CB(N)Z instructions
12154 // will not be produced, as they are conditional branch instructions that do
12155 // not set flags.
12156 bool ProduceNonFlagSettingCondBr =
12157 !MF.getFunction().hasFnAttribute(Attribute::SpeculativeLoadHardening);
12158
12159 // Handle f128 first, since lowering it will result in comparing the return
12160 // value of a libcall against zero, which is just what the rest of LowerBR_CC
12161 // is expecting to deal with.
12162 if (LHS.getValueType() == MVT::f128) {
12163 softenSetCCOperands(DAG, MVT::f128, LHS, RHS, CC, DL, LHS, RHS);
12164
12165 // If softenSetCCOperands returned a scalar, we need to compare the result
12166 // against zero to select between true and false values.
12167 if (!RHS.getNode()) {
12168 RHS = DAG.getConstant(0, DL, LHS.getValueType());
12169 CC = ISD::SETNE;
12170 }
12171 }
12172
12173 // Optimize {s|u}{add|sub|mul}.with.overflow feeding into a branch
12174 // instruction.
12176 (CC == ISD::SETEQ || CC == ISD::SETNE)) {
12177 // Only lower legal XALUO ops.
12178 if (!DAG.getTargetLoweringInfo().isTypeLegal(LHS->getValueType(0)))
12179 return SDValue();
12180
12181 // The actual operation with overflow check.
12183 SDValue Value, Overflow;
12184 std::tie(Value, Overflow) = getAArch64XALUOOp(OFCC, LHS.getValue(0), DAG);
12185
12186 if (CC == ISD::SETNE)
12187 OFCC = getInvertedCondCode(OFCC);
12188 SDValue CCVal = getCondCode(DAG, OFCC);
12189
12190 return DAG.getNode(AArch64ISD::BRCOND, DL, MVT::Other, Chain, Dest, CCVal,
12191 Overflow);
12192 }
12193
12194 // Fold CSET + BR_CC to a conditional branch (rather than keeping the CSET
12195 // and emitting a TB[N]Z below).
12196 {
12197 using namespace llvm::SDPatternMatch;
12198 SDValue Flags;
12199 uint64_t InverseCC;
12200 // `CSET <Wd>, <cond>` is an alias of `CSINC <Wd>, WZR, WZR, invert(<cond>)`
12201 auto m_CSET = m_Node(AArch64ISD::CSINC, m_Zero(), m_Zero(),
12202 m_ConstInt(InverseCC), m_Value(Flags));
12203 // Note: We look through `& 1` as the result of CSET is known to be 0 or 1.
12204 if ((CC == ISD::SETEQ || CC == ISD::SETNE) && isNullConstant(RHS) &&
12205 sd_match(LHS, m_AnyOf(m_CSET, m_And(m_CSET, m_One())))) {
12206 AArch64CC::CondCode BranchCC = AArch64CC::CondCode(InverseCC);
12207 if (CC == ISD::SETNE)
12208 BranchCC = AArch64CC::getInvertedCondCode(BranchCC);
12209 return DAG.getNode(AArch64ISD::BRCOND, DL, MVT::Other, Chain, Dest,
12210 getCondCode(DAG, BranchCC), Flags);
12211 }
12212 }
12213
12214 if (LHS.getValueType().isInteger()) {
12215 assert((LHS.getValueType() == RHS.getValueType()) &&
12216 (LHS.getValueType() == MVT::i32 || LHS.getValueType() == MVT::i64));
12217
12218 // Normalize (LHS CC 1) -> (LHS NewCC 0) when LHS is known to be 0 or 1.
12219 // This enables the CBZ/CBNZ matching below.
12220 const ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS);
12221 if (RHSC && RHSC->getZExtValue() == 1 && ProduceNonFlagSettingCondBr &&
12222 // Don't do this when LHS is an overflow/carry result (resNo == 1)
12223 // because we can fold cset + cmp #1 + b.cc into a direct
12224 // flag-consuming branch, which CBZ/CBNZ would prevent.
12225 LHS.getResNo() == 0 &&
12226 // This is true only when we somehow know that it's either 0 or 1.
12227 DAG.computeKnownBits(LHS).getMaxValue().ule(1)) {
12228 // Output params unused; we only care whether it returns true.
12229 bool CanNegate, MustBeFirst, PreferFirst;
12230 // Also skip when LHS is a conjunction tree (AND/OR of SETCCs) --
12231 // emitConjunction will lower it as a CCMP chain, which is better
12232 // than materializing the boolean for CBZ.
12233 if (!canEmitConjunction(DAG, LHS, CanNegate, MustBeFirst, PreferFirst,
12234 false)) {
12236 switch (CC) {
12237 // SETLT/SETGE are canonicalized away before reaching here, but
12238 // handle them defensively.
12239 case ISD::SETNE:
12240 case ISD::SETULT:
12241 case ISD::SETLT:
12242 NewCC = ISD::SETEQ;
12243 break;
12244 case ISD::SETEQ:
12245 case ISD::SETUGE:
12246 case ISD::SETGE:
12247 NewCC = ISD::SETNE;
12248 break;
12249 default:
12250 break;
12251 }
12252 if (NewCC != ISD::SETCC_INVALID) {
12253 CC = NewCC;
12254 RHS = DAG.getConstant(0, DL, LHS.getValueType());
12255 RHSC = cast<ConstantSDNode>(RHS);
12256 }
12257 }
12258 }
12259
12260 // If the RHS of the comparison is zero, we can potentially fold this
12261 // to a specialized branch.
12262 if (RHSC && RHSC->getZExtValue() == 0 && ProduceNonFlagSettingCondBr) {
12263 if (CC == ISD::SETEQ) {
12264 if (SDValue Result =
12265 optimizeBitTest(DL, LHS, Chain, Dest, AArch64ISD::TBZ, DAG))
12266 return Result;
12267
12268 return DAG.getNode(AArch64ISD::CBZ, DL, MVT::Other, Chain, LHS, Dest);
12269 } else if (CC == ISD::SETNE) {
12270 if (SDValue Result =
12271 optimizeBitTest(DL, LHS, Chain, Dest, AArch64ISD::TBNZ, DAG))
12272 return Result;
12273
12274 return DAG.getNode(AArch64ISD::CBNZ, DL, MVT::Other, Chain, LHS, Dest);
12275 } else if (CC == ISD::SETLT && LHS.getOpcode() != ISD::AND) {
12276 // Don't combine AND since emitComparison converts the AND to an ANDS
12277 // (a.k.a. TST) and the test in the test bit and branch instruction
12278 // becomes redundant. This would also increase register pressure.
12279 uint64_t SignBitPos;
12280 std::tie(LHS, SignBitPos) = lookThroughSignExtension(LHS);
12281 return DAG.getNode(AArch64ISD::TBNZ, DL, MVT::Other, Chain, LHS,
12282 DAG.getConstant(SignBitPos, DL, MVT::i64), Dest);
12283 }
12284 }
12285 if (RHSC && RHSC->getSExtValue() == -1 && CC == ISD::SETGT &&
12286 LHS.getOpcode() != ISD::AND && ProduceNonFlagSettingCondBr) {
12287 // Don't combine AND since emitComparison converts the AND to an ANDS
12288 // (a.k.a. TST) and the test in the test bit and branch instruction
12289 // becomes redundant. This would also increase register pressure.
12290 uint64_t SignBitPos;
12291 std::tie(LHS, SignBitPos) = lookThroughSignExtension(LHS);
12292 return DAG.getNode(AArch64ISD::TBZ, DL, MVT::Other, Chain, LHS,
12293 DAG.getConstant(SignBitPos, DL, MVT::i64), Dest);
12294 }
12295
12296 // Try to emit Armv9.6 CB instructions. We prefer tb{n}z/cb{n}z due to their
12297 // larger branch displacement but do prefer CB over cmp + br.
12298 if (Subtarget->hasCMPBR() &&
12300 ProduceNonFlagSettingCondBr) {
12301 SDValue Cond =
12303 return DAG.getNode(AArch64ISD::CB, DL, MVT::Other, Chain, Cond, LHS, RHS,
12304 Dest);
12305 }
12306
12307 SDValue CCVal;
12308 SDValue Cmp = getAArch64Cmp(LHS, RHS, CC, CCVal, DAG, DL);
12309 return DAG.getNode(AArch64ISD::BRCOND, DL, MVT::Other, Chain, Dest, CCVal,
12310 Cmp);
12311 }
12312
12313 assert(LHS.getValueType() == MVT::f16 || LHS.getValueType() == MVT::bf16 ||
12314 LHS.getValueType() == MVT::f32 || LHS.getValueType() == MVT::f64);
12315
12316 // Unfortunately, the mapping of LLVM FP CC's onto AArch64 CC's isn't totally
12317 // clean. Some of them require two branches to implement.
12318 SDValue Cmp = emitComparison(LHS, RHS, CC, DL, DAG);
12319 AArch64CC::CondCode CC1, CC2;
12320 changeFPCCToAArch64CC(CC, CC1, CC2);
12321 SDValue CC1Val = getCondCode(DAG, CC1);
12322 SDValue BR1 =
12323 DAG.getNode(AArch64ISD::BRCOND, DL, MVT::Other, Chain, Dest, CC1Val, Cmp);
12324 if (CC2 != AArch64CC::AL) {
12325 SDValue CC2Val = getCondCode(DAG, CC2);
12326 return DAG.getNode(AArch64ISD::BRCOND, DL, MVT::Other, BR1, Dest, CC2Val,
12327 Cmp);
12328 }
12329
12330 return BR1;
12331}
12332
12333SDValue AArch64TargetLowering::LowerFCOPYSIGN(SDValue Op,
12334 SelectionDAG &DAG) const {
12335 if (!Subtarget->isNeonAvailable() &&
12336 !Subtarget->useSVEForFixedLengthVectors())
12337 return SDValue();
12338
12339 EVT VT = Op.getValueType();
12340 EVT IntVT = VT.changeTypeToInteger();
12341 SDLoc DL(Op);
12342
12343 SDValue In1 = Op.getOperand(0);
12344 SDValue In2 = Op.getOperand(1);
12345 EVT SrcVT = In2.getValueType();
12346
12347 if (!SrcVT.bitsEq(VT))
12348 In2 = DAG.getFPExtendOrRound(In2, DL, VT);
12349
12350 if (VT.isScalableVector())
12351 IntVT =
12353
12354 if (VT.isFixedLengthVector() &&
12355 useSVEForFixedLengthVectorVT(VT, !Subtarget->isNeonAvailable())) {
12356 EVT ContainerVT = getContainerForFixedLengthVector(DAG, VT);
12357
12358 In1 = convertToScalableVector(DAG, ContainerVT, In1);
12359 In2 = convertToScalableVector(DAG, ContainerVT, In2);
12360
12361 SDValue Res = DAG.getNode(ISD::FCOPYSIGN, DL, ContainerVT, In1, In2);
12362 return convertFromScalableVector(DAG, VT, Res);
12363 }
12364
12365 // With SVE, but without Neon, extend the scalars to scalable vectors and use
12366 // a SVE FCOPYSIGN.
12367 if (!VT.isVector() && !Subtarget->isNeonAvailable() &&
12368 Subtarget->isSVEorStreamingSVEAvailable()) {
12369 if (VT != MVT::f16 && VT != MVT::f32 && VT != MVT::f64 && VT != MVT::bf16)
12370 return SDValue();
12371 EVT SVT = getPackedSVEVectorVT(VT);
12372
12373 SDValue Poison = DAG.getPOISON(SVT);
12374 SDValue Zero = DAG.getConstant(0, DL, MVT::i64);
12375 SDValue Ins1 =
12376 DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, SVT, Poison, In1, Zero);
12377 SDValue Ins2 =
12378 DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, SVT, Poison, In2, Zero);
12379 SDValue FCS = DAG.getNode(ISD::FCOPYSIGN, DL, SVT, Ins1, Ins2);
12380 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, FCS, Zero);
12381 }
12382
12383 auto BitCast = [this](EVT VT, SDValue Op, SelectionDAG &DAG) {
12384 if (VT.isScalableVector())
12385 return getSVESafeBitCast(VT, Op, DAG);
12386
12387 return DAG.getBitcast(VT, Op);
12388 };
12389
12390 SDValue VecVal1, VecVal2;
12391 EVT VecVT;
12392 auto SetVecVal = [&](int Idx = -1) {
12393 if (!VT.isVector()) {
12394 SDValue Poison = DAG.getPOISON(VecVT);
12395 VecVal1 = DAG.getTargetInsertSubreg(Idx, DL, VecVT, Poison, In1);
12396 VecVal2 = DAG.getTargetInsertSubreg(Idx, DL, VecVT, Poison, In2);
12397 } else {
12398 VecVal1 = BitCast(VecVT, In1, DAG);
12399 VecVal2 = BitCast(VecVT, In2, DAG);
12400 }
12401 };
12402 if (VT.isVector()) {
12403 VecVT = IntVT;
12404 SetVecVal();
12405 } else if (VT == MVT::f64) {
12406 VecVT = MVT::v2i64;
12407 SetVecVal(AArch64::dsub);
12408 } else if (VT == MVT::f32) {
12409 VecVT = MVT::v4i32;
12410 SetVecVal(AArch64::ssub);
12411 } else if (VT == MVT::f16 || VT == MVT::bf16) {
12412 VecVT = MVT::v8i16;
12413 SetVecVal(AArch64::hsub);
12414 } else {
12415 llvm_unreachable("Invalid type for copysign!");
12416 }
12417
12418 unsigned BitWidth = In1.getScalarValueSizeInBits();
12419 SDValue SignMaskV = DAG.getConstant(~APInt::getSignMask(BitWidth), DL, VecVT);
12420
12421 // We want to materialize a mask with every bit but the high bit set, but the
12422 // AdvSIMD immediate moves cannot materialize that in a single instruction for
12423 // 64-bit elements. Instead, materialize all bits set and then negate that.
12424 if (VT == MVT::f64 || VT == MVT::v2f64) {
12425 SignMaskV = DAG.getConstant(APInt::getAllOnes(BitWidth), DL, VecVT);
12426 SignMaskV = DAG.getNode(ISD::BITCAST, DL, MVT::v2f64, SignMaskV);
12427 SignMaskV = DAG.getNode(ISD::FNEG, DL, MVT::v2f64, SignMaskV);
12428 SignMaskV = DAG.getNode(ISD::BITCAST, DL, MVT::v2i64, SignMaskV);
12429 }
12430
12431 SDValue BSP =
12432 DAG.getNode(AArch64ISD::BSP, DL, VecVT, SignMaskV, VecVal1, VecVal2);
12433 if (VT == MVT::f16 || VT == MVT::bf16)
12434 return DAG.getTargetExtractSubreg(AArch64::hsub, DL, VT, BSP);
12435 if (VT == MVT::f32)
12436 return DAG.getTargetExtractSubreg(AArch64::ssub, DL, VT, BSP);
12437 if (VT == MVT::f64)
12438 return DAG.getTargetExtractSubreg(AArch64::dsub, DL, VT, BSP);
12439
12440 return BitCast(VT, BSP, DAG);
12441}
12442
12443SDValue AArch64TargetLowering::LowerCTPOP_PARITY(SDValue Op,
12444 SelectionDAG &DAG) const {
12446 Attribute::NoImplicitFloat))
12447 return SDValue();
12448
12449 EVT VT = Op.getValueType();
12450 if (VT.isVector() && Subtarget->isSVEorStreamingSVEAvailable())
12451 return LowerToPredicatedOp(Op, DAG, AArch64ISD::CTPOP_MERGE_PASSTHRU);
12452
12453 bool IsParity = Op.getOpcode() == ISD::PARITY;
12454 SDValue Val = Op.getOperand(0);
12455 SDLoc DL(Op);
12456
12457 // for i32, general parity function using EORs is more efficient compared to
12458 // using floating point
12459 if (VT == MVT::i32 && IsParity)
12460 return SDValue();
12461
12462 if (Subtarget->isSVEorStreamingSVEAvailable()) {
12463 if (VT == MVT::i32 || VT == MVT::i64) {
12464 EVT ContainerVT = VT == MVT::i32 ? MVT::nxv4i32 : MVT::nxv2i64;
12465 Val = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, ContainerVT,
12466 DAG.getPOISON(ContainerVT), Val,
12467 DAG.getVectorIdxConstant(0, DL));
12468 Val = DAG.getNode(ISD::CTPOP, DL, ContainerVT, Val);
12469 Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Val,
12470 DAG.getVectorIdxConstant(0, DL));
12471 if (IsParity)
12472 Val = DAG.getNode(ISD::AND, DL, VT, Val, DAG.getConstant(1, DL, VT));
12473 return Val;
12474 }
12475
12476 if (VT == MVT::i128) {
12477 Val = DAG.getNode(ISD::BITCAST, DL, MVT::v2i64, Val);
12478 Val = convertToScalableVector(DAG, MVT::nxv2i64, Val);
12479 Val = DAG.getNode(ISD::CTPOP, DL, MVT::nxv2i64, Val);
12480 Val = convertFromScalableVector(DAG, MVT::v2i64, Val);
12481 Val = DAG.getNode(ISD::VECREDUCE_ADD, DL, MVT::i64, Val);
12482 Val = DAG.getZExtOrTrunc(Val, DL, VT);
12483 if (IsParity)
12484 Val = DAG.getNode(ISD::AND, DL, VT, Val, DAG.getConstant(1, DL, VT));
12485 return Val;
12486 }
12487 }
12488
12489 if (!Subtarget->isNeonAvailable())
12490 return SDValue();
12491
12492 // If there is no CNT instruction available, GPR popcount can
12493 // be more efficiently lowered to the following sequence that uses
12494 // AdvSIMD registers/instructions as long as the copies to/from
12495 // the AdvSIMD registers are cheap.
12496 // FMOV D0, X0 // copy 64-bit int to vector, high bits zero'd
12497 // CNT V0.8B, V0.8B // 8xbyte pop-counts
12498 // ADDV B0, V0.8B // sum 8xbyte pop-counts
12499 // FMOV X0, D0 // copy result back to integer reg
12500 if (VT == MVT::i32 || VT == MVT::i64) {
12501 if (VT == MVT::i32)
12502 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Val);
12503 Val = DAG.getNode(ISD::BITCAST, DL, MVT::v8i8, Val);
12504
12505 SDValue CtPop = DAG.getNode(ISD::CTPOP, DL, MVT::v8i8, Val);
12506 SDValue AddV = DAG.getNode(AArch64ISD::UADDV, DL, MVT::v8i8, CtPop);
12507 AddV = DAG.getNode(AArch64ISD::NVCAST, DL,
12508 VT == MVT::i32 ? MVT::v2i32 : MVT::v1i64, AddV);
12509 AddV = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, AddV,
12510 DAG.getConstant(0, DL, MVT::i64));
12511 if (IsParity)
12512 AddV = DAG.getNode(ISD::AND, DL, VT, AddV, DAG.getConstant(1, DL, VT));
12513 return AddV;
12514 } else if (VT == MVT::i128) {
12515 Val = DAG.getNode(ISD::BITCAST, DL, MVT::v16i8, Val);
12516
12517 SDValue CtPop = DAG.getNode(ISD::CTPOP, DL, MVT::v16i8, Val);
12518 SDValue AddV = DAG.getNode(AArch64ISD::UADDV, DL, MVT::v16i8, CtPop);
12519 AddV = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i64,
12520 DAG.getNode(AArch64ISD::NVCAST, DL, MVT::v2i64, AddV),
12521 DAG.getConstant(0, DL, MVT::i64));
12522 AddV = DAG.getZExtOrTrunc(AddV, DL, VT);
12523 if (IsParity)
12524 AddV = DAG.getNode(ISD::AND, DL, VT, AddV, DAG.getConstant(1, DL, VT));
12525 return AddV;
12526 }
12527
12528 assert(!IsParity && "ISD::PARITY of vector types not supported");
12529
12530 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
12531 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
12532 "Unexpected type for custom ctpop lowering");
12533
12534 EVT VT8Bit = VT.is64BitVector() ? MVT::v8i8 : MVT::v16i8;
12535 Val = DAG.getBitcast(VT8Bit, Val);
12536 Val = DAG.getNode(ISD::CTPOP, DL, VT8Bit, Val);
12537
12538 if (Subtarget->hasDotProd() && VT.getScalarSizeInBits() != 16 &&
12539 VT.getVectorNumElements() >= 2) {
12540 EVT DT = VT == MVT::v2i64 ? MVT::v4i32 : VT;
12541 SDValue Zeros = DAG.getConstant(0, DL, DT);
12542 SDValue Ones = DAG.getConstant(1, DL, VT8Bit);
12543
12544 if (VT == MVT::v2i64) {
12545 Val = DAG.getNode(AArch64ISD::UDOT, DL, DT, Zeros, Ones, Val);
12546 Val = DAG.getNode(AArch64ISD::UADDLP, DL, VT, Val);
12547 } else if (VT == MVT::v2i32) {
12548 Val = DAG.getNode(AArch64ISD::UDOT, DL, DT, Zeros, Ones, Val);
12549 } else if (VT == MVT::v4i32) {
12550 Val = DAG.getNode(AArch64ISD::UDOT, DL, DT, Zeros, Ones, Val);
12551 } else {
12552 llvm_unreachable("Unexpected type for custom ctpop lowering");
12553 }
12554
12555 return Val;
12556 }
12557
12558 // Widen v8i8/v16i8 CTPOP result to VT by repeatedly widening pairwise adds.
12559 unsigned EltSize = 8;
12560 unsigned NumElts = VT.is64BitVector() ? 8 : 16;
12561 while (EltSize != VT.getScalarSizeInBits()) {
12562 EltSize *= 2;
12563 NumElts /= 2;
12564 MVT WidenVT = MVT::getVectorVT(MVT::getIntegerVT(EltSize), NumElts);
12565 Val = DAG.getNode(AArch64ISD::UADDLP, DL, WidenVT, Val);
12566 }
12567
12568 return Val;
12569}
12570
12571SDValue AArch64TargetLowering::LowerCTTZ(SDValue Op, SelectionDAG &DAG) const {
12572 EVT VT = Op.getValueType();
12573 SDLoc DL(Op);
12574 SDValue RBIT = DAG.getNode(ISD::BITREVERSE, DL, VT, Op.getOperand(0));
12575 return DAG.getNode(ISD::CTLZ, DL, VT, RBIT);
12576}
12577
12578SDValue AArch64TargetLowering::LowerMinMax(SDValue Op,
12579 SelectionDAG &DAG) const {
12580
12581 EVT VT = Op.getValueType();
12582 SDLoc DL(Op);
12583 unsigned Opcode = Op.getOpcode();
12584 ISD::CondCode CC;
12585 switch (Opcode) {
12586 default:
12587 llvm_unreachable("Wrong instruction");
12588 case ISD::SMAX:
12589 CC = ISD::SETGT;
12590 break;
12591 case ISD::SMIN:
12592 CC = ISD::SETLT;
12593 break;
12594 case ISD::UMAX:
12595 CC = ISD::SETUGT;
12596 break;
12597 case ISD::UMIN:
12598 CC = ISD::SETULT;
12599 break;
12600 }
12601
12602 // Note: This lowering only overrides NEON for v1i64 and v2i64, where we
12603 // prefer using SVE if available.
12604 if (VT.isVector() && Subtarget->isSVEorStreamingSVEAvailable()) {
12605 switch (Opcode) {
12606 default:
12607 llvm_unreachable("Wrong instruction");
12608 case ISD::SMAX:
12609 return LowerToPredicatedOp(Op, DAG, AArch64ISD::SMAX_PRED);
12610 case ISD::SMIN:
12611 return LowerToPredicatedOp(Op, DAG, AArch64ISD::SMIN_PRED);
12612 case ISD::UMAX:
12613 return LowerToPredicatedOp(Op, DAG, AArch64ISD::UMAX_PRED);
12614 case ISD::UMIN:
12615 return LowerToPredicatedOp(Op, DAG, AArch64ISD::UMIN_PRED);
12616 }
12617 }
12618
12619 SDValue Op0 = Op.getOperand(0);
12620 SDValue Op1 = Op.getOperand(1);
12621 SDValue Cond = DAG.getSetCC(DL, VT, Op0, Op1, CC);
12622 return DAG.getSelect(DL, VT, Cond, Op0, Op1);
12623}
12624
12625SDValue AArch64TargetLowering::LowerBitreverse(SDValue Op,
12626 SelectionDAG &DAG) const {
12627 EVT VT = Op.getValueType();
12628
12629 if (Subtarget->isSVEorStreamingSVEAvailable())
12630 return LowerToPredicatedOp(Op, DAG, AArch64ISD::BITREVERSE_MERGE_PASSTHRU);
12631
12632 SDLoc DL(Op);
12633 SDValue REVB;
12634 MVT VST;
12635
12636 switch (VT.getSimpleVT().SimpleTy) {
12637 default:
12638 llvm_unreachable("Invalid type for bitreverse!");
12639
12640 case MVT::v2i32: {
12641 VST = MVT::v8i8;
12642 REVB = DAG.getNode(AArch64ISD::REV32, DL, VST, Op.getOperand(0));
12643
12644 break;
12645 }
12646
12647 case MVT::v4i32: {
12648 VST = MVT::v16i8;
12649 REVB = DAG.getNode(AArch64ISD::REV32, DL, VST, Op.getOperand(0));
12650
12651 break;
12652 }
12653
12654 case MVT::v1i64: {
12655 VST = MVT::v8i8;
12656 REVB = DAG.getNode(AArch64ISD::REV64, DL, VST, Op.getOperand(0));
12657
12658 break;
12659 }
12660
12661 case MVT::v2i64: {
12662 VST = MVT::v16i8;
12663 REVB = DAG.getNode(AArch64ISD::REV64, DL, VST, Op.getOperand(0));
12664
12665 break;
12666 }
12667 }
12668
12669 return DAG.getNode(AArch64ISD::NVCAST, DL, VT,
12670 DAG.getNode(ISD::BITREVERSE, DL, VST, REVB));
12671}
12672
12673// A CCMP folds in only a 5-bit unsigned immediate (or its negation, via CCMN);
12674// any other constant must be materialized into a register first.
12675static bool isLegalCondCmpImmediate(const APInt &Imm) {
12676 return Imm.sgt(-32) && Imm.slt(32);
12677}
12678
12679// True unless one of the operands is a constant that cannot be encoded as a
12680// CMP/CMN immediate. A non-constant operand always lives in a register, so it
12681// is fine.
12684 if (C && !llvm::AArch64_AM::isLegalCmpImmed(C->getAPIntValue()))
12685 return false;
12687 if (C && !llvm::AArch64_AM::isLegalCmpImmed(C->getAPIntValue()))
12688 return false;
12689 return true;
12690}
12691
12692// As hasLegalCmpImmediate, but for the tighter CCMP immediate form.
12695 if (C && !isLegalCondCmpImmediate(C->getAPIntValue()))
12696 return false;
12698 if (C && !isLegalCondCmpImmediate(C->getAPIntValue()))
12699 return false;
12700 return true;
12701}
12702
12703// True if either operand is a constant that does not fit a CCMP immediate but
12704// is a legal logical immediate: folding it into the xor is a single cheap
12705// instruction, yet the result still needs a scratch register for the CCMP.
12706// Chaining more than two such compares costs more than the CCMP form saves.
12708 const std::pair<SDValue, SDValue> &Pair) {
12709 for (SDValue V : {Pair.first, Pair.second}) {
12710 auto *C = dyn_cast<ConstantSDNode>(V);
12711 if (!C || isLegalCondCmpImmediate(C->getAPIntValue()))
12712 continue;
12713 const APInt &Imm = C->getAPIntValue();
12714 unsigned BitWidth = Imm.getBitWidth() <= 32 ? 32 : 64;
12715 if (Imm.getBitWidth() <= BitWidth &&
12717 return true;
12718 }
12719 return false;
12720}
12721
12722// Check whether the continuous comparison sequence.
12723static bool
12724isOrXorChain(SDValue N, SelectionDAG &DAG, unsigned &NumLeaves,
12725 unsigned &NumXors, bool &SawXor, bool RequireLegalCmpImmediates,
12726 SmallVectorImpl<std::pair<SDValue, SDValue>> &WorkList) {
12727 if (NumLeaves == MaxXors)
12728 return false;
12729
12730 // Skip the one-use zext
12731 if (N->getOpcode() == ISD::ZERO_EXTEND && N->hasOneUse())
12732 N = N->getOperand(0);
12733
12734 if (N->getOpcode() == ISD::XOR) {
12735 if (RequireLegalCmpImmediates &&
12736 !hasLegalCmpImmediate(N->getOperand(0), N->getOperand(1)))
12737 return false;
12738 WorkList.push_back(std::make_pair(N->getOperand(0), N->getOperand(1)));
12739 NumLeaves++;
12740 NumXors++;
12741 SawXor = true;
12742 return true;
12743 }
12744
12745 // All the non-leaf nodes must be OR.
12746 if (N->getOpcode() == ISD::OR && N->hasOneUse())
12747 return isOrXorChain(N->getOperand(0), DAG, NumLeaves, NumXors, SawXor,
12748 RequireLegalCmpImmediates, WorkList) &&
12749 isOrXorChain(N->getOperand(1), DAG, NumLeaves, NumXors, SawXor,
12750 RequireLegalCmpImmediates, WorkList);
12751 if (N->getOpcode() == ISD::OR)
12752 return false;
12753
12754 EVT VT = N.getValueType();
12755 if (!VT.isScalarInteger())
12756 return false;
12757
12758 // A xor with zero may have been folded away before this combine sees it.
12759 // Treat such leaves as comparisons with zero so the original OR/XOR form and
12760 // type-legalized wide integer equality compares converge to the same SETCC
12761 // tree.
12762 WorkList.push_back(std::make_pair(N, DAG.getConstant(0, SDLoc(N), VT)));
12763 NumLeaves++;
12764 return true;
12765}
12766
12767// Transform chains of ORs and XORs, which usually outlined by memcmp/bmp.
12769 SDValue LHS = N->getOperand(0);
12770 SDValue RHS = N->getOperand(1);
12771 SDLoc DL(N);
12772 EVT VT = N->getValueType(0);
12774
12775 // Only handle integer compares.
12776 if (N->getOpcode() != ISD::SETCC || LHS.getValueType().isVector() ||
12777 LHS.getValueType().getSizeInBits() > 64)
12778 return SDValue();
12779
12780 ISD::CondCode Cond = cast<CondCodeSDNode>(N->getOperand(2))->get();
12781 // Try to express conjunction "cmp 0 (or (xor A0 A1) (xor B0 B1))" as:
12782 // sub A0, A1; ccmp B0, B1, 0, eq; cmp inv(Cond) flag
12783 unsigned NumLeaves = 0;
12784 unsigned NumXors = 0;
12785 bool SawXor = false;
12786 bool RequireLegalCmpImmediates = any_of(N->users(), [](SDNode *User) {
12787 return User->getOpcode() == ISD::BRCOND ||
12788 User->getOpcode() == AArch64ISD::BRCOND;
12789 });
12790 if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && isNullConstant(RHS) &&
12791 LHS->getOpcode() == ISD::OR && LHS->hasOneUse() &&
12792 isOrXorChain(LHS, DAG, NumLeaves, NumXors, SawXor,
12793 RequireLegalCmpImmediates, WorkList) &&
12794 SawXor) {
12795 // A CCMP sequence serializes the comparisons through NZCV. Keep the
12796 // default transform to short chains, but account for real XOR leaves: each
12797 // one removed is a code-size and front-end win. Under size optimization,
12798 // prefer the smaller CCMP form unless another guard rejects it.
12799 const Function &F = DAG.getMachineFunction().getFunction();
12800 unsigned Limit = 5;
12801 if (NumXors >= 6) {
12802 Limit = 6;
12803 if (NumXors == NumLeaves)
12804 Limit = std::min<unsigned>(8, NumXors);
12805 }
12806 if (F.hasMinSize())
12807 Limit = MaxXors;
12808 if (WorkList.size() > Limit)
12809 return SDValue();
12810
12811 if (WorkList.size() > 2 &&
12813 return SDValue();
12814
12815 // Only the leading compare of the chain uses the wider CMP immediate; the
12816 // rest become CCMPs. So a compare whose immediate is a legal CMP operand
12817 // but not a legal CCMP operand is cheapest at the front.
12818 auto PreferAsFirstCmp = [](const std::pair<SDValue, SDValue> &Pair) {
12819 return hasLegalCmpImmediate(Pair.first, Pair.second) &&
12820 !hasLegalCondCmpImmediate(Pair.first, Pair.second);
12821 };
12823 find_if(WorkList, PreferAsFirstCmp);
12824 if (First != WorkList.end())
12825 std::iter_swap(WorkList.begin(), First);
12826
12827 SDValue XOR0, XOR1;
12828 std::tie(XOR0, XOR1) = WorkList[0];
12829 unsigned LogicOp = (Cond == ISD::SETEQ) ? ISD::AND : ISD::OR;
12830 SDValue Cmp = DAG.getSetCC(DL, VT, XOR0, XOR1, Cond);
12831 for (unsigned I = 1; I < WorkList.size(); I++) {
12832 std::tie(XOR0, XOR1) = WorkList[I];
12833 SDValue CmpChain = DAG.getSetCC(DL, VT, XOR0, XOR1, Cond);
12834 Cmp = DAG.getNode(LogicOp, DL, VT, Cmp, CmpChain);
12835 }
12836
12837 // Exit early by inverting the condition, which help reduce indentations.
12838 return Cmp;
12839 }
12840
12841 return SDValue();
12842}
12843
12844SDValue AArch64TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
12845
12846 if (Op.getValueType().isVector())
12847 return LowerVSETCC(Op, DAG);
12848
12849 bool IsStrict = Op->isStrictFPOpcode();
12850 bool IsSignaling = Op.getOpcode() == ISD::STRICT_FSETCCS;
12851 unsigned OpNo = IsStrict ? 1 : 0;
12852 SDValue Chain;
12853 if (IsStrict)
12854 Chain = Op.getOperand(0);
12855 SDValue LHS = Op.getOperand(OpNo + 0);
12856 SDValue RHS = Op.getOperand(OpNo + 1);
12857 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(OpNo + 2))->get();
12858 SDLoc DL(Op);
12859
12860 // We chose ZeroOrOneBooleanContents, so use zero and one.
12861 EVT VT = Op.getValueType();
12862 SDValue TVal = DAG.getConstant(1, DL, VT);
12863 SDValue FVal = DAG.getConstant(0, DL, VT);
12864
12865 // Handle f128 first, since one possible outcome is a normal integer
12866 // comparison which gets picked up by the next if statement.
12867 if (LHS.getValueType() == MVT::f128) {
12868 softenSetCCOperands(DAG, MVT::f128, LHS, RHS, CC, DL, LHS, RHS, Chain,
12869 IsSignaling);
12870
12871 // If softenSetCCOperands returned a scalar, use it.
12872 if (!RHS.getNode()) {
12873 assert(LHS.getValueType() == Op.getValueType() &&
12874 "Unexpected setcc expansion!");
12875 return IsStrict ? DAG.getMergeValues({LHS, Chain}, DL) : LHS;
12876 }
12877 }
12878
12879 if (LHS.getValueType().isInteger()) {
12880 if (Subtarget->hasCSSC() && CC == ISD::SETNE && isNullConstant(RHS)) {
12881 SDValue One = DAG.getConstant(1, DL, LHS.getValueType());
12882 SDValue UMin = DAG.getNode(ISD::UMIN, DL, LHS.getValueType(), LHS, One);
12883 SDValue Res = DAG.getZExtOrTrunc(UMin, DL, VT);
12884 return IsStrict ? DAG.getMergeValues({Res, Chain}, DL) : Res;
12885 }
12886 simplifySetCCIntoEq(CC, LHS, RHS, DAG, DL);
12887
12888 SDValue CCVal;
12890 LHS, RHS, ISD::getSetCCInverse(CC, LHS.getValueType()), CCVal, DAG, DL);
12891
12892 // Note that we inverted the condition above, so we reverse the order of
12893 // the true and false operands here. This will allow the setcc to be
12894 // matched to a single CSINC instruction.
12895 SDValue Res = DAG.getNode(AArch64ISD::CSEL, DL, VT, FVal, TVal, CCVal, Cmp);
12896 return IsStrict ? DAG.getMergeValues({Res, Chain}, DL) : Res;
12897 }
12898
12899 // Now we know we're dealing with FP values.
12900 assert(LHS.getValueType() == MVT::bf16 || LHS.getValueType() == MVT::f16 ||
12901 LHS.getValueType() == MVT::f32 || LHS.getValueType() == MVT::f64);
12902
12903 // If that fails, we'll need to perform an FCMP + CSEL sequence. Go ahead
12904 // and do the comparison.
12905 SDValue Cmp;
12906 if (IsStrict)
12907 Cmp = emitStrictFPComparison(LHS, RHS, DL, DAG, Chain, IsSignaling);
12908 else
12909 Cmp = emitComparison(LHS, RHS, CC, DL, DAG);
12910
12911 AArch64CC::CondCode CC1, CC2;
12912 changeFPCCToAArch64CC(CC, CC1, CC2);
12913 SDValue Res;
12914 if (CC2 == AArch64CC::AL) {
12915 changeFPCCToAArch64CC(ISD::getSetCCInverse(CC, LHS.getValueType()), CC1,
12916 CC2);
12917 SDValue CC1Val = getCondCode(DAG, CC1);
12918
12919 // Note that we inverted the condition above, so we reverse the order of
12920 // the true and false operands here. This will allow the setcc to be
12921 // matched to a single CSINC instruction.
12922 Res = DAG.getNode(AArch64ISD::CSEL, DL, VT, FVal, TVal, CC1Val, Cmp);
12923 } else {
12924 // Unfortunately, the mapping of LLVM FP CC's onto AArch64 CC's isn't
12925 // totally clean. Some of them require two CSELs to implement. As is in
12926 // this case, we emit the first CSEL and then emit a second using the output
12927 // of the first as the RHS. We're effectively OR'ing the two CC's together.
12928
12929 // FIXME: It would be nice if we could match the two CSELs to two CSINCs.
12930 SDValue CC1Val = getCondCode(DAG, CC1);
12931 SDValue CS1 =
12932 DAG.getNode(AArch64ISD::CSEL, DL, VT, TVal, FVal, CC1Val, Cmp);
12933
12934 SDValue CC2Val = getCondCode(DAG, CC2);
12935 Res = DAG.getNode(AArch64ISD::CSEL, DL, VT, TVal, CS1, CC2Val, Cmp);
12936 }
12937 return IsStrict ? DAG.getMergeValues({Res, Cmp.getValue(1)}, DL) : Res;
12938}
12939
12940SDValue AArch64TargetLowering::LowerSETCCCARRY(SDValue Op,
12941 SelectionDAG &DAG) const {
12942
12943 SDValue LHS = Op.getOperand(0);
12944 SDValue RHS = Op.getOperand(1);
12945 EVT VT = LHS.getValueType();
12946 if (VT != MVT::i32 && VT != MVT::i64)
12947 return SDValue();
12948
12949 SDLoc DL(Op);
12950 SDValue Carry = Op.getOperand(2);
12951 // SBCS uses a carry not a borrow so the carry flag should be inverted first.
12952 SDValue InvCarry = valueToCarryFlag(Carry, DAG, true);
12953 SDValue Cmp = DAG.getNode(AArch64ISD::SBCS, DL, DAG.getVTList(VT, FlagsVT),
12954 LHS, RHS, InvCarry);
12955
12956 EVT OpVT = Op.getValueType();
12957 SDValue TVal = DAG.getConstant(1, DL, OpVT);
12958 SDValue FVal = DAG.getConstant(0, DL, OpVT);
12959
12960 ISD::CondCode Cond = cast<CondCodeSDNode>(Op.getOperand(3))->get();
12962 SDValue CCVal = getCondCode(DAG, changeIntCCToAArch64CC(CondInv));
12963 // Inputs are swapped because the condition is inverted. This will allow
12964 // matching with a single CSINC instruction.
12965 return DAG.getNode(AArch64ISD::CSEL, DL, OpVT, FVal, TVal, CCVal,
12966 Cmp.getValue(1));
12967}
12968
12969/// Emit vector comparison for floating-point values, producing a mask.
12971 AArch64CC::CondCode CC, bool NoNans, EVT VT,
12972 const SDLoc &DL, SelectionDAG &DAG) {
12973 assert(VT.getSizeInBits() == LHS.getValueType().getSizeInBits() &&
12974 "function only supposed to emit natural comparisons");
12975
12976 switch (CC) {
12977 default:
12978 return SDValue();
12979 case AArch64CC::NE: {
12980 SDValue Fcmeq = DAG.getNode(AArch64ISD::FCMEQ, DL, VT, LHS, RHS);
12981 // Use vector semantics for the inversion to potentially save a copy between
12982 // SIMD and regular registers.
12983 if (!LHS.getValueType().isVector()) {
12984 EVT VecVT =
12985 EVT::getVectorVT(*DAG.getContext(), VT, 128 / VT.getSizeInBits());
12986 SDValue Zero = DAG.getConstant(0, DL, MVT::i64);
12987 SDValue MaskVec = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VecVT,
12988 DAG.getPOISON(VecVT), Fcmeq, Zero);
12989 SDValue InvertedMask = DAG.getNOT(DL, MaskVec, VecVT);
12990 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, InvertedMask, Zero);
12991 }
12992 return DAG.getNOT(DL, Fcmeq, VT);
12993 }
12994 case AArch64CC::EQ:
12995 return DAG.getNode(AArch64ISD::FCMEQ, DL, VT, LHS, RHS);
12996 case AArch64CC::GE:
12997 return DAG.getNode(AArch64ISD::FCMGE, DL, VT, LHS, RHS);
12998 case AArch64CC::GT:
12999 return DAG.getNode(AArch64ISD::FCMGT, DL, VT, LHS, RHS);
13000 case AArch64CC::LE:
13001 if (!NoNans)
13002 return SDValue();
13003 // If we ignore NaNs then we can use to the LS implementation.
13004 [[fallthrough]];
13005 case AArch64CC::LS:
13006 return DAG.getNode(AArch64ISD::FCMGE, DL, VT, RHS, LHS);
13007 case AArch64CC::LT:
13008 if (!NoNans)
13009 return SDValue();
13010 // If we ignore NaNs then we can use to the MI implementation.
13011 [[fallthrough]];
13012 case AArch64CC::MI:
13013 return DAG.getNode(AArch64ISD::FCMGT, DL, VT, RHS, LHS);
13014 }
13015}
13016
13017/// For SELECT_CC, when the true/false values are (-1, 0) and the compared
13018/// values are scalars, try to emit a mask generating vector instruction.
13020 SDValue FVal, ISD::CondCode CC, bool NoNaNs,
13021 const SDLoc &DL, SelectionDAG &DAG) {
13022 assert(!LHS.getValueType().isVector());
13023 assert(!RHS.getValueType().isVector());
13024
13025 auto *CTVal = dyn_cast<ConstantSDNode>(TVal);
13026 auto *CFVal = dyn_cast<ConstantSDNode>(FVal);
13027 if (!CTVal || !CFVal)
13028 return {};
13029 if (!(CTVal->isAllOnes() && CFVal->isZero()) &&
13030 !(CTVal->isZero() && CFVal->isAllOnes()))
13031 return {};
13032
13033 if (CTVal->isZero())
13034 CC = ISD::getSetCCInverse(CC, LHS.getValueType());
13035
13036 EVT VT = TVal.getValueType();
13037 if (VT.getSizeInBits() != LHS.getValueType().getSizeInBits())
13038 return {};
13039
13040 if (!NoNaNs && (CC == ISD::SETUO || CC == ISD::SETO)) {
13041 bool OneNaN = false;
13042 if (LHS == RHS) {
13043 OneNaN = true;
13044 } else if (DAG.isKnownNeverNaN(RHS)) {
13045 OneNaN = true;
13046 RHS = LHS;
13047 } else if (DAG.isKnownNeverNaN(LHS)) {
13048 OneNaN = true;
13049 LHS = RHS;
13050 }
13051 if (OneNaN)
13052 CC = (CC == ISD::SETUO) ? ISD::SETUNE : ISD::SETOEQ;
13053 }
13054
13057 bool ShouldInvert = false;
13058 changeVectorFPCCToAArch64CC(CC, CC1, CC2, ShouldInvert);
13059 SDValue Cmp = emitVectorComparison(LHS, RHS, CC1, NoNaNs, VT, DL, DAG);
13060 SDValue Cmp2;
13061 if (CC2 != AArch64CC::AL) {
13062 Cmp2 = emitVectorComparison(LHS, RHS, CC2, NoNaNs, VT, DL, DAG);
13063 if (!Cmp2)
13064 return {};
13065 }
13066 if (!Cmp2 && !ShouldInvert)
13067 return Cmp;
13068
13069 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), VT, 128 / VT.getSizeInBits());
13070 SDValue Zero = DAG.getConstant(0, DL, MVT::i64);
13071 SDValue Poison = DAG.getPOISON(VecVT);
13072 Cmp = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VecVT, Poison, Cmp, Zero);
13073 if (Cmp2) {
13074 Cmp2 = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VecVT, Poison, Cmp2, Zero);
13075 Cmp = DAG.getNode(ISD::OR, DL, VecVT, Cmp, Cmp2);
13076 }
13077 if (ShouldInvert)
13078 Cmp = DAG.getNOT(DL, Cmp, VecVT);
13079 Cmp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Cmp, Zero);
13080 return Cmp;
13081}
13082
13083SDValue AArch64TargetLowering::LowerSELECT_CC(
13086 const SDLoc &DL, SelectionDAG &DAG) const {
13087 // Handle f128 first, because it will result in a comparison of some RTLIB
13088 // call result against zero.
13089 if (LHS.getValueType() == MVT::f128) {
13090 softenSetCCOperands(DAG, MVT::f128, LHS, RHS, CC, DL, LHS, RHS);
13091
13092 // If softenSetCCOperands returned a scalar, we need to compare the result
13093 // against zero to select between true and false values.
13094 if (!RHS.getNode()) {
13095 RHS = DAG.getConstant(0, DL, LHS.getValueType());
13096 CC = ISD::SETNE;
13097 }
13098 }
13099
13100 // Also handle f16, for which we need to do a f32 comparison.
13101 if ((LHS.getValueType() == MVT::f16 && !Subtarget->hasFullFP16()) ||
13102 LHS.getValueType() == MVT::bf16) {
13103 LHS = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, LHS);
13104 RHS = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, RHS);
13105 }
13106
13107 // Next, handle integers.
13108 if (LHS.getValueType().isInteger()) {
13109 assert((LHS.getValueType() == RHS.getValueType()) &&
13110 (LHS.getValueType() == MVT::i32 || LHS.getValueType() == MVT::i64));
13111
13112 ConstantSDNode *CFVal = dyn_cast<ConstantSDNode>(FVal);
13113 ConstantSDNode *CTVal = dyn_cast<ConstantSDNode>(TVal);
13114 ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS);
13115
13116 // Check for SMAX(lhs, 0) and SMIN(lhs, 0) patterns.
13117 // (SELECT_CC setgt, lhs, 0, lhs, 0) -> (BIC lhs, (SRA lhs, typesize-1))
13118 // (SELECT_CC setlt, lhs, 0, lhs, 0) -> (AND lhs, (SRA lhs, typesize-1))
13119 // Both require less instructions than compare and conditional select.
13120 if ((CC == ISD::SETGT || CC == ISD::SETLT) && LHS == TVal &&
13121 RHSC && RHSC->isZero() && CFVal && CFVal->isZero() &&
13122 LHS.getValueType() == RHS.getValueType()) {
13123 EVT VT = LHS.getValueType();
13124 SDValue Shift =
13125 DAG.getNode(ISD::SRA, DL, VT, LHS,
13126 DAG.getConstant(VT.getSizeInBits() - 1, DL, VT));
13127
13128 if (CC == ISD::SETGT)
13129 Shift = DAG.getNOT(DL, Shift, VT);
13130
13131 return DAG.getNode(ISD::AND, DL, VT, LHS, Shift);
13132 }
13133
13134 // Check for sign bit test patterns that can use TST optimization.
13135 // (SELECT_CC setlt, sign_extend_inreg, 0, tval, fval)
13136 // -> TST %operand, sign_bit; CSEL
13137 // (SELECT_CC setlt, sign_extend, 0, tval, fval)
13138 // -> TST %operand, sign_bit; CSEL
13139 if (CC == ISD::SETLT && RHSC && RHSC->isZero() && LHS.hasOneUse() &&
13140 (LHS.getOpcode() == ISD::SIGN_EXTEND_INREG ||
13141 LHS.getOpcode() == ISD::SIGN_EXTEND)) {
13142
13143 uint64_t SignBitPos;
13144 std::tie(LHS, SignBitPos) = lookThroughSignExtension(LHS);
13145 EVT TestVT = LHS.getValueType();
13146 SDValue SignBitConst = DAG.getConstant(1ULL << SignBitPos, DL, TestVT);
13147 SDValue TST =
13148 DAG.getNode(AArch64ISD::ANDS, DL, DAG.getVTList(TestVT, MVT::i32),
13149 LHS, SignBitConst);
13150
13151 SDValue Flags = TST.getValue(1);
13152 return DAG.getNode(AArch64ISD::CSEL, DL, TVal.getValueType(), TVal, FVal,
13153 DAG.getConstant(AArch64CC::NE, DL, MVT::i32), Flags);
13154 }
13155
13156 // Canonicalise absolute difference patterns:
13157 // select_cc lhs, rhs, sub(lhs, rhs), sub(rhs, lhs), cc ->
13158 // select_cc lhs, rhs, sub(lhs, rhs), neg(sub(lhs, rhs)), cc
13159 //
13160 // select_cc lhs, rhs, sub(rhs, lhs), sub(lhs, rhs), cc ->
13161 // select_cc lhs, rhs, neg(sub(lhs, rhs)), sub(lhs, rhs), cc
13162 // The second forms can be matched into subs+cneg.
13163 // NOTE: Drop poison generating flags from the negated operand to avoid
13164 // inadvertently propagating poison after the canonicalisation.
13165 if (TVal.getOpcode() == ISD::SUB && FVal.getOpcode() == ISD::SUB) {
13166 if (TVal.getOperand(0) == LHS && TVal.getOperand(1) == RHS &&
13167 FVal.getOperand(0) == RHS && FVal.getOperand(1) == LHS) {
13169 FVal = DAG.getNegative(TVal, DL, TVal.getValueType());
13170 } else if (TVal.getOperand(0) == RHS && TVal.getOperand(1) == LHS &&
13171 FVal.getOperand(0) == LHS && FVal.getOperand(1) == RHS) {
13173 TVal = DAG.getNegative(FVal, DL, FVal.getValueType());
13174 }
13175 }
13176
13177 unsigned Opcode = AArch64ISD::CSEL;
13178
13179 // If both the TVal and the FVal are constants, see if we can swap them in
13180 // order to for a CSINV or CSINC out of them.
13181 if (CTVal && CFVal && CTVal->isAllOnes() && CFVal->isZero()) {
13182 std::swap(TVal, FVal);
13183 std::swap(CTVal, CFVal);
13184 CC = ISD::getSetCCInverse(CC, LHS.getValueType());
13185 } else if (CTVal && CFVal && CTVal->isOne() && CFVal->isZero()) {
13186 std::swap(TVal, FVal);
13187 std::swap(CTVal, CFVal);
13188 CC = ISD::getSetCCInverse(CC, LHS.getValueType());
13189 } else if (TVal.getOpcode() == ISD::XOR) {
13190 // If TVal is a NOT we want to swap TVal and FVal so that we can match
13191 // with a CSINV rather than a CSEL.
13192 if (isAllOnesConstant(TVal.getOperand(1))) {
13193 std::swap(TVal, FVal);
13194 std::swap(CTVal, CFVal);
13195 CC = ISD::getSetCCInverse(CC, LHS.getValueType());
13196 }
13197 } else if (TVal.getOpcode() == ISD::SUB) {
13198 // If TVal is a negation (SUB from 0) we want to swap TVal and FVal so
13199 // that we can match with a CSNEG rather than a CSEL.
13200 if (isNullConstant(TVal.getOperand(0))) {
13201 std::swap(TVal, FVal);
13202 std::swap(CTVal, CFVal);
13203 CC = ISD::getSetCCInverse(CC, LHS.getValueType());
13204 }
13205 } else if (CTVal && CFVal) {
13206 const int64_t TrueVal = CTVal->getSExtValue();
13207 const int64_t FalseVal = CFVal->getSExtValue();
13208 bool Swap = false;
13209
13210 // If both TVal and FVal are constants, see if FVal is the
13211 // inverse/negation/increment of TVal and generate a CSINV/CSNEG/CSINC
13212 // instead of a CSEL in that case.
13213 if (TrueVal == ~FalseVal) {
13214 Opcode = AArch64ISD::CSINV;
13215 } else if (FalseVal > std::numeric_limits<int64_t>::min() &&
13216 TrueVal == -FalseVal) {
13217 Opcode = AArch64ISD::CSNEG;
13218 } else if (TVal.getValueType() == MVT::i32) {
13219 // If our operands are only 32-bit wide, make sure we use 32-bit
13220 // arithmetic for the check whether we can use CSINC. This ensures that
13221 // the addition in the check will wrap around properly in case there is
13222 // an overflow (which would not be the case if we do the check with
13223 // 64-bit arithmetic).
13224 const uint32_t TrueVal32 = CTVal->getZExtValue();
13225 const uint32_t FalseVal32 = CFVal->getZExtValue();
13226
13227 if ((TrueVal32 == FalseVal32 + 1) || (TrueVal32 + 1 == FalseVal32)) {
13228 Opcode = AArch64ISD::CSINC;
13229
13230 if (TrueVal32 > FalseVal32) {
13231 Swap = true;
13232 }
13233 }
13234 } else {
13235 // 64-bit check whether we can use CSINC.
13236 const uint64_t TrueVal64 = TrueVal;
13237 const uint64_t FalseVal64 = FalseVal;
13238
13239 if ((TrueVal64 == FalseVal64 + 1) || (TrueVal64 + 1 == FalseVal64)) {
13240 Opcode = AArch64ISD::CSINC;
13241
13242 if (TrueVal > FalseVal) {
13243 Swap = true;
13244 }
13245 }
13246 }
13247
13248 // Swap TVal and FVal if necessary.
13249 if (Swap) {
13250 std::swap(TVal, FVal);
13251 std::swap(CTVal, CFVal);
13252 CC = ISD::getSetCCInverse(CC, LHS.getValueType());
13253 }
13254
13255 if (Opcode != AArch64ISD::CSEL) {
13256 // Drop FVal since we can get its value by simply inverting/negating
13257 // TVal.
13258 FVal = TVal;
13259 }
13260 }
13261
13262 // Avoid materializing a constant when possible by reusing a known value in
13263 // a register. However, don't perform this optimization if the known value
13264 // is one, zero or negative one in the case of a CSEL. We can always
13265 // materialize these values using CSINC, CSEL and CSINV with wzr/xzr as the
13266 // FVal, respectively.
13267 ConstantSDNode *RHSVal = dyn_cast<ConstantSDNode>(RHS);
13268 if (Opcode == AArch64ISD::CSEL && RHSVal && !RHSVal->isOne() &&
13269 !RHSVal->isZero() && !RHSVal->isAllOnes()) {
13271 // Transform "a == C ? C : x" to "a == C ? a : x" and "a != C ? x : C" to
13272 // "a != C ? x : a" to avoid materializing C.
13273 if (CTVal && CTVal == RHSVal && AArch64CC == AArch64CC::EQ)
13274 TVal = LHS;
13275 else if (CFVal && CFVal == RHSVal && AArch64CC == AArch64CC::NE)
13276 FVal = LHS;
13277 } else if (Opcode == AArch64ISD::CSNEG && RHSVal && RHSVal->isOne()) {
13278 assert (CTVal && CFVal && "Expected constant operands for CSNEG.");
13279 // Use a CSINV to transform "a == C ? 1 : -1" to "a == C ? a : -1" to
13280 // avoid materializing C.
13282 if (CTVal == RHSVal && AArch64CC == AArch64CC::EQ) {
13283 Opcode = AArch64ISD::CSINV;
13284 TVal = LHS;
13285 FVal = DAG.getConstant(0, DL, FVal.getValueType());
13286 }
13287 }
13288
13289 SDValue CCVal;
13290 SDValue Cmp = getAArch64Cmp(LHS, RHS, CC, CCVal, DAG, DL);
13291 EVT VT = TVal.getValueType();
13292 return DAG.getNode(Opcode, DL, VT, TVal, FVal, CCVal, Cmp);
13293 }
13294
13295 // Now we know we're dealing with FP values.
13296 assert(LHS.getValueType() == MVT::f16 || LHS.getValueType() == MVT::f32 ||
13297 LHS.getValueType() == MVT::f64);
13298 assert(LHS.getValueType() == RHS.getValueType());
13299 EVT VT = TVal.getValueType();
13300
13301 // If the purpose of the comparison is to select between all ones
13302 // or all zeros, try to use a vector comparison because the operands are
13303 // already stored in SIMD registers.
13304 if (Subtarget->isNeonAvailable() && all_of(Users, [](const SDNode *U) {
13305 switch (U->getOpcode()) {
13306 default:
13307 return false;
13310 case AArch64ISD::DUP:
13311 return true;
13312 }
13313 })) {
13314 bool NoNaNs = Flags.hasNoNaNs();
13315 SDValue VectorCmp =
13316 emitFloatCompareMask(LHS, RHS, TVal, FVal, CC, NoNaNs, DL, DAG);
13317 if (VectorCmp)
13318 return VectorCmp;
13319 }
13320
13321 SDValue Cmp = emitComparison(LHS, RHS, CC, DL, DAG);
13322
13323 // Unfortunately, the mapping of LLVM FP CC's onto AArch64 CC's isn't totally
13324 // clean. Some of them require two CSELs to implement.
13325 AArch64CC::CondCode CC1, CC2;
13326 changeFPCCToAArch64CC(CC, CC1, CC2);
13327
13328 if (Flags.hasNoSignedZeros()) {
13329 // Transform "a == 0.0 ? 0.0 : x" to "a == 0.0 ? a : x" and
13330 // "a != 0.0 ? x : 0.0" to "a != 0.0 ? x : a" to avoid materializing 0.0.
13331 ConstantFPSDNode *RHSVal = dyn_cast<ConstantFPSDNode>(RHS);
13332 if (RHSVal && RHSVal->isZero()) {
13333 ConstantFPSDNode *CFVal = dyn_cast<ConstantFPSDNode>(FVal);
13334 ConstantFPSDNode *CTVal = dyn_cast<ConstantFPSDNode>(TVal);
13335
13336 if ((CC == ISD::SETEQ || CC == ISD::SETOEQ || CC == ISD::SETUEQ) &&
13337 CTVal && CTVal->isZero() && TVal.getValueType() == LHS.getValueType())
13338 TVal = LHS;
13339 else if ((CC == ISD::SETNE || CC == ISD::SETONE || CC == ISD::SETUNE) &&
13340 CFVal && CFVal->isZero() &&
13341 FVal.getValueType() == LHS.getValueType())
13342 FVal = LHS;
13343 }
13344 }
13345
13346 // Emit first, and possibly only, CSEL.
13347 // Propagate all flags to the CSEL node for downstream optimization passes.
13348 SDValue CC1Val = getCondCode(DAG, CC1);
13349 SDValue CS1 =
13350 DAG.getNode(AArch64ISD::CSEL, DL, VT, {TVal, FVal, CC1Val, Cmp}, Flags);
13351
13352 // If we need a second CSEL, emit it, using the output of the first as the
13353 // RHS. We're effectively OR'ing the two CC's together.
13354 if (CC2 != AArch64CC::AL) {
13355 SDValue CC2Val = getCondCode(DAG, CC2);
13356 return DAG.getNode(AArch64ISD::CSEL, DL, VT, TVal, CS1, CC2Val, Cmp);
13357 }
13358
13359 // Otherwise, return the output of the first CSEL.
13360 return CS1;
13361}
13362
13363SDValue AArch64TargetLowering::LowerVECTOR_SPLICE(SDValue Op,
13364 SelectionDAG &DAG) const {
13365 EVT Ty = Op.getValueType();
13366 if (!isa<ConstantSDNode>(Op.getOperand(2)))
13367 return SDValue();
13368 auto Idx = Op.getConstantOperandAPInt(2);
13369 int64_t IdxVal = Idx.getSExtValue();
13370 assert(Ty.isScalableVector() &&
13371 "Only expect scalable vectors for custom lowering of VECTOR_SPLICE");
13372
13373 // We can use the splice instruction for certain index values where we are
13374 // able to efficiently generate the correct predicate. The index will be
13375 // inverted and used directly as the input to the ptrue instruction, i.e.
13376 // -1 -> vl1, -2 -> vl2, etc. The predicate will then be reversed to get the
13377 // splice predicate. However, we can only do this if we can guarantee that
13378 // there are enough elements in the vector, hence we check the index <= min
13379 // number of elements.
13380 std::optional<unsigned> PredPattern;
13381 if (Ty.isScalableVector() && Op.getOpcode() == ISD::VECTOR_SPLICE_RIGHT &&
13382 (PredPattern = getSVEPredPatternFromNumElements(IdxVal)) !=
13383 std::nullopt) {
13384 SDLoc DL(Op);
13385
13386 // Create a predicate where all but the last -IdxVal elements are false.
13387 EVT PredVT = Ty.changeVectorElementType(*DAG.getContext(), MVT::i1);
13388 SDValue Pred = getPTrue(DAG, DL, PredVT, *PredPattern);
13389 Pred = DAG.getNode(ISD::VECTOR_REVERSE, DL, PredVT, Pred);
13390
13391 // Now splice the two inputs together using the predicate.
13392 return DAG.getNode(AArch64ISD::SPLICE, DL, Ty, Pred, Op.getOperand(0),
13393 Op.getOperand(1));
13394 }
13395
13396 // We can select to an EXT instruction when indexing the first 256 bytes.
13398 if (Op.getOpcode() == ISD::VECTOR_SPLICE_LEFT &&
13399 (IdxVal * BlockSize / 8) < 256)
13400 return Op;
13401
13402 return SDValue();
13403}
13404
13405SDValue AArch64TargetLowering::LowerSELECT_CC(SDValue Op,
13406 SelectionDAG &DAG) const {
13407 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
13408 SDValue LHS = Op.getOperand(0);
13409 SDValue RHS = Op.getOperand(1);
13410 SDValue TVal = Op.getOperand(2);
13411 SDValue FVal = Op.getOperand(3);
13412 SDNodeFlags Flags = Op->getFlags();
13413 SDLoc DL(Op);
13414 return LowerSELECT_CC(CC, LHS, RHS, TVal, FVal, Op->users(), Flags, DL, DAG);
13415}
13416
13417SDValue AArch64TargetLowering::LowerSELECT(SDValue Op,
13418 SelectionDAG &DAG) const {
13419 SDValue CCVal = Op->getOperand(0);
13420 SDValue TVal = Op->getOperand(1);
13421 SDValue FVal = Op->getOperand(2);
13422 SDLoc DL(Op);
13423
13424 EVT Ty = Op.getValueType();
13425 if (Ty == MVT::aarch64svcount) {
13426 TVal = DAG.getNode(ISD::BITCAST, DL, MVT::nxv16i1, TVal);
13427 FVal = DAG.getNode(ISD::BITCAST, DL, MVT::nxv16i1, FVal);
13428 SDValue Sel =
13429 DAG.getNode(ISD::SELECT, DL, MVT::nxv16i1, CCVal, TVal, FVal);
13430 return DAG.getNode(ISD::BITCAST, DL, Ty, Sel);
13431 }
13432
13433 if (Ty.isScalableVector()) {
13434 MVT PredVT = MVT::getVectorVT(MVT::i1, Ty.getVectorElementCount());
13435 SDValue SplatPred = DAG.getNode(ISD::SPLAT_VECTOR, DL, PredVT, CCVal);
13436 return DAG.getNode(ISD::VSELECT, DL, Ty, SplatPred, TVal, FVal);
13437 }
13438
13439 if (useSVEForFixedLengthVectorVT(Ty, !Subtarget->isNeonAvailable())) {
13440 // FIXME: Ideally this would be the same as above using i1 types, however
13441 // for the moment we can't deal with fixed i1 vector types properly, so
13442 // instead extend the predicate to a result type sized integer vector.
13443 MVT SplatValVT = MVT::getIntegerVT(Ty.getScalarSizeInBits());
13444 MVT PredVT = MVT::getVectorVT(SplatValVT, Ty.getVectorElementCount());
13445 SDValue SplatVal = DAG.getSExtOrTrunc(CCVal, DL, SplatValVT);
13446 SDValue SplatPred = DAG.getNode(ISD::SPLAT_VECTOR, DL, PredVT, SplatVal);
13447 return DAG.getNode(ISD::VSELECT, DL, Ty, SplatPred, TVal, FVal);
13448 }
13449
13450 // Optimize {s|u}{add|sub|mul}.with.overflow feeding into a select
13451 // instruction.
13452 if (ISD::isOverflowIntrOpRes(CCVal)) {
13453 // Only lower legal XALUO ops.
13454 if (!DAG.getTargetLoweringInfo().isTypeLegal(CCVal->getValueType(0)))
13455 return SDValue();
13456
13458 SDValue Value, Overflow;
13459 std::tie(Value, Overflow) = getAArch64XALUOOp(OFCC, CCVal.getValue(0), DAG);
13460 SDValue CCVal = getCondCode(DAG, OFCC);
13461
13462 return DAG.getNode(AArch64ISD::CSEL, DL, Op.getValueType(), TVal, FVal,
13463 CCVal, Overflow);
13464 }
13465
13466 // Lower it the same way as we would lower a SELECT_CC node.
13467 ISD::CondCode CC;
13468 SDValue LHS, RHS;
13469 if (CCVal.getOpcode() == ISD::SETCC) {
13470 LHS = CCVal.getOperand(0);
13471 RHS = CCVal.getOperand(1);
13472 CC = cast<CondCodeSDNode>(CCVal.getOperand(2))->get();
13473 } else {
13474 LHS = CCVal;
13475 RHS = DAG.getConstant(0, DL, CCVal.getValueType());
13476 CC = ISD::SETNE;
13477 }
13478
13479 // If we are lowering a f16 and we do not have fullf16, convert to a f32 in
13480 // order to use FCSELSrrr
13481 if ((Ty == MVT::f16 || Ty == MVT::bf16) && !Subtarget->hasFullFP16()) {
13482 SDValue Poison = DAG.getPOISON(MVT::f32);
13483 TVal = DAG.getTargetInsertSubreg(AArch64::hsub, DL, MVT::f32, Poison, TVal);
13484 FVal = DAG.getTargetInsertSubreg(AArch64::hsub, DL, MVT::f32, Poison, FVal);
13485 }
13486
13487 SDValue Res = LowerSELECT_CC(CC, LHS, RHS, TVal, FVal, Op->users(),
13488 Op->getFlags(), DL, DAG);
13489
13490 if ((Ty == MVT::f16 || Ty == MVT::bf16) && !Subtarget->hasFullFP16()) {
13491 return DAG.getTargetExtractSubreg(AArch64::hsub, DL, Ty, Res);
13492 }
13493
13494 return Res;
13495}
13496
13497SDValue AArch64TargetLowering::LowerJumpTable(SDValue Op,
13498 SelectionDAG &DAG) const {
13499 // Jump table entries as PC relative offsets. No additional tweaking
13500 // is necessary here. Just get the address of the jump table.
13501 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
13502
13505 !Subtarget->isTargetMachO())
13506 return getAddrLarge(JT, DAG);
13507 if (CM == CodeModel::Tiny)
13508 return getAddrTiny(JT, DAG);
13509 return getAddr(JT, DAG);
13510}
13511
13512SDValue AArch64TargetLowering::LowerBR_JT(SDValue Op,
13513 SelectionDAG &DAG) const {
13514 // Jump table entries as PC relative offsets. No additional tweaking
13515 // is necessary here. Just get the address of the jump table.
13516 SDLoc DL(Op);
13517 SDValue JT = Op.getOperand(1);
13518 SDValue Entry = Op.getOperand(2);
13519 int JTI = cast<JumpTableSDNode>(JT.getNode())->getIndex();
13520
13521 auto *AFI = DAG.getMachineFunction().getInfo<AArch64FunctionInfo>();
13522 AFI->setJumpTableEntryInfo(JTI, 4, nullptr);
13523
13524 // With aarch64-jump-table-hardening, we only expand the jump table dispatch
13525 // sequence later, to guarantee the integrity of the intermediate values.
13527 "aarch64-jump-table-hardening")) {
13529 if (Subtarget->isTargetMachO()) {
13530 if (CM != CodeModel::Small && CM != CodeModel::Large)
13531 report_fatal_error("Unsupported code-model for hardened jump-table");
13532 } else {
13533 // Note that COFF support would likely also need JUMP_TABLE_DEBUG_INFO.
13534 assert(Subtarget->isTargetELF() &&
13535 "jump table hardening only supported on MachO/ELF");
13536 if (CM != CodeModel::Small)
13537 report_fatal_error("Unsupported code-model for hardened jump-table");
13538 }
13539
13540 SDValue X16Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, AArch64::X16,
13541 Entry, SDValue());
13542 SDNode *B = DAG.getMachineNode(AArch64::BR_JumpTable, DL, MVT::Other,
13543 DAG.getTargetJumpTable(JTI, MVT::i32),
13544 X16Copy.getValue(0), X16Copy.getValue(1));
13545 return SDValue(B, 0);
13546 }
13547
13548 SDNode *Dest =
13549 DAG.getMachineNode(AArch64::JumpTableDest32, DL, MVT::i64, MVT::i64, JT,
13550 Entry, DAG.getTargetJumpTable(JTI, MVT::i32));
13551 SDValue JTInfo = DAG.getJumpTableDebugInfo(JTI, Op.getOperand(0), DL);
13552 return DAG.getNode(ISD::BRIND, DL, MVT::Other, JTInfo, SDValue(Dest, 0));
13553}
13554
13555SDValue AArch64TargetLowering::LowerBRIND(SDValue Op, SelectionDAG &DAG) const {
13556 SDValue Chain = Op.getOperand(0);
13557 SDValue Dest = Op.getOperand(1);
13558
13559 // BR_JT is lowered to BRIND, but the later lowering is specific to indirectbr
13560 // Skip over the jump-table BRINDs, where the destination is JumpTableDest32.
13561 if (Dest->isMachineOpcode() &&
13562 Dest->getMachineOpcode() == AArch64::JumpTableDest32)
13563 return SDValue();
13564
13565 const MachineFunction &MF = DAG.getMachineFunction();
13566 std::optional<uint16_t> BADisc =
13567 Subtarget->getPtrAuthBlockAddressDiscriminatorIfEnabled(MF.getFunction());
13568 if (!BADisc)
13569 return SDValue();
13570
13571 SDLoc DL(Op);
13572
13573 SDValue Disc = DAG.getTargetConstant(*BADisc, DL, MVT::i64);
13575 SDValue AddrDisc = DAG.getRegister(AArch64::XZR, MVT::i64);
13576
13577 SDNode *BrA = DAG.getMachineNode(AArch64::BRA, DL, MVT::Other,
13578 {Dest, Key, Disc, AddrDisc, Chain});
13579 return SDValue(BrA, 0);
13580}
13581
13582SDValue AArch64TargetLowering::LowerConstantPool(SDValue Op,
13583 SelectionDAG &DAG) const {
13584 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
13586 if (CM == CodeModel::Large) {
13587 // Use the GOT for the large code model on iOS.
13588 if (Subtarget->isTargetMachO()) {
13589 return getGOT(CP, DAG);
13590 }
13592 return getAddrLarge(CP, DAG);
13593 } else if (CM == CodeModel::Tiny) {
13594 return getAddrTiny(CP, DAG);
13595 }
13596 return getAddr(CP, DAG);
13597}
13598
13599SDValue AArch64TargetLowering::LowerBlockAddress(SDValue Op,
13600 SelectionDAG &DAG) const {
13601 BlockAddressSDNode *BAN = cast<BlockAddressSDNode>(Op);
13602 const BlockAddress *BA = BAN->getBlockAddress();
13603
13604 if (std::optional<uint16_t> BADisc =
13605 Subtarget->getPtrAuthBlockAddressDiscriminatorIfEnabled(
13606 *BA->getFunction())) {
13607 SDLoc DL(Op);
13608
13609 // This isn't cheap, but BRIND is rare.
13610 SDValue TargetBA = DAG.getTargetBlockAddress(BA, BAN->getValueType(0));
13611
13612 SDValue Disc = DAG.getTargetConstant(*BADisc, DL, MVT::i64);
13613
13615 SDValue AddrDisc = DAG.getRegister(AArch64::XZR, MVT::i64);
13616
13617 SDNode *MOV =
13618 DAG.getMachineNode(AArch64::MOVaddrPAC, DL, {MVT::Other, MVT::Glue},
13619 {TargetBA, Key, AddrDisc, Disc});
13620 return DAG.getCopyFromReg(SDValue(MOV, 0), DL, AArch64::X16, MVT::i64,
13621 SDValue(MOV, 1));
13622 }
13623
13625 if (CM == CodeModel::Large && !Subtarget->isTargetMachO()) {
13627 return getAddrLarge(BAN, DAG);
13628 } else if (CM == CodeModel::Tiny) {
13629 return getAddrTiny(BAN, DAG);
13630 }
13631 return getAddr(BAN, DAG);
13632}
13633
13634SDValue AArch64TargetLowering::LowerDarwin_VASTART(SDValue Op,
13635 SelectionDAG &DAG) const {
13636 AArch64FunctionInfo *FuncInfo =
13637 DAG.getMachineFunction().getInfo<AArch64FunctionInfo>();
13638
13639 SDLoc DL(Op);
13640 SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsStackIndex(),
13642 FR = DAG.getZExtOrTrunc(FR, DL, getPointerMemTy(DAG.getDataLayout()));
13643 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
13644 return DAG.getStore(Op.getOperand(0), DL, FR, Op.getOperand(1),
13645 MachinePointerInfo(SV));
13646}
13647
13648SDValue AArch64TargetLowering::LowerWin64_VASTART(SDValue Op,
13649 SelectionDAG &DAG) const {
13651 AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
13652
13653 SDLoc DL(Op);
13654 SDValue FR;
13655 if (Subtarget->isWindowsArm64EC()) {
13656 // With the Arm64EC ABI, we compute the address of the varargs save area
13657 // relative to x4. For a normal AArch64->AArch64 call, x4 == sp on entry,
13658 // but calls from an entry thunk can pass in a different address.
13659 Register VReg = MF.addLiveIn(AArch64::X4, &AArch64::GPR64RegClass);
13660 SDValue Val = DAG.getCopyFromReg(DAG.getEntryNode(), DL, VReg, MVT::i64);
13661 uint64_t StackOffset;
13662 if (FuncInfo->getVarArgsGPRSize() > 0)
13663 StackOffset = -(uint64_t)FuncInfo->getVarArgsGPRSize();
13664 else
13665 StackOffset = FuncInfo->getVarArgsStackOffset();
13666 FR = DAG.getNode(ISD::ADD, DL, MVT::i64, Val,
13667 DAG.getConstant(StackOffset, DL, MVT::i64));
13668 } else {
13669 FR = DAG.getFrameIndex(FuncInfo->getVarArgsGPRSize() > 0
13670 ? FuncInfo->getVarArgsGPRIndex()
13671 : FuncInfo->getVarArgsStackIndex(),
13673 }
13674 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
13675 return DAG.getStore(Op.getOperand(0), DL, FR, Op.getOperand(1),
13676 MachinePointerInfo(SV));
13677}
13678
13679SDValue AArch64TargetLowering::LowerAAPCS_VASTART(SDValue Op,
13680 SelectionDAG &DAG) const {
13681 // The layout of the va_list struct is specified in the AArch64 Procedure Call
13682 // Standard, section B.3.
13684 AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
13685 unsigned PtrSize = Subtarget->isTargetILP32() ? 4 : 8;
13686 auto PtrMemVT = getPointerMemTy(DAG.getDataLayout());
13687 auto PtrVT = getPointerTy(DAG.getDataLayout());
13688 SDLoc DL(Op);
13689
13690 SDValue Chain = Op.getOperand(0);
13691 SDValue VAList = Op.getOperand(1);
13692 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
13694
13695 // void *__stack at offset 0
13696 unsigned Offset = 0;
13697 SDValue Stack = DAG.getFrameIndex(FuncInfo->getVarArgsStackIndex(), PtrVT);
13698 Stack = DAG.getZExtOrTrunc(Stack, DL, PtrMemVT);
13699 MemOps.push_back(DAG.getStore(Chain, DL, Stack, VAList,
13700 MachinePointerInfo(SV), Align(PtrSize)));
13701
13702 // void *__gr_top at offset 8 (4 on ILP32)
13703 Offset += PtrSize;
13704 int GPRSize = FuncInfo->getVarArgsGPRSize();
13705 if (GPRSize > 0) {
13706 SDValue GRTop, GRTopAddr;
13707
13708 GRTopAddr = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
13709 DAG.getConstant(Offset, DL, PtrVT));
13710
13711 GRTop = DAG.getFrameIndex(FuncInfo->getVarArgsGPRIndex(), PtrVT);
13712 GRTop = DAG.getNode(ISD::ADD, DL, PtrVT, GRTop,
13713 DAG.getSignedConstant(GPRSize, DL, PtrVT));
13714 GRTop = DAG.getZExtOrTrunc(GRTop, DL, PtrMemVT);
13715
13716 MemOps.push_back(DAG.getStore(Chain, DL, GRTop, GRTopAddr,
13717 MachinePointerInfo(SV, Offset),
13718 Align(PtrSize)));
13719 }
13720
13721 // void *__vr_top at offset 16 (8 on ILP32)
13722 Offset += PtrSize;
13723 int FPRSize = FuncInfo->getVarArgsFPRSize();
13724 if (FPRSize > 0) {
13725 SDValue VRTop, VRTopAddr;
13726 VRTopAddr = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
13727 DAG.getConstant(Offset, DL, PtrVT));
13728
13729 VRTop = DAG.getFrameIndex(FuncInfo->getVarArgsFPRIndex(), PtrVT);
13730 VRTop = DAG.getNode(ISD::ADD, DL, PtrVT, VRTop,
13731 DAG.getSignedConstant(FPRSize, DL, PtrVT));
13732 VRTop = DAG.getZExtOrTrunc(VRTop, DL, PtrMemVT);
13733
13734 MemOps.push_back(DAG.getStore(Chain, DL, VRTop, VRTopAddr,
13735 MachinePointerInfo(SV, Offset),
13736 Align(PtrSize)));
13737 }
13738
13739 // int __gr_offs at offset 24 (12 on ILP32)
13740 Offset += PtrSize;
13741 SDValue GROffsAddr = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
13742 DAG.getConstant(Offset, DL, PtrVT));
13743 MemOps.push_back(
13744 DAG.getStore(Chain, DL, DAG.getSignedConstant(-GPRSize, DL, MVT::i32),
13745 GROffsAddr, MachinePointerInfo(SV, Offset), Align(4)));
13746
13747 // int __vr_offs at offset 28 (16 on ILP32)
13748 Offset += 4;
13749 SDValue VROffsAddr = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
13750 DAG.getConstant(Offset, DL, PtrVT));
13751 MemOps.push_back(
13752 DAG.getStore(Chain, DL, DAG.getSignedConstant(-FPRSize, DL, MVT::i32),
13753 VROffsAddr, MachinePointerInfo(SV, Offset), Align(4)));
13754
13755 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOps);
13756}
13757
13758SDValue AArch64TargetLowering::LowerVASTART(SDValue Op,
13759 SelectionDAG &DAG) const {
13761 Function &F = MF.getFunction();
13762
13763 if (Subtarget->isCallingConvWin64(F.getCallingConv(), F.isVarArg()))
13764 return LowerWin64_VASTART(Op, DAG);
13765 else if (Subtarget->isTargetDarwin())
13766 return LowerDarwin_VASTART(Op, DAG);
13767 else
13768 return LowerAAPCS_VASTART(Op, DAG);
13769}
13770
13771SDValue AArch64TargetLowering::LowerVACOPY(SDValue Op,
13772 SelectionDAG &DAG) const {
13773 // AAPCS has three pointers and two ints (= 32 bytes), Darwin has single
13774 // pointer.
13775 SDLoc DL(Op);
13776 unsigned PtrSize = Subtarget->isTargetILP32() ? 4 : 8;
13777 unsigned VaListSize =
13778 (Subtarget->isTargetDarwin() || Subtarget->isTargetWindows())
13779 ? PtrSize
13780 : Subtarget->isTargetILP32() ? 20 : 32;
13781 const Value *DestSV = cast<SrcValueSDNode>(Op.getOperand(3))->getValue();
13782 const Value *SrcSV = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
13783
13784 return DAG.getMemcpy(Op.getOperand(0), DL, Op.getOperand(1), Op.getOperand(2),
13785 DAG.getConstant(VaListSize, DL, MVT::i32),
13786 Align(PtrSize), Align(PtrSize), false, false,
13787 /*CI=*/nullptr, std::nullopt, MachinePointerInfo(DestSV),
13788 MachinePointerInfo(SrcSV));
13789}
13790
13791SDValue AArch64TargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG) const {
13792 assert(Subtarget->isTargetDarwin() &&
13793 "automatic va_arg instruction only works on Darwin");
13794
13795 const Value *V = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
13796 EVT VT = Op.getValueType();
13797 SDLoc DL(Op);
13798 SDValue Chain = Op.getOperand(0);
13799 SDValue Addr = Op.getOperand(1);
13800 MaybeAlign Align(Op.getConstantOperandVal(3));
13801 unsigned MinSlotSize = Subtarget->isTargetILP32() ? 4 : 8;
13802 auto PtrVT = getPointerTy(DAG.getDataLayout());
13803 auto PtrMemVT = getPointerMemTy(DAG.getDataLayout());
13804 SDValue VAList =
13805 DAG.getLoad(PtrMemVT, DL, Chain, Addr, MachinePointerInfo(V));
13806 Chain = VAList.getValue(1);
13807 VAList = DAG.getZExtOrTrunc(VAList, DL, PtrVT);
13808
13809 if (VT.isScalableVector())
13810 report_fatal_error("Passing SVE types to variadic functions is "
13811 "currently not supported");
13812
13813 if (Align && *Align > MinSlotSize) {
13814 VAList = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
13815 DAG.getConstant(Align->value() - 1, DL, PtrVT));
13816 VAList =
13817 DAG.getNode(ISD::AND, DL, PtrVT, VAList,
13818 DAG.getSignedConstant(-(int64_t)Align->value(), DL, PtrVT));
13819 }
13820
13821 Type *ArgTy = VT.getTypeForEVT(*DAG.getContext());
13822 unsigned ArgSize = DAG.getDataLayout().getTypeAllocSize(ArgTy);
13823
13824 // Scalar integer and FP values smaller than 64 bits are implicitly extended
13825 // up to 64 bits. At the very least, we have to increase the striding of the
13826 // vaargs list to match this, and for FP values we need to introduce
13827 // FP_ROUND nodes as well.
13828 if (VT.isInteger() && !VT.isVector())
13829 ArgSize = std::max(ArgSize, MinSlotSize);
13830 bool NeedFPTrunc = false;
13831 if (VT.isFloatingPoint() && !VT.isVector() && VT != MVT::f64) {
13832 ArgSize = 8;
13833 NeedFPTrunc = true;
13834 }
13835
13836 // Increment the pointer, VAList, to the next vaarg
13837 SDValue VANext = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
13838 DAG.getConstant(ArgSize, DL, PtrVT));
13839 VANext = DAG.getZExtOrTrunc(VANext, DL, PtrMemVT);
13840
13841 // Store the incremented VAList to the legalized pointer
13842 SDValue APStore =
13843 DAG.getStore(Chain, DL, VANext, Addr, MachinePointerInfo(V));
13844
13845 // Load the actual argument out of the pointer VAList
13846 if (NeedFPTrunc) {
13847 // Load the value as an f64.
13848 SDValue WideFP =
13849 DAG.getLoad(MVT::f64, DL, APStore, VAList, MachinePointerInfo());
13850 // Round the value down to an f32.
13851 SDValue NarrowFP =
13852 DAG.getNode(ISD::FP_ROUND, DL, VT, WideFP.getValue(0),
13853 DAG.getIntPtrConstant(1, DL, /*isTarget=*/true));
13854 SDValue Ops[] = { NarrowFP, WideFP.getValue(1) };
13855 // Merge the rounded value with the chain output of the load.
13856 return DAG.getMergeValues(Ops, DL);
13857 }
13858
13859 return DAG.getLoad(VT, DL, APStore, VAList, MachinePointerInfo());
13860}
13861
13862SDValue AArch64TargetLowering::LowerFRAMEADDR(SDValue Op,
13863 SelectionDAG &DAG) const {
13864 MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
13865 MFI.setFrameAddressIsTaken(true);
13866
13867 EVT VT = Op.getValueType();
13868 SDLoc DL(Op);
13869 unsigned Depth = Op.getConstantOperandVal(0);
13870 SDValue FrameAddr =
13871 DAG.getCopyFromReg(DAG.getEntryNode(), DL, AArch64::FP, MVT::i64);
13872 while (Depth--)
13873 FrameAddr = DAG.getLoad(VT, DL, DAG.getEntryNode(), FrameAddr,
13874 MachinePointerInfo());
13875
13876 if (Subtarget->isTargetILP32())
13877 FrameAddr = DAG.getNode(ISD::AssertZext, DL, MVT::i64, FrameAddr,
13878 DAG.getValueType(VT));
13879
13880 return FrameAddr;
13881}
13882
13883SDValue AArch64TargetLowering::LowerSPONENTRY(SDValue Op,
13884 SelectionDAG &DAG) const {
13885 MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
13886
13887 EVT VT = getPointerTy(DAG.getDataLayout());
13888 int FI = MFI.CreateFixedObject(4, 0, false);
13889 return DAG.getFrameIndex(FI, VT);
13890}
13891
13892#define GET_REGISTER_MATCHER
13893#include "AArch64GenAsmMatcher.inc"
13894
13898
13899// FIXME? Maybe this could be a TableGen attribute on some registers and
13900// this table could be generated automatically from RegInfo.
13901Register AArch64TargetLowering::
13902getRegisterByName(const char* RegName, LLT VT, const MachineFunction &MF) const {
13904 // llvm.read_register / llvm.write_register instrisinc handled through the
13905 // generic SelectionDAG path can only access a register that is not
13906 // allocatable: reading one would use an undefined physical register, and its
13907 // contents are not meaningful. Reject anything allocatable here so the
13908 // generic path diagnoses rather than emitting invalid code.
13909 if (Reg && !Subtarget->getRegisterInfo()->isReservedReg(MF, Reg))
13910 Reg = Register();
13911 return Reg;
13912}
13913
13914SDValue AArch64TargetLowering::LowerADDROFRETURNADDR(SDValue Op,
13915 SelectionDAG &DAG) const {
13917
13918 EVT VT = Op.getValueType();
13919 SDLoc DL(Op);
13920
13921 SDValue FrameAddr =
13922 DAG.getCopyFromReg(DAG.getEntryNode(), DL, AArch64::FP, VT);
13924
13925 return DAG.getNode(ISD::ADD, DL, VT, FrameAddr, Offset);
13926}
13927
13928SDValue AArch64TargetLowering::LowerRETURNADDR(SDValue Op,
13929 SelectionDAG &DAG) const {
13931 MachineFrameInfo &MFI = MF.getFrameInfo();
13932 MFI.setReturnAddressIsTaken(true);
13933
13934 EVT VT = Op.getValueType();
13935 SDLoc DL(Op);
13936 unsigned Depth = Op.getConstantOperandVal(0);
13937 SDValue ReturnAddress;
13938 if (Depth) {
13939 SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
13941 ReturnAddress = DAG.getLoad(
13942 VT, DL, DAG.getEntryNode(),
13943 DAG.getNode(ISD::ADD, DL, VT, FrameAddr, Offset), MachinePointerInfo());
13944 } else {
13945 // Return LR, which contains the return address. Mark it an implicit
13946 // live-in.
13947 Register Reg = MF.addLiveIn(AArch64::LR, &AArch64::GPR64RegClass);
13948 ReturnAddress = DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, VT);
13949 }
13950
13951 // The XPACLRI instruction assembles to a hint-space instruction before
13952 // Armv8.3-A therefore this instruction can be safely used for any pre
13953 // Armv8.3-A architectures. On Armv8.3-A and onwards XPACI is available so use
13954 // that instead.
13955 SDNode *St;
13956 if (Subtarget->hasPAuth()) {
13957 St = DAG.getMachineNode(AArch64::XPACI, DL, VT, ReturnAddress);
13958 } else {
13959 // XPACLRI operates on LR therefore we must move the operand accordingly.
13960 SDValue Chain =
13961 DAG.getCopyToReg(DAG.getEntryNode(), DL, AArch64::LR, ReturnAddress);
13962 St = DAG.getMachineNode(AArch64::XPACLRI, DL, VT, Chain);
13963 }
13964 return SDValue(St, 0);
13965}
13966
13967/// LowerShiftParts - Lower SHL_PARTS/SRA_PARTS/SRL_PARTS, which returns two
13968/// i32 values and take a 2 x i32 value to shift plus a shift amount.
13969SDValue AArch64TargetLowering::LowerShiftParts(SDValue Op,
13970 SelectionDAG &DAG) const {
13971 SDValue Lo, Hi;
13972 expandShiftParts(Op.getNode(), Lo, Hi, DAG);
13973 return DAG.getMergeValues({Lo, Hi}, SDLoc(Op));
13974}
13975
13977 const GlobalAddressSDNode *GA) const {
13978 // Offsets are folded in the DAG combine rather than here so that we can
13979 // intelligently choose an offset based on the uses.
13980 return false;
13981}
13982
13984 EVT VT) const {
13985 // We can materialize #0.0 as fmov $Rd, XZR for 64-bit, 32-bit cases, and
13986 // 16-bit case when target has full fp16 support.
13987 // We encode bf16 bit patterns as if they were fp16. This results in very
13988 // strange looking assembly but should populate the register with appropriate
13989 // values. Let's say we wanted to encode 0xR3FC0 which is 1.5 in BF16. We will
13990 // end up encoding this as the imm8 0x7f. This imm8 will be expanded to the
13991 // FP16 1.9375 which shares the same bit pattern as BF16 1.5.
13992 // FIXME: We should be able to handle f128 as well with a clever lowering.
13993 const APInt ImmInt = Imm.bitcastToAPInt();
13994
13995 if (VT == MVT::f64)
13996 return AArch64_AM::getFP64Imm(ImmInt) != -1 || Imm.isPosZero();
13997
13998 if (VT == MVT::f32)
13999 return AArch64_AM::getFP32Imm(ImmInt) != -1 || Imm.isPosZero();
14000
14001 if (VT == MVT::f16 || VT == MVT::bf16)
14002 return (Subtarget->hasFullFP16() && AArch64_AM::getFP16Imm(ImmInt) != -1) ||
14003 Imm.isPosZero();
14004
14005 return false;
14006}
14007
14009 bool OptForSize) const {
14010 bool IsLegal = isFPImmLegalAsFMov(Imm, VT);
14011
14012 // If we can not materialize in immediate field for fmov, check if the
14013 // value can be encoded as the immediate operand of a logical instruction.
14014 // The immediate value will be created with either MOVZ, MOVN, or ORR.
14015 // TODO: fmov h0, w0 is also legal, however we don't have an isel pattern to
14016 // generate that fmov.
14017 if (!IsLegal && (VT == MVT::f64 || VT == MVT::f32)) {
14018 // The cost is actually exactly the same for mov+fmov vs. adrp+ldr;
14019 // however the mov+fmov sequence is always better because of the reduced
14020 // cache pressure. The timings are still the same if you consider
14021 // movw+movk+fmov vs. adrp+ldr (it's one instruction longer, but the
14022 // movw+movk is fused). So by default we limit up to 2 instructions
14023 // or 4 with hasFuseLiterals.
14025 const APInt ImmInt = Imm.bitcastToAPInt();
14027 assert(Insn.size() <= 4 &&
14028 "Should be able to build any value with at most 4 moves");
14029
14030 unsigned Limit = OptForSize ? 1 : 2;
14031
14032 if (!OptForSize && Insn.size() > Limit && Subtarget->hasFuseLiterals()) {
14033 // Relax the limit based on subtarget fusion capabilites
14034 for (unsigned I = 0; I + 1 < Insn.size(); ++I) {
14035 const AArch64_IMM::ImmInsnModel &First = Insn[I];
14036 const AArch64_IMM::ImmInsnModel &Second = Insn[I + 1];
14037 if (Subtarget->fusesMOVImmPair(First.Opcode, First.Op2, Second.Opcode,
14038 Second.Op2)) {
14039 ++Limit;
14040 // An instruction can only be fused once, so the 2nd one of the pair
14041 // cannot start another pair and is skipped.
14042 ++I;
14043 }
14044 }
14045 }
14046
14047 IsLegal = Insn.size() <= Limit;
14048 }
14049
14050 LLVM_DEBUG(dbgs() << (IsLegal ? "Legal " : "Illegal ") << VT
14051 << " imm value: ";
14052 Imm.dump(););
14053 return IsLegal;
14054}
14055
14056//===----------------------------------------------------------------------===//
14057// AArch64 Optimization Hooks
14058//===----------------------------------------------------------------------===//
14059
14060static SDValue getEstimate(const AArch64Subtarget *ST, unsigned Opcode,
14061 SDValue Operand, SelectionDAG &DAG,
14062 int &ExtraSteps) {
14063 EVT VT = Operand.getValueType();
14064 if ((ST->hasNEON() &&
14065 (VT == MVT::f64 || VT == MVT::v1f64 || VT == MVT::v2f64 ||
14066 VT == MVT::f32 || VT == MVT::v1f32 || VT == MVT::v2f32 ||
14067 VT == MVT::v4f32)) ||
14068 (ST->hasSVE() &&
14069 (VT == MVT::nxv8f16 || VT == MVT::nxv4f32 || VT == MVT::nxv2f64))) {
14071 // For the reciprocal estimates, convergence is quadratic, so the number
14072 // of digits is doubled after each iteration. In ARMv8, the accuracy of
14073 // the initial estimate is 2^-8. Thus the number of extra steps to refine
14074 // the result for float (23 mantissa bits) is 2 and for double (52
14075 // mantissa bits) is 3.
14076 constexpr unsigned AccurateBits = 8;
14077 unsigned DesiredBits = APFloat::semanticsPrecision(VT.getFltSemantics());
14078 ExtraSteps = DesiredBits <= AccurateBits
14079 ? 0
14080 : Log2_64_Ceil(DesiredBits) - Log2_64_Ceil(AccurateBits);
14081 }
14082
14083 return DAG.getNode(Opcode, SDLoc(Operand), VT, Operand);
14084 }
14085
14086 return SDValue();
14087}
14088
14089SDValue AArch64TargetLowering::getSqrtInputTest(SDValue Op, SelectionDAG &DAG,
14090 const DenormalMode &Mode,
14091 SDNodeFlags Flags) const {
14092 SDLoc DL(Op);
14093 EVT VT = Op.getValueType();
14094 EVT CCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
14095 SDValue FPZero = DAG.getConstantFP(0.0, DL, VT);
14096 return DAG.getSetCC(DL, CCVT, Op, FPZero, ISD::SETEQ, /*Chain=*/{},
14097 /*Signaling=*/false, Flags);
14098}
14099
14100SDValue
14101AArch64TargetLowering::getSqrtResultForDenormInput(SDValue Op,
14102 SelectionDAG &DAG) const {
14103 return Op;
14104}
14105
14106SDValue AArch64TargetLowering::getSqrtEstimate(SDValue Operand,
14107 SelectionDAG &DAG, int Enabled,
14108 int &ExtraSteps,
14109 bool &UseOneConst,
14110 bool Reciprocal) const {
14112 (Enabled == ReciprocalEstimate::Unspecified && Subtarget->useRSqrt()))
14113 if (SDValue Estimate = getEstimate(Subtarget, AArch64ISD::FRSQRTE, Operand,
14114 DAG, ExtraSteps)) {
14115 SDLoc DL(Operand);
14116 EVT VT = Operand.getValueType();
14117
14118 // Ensure nodes can be recognized by isAssociativeAndCommutative.
14119 SDNodeFlags Flags =
14121
14122 // Newton reciprocal square root iteration: E * 0.5 * (3 - X * E^2)
14123 // AArch64 reciprocal square root iteration instruction: 0.5 * (3 - M * N)
14124 for (int i = ExtraSteps; i > 0; --i) {
14125 SDValue Step = DAG.getNode(ISD::FMUL, DL, VT, Estimate, Estimate,
14126 Flags);
14127 Step = DAG.getNode(AArch64ISD::FRSQRTS, DL, VT, Operand, Step, Flags);
14128 Estimate = DAG.getNode(ISD::FMUL, DL, VT, Estimate, Step, Flags);
14129 }
14130 if (!Reciprocal)
14131 Estimate = DAG.getNode(ISD::FMUL, DL, VT, Operand, Estimate, Flags);
14132
14133 ExtraSteps = 0;
14134 return Estimate;
14135 }
14136
14137 return SDValue();
14138}
14139
14140SDValue AArch64TargetLowering::getRecipEstimate(SDValue Operand,
14141 SelectionDAG &DAG, int Enabled,
14142 int &ExtraSteps) const {
14144 if (SDValue Estimate = getEstimate(Subtarget, AArch64ISD::FRECPE, Operand,
14145 DAG, ExtraSteps)) {
14146 SDLoc DL(Operand);
14147 EVT VT = Operand.getValueType();
14148
14150
14151 // Newton reciprocal iteration: E * (2 - X * E)
14152 // AArch64 reciprocal iteration instruction: (2 - M * N)
14153 for (int i = ExtraSteps; i > 0; --i) {
14154 SDValue Step = DAG.getNode(AArch64ISD::FRECPS, DL, VT, Operand,
14155 Estimate, Flags);
14156 Estimate = DAG.getNode(ISD::FMUL, DL, VT, Estimate, Step, Flags);
14157 }
14158
14159 ExtraSteps = 0;
14160 return Estimate;
14161 }
14162
14163 return SDValue();
14164}
14165
14166//===----------------------------------------------------------------------===//
14167// AArch64 Inline Assembly Support
14168//===----------------------------------------------------------------------===//
14169
14170// Table of Constraints
14171// TODO: This is the current set of constraints supported by ARM for the
14172// compiler, not all of them may make sense.
14173//
14174// r - A general register
14175// w - An FP/SIMD register of some size in the range v0-v31
14176// x - An FP/SIMD register of some size in the range v0-v15
14177// I - Constant that can be used with an ADD instruction
14178// J - Constant that can be used with a SUB instruction
14179// K - Constant that can be used with a 32-bit logical instruction
14180// L - Constant that can be used with a 64-bit logical instruction
14181// M - Constant that can be used as a 32-bit MOV immediate
14182// N - Constant that can be used as a 64-bit MOV immediate
14183// Q - A memory reference with base register and no offset
14184// S - A symbolic address
14185// Y - Floating point constant zero
14186// Z - Integer constant zero
14187//
14188// Note that general register operands will be output using their 64-bit x
14189// register name, whatever the size of the variable, unless the asm operand
14190// is prefixed by the %w modifier. Floating-point and SIMD register operands
14191// will be output with the v prefix unless prefixed by the %b, %h, %s, %d or
14192// %q modifier.
14193const char *AArch64TargetLowering::LowerXConstraint(EVT ConstraintVT) const {
14194 // At this point, we have to lower this constraint to something else, so we
14195 // lower it to an "r" or "w". However, by doing this we will force the result
14196 // to be in register, while the X constraint is much more permissive.
14197 //
14198 // Although we are correct (we are free to emit anything, without
14199 // constraints), we might break use cases that would expect us to be more
14200 // efficient and emit something else.
14201 if (!Subtarget->hasFPARMv8())
14202 return "r";
14203
14204 if (ConstraintVT.isFloatingPoint())
14205 return "w";
14206
14207 if (ConstraintVT.isVector() &&
14208 (ConstraintVT.getSizeInBits() == 64 ||
14209 ConstraintVT.getSizeInBits() == 128))
14210 return "w";
14211
14212 return "r";
14213}
14214
14216
14217// Returns a {Reg, RegisterClass} tuple if the constraint is
14218// a specific predicate register.
14219//
14220// For some constraint like "{pn3}" the default path in
14221// TargetLowering::getRegForInlineAsmConstraint() leads it to determine that a
14222// suitable register class for this register is "PPRorPNR", after which it
14223// determines that nxv16i1 is an appropriate type for the constraint, which is
14224// not what we want. The code here pre-empts this by matching the register
14225// explicitly.
14226static std::optional<std::pair<unsigned, const TargetRegisterClass *>>
14228 if (!Constraint.starts_with('{') || !Constraint.ends_with('}') ||
14229 (Constraint[1] != 'p' && Constraint[1] != 'z'))
14230 return std::nullopt;
14231
14232 bool IsPredicate = Constraint[1] == 'p';
14233 Constraint = Constraint.substr(2, Constraint.size() - 3);
14234 bool IsPredicateAsCount = IsPredicate && Constraint.starts_with("n");
14235 if (IsPredicateAsCount)
14236 Constraint = Constraint.drop_front(1);
14237
14238 unsigned V;
14239 if (Constraint.getAsInteger(10, V) || V > 31)
14240 return std::nullopt;
14241
14242 if (IsPredicateAsCount)
14243 return std::make_pair(AArch64::PN0 + V, &AArch64::PNRRegClass);
14244 if (IsPredicate)
14245 return std::make_pair(AArch64::P0 + V, &AArch64::PPRRegClass);
14246 return std::make_pair(AArch64::Z0 + V, &AArch64::ZPRRegClass);
14247}
14248
14249static std::optional<PredicateConstraint>
14252 .Case("Uph", PredicateConstraint::Uph)
14255 .Default(std::nullopt);
14256}
14257
14258static const TargetRegisterClass *
14260 if (VT != MVT::aarch64svcount && !VT.isScalableVectorOf(MVT::i1))
14261 return nullptr;
14262
14263 switch (Constraint) {
14265 return VT == MVT::aarch64svcount ? &AArch64::PNR_p8to15RegClass
14266 : &AArch64::PPR_p8to15RegClass;
14268 return VT == MVT::aarch64svcount ? &AArch64::PNR_3bRegClass
14269 : &AArch64::PPR_3bRegClass;
14271 return VT == MVT::aarch64svcount ? &AArch64::PNRRegClass
14272 : &AArch64::PPRRegClass;
14273 }
14274
14275 llvm_unreachable("Missing PredicateConstraint!");
14276}
14277
14279
14280static std::optional<ReducedGprConstraint>
14283 .Case("Uci", ReducedGprConstraint::Uci)
14285 .Default(std::nullopt);
14286}
14287
14288static const TargetRegisterClass *
14290 if (!VT.isScalarInteger() || VT.getFixedSizeInBits() > 64)
14291 return nullptr;
14292
14293 switch (Constraint) {
14295 return &AArch64::MatrixIndexGPR32_8_11RegClass;
14297 return &AArch64::MatrixIndexGPR32_12_15RegClass;
14298 }
14299
14300 llvm_unreachable("Missing ReducedGprConstraint!");
14301}
14302
14303// The set of cc code supported is from
14304// https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Flag-Output-Operands
14307 .Case("{@cchi}", AArch64CC::HI)
14308 .Case("{@cccs}", AArch64CC::HS)
14309 .Case("{@cclo}", AArch64CC::LO)
14310 .Case("{@ccls}", AArch64CC::LS)
14311 .Case("{@cccc}", AArch64CC::LO)
14312 .Case("{@cceq}", AArch64CC::EQ)
14313 .Case("{@ccgt}", AArch64CC::GT)
14314 .Case("{@ccge}", AArch64CC::GE)
14315 .Case("{@cclt}", AArch64CC::LT)
14316 .Case("{@ccle}", AArch64CC::LE)
14317 .Case("{@cchs}", AArch64CC::HS)
14318 .Case("{@ccne}", AArch64CC::NE)
14319 .Case("{@ccvc}", AArch64CC::VC)
14320 .Case("{@ccpl}", AArch64CC::PL)
14321 .Case("{@ccvs}", AArch64CC::VS)
14322 .Case("{@ccmi}", AArch64CC::MI)
14324 return Cond;
14325}
14326
14327/// Helper function to create 'CSET', which is equivalent to 'CSINC <Wd>, WZR,
14328/// WZR, invert(<cond>)'.
14330 SelectionDAG &DAG) {
14331 return DAG.getNode(AArch64ISD::CSINC, DL, MVT::i32,
14332 DAG.getConstant(0, DL, MVT::i32),
14333 DAG.getConstant(0, DL, MVT::i32),
14334 getCondCode(DAG, getInvertedCondCode(CC)), NZCV);
14335}
14336
14337// Lower @cc flag output via getSETCC.
14338SDValue AArch64TargetLowering::LowerAsmOutputForConstraint(
14339 SDValue &Chain, SDValue &Glue, const SDLoc &DL,
14340 const AsmOperandInfo &OpInfo, SelectionDAG &DAG) const {
14341 AArch64CC::CondCode Cond = parseConstraintCode(OpInfo.ConstraintCode);
14342 if (Cond == AArch64CC::Invalid)
14343 return SDValue();
14344 // The output variable should be a scalar integer.
14345 if (OpInfo.ConstraintVT.isVector() || !OpInfo.ConstraintVT.isInteger() ||
14346 OpInfo.ConstraintVT.getSizeInBits() < 8)
14347 report_fatal_error("Flag output operand is of invalid type");
14348
14349 // Get NZCV register. Only update chain when copyfrom is glued.
14350 if (Glue.getNode()) {
14351 Glue = DAG.getCopyFromReg(Chain, DL, AArch64::NZCV, FlagsVT, Glue);
14352 Chain = Glue.getValue(1);
14353 } else
14354 Glue = DAG.getCopyFromReg(Chain, DL, AArch64::NZCV, FlagsVT);
14355 // Extract CC code.
14356 SDValue CC = getSETCC(Cond, Glue, DL, DAG);
14357
14359
14360 // Truncate or ZERO_EXTEND based on value types.
14361 if (OpInfo.ConstraintVT.getSizeInBits() <= 32)
14362 Result = DAG.getNode(ISD::TRUNCATE, DL, OpInfo.ConstraintVT, CC);
14363 else
14364 Result = DAG.getNode(ISD::ZERO_EXTEND, DL, OpInfo.ConstraintVT, CC);
14365
14366 return Result;
14367}
14368
14369/// getConstraintType - Given a constraint letter, return the type of
14370/// constraint it is for this target.
14372AArch64TargetLowering::getConstraintType(StringRef Constraint) const {
14373 if (Constraint.size() == 1) {
14374 switch (Constraint[0]) {
14375 default:
14376 break;
14377 case 'x':
14378 case 'w':
14379 case 'y':
14380 return C_RegisterClass;
14381 // An address with a single base register. Due to the way we
14382 // currently handle addresses it is the same as 'r'.
14383 case 'Q':
14384 return C_Memory;
14385 case 'I':
14386 case 'J':
14387 case 'K':
14388 case 'L':
14389 case 'M':
14390 case 'N':
14391 case 'Y':
14392 case 'Z':
14393 return C_Immediate;
14394 case 'z':
14395 case 'S': // A symbol or label reference with a constant offset
14396 return C_Other;
14397 }
14398 } else if (parsePredicateConstraint(Constraint))
14399 return C_RegisterClass;
14400 else if (parseReducedGprConstraint(Constraint))
14401 return C_RegisterClass;
14402 else if (parseConstraintCode(Constraint) != AArch64CC::Invalid)
14403 return C_Other;
14404 return TargetLowering::getConstraintType(Constraint);
14405}
14406
14407/// Examine constraint type and operand type and determine a weight value.
14408/// This object must already have been set up with the operand type
14409/// and the current alternative constraint selected.
14411AArch64TargetLowering::getSingleConstraintMatchWeight(
14412 AsmOperandInfo &info, const char *constraint) const {
14414 Value *CallOperandVal = info.CallOperandVal;
14415 // If we don't have a value, we can't do a match,
14416 // but allow it at the lowest weight.
14417 if (!CallOperandVal)
14418 return CW_Default;
14419 Type *type = CallOperandVal->getType();
14420 // Look at the constraint type.
14421 switch (*constraint) {
14422 default:
14424 break;
14425 case 'x':
14426 case 'w':
14427 case 'y':
14428 if (type->isFloatingPointTy() || type->isVectorTy())
14429 weight = CW_Register;
14430 break;
14431 case 'z':
14432 weight = CW_Constant;
14433 break;
14434 case 'U':
14435 if (parsePredicateConstraint(constraint) ||
14436 parseReducedGprConstraint(constraint))
14437 weight = CW_Register;
14438 break;
14439 }
14440 return weight;
14441}
14442
14443std::pair<unsigned, const TargetRegisterClass *>
14444AArch64TargetLowering::getRegForInlineAsmConstraint(
14445 const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
14446 if (Constraint.size() == 1) {
14447 switch (Constraint[0]) {
14448 case 'r':
14449 if (VT.isScalableVector())
14450 return std::make_pair(0U, nullptr);
14451 if (Subtarget->hasLS64() && VT.getSizeInBits() == 512)
14452 return std::make_pair(0U, &AArch64::GPR64x8ClassRegClass);
14453 if (VT.getFixedSizeInBits() == 64)
14454 return std::make_pair(0U, &AArch64::GPR64commonRegClass);
14455 return std::make_pair(0U, &AArch64::GPR32commonRegClass);
14456 case 'w': {
14457 if (!Subtarget->hasFPARMv8())
14458 break;
14459 if (VT.isScalableVector()) {
14460 if (VT.getVectorElementType() != MVT::i1)
14461 return std::make_pair(0U, &AArch64::ZPRRegClass);
14462 return std::make_pair(0U, nullptr);
14463 }
14464 if (VT == MVT::Other)
14465 break;
14466 uint64_t VTSize = VT.getFixedSizeInBits();
14467 if (VTSize == 16)
14468 return std::make_pair(0U, &AArch64::FPR16RegClass);
14469 if (VTSize == 32)
14470 return std::make_pair(0U, &AArch64::FPR32RegClass);
14471 if (VTSize == 64)
14472 return std::make_pair(0U, &AArch64::FPR64RegClass);
14473 if (VTSize == 128)
14474 return std::make_pair(0U, &AArch64::FPR128RegClass);
14475 break;
14476 }
14477 // The instructions that this constraint is designed for can
14478 // only take 128-bit registers so just use that regclass.
14479 case 'x':
14480 if (!Subtarget->hasFPARMv8())
14481 break;
14482 if (VT.isScalableVector())
14483 return std::make_pair(0U, &AArch64::ZPR_4bRegClass);
14484 if (VT.getSizeInBits() == 128)
14485 return std::make_pair(0U, &AArch64::FPR128_loRegClass);
14486 break;
14487 case 'y':
14488 if (!Subtarget->hasFPARMv8())
14489 break;
14490 if (VT.isScalableVector())
14491 return std::make_pair(0U, &AArch64::ZPR_3bRegClass);
14492 break;
14493 }
14494 } else {
14495 if (const auto P = parseSVERegAsConstraint(Constraint)) {
14496 if (!AArch64::ZPRRegClass.hasSubClassEq(P->second))
14497 return *P;
14498
14499 // A named Z-register constraint with MVT::Other
14500 // represents an untyped clobber.
14501 if (VT == MVT::Other) {
14502 // SME functions that are not in streaming mode, should
14503 // still observe clobbers of Z-registers by clobbering
14504 // the lower 128bits of those registers.
14505 if (!Subtarget->isSVEorStreamingSVEAvailable())
14506 return std::make_pair(TRI->getSubReg(P->first, AArch64::zsub),
14507 &AArch64::FPR128RegClass);
14508 return *P;
14509 }
14510
14511 if (Subtarget->isSVEorStreamingSVEAvailable()) {
14512 // Accept the full-width SVE vector types representable in C
14513 switch (VT.SimpleTy) {
14514 case MVT::nxv16i8:
14515 case MVT::nxv8i16:
14516 case MVT::nxv4i32:
14517 case MVT::nxv2i64:
14518 case MVT::nxv8f16:
14519 case MVT::nxv4f32:
14520 case MVT::nxv2f64:
14521 case MVT::nxv8bf16:
14522 return *P;
14523 default:
14524 break;
14525 }
14526 }
14527
14528 return std::make_pair(0U, nullptr);
14529 }
14530 if (const auto PC = parsePredicateConstraint(Constraint))
14531 if (const auto *RegClass = getPredicateRegisterClass(*PC, VT))
14532 return std::make_pair(0U, RegClass);
14533
14534 if (const auto RGC = parseReducedGprConstraint(Constraint))
14535 if (const auto *RegClass = getReducedGprRegisterClass(*RGC, VT))
14536 return std::make_pair(0U, RegClass);
14537 }
14538 if (StringRef("{cc}").equals_insensitive(Constraint) ||
14540 return std::make_pair(unsigned(AArch64::NZCV), &AArch64::CCRRegClass);
14541
14542 if (Constraint == "{za}") {
14543 return std::make_pair(unsigned(AArch64::ZA), &AArch64::MPRRegClass);
14544 }
14545
14546 if (Constraint == "{zt0}") {
14547 return std::make_pair(unsigned(AArch64::ZT0), &AArch64::ZTRRegClass);
14548 }
14549
14550 // Clang will correctly decode the usage of register name aliases into their
14551 // official names. However, other frontends like `rustc` do not. The
14552 // conversion below allows users of these frontends to use the ABI names for
14553 // registers in LLVM-style register constraints.
14554 //
14555 // x31->sp is not included here because it's not a general register and
14556 // needs different handling
14557 unsigned XRegFromAlias = StringSwitch<unsigned>(Constraint.lower())
14558 .Cases({"{x29}", "{fp}"}, AArch64::FP)
14559 .Cases({"{x30}", "{lr}"}, AArch64::LR)
14560 .Default(AArch64::NoRegister);
14561 if (XRegFromAlias != AArch64::NoRegister)
14562 return std::make_pair(XRegFromAlias, &AArch64::GPR64RegClass);
14563
14564 // Use the default implementation in TargetLowering to convert the register
14565 // constraint into a member of a register class.
14566 std::pair<unsigned, const TargetRegisterClass *> Res;
14568
14569 // Not found as a standard register?
14570 if (!Res.second) {
14571 unsigned Size = Constraint.size();
14572 if ((Size == 4 || Size == 5) && Constraint[0] == '{' &&
14573 tolower(Constraint[1]) == 'v' && Constraint[Size - 1] == '}') {
14574 int RegNo;
14575 bool Failed = Constraint.slice(2, Size - 1).getAsInteger(10, RegNo);
14576 if (!Failed && RegNo >= 0 && RegNo <= 31) {
14577 // v0 - v31 are aliases of q0/d0/s0/h0 - ...31 depending on size.
14578 // By default we'll emit v0-v31 for this unless there's a modifier where
14579 // we'll emit the correct register as well.
14580 if (VT != MVT::Other) {
14581 switch (VT.getSizeInBits()) {
14582 case 16:
14583 Res.first = AArch64::FPR16RegClass.getRegister(RegNo);
14584 Res.second = &AArch64::FPR16RegClass;
14585 break;
14586 case 32:
14587 Res.first = AArch64::FPR32RegClass.getRegister(RegNo);
14588 Res.second = &AArch64::FPR32RegClass;
14589 break;
14590 case 64:
14591 Res.first = AArch64::FPR64RegClass.getRegister(RegNo);
14592 Res.second = &AArch64::FPR64RegClass;
14593 break;
14594 case 128:
14595 Res.first = AArch64::FPR128RegClass.getRegister(RegNo);
14596 Res.second = &AArch64::FPR128RegClass;
14597 break;
14598 default:
14599 return std::make_pair(0U, nullptr);
14600 }
14601 } else {
14602 Res.first = AArch64::FPR128RegClass.getRegister(RegNo);
14603 Res.second = &AArch64::FPR128RegClass;
14604 }
14605 }
14606 }
14607 }
14608
14609 if (Res.second && !Subtarget->hasFPARMv8() &&
14610 !AArch64::GPR32allRegClass.hasSubClassEq(Res.second) &&
14611 !AArch64::GPR64allRegClass.hasSubClassEq(Res.second))
14612 return std::make_pair(0U, nullptr);
14613
14614 return Res;
14615}
14616
14618 llvm::Type *Ty,
14619 bool AllowUnknown) const {
14620 if (Subtarget->hasLS64() && Ty->isIntegerTy(512))
14621 return EVT(MVT::i64x8);
14622
14623 return TargetLowering::getAsmOperandValueType(DL, Ty, AllowUnknown);
14624}
14625
14626/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
14627/// vector. If it is invalid, don't add anything to Ops.
14628void AArch64TargetLowering::LowerAsmOperandForConstraint(
14629 SDValue Op, StringRef Constraint, std::vector<SDValue> &Ops,
14630 SelectionDAG &DAG) const {
14631 SDValue Result;
14632
14633 // Currently only support length 1 constraints.
14634 if (Constraint.size() != 1)
14635 return;
14636
14637 char ConstraintLetter = Constraint[0];
14638 switch (ConstraintLetter) {
14639 default:
14640 break;
14641
14642 // This set of constraints deal with valid constants for various instructions.
14643 // Validate and return a target constant for them if we can.
14644 case 'z': {
14645 // 'z' maps to xzr or wzr so it needs an input of 0.
14646 if (!isNullConstant(Op))
14647 return;
14648
14649 if (Op.getValueType() == MVT::i64)
14650 Result = DAG.getRegister(AArch64::XZR, MVT::i64);
14651 else
14652 Result = DAG.getRegister(AArch64::WZR, MVT::i32);
14653 break;
14654 }
14655 case 'S':
14656 // Use the generic code path for "s". In GCC's aarch64 port, "S" is
14657 // supported for PIC while "s" isn't, making "s" less useful. We implement
14658 // "S" but not "s".
14660 break;
14661
14662 case 'I':
14663 case 'J':
14664 case 'K':
14665 case 'L':
14666 case 'M':
14667 case 'N':
14669 if (!C)
14670 return;
14671
14672 // Grab the value and do some validation.
14673 uint64_t CVal = C->getZExtValue();
14674 switch (ConstraintLetter) {
14675 // The I constraint applies only to simple ADD or SUB immediate operands:
14676 // i.e. 0 to 4095 with optional shift by 12
14677 // The J constraint applies only to ADD or SUB immediates that would be
14678 // valid when negated, i.e. if [an add pattern] were to be output as a SUB
14679 // instruction [or vice versa], in other words -1 to -4095 with optional
14680 // left shift by 12.
14681 case 'I':
14682 if (isUInt<12>(CVal) || isShiftedUInt<12, 12>(CVal))
14683 break;
14684 return;
14685 case 'J': {
14686 uint64_t NVal = -C->getSExtValue();
14687 if (isUInt<12>(NVal) || isShiftedUInt<12, 12>(NVal)) {
14688 CVal = C->getSExtValue();
14689 break;
14690 }
14691 return;
14692 }
14693 // The K and L constraints apply *only* to logical immediates, including
14694 // what used to be the MOVI alias for ORR (though the MOVI alias has now
14695 // been removed and MOV should be used). So these constraints have to
14696 // distinguish between bit patterns that are valid 32-bit or 64-bit
14697 // "bitmask immediates": for example 0xaaaaaaaa is a valid bimm32 (K), but
14698 // not a valid bimm64 (L) where 0xaaaaaaaaaaaaaaaa would be valid, and vice
14699 // versa.
14700 case 'K':
14701 if (AArch64_AM::isLogicalImmediate(CVal, 32))
14702 break;
14703 return;
14704 case 'L':
14705 if (AArch64_AM::isLogicalImmediate(CVal, 64))
14706 break;
14707 return;
14708 // The M and N constraints are a superset of K and L respectively, for use
14709 // with the MOV (immediate) alias. As well as the logical immediates they
14710 // also match 32 or 64-bit immediates that can be loaded either using a
14711 // *single* MOVZ or MOVN , such as 32-bit 0x12340000, 0x00001234, 0xffffedca
14712 // (M) or 64-bit 0x1234000000000000 (N) etc.
14713 // As a note some of this code is liberally stolen from the asm parser.
14714 case 'M': {
14715 if (!isUInt<32>(CVal))
14716 return;
14717 if (AArch64_AM::isLogicalImmediate(CVal, 32))
14718 break;
14719 if ((CVal & 0xFFFF) == CVal)
14720 break;
14721 if ((CVal & 0xFFFF0000ULL) == CVal)
14722 break;
14723 uint64_t NCVal = ~(uint32_t)CVal;
14724 if ((NCVal & 0xFFFFULL) == NCVal)
14725 break;
14726 if ((NCVal & 0xFFFF0000ULL) == NCVal)
14727 break;
14728 return;
14729 }
14730 case 'N': {
14731 if (AArch64_AM::isLogicalImmediate(CVal, 64))
14732 break;
14733 if ((CVal & 0xFFFFULL) == CVal)
14734 break;
14735 if ((CVal & 0xFFFF0000ULL) == CVal)
14736 break;
14737 if ((CVal & 0xFFFF00000000ULL) == CVal)
14738 break;
14739 if ((CVal & 0xFFFF000000000000ULL) == CVal)
14740 break;
14741 uint64_t NCVal = ~CVal;
14742 if ((NCVal & 0xFFFFULL) == NCVal)
14743 break;
14744 if ((NCVal & 0xFFFF0000ULL) == NCVal)
14745 break;
14746 if ((NCVal & 0xFFFF00000000ULL) == NCVal)
14747 break;
14748 if ((NCVal & 0xFFFF000000000000ULL) == NCVal)
14749 break;
14750 return;
14751 }
14752 default:
14753 return;
14754 }
14755
14756 // All assembler immediates are 64-bit integers.
14757 Result = DAG.getTargetConstant(CVal, SDLoc(Op), MVT::i64);
14758 break;
14759 }
14760
14761 if (Result.getNode()) {
14762 Ops.push_back(Result);
14763 return;
14764 }
14765
14766 return TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
14767}
14768
14769//===----------------------------------------------------------------------===//
14770// AArch64 Advanced SIMD Support
14771//===----------------------------------------------------------------------===//
14772
14773/// WidenVector - Given a value in the V64 register class, produce the
14774/// equivalent value in the V128 register class.
14776 EVT VT = V64Reg.getValueType();
14777 unsigned NarrowSize = VT.getVectorNumElements();
14778 MVT EltTy = VT.getVectorElementType().getSimpleVT();
14779 MVT WideTy = MVT::getVectorVT(EltTy, 2 * NarrowSize);
14780 SDLoc DL(V64Reg);
14781
14782 return DAG.getInsertSubvector(DL, DAG.getPOISON(WideTy), V64Reg, 0);
14783}
14784
14785/// getExtFactor - Determine the adjustment factor for the position when
14786/// generating an "extract from vector registers" instruction.
14787static unsigned getExtFactor(SDValue &V) {
14788 EVT EltType = V.getValueType().getVectorElementType();
14789 return EltType.getSizeInBits() / 8;
14790}
14791
14792// Check if a vector is built from one vector via extracted elements of
14793// another together with an AND mask, ensuring that all elements fit
14794// within range. This can be reconstructed using AND and NEON's TBL1.
14796 assert(Op.getOpcode() == ISD::BUILD_VECTOR && "Unknown opcode!");
14797 SDLoc DL(Op);
14798 EVT VT = Op.getValueType();
14799 assert(!VT.isScalableVector() &&
14800 "Scalable vectors cannot be used with ISD::BUILD_VECTOR");
14801
14802 // Can only recreate a shuffle with 16xi8 or 8xi8 elements, as they map
14803 // directly to TBL1.
14804 if (VT != MVT::v16i8 && VT != MVT::v8i8)
14805 return SDValue();
14806
14807 unsigned NumElts = VT.getVectorNumElements();
14808 assert((NumElts == 8 || NumElts == 16) &&
14809 "Need to have exactly 8 or 16 elements in vector.");
14810
14811 SDValue SourceVec;
14812 SDValue MaskSourceVec;
14813 SmallVector<SDValue, 16> AndMaskConstants;
14814
14815 for (unsigned i = 0; i < NumElts; ++i) {
14816 SDValue V = Op.getOperand(i);
14817 if (V.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
14818 return SDValue();
14819
14820 SDValue OperandSourceVec = V.getOperand(0);
14821 if (!SourceVec)
14822 SourceVec = OperandSourceVec;
14823 else if (SourceVec != OperandSourceVec)
14824 return SDValue();
14825
14826 // This only looks at shuffles with elements that are
14827 // a) truncated by a constant AND mask extracted from a mask vector, or
14828 // b) extracted directly from a mask vector.
14829 SDValue MaskSource = V.getOperand(1);
14830 if (MaskSource.getOpcode() == ISD::AND) {
14831 if (!isa<ConstantSDNode>(MaskSource.getOperand(1)))
14832 return SDValue();
14833
14834 AndMaskConstants.push_back(MaskSource.getOperand(1));
14835 MaskSource = MaskSource->getOperand(0);
14836 } else if (!AndMaskConstants.empty()) {
14837 // Either all or no operands should have an AND mask.
14838 return SDValue();
14839 }
14840
14841 // An ANY_EXTEND may be inserted between the AND and the source vector
14842 // extraction. We don't care about that, so we can just skip it.
14843 if (MaskSource.getOpcode() == ISD::ANY_EXTEND)
14844 MaskSource = MaskSource.getOperand(0);
14845
14846 if (MaskSource.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
14847 return SDValue();
14848
14849 SDValue MaskIdx = MaskSource.getOperand(1);
14850 if (!isa<ConstantSDNode>(MaskIdx) ||
14851 !cast<ConstantSDNode>(MaskIdx)->getConstantIntValue()->equalsInt(i))
14852 return SDValue();
14853
14854 // We only apply this if all elements come from the same vector with the
14855 // same vector type.
14856 if (!MaskSourceVec) {
14857 MaskSourceVec = MaskSource->getOperand(0);
14858 if (MaskSourceVec.getValueType() != VT)
14859 return SDValue();
14860 } else if (MaskSourceVec != MaskSource->getOperand(0)) {
14861 return SDValue();
14862 }
14863 }
14864
14865 // We need a v16i8 for TBL, so we extend the source with a placeholder vector
14866 // for v8i8 to get a v16i8. As the pattern we are replacing is extract +
14867 // insert, we know that the index in the mask must be smaller than the number
14868 // of elements in the source, or we would have an out-of-bounds access.
14869 if (NumElts == 8)
14870 SourceVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v16i8, SourceVec,
14871 DAG.getPOISON(VT));
14872
14873 // Preconditions met, so we can use a vector (AND +) TBL to build this vector.
14874 if (!AndMaskConstants.empty())
14875 MaskSourceVec = DAG.getNode(ISD::AND, DL, VT, MaskSourceVec,
14876 DAG.getBuildVector(VT, DL, AndMaskConstants));
14877
14878 return DAG.getNode(
14880 DAG.getTargetConstant(Intrinsic::aarch64_neon_tbl1, DL, MVT::i32),
14881 SourceVec, MaskSourceVec);
14882}
14883
14884// Gather data to see if the operation can be modelled as a
14885// shuffle in combination with VEXTs.
14887 SelectionDAG &DAG) const {
14888 assert(Op.getOpcode() == ISD::BUILD_VECTOR && "Unknown opcode!");
14889 LLVM_DEBUG(dbgs() << "AArch64TargetLowering::ReconstructShuffle\n");
14890 SDLoc DL(Op);
14891 EVT VT = Op.getValueType();
14892 assert(!VT.isScalableVector() &&
14893 "Scalable vectors cannot be used with ISD::BUILD_VECTOR");
14894 unsigned NumElts = VT.getVectorNumElements();
14895
14896 struct ShuffleSourceInfo {
14897 SDValue Vec;
14898 unsigned MinElt;
14899 unsigned MaxElt;
14900
14901 // We may insert some combination of BITCASTs and VEXT nodes to force Vec to
14902 // be compatible with the shuffle we intend to construct. As a result
14903 // ShuffleVec will be some sliding window into the original Vec.
14904 SDValue ShuffleVec;
14905
14906 // Code should guarantee that element i in Vec starts at element "WindowBase
14907 // + i * WindowScale in ShuffleVec".
14908 int WindowBase;
14909 int WindowScale;
14910
14911 ShuffleSourceInfo(SDValue Vec)
14912 : Vec(Vec), MinElt(std::numeric_limits<unsigned>::max()), MaxElt(0),
14913 ShuffleVec(Vec), WindowBase(0), WindowScale(1) {}
14914
14915 bool operator ==(SDValue OtherVec) { return Vec == OtherVec; }
14916 };
14917
14918 auto IsNeonSized = [](EVT VT) {
14919 return VT.is128BitVector() || VT.is64BitVector();
14920 };
14921
14922 // First gather all vectors used as an immediate source for this BUILD_VECTOR
14923 // node.
14925 for (unsigned i = 0; i < NumElts; ++i) {
14926 SDValue V = Op.getOperand(i);
14927 if (V.isUndef())
14928 continue;
14929 else if (V.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
14930 !isa<ConstantSDNode>(V.getOperand(1)) ||
14931 !IsNeonSized(V->getOperand(0).getValueType())) {
14932 LLVM_DEBUG(
14933 dbgs() << "Reshuffle failed: "
14934 "a shuffle can only come from building a vector from "
14935 "various elements of other NEON-sized vectors, provided "
14936 "their indices are constant\n");
14937 return SDValue();
14938 }
14939
14940 // Add this element source to the list if it's not already there.
14941 SDValue SourceVec = V.getOperand(0);
14942 auto Source = find(Sources, SourceVec);
14943 if (Source == Sources.end())
14944 Source = Sources.insert(Sources.end(), ShuffleSourceInfo(SourceVec));
14945
14946 // Update the minimum and maximum lane number seen.
14947 unsigned EltNo = V.getConstantOperandVal(1);
14948 Source->MinElt = std::min(Source->MinElt, EltNo);
14949 Source->MaxElt = std::max(Source->MaxElt, EltNo);
14950 }
14951
14952 // If we have 3 or 4 sources, try to generate a TBL, which will at least be
14953 // better than moving to/from gpr registers for larger vectors.
14954 if ((Sources.size() == 3 || Sources.size() == 4) && NumElts > 4) {
14955 // Construct a mask for the tbl. We may need to adjust the index for types
14956 // larger than i8.
14958 unsigned OutputFactor = VT.getScalarSizeInBits() / 8;
14959 for (unsigned I = 0; I < NumElts; ++I) {
14960 SDValue V = Op.getOperand(I);
14961 if (V.isUndef()) {
14962 for (unsigned OF = 0; OF < OutputFactor; OF++)
14963 Mask.push_back(-1);
14964 continue;
14965 }
14966 // Set the Mask lanes adjusted for the size of the input and output
14967 // lanes. The Mask is always i8, so it will set OutputFactor lanes per
14968 // output element, adjusted in their positions per input and output types.
14969 unsigned Lane = V.getConstantOperandVal(1);
14970 for (unsigned S = 0; S < Sources.size(); S++) {
14971 if (V.getOperand(0) == Sources[S].Vec) {
14972 unsigned InputSize = Sources[S].Vec.getScalarValueSizeInBits();
14973 unsigned InputBase = 16 * S + Lane * InputSize / 8;
14974 for (unsigned OF = 0; OF < OutputFactor; OF++)
14975 Mask.push_back(InputBase + OF);
14976 break;
14977 }
14978 }
14979 }
14980
14981 // Construct the tbl3/tbl4 out of an intrinsic, the sources converted to
14982 // v16i8, and the TBLMask
14983 SmallVector<SDValue, 16> TBLOperands;
14984 TBLOperands.push_back(DAG.getConstant(Sources.size() == 3
14985 ? Intrinsic::aarch64_neon_tbl3
14986 : Intrinsic::aarch64_neon_tbl4,
14987 DL, MVT::i32));
14988 for (unsigned i = 0; i < Sources.size(); i++) {
14989 SDValue Src = Sources[i].Vec;
14990 EVT SrcVT = Src.getValueType();
14991 Src = DAG.getBitcast(SrcVT.is64BitVector() ? MVT::v8i8 : MVT::v16i8, Src);
14992 assert((SrcVT.is64BitVector() || SrcVT.is128BitVector()) &&
14993 "Expected a legally typed vector");
14994 if (SrcVT.is64BitVector())
14995 Src = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v16i8, Src,
14996 DAG.getPOISON(MVT::v8i8));
14997 TBLOperands.push_back(Src);
14998 }
14999
15001 for (unsigned i = 0; i < Mask.size(); i++)
15002 TBLMask.push_back(DAG.getConstant(Mask[i], DL, MVT::i32));
15003 assert((Mask.size() == 8 || Mask.size() == 16) &&
15004 "Expected a v8i8 or v16i8 Mask");
15005 TBLOperands.push_back(DAG.getBuildVector(
15006 Mask.size() == 8 ? MVT::v8i8 : MVT::v16i8, DL, TBLMask));
15007
15008 SDValue Shuffle =
15010 Mask.size() == 8 ? MVT::v8i8 : MVT::v16i8, TBLOperands);
15011 return DAG.getBitcast(VT, Shuffle);
15012 }
15013
15014 if (Sources.size() > 2) {
15015 LLVM_DEBUG(dbgs() << "Reshuffle failed: currently only do something "
15016 << "sensible when at most two source vectors are "
15017 << "involved\n");
15018 return SDValue();
15019 }
15020
15021 // Find out the smallest element size among result and two sources, and use
15022 // it as element size to build the shuffle_vector.
15023 EVT SmallestEltTy = VT.getVectorElementType();
15024 for (auto &Source : Sources) {
15025 EVT SrcEltTy = Source.Vec.getValueType().getVectorElementType();
15026 if (SrcEltTy.bitsLT(SmallestEltTy)) {
15027 SmallestEltTy = SrcEltTy;
15028 }
15029 }
15030 unsigned ResMultiplier =
15031 VT.getScalarSizeInBits() / SmallestEltTy.getFixedSizeInBits();
15032 uint64_t VTSize = VT.getFixedSizeInBits();
15033 NumElts = VTSize / SmallestEltTy.getFixedSizeInBits();
15034 EVT ShuffleVT = EVT::getVectorVT(*DAG.getContext(), SmallestEltTy, NumElts);
15035
15036 // If the source vector is too wide or too narrow, we may nevertheless be able
15037 // to construct a compatible shuffle either by concatenating it with UNDEF or
15038 // extracting a suitable range of elements.
15039 for (auto &Src : Sources) {
15040 EVT SrcVT = Src.ShuffleVec.getValueType();
15041
15042 TypeSize SrcVTSize = SrcVT.getSizeInBits();
15043 if (SrcVTSize == TypeSize::getFixed(VTSize))
15044 continue;
15045
15046 // This stage of the search produces a source with the same element type as
15047 // the original, but with a total width matching the BUILD_VECTOR output.
15048 EVT EltVT = SrcVT.getVectorElementType();
15049 unsigned NumSrcElts = VTSize / EltVT.getFixedSizeInBits();
15050 EVT DestVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NumSrcElts);
15051
15052 if (SrcVTSize.getFixedValue() < VTSize) {
15053 assert(2 * SrcVTSize == VTSize);
15054 // We can pad out the smaller vector for free, so if it's part of a
15055 // shuffle...
15056 Src.ShuffleVec =
15057 DAG.getNode(ISD::CONCAT_VECTORS, DL, DestVT, Src.ShuffleVec,
15058 DAG.getPOISON(Src.ShuffleVec.getValueType()));
15059 continue;
15060 }
15061
15062 if (SrcVTSize.getFixedValue() != 2 * VTSize) {
15063 LLVM_DEBUG(
15064 dbgs() << "Reshuffle failed: result vector too small to extract\n");
15065 return SDValue();
15066 }
15067
15068 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
15069 LLVM_DEBUG(
15070 dbgs() << "Reshuffle failed: span too large for a VEXT to cope\n");
15071 return SDValue();
15072 }
15073
15074 if (Src.MinElt >= NumSrcElts) {
15075 // The extraction can just take the second half
15076 Src.ShuffleVec =
15077 DAG.getExtractSubvector(DL, DestVT, Src.ShuffleVec, NumSrcElts);
15078 Src.WindowBase = -NumSrcElts;
15079 } else if (Src.MaxElt < NumSrcElts) {
15080 // The extraction can just take the first half
15081 Src.ShuffleVec = DAG.getExtractSubvector(DL, DestVT, Src.ShuffleVec, 0);
15082 } else {
15083 // An actual VEXT is needed
15084 SDValue VEXTSrc1 = DAG.getExtractSubvector(DL, DestVT, Src.ShuffleVec, 0);
15085 SDValue VEXTSrc2 =
15086 DAG.getExtractSubvector(DL, DestVT, Src.ShuffleVec, NumSrcElts);
15087 unsigned Imm = Src.MinElt * getExtFactor(VEXTSrc1);
15088
15089 if (!SrcVT.is64BitVector()) {
15090 LLVM_DEBUG(
15091 dbgs() << "Reshuffle failed: don't know how to lower AArch64ISD::EXT "
15092 "for SVE vectors.");
15093 return SDValue();
15094 }
15095
15096 Src.ShuffleVec =
15097 DAG.getNode(AArch64ISD::EXT, DL, DestVT, VEXTSrc1, VEXTSrc2,
15098 DAG.getConstant(Imm, DL, MVT::i32));
15099 Src.WindowBase = -Src.MinElt;
15100 }
15101 }
15102
15103 // Another possible incompatibility occurs from the vector element types. We
15104 // can fix this by bitcasting the source vectors to the same type we intend
15105 // for the shuffle.
15106 for (auto &Src : Sources) {
15107 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
15108 if (SrcEltTy == SmallestEltTy)
15109 continue;
15110 assert(ShuffleVT.getVectorElementType() == SmallestEltTy);
15111 if (DAG.getDataLayout().isBigEndian()) {
15112 Src.ShuffleVec =
15113 DAG.getNode(AArch64ISD::NVCAST, DL, ShuffleVT, Src.ShuffleVec);
15114 } else {
15115 Src.ShuffleVec = DAG.getNode(ISD::BITCAST, DL, ShuffleVT, Src.ShuffleVec);
15116 }
15117 Src.WindowScale =
15118 SrcEltTy.getFixedSizeInBits() / SmallestEltTy.getFixedSizeInBits();
15119 Src.WindowBase *= Src.WindowScale;
15120 }
15121
15122 // Final check before we try to actually produce a shuffle.
15123 LLVM_DEBUG({
15124 for (auto Src : Sources)
15125 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
15126 });
15127
15128 // The stars all align, our next step is to produce the mask for the shuffle.
15129 SmallVector<int, 8> Mask(ShuffleVT.getVectorNumElements(), -1);
15130 int BitsPerShuffleLane = ShuffleVT.getScalarSizeInBits();
15131 for (unsigned i = 0; i < VT.getVectorNumElements(); ++i) {
15132 SDValue Entry = Op.getOperand(i);
15133 if (Entry.isUndef())
15134 continue;
15135
15136 auto Src = find(Sources, Entry.getOperand(0));
15137 int EltNo = cast<ConstantSDNode>(Entry.getOperand(1))->getSExtValue();
15138
15139 // EXTRACT_VECTOR_ELT performs an implicit any_ext; BUILD_VECTOR an implicit
15140 // trunc. So only std::min(SrcBits, DestBits) actually get defined in this
15141 // segment.
15142 EVT OrigEltTy = Entry.getOperand(0).getValueType().getVectorElementType();
15143 int BitsDefined = std::min(OrigEltTy.getScalarSizeInBits(),
15144 VT.getScalarSizeInBits());
15145 int LanesDefined = BitsDefined / BitsPerShuffleLane;
15146
15147 // This source is expected to fill ResMultiplier lanes of the final shuffle,
15148 // starting at the appropriate offset.
15149 int *LaneMask = &Mask[i * ResMultiplier];
15150
15151 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
15152 ExtractBase += NumElts * (Src - Sources.begin());
15153 for (int j = 0; j < LanesDefined; ++j)
15154 LaneMask[j] = ExtractBase + j;
15155 }
15156
15157 // Final check before we try to produce nonsense...
15158 if (!isShuffleMaskLegal(Mask, ShuffleVT)) {
15159 LLVM_DEBUG(dbgs() << "Reshuffle failed: illegal shuffle mask\n");
15160 return SDValue();
15161 }
15162
15163 SDValue Poison = DAG.getPOISON(ShuffleVT);
15165 for (unsigned i = 0; i < Sources.size(); ++i)
15166 ShuffleOps[i] = Sources[i].ShuffleVec;
15167
15168 SDValue Shuffle =
15169 DAG.getVectorShuffle(ShuffleVT, DL, ShuffleOps[0], ShuffleOps[1], Mask);
15170 SDValue V;
15171 if (DAG.getDataLayout().isBigEndian()) {
15172 V = DAG.getNode(AArch64ISD::NVCAST, DL, VT, Shuffle);
15173 } else {
15174 V = DAG.getNode(ISD::BITCAST, DL, VT, Shuffle);
15175 }
15176
15177 LLVM_DEBUG(dbgs() << "Reshuffle, creating node: "; Shuffle.dump();
15178 dbgs() << "Reshuffle, creating node: "; V.dump(););
15179
15180 return V;
15181}
15182
15183// check if an EXT instruction can handle the shuffle mask when the
15184// vector sources of the shuffle are the same.
15185static bool isSingletonEXTMask(ArrayRef<int> M, EVT VT, unsigned &Imm) {
15186 unsigned NumElts = VT.getVectorNumElements();
15187
15188 // Assume that the first shuffle index is not UNDEF. Fail if it is.
15189 if (M[0] < 0)
15190 return false;
15191
15192 Imm = M[0];
15193
15194 // If this is a VEXT shuffle, the immediate value is the index of the first
15195 // element. The other shuffle indices must be the successive elements after
15196 // the first one.
15197 unsigned ExpectedElt = Imm;
15198 for (unsigned i = 1; i < NumElts; ++i) {
15199 // Increment the expected index. If it wraps around, just follow it
15200 // back to index zero and keep going.
15201 ++ExpectedElt;
15202 if (ExpectedElt == NumElts)
15203 ExpectedElt = 0;
15204
15205 if (M[i] < 0)
15206 continue; // ignore UNDEF indices
15207 if (ExpectedElt != static_cast<unsigned>(M[i]))
15208 return false;
15209 }
15210
15211 return true;
15212}
15213
15214// Detect patterns of a0,a1,a2,a3,b0,b1,b2,b3,c0,c1,c2,c3,d0,d1,d2,d3 from
15215// v4i32s. This is really a truncate, which we can construct out of (legal)
15216// concats and truncate nodes.
15218 if (V.getValueType() != MVT::v16i8)
15219 return SDValue();
15220 assert(V.getNumOperands() == 16 && "Expected 16 operands on the BUILDVECTOR");
15221
15222 for (unsigned X = 0; X < 4; X++) {
15223 // Check the first item in each group is an extract from lane 0 of a v4i32
15224 // or v4i16.
15225 SDValue BaseExt = V.getOperand(X * 4);
15226 if (BaseExt.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
15227 (BaseExt.getOperand(0).getValueType() != MVT::v4i16 &&
15228 BaseExt.getOperand(0).getValueType() != MVT::v4i32) ||
15229 !isa<ConstantSDNode>(BaseExt.getOperand(1)) ||
15230 BaseExt.getConstantOperandVal(1) != 0)
15231 return SDValue();
15232 SDValue Base = BaseExt.getOperand(0);
15233 // And check the other items are extracts from the same vector.
15234 for (unsigned Y = 1; Y < 4; Y++) {
15235 SDValue Ext = V.getOperand(X * 4 + Y);
15236 if (Ext.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
15237 Ext.getOperand(0) != Base ||
15239 Ext.getConstantOperandVal(1) != Y)
15240 return SDValue();
15241 }
15242 }
15243
15244 // Turn the buildvector into a series of truncates and concates, which will
15245 // become uzip1's. Any v4i32s we found get truncated to v4i16, which are
15246 // concat together to produce 2 v8i16. These are both truncated and concat
15247 // together.
15248 SDLoc DL(V);
15249 SDValue Trunc[4] = {
15250 V.getOperand(0).getOperand(0), V.getOperand(4).getOperand(0),
15251 V.getOperand(8).getOperand(0), V.getOperand(12).getOperand(0)};
15252 for (SDValue &V : Trunc)
15253 if (V.getValueType() == MVT::v4i32)
15254 V = DAG.getNode(ISD::TRUNCATE, DL, MVT::v4i16, V);
15255 SDValue Concat0 =
15256 DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v8i16, Trunc[0], Trunc[1]);
15257 SDValue Concat1 =
15258 DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v8i16, Trunc[2], Trunc[3]);
15259 SDValue Trunc0 = DAG.getNode(ISD::TRUNCATE, DL, MVT::v8i8, Concat0);
15260 SDValue Trunc1 = DAG.getNode(ISD::TRUNCATE, DL, MVT::v8i8, Concat1);
15261 return DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v16i8, Trunc0, Trunc1);
15262}
15263
15264/// Check if a vector shuffle corresponds to a DUP instructions with a larger
15265/// element width than the vector lane type. If that is the case the function
15266/// returns true and writes the value of the DUP instruction lane operand into
15267/// DupLaneOp
15268static bool isWideDUPMask(ArrayRef<int> M, EVT VT, unsigned BlockSize,
15269 unsigned &DupLaneOp) {
15270 assert((BlockSize == 16 || BlockSize == 32 || BlockSize == 64) &&
15271 "Only possible block sizes for wide DUP are: 16, 32, 64");
15272
15273 if (BlockSize <= VT.getScalarSizeInBits())
15274 return false;
15275 if (BlockSize % VT.getScalarSizeInBits() != 0)
15276 return false;
15277 if (VT.getSizeInBits() % BlockSize != 0)
15278 return false;
15279
15280 size_t SingleVecNumElements = VT.getVectorNumElements();
15281 size_t NumEltsPerBlock = BlockSize / VT.getScalarSizeInBits();
15282 size_t NumBlocks = VT.getSizeInBits() / BlockSize;
15283
15284 // We are looking for masks like
15285 // [0, 1, 0, 1] or [2, 3, 2, 3] or [4, 5, 6, 7, 4, 5, 6, 7] where any element
15286 // might be replaced by 'undefined'. BlockIndices will eventually contain
15287 // lane indices of the duplicated block (i.e. [0, 1], [2, 3] and [4, 5, 6, 7]
15288 // for the above examples)
15289 SmallVector<int, 8> BlockElts(NumEltsPerBlock, -1);
15290 for (size_t BlockIndex = 0; BlockIndex < NumBlocks; BlockIndex++)
15291 for (size_t I = 0; I < NumEltsPerBlock; I++) {
15292 int Elt = M[BlockIndex * NumEltsPerBlock + I];
15293 if (Elt < 0)
15294 continue;
15295 // For now we don't support shuffles that use the second operand
15296 if ((unsigned)Elt >= SingleVecNumElements)
15297 return false;
15298 if (BlockElts[I] < 0)
15299 BlockElts[I] = Elt;
15300 else if (BlockElts[I] != Elt)
15301 return false;
15302 }
15303
15304 // We found a candidate block (possibly with some undefs). It must be a
15305 // sequence of consecutive integers starting with a value divisible by
15306 // NumEltsPerBlock with some values possibly replaced by undef-s.
15307
15308 // Find first non-undef element
15309 auto FirstRealEltIter = find_if(BlockElts, [](int Elt) { return Elt >= 0; });
15310 assert(FirstRealEltIter != BlockElts.end() &&
15311 "Shuffle with all-undefs must have been caught by previous cases, "
15312 "e.g. isSplat()");
15313 if (FirstRealEltIter == BlockElts.end()) {
15314 DupLaneOp = 0;
15315 return true;
15316 }
15317
15318 // Index of FirstRealElt in BlockElts
15319 size_t FirstRealIndex = FirstRealEltIter - BlockElts.begin();
15320
15321 if ((unsigned)*FirstRealEltIter < FirstRealIndex)
15322 return false;
15323 // BlockElts[0] must have the following value if it isn't undef:
15324 size_t Elt0 = *FirstRealEltIter - FirstRealIndex;
15325
15326 // Check the first element
15327 if (Elt0 % NumEltsPerBlock != 0)
15328 return false;
15329 // Check that the sequence indeed consists of consecutive integers (modulo
15330 // undefs)
15331 for (size_t I = 0; I < NumEltsPerBlock; I++)
15332 if (BlockElts[I] >= 0 && (unsigned)BlockElts[I] != Elt0 + I)
15333 return false;
15334
15335 DupLaneOp = Elt0 / NumEltsPerBlock;
15336 return true;
15337}
15338
15339// check if an EXT instruction can handle the shuffle mask when the
15340// vector sources of the shuffle are different.
15341static bool isEXTMask(ArrayRef<int> M, EVT VT, bool &ReverseEXT,
15342 unsigned &Imm) {
15343 // Look for the first non-undef element.
15344 const int *FirstRealElt = find_if(M, [](int Elt) { return Elt >= 0; });
15345
15346 // Benefit from APInt to handle overflow when calculating expected element.
15347 unsigned NumElts = VT.getVectorNumElements();
15348 unsigned MaskBits = APInt(32, NumElts * 2).logBase2();
15349 APInt ExpectedElt = APInt(MaskBits, *FirstRealElt + 1, /*isSigned=*/false,
15350 /*implicitTrunc=*/true);
15351 // The following shuffle indices must be the successive elements after the
15352 // first real element.
15353 bool FoundWrongElt = std::any_of(FirstRealElt + 1, M.end(), [&](int Elt) {
15354 return Elt != ExpectedElt++ && Elt >= 0;
15355 });
15356 if (FoundWrongElt)
15357 return false;
15358
15359 // The index of an EXT is the first element if it is not UNDEF.
15360 // Watch out for the beginning UNDEFs. The EXT index should be the expected
15361 // value of the first element. E.g.
15362 // <-1, -1, 3, ...> is treated as <1, 2, 3, ...>.
15363 // <-1, -1, 0, 1, ...> is treated as <2*NumElts-2, 2*NumElts-1, 0, 1, ...>.
15364 // ExpectedElt is the last mask index plus 1.
15365 Imm = ExpectedElt.getZExtValue();
15366
15367 // There are two difference cases requiring to reverse input vectors.
15368 // For example, for vector <4 x i32> we have the following cases,
15369 // Case 1: shufflevector(<4 x i32>,<4 x i32>,<-1, -1, -1, 0>)
15370 // Case 2: shufflevector(<4 x i32>,<4 x i32>,<-1, -1, 7, 0>)
15371 // For both cases, we finally use mask <5, 6, 7, 0>, which requires
15372 // to reverse two input vectors.
15373 if (Imm < NumElts)
15374 ReverseEXT = true;
15375 else
15376 Imm -= NumElts;
15377
15378 return true;
15379}
15380
15381/// Flag slide shuffle patterns where one operand is zeros.
15382/// Left slide: shufflevector %v, zeros, <1,2,3,...> -> ushr
15383/// Right slide: shufflevector zeros, %v, <N-1,N,N+1,...> -> shl
15384/// Check if a single 64-bit lane has a valid slide pattern.
15385/// LaneStart: first element index of this lane in the full vector
15386/// LaneElts: number of elements in the lane
15387/// Returns slide amount in elements, or 0 if not a valid slide.
15388static unsigned checkLaneSlide(ArrayRef<int> Mask, unsigned LaneStart,
15389 unsigned LaneElts, unsigned NumElts,
15390 bool &IsLeftSlide) {
15391 // Check for left slide: <k, k+1, ..., LaneElts-1, zero, ...>
15392 // where k > 0 and elements stay within lane
15393 int FirstIdx = Mask[LaneStart];
15394 if (FirstIdx > (int)LaneStart && FirstIdx < (int)(LaneStart + LaneElts)) {
15395 unsigned SlideAmt = FirstIdx - LaneStart;
15396 for (unsigned i = 0; i < LaneElts; ++i) {
15397 int MaskIdx = Mask[LaneStart + i];
15398 if (MaskIdx < 0)
15399 continue;
15400 if (i < LaneElts - SlideAmt) {
15401 // Data element: must be consecutive within lane
15402 if (MaskIdx != (int)(LaneStart + SlideAmt + i))
15403 return 0;
15404 } else {
15405 // Zero element: any index >= NumElts is fine (all from V2 which is
15406 // zeros)
15407 if (MaskIdx < (int)NumElts)
15408 return 0;
15409 }
15410 }
15411 IsLeftSlide = true;
15412 return SlideAmt;
15413 }
15414
15415 // Check for right slide: <zero, ..., 0, 1, ...>
15416 // where zeros come first, then consecutive from lane start
15417 if (Mask[LaneStart] >= (int)NumElts || Mask[LaneStart] < 0) {
15418 unsigned ZeroCount = 0;
15419 for (unsigned i = 0; i < LaneElts; ++i) {
15420 int MaskIdx = Mask[LaneStart + i];
15421 if (MaskIdx >= 0 && MaskIdx < (int)NumElts)
15422 break;
15423 ZeroCount++;
15424 }
15425 if (ZeroCount > 0 && ZeroCount < LaneElts) {
15426 for (unsigned i = ZeroCount; i < LaneElts; ++i) {
15427 int MaskIdx = Mask[LaneStart + i];
15428 if (MaskIdx < 0)
15429 continue;
15430 if (MaskIdx != (int)(LaneStart + i - ZeroCount))
15431 return 0;
15432 }
15433 IsLeftSlide = false;
15434 return ZeroCount;
15435 }
15436 }
15437
15438 return 0;
15439}
15440
15442 SDValue V2, unsigned &ShiftAmount,
15443 bool &IsRightShift,
15444 unsigned &MatchedLaneSize) {
15445 unsigned VTSize = VT.getSizeInBits();
15446 if (VTSize != 64 && VTSize != 128)
15447 return SDValue();
15448
15449 unsigned NumElts = VT.getVectorNumElements();
15450 unsigned EltSize = VT.getScalarSizeInBits();
15451
15452 bool V1IsZeros = ISD::isBuildVectorAllZeros(V1.getNode());
15453 bool V2IsZeros = ISD::isBuildVectorAllZeros(V2.getNode());
15454
15455 // Exactly one operand must be zeros
15456 if (V1IsZeros == V2IsZeros)
15457 return SDValue();
15458
15459 // Canonicalize so V2 is zeros
15460 SmallVector<int, 16> Mask(M.begin(), M.end());
15461 SDValue DataVec = V1;
15462 if (V1IsZeros) {
15464 DataVec = V2;
15465 }
15466
15467 // Try lane sizes 64, 32, 16 bits.
15468 // For each lane size, check all lanes have the same slide pattern.
15469 for (unsigned LaneSize : {64u, 32u, 16u}) {
15470 if (LaneSize < EltSize * 2)
15471 break; // need at least 2 elements per lane
15472 unsigned LaneElts = LaneSize / EltSize;
15473 unsigned NumLanes = VTSize / LaneSize;
15474
15475 bool FirstIsLeftSlide;
15476 unsigned FirstSlideAmt =
15477 checkLaneSlide(Mask, 0, LaneElts, NumElts, FirstIsLeftSlide);
15478 if (FirstSlideAmt == 0)
15479 continue;
15480
15481 // Verify all lanes match
15482 bool AllMatch = true;
15483 for (unsigned Lane = 1; Lane < NumLanes; Lane++) {
15484 bool IsLeftSlide;
15485 unsigned SlideAmt =
15486 checkLaneSlide(Mask, Lane * LaneElts, LaneElts, NumElts, IsLeftSlide);
15487 if (SlideAmt != FirstSlideAmt || IsLeftSlide != FirstIsLeftSlide) {
15488 AllMatch = false;
15489 break;
15490 }
15491 }
15492 if (!AllMatch)
15493 continue;
15494
15495 ShiftAmount = FirstSlideAmt * EltSize;
15496 IsRightShift = FirstIsLeftSlide;
15497 if (ShiftAmount > 0 && ShiftAmount < LaneSize) {
15498 MatchedLaneSize = LaneSize;
15499 return DataVec;
15500 }
15501 }
15502 return SDValue();
15503}
15504
15505// Check if an EXT instruction can handle the shuffle mask when one source is a
15506// splat. This matches shuffles where the splat occupies either a prefix or a
15507// suffix and the remaining lanes are a contiguous slice from the non-splat
15508// source.
15509static bool isEXTMaskWithSplat(ArrayRef<int> M, EVT VT, unsigned SplatOperand,
15510 bool &ReverseEXT, unsigned &Imm) {
15511 unsigned NumElts = VT.getVectorNumElements();
15512 unsigned OtherBase = SplatOperand == 0 ? NumElts : 0;
15513 auto IsSplatElt = [=](int Elt) {
15514 return Elt < 0 ||
15515 (SplatOperand == 0 ? Elt < (int)NumElts : Elt >= (int)NumElts);
15516 };
15517
15518 unsigned PrefixSplatElts = 0;
15519 while (PrefixSplatElts != NumElts && IsSplatElt(M[PrefixSplatElts]))
15520 ++PrefixSplatElts;
15521
15522 if (PrefixSplatElts > 0 && PrefixSplatElts < NumElts) {
15523 bool Match = true;
15524 for (unsigned I = PrefixSplatElts; I != NumElts; ++I) {
15525 int Expected = OtherBase + I - PrefixSplatElts;
15526 if (M[I] >= 0 && M[I] != Expected) {
15527 Match = false;
15528 break;
15529 }
15530 }
15531
15532 if (Match) {
15533 ReverseEXT = SplatOperand == 1;
15534 Imm = NumElts - PrefixSplatElts;
15535 return true;
15536 }
15537 }
15538
15539 unsigned SuffixSplatElts = 0;
15540 while (SuffixSplatElts != NumElts &&
15541 IsSplatElt(M[NumElts - 1 - SuffixSplatElts]))
15542 ++SuffixSplatElts;
15543
15544 if (0 < SuffixSplatElts && SuffixSplatElts < NumElts) {
15545 bool Match = true;
15546 for (unsigned I = 0; I != NumElts - SuffixSplatElts; ++I) {
15547 int Expected = OtherBase + I + SuffixSplatElts;
15548 if (M[I] >= 0 && M[I] != Expected) {
15549 Match = false;
15550 break;
15551 }
15552 }
15553
15554 if (Match) {
15555 ReverseEXT = SplatOperand == 0;
15556 Imm = SuffixSplatElts;
15557 return true;
15558 }
15559 }
15560
15561 return false;
15562}
15563
15564static bool isINSMask(ArrayRef<int> M, int NumInputElements,
15565 bool &DstIsLeft, int &Anomaly) {
15566 if (M.size() != static_cast<size_t>(NumInputElements))
15567 return false;
15568
15569 int NumLHSMatch = 0, NumRHSMatch = 0;
15570 int LastLHSMismatch = -1, LastRHSMismatch = -1;
15571
15572 for (int i = 0; i < NumInputElements; ++i) {
15573 if (M[i] == -1) {
15574 ++NumLHSMatch;
15575 ++NumRHSMatch;
15576 continue;
15577 }
15578
15579 if (M[i] == i)
15580 ++NumLHSMatch;
15581 else
15582 LastLHSMismatch = i;
15583
15584 if (M[i] == i + NumInputElements)
15585 ++NumRHSMatch;
15586 else
15587 LastRHSMismatch = i;
15588 }
15589
15590 if (NumLHSMatch == NumInputElements - 1) {
15591 DstIsLeft = true;
15592 Anomaly = LastLHSMismatch;
15593 return true;
15594 } else if (NumRHSMatch == NumInputElements - 1) {
15595 DstIsLeft = false;
15596 Anomaly = LastRHSMismatch;
15597 return true;
15598 }
15599
15600 return false;
15601}
15602
15603static bool isConcatMask(ArrayRef<int> Mask, EVT VT, bool SplitLHS) {
15604 if (VT.getSizeInBits() != 128)
15605 return false;
15606
15607 unsigned NumElts = VT.getVectorNumElements();
15608
15609 for (int I = 0, E = NumElts / 2; I != E; I++) {
15610 if (Mask[I] != I)
15611 return false;
15612 }
15613
15614 int Offset = NumElts / 2;
15615 for (int I = NumElts / 2, E = NumElts; I != E; I++) {
15616 if (Mask[I] != I + SplitLHS * Offset)
15617 return false;
15618 }
15619
15620 return true;
15621}
15622
15624 SDLoc DL(Op);
15625 EVT VT = Op.getValueType();
15626 SDValue V0 = Op.getOperand(0);
15627 SDValue V1 = Op.getOperand(1);
15628 ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(Op)->getMask();
15629
15630 if (VT.getVectorElementType() != V0.getValueType().getVectorElementType() ||
15631 VT.getVectorElementType() != V1.getValueType().getVectorElementType())
15632 return SDValue();
15633
15634 bool SplitV0 = V0.getValueSizeInBits() == 128;
15635
15636 if (!isConcatMask(Mask, VT, SplitV0))
15637 return SDValue();
15638
15639 EVT CastVT = VT.getHalfNumVectorElementsVT(*DAG.getContext());
15640 if (SplitV0) {
15641 V0 = DAG.getExtractSubvector(DL, CastVT, V0, 0);
15642 }
15643 if (V1.getValueSizeInBits() == 128) {
15644 V1 = DAG.getExtractSubvector(DL, CastVT, V1, 0);
15645 }
15646 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, V0, V1);
15647}
15648
15649/// GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit
15650/// the specified operations to build the shuffle. ID is the perfect-shuffle
15651//ID, V1 and V2 are the original shuffle inputs. PFEntry is the Perfect shuffle
15652//table entry and LHS/RHS are the immediate inputs for this stage of the
15653//shuffle.
15655 unsigned PFEntry, SDValue LHS,
15656 SDValue RHS, SelectionDAG &DAG,
15657 const SDLoc &DL) {
15658 unsigned OpNum = (PFEntry >> 26) & 0x0F;
15659 unsigned LHSID = (PFEntry >> 13) & ((1 << 13) - 1);
15660 unsigned RHSID = (PFEntry >> 0) & ((1 << 13) - 1);
15661
15662 enum {
15663 OP_COPY = 0, // Copy, used for things like <u,u,u,3> to say it is <0,1,2,3>
15664 OP_VREV,
15665 OP_VDUP0,
15666 OP_VDUP1,
15667 OP_VDUP2,
15668 OP_VDUP3,
15669 OP_VEXT1,
15670 OP_VEXT2,
15671 OP_VEXT3,
15672 OP_VUZPL, // VUZP, left result
15673 OP_VUZPR, // VUZP, right result
15674 OP_VZIPL, // VZIP, left result
15675 OP_VZIPR, // VZIP, right result
15676 OP_VTRNL, // VTRN, left result
15677 OP_VTRNR, // VTRN, right result
15678 OP_MOVLANE // Move lane. RHSID is the lane to move into
15679 };
15680
15681 if (OpNum == OP_COPY) {
15682 if (LHSID == (1 * 9 + 2) * 9 + 3)
15683 return LHS;
15684 assert(LHSID == ((4 * 9 + 5) * 9 + 6) * 9 + 7 && "Illegal OP_COPY!");
15685 return RHS;
15686 }
15687
15688 if (OpNum == OP_MOVLANE) {
15689 // Decompose a PerfectShuffle ID to get the Mask for lane Elt
15690 auto getPFIDLane = [](unsigned ID, int Elt) -> int {
15691 assert(Elt < 4 && "Expected Perfect Lanes to be less than 4");
15692 Elt = 3 - Elt;
15693 while (Elt > 0) {
15694 ID /= 9;
15695 Elt--;
15696 }
15697 return (ID % 9 == 8) ? -1 : ID % 9;
15698 };
15699
15700 // For OP_MOVLANE shuffles, the RHSID represents the lane to move into. We
15701 // get the lane to move from the PFID, which is always from the
15702 // original vectors (V1 or V2).
15704 LHSID, V1, V2, PerfectShuffleTable[LHSID], LHS, RHS, DAG, DL);
15705 EVT VT = OpLHS.getValueType();
15706 assert(RHSID < 8 && "Expected a lane index for RHSID!");
15707 unsigned ExtLane = 0;
15708 SDValue Input;
15709
15710 // OP_MOVLANE are either D movs (if bit 0x4 is set) or S movs. D movs
15711 // convert into a higher type.
15712 if (RHSID & 0x4) {
15713 int MaskElt = getPFIDLane(ID, (RHSID & 0x01) << 1) >> 1;
15714 if (MaskElt == -1)
15715 MaskElt = (getPFIDLane(ID, ((RHSID & 0x01) << 1) + 1) - 1) >> 1;
15716 assert(MaskElt >= 0 && "Didn't expect an undef movlane index!");
15717 ExtLane = MaskElt < 2 ? MaskElt : (MaskElt - 2);
15718 Input = MaskElt < 2 ? V1 : V2;
15719 if (VT.getScalarSizeInBits() == 16) {
15720 Input = DAG.getBitcast(MVT::v2f32, Input);
15721 OpLHS = DAG.getBitcast(MVT::v2f32, OpLHS);
15722 } else {
15723 assert(VT.getScalarSizeInBits() == 32 &&
15724 "Expected 16 or 32 bit shuffle elements");
15725 Input = DAG.getBitcast(MVT::v2f64, Input);
15726 OpLHS = DAG.getBitcast(MVT::v2f64, OpLHS);
15727 }
15728 } else {
15729 int MaskElt = getPFIDLane(ID, RHSID);
15730 assert(MaskElt >= 0 && "Didn't expect an undef movlane index!");
15731 ExtLane = MaskElt < 4 ? MaskElt : (MaskElt - 4);
15732 Input = MaskElt < 4 ? V1 : V2;
15733 // Be careful about creating illegal types. Use f16 instead of i16.
15734 if (VT == MVT::v4i16) {
15735 Input = DAG.getBitcast(MVT::v4f16, Input);
15736 OpLHS = DAG.getBitcast(MVT::v4f16, OpLHS);
15737 }
15738 }
15740 Input.getValueType().getVectorElementType(),
15741 Input, DAG.getVectorIdxConstant(ExtLane, DL));
15742 SDValue Ins =
15743 DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, Input.getValueType(), OpLHS,
15744 Ext, DAG.getVectorIdxConstant(RHSID & 0x3, DL));
15745 return DAG.getBitcast(VT, Ins);
15746 }
15747
15748 SDValue OpLHS, OpRHS;
15749 OpLHS = GeneratePerfectShuffle(LHSID, V1, V2, PerfectShuffleTable[LHSID], LHS,
15750 RHS, DAG, DL);
15751 OpRHS = GeneratePerfectShuffle(RHSID, V1, V2, PerfectShuffleTable[RHSID], LHS,
15752 RHS, DAG, DL);
15753 EVT VT = OpLHS.getValueType();
15754
15755 switch (OpNum) {
15756 default:
15757 llvm_unreachable("Unknown shuffle opcode!");
15758 case OP_VREV: {
15759 // VREV divides the vector in half and swaps within the half.
15760 if (VT.getVectorElementType() == MVT::i32 ||
15761 VT.getVectorElementType() == MVT::f32)
15762 return DAG.getNode(AArch64ISD::REV64, DL, VT, OpLHS);
15763 // vrev <4 x i16> -> REV32
15764 if (VT.getVectorElementType() == MVT::i16 ||
15765 VT.getVectorElementType() == MVT::f16 ||
15766 VT.getVectorElementType() == MVT::bf16)
15767 return DAG.getNode(AArch64ISD::REV32, DL, VT, OpLHS);
15768 // vrev <4 x i8> -> BSWAP which is REV16
15769 assert(VT == MVT::v8i8 || VT == MVT::v16i8);
15770 EVT BSVT = VT == MVT::v8i8 ? MVT::v4i16 : MVT::v8i16;
15771 return DAG.getNode(
15772 AArch64ISD::NVCAST, DL, VT,
15773 DAG.getNode(ISD::BSWAP, DL, BSVT,
15774 DAG.getNode(AArch64ISD::NVCAST, DL, BSVT, OpLHS)));
15775 }
15776 case OP_VDUP0:
15777 case OP_VDUP1:
15778 case OP_VDUP2:
15779 case OP_VDUP3: {
15780 EVT EltTy = VT.getVectorElementType();
15781 unsigned Opcode;
15782 if (EltTy == MVT::i8)
15783 Opcode = AArch64ISD::DUPLANE8;
15784 else if (EltTy == MVT::i16 || EltTy == MVT::f16 || EltTy == MVT::bf16)
15785 Opcode = AArch64ISD::DUPLANE16;
15786 else if (EltTy == MVT::i32 || EltTy == MVT::f32)
15787 Opcode = AArch64ISD::DUPLANE32;
15788 else if (EltTy == MVT::i64 || EltTy == MVT::f64)
15789 Opcode = AArch64ISD::DUPLANE64;
15790 else
15791 llvm_unreachable("Invalid vector element type?");
15792
15793 if (VT.getSizeInBits() == 64)
15794 OpLHS = WidenVector(OpLHS, DAG);
15795 SDValue Lane = DAG.getConstant(OpNum - OP_VDUP0, DL, MVT::i64);
15796 return DAG.getNode(Opcode, DL, VT, OpLHS, Lane);
15797 }
15798 case OP_VEXT1:
15799 case OP_VEXT2:
15800 case OP_VEXT3: {
15801 unsigned Imm = (OpNum - OP_VEXT1 + 1) * getExtFactor(OpLHS);
15802 return DAG.getNode(AArch64ISD::EXT, DL, VT, OpLHS, OpRHS,
15803 DAG.getConstant(Imm, DL, MVT::i32));
15804 }
15805 case OP_VUZPL:
15806 return DAG.getNode(AArch64ISD::UZP1, DL, VT, OpLHS, OpRHS);
15807 case OP_VUZPR:
15808 return DAG.getNode(AArch64ISD::UZP2, DL, VT, OpLHS, OpRHS);
15809 case OP_VZIPL:
15810 return DAG.getNode(AArch64ISD::ZIP1, DL, VT, OpLHS, OpRHS);
15811 case OP_VZIPR:
15812 return DAG.getNode(AArch64ISD::ZIP2, DL, VT, OpLHS, OpRHS);
15813 case OP_VTRNL:
15814 return DAG.getNode(AArch64ISD::TRN1, DL, VT, OpLHS, OpRHS);
15815 case OP_VTRNR:
15816 return DAG.getNode(AArch64ISD::TRN2, DL, VT, OpLHS, OpRHS);
15817 }
15818}
15819
15821 SelectionDAG &DAG) {
15822 // Check to see if we can use the TBL instruction.
15823 SDValue V1 = Op.getOperand(0);
15824 SDValue V2 = Op.getOperand(1);
15825 SDLoc DL(Op);
15826
15827 EVT EltVT = Op.getValueType().getVectorElementType();
15828 unsigned BytesPerElt = EltVT.getSizeInBits() / 8;
15829
15830 bool Swap = false;
15831 if (V1.isUndef() || isZerosVector(V1.getNode())) {
15832 std::swap(V1, V2);
15833 Swap = true;
15834 }
15835
15836 // If the V2 source is undef or zero then we can use a tbl1, as tbl1 will fill
15837 // out of range values with 0s. We do need to make sure that any out-of-range
15838 // values are really out-of-range for a v16i8 vector.
15839 bool IsUndefOrZero = V2.isUndef() || isZerosVector(V2.getNode());
15840 MVT IndexVT = MVT::v8i8;
15841 unsigned IndexLen = 8;
15842 if (Op.getValueSizeInBits() == 128) {
15843 IndexVT = MVT::v16i8;
15844 IndexLen = 16;
15845 }
15846
15848 for (int Val : ShuffleMask) {
15849 for (unsigned Byte = 0; Byte < BytesPerElt; ++Byte) {
15850 unsigned Offset = Byte + Val * BytesPerElt;
15851 if (Swap)
15852 Offset = Offset < IndexLen ? Offset + IndexLen : Offset - IndexLen;
15853 if (IsUndefOrZero && Offset >= IndexLen)
15854 Offset = 255;
15855 TBLMask.push_back(DAG.getConstant(Offset, DL, MVT::i32));
15856 }
15857 }
15858
15859 SDValue V1Cst = DAG.getNode(ISD::BITCAST, DL, IndexVT, V1);
15860 SDValue V2Cst = DAG.getNode(ISD::BITCAST, DL, IndexVT, V2);
15861
15862 SDValue Shuffle;
15863 if (IsUndefOrZero) {
15864 if (IndexLen == 8)
15865 V1Cst = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v16i8, V1Cst, V1Cst);
15866 Shuffle = DAG.getNode(
15867 ISD::INTRINSIC_WO_CHAIN, DL, IndexVT,
15868 DAG.getTargetConstant(Intrinsic::aarch64_neon_tbl1, DL, MVT::i32),
15869 V1Cst,
15870 DAG.getBuildVector(IndexVT, DL, ArrayRef(TBLMask.data(), IndexLen)));
15871 } else {
15872 if (IndexLen == 8) {
15873 V1Cst = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v16i8, V1Cst, V2Cst);
15874 Shuffle = DAG.getNode(
15875 ISD::INTRINSIC_WO_CHAIN, DL, IndexVT,
15876 DAG.getTargetConstant(Intrinsic::aarch64_neon_tbl1, DL, MVT::i32),
15877 V1Cst,
15878 DAG.getBuildVector(IndexVT, DL, ArrayRef(TBLMask.data(), IndexLen)));
15879 } else {
15880 // FIXME: We cannot, for the moment, emit a TBL2 instruction because we
15881 // cannot currently represent the register constraints on the input
15882 // table registers.
15883 // Shuffle = DAG.getNode(AArch64ISD::TBL2, DL, IndexVT, V1Cst, V2Cst,
15884 // DAG.getBuildVector(IndexVT, DL, &TBLMask[0],
15885 // IndexLen));
15886 Shuffle = DAG.getNode(
15887 ISD::INTRINSIC_WO_CHAIN, DL, IndexVT,
15888 DAG.getTargetConstant(Intrinsic::aarch64_neon_tbl2, DL, MVT::i32),
15889 V1Cst, V2Cst,
15890 DAG.getBuildVector(IndexVT, DL, ArrayRef(TBLMask.data(), IndexLen)));
15891 }
15892 }
15893 return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Shuffle);
15894}
15895
15896static unsigned getDUPLANEOp(EVT EltType) {
15897 if (EltType == MVT::i8)
15898 return AArch64ISD::DUPLANE8;
15899 if (EltType == MVT::i16 || EltType == MVT::f16 || EltType == MVT::bf16)
15900 return AArch64ISD::DUPLANE16;
15901 if (EltType == MVT::i32 || EltType == MVT::f32)
15902 return AArch64ISD::DUPLANE32;
15903 if (EltType == MVT::i64 || EltType == MVT::f64)
15904 return AArch64ISD::DUPLANE64;
15905
15906 llvm_unreachable("Invalid vector element type?");
15907}
15908
15909static SDValue constructDup(SDValue V, int Lane, SDLoc DL, EVT VT,
15910 unsigned Opcode, SelectionDAG &DAG) {
15911 // Try to eliminate a bitcasted extract subvector before a DUPLANE.
15912 auto getScaledOffsetDup = [](SDValue BitCast, int &LaneC, MVT &CastVT) {
15913 // Match: dup (bitcast (extract_subv X, C)), LaneC
15914 if (BitCast.getOpcode() != ISD::BITCAST ||
15916 return false;
15917
15918 // The extract index must align in the destination type. That may not
15919 // happen if the bitcast is from narrow to wide type.
15920 SDValue Extract = BitCast.getOperand(0);
15921 unsigned ExtIdx = Extract.getConstantOperandVal(1);
15922 unsigned SrcEltBitWidth = Extract.getScalarValueSizeInBits();
15923 unsigned ExtIdxInBits = ExtIdx * SrcEltBitWidth;
15924 unsigned CastedEltBitWidth = BitCast.getScalarValueSizeInBits();
15925 if (ExtIdxInBits % CastedEltBitWidth != 0)
15926 return false;
15927
15928 // Can't handle cases where vector size is not 128-bit
15929 if (!Extract.getOperand(0).getValueType().is128BitVector())
15930 return false;
15931
15932 // Update the lane value by offsetting with the scaled extract index.
15933 LaneC += ExtIdxInBits / CastedEltBitWidth;
15934
15935 // Determine the casted vector type of the wide vector input.
15936 // dup (bitcast (extract_subv X, C)), LaneC --> dup (bitcast X), LaneC'
15937 // Examples:
15938 // dup (bitcast (extract_subv v2f64 X, 1) to v2f32), 1 --> dup v4f32 X, 3
15939 // dup (bitcast (extract_subv v16i8 X, 8) to v4i16), 1 --> dup v8i16 X, 5
15940 unsigned SrcVecNumElts =
15941 Extract.getOperand(0).getValueSizeInBits() / CastedEltBitWidth;
15943 SrcVecNumElts);
15944 return true;
15945 };
15946 MVT CastVT;
15947 if (getScaledOffsetDup(V, Lane, CastVT)) {
15948 V = DAG.getBitcast(CastVT, V.getOperand(0).getOperand(0));
15949 } else if (V.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
15950 V.getOperand(0).getValueType().is128BitVector()) {
15951 // The lane is incremented by the index of the extract.
15952 // Example: dup v2f32 (extract v4f32 X, 2), 1 --> dup v4f32 X, 3
15953 Lane += V.getConstantOperandVal(1);
15954 V = V.getOperand(0);
15955 } else if (V.getOpcode() == ISD::CONCAT_VECTORS) {
15956 // The lane is decremented if we are splatting from the 2nd operand.
15957 // Example: dup v4i32 (concat v2i32 X, v2i32 Y), 3 --> dup v4i32 Y, 1
15958 unsigned Idx = Lane >= (int)VT.getVectorNumElements() / 2;
15959 Lane -= Idx * VT.getVectorNumElements() / 2;
15960 V = WidenVector(V.getOperand(Idx), DAG);
15961 } else if (VT.getSizeInBits() == 64) {
15962 // Widen the operand to 128-bit register with undef.
15963 V = WidenVector(V, DAG);
15964 }
15965 return DAG.getNode(Opcode, DL, VT, V, DAG.getConstant(Lane, DL, MVT::i64));
15966}
15967
15968// Try to widen element type to get a new mask value for a better permutation
15969// sequence, so that we can use NEON shuffle instructions, such as zip1/2,
15970// UZP1/2, TRN1/2, REV, INS, etc.
15971// For example:
15972// shufflevector <4 x i32> %a, <4 x i32> %b,
15973// <4 x i32> <i32 6, i32 7, i32 2, i32 3>
15974// is equivalent to:
15975// shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 3, i32 1>
15976// Finally, we can get:
15977// mov v0.d[0], v1.d[1]
15979 SDLoc DL(Op);
15980 EVT VT = Op.getValueType();
15981 EVT ScalarVT = VT.getVectorElementType();
15982 unsigned ElementSize = ScalarVT.getFixedSizeInBits();
15983 SDValue V0 = Op.getOperand(0);
15984 SDValue V1 = Op.getOperand(1);
15985 ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(Op)->getMask();
15986
15987 // If combining adjacent elements, like two i16's -> i32, two i32's -> i64 ...
15988 // We need to make sure the wider element type is legal. Thus, ElementSize
15989 // should be not larger than 32 bits, and i1 type should also be excluded.
15990 if (ElementSize > 32 || ElementSize == 1)
15991 return SDValue();
15992
15993 SmallVector<int, 8> NewMask;
15994 if (widenShuffleMaskElts(Mask, NewMask)) {
15995 MVT NewEltVT = VT.isFloatingPoint()
15996 ? MVT::getFloatingPointVT(ElementSize * 2)
15997 : MVT::getIntegerVT(ElementSize * 2);
15998 MVT NewVT = MVT::getVectorVT(NewEltVT, VT.getVectorNumElements() / 2);
15999 if (DAG.getTargetLoweringInfo().isTypeLegal(NewVT)) {
16000 V0 = DAG.getBitcast(NewVT, V0);
16001 V1 = DAG.getBitcast(NewVT, V1);
16002 return DAG.getBitcast(VT,
16003 DAG.getVectorShuffle(NewVT, DL, V0, V1, NewMask));
16004 }
16005 }
16006
16007 return SDValue();
16008}
16009
16010// Try to fold shuffle (tbl2, tbl2) into a single tbl4.
16012 ArrayRef<int> ShuffleMask,
16013 SelectionDAG &DAG) {
16014 SDValue Tbl1 = Op->getOperand(0);
16015 SDValue Tbl2 = Op->getOperand(1);
16016 SDLoc DL(Op);
16017 SDValue Tbl2ID =
16018 DAG.getTargetConstant(Intrinsic::aarch64_neon_tbl2, DL, MVT::i64);
16019
16020 EVT VT = Op.getValueType();
16021 if (Tbl1.getOpcode() != ISD::INTRINSIC_WO_CHAIN ||
16022 Tbl1.getOperand(0) != Tbl2ID ||
16024 Tbl2.getOperand(0) != Tbl2ID)
16025 return SDValue();
16026
16027 if (Tbl1.getValueType() != MVT::v16i8 || Tbl2.getValueType() != MVT::v16i8)
16028 return SDValue();
16029
16030 SDValue Mask1 = Tbl1.getOperand(3);
16031 SDValue Mask2 = Tbl2.getOperand(3);
16032 if (Mask1.getOpcode() != ISD::BUILD_VECTOR ||
16033 Mask2.getOpcode() != ISD::BUILD_VECTOR)
16034 return SDValue();
16035
16036 SmallVector<SDValue, 16> TBLMaskParts(16, SDValue());
16037 for (unsigned I = 0; I < 16; I++) {
16038 if (ShuffleMask[I] < 16)
16039 TBLMaskParts[I] = Mask1.getOperand(ShuffleMask[I]);
16040 else {
16041 auto *C = dyn_cast<ConstantSDNode>(Mask2.getOperand(ShuffleMask[I] - 16));
16042 if (!C)
16043 return SDValue();
16044 TBLMaskParts[I] = DAG.getConstant(C->getSExtValue() + 32, DL, MVT::i32);
16045 }
16046 }
16047
16048 SDValue TBLMask = DAG.getBuildVector(VT, DL, TBLMaskParts);
16049 SDValue ID =
16050 DAG.getTargetConstant(Intrinsic::aarch64_neon_tbl4, DL, MVT::i64);
16051
16052 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::v16i8,
16053 {ID, Tbl1->getOperand(1), Tbl1->getOperand(2),
16054 Tbl2->getOperand(1), Tbl2->getOperand(2), TBLMask});
16055}
16056
16057SDValue
16058AArch64TargetLowering::LowerEXTEND_VECTOR_INREG(SDValue Op,
16059 SelectionDAG &DAG) const {
16060 SDLoc DL(Op);
16061 EVT VT = Op.getValueType();
16062 assert(VT.isScalableVector() && "Unexpected result type!");
16063
16064 bool Signed = Op.getOpcode() == ISD::SIGN_EXTEND_VECTOR_INREG;
16065 unsigned UnpackOpcode = Signed ? AArch64ISD::SUNPKLO : AArch64ISD::UUNPKLO;
16066
16067 // Repeatedly unpack Val until the result is of the desired type.
16068 SDValue Val = Op.getOperand(0);
16069 switch (Val.getSimpleValueType().SimpleTy) {
16070 default:
16071 return SDValue();
16072 case MVT::nxv16i8:
16073 Val = DAG.getNode(UnpackOpcode, DL, MVT::nxv8i16, Val);
16074 if (VT == MVT::nxv8i16)
16075 break;
16076 [[fallthrough]];
16077 case MVT::nxv8i16:
16078 Val = DAG.getNode(UnpackOpcode, DL, MVT::nxv4i32, Val);
16079 if (VT == MVT::nxv4i32)
16080 break;
16081 [[fallthrough]];
16082 case MVT::nxv4i32:
16083 Val = DAG.getNode(UnpackOpcode, DL, MVT::nxv2i64, Val);
16084 assert(VT == MVT::nxv2i64 && "Unexpected result type!");
16085 break;
16086 }
16087
16088 return Val;
16089}
16090
16091// Baseline legalization for ZERO_EXTEND_VECTOR_INREG will blend-in zeros,
16092// but we don't have an appropriate instruction,
16093// so custom-lower it as ZIP1-with-zeros.
16094SDValue
16095AArch64TargetLowering::LowerZERO_EXTEND_VECTOR_INREG(SDValue Op,
16096 SelectionDAG &DAG) const {
16097 SDLoc DL(Op);
16098 EVT VT = Op.getValueType();
16099
16100 if (VT.isScalableVector())
16101 return LowerEXTEND_VECTOR_INREG(Op, DAG);
16102
16103 SDValue SrcOp = Op.getOperand(0);
16104 EVT SrcVT = SrcOp.getValueType();
16105 assert(VT.getScalarSizeInBits() % SrcVT.getScalarSizeInBits() == 0 &&
16106 "Unexpected extension factor.");
16107 unsigned Scale = VT.getScalarSizeInBits() / SrcVT.getScalarSizeInBits();
16108 // FIXME: support multi-step zipping?
16109 if (Scale != 2)
16110 return SDValue();
16111 SDValue Zeros = DAG.getConstant(0, DL, SrcVT);
16112 return DAG.getBitcast(VT,
16113 DAG.getNode(AArch64ISD::ZIP1, DL, SrcVT, SrcOp, Zeros));
16114}
16115
16116SDValue AArch64TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
16117 SelectionDAG &DAG) const {
16118 SDLoc DL(Op);
16119 EVT VT = Op.getValueType();
16120
16121 ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op.getNode());
16122
16123 if (useSVEForFixedLengthVectorVT(VT, !Subtarget->isNeonAvailable()))
16124 return LowerFixedLengthVECTOR_SHUFFLEToSVE(Op, DAG);
16125
16126 // Convert shuffles that are directly supported on NEON to target-specific
16127 // DAG nodes, instead of keeping them as shuffles and matching them again
16128 // during code selection. This is more efficient and avoids the possibility
16129 // of inconsistencies between legalization and selection.
16130 ArrayRef<int> ShuffleMask = SVN->getMask();
16131
16132 SDValue V1 = Op.getOperand(0);
16133 SDValue V2 = Op.getOperand(1);
16134
16135 assert(V1.getValueType() == VT && "Unexpected VECTOR_SHUFFLE type!");
16136 assert(ShuffleMask.size() == VT.getVectorNumElements() &&
16137 "Unexpected VECTOR_SHUFFLE mask size!");
16138
16139 if (SDValue Res = tryToConvertShuffleOfTbl2ToTbl4(Op, ShuffleMask, DAG))
16140 return Res;
16141
16142 if (SVN->isSplat()) {
16143 int Lane = SVN->getSplatIndex();
16144 // If this is undef splat, generate it via "just" vdup, if possible.
16145 if (Lane == -1)
16146 Lane = 0;
16147
16148 if (Lane == 0 && V1.getOpcode() == ISD::SCALAR_TO_VECTOR)
16149 return DAG.getNode(AArch64ISD::DUP, DL, V1.getValueType(),
16150 V1.getOperand(0));
16151 // Test if V1 is a BUILD_VECTOR and the lane being referenced is a non-
16152 // constant. If so, we can just reference the lane's definition directly.
16153 if (V1.getOpcode() == ISD::BUILD_VECTOR &&
16154 !isa<ConstantSDNode>(V1.getOperand(Lane)))
16155 return DAG.getNode(AArch64ISD::DUP, DL, VT, V1.getOperand(Lane));
16156
16157 // Otherwise, duplicate from the lane of the input vector.
16158 unsigned Opcode = getDUPLANEOp(V1.getValueType().getVectorElementType());
16159 return constructDup(V1, Lane, DL, VT, Opcode, DAG);
16160 }
16161
16162 // Check if the mask matches a DUP for a wider element
16163 for (unsigned LaneSize : {64U, 32U, 16U}) {
16164 unsigned Lane = 0;
16165 if (isWideDUPMask(ShuffleMask, VT, LaneSize, Lane)) {
16166 unsigned Opcode = LaneSize == 64 ? AArch64ISD::DUPLANE64
16167 : LaneSize == 32 ? AArch64ISD::DUPLANE32
16168 : AArch64ISD::DUPLANE16;
16169 // Cast V1 to an integer vector with required lane size
16170 MVT NewEltTy = MVT::getIntegerVT(LaneSize);
16171 unsigned NewEltCount = VT.getSizeInBits() / LaneSize;
16172 MVT NewVecTy = MVT::getVectorVT(NewEltTy, NewEltCount);
16173 V1 = DAG.getBitcast(NewVecTy, V1);
16174 // Construct the DUP instruction
16175 V1 = constructDup(V1, Lane, DL, NewVecTy, Opcode, DAG);
16176 // Cast back to the original type
16177 return DAG.getBitcast(VT, V1);
16178 }
16179 }
16180
16181 unsigned NumElts = VT.getVectorNumElements();
16182 unsigned EltSize = VT.getScalarSizeInBits();
16183 if (isREVMask(ShuffleMask, EltSize, NumElts, 64))
16184 return DAG.getNode(AArch64ISD::REV64, DL, V1.getValueType(), V1);
16185 if (isREVMask(ShuffleMask, EltSize, NumElts, 32))
16186 return DAG.getNode(AArch64ISD::REV32, DL, V1.getValueType(), V1);
16187 if (isREVMask(ShuffleMask, EltSize, NumElts, 16)) {
16188 EVT VT = V1.getValueType();
16189 assert(VT == MVT::v8i8 || VT == MVT::v16i8);
16190 EVT BSVT = VT == MVT::v8i8 ? MVT::v4i16 : MVT::v8i16;
16191 return DAG.getNode(
16192 AArch64ISD::NVCAST, DL, VT,
16193 DAG.getNode(ISD::BSWAP, DL, BSVT,
16194 DAG.getNode(AArch64ISD::NVCAST, DL, BSVT, V1)));
16195 }
16196
16197 if (((NumElts == 8 && EltSize == 16) || (NumElts == 16 && EltSize == 8)) &&
16198 ShuffleVectorInst::isReverseMask(ShuffleMask, ShuffleMask.size())) {
16199 SDValue Rev = DAG.getNode(AArch64ISD::REV64, DL, VT, V1);
16200 return DAG.getNode(AArch64ISD::EXT, DL, VT, Rev, Rev,
16201 DAG.getConstant(8, DL, MVT::i32));
16202 }
16203
16204 // Check for slide-with-zeros pattern before EXT (slide is also valid EXT)
16205 {
16206 unsigned ShiftAmount;
16207 bool IsRightShift;
16208 unsigned MatchedLaneSize;
16209 if (SDValue DataVec =
16210 isSlideWithZerosMask(ShuffleMask, VT, V1, V2, ShiftAmount,
16211 IsRightShift, MatchedLaneSize)) {
16212 MVT ShiftVT = MVT::getVectorVT(MVT::getIntegerVT(MatchedLaneSize),
16213 VT.getSizeInBits() / MatchedLaneSize);
16214 SDValue Vec = DAG.getNode(AArch64ISD::NVCAST, DL, ShiftVT, DataVec);
16215
16216 SDValue ShiftAmt = DAG.getTargetConstant(ShiftAmount, DL, MVT::i32);
16217 unsigned Opc = IsRightShift ? AArch64ISD::VLSHR : AArch64ISD::VSHL;
16218 SDValue Shifted = DAG.getNode(Opc, DL, ShiftVT, Vec, ShiftAmt);
16219
16220 return DAG.getNode(AArch64ISD::NVCAST, DL, VT, Shifted);
16221 }
16222 }
16223
16224 bool IsSplat1 =
16225 V1.getValueType() == VT && DAG.isSplatValue(V1, /*AllowUndefs=*/false);
16226 bool IsSplat2 =
16227 V2.getValueType() == VT && DAG.isSplatValue(V2, /*AllowUndefs=*/false);
16228 for (unsigned SplatOperand : {0U, 1U}) {
16229 if ((SplatOperand == 0 && !IsSplat1) || (SplatOperand == 1 && !IsSplat2))
16230 continue;
16231
16232 bool ReverseSplatEXT = false;
16233 unsigned SplatImm;
16234 if (isEXTMaskWithSplat(ShuffleMask, VT, SplatOperand, ReverseSplatEXT,
16235 SplatImm)) {
16236 SDValue ExtOp1 = V1;
16237 SDValue ExtOp2 = V2;
16238 if (ReverseSplatEXT)
16239 std::swap(ExtOp1, ExtOp2);
16240 SplatImm *= getExtFactor(ExtOp1);
16241 return DAG.getNode(AArch64ISD::EXT, DL, VT, ExtOp1, ExtOp2,
16242 DAG.getConstant(SplatImm, DL, MVT::i32));
16243 }
16244 }
16245
16246 bool ReverseEXT = false;
16247 unsigned Imm;
16248 if (isEXTMask(ShuffleMask, VT, ReverseEXT, Imm)) {
16249 if (ReverseEXT)
16250 std::swap(V1, V2);
16251 Imm *= getExtFactor(V1);
16252 return DAG.getNode(AArch64ISD::EXT, DL, V1.getValueType(), V1, V2,
16253 DAG.getConstant(Imm, DL, MVT::i32));
16254 } else if (V2->isUndef() && isSingletonEXTMask(ShuffleMask, VT, Imm)) {
16255 Imm *= getExtFactor(V1);
16256 return DAG.getNode(AArch64ISD::EXT, DL, V1.getValueType(), V1, V1,
16257 DAG.getConstant(Imm, DL, MVT::i32));
16258 }
16259
16260 unsigned WhichResult;
16261 unsigned OperandOrder;
16262 if (isZIPMask(ShuffleMask, NumElts, WhichResult, OperandOrder)) {
16263 unsigned Opc = (WhichResult == 0) ? AArch64ISD::ZIP1 : AArch64ISD::ZIP2;
16264 return DAG.getNode(Opc, DL, V1.getValueType(), OperandOrder == 0 ? V1 : V2,
16265 OperandOrder == 0 ? V2 : V1);
16266 }
16267 if (isUZPMask(ShuffleMask, NumElts, WhichResult)) {
16268 unsigned Opc = (WhichResult == 0) ? AArch64ISD::UZP1 : AArch64ISD::UZP2;
16269 return DAG.getNode(Opc, DL, V1.getValueType(), V1, V2);
16270 }
16271 if (isTRNMask(ShuffleMask, NumElts, WhichResult, OperandOrder)) {
16272 unsigned Opc = (WhichResult == 0) ? AArch64ISD::TRN1 : AArch64ISD::TRN2;
16273 return DAG.getNode(Opc, DL, V1.getValueType(), OperandOrder == 0 ? V1 : V2,
16274 OperandOrder == 0 ? V2 : V1);
16275 }
16276
16277 if (isZIP_v_undef_Mask(ShuffleMask, NumElts, WhichResult)) {
16278 unsigned Opc = (WhichResult == 0) ? AArch64ISD::ZIP1 : AArch64ISD::ZIP2;
16279 return DAG.getNode(Opc, DL, V1.getValueType(), V1, V1);
16280 }
16281 if (isUZP_v_undef_Mask(ShuffleMask, NumElts, WhichResult)) {
16282 unsigned Opc = (WhichResult == 0) ? AArch64ISD::UZP1 : AArch64ISD::UZP2;
16283 return DAG.getNode(Opc, DL, V1.getValueType(), V1, V1);
16284 }
16285 if (isTRN_v_undef_Mask(ShuffleMask, NumElts, WhichResult)) {
16286 unsigned Opc = (WhichResult == 0) ? AArch64ISD::TRN1 : AArch64ISD::TRN2;
16287 return DAG.getNode(Opc, DL, V1.getValueType(), V1, V1);
16288 }
16289
16291 return Concat;
16292
16293 bool DstIsLeft;
16294 int Anomaly;
16295 int NumInputElements = V1.getValueType().getVectorNumElements();
16296 if (isINSMask(ShuffleMask, NumInputElements, DstIsLeft, Anomaly)) {
16297 SDValue DstVec = DstIsLeft ? V1 : V2;
16298 SDValue DstLaneV = DAG.getConstant(Anomaly, DL, MVT::i64);
16299
16300 SDValue SrcVec = V1;
16301 int SrcLane = ShuffleMask[Anomaly];
16302 if (SrcLane >= NumInputElements) {
16303 SrcVec = V2;
16304 SrcLane -= NumElts;
16305 }
16306 SDValue SrcLaneV = DAG.getConstant(SrcLane, DL, MVT::i64);
16307
16308 EVT ScalarVT = VT.getVectorElementType();
16309
16310 if (ScalarVT.getFixedSizeInBits() < 32 && ScalarVT.isInteger())
16311 ScalarVT = MVT::i32;
16312
16313 return DAG.getNode(
16314 ISD::INSERT_VECTOR_ELT, DL, VT, DstVec,
16315 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, ScalarVT, SrcVec, SrcLaneV),
16316 DstLaneV);
16317 }
16318
16319 if (SDValue NewSD = tryWidenMaskForShuffle(Op, DAG))
16320 return NewSD;
16321
16322 // If the shuffle is not directly supported and it has 4 elements, use
16323 // the PerfectShuffle-generated table to synthesize it from other shuffles.
16324 if (NumElts == 4) {
16325 unsigned PFIndexes[4];
16326 for (unsigned i = 0; i != 4; ++i) {
16327 if (ShuffleMask[i] < 0)
16328 PFIndexes[i] = 8;
16329 else
16330 PFIndexes[i] = ShuffleMask[i];
16331 }
16332
16333 // Compute the index in the perfect shuffle table.
16334 unsigned PFTableIndex = PFIndexes[0] * 9 * 9 * 9 + PFIndexes[1] * 9 * 9 +
16335 PFIndexes[2] * 9 + PFIndexes[3];
16336 unsigned PFEntry = PerfectShuffleTable[PFTableIndex];
16337 return GeneratePerfectShuffle(PFTableIndex, V1, V2, PFEntry, V1, V2, DAG,
16338 DL);
16339 }
16340
16341 // Check for a "select shuffle", generating a BSL to pick between lanes in
16342 // V1/V2.
16343 if (ShuffleVectorInst::isSelectMask(ShuffleMask, NumElts)) {
16344 assert(VT.getScalarSizeInBits() <= 32 &&
16345 "Expected larger vector element sizes to be handled already");
16346 SmallVector<SDValue> MaskElts;
16347 for (int M : ShuffleMask)
16348 MaskElts.push_back(DAG.getConstant(
16349 M >= static_cast<int>(NumElts) ? 0 : 0xffffffff, DL, MVT::i32));
16350 EVT IVT = VT.changeVectorElementTypeToInteger();
16351 SDValue MaskConst = DAG.getBuildVector(IVT, DL, MaskElts);
16352 return DAG.getBitcast(VT, DAG.getNode(AArch64ISD::BSP, DL, IVT, MaskConst,
16353 DAG.getBitcast(IVT, V1),
16354 DAG.getBitcast(IVT, V2)));
16355 }
16356
16357 // Fall back to generating a TBL
16358 return GenerateTBL(Op, ShuffleMask, DAG);
16359}
16360
16361SDValue AArch64TargetLowering::LowerSPLAT_VECTOR(SDValue Op,
16362 SelectionDAG &DAG) const {
16363 EVT VT = Op.getValueType();
16364
16365 if (useSVEForFixedLengthVectorVT(VT, !Subtarget->isNeonAvailable()))
16366 return LowerToScalableOp(Op, DAG);
16367
16368 assert(VT.isScalableVectorOf(MVT::i1) && "Unexpected vector type!");
16369
16370 // We can handle the constant cases during isel.
16371 if (isa<ConstantSDNode>(Op.getOperand(0)))
16372 return Op;
16373
16374 // There isn't a natural way to handle the general i1 case, so we use some
16375 // trickery with whilelo.
16376 SDLoc DL(Op);
16377 SDValue SplatVal = DAG.getAnyExtOrTrunc(Op.getOperand(0), DL, MVT::i64);
16378 SplatVal = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, SplatVal,
16379 DAG.getValueType(MVT::i1));
16380 SDValue ID =
16381 DAG.getTargetConstant(Intrinsic::aarch64_sve_whilelo, DL, MVT::i64);
16382 SDValue Zero = DAG.getConstant(0, DL, MVT::i64);
16383 if (VT == MVT::nxv1i1)
16384 return DAG.getExtractSubvector(DL, MVT::nxv1i1,
16386 MVT::nxv2i1, ID, Zero, SplatVal),
16387 0);
16388 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, ID, Zero, SplatVal);
16389}
16390
16391SDValue AArch64TargetLowering::LowerDUPQLane(SDValue Op,
16392 SelectionDAG &DAG) const {
16393 SDLoc DL(Op);
16394
16395 EVT VT = Op.getValueType();
16396 if (!isTypeLegal(VT) || !VT.isScalableVector())
16397 return SDValue();
16398
16399 // Current lowering only supports the SVE-ACLE types.
16401 return SDValue();
16402
16403 // The DUPQ operation is independent of element type so normalise to i64s.
16404 SDValue Idx128 = Op.getOperand(2);
16405
16406 // DUPQ can be used when idx is in range.
16407 auto *CIdx = dyn_cast<ConstantSDNode>(Idx128);
16408 if (CIdx && (CIdx->getZExtValue() <= 3)) {
16409 SDValue CI = DAG.getTargetConstant(CIdx->getZExtValue(), DL, MVT::i64);
16410 return DAG.getNode(AArch64ISD::DUPLANE128, DL, VT, Op.getOperand(1), CI);
16411 }
16412
16413 SDValue V = DAG.getNode(ISD::BITCAST, DL, MVT::nxv2i64, Op.getOperand(1));
16414
16415 // The ACLE says this must produce the same result as:
16416 // svtbl(data, svadd_x(svptrue_b64(),
16417 // svand_x(svptrue_b64(), svindex_u64(0, 1), 1),
16418 // index * 2))
16419 SDValue One = DAG.getConstant(1, DL, MVT::i64);
16420 SDValue SplatOne = DAG.getNode(ISD::SPLAT_VECTOR, DL, MVT::nxv2i64, One);
16421
16422 // create the vector 0,1,0,1,...
16423 SDValue SV = DAG.getStepVector(DL, MVT::nxv2i64);
16424 SV = DAG.getNode(ISD::AND, DL, MVT::nxv2i64, SV, SplatOne);
16425
16426 // create the vector idx64,idx64+1,idx64,idx64+1,...
16427 SDValue Idx64 = DAG.getNode(ISD::ADD, DL, MVT::i64, Idx128, Idx128);
16428 SDValue SplatIdx64 = DAG.getNode(ISD::SPLAT_VECTOR, DL, MVT::nxv2i64, Idx64);
16429 SDValue ShuffleMask = DAG.getNode(ISD::ADD, DL, MVT::nxv2i64, SV, SplatIdx64);
16430
16431 // create the vector Val[idx64],Val[idx64+1],Val[idx64],Val[idx64+1],...
16432 SDValue TBL = DAG.getNode(AArch64ISD::TBL, DL, MVT::nxv2i64, V, ShuffleMask);
16433 return DAG.getNode(ISD::BITCAST, DL, VT, TBL);
16434}
16435
16436
16437static bool resolveBuildVector(BuildVectorSDNode *BVN, APInt &CnstBits,
16438 APInt &UndefBits) {
16439 EVT VT = BVN->getValueType(0);
16440 APInt SplatBits, SplatUndef;
16441 unsigned SplatBitSize;
16442 bool HasAnyUndefs;
16443 if (BVN->isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
16444 unsigned NumSplats = VT.getSizeInBits() / SplatBitSize;
16445
16446 for (unsigned i = 0; i < NumSplats; ++i) {
16447 CnstBits <<= SplatBitSize;
16448 UndefBits <<= SplatBitSize;
16449 CnstBits |= SplatBits.zextOrTrunc(VT.getSizeInBits());
16450 UndefBits |= (SplatBits ^ SplatUndef).zextOrTrunc(VT.getSizeInBits());
16451 }
16452
16453 return true;
16454 }
16455
16456 return false;
16457}
16458
16459// Try 64-bit splatted SIMD immediate.
16460static SDValue tryAdvSIMDModImm64(unsigned NewOp, SDValue Op, SelectionDAG &DAG,
16461 const APInt &Bits) {
16462 if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
16463 uint64_t Value = Bits.zextOrTrunc(64).getZExtValue();
16464 EVT VT = Op.getValueType();
16465 MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v2i64 : MVT::f64;
16466
16469
16470 SDLoc DL(Op);
16471 SDValue Mov =
16472 DAG.getNode(NewOp, DL, MovTy, DAG.getConstant(Value, DL, MVT::i32));
16473 return DAG.getNode(AArch64ISD::NVCAST, DL, VT, Mov);
16474 }
16475 }
16476
16477 return SDValue();
16478}
16479
16480// Try 32-bit splatted SIMD immediate.
16481static SDValue tryAdvSIMDModImm32(unsigned NewOp, SDValue Op, SelectionDAG &DAG,
16482 const APInt &Bits,
16483 const SDValue *LHS = nullptr) {
16484 EVT VT = Op.getValueType();
16485 if (VT.isFixedLengthVector() &&
16487 return SDValue();
16488
16489 if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
16490 uint64_t Value = Bits.zextOrTrunc(64).getZExtValue();
16491 MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
16492 bool isAdvSIMDModImm = false;
16493 uint64_t Shift;
16494
16495 if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType1(Value))) {
16497 Shift = 0;
16498 }
16499 else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType2(Value))) {
16501 Shift = 8;
16502 }
16503 else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType3(Value))) {
16505 Shift = 16;
16506 }
16507 else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType4(Value))) {
16509 Shift = 24;
16510 }
16511
16512 if (isAdvSIMDModImm) {
16513 SDLoc DL(Op);
16514 SDValue Mov;
16515
16516 if (LHS)
16517 Mov = DAG.getNode(NewOp, DL, MovTy,
16518 DAG.getNode(AArch64ISD::NVCAST, DL, MovTy, *LHS),
16519 DAG.getConstant(Value, DL, MVT::i32),
16520 DAG.getConstant(Shift, DL, MVT::i32));
16521 else
16522 Mov =
16523 DAG.getNode(NewOp, DL, MovTy, DAG.getConstant(Value, DL, MVT::i32),
16524 DAG.getConstant(Shift, DL, MVT::i32));
16525
16526 return DAG.getNode(AArch64ISD::NVCAST, DL, VT, Mov);
16527 }
16528 }
16529
16530 return SDValue();
16531}
16532
16533// Try 16-bit splatted SIMD immediate.
16534static SDValue tryAdvSIMDModImm16(unsigned NewOp, SDValue Op, SelectionDAG &DAG,
16535 const APInt &Bits,
16536 const SDValue *LHS = nullptr) {
16537 EVT VT = Op.getValueType();
16538 if (VT.isFixedLengthVector() &&
16540 return SDValue();
16541
16542 if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
16543 uint64_t Value = Bits.zextOrTrunc(64).getZExtValue();
16544 MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v8i16 : MVT::v4i16;
16545 bool isAdvSIMDModImm = false;
16546 uint64_t Shift;
16547
16548 if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType5(Value))) {
16550 Shift = 0;
16551 }
16552 else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType6(Value))) {
16554 Shift = 8;
16555 }
16556
16557 if (isAdvSIMDModImm) {
16558 SDLoc DL(Op);
16559 SDValue Mov;
16560
16561 if (LHS)
16562 Mov = DAG.getNode(NewOp, DL, MovTy,
16563 DAG.getNode(AArch64ISD::NVCAST, DL, MovTy, *LHS),
16564 DAG.getConstant(Value, DL, MVT::i32),
16565 DAG.getConstant(Shift, DL, MVT::i32));
16566 else
16567 Mov =
16568 DAG.getNode(NewOp, DL, MovTy, DAG.getConstant(Value, DL, MVT::i32),
16569 DAG.getConstant(Shift, DL, MVT::i32));
16570
16571 return DAG.getNode(AArch64ISD::NVCAST, DL, VT, Mov);
16572 }
16573 }
16574
16575 return SDValue();
16576}
16577
16578// Try 32-bit splatted SIMD immediate with shifted ones.
16580 SelectionDAG &DAG, const APInt &Bits) {
16581 if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
16582 uint64_t Value = Bits.zextOrTrunc(64).getZExtValue();
16583 EVT VT = Op.getValueType();
16584 MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v4i32 : MVT::v2i32;
16585 bool isAdvSIMDModImm = false;
16586 uint64_t Shift;
16587
16588 if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType7(Value))) {
16590 Shift = 264;
16591 }
16592 else if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType8(Value))) {
16594 Shift = 272;
16595 }
16596
16597 if (isAdvSIMDModImm) {
16598 SDLoc DL(Op);
16599 SDValue Mov =
16600 DAG.getNode(NewOp, DL, MovTy, DAG.getConstant(Value, DL, MVT::i32),
16601 DAG.getConstant(Shift, DL, MVT::i32));
16602 return DAG.getNode(AArch64ISD::NVCAST, DL, VT, Mov);
16603 }
16604 }
16605
16606 return SDValue();
16607}
16608
16609// Try 8-bit splatted SIMD immediate.
16610static SDValue tryAdvSIMDModImm8(unsigned NewOp, SDValue Op, SelectionDAG &DAG,
16611 const APInt &Bits) {
16612 if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
16613 uint64_t Value = Bits.zextOrTrunc(64).getZExtValue();
16614 EVT VT = Op.getValueType();
16615 MVT MovTy = (VT.getSizeInBits() == 128) ? MVT::v16i8 : MVT::v8i8;
16616
16619
16620 SDLoc DL(Op);
16621 SDValue Mov =
16622 DAG.getNode(NewOp, DL, MovTy, DAG.getConstant(Value, DL, MVT::i32));
16623 return DAG.getNode(AArch64ISD::NVCAST, DL, VT, Mov);
16624 }
16625 }
16626
16627 return SDValue();
16628}
16629
16630// Try FP splatted SIMD immediate.
16631static SDValue tryAdvSIMDModImmFP(unsigned NewOp, SDValue Op, SelectionDAG &DAG,
16632 const APInt &Bits) {
16633 if (Bits.getHiBits(64) == Bits.getLoBits(64)) {
16634 uint64_t Value = Bits.zextOrTrunc(64).getZExtValue();
16635 EVT VT = Op.getValueType();
16636 bool isWide = (VT.getSizeInBits() == 128);
16637 MVT MovTy;
16638 bool isAdvSIMDModImm = false;
16639
16640 if ((isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType11(Value))) {
16642 MovTy = isWide ? MVT::v4f32 : MVT::v2f32;
16643 }
16644 else if (isWide &&
16645 (isAdvSIMDModImm = AArch64_AM::isAdvSIMDModImmType12(Value))) {
16647 MovTy = MVT::v2f64;
16648 }
16649
16650 if (isAdvSIMDModImm) {
16651 SDLoc DL(Op);
16652 SDValue Mov =
16653 DAG.getNode(NewOp, DL, MovTy, DAG.getConstant(Value, DL, MVT::i32));
16654 return DAG.getNode(AArch64ISD::NVCAST, DL, VT, Mov);
16655 }
16656 }
16657
16658 return SDValue();
16659}
16660
16661// Specialized code to quickly find if PotentialBVec is a BuildVector that
16662// consists of only the same constant int value, returned in reference arg
16663// ConstVal
16664static bool isAllConstantBuildVector(const SDValue &PotentialBVec,
16665 uint64_t &ConstVal) {
16666 BuildVectorSDNode *Bvec = dyn_cast<BuildVectorSDNode>(PotentialBVec);
16667 if (!Bvec)
16668 return false;
16670 if (!FirstElt)
16671 return false;
16672 EVT VT = Bvec->getValueType(0);
16673 unsigned NumElts = VT.getVectorNumElements();
16674 for (unsigned i = 1; i < NumElts; ++i)
16675 if (dyn_cast<ConstantSDNode>(Bvec->getOperand(i)) != FirstElt)
16676 return false;
16677 ConstVal = FirstElt->getZExtValue();
16678 return true;
16679}
16680
16682 // Look through cast.
16683 while (N.getOpcode() == AArch64ISD::REINTERPRET_CAST)
16684 N = N.getOperand(0);
16685
16686 return ISD::isConstantSplatVectorAllZeros(N.getNode());
16687}
16688
16689static bool isAllActivePredicate(const SelectionDAG &DAG, SDValue N) {
16690 unsigned NumElts = N.getValueType().getVectorMinNumElements();
16691
16692 // Look through cast.
16693 while (N.getOpcode() == AArch64ISD::REINTERPRET_CAST) {
16694 N = N.getOperand(0);
16695 // When reinterpreting from a type with fewer elements the "new" elements
16696 // are not active, so bail if they're likely to be used.
16697 if (N.getValueType().getVectorMinNumElements() < NumElts)
16698 return false;
16699 }
16700
16701 if (ISD::isConstantSplatVectorAllOnes(N.getNode()))
16702 return true;
16703
16704 // "ptrue p.<ty>, all" can be considered all active when <ty> is the same size
16705 // or smaller than the implicit element type represented by N.
16706 // NOTE: A larger element count implies a smaller element type.
16707 if (N.getOpcode() == AArch64ISD::PTRUE &&
16708 N.getConstantOperandVal(0) == AArch64SVEPredPattern::all)
16709 return N.getValueType().getVectorMinNumElements() >= NumElts;
16710
16711 return false;
16712}
16713
16714// Attempt to form a vector S[LR]I from (or (and X, BvecC1), (lsl Y, C2)),
16715// to (SLI X, Y, C2), where X and Y have matching vector types, BvecC1 is a
16716// BUILD_VECTORs with constant element C1, C2 is a constant, and:
16717// - for the SLI case: C1 == ~(Ones(ElemSizeInBits) << C2)
16718// - for the SRI case: C1 == ~(Ones(ElemSizeInBits) >> C2)
16719// The (or (lsl Y, C2), (and X, BvecC1)) case is also handled.
16721 EVT VT = N->getValueType(0);
16722
16723 if (!VT.isVector())
16724 return SDValue();
16725
16726 SDLoc DL(N);
16727
16728 SDValue And;
16729 SDValue Shift;
16730
16731 SDValue FirstOp = N->getOperand(0);
16732 unsigned FirstOpc = FirstOp.getOpcode();
16733 SDValue SecondOp = N->getOperand(1);
16734 unsigned SecondOpc = SecondOp.getOpcode();
16735
16736 // Is one of the operands an AND or a BICi? The AND may have been optimised to
16737 // a BICi in order to use an immediate instead of a register.
16738 // Is the other operand an shl or lshr? This will have been turned into:
16739 // AArch64ISD::VSHL vector, #shift or AArch64ISD::VLSHR vector, #shift
16740 // or (AArch64ISD::SHL_PRED || AArch64ISD::SRL_PRED) mask, vector, #shiftVec.
16741 if ((FirstOpc == ISD::AND || FirstOpc == AArch64ISD::BICi) &&
16742 (SecondOpc == AArch64ISD::VSHL || SecondOpc == AArch64ISD::VLSHR ||
16743 SecondOpc == AArch64ISD::SHL_PRED ||
16744 SecondOpc == AArch64ISD::SRL_PRED)) {
16745 And = FirstOp;
16746 Shift = SecondOp;
16747
16748 } else if ((SecondOpc == ISD::AND || SecondOpc == AArch64ISD::BICi) &&
16749 (FirstOpc == AArch64ISD::VSHL || FirstOpc == AArch64ISD::VLSHR ||
16750 FirstOpc == AArch64ISD::SHL_PRED ||
16751 FirstOpc == AArch64ISD::SRL_PRED)) {
16752 And = SecondOp;
16753 Shift = FirstOp;
16754 } else
16755 return SDValue();
16756
16757 bool IsAnd = And.getOpcode() == ISD::AND;
16758 bool IsShiftRight = Shift.getOpcode() == AArch64ISD::VLSHR ||
16759 Shift.getOpcode() == AArch64ISD::SRL_PRED;
16760 bool ShiftHasPredOp = Shift.getOpcode() == AArch64ISD::SHL_PRED ||
16761 Shift.getOpcode() == AArch64ISD::SRL_PRED;
16762
16763 // Is the shift amount constant and are all lanes active?
16764 uint64_t C2;
16765 if (ShiftHasPredOp) {
16766 if (!isAllActivePredicate(DAG, Shift.getOperand(0)))
16767 return SDValue();
16768 APInt C;
16770 return SDValue();
16771 C2 = C.getZExtValue();
16772 } else if (ConstantSDNode *C2node =
16774 C2 = C2node->getZExtValue();
16775 else
16776 return SDValue();
16777
16778 APInt C1AsAPInt;
16779 unsigned ElemSizeInBits = VT.getScalarSizeInBits();
16780 if (IsAnd) {
16781 // Is the and mask vector all constant?
16782 if (!ISD::isConstantSplatVector(And.getOperand(1).getNode(), C1AsAPInt))
16783 return SDValue();
16784 } else {
16785 // Reconstruct the corresponding AND immediate from the two BICi immediates.
16786 ConstantSDNode *C1nodeImm = dyn_cast<ConstantSDNode>(And.getOperand(1));
16787 ConstantSDNode *C1nodeShift = dyn_cast<ConstantSDNode>(And.getOperand(2));
16788 assert(C1nodeImm && C1nodeShift);
16789 C1AsAPInt = ~(C1nodeImm->getAPIntValue() << C1nodeShift->getAPIntValue());
16790 C1AsAPInt = C1AsAPInt.zextOrTrunc(ElemSizeInBits);
16791 }
16792
16793 // Is C1 == ~(Ones(ElemSizeInBits) << C2) or
16794 // C1 == ~(Ones(ElemSizeInBits) >> C2), taking into account
16795 // how much one can shift elements of a particular size?
16796 if (C2 > ElemSizeInBits)
16797 return SDValue();
16798
16799 APInt RequiredC1 = IsShiftRight ? APInt::getHighBitsSet(ElemSizeInBits, C2)
16800 : APInt::getLowBitsSet(ElemSizeInBits, C2);
16801 if (C1AsAPInt != RequiredC1)
16802 return SDValue();
16803
16804 SDValue X = And.getOperand(0);
16805 SDValue Y = ShiftHasPredOp ? Shift.getOperand(1) : Shift.getOperand(0);
16806 SDValue Imm = ShiftHasPredOp ? DAG.getTargetConstant(C2, DL, MVT::i32)
16807 : Shift.getOperand(1);
16808
16809 unsigned Inst = IsShiftRight ? AArch64ISD::VSRI : AArch64ISD::VSLI;
16810 return DAG.getNode(Inst, DL, VT, X, Y, Imm);
16811}
16812
16814 EVT VT = N->getValueType(0);
16815 assert(VT.isVector() && "Expected vector type in tryLowerToBSL\n");
16816 SDLoc DL(N);
16817 const auto &Subtarget = DAG.getSubtarget<AArch64Subtarget>();
16818
16819 if (VT.isScalableVector() && !Subtarget.hasSVE2())
16820 return SDValue();
16821
16822 SDValue N0 = N->getOperand(0);
16823 if (N0.getOpcode() != ISD::AND)
16824 return SDValue();
16825
16826 SDValue N1 = N->getOperand(1);
16827 if (N1.getOpcode() != ISD::AND)
16828 return SDValue();
16829
16830 // InstCombine does (not (neg a)) => (add a -1).
16831 // Try: (or (and (neg a) b) (and (add a -1) c)) => (bsl (neg a) b c)
16832 // Loop over all combinations of AND operands.
16833 for (int i = 1; i >= 0; --i) {
16834 for (int j = 1; j >= 0; --j) {
16835 SDValue O0 = N0->getOperand(i);
16836 SDValue O1 = N1->getOperand(j);
16837 SDValue Sub, Add, SubSibling, AddSibling;
16838
16839 // Find a SUB and an ADD operand, one from each AND.
16840 if (O0.getOpcode() == ISD::SUB && O1.getOpcode() == ISD::ADD) {
16841 Sub = O0;
16842 Add = O1;
16843 SubSibling = N0->getOperand(1 - i);
16844 AddSibling = N1->getOperand(1 - j);
16845 } else if (O0.getOpcode() == ISD::ADD && O1.getOpcode() == ISD::SUB) {
16846 Add = O0;
16847 Sub = O1;
16848 AddSibling = N0->getOperand(1 - i);
16849 SubSibling = N1->getOperand(1 - j);
16850 } else
16851 continue;
16852
16853 if (!ISD::isConstantSplatVectorAllZeros(Sub.getOperand(0).getNode()))
16854 continue;
16855
16856 // Constant ones is always righthand operand of the Add.
16857 if (!ISD::isConstantSplatVectorAllOnes(Add.getOperand(1).getNode()))
16858 continue;
16859
16860 if (Sub.getOperand(1) != Add.getOperand(0))
16861 continue;
16862
16863 return DAG.getNode(AArch64ISD::BSP, DL, VT, Sub, SubSibling, AddSibling);
16864 }
16865 }
16866
16867 // (or (and a b) (and (not a) c)) => (bsl a b c)
16868 // We only have to look for constant vectors here since the general, variable
16869 // case can be handled in TableGen.
16870 unsigned Bits = VT.getScalarSizeInBits();
16871 for (int i = 1; i >= 0; --i)
16872 for (int j = 1; j >= 0; --j) {
16873 APInt Val1, Val2;
16874
16875 if (ISD::isConstantSplatVector(N0->getOperand(i).getNode(), Val1) &&
16877 ~Val1.trunc(Bits) == Val2.trunc(Bits)) {
16878 return DAG.getNode(AArch64ISD::BSP, DL, VT, N0->getOperand(i),
16879 N0->getOperand(1 - i), N1->getOperand(1 - j));
16880 }
16883 if (!BVN0 || !BVN1)
16884 continue;
16885
16886 bool FoundMatch = true;
16887 for (unsigned k = 0; k < VT.getVectorNumElements(); ++k) {
16890 if (!CN0 || !CN1 ||
16891 CN0->getAPIntValue().trunc(Bits) !=
16892 ~CN1->getAsAPIntVal().trunc(Bits)) {
16893 FoundMatch = false;
16894 break;
16895 }
16896 }
16897 if (FoundMatch)
16898 return DAG.getNode(AArch64ISD::BSP, DL, VT, N0->getOperand(i),
16899 N0->getOperand(1 - i), N1->getOperand(1 - j));
16900 }
16901
16902 return SDValue();
16903}
16904
16905SDValue AArch64TargetLowering::LowerVectorOR(SDValue Op,
16906 SelectionDAG &DAG) const {
16907 if (useSVEForFixedLengthVectorVT(Op.getValueType(),
16908 !Subtarget->isNeonAvailable()))
16909 return LowerToScalableOp(Op, DAG);
16910
16911 if (SDValue Res = tryLowerToBSL(Op, DAG))
16912 return Res;
16913
16914 // Attempt to form a vector S[LR]I from (or (and X, C1), (lsl Y, C2))
16915 if (SDValue Res = tryLowerToSLI(Op.getNode(), DAG))
16916 return Res;
16917
16918 EVT VT = Op.getValueType();
16919 if (VT.isScalableVector())
16920 return Op;
16921
16922 SDValue LHS = Op.getOperand(0);
16923 BuildVectorSDNode *BVN =
16924 dyn_cast<BuildVectorSDNode>(Op.getOperand(1).getNode());
16925 if (!BVN) {
16926 // OR commutes, so try swapping the operands.
16927 LHS = Op.getOperand(1);
16928 BVN = dyn_cast<BuildVectorSDNode>(Op.getOperand(0).getNode());
16929 }
16930 if (!BVN)
16931 return Op;
16932
16933 APInt DefBits(VT.getSizeInBits(), 0);
16934 APInt UndefBits(VT.getSizeInBits(), 0);
16935 if (resolveBuildVector(BVN, DefBits, UndefBits)) {
16936 SDValue NewOp;
16937
16938 if ((NewOp = tryAdvSIMDModImm32(AArch64ISD::ORRi, Op, DAG,
16939 DefBits, &LHS)) ||
16940 (NewOp = tryAdvSIMDModImm16(AArch64ISD::ORRi, Op, DAG,
16941 DefBits, &LHS)))
16942 return NewOp;
16943
16944 if ((NewOp = tryAdvSIMDModImm32(AArch64ISD::ORRi, Op, DAG,
16945 UndefBits, &LHS)) ||
16946 (NewOp = tryAdvSIMDModImm16(AArch64ISD::ORRi, Op, DAG,
16947 UndefBits, &LHS)))
16948 return NewOp;
16949 }
16950
16951 // We can always fall back to a non-immediate OR.
16952 return Op;
16953}
16954
16955// Normalize the operands of BUILD_VECTOR. The value of constant operands will
16956// be truncated to fit element width.
16958 SelectionDAG &DAG) {
16959 assert(Op.getOpcode() == ISD::BUILD_VECTOR && "Unknown opcode!");
16960 SDLoc DL(Op);
16961 EVT VT = Op.getValueType();
16962 EVT EltTy= VT.getVectorElementType();
16963
16964 if (EltTy.isFloatingPoint() || EltTy.getSizeInBits() > 16)
16965 return Op;
16966
16968 for (SDValue Lane : Op->ops()) {
16969 // For integer vectors, type legalization would have promoted the
16970 // operands already. Otherwise, if Op is a floating-point splat
16971 // (with operands cast to integers), then the only possibilities
16972 // are constants and UNDEFs.
16973 if (auto *CstLane = dyn_cast<ConstantSDNode>(Lane)) {
16974 Lane = DAG.getConstant(
16975 CstLane->getAPIntValue().trunc(EltTy.getSizeInBits()).getZExtValue(),
16976 DL, MVT::i32);
16977 } else if (Lane.getOpcode() == ISD::POISON) {
16978 Lane = DAG.getPOISON(MVT::i32);
16979 } else if (Lane.getOpcode() == ISD::UNDEF) {
16980 Lane = DAG.getUNDEF(MVT::i32);
16981 } else {
16982 assert(Lane.getValueType() == MVT::i32 &&
16983 "Unexpected BUILD_VECTOR operand type");
16984 }
16985 Ops.push_back(Lane);
16986 }
16987 return DAG.getBuildVector(VT, DL, Ops);
16988}
16989
16991 const AArch64Subtarget *ST, APInt &DefBits) {
16992 EVT VT = Op.getValueType();
16993 // TODO: We should be able to support 64-bit destinations too
16994 if (!ST->hasSVE() || !VT.is128BitVector() ||
16995 DefBits.getHiBits(64) != DefBits.getLoBits(64))
16996 return SDValue();
16997
16998 // See if we can make use of the SVE dup instruction.
16999 APInt Val64 = DefBits.trunc(64);
17000 int32_t ImmVal, ShiftVal;
17001 uint64_t Encoding;
17002 if (!AArch64_AM::isSVECpyDupImm(64, Val64.getSExtValue(), ImmVal, ShiftVal) &&
17003 !AArch64_AM::isSVELogicalImm(64, Val64.getZExtValue(), Encoding))
17004 return SDValue();
17005
17006 SDLoc DL(Op);
17007 SDValue SplatVal = DAG.getNode(AArch64ISD::DUP, DL, MVT::v2i64,
17008 DAG.getConstant(Val64, DL, MVT::i64));
17009 return DAG.getNode(AArch64ISD::NVCAST, DL, VT, SplatVal);
17010}
17011
17013 const AArch64Subtarget *ST) {
17014 EVT VT = Op.getValueType();
17015 assert((VT.getSizeInBits() == 64 || VT.getSizeInBits() == 128) &&
17016 "Expected a legal NEON vector");
17017
17018 APInt DefBits(VT.getSizeInBits(), 0);
17019 APInt UndefBits(VT.getSizeInBits(), 0);
17021 if (resolveBuildVector(BVN, DefBits, UndefBits)) {
17022 auto TryMOVIWithBits = [&](APInt DefBits) {
17023 SDValue NewOp;
17024 if ((NewOp =
17025 tryAdvSIMDModImm64(AArch64ISD::MOVIedit, Op, DAG, DefBits)) ||
17026 (NewOp =
17027 tryAdvSIMDModImm32(AArch64ISD::MOVIshift, Op, DAG, DefBits)) ||
17028 (NewOp =
17029 tryAdvSIMDModImm321s(AArch64ISD::MOVImsl, Op, DAG, DefBits)) ||
17030 (NewOp =
17031 tryAdvSIMDModImm16(AArch64ISD::MOVIshift, Op, DAG, DefBits)) ||
17032 (NewOp = tryAdvSIMDModImm8(AArch64ISD::MOVI, Op, DAG, DefBits)) ||
17033 (NewOp = tryAdvSIMDModImmFP(AArch64ISD::FMOV, Op, DAG, DefBits)))
17034 return NewOp;
17035
17036 APInt NotDefBits = ~DefBits;
17037 if ((NewOp = tryAdvSIMDModImm32(AArch64ISD::MVNIshift, Op, DAG,
17038 NotDefBits)) ||
17039 (NewOp = tryAdvSIMDModImm321s(AArch64ISD::MVNImsl, Op, DAG,
17040 NotDefBits)) ||
17041 (NewOp =
17042 tryAdvSIMDModImm16(AArch64ISD::MVNIshift, Op, DAG, NotDefBits)))
17043 return NewOp;
17044 return SDValue();
17045 };
17046 if (SDValue R = TryMOVIWithBits(DefBits))
17047 return R;
17048 if (SDValue R = TryMOVIWithBits(UndefBits))
17049 return R;
17050
17051 // Try to materialise the constant using SVE when available.
17052 if (SDValue R = trySVESplat64(Op, DAG, ST, DefBits))
17053 return R;
17054
17055 // See if a fneg of the constant can be materialized with a MOVI, etc
17056 auto TryWithFNeg = [&](APInt DefBits, MVT FVT) {
17057 // FNegate each sub-element of the constant
17058 assert(VT.getSizeInBits() % FVT.getScalarSizeInBits() == 0);
17059 APInt Neg = APInt::getHighBitsSet(FVT.getSizeInBits(), 1)
17060 .zext(VT.getSizeInBits());
17061 APInt NegBits(VT.getSizeInBits(), 0);
17062 unsigned NumElts = VT.getSizeInBits() / FVT.getScalarSizeInBits();
17063 for (unsigned i = 0; i < NumElts; i++)
17064 NegBits |= Neg << (FVT.getScalarSizeInBits() * i);
17065 NegBits = DefBits ^ NegBits;
17066
17067 // Try to create the new constants with MOVI, and if so generate a fneg
17068 // for it.
17069 if (SDValue NewOp = TryMOVIWithBits(NegBits)) {
17070 SDLoc DL(Op);
17071 MVT VFVT = NumElts == 1 ? FVT : MVT::getVectorVT(FVT, NumElts);
17072 return DAG.getNode(
17073 AArch64ISD::NVCAST, DL, VT,
17074 DAG.getNode(ISD::FNEG, DL, VFVT,
17075 DAG.getNode(AArch64ISD::NVCAST, DL, VFVT, NewOp)));
17076 }
17077 return SDValue();
17078 };
17079 SDValue R;
17080 if ((R = TryWithFNeg(DefBits, MVT::f32)) ||
17081 (R = TryWithFNeg(DefBits, MVT::f64)) ||
17082 (ST->hasFullFP16() && (R = TryWithFNeg(DefBits, MVT::f16))))
17083 return R;
17084 }
17085
17086 return SDValue();
17087}
17088
17089SDValue AArch64TargetLowering::LowerFixedLengthBuildVectorToSVE(
17090 SDValue Op, SelectionDAG &DAG) const {
17091 EVT VT = Op.getValueType();
17092 SDLoc DL(Op);
17093 EVT ContainerVT = getContainerForFixedLengthVector(DAG, VT);
17094 auto *BVN = cast<BuildVectorSDNode>(Op);
17095
17096 if (auto SeqInfo = BVN->isArithmeticSequence()) {
17097 SDValue Start = DAG.getConstant(SeqInfo->first, DL, ContainerVT);
17098 SDValue Steps = DAG.getStepVector(DL, ContainerVT, SeqInfo->second);
17099 SDValue Seq = DAG.getNode(ISD::ADD, DL, ContainerVT, Start, Steps);
17100 return convertFromScalableVector(DAG, VT, Seq);
17101 }
17102
17103 unsigned NumElems = VT.getVectorNumElements();
17104 if (!VT.isPow2VectorType() || VT.getFixedSizeInBits() > 128 ||
17105 NumElems <= 1 || BVN->isConstant())
17106 return SDValue();
17107
17108 auto IsExtractElt = [](SDValue Op) {
17109 return Op.getOpcode() == ISD::EXTRACT_VECTOR_ELT;
17110 };
17111
17112 // For integer types that are not already in vectors limit to at most four
17113 // elements. This is an arbitrary restriction to avoid many fmovs from GPRs.
17114 if (VT.getScalarType().isInteger() &&
17115 NumElems - count_if(Op->op_values(), IsExtractElt) > 4)
17116 return SDValue();
17117
17118 // Lower (pow2) BUILD_VECTORS that are <= 128-bit to a sequence of ZIP1s.
17119 SDValue ZeroI64 = DAG.getConstant(0, DL, MVT::i64);
17121 Op->op_values(), [&, Poison = DAG.getPOISON(ContainerVT)](SDValue Op) {
17122 return Op.isUndef() ? Poison
17123 : DAG.getNode(ISD::INSERT_VECTOR_ELT, DL,
17124 ContainerVT, Poison, Op, ZeroI64);
17125 });
17126
17127 ElementCount ZipEC = ContainerVT.getVectorElementCount();
17128 while (Intermediates.size() > 1) {
17129 EVT ZipVT = getPackedSVEVectorVT(ZipEC);
17130
17131 for (unsigned I = 0; I < Intermediates.size(); I += 2) {
17132 SDValue Op0 = DAG.getBitcast(ZipVT, Intermediates[I + 0]);
17133 SDValue Op1 = DAG.getBitcast(ZipVT, Intermediates[I + 1]);
17134 Intermediates[I / 2] =
17135 Op1.isUndef() ? Op0
17136 : DAG.getNode(AArch64ISD::ZIP1, DL, ZipVT, Op0, Op1);
17137 }
17138
17139 Intermediates.resize(Intermediates.size() / 2);
17140 ZipEC = ZipEC.divideCoefficientBy(2);
17141 }
17142
17143 assert(Intermediates.size() == 1);
17144 SDValue Vec = DAG.getBitcast(ContainerVT, Intermediates[0]);
17145 return convertFromScalableVector(DAG, VT, Vec);
17146}
17147
17148SDValue AArch64TargetLowering::LowerBUILD_VECTOR(SDValue Op,
17149 SelectionDAG &DAG) const {
17150 EVT VT = Op.getValueType();
17151
17152 bool OverrideNEON = !Subtarget->isNeonAvailable();
17153 if (!OverrideNEON && Subtarget->isSVEorStreamingSVEAvailable()) {
17154 if (auto Seq = cast<BuildVectorSDNode>(Op)->isArithmeticSequence()) {
17155 // Only attempt to use the SVE index instruction if both operands are
17156 // immediate, otherwise it's better to load a literal.
17157 if (Seq->first.sge(-16) && Seq->first.slt(16) && Seq->second.sge(-16) &&
17158 Seq->second.slt(16))
17159 OverrideNEON = true;
17160 }
17161 }
17162 if (useSVEForFixedLengthVectorVT(VT, OverrideNEON))
17163 return LowerFixedLengthBuildVectorToSVE(Op, DAG);
17164
17165 // Try to build a simple constant vector.
17166 Op = NormalizeBuildVector(Op, DAG);
17167 // Thought this might return a non-BUILD_VECTOR (e.g. CONCAT_VECTORS), if so,
17168 // abort.
17169 if (Op.getOpcode() != ISD::BUILD_VECTOR)
17170 return SDValue();
17171
17172 // Certain vector constants, used to express things like logical NOT and
17173 // arithmetic NEG, are passed through unmodified. This allows special
17174 // patterns for these operations to match, which will lower these constants
17175 // to whatever is proven necessary.
17176 BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Op.getNode());
17177 if (BVN->isConstant()) {
17178 if (ConstantSDNode *Const = BVN->getConstantSplatNode()) {
17179 unsigned BitSize = VT.getVectorElementType().getSizeInBits();
17180 APInt Val(BitSize,
17181 Const->getAPIntValue().zextOrTrunc(BitSize).getZExtValue());
17182 if (Val.isZero() || (VT.isInteger() && Val.isAllOnes()))
17183 return Op;
17184 }
17185 if (ConstantFPSDNode *Const = BVN->getConstantFPSplatNode())
17186 if (Const->isZero() && !Const->isNegative())
17187 return Op;
17188 }
17189
17190 if (SDValue V = ConstantBuildVector(Op, DAG, Subtarget))
17191 return V;
17192
17193 // Scan through the operands to find some interesting properties we can
17194 // exploit:
17195 // 1) If only one value is used, we can use a DUP, or
17196 // 2) if only the low element is not undef, we can just insert that, or
17197 // 3) if only one constant value is used (w/ some non-constant lanes),
17198 // we can splat the constant value into the whole vector then fill
17199 // in the non-constant lanes.
17200 // 4) FIXME: If different constant values are used, but we can intelligently
17201 // select the values we'll be overwriting for the non-constant
17202 // lanes such that we can directly materialize the vector
17203 // some other way (MOVI, e.g.), we can be sneaky.
17204 // 5) if all operands are EXTRACT_VECTOR_ELT, check for VUZP.
17205 SDLoc DL(Op);
17206 unsigned NumElts = VT.getVectorNumElements();
17207 bool isOnlyLowElement = true;
17208 bool usesOnlyOneValue = true;
17209 bool usesOnlyOneConstantValue = true;
17210 bool isConstant = true;
17211 bool AllLanesExtractElt = true;
17212 unsigned NumConstantLanes = 0;
17213 unsigned NumDifferentLanes = 0;
17214 unsigned NumUndefLanes = 0;
17215 SDValue Value;
17216 SDValue ConstantValue;
17217 SmallMapVector<SDValue, unsigned, 16> DifferentValueMap;
17218 unsigned ConsecutiveValCount = 0;
17219 SDValue PrevVal;
17220 auto IsZero = [&](SDValue V) {
17221 return isNullConstant(V) || isNullFPConstant(V);
17222 };
17223 bool MaybeLowHalfZeroHigh =
17224 VT.isFixedLengthVector() && VT.getSizeInBits() == 128;
17225 unsigned HalfElts = MaybeLowHalfZeroHigh ? (NumElts >> 1) : 0;
17226 SDValue LowHalfFirstVal = MaybeLowHalfZeroHigh ? Op.getOperand(0) : SDValue();
17227 for (unsigned i = 0; i < NumElts; ++i) {
17228 SDValue V = Op.getOperand(i);
17229 if (V.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
17230 AllLanesExtractElt = false;
17231 if (V.isUndef()) {
17232 ++NumUndefLanes;
17233 MaybeLowHalfZeroHigh = false;
17234 continue;
17235 }
17236 if (i > 0)
17237 isOnlyLowElement = false;
17238 if (!isIntOrFPConstant(V))
17239 isConstant = false;
17240
17241 if (isIntOrFPConstant(V)) {
17242 ++NumConstantLanes;
17243 if (!ConstantValue.getNode())
17244 ConstantValue = V;
17245 else if (ConstantValue != V)
17246 usesOnlyOneConstantValue = false;
17247 }
17248
17249 if (!Value.getNode())
17250 Value = V;
17251 else if (V != Value) {
17252 usesOnlyOneValue = false;
17253 ++NumDifferentLanes;
17254 }
17255
17256 if (PrevVal != V) {
17257 ConsecutiveValCount = 0;
17258 PrevVal = V;
17259 }
17260 if (MaybeLowHalfZeroHigh) {
17261 if (i < HalfElts) {
17262 if (V != LowHalfFirstVal)
17263 MaybeLowHalfZeroHigh = false;
17264 } else if (!IsZero(V)) {
17265 MaybeLowHalfZeroHigh = false;
17266 }
17267 }
17268
17269 // Keep different values and its last consecutive count. For example,
17270 //
17271 // t22: v16i8 = build_vector t23, t23, t23, t23, t23, t23, t23, t23,
17272 // t24, t24, t24, t24, t24, t24, t24, t24
17273 // t23 = consecutive count 8
17274 // t24 = consecutive count 8
17275 // ------------------------------------------------------------------
17276 // t22: v16i8 = build_vector t24, t24, t23, t23, t23, t23, t23, t24,
17277 // t24, t24, t24, t24, t24, t24, t24, t24
17278 // t23 = consecutive count 5
17279 // t24 = consecutive count 9
17280 DifferentValueMap[V] = ++ConsecutiveValCount;
17281 }
17282
17283 if (!Value.getNode()) {
17284 LLVM_DEBUG(
17285 dbgs() << "LowerBUILD_VECTOR: value undefined, creating undef node\n");
17286 return DAG.getUNDEF(VT);
17287 }
17288
17289 // Convert BUILD_VECTOR where all elements but the lowest are undef into
17290 // SCALAR_TO_VECTOR, except for when we have a constant vector
17291 // as SimplifyDemandedBits will just turn that back into BUILD_VECTOR.
17292 if (isOnlyLowElement && !isIntOrFPConstant(Value)) {
17293 LLVM_DEBUG(dbgs() << "LowerBUILD_VECTOR: only low element used, creating 1 "
17294 "SCALAR_TO_VECTOR node\n");
17295 return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Value);
17296 }
17297
17298 if (MaybeLowHalfZeroHigh && LowHalfFirstVal.getNode() &&
17299 !LowHalfFirstVal.isUndef() && !isIntOrFPConstant(LowHalfFirstVal)) {
17300 EVT LaneVT = VT.getVectorElementType();
17301 EVT HalfVT = VT.getHalfNumVectorElementsVT(*DAG.getContext());
17302
17303 SDValue HiZero = LaneVT.isInteger() ? DAG.getConstant(0, DL, HalfVT)
17304 : DAG.getConstantFP(0.0, DL, HalfVT);
17305
17306 SDValue LoHalf =
17307 LaneVT.getSizeInBits() == 64
17308 ? DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, HalfVT, LowHalfFirstVal)
17309 : DAG.getNode(AArch64ISD::DUP, DL, HalfVT, LowHalfFirstVal);
17310
17311 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, LoHalf, HiZero);
17312 }
17313
17314 if (AllLanesExtractElt) {
17315 SDNode *Vector = nullptr;
17316 bool Even = false;
17317 bool Odd = false;
17318 // Check whether the extract elements match the Even pattern <0,2,4,...> or
17319 // the Odd pattern <1,3,5,...>.
17320 for (unsigned i = 0; i < NumElts; ++i) {
17321 SDValue V = Op.getOperand(i);
17322 const SDNode *N = V.getNode();
17323 if (!isa<ConstantSDNode>(N->getOperand(1))) {
17324 Even = false;
17325 Odd = false;
17326 break;
17327 }
17328 SDValue N0 = N->getOperand(0);
17329
17330 // All elements are extracted from the same vector.
17331 if (!Vector) {
17332 Vector = N0.getNode();
17333 // Check that the type of EXTRACT_VECTOR_ELT matches the type of
17334 // BUILD_VECTOR.
17335 if (VT.getVectorElementType() !=
17337 break;
17338 } else if (Vector != N0.getNode()) {
17339 Odd = false;
17340 Even = false;
17341 break;
17342 }
17343
17344 // Extracted values are either at Even indices <0,2,4,...> or at Odd
17345 // indices <1,3,5,...>.
17347 if (Val == 2 * i) {
17348 Even = true;
17349 continue;
17350 }
17351 if (Val - 1 == 2 * i) {
17352 Odd = true;
17353 continue;
17354 }
17355
17356 // Something does not match: abort.
17357 Odd = false;
17358 Even = false;
17359 break;
17360 }
17361 if (Even || Odd) {
17362 SDValue LHS = DAG.getExtractSubvector(DL, VT, SDValue(Vector, 0), 0);
17363 SDValue RHS =
17364 DAG.getExtractSubvector(DL, VT, SDValue(Vector, 0), NumElts);
17365
17366 if (Even && !Odd)
17367 return DAG.getNode(AArch64ISD::UZP1, DL, VT, LHS, RHS);
17368 if (Odd && !Even)
17369 return DAG.getNode(AArch64ISD::UZP2, DL, VT, LHS, RHS);
17370 }
17371 }
17372
17373 // Use DUP for non-constant splats. For f32 constant splats, reduce to
17374 // i32 and try again.
17375 if (usesOnlyOneValue) {
17376 if (!isConstant) {
17377 if (Value.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
17378 Value.getValueType() != VT) {
17379 LLVM_DEBUG(
17380 dbgs() << "LowerBUILD_VECTOR: use DUP for non-constant splats\n");
17381 return DAG.getNode(AArch64ISD::DUP, DL, VT, Value);
17382 }
17383
17384 // This is actually a DUPLANExx operation, which keeps everything vectory.
17385
17386 SDValue Lane = Value.getOperand(1);
17387 Value = Value.getOperand(0);
17388 if (Value.getValueSizeInBits() == 64) {
17389 LLVM_DEBUG(
17390 dbgs() << "LowerBUILD_VECTOR: DUPLANE works on 128-bit vectors, "
17391 "widening it\n");
17392 Value = WidenVector(Value, DAG);
17393 }
17394
17395 unsigned Opcode = getDUPLANEOp(VT.getVectorElementType());
17396 return DAG.getNode(Opcode, DL, VT, Value, Lane);
17397 }
17398
17401 EVT EltTy = VT.getVectorElementType();
17402 assert ((EltTy == MVT::f16 || EltTy == MVT::bf16 || EltTy == MVT::f32 ||
17403 EltTy == MVT::f64) && "Unsupported floating-point vector type");
17404 LLVM_DEBUG(
17405 dbgs() << "LowerBUILD_VECTOR: float constant splats, creating int "
17406 "BITCASTS, and try again\n");
17407 MVT NewType = MVT::getIntegerVT(EltTy.getSizeInBits());
17408 for (unsigned i = 0; i < NumElts; ++i)
17409 Ops.push_back(DAG.getNode(ISD::BITCAST, DL, NewType, Op.getOperand(i)));
17410 EVT VecVT = EVT::getVectorVT(*DAG.getContext(), NewType, NumElts);
17411 SDValue Val = DAG.getBuildVector(VecVT, DL, Ops);
17412 LLVM_DEBUG(dbgs() << "LowerBUILD_VECTOR: trying to lower new vector: ";
17413 Val.dump(););
17414 Val = LowerBUILD_VECTOR(Val, DAG);
17415 if (Val.getNode())
17416 return DAG.getNode(ISD::BITCAST, DL, VT, Val);
17417 }
17418 }
17419
17420 // If we need to insert a small number of different non-constant elements and
17421 // the vector width is sufficiently large, prefer using DUP with the common
17422 // value and INSERT_VECTOR_ELT for the different lanes. If DUP is preferred,
17423 // skip the constant lane handling below.
17424 bool PreferDUPAndInsert =
17425 !isConstant && NumDifferentLanes >= 1 &&
17426 NumDifferentLanes < ((NumElts - NumUndefLanes) / 2) &&
17427 NumDifferentLanes >= NumConstantLanes;
17428
17429 // If there was only one constant value used and for more than one lane,
17430 // start by splatting that value, then replace the non-constant lanes. This
17431 // is better than the default, which will perform a separate initialization
17432 // for each lane.
17433 if (!PreferDUPAndInsert && NumConstantLanes > 0 && usesOnlyOneConstantValue) {
17434 // Firstly, try to materialize the splat constant.
17435 SDValue Val = DAG.getSplatBuildVector(VT, DL, ConstantValue);
17436 unsigned BitSize = VT.getScalarSizeInBits();
17437 APInt ConstantValueAPInt(1, 0);
17438 if (auto *C = dyn_cast<ConstantSDNode>(ConstantValue))
17439 ConstantValueAPInt = C->getAPIntValue().zextOrTrunc(BitSize);
17440 if (!isNullConstant(ConstantValue) && !isNullFPConstant(ConstantValue) &&
17441 !ConstantValueAPInt.isAllOnes()) {
17442 Val = ConstantBuildVector(Val, DAG, Subtarget);
17443 if (!Val)
17444 // Otherwise, materialize the constant and splat it.
17445 Val = DAG.getNode(AArch64ISD::DUP, DL, VT, ConstantValue);
17446 }
17447
17448 // Now insert the non-constant lanes.
17449 for (unsigned i = 0; i < NumElts; ++i) {
17450 SDValue V = Op.getOperand(i);
17451 SDValue LaneIdx = DAG.getConstant(i, DL, MVT::i64);
17452 if (!isIntOrFPConstant(V) && !V.isUndef())
17453 // Note that type legalization likely mucked about with the VT of the
17454 // source operand, so we may have to convert it here before inserting.
17455 Val = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Val, V, LaneIdx);
17456 }
17457 return Val;
17458 }
17459
17460 // Handle 64-bit constant BUILD_VECTORs by packing them into an i64 immediate.
17461 // This is cheaper than a load if the immediate can be materialized in a few
17462 // mov instructions. This optimization is disabled for big-endian targets for
17463 // now.
17464 if (BVN->isConstant() && VT.isFixedLengthVector() &&
17465 VT.getSizeInBits() == 64 && !DAG.getDataLayout().isBigEndian()) {
17466 const SDLoc DL(Op);
17467 APInt PackedVal(64, 0);
17468 unsigned BitPos = 0;
17469
17470 unsigned EltSizeInBits = VT.getScalarSizeInBits();
17471 for (unsigned i = 0, e = BVN->getNumOperands(); i != e; ++i) {
17472 const SDValue &LaneOp = BVN->getOperand(i);
17473 APInt LaneBits;
17474 if (LaneOp.getOpcode() == ISD::UNDEF)
17475 LaneBits = APInt(EltSizeInBits, 0);
17476 else if (auto *C = dyn_cast<ConstantSDNode>(LaneOp))
17477 LaneBits = C->getAPIntValue();
17478 else if (auto *CFP = dyn_cast<ConstantFPSDNode>(LaneOp))
17479 LaneBits = CFP->getValueAPF().bitcastToAPInt();
17480 else
17481 return SDValue();
17482
17483 PackedVal |= LaneBits.trunc(VT.getScalarSizeInBits()).zext(64) << BitPos;
17484 BitPos += EltSizeInBits;
17485 }
17486
17487 // This optimization kicks in if the number of mov instructions
17488 // is under 2
17490 AArch64_IMM::expandMOVImm(PackedVal.getZExtValue(), 64, Insns);
17491 if (Insns.size() > 2)
17492 return SDValue();
17493
17494 SDValue ScalarConst = DAG.getConstant(PackedVal, DL, MVT::i64);
17495 // Use BITCAST to reinterpret the scalar constant's bits as a vector.
17496 return DAG.getNode(ISD::BITCAST, DL, VT, ScalarConst);
17497 }
17498
17499 // This will generate a load from the constant pool.
17500 if (isConstant) {
17501 LLVM_DEBUG(
17502 dbgs() << "LowerBUILD_VECTOR: all elements are constant, use default "
17503 "expansion\n");
17504 return SDValue();
17505 }
17506
17507 // Detect patterns of a0,a1,a2,a3,b0,b1,b2,b3,c0,c1,c2,c3,d0,d1,d2,d3 from
17508 // v4i32s. This is really a truncate, which we can construct out of (legal)
17509 // concats and truncate nodes.
17511 return M;
17512
17513 // Empirical tests suggest this is rarely worth it for vectors of length <= 2.
17514 if (NumElts >= 4) {
17515 if (SDValue Shuffle = ReconstructShuffle(Op, DAG))
17516 return Shuffle;
17517
17518 if (SDValue Shuffle = ReconstructShuffleWithRuntimeMask(Op, DAG))
17519 return Shuffle;
17520 }
17521
17522 if (PreferDUPAndInsert) {
17523 // First, build a constant vector with the common element.
17525 SDValue NewVector = LowerBUILD_VECTOR(DAG.getBuildVector(VT, DL, Ops), DAG);
17526 // Next, insert the elements that do not match the common value.
17527 for (unsigned I = 0; I < NumElts; ++I)
17528 if (Op.getOperand(I) != Value)
17529 NewVector =
17530 DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, NewVector,
17531 Op.getOperand(I), DAG.getConstant(I, DL, MVT::i64));
17532
17533 return NewVector;
17534 }
17535
17536 // If vector consists of two different values, try to generate two DUPs and
17537 // (CONCAT_VECTORS or VECTOR_SHUFFLE).
17538 if (DifferentValueMap.size() == 2 && NumUndefLanes == 0) {
17540 // Check the consecutive count of the value is the half number of vector
17541 // elements. In this case, we can use CONCAT_VECTORS. For example,
17542 //
17543 // canUseVECTOR_CONCAT = true;
17544 // t22: v16i8 = build_vector t23, t23, t23, t23, t23, t23, t23, t23,
17545 // t24, t24, t24, t24, t24, t24, t24, t24
17546 //
17547 // canUseVECTOR_CONCAT = false;
17548 // t22: v16i8 = build_vector t23, t23, t23, t23, t23, t24, t24, t24,
17549 // t24, t24, t24, t24, t24, t24, t24, t24
17550 bool canUseVECTOR_CONCAT = true;
17551 for (auto Pair : DifferentValueMap) {
17552 // Check different values have same length which is NumElts / 2.
17553 if (Pair.second != NumElts / 2)
17554 canUseVECTOR_CONCAT = false;
17555 Vals.push_back(Pair.first);
17556 }
17557
17558 // If canUseVECTOR_CONCAT is true, we can generate two DUPs and
17559 // CONCAT_VECTORs. For example,
17560 //
17561 // t22: v16i8 = BUILD_VECTOR t23, t23, t23, t23, t23, t23, t23, t23,
17562 // t24, t24, t24, t24, t24, t24, t24, t24
17563 // ==>
17564 // t26: v8i8 = AArch64ISD::DUP t23
17565 // t28: v8i8 = AArch64ISD::DUP t24
17566 // t29: v16i8 = concat_vectors t26, t28
17567 if (canUseVECTOR_CONCAT) {
17568 EVT SubVT = VT.getHalfNumVectorElementsVT(*DAG.getContext());
17569 if (isTypeLegal(SubVT) && SubVT.isVector() &&
17570 SubVT.getVectorNumElements() >= 2) {
17571 SmallVector<SDValue, 8> Ops1(NumElts / 2, Vals[0]);
17572 SmallVector<SDValue, 8> Ops2(NumElts / 2, Vals[1]);
17573 SDValue DUP1 =
17574 LowerBUILD_VECTOR(DAG.getBuildVector(SubVT, DL, Ops1), DAG);
17575 SDValue DUP2 =
17576 LowerBUILD_VECTOR(DAG.getBuildVector(SubVT, DL, Ops2), DAG);
17578 DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, DUP1, DUP2);
17579 return CONCAT_VECTORS;
17580 }
17581 }
17582
17583 // Let's try to generate VECTOR_SHUFFLE. For example,
17584 //
17585 // t24: v8i8 = BUILD_VECTOR t25, t25, t25, t25, t26, t26, t26, t26
17586 // ==>
17587 // t27: v8i8 = BUILD_VECTOR t26, t26, t26, t26, t26, t26, t26, t26
17588 // t28: v8i8 = BUILD_VECTOR t25, t25, t25, t25, t25, t25, t25, t25
17589 // t29: v8i8 = vector_shuffle<0,1,2,3,12,13,14,15> t27, t28
17590 if (NumElts >= 8) {
17591 SmallVector<int, 16> MaskVec;
17592 // Build mask for VECTOR_SHUFLLE.
17593 SDValue FirstLaneVal = Op.getOperand(0);
17594 for (unsigned i = 0; i < NumElts; ++i) {
17595 SDValue Val = Op.getOperand(i);
17596 if (FirstLaneVal == Val)
17597 MaskVec.push_back(i);
17598 else
17599 MaskVec.push_back(i + NumElts);
17600 }
17601
17602 SmallVector<SDValue, 8> Ops1(NumElts, Vals[0]);
17603 SmallVector<SDValue, 8> Ops2(NumElts, Vals[1]);
17604 SDValue VEC1 = DAG.getBuildVector(VT, DL, Ops1);
17605 SDValue VEC2 = DAG.getBuildVector(VT, DL, Ops2);
17607 DAG.getVectorShuffle(VT, DL, VEC1, VEC2, MaskVec);
17608 return VECTOR_SHUFFLE;
17609 }
17610 }
17611
17612 // If all else fails, just use a sequence of INSERT_VECTOR_ELT when we
17613 // know the default expansion would otherwise fall back on something even
17614 // worse. For a vector with one or two non-undef values, that's
17615 // scalar_to_vector for the elements followed by a shuffle (provided the
17616 // shuffle is valid for the target) and materialization element by element
17617 // on the stack followed by a load for everything else.
17618 if (!isConstant && !usesOnlyOneValue) {
17619 LLVM_DEBUG(
17620 dbgs() << "LowerBUILD_VECTOR: alternatives failed, creating sequence "
17621 "of INSERT_VECTOR_ELT\n");
17622
17623 SDValue Vec = DAG.getPOISON(VT);
17624 SDValue Op0 = Op.getOperand(0);
17625 unsigned i = 0;
17626
17627 // Use SCALAR_TO_VECTOR for lane zero to
17628 // a) Avoid a RMW dependency on the full vector register, and
17629 // b) Allow the register coalescer to fold away the copy if the
17630 // value is already in an S or D register, and we're forced to emit an
17631 // INSERT_SUBREG that we can't fold anywhere.
17632 //
17633 // We also allow types like i8 and i16 which are illegal scalar but legal
17634 // vector element types. After type-legalization the inserted value is
17635 // extended (i32) and it is safe to cast them to the vector type by ignoring
17636 // the upper bits of the lowest lane (e.g. v8i8, v4i16).
17637 if (!Op0.isUndef()) {
17638 LLVM_DEBUG(dbgs() << "Creating node for op0, it is not undefined:\n");
17639 Vec = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Op0);
17640 ++i;
17641 }
17642 LLVM_DEBUG({
17643 if (i < NumElts)
17644 dbgs() << "Creating nodes for the other vector elements:\n";
17645 });
17646 for (; i < NumElts; ++i) {
17647 SDValue V = Op.getOperand(i);
17648 if (V.isUndef())
17649 continue;
17650 SDValue LaneIdx = DAG.getConstant(i, DL, MVT::i64);
17651 Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VT, Vec, V, LaneIdx);
17652 }
17653 return Vec;
17654 }
17655
17656 LLVM_DEBUG(
17657 dbgs() << "LowerBUILD_VECTOR: use default expansion, failed to find "
17658 "better alternative\n");
17659 return SDValue();
17660}
17661
17662SDValue AArch64TargetLowering::LowerCONCAT_VECTORS(SDValue Op,
17663 SelectionDAG &DAG) const {
17664 if (useSVEForFixedLengthVectorVT(Op.getValueType(),
17665 !Subtarget->isNeonAvailable()))
17666 return LowerFixedLengthConcatVectorsToSVE(Op, DAG);
17667
17668 assert(Op.getValueType().isScalableVector() &&
17669 isTypeLegal(Op.getValueType()) &&
17670 "Expected legal scalable vector type!");
17671
17672 if (isTypeLegal(Op.getOperand(0).getValueType())) {
17673 unsigned NumOperands = Op->getNumOperands();
17674 assert(NumOperands > 1 && isPowerOf2_32(NumOperands) &&
17675 "Unexpected number of operands in CONCAT_VECTORS");
17676
17677 if (NumOperands == 2)
17678 return Op;
17679
17680 // Concat each pair of subvectors and pack into the lower half of the array.
17681 SmallVector<SDValue> ConcatOps(Op->ops());
17682 while (ConcatOps.size() > 1) {
17683 for (unsigned I = 0, E = ConcatOps.size(); I != E; I += 2) {
17684 SDValue V1 = ConcatOps[I];
17685 SDValue V2 = ConcatOps[I + 1];
17686 EVT SubVT = V1.getValueType();
17687 EVT PairVT = SubVT.getDoubleNumVectorElementsVT(*DAG.getContext());
17688 ConcatOps[I / 2] =
17689 DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Op), PairVT, V1, V2);
17690 }
17691 ConcatOps.resize(ConcatOps.size() / 2);
17692 }
17693 return ConcatOps[0];
17694 }
17695
17696 return SDValue();
17697}
17698
17699SDValue AArch64TargetLowering::LowerINSERT_VECTOR_ELT(SDValue Op,
17700 SelectionDAG &DAG) const {
17701 assert(Op.getOpcode() == ISD::INSERT_VECTOR_ELT && "Unknown opcode!");
17702
17703 if (useSVEForFixedLengthVectorVT(Op.getValueType(),
17704 !Subtarget->isNeonAvailable()))
17705 return LowerFixedLengthInsertVectorElt(Op, DAG);
17706
17707 EVT VT = Op.getValueType();
17708 SDValue Vec = Op.getOperand(0);
17709 SDValue Elt = Op.getOperand(1);
17710 SDValue Idx = Op.getOperand(2);
17711
17712 if (VT.getScalarType() == MVT::i1) {
17713 SDLoc DL(Op);
17714
17715 // MVT::nxv1i8 is not a legal type so widen->insert->shrink instead.
17716 if (VT == MVT::nxv1i1) {
17717 SDValue WidenVec =
17718 DAG.getInsertSubvector(DL, DAG.getPOISON(MVT::nxv2i1), Vec, 0);
17719 SDValue Insert = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, MVT::nxv2i1,
17720 WidenVec, Elt, Idx);
17721 return DAG.getExtractSubvector(DL, MVT::nxv1i1, Insert, 0);
17722 }
17723
17724 EVT PromoteVT = getPromotedVTForPredicate(VT);
17725 SDValue PromoteVec = DAG.getNode(ISD::ANY_EXTEND, DL, PromoteVT, Vec);
17726 if (PromoteVT.getVectorElementType() == MVT::i64)
17727 Elt = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Elt);
17729 PromoteVec, Elt, Idx);
17730 return DAG.getNode(ISD::TRUNCATE, DL, VT, Insert);
17731 }
17732
17733 // Check for non-constant or out of range lane.
17734 ConstantSDNode *CI = dyn_cast<ConstantSDNode>(Idx);
17735 if (!CI || CI->getZExtValue() >= VT.getVectorNumElements())
17736 return SDValue();
17737
17738 return Op;
17739}
17740
17741SDValue
17742AArch64TargetLowering::LowerEXTRACT_VECTOR_ELT(SDValue Op,
17743 SelectionDAG &DAG) const {
17744 assert(Op.getOpcode() == ISD::EXTRACT_VECTOR_ELT && "Unknown opcode!");
17745 EVT VT = Op.getOperand(0).getValueType();
17746
17747 if (VT.getScalarType() == MVT::i1) {
17748 SDLoc DL(Op);
17749 // There are no operations to extend a nxv1i1 predicate to a nxv1i128 vector
17750 // An easy lowering is widening the input predicate to nxv2i1.
17751 if (VT == MVT::nxv1i1) {
17752 SDValue WidenedPred = DAG.getInsertSubvector(
17753 DL, DAG.getPOISON(MVT::nxv2i1), Op->getOperand(0), 0);
17754 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, Op.getValueType(),
17755 WidenedPred, Op.getOperand(1));
17756 }
17757 // We can't directly extract from an SVE predicate; extend it first.
17758 // (This isn't the only possible lowering, but it's straightforward.)
17759 EVT VectorVT = getPromotedVTForPredicate(VT);
17760 SDValue Extend =
17761 DAG.getNode(ISD::ANY_EXTEND, DL, VectorVT, Op.getOperand(0));
17762 MVT ExtractTy = VectorVT == MVT::nxv2i64 ? MVT::i64 : MVT::i32;
17763 SDValue Extract = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, ExtractTy,
17764 Extend, Op.getOperand(1));
17765 return DAG.getAnyExtOrTrunc(Extract, DL, Op.getValueType());
17766 }
17767
17768 if (useSVEForFixedLengthVectorVT(VT, !Subtarget->isNeonAvailable()))
17769 return LowerFixedLengthExtractVectorElt(Op, DAG);
17770
17771 // Check for non-constant or out of range lane.
17772 ConstantSDNode *CI = dyn_cast<ConstantSDNode>(Op.getOperand(1));
17773 if (!CI || CI->getZExtValue() >= VT.getVectorNumElements())
17774 return SDValue();
17775
17776 // Insertion/extraction are legal for V128 types.
17777 if (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 ||
17778 VT == MVT::v2i64 || VT == MVT::v4f32 || VT == MVT::v2f64 ||
17779 VT == MVT::v8f16 || VT == MVT::v8bf16)
17780 return Op;
17781
17782 if (VT != MVT::v8i8 && VT != MVT::v4i16 && VT != MVT::v2i32 &&
17783 VT != MVT::v1i64 && VT != MVT::v2f32 && VT != MVT::v4f16 &&
17784 VT != MVT::v4bf16)
17785 return SDValue();
17786
17787 // For V64 types, we perform extraction by expanding the value
17788 // to a V128 type and perform the extraction on that.
17789 SDLoc DL(Op);
17790 SDValue WideVec = WidenVector(Op.getOperand(0), DAG);
17791 EVT WideTy = WideVec.getValueType();
17792
17793 EVT ExtrTy = WideTy.getVectorElementType();
17794 if (ExtrTy == MVT::i16 || ExtrTy == MVT::i8)
17795 ExtrTy = MVT::i32;
17796
17797 // For extractions, we just return the result directly.
17798 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, ExtrTy, WideVec,
17799 Op.getOperand(1));
17800}
17801
17802SDValue AArch64TargetLowering::LowerEXTRACT_SUBVECTOR(SDValue Op,
17803 SelectionDAG &DAG) const {
17804 EVT VT = Op.getValueType();
17806 "Only cases that extract a fixed length vector are supported!");
17807 EVT InVT = Op.getOperand(0).getValueType();
17808
17809 // If we don't have legal types yet, do nothing
17810 if (!isTypeLegal(InVT))
17811 return SDValue();
17812
17813 if (InVT.is128BitVector()) {
17814 assert(VT.is64BitVector() && "Extracting unexpected vector type!");
17815 unsigned Idx = Op.getConstantOperandVal(1);
17816
17817 // This will get lowered to an appropriate EXTRACT_SUBREG in ISel.
17818 if (Idx == 0)
17819 return Op;
17820
17821 // If this is extracting the upper 64-bits of a 128-bit vector, we match
17822 // that directly.
17823 if (Idx * InVT.getScalarSizeInBits() == 64 && Subtarget->isNeonAvailable())
17824 return Op;
17825 }
17826
17827 if (InVT.isScalableVector() ||
17828 useSVEForFixedLengthVectorVT(InVT, !Subtarget->isNeonAvailable())) {
17829 SDLoc DL(Op);
17830 SDValue Vec = Op.getOperand(0);
17831 SDValue Idx = Op.getOperand(1);
17832
17833 EVT PackedVT = getPackedSVEVectorVT(InVT.getVectorElementType());
17834 if (PackedVT != InVT) {
17835 // Pack input into the bottom part of an SVE register and try again.
17836 SDValue Container =
17837 DAG.getInsertSubvector(DL, DAG.getPOISON(PackedVT), Vec, 0);
17838 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Container, Idx);
17839 }
17840
17841 // This will get matched by custom code during ISelDAGToDAG.
17842 if (isNullConstant(Idx))
17843 return Op;
17844
17845 assert(InVT.isScalableVector() && "Unexpected vector type!");
17846 // Move requested subvector to the start of the vector and try again.
17847 SDValue Splice =
17848 DAG.getNode(ISD::VECTOR_SPLICE_LEFT, DL, InVT, Vec, Vec, Idx);
17849 return convertFromScalableVector(DAG, VT, Splice);
17850 }
17851
17852 return SDValue();
17853}
17854
17855SDValue AArch64TargetLowering::LowerINSERT_SUBVECTOR(SDValue Op,
17856 SelectionDAG &DAG) const {
17857 assert(Op.getValueType().isScalableVector() &&
17858 "Only expect to lower inserts into scalable vectors!");
17859
17860 EVT InVT = Op.getOperand(1).getValueType();
17861 unsigned Idx = Op.getConstantOperandVal(2);
17862
17863 SDValue Vec0 = Op.getOperand(0);
17864 SDValue Vec1 = Op.getOperand(1);
17865 SDLoc DL(Op);
17866 EVT VT = Op.getValueType();
17867
17868 if (InVT.isScalableVector()) {
17869 if (!isTypeLegal(VT))
17870 return SDValue();
17871
17872 // Break down insert_subvector into simpler parts.
17873 if (VT.getVectorElementType() == MVT::i1) {
17874 unsigned NumElts = VT.getVectorMinNumElements();
17875 EVT HalfVT = VT.getHalfNumVectorElementsVT(*DAG.getContext());
17876
17877 SDValue Lo, Hi;
17878 Lo = DAG.getExtractSubvector(DL, HalfVT, Vec0, 0);
17879 Hi = DAG.getExtractSubvector(DL, HalfVT, Vec0, NumElts / 2);
17880 if (Idx < (NumElts / 2))
17881 Lo = DAG.getInsertSubvector(DL, Lo, Vec1, Idx);
17882 else
17883 Hi = DAG.getInsertSubvector(DL, Hi, Vec1, Idx - (NumElts / 2));
17884
17885 return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi);
17886 }
17887
17888 // We can select these directly.
17889 if (isTypeLegal(InVT) && Vec0.isUndef())
17890 return Op;
17891
17892 // Ensure the subvector is half the size of the main vector.
17893 if (VT.getVectorElementCount() != (InVT.getVectorElementCount() * 2))
17894 return SDValue();
17895
17896 // Here narrow and wide refers to the vector element types. After "casting"
17897 // both vectors must have the same bit length and so because the subvector
17898 // has fewer elements, those elements need to be bigger.
17899 EVT NarrowVT = getPackedSVEVectorVT(VT.getVectorElementCount());
17900 EVT WideVT = getPackedSVEVectorVT(InVT.getVectorElementCount());
17901
17902 // NOP cast operands to the largest legal vector of the same element count.
17903 if (VT.isFloatingPoint()) {
17904 Vec0 = getSVESafeBitCast(NarrowVT, Vec0, DAG);
17905 Vec1 = getSVESafeBitCast(NarrowVT, Vec1, DAG);
17906 } else {
17907 // Legal integer vectors are already their largest so Vec0 is fine as is.
17908 Vec1 = DAG.getNode(ISD::ANY_EXTEND, DL, WideVT, Vec1);
17909 Vec1 = DAG.getNode(AArch64ISD::NVCAST, DL, NarrowVT, Vec1);
17910 }
17911
17912 // To replace the top/bottom half of vector V with vector SubV we widen the
17913 // preserved half of V, concatenate this to SubV (the order depending on the
17914 // half being replaced) and then narrow the result.
17915 SDValue Narrow;
17916 if (Idx == 0) {
17917 SDValue HiVec0 = DAG.getNode(AArch64ISD::UUNPKHI, DL, WideVT, Vec0);
17918 HiVec0 = DAG.getNode(AArch64ISD::NVCAST, DL, NarrowVT, HiVec0);
17919 Narrow = DAG.getNode(AArch64ISD::UZP1, DL, NarrowVT, Vec1, HiVec0);
17920 } else {
17921 assert(Idx == InVT.getVectorMinNumElements() &&
17922 "Invalid subvector index!");
17923 SDValue LoVec0 = DAG.getNode(AArch64ISD::UUNPKLO, DL, WideVT, Vec0);
17924 LoVec0 = DAG.getNode(AArch64ISD::NVCAST, DL, NarrowVT, LoVec0);
17925 Narrow = DAG.getNode(AArch64ISD::UZP1, DL, NarrowVT, LoVec0, Vec1);
17926 }
17927
17928 return getSVESafeBitCast(VT, Narrow, DAG);
17929 }
17930
17931 if (Idx == 0 && isPackedVectorType(VT, DAG)) {
17932 // This will be matched by custom code during ISelDAGToDAG.
17933 if (Vec0.isUndef())
17934 return Op;
17935
17936 std::optional<unsigned> PredPattern =
17938 auto PredTy = VT.changeVectorElementType(*DAG.getContext(), MVT::i1);
17939 SDValue PTrue = getPTrue(DAG, DL, PredTy, *PredPattern);
17940 SDValue ScalableVec1 = convertToScalableVector(DAG, VT, Vec1);
17941 return DAG.getNode(ISD::VSELECT, DL, VT, PTrue, ScalableVec1, Vec0);
17942 }
17943
17944 return SDValue();
17945}
17946
17947static bool isPow2Splat(SDValue Op, uint64_t &SplatVal, bool &Negated) {
17948 if (Op.getOpcode() != AArch64ISD::DUP &&
17949 Op.getOpcode() != ISD::SPLAT_VECTOR &&
17950 Op.getOpcode() != ISD::BUILD_VECTOR)
17951 return false;
17952
17953 if (Op.getOpcode() == ISD::BUILD_VECTOR &&
17954 !isAllConstantBuildVector(Op, SplatVal))
17955 return false;
17956
17957 if (Op.getOpcode() != ISD::BUILD_VECTOR &&
17958 !isa<ConstantSDNode>(Op->getOperand(0)))
17959 return false;
17960
17961 SplatVal = Op->getConstantOperandVal(0);
17962 if (Op.getValueType().getVectorElementType() != MVT::i64)
17963 SplatVal = (int32_t)SplatVal;
17964
17965 Negated = false;
17966 if (isPowerOf2_64(SplatVal))
17967 return true;
17968
17969 Negated = true;
17970 if (isPowerOf2_64(-SplatVal)) {
17971 SplatVal = -SplatVal;
17972 return true;
17973 }
17974
17975 return false;
17976}
17977
17978SDValue AArch64TargetLowering::LowerDIV(SDValue Op, SelectionDAG &DAG) const {
17979 EVT VT = Op.getValueType();
17980 SDLoc DL(Op);
17981
17982 if (VT.isFixedLengthVector() && Subtarget->isSVEorStreamingSVEAvailable())
17983 return LowerFixedLengthVectorIntDivideToSVE(Op, DAG);
17984
17985 unsigned Opc = Op.getOpcode();
17986 assert((Opc == ISD::SDIV || Opc == ISD::UDIV) && "Expected a DIV opcode.");
17987 assert(VT.isScalableVector() && "Expected a scalable vector.");
17988 bool Signed = Opc == ISD::SDIV;
17989
17990 bool Negated;
17991 uint64_t SplatVal;
17992 // NOTE: SRAD cannot be used to represent sdiv-by-one.
17993 if (Signed && isPow2Splat(Op.getOperand(1), SplatVal, Negated) &&
17994 SplatVal > 1) {
17996 SDValue Res =
17997 DAG.getNode(AArch64ISD::ASRD_MERGE_OP1, DL, VT, Pg, Op->getOperand(0),
17998 DAG.getTargetConstant(Log2_64(SplatVal), DL, MVT::i32));
17999 if (Negated)
18000 Res = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), Res);
18001
18002 return Res;
18003 }
18004
18005 if (VT == MVT::nxv4i32 || VT == MVT::nxv2i64) {
18006 unsigned MaskedOpcode = Signed ? ISD::MASKED_SDIV : ISD::MASKED_UDIV;
18007 return DAG.getNode(MaskedOpcode, DL, VT, Op.getOperand(0), Op.getOperand(1),
18008 getPredicateForVector(DAG, DL, VT));
18009 }
18010
18011 // SVE doesn't have i8 and i16 DIV operations; widen them to 32-bit
18012 // operations, and truncate the result.
18013 EVT WidenedVT;
18014 if (VT == MVT::nxv16i8)
18015 WidenedVT = MVT::nxv8i16;
18016 else if (VT == MVT::nxv8i16)
18017 WidenedVT = MVT::nxv4i32;
18018 else
18019 llvm_unreachable("Unexpected Custom DIV operation");
18020
18021 unsigned UnpkLo = Signed ? AArch64ISD::SUNPKLO : AArch64ISD::UUNPKLO;
18022 unsigned UnpkHi = Signed ? AArch64ISD::SUNPKHI : AArch64ISD::UUNPKHI;
18023 SDValue Op0Lo = DAG.getNode(UnpkLo, DL, WidenedVT, Op.getOperand(0));
18024 SDValue Op1Lo = DAG.getNode(UnpkLo, DL, WidenedVT, Op.getOperand(1));
18025 SDValue Op0Hi = DAG.getNode(UnpkHi, DL, WidenedVT, Op.getOperand(0));
18026 SDValue Op1Hi = DAG.getNode(UnpkHi, DL, WidenedVT, Op.getOperand(1));
18027 SDValue ResultLo = DAG.getNode(Opc, DL, WidenedVT, Op0Lo, Op1Lo);
18028 SDValue ResultHi = DAG.getNode(Opc, DL, WidenedVT, Op0Hi, Op1Hi);
18029 SDValue ResultLoCast = DAG.getNode(AArch64ISD::NVCAST, DL, VT, ResultLo);
18030 SDValue ResultHiCast = DAG.getNode(AArch64ISD::NVCAST, DL, VT, ResultHi);
18031 return DAG.getNode(AArch64ISD::UZP1, DL, VT, ResultLoCast, ResultHiCast);
18032}
18033
18034bool AArch64TargetLowering::shouldExpandBuildVectorWithShuffles(
18035 EVT VT, unsigned DefinedValues) const {
18036 if (!Subtarget->isNeonAvailable())
18037 return false;
18039}
18040
18042 // Currently no fixed length shuffles that require SVE are legal.
18043 if (useSVEForFixedLengthVectorVT(VT, !Subtarget->isNeonAvailable()))
18044 return false;
18045
18046 if (VT.getVectorNumElements() == 4 &&
18047 (VT.is128BitVector() || VT.is64BitVector())) {
18048 unsigned Cost = getPerfectShuffleCost(M);
18049 if (Cost <= 1)
18050 return true;
18051 }
18052
18053 bool DummyBool;
18054 int DummyInt;
18055 unsigned DummyUnsigned;
18056
18057 unsigned EltSize = VT.getScalarSizeInBits();
18058 unsigned NumElts = VT.getVectorNumElements();
18060 isREVMask(M, EltSize, NumElts, 64) ||
18061 isREVMask(M, EltSize, NumElts, 32) ||
18062 isREVMask(M, EltSize, NumElts, 16) ||
18063 isEXTMask(M, VT, DummyBool, DummyUnsigned) ||
18064 isSingletonEXTMask(M, VT, DummyUnsigned) ||
18065 isTRNMask(M, NumElts, DummyUnsigned, DummyUnsigned) ||
18066 isUZPMask(M, NumElts, DummyUnsigned) ||
18067 isZIPMask(M, NumElts, DummyUnsigned, DummyUnsigned) ||
18068 isTRN_v_undef_Mask(M, NumElts, DummyUnsigned) ||
18069 isUZP_v_undef_Mask(M, NumElts, DummyUnsigned) ||
18070 isZIP_v_undef_Mask(M, NumElts, DummyUnsigned) ||
18071 isINSMask(M, NumElts, DummyBool, DummyInt) ||
18072 isConcatMask(M, VT, VT.getSizeInBits() == 128));
18073}
18074
18076 EVT VT) const {
18077 // Just delegate to the generic legality, clear masks aren't special.
18078 return isShuffleMaskLegal(M, VT);
18079}
18080
18081/// getVShiftImm - Check if this is a valid build_vector for the immediate
18082/// operand of a vector shift operation, where all the elements of the
18083/// build_vector must have the same constant integer value.
18084static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt) {
18085 // Ignore bit_converts.
18086 while (Op.getOpcode() == ISD::BITCAST)
18087 Op = Op.getOperand(0);
18089 APInt SplatBits, SplatUndef;
18090 unsigned SplatBitSize;
18091 bool HasAnyUndefs;
18092 if (!BVN || !BVN->isConstantSplat(SplatBits, SplatUndef, SplatBitSize,
18093 HasAnyUndefs, ElementBits) ||
18094 SplatBitSize > ElementBits)
18095 return false;
18096 Cnt = SplatBits.getSExtValue();
18097 return true;
18098}
18099
18100/// isVShiftLImm - Check if this is a valid build_vector for the immediate
18101/// operand of a vector shift left operation. That value must be in the range:
18102/// 0 <= Value < ElementBits for a left shift; or
18103/// 0 <= Value <= ElementBits for a long left shift.
18104static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt) {
18105 assert(VT.isVector() && "vector shift count is not a vector type");
18106 int64_t ElementBits = VT.getScalarSizeInBits();
18107 if (!getVShiftImm(Op, ElementBits, Cnt))
18108 return false;
18109 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
18110}
18111
18112/// isVShiftRImm - Check if this is a valid build_vector for the immediate
18113/// operand of a vector shift right operation. The value must be in the range:
18114/// 1 <= Value <= ElementBits for a right shift; or
18115static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt) {
18116 assert(VT.isVector() && "vector shift count is not a vector type");
18117 int64_t ElementBits = VT.getScalarSizeInBits();
18118 if (!getVShiftImm(Op, ElementBits, Cnt))
18119 return false;
18120 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
18121}
18122
18123SDValue AArch64TargetLowering::LowerTRUNCATE(SDValue Op,
18124 SelectionDAG &DAG) const {
18125 EVT VT = Op.getValueType();
18126
18127 if (VT.getScalarType() == MVT::i1) {
18128 // Lower i1 truncate to `(x & 1) != 0`.
18129 SDLoc DL(Op);
18130 EVT OpVT = Op.getOperand(0).getValueType();
18131 SDValue Zero = DAG.getConstant(0, DL, OpVT);
18132 SDValue One = DAG.getConstant(1, DL, OpVT);
18133 SDValue And = DAG.getNode(ISD::AND, DL, OpVT, Op.getOperand(0), One);
18134 return DAG.getSetCC(DL, VT, And, Zero, ISD::SETNE);
18135 }
18136
18137 if (!VT.isVector() || VT.isScalableVector())
18138 return SDValue();
18139
18140 if (useSVEForFixedLengthVectorVT(Op.getOperand(0).getValueType(),
18141 !Subtarget->isNeonAvailable()))
18142 return LowerFixedLengthVectorTruncateToSVE(Op, DAG);
18143
18144 // We can select these directly.
18145 if (VT.is64BitVector() && Op.getOperand(0).getValueType().is128BitVector())
18146 return Op;
18147
18148 return SDValue();
18149}
18150
18151// Check if we can we lower this SRL to a rounding shift instruction. ResVT is
18152// possibly a truncated type, it tells how many bits of the value are to be
18153// used.
18155 SelectionDAG &DAG,
18156 unsigned &ShiftValue,
18157 SDValue &RShOperand) {
18158 if (Shift->getOpcode() != ISD::SRL)
18159 return false;
18160
18161 EVT VT = Shift.getValueType();
18162 assert(VT.isScalableVT());
18163
18164 auto ShiftOp1 =
18166 if (!ShiftOp1)
18167 return false;
18168
18169 ShiftValue = ShiftOp1->getZExtValue();
18170 if (ShiftValue < 1 || ShiftValue > ResVT.getScalarSizeInBits())
18171 return false;
18172
18173 SDValue Add = Shift->getOperand(0);
18174 if (Add->getOpcode() != ISD::ADD || !Add->hasOneUse())
18175 return false;
18176
18178 "ResVT must be truncated or same type as the shift.");
18179 // Check if an overflow can lead to incorrect results.
18180 uint64_t ExtraBits = VT.getScalarSizeInBits() - ResVT.getScalarSizeInBits();
18181 if (ShiftValue > ExtraBits && !Add->getFlags().hasNoUnsignedWrap())
18182 return false;
18183
18184 auto AddOp1 =
18186 if (!AddOp1)
18187 return false;
18188 uint64_t AddValue = AddOp1->getZExtValue();
18189 if (AddValue != 1ULL << (ShiftValue - 1))
18190 return false;
18191
18192 RShOperand = Add->getOperand(0);
18193 return true;
18194}
18195
18196SDValue AArch64TargetLowering::LowerVectorSRA_SRL_SHL(SDValue Op,
18197 SelectionDAG &DAG) const {
18198 EVT VT = Op.getValueType();
18199 SDLoc DL(Op);
18200 int64_t Cnt;
18201
18202 if (!Op.getOperand(1).getValueType().isVector())
18203 return Op;
18204 unsigned EltSize = VT.getScalarSizeInBits();
18205
18206 switch (Op.getOpcode()) {
18207 case ISD::SHL:
18208 if (VT.isScalableVector() ||
18209 useSVEForFixedLengthVectorVT(VT, !Subtarget->isNeonAvailable()))
18210 return LowerToPredicatedOp(Op, DAG, AArch64ISD::SHL_PRED);
18211
18212 if (isVShiftLImm(Op.getOperand(1), VT, false, Cnt) && Cnt < EltSize)
18213 return DAG.getNode(AArch64ISD::VSHL, DL, VT, Op.getOperand(0),
18214 DAG.getTargetConstant(Cnt, DL, MVT::i32));
18215 return DAG.getNode(
18217 DAG.getTargetConstant(Intrinsic::aarch64_neon_ushl, DL, MVT::i32),
18218 Op.getOperand(0), Op.getOperand(1));
18219 case ISD::SRA:
18220 case ISD::SRL:
18221 if (VT.isScalableVector() &&
18222 (Subtarget->hasSVE2() ||
18223 (Subtarget->hasSME() && Subtarget->isStreaming()))) {
18224 SDValue RShOperand;
18225 unsigned ShiftValue;
18226 if (canLowerSRLToRoundingShiftForVT(Op, VT, DAG, ShiftValue, RShOperand))
18227 return DAG.getNode(AArch64ISD::URSHR_I_PRED, DL, VT,
18228 getPredicateForVector(DAG, DL, VT), RShOperand,
18229 DAG.getTargetConstant(ShiftValue, DL, MVT::i32));
18230 }
18231
18232 if (VT.isScalableVector() ||
18233 useSVEForFixedLengthVectorVT(VT, !Subtarget->isNeonAvailable())) {
18234 unsigned Opc = Op.getOpcode() == ISD::SRA ? AArch64ISD::SRA_PRED
18235 : AArch64ISD::SRL_PRED;
18236 return LowerToPredicatedOp(Op, DAG, Opc);
18237 }
18238
18239 // Right shift immediate
18240 if (isVShiftRImm(Op.getOperand(1), VT, false, Cnt) && Cnt < EltSize) {
18241 unsigned Opc =
18242 (Op.getOpcode() == ISD::SRA) ? AArch64ISD::VASHR : AArch64ISD::VLSHR;
18243 return DAG.getNode(Opc, DL, VT, Op.getOperand(0),
18244 DAG.getTargetConstant(Cnt, DL, MVT::i32),
18245 Op->getFlags());
18246 }
18247
18248 // Right shift register. Note, there is not a shift right register
18249 // instruction, but the shift left register instruction takes a signed
18250 // value, where negative numbers specify a right shift.
18251 unsigned Opc = (Op.getOpcode() == ISD::SRA) ? Intrinsic::aarch64_neon_sshl
18252 : Intrinsic::aarch64_neon_ushl;
18253 // negate the shift amount
18254 SDValue NegShift = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT),
18255 Op.getOperand(1));
18256 SDValue NegShiftLeft =
18258 DAG.getConstant(Opc, DL, MVT::i32), Op.getOperand(0),
18259 NegShift);
18260 return NegShiftLeft;
18261 }
18262
18263 llvm_unreachable("unexpected shift opcode");
18264}
18265
18266SDValue AArch64TargetLowering::LowerVSETCC(SDValue Op,
18267 SelectionDAG &DAG) const {
18268 if (Op.getValueType().isScalableVector())
18269 return LowerToPredicatedOp(Op, DAG, AArch64ISD::SETCC_MERGE_ZERO);
18270
18271 if (useSVEForFixedLengthVectorVT(Op.getOperand(0).getValueType(),
18272 !Subtarget->isNeonAvailable()))
18273 return LowerFixedLengthVectorSetccToSVE(Op, DAG);
18274
18275 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
18276 SDValue LHS = Op.getOperand(0);
18277 SDValue RHS = Op.getOperand(1);
18278 EVT CmpVT = LHS.getValueType().changeVectorElementTypeToInteger();
18279 SDLoc DL(Op);
18280
18281 if (LHS.getValueType().getVectorElementType().isInteger())
18282 return Op;
18283
18284 assert(((!Subtarget->hasFullFP16() &&
18285 LHS.getValueType().getVectorElementType() != MVT::f16) ||
18286 LHS.getValueType().getVectorElementType() != MVT::bf16 ||
18287 LHS.getValueType().getVectorElementType() != MVT::f128) &&
18288 "Unexpected type!");
18289
18290 // Lower isnan(x) | isnan(never-nan) to x != x.
18291 // Lower !isnan(x) & !isnan(never-nan) to x == x.
18292 if (CC == ISD::SETUO || CC == ISD::SETO) {
18293 bool OneNaN = false;
18294 if (LHS == RHS) {
18295 OneNaN = true;
18296 } else if (DAG.isKnownNeverNaN(RHS)) {
18297 OneNaN = true;
18298 RHS = LHS;
18299 } else if (DAG.isKnownNeverNaN(LHS)) {
18300 OneNaN = true;
18301 LHS = RHS;
18302 }
18303 if (OneNaN) {
18304 CC = CC == ISD::SETUO ? ISD::SETUNE : ISD::SETOEQ;
18305 }
18306 }
18307
18308 // Unfortunately, the mapping of LLVM FP CC's onto AArch64 CC's isn't totally
18309 // clean. Some of them require two branches to implement.
18310 AArch64CC::CondCode CC1, CC2;
18311 bool ShouldInvert;
18312 changeVectorFPCCToAArch64CC(CC, CC1, CC2, ShouldInvert);
18313
18314 bool NoNaNs = Op->getFlags().hasNoNaNs();
18315 SDValue Cmp = emitVectorComparison(LHS, RHS, CC1, NoNaNs, CmpVT, DL, DAG);
18316 if (!Cmp.getNode())
18317 return SDValue();
18318
18319 if (CC2 != AArch64CC::AL) {
18320 SDValue Cmp2 = emitVectorComparison(LHS, RHS, CC2, NoNaNs, CmpVT, DL, DAG);
18321 if (!Cmp2.getNode())
18322 return SDValue();
18323
18324 Cmp = DAG.getNode(ISD::OR, DL, CmpVT, Cmp, Cmp2);
18325 }
18326
18327 Cmp = DAG.getSExtOrTrunc(Cmp, DL, Op.getValueType());
18328
18329 if (ShouldInvert)
18330 Cmp = DAG.getNOT(DL, Cmp, Cmp.getValueType());
18331
18332 return Cmp;
18333}
18334
18335static SDValue getReductionSDNode(unsigned Op, SDLoc DL, SDValue ScalarOp,
18336 SelectionDAG &DAG) {
18337 SDValue VecOp = ScalarOp.getOperand(0);
18338 auto Rdx = DAG.getNode(Op, DL, VecOp.getSimpleValueType(), VecOp);
18339 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, ScalarOp.getValueType(), Rdx,
18340 DAG.getConstant(0, DL, MVT::i64));
18341}
18342
18343static SDValue getVectorBitwiseReduce(unsigned Opcode, SDValue Vec, EVT VT,
18344 SDLoc DL, SelectionDAG &DAG) {
18345 unsigned ScalarOpcode;
18346 switch (Opcode) {
18347 case ISD::VECREDUCE_AND:
18348 ScalarOpcode = ISD::AND;
18349 break;
18350 case ISD::VECREDUCE_OR:
18351 ScalarOpcode = ISD::OR;
18352 break;
18353 case ISD::VECREDUCE_XOR:
18354 ScalarOpcode = ISD::XOR;
18355 break;
18356 default:
18357 llvm_unreachable("Expected bitwise vector reduction");
18358 return SDValue();
18359 }
18360
18361 EVT VecVT = Vec.getValueType();
18362 assert(VecVT.isFixedLengthVector() && VecVT.isPow2VectorType() &&
18363 "Expected power-of-2 length vector");
18364
18365 EVT ElemVT = VecVT.getVectorElementType();
18366
18367 SDValue Result;
18368 unsigned NumElems = VecVT.getVectorNumElements();
18369
18370 // Special case for boolean reductions
18371 if (ElemVT == MVT::i1) {
18372 // Split large vectors into smaller ones
18373 if (NumElems > 16) {
18374 SDValue Lo, Hi;
18375 std::tie(Lo, Hi) = DAG.SplitVector(Vec, DL);
18376 EVT HalfVT = Lo.getValueType();
18377 SDValue HalfVec = DAG.getNode(ScalarOpcode, DL, HalfVT, Lo, Hi);
18378 return getVectorBitwiseReduce(Opcode, HalfVec, VT, DL, DAG);
18379 }
18380
18381 // Results of setcc operations get widened to 128 bits if their input
18382 // operands are 128 bits wide, otherwise vectors that are less than 64 bits
18383 // get widened to neatly fit a 64 bit register, so e.g. <4 x i1> gets
18384 // lowered to either <4 x i16> or <4 x i32>. Sign extending to this element
18385 // size leads to the best codegen, since e.g. setcc results might need to be
18386 // truncated otherwise.
18387 unsigned ExtendedWidth = 64;
18388 if (Vec.getOpcode() == ISD::SETCC &&
18389 Vec.getOperand(0).getValueSizeInBits() >= 128) {
18390 ExtendedWidth = 128;
18391 }
18392 EVT ExtendedVT = MVT::getIntegerVT(std::max(ExtendedWidth / NumElems, 8u));
18393
18394 // any_ext doesn't work with umin/umax, so only use it for uadd.
18395 unsigned ExtendOp =
18396 ScalarOpcode == ISD::XOR ? ISD::ANY_EXTEND : ISD::SIGN_EXTEND;
18397 SDValue Extended = DAG.getNode(
18398 ExtendOp, DL,
18399 VecVT.changeVectorElementType(*DAG.getContext(), ExtendedVT), Vec);
18400 // The uminp/uminv and umaxp/umaxv instructions don't have .2d variants, so
18401 // in that case we bitcast the sign extended values from v2i64 to v4i32
18402 // before reduction for optimal code generation.
18403 if ((ScalarOpcode == ISD::AND || ScalarOpcode == ISD::OR) &&
18404 NumElems == 2 && ExtendedWidth == 128) {
18405 Extended = DAG.getBitcast(MVT::v4i32, Extended);
18406 ExtendedVT = MVT::i32;
18407 }
18408 switch (ScalarOpcode) {
18409 case ISD::AND:
18410 Result = DAG.getNode(ISD::VECREDUCE_UMIN, DL, ExtendedVT, Extended);
18411 break;
18412 case ISD::OR:
18413 Result = DAG.getNode(ISD::VECREDUCE_UMAX, DL, ExtendedVT, Extended);
18414 break;
18415 case ISD::XOR:
18416 Result = DAG.getNode(ISD::VECREDUCE_ADD, DL, ExtendedVT, Extended);
18417 break;
18418 default:
18419 llvm_unreachable("Unexpected Opcode");
18420 }
18421
18422 Result = DAG.getAnyExtOrTrunc(Result, DL, MVT::i1);
18423 } else {
18424 // Iteratively split the vector in half and combine using the bitwise
18425 // operation until it fits in a 64 bit register.
18426 while (VecVT.getSizeInBits() > 64) {
18427 SDValue Lo, Hi;
18428 std::tie(Lo, Hi) = DAG.SplitVector(Vec, DL);
18429 VecVT = Lo.getValueType();
18430 NumElems = VecVT.getVectorNumElements();
18431 Vec = DAG.getNode(ScalarOpcode, DL, VecVT, Lo, Hi);
18432 }
18433
18434 EVT ScalarVT = EVT::getIntegerVT(*DAG.getContext(), VecVT.getSizeInBits());
18435
18436 // Do the remaining work on a scalar since it allows the code generator to
18437 // combine the shift and bitwise operation into one instruction and since
18438 // integer instructions can have higher throughput than vector instructions.
18439 SDValue Scalar = DAG.getBitcast(ScalarVT, Vec);
18440
18441 // Iteratively combine the lower and upper halves of the scalar using the
18442 // bitwise operation, halving the relevant region of the scalar in each
18443 // iteration, until the relevant region is just one element of the original
18444 // vector.
18445 for (unsigned Shift = NumElems / 2; Shift > 0; Shift /= 2) {
18446 SDValue ShiftAmount =
18447 DAG.getConstant(Shift * ElemVT.getSizeInBits(), DL, MVT::i64);
18448 SDValue Shifted =
18449 DAG.getNode(ISD::SRL, DL, ScalarVT, Scalar, ShiftAmount);
18450 Scalar = DAG.getNode(ScalarOpcode, DL, ScalarVT, Scalar, Shifted);
18451 }
18452
18453 Result = DAG.getAnyExtOrTrunc(Scalar, DL, ElemVT);
18454 }
18455
18456 return DAG.getAnyExtOrTrunc(Result, DL, VT);
18457}
18458
18459SDValue AArch64TargetLowering::LowerVECREDUCE(SDValue Op,
18460 SelectionDAG &DAG) const {
18461 SDLoc DL(Op);
18462 SDValue Src = Op.getOperand(0);
18463 EVT SrcVT = Src.getValueType();
18464
18465 // Scalarize v2f16 to turn it into a faddp. This will be more efficient than
18466 // widening by inserting zeroes.
18467 if (Subtarget->hasFullFP16() && Op.getOpcode() == ISD::VECREDUCE_FADD &&
18468 SrcVT == MVT::v2f16) {
18469 return DAG.getNode(ISD::FADD, DL, MVT::f16,
18470 DAG.getExtractVectorElt(DL, MVT::f16, Src, 0),
18471 DAG.getExtractVectorElt(DL, MVT::f16, Src, 1));
18472 }
18473
18474 // Try lowering the reduction to SVE. This will fail for NEON reductions where
18475 // SVE is not preferred.
18476 if (SDValue Result = LowerReductionToSVE(Op, DAG))
18477 return Result;
18478
18479 // Lower NEON reductions.
18480 switch (Op.getOpcode()) {
18481 case ISD::VECREDUCE_AND:
18482 case ISD::VECREDUCE_OR:
18483 case ISD::VECREDUCE_XOR:
18484 return getVectorBitwiseReduce(Op.getOpcode(), Op.getOperand(0),
18485 Op.getValueType(), DL, DAG);
18486 case ISD::VECREDUCE_ADD:
18487 return getReductionSDNode(AArch64ISD::UADDV, DL, Op, DAG);
18489 return getReductionSDNode(AArch64ISD::SMAXV, DL, Op, DAG);
18491 return getReductionSDNode(AArch64ISD::SMINV, DL, Op, DAG);
18493 return getReductionSDNode(AArch64ISD::UMAXV, DL, Op, DAG);
18495 return getReductionSDNode(AArch64ISD::UMINV, DL, Op, DAG);
18496 default:
18497 llvm_unreachable("Unhandled reduction");
18498 }
18499}
18500
18501SDValue AArch64TargetLowering::LowerVECREDUCE_MUL(SDValue Op,
18502 SelectionDAG &DAG) const {
18503 SDLoc DL(Op);
18504 SDValue Src = Op.getOperand(0);
18505 EVT SrcVT = Src.getValueType();
18506 assert(SrcVT.isScalableVector() && "Unexpected operand type!");
18507
18508 SDVTList SrcVTs = DAG.getVTList(SrcVT, SrcVT);
18509 unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Op.getOpcode());
18510 SDValue Identity = DAG.getIdentityElement(BaseOpc, DL, SrcVT, Op->getFlags());
18511
18512 // Whilst we don't know the size of the vector we do know the maximum size so
18513 // can perform a tree reduction with an identity vector, which means once we
18514 // arrive at the result the remaining stages (when the vector is smaller than
18515 // the maximum) have no affect.
18516
18518 unsigned Stages = llvm::Log2_32(Segments * SrcVT.getVectorMinNumElements());
18519
18520 for (unsigned I = 0; I < Stages; ++I) {
18521 Src = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL, SrcVTs, Src, Identity);
18522 Src = DAG.getNode(BaseOpc, DL, SrcVT, Src.getValue(0), Src.getValue(1));
18523 }
18524
18525 return DAG.getExtractVectorElt(DL, Op.getValueType(), Src, 0);
18526}
18527
18528SDValue AArch64TargetLowering::LowerATOMIC_LOAD_AND(SDValue Op,
18529 SelectionDAG &DAG) const {
18530 auto &Subtarget = DAG.getSubtarget<AArch64Subtarget>();
18531 // No point replacing if we don't have the relevant instruction/libcall anyway
18532 if (!Subtarget.hasLSE() && !Subtarget.outlineAtomics())
18533 return SDValue();
18534
18535 // LSE has an atomic load-clear instruction, but not a load-and.
18536 SDLoc DL(Op);
18537 MVT VT = Op.getSimpleValueType();
18538 assert(VT != MVT::i128 && "Handled elsewhere, code replicated.");
18539 SDValue RHS = Op.getOperand(2);
18540 AtomicSDNode *AN = cast<AtomicSDNode>(Op.getNode());
18541 RHS = DAG.getNode(ISD::XOR, DL, VT, DAG.getAllOnesConstant(DL, VT), RHS);
18542 return DAG.getAtomic(ISD::ATOMIC_LOAD_CLR, DL, AN->getMemoryVT(),
18543 Op.getOperand(0), Op.getOperand(1), RHS,
18544 AN->getMemOperand());
18545}
18546
18547SDValue
18548AArch64TargetLowering::LowerWindowsDYNAMIC_STACKALLOC(SDValue Op,
18549 SelectionDAG &DAG) const {
18550
18551 SDLoc DL(Op);
18552 // Get the inputs.
18553 SDNode *Node = Op.getNode();
18554 SDValue Chain = Op.getOperand(0);
18555 SDValue Size = Op.getOperand(1);
18556 MaybeAlign Align =
18557 cast<ConstantSDNode>(Op.getOperand(2))->getMaybeAlignValue();
18558 EVT VT = Node->getValueType(0);
18559
18561 "no-stack-arg-probe")) {
18562 SDValue SP = DAG.getCopyFromReg(Chain, DL, AArch64::SP, MVT::i64);
18563 Chain = SP.getValue(1);
18564 SP = DAG.getNode(ISD::SUB, DL, MVT::i64, SP, Size);
18565 if (Align)
18566 SP = DAG.getNode(ISD::AND, DL, VT, SP.getValue(0),
18567 DAG.getSignedConstant(-Align->value(), DL, VT));
18568 Chain = DAG.getCopyToReg(Chain, DL, AArch64::SP, SP);
18569 SDValue Ops[2] = {SP, Chain};
18570 return DAG.getMergeValues(Ops, DL);
18571 }
18572
18573 RTLIB::LibcallImpl ChkStkImpl = getLibcallImpl(RTLIB::STACK_PROBE);
18574 if (ChkStkImpl == RTLIB::Unsupported)
18575 return SDValue();
18576
18577 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL);
18578
18579 EVT PtrVT = getPointerTy(DAG.getDataLayout());
18581 getLibcallImplName(ChkStkImpl).data(), PtrVT, 0);
18582
18583 const AArch64RegisterInfo *TRI = Subtarget->getRegisterInfo();
18584 const uint32_t *Mask = TRI->getWindowsStackProbePreservedMask();
18585 if (Subtarget->hasCustomCallingConv())
18586 TRI->UpdateCustomCallPreservedMask(DAG.getMachineFunction(), &Mask);
18587
18588 Size = DAG.getNode(ISD::SRL, DL, MVT::i64, Size,
18589 DAG.getConstant(4, DL, MVT::i64));
18590 Chain = DAG.getCopyToReg(Chain, DL, AArch64::X15, Size, SDValue());
18591 Chain =
18592 DAG.getNode(AArch64ISD::CALL, DL, DAG.getVTList(MVT::Other, MVT::Glue),
18593 Chain, Callee, DAG.getRegister(AArch64::X15, MVT::i64),
18594 DAG.getRegisterMask(Mask), Chain.getValue(1));
18595 // To match the actual intent better, we should read the output from X15 here
18596 // again (instead of potentially spilling it to the stack), but rereading Size
18597 // from X15 here doesn't work at -O0, since it thinks that X15 is undefined
18598 // here.
18599
18600 Size = DAG.getNode(ISD::SHL, DL, MVT::i64, Size,
18601 DAG.getConstant(4, DL, MVT::i64));
18602
18603 SDValue SP = DAG.getCopyFromReg(Chain, DL, AArch64::SP, MVT::i64);
18604 Chain = SP.getValue(1);
18605 SP = DAG.getNode(ISD::SUB, DL, MVT::i64, SP, Size);
18606 if (Align)
18607 SP = DAG.getNode(ISD::AND, DL, VT, SP.getValue(0),
18608 DAG.getSignedConstant(-Align->value(), DL, VT));
18609 Chain = DAG.getCopyToReg(Chain, DL, AArch64::SP, SP);
18610
18611 Chain = DAG.getCALLSEQ_END(Chain, 0, 0, SDValue(), DL);
18612
18613 SDValue Ops[2] = {SP, Chain};
18614 return DAG.getMergeValues(Ops, DL);
18615}
18616
18617SDValue
18618AArch64TargetLowering::LowerInlineDYNAMIC_STACKALLOC(SDValue Op,
18619 SelectionDAG &DAG) const {
18620 // Get the inputs.
18621 SDNode *Node = Op.getNode();
18622 SDValue Chain = Op.getOperand(0);
18623 SDValue Size = Op.getOperand(1);
18624
18625 MaybeAlign Align =
18626 cast<ConstantSDNode>(Op.getOperand(2))->getMaybeAlignValue();
18627 SDLoc DL(Op);
18628 EVT VT = Node->getValueType(0);
18629
18630 // Construct the new SP value in a GPR.
18631 SDValue SP = DAG.getCopyFromReg(Chain, DL, AArch64::SP, MVT::i64);
18632 Chain = SP.getValue(1);
18633 SP = DAG.getNode(ISD::SUB, DL, MVT::i64, SP, Size);
18634 if (Align)
18635 SP = DAG.getNode(ISD::AND, DL, VT, SP.getValue(0),
18636 DAG.getSignedConstant(-Align->value(), DL, VT));
18637
18638 // Set the real SP to the new value with a probing loop.
18639 Chain = DAG.getNode(AArch64ISD::PROBED_ALLOCA, DL, MVT::Other, Chain, SP);
18640 SDValue Ops[2] = {SP, Chain};
18641 return DAG.getMergeValues(Ops, DL);
18642}
18643
18644SDValue
18645AArch64TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
18646 SelectionDAG &DAG) const {
18648
18649 if (Subtarget->isTargetWindows())
18650 return LowerWindowsDYNAMIC_STACKALLOC(Op, DAG);
18651 else if (hasInlineStackProbe(MF))
18652 return LowerInlineDYNAMIC_STACKALLOC(Op, DAG);
18653 else
18654 return SDValue();
18655}
18656
18657SDValue AArch64TargetLowering::LowerAVG(SDValue Op, SelectionDAG &DAG,
18658 unsigned NewOp) const {
18659 if (Subtarget->hasSVE2())
18660 return LowerToPredicatedOp(Op, DAG, NewOp);
18661
18662 // Default to expand.
18663 return SDValue();
18664}
18665
18666SDValue AArch64TargetLowering::LowerVSCALE(SDValue Op,
18667 SelectionDAG &DAG) const {
18668 EVT VT = Op.getValueType();
18669 assert(VT != MVT::i64 && "Expected illegal VSCALE node");
18670
18671 SDLoc DL(Op);
18672 APInt MulImm = Op.getConstantOperandAPInt(0);
18673 return DAG.getZExtOrTrunc(DAG.getVScale(DL, MVT::i64, MulImm.sext(64)), DL,
18674 VT);
18675}
18676
18677/// Set the IntrinsicInfo for the `aarch64_sve_st<N>` intrinsics.
18678template <unsigned NumVecs>
18679static void
18682 Info.opc = ISD::INTRINSIC_VOID;
18683 // Retrieve EC from first vector argument.
18684 const EVT VT = TLI.getMemValueType(DL, CI.getArgOperand(0)->getType());
18686#ifndef NDEBUG
18687 // Check the assumption that all input vectors are the same type.
18688 for (unsigned I = 0; I < NumVecs; ++I)
18689 assert(VT == TLI.getMemValueType(DL, CI.getArgOperand(I)->getType()) &&
18690 "Invalid type.");
18691#endif
18692 // memVT is `NumVecs * VT`.
18693 Info.memVT = EVT::getVectorVT(CI.getType()->getContext(), VT.getScalarType(),
18694 EC * NumVecs);
18695 Info.ptrVal = CI.getArgOperand(CI.arg_size() - 1);
18696 Info.offset = 0;
18697 // Unless all predicate lanes are known to be active, the full scalable
18698 // vector size is only an upper bound on the memory accessed, which
18699 // MachineMemOperand cannot represent so set it unknown.
18700 // `NumVecs` used in operand below because predicate is after
18701 // all vector i.e. stN(vec0, ..., vecN-1, predicate, pointer)
18702 const auto *Pred = dyn_cast<Constant>(CI.getArgOperand(NumVecs));
18703 if (!Pred || !Pred->isAllOnesValue())
18704 Info.size = MemoryLocation::UnknownSize;
18705 Info.align.reset();
18706 Info.flags = MachineMemOperand::MOStore;
18707}
18708
18709/// getTgtMemIntrinsic - Represent NEON load and store intrinsics as
18710/// MemIntrinsicNodes. The associated MachineMemOperands record the alignment
18711/// specified in the intrinsic calls.
18714 MachineFunction &MF, unsigned Intrinsic) const {
18715 IntrinsicInfo Info;
18716 auto &DL = I.getDataLayout();
18717 switch (Intrinsic) {
18718 case Intrinsic::aarch64_sve_st2:
18719 case Intrinsic::aarch64_sve_st2q:
18720 setInfoSVEStN<2>(*this, DL, Info, I);
18721 Infos.push_back(Info);
18722 return;
18723 case Intrinsic::aarch64_sve_st3:
18724 case Intrinsic::aarch64_sve_st3q:
18725 setInfoSVEStN<3>(*this, DL, Info, I);
18726 Infos.push_back(Info);
18727 return;
18728 case Intrinsic::aarch64_sve_st4:
18729 case Intrinsic::aarch64_sve_st4q:
18730 setInfoSVEStN<4>(*this, DL, Info, I);
18731 Infos.push_back(Info);
18732 return;
18733 case Intrinsic::aarch64_neon_ld2:
18734 case Intrinsic::aarch64_neon_ld3:
18735 case Intrinsic::aarch64_neon_ld4:
18736 case Intrinsic::aarch64_neon_ld1x2:
18737 case Intrinsic::aarch64_neon_ld1x3:
18738 case Intrinsic::aarch64_neon_ld1x4: {
18739 Info.opc = ISD::INTRINSIC_W_CHAIN;
18740 uint64_t NumElts = DL.getTypeSizeInBits(I.getType()) / 64;
18741 Info.memVT = EVT::getVectorVT(I.getType()->getContext(), MVT::i64, NumElts);
18742 Info.ptrVal = I.getArgOperand(I.arg_size() - 1);
18743 Info.offset = 0;
18744 Info.align.reset();
18745 // volatile loads with NEON intrinsics not supported
18746 Info.flags = MachineMemOperand::MOLoad;
18747 Infos.push_back(Info);
18748 return;
18749 }
18750 case Intrinsic::aarch64_neon_ld2lane:
18751 case Intrinsic::aarch64_neon_ld3lane:
18752 case Intrinsic::aarch64_neon_ld4lane:
18753 case Intrinsic::aarch64_neon_ld2r:
18754 case Intrinsic::aarch64_neon_ld3r:
18755 case Intrinsic::aarch64_neon_ld4r: {
18756 Info.opc = ISD::INTRINSIC_W_CHAIN;
18757 // ldx return struct with the same vec type
18758 Type *RetTy = I.getType();
18759 auto *StructTy = cast<StructType>(RetTy);
18760 unsigned NumElts = StructTy->getNumElements();
18761 Type *VecTy = StructTy->getElementType(0);
18762 MVT EleVT = MVT::getVT(VecTy).getVectorElementType();
18763 Info.memVT = EVT::getVectorVT(I.getType()->getContext(), EleVT, NumElts);
18764 Info.ptrVal = I.getArgOperand(I.arg_size() - 1);
18765 Info.offset = 0;
18766 Info.align.reset();
18767 // volatile loads with NEON intrinsics not supported
18768 Info.flags = MachineMemOperand::MOLoad;
18769 Infos.push_back(Info);
18770 return;
18771 }
18772 case Intrinsic::aarch64_neon_st2:
18773 case Intrinsic::aarch64_neon_st3:
18774 case Intrinsic::aarch64_neon_st4:
18775 case Intrinsic::aarch64_neon_st1x2:
18776 case Intrinsic::aarch64_neon_st1x3:
18777 case Intrinsic::aarch64_neon_st1x4: {
18778 Info.opc = ISD::INTRINSIC_VOID;
18779 unsigned NumElts = 0;
18780 for (const Value *Arg : I.args()) {
18781 Type *ArgTy = Arg->getType();
18782 if (!ArgTy->isVectorTy())
18783 break;
18784 NumElts += DL.getTypeSizeInBits(ArgTy) / 64;
18785 }
18786 Info.memVT = EVT::getVectorVT(I.getType()->getContext(), MVT::i64, NumElts);
18787 Info.ptrVal = I.getArgOperand(I.arg_size() - 1);
18788 Info.offset = 0;
18789 Info.align.reset();
18790 // volatile stores with NEON intrinsics not supported
18791 Info.flags = MachineMemOperand::MOStore;
18792 Infos.push_back(Info);
18793 return;
18794 }
18795 case Intrinsic::aarch64_neon_st2lane:
18796 case Intrinsic::aarch64_neon_st3lane:
18797 case Intrinsic::aarch64_neon_st4lane: {
18798 Info.opc = ISD::INTRINSIC_VOID;
18799 unsigned NumElts = 0;
18800 // all the vector type is same
18801 Type *VecTy = I.getArgOperand(0)->getType();
18802 MVT EleVT = MVT::getVT(VecTy).getVectorElementType();
18803
18804 for (const Value *Arg : I.args()) {
18805 Type *ArgTy = Arg->getType();
18806 if (!ArgTy->isVectorTy())
18807 break;
18808 NumElts += 1;
18809 }
18810
18811 Info.memVT = EVT::getVectorVT(I.getType()->getContext(), EleVT, NumElts);
18812 Info.ptrVal = I.getArgOperand(I.arg_size() - 1);
18813 Info.offset = 0;
18814 Info.align.reset();
18815 // volatile stores with NEON intrinsics not supported
18816 Info.flags = MachineMemOperand::MOStore;
18817 Infos.push_back(Info);
18818 return;
18819 }
18820 case Intrinsic::aarch64_ldaxr:
18821 case Intrinsic::aarch64_ldxr: {
18822 Type *ValTy = I.getParamElementType(0);
18823 Info.opc = ISD::INTRINSIC_W_CHAIN;
18824 Info.memVT = MVT::getVT(ValTy);
18825 Info.ptrVal = I.getArgOperand(0);
18826 Info.offset = 0;
18827 Info.align = DL.getABITypeAlign(ValTy);
18829 Infos.push_back(Info);
18830 return;
18831 }
18832 case Intrinsic::aarch64_stlxr:
18833 case Intrinsic::aarch64_stxr: {
18834 Type *ValTy = I.getParamElementType(1);
18835 Info.opc = ISD::INTRINSIC_W_CHAIN;
18836 Info.memVT = MVT::getVT(ValTy);
18837 Info.ptrVal = I.getArgOperand(1);
18838 Info.offset = 0;
18839 Info.align = DL.getABITypeAlign(ValTy);
18841 Infos.push_back(Info);
18842 return;
18843 }
18844 case Intrinsic::aarch64_ldaxp:
18845 case Intrinsic::aarch64_ldxp:
18846 Info.opc = ISD::INTRINSIC_W_CHAIN;
18847 Info.memVT = MVT::i128;
18848 Info.ptrVal = I.getArgOperand(0);
18849 Info.offset = 0;
18850 Info.align = Align(16);
18852 Infos.push_back(Info);
18853 return;
18854 case Intrinsic::aarch64_stlxp:
18855 case Intrinsic::aarch64_stxp:
18856 Info.opc = ISD::INTRINSIC_W_CHAIN;
18857 Info.memVT = MVT::i128;
18858 Info.ptrVal = I.getArgOperand(2);
18859 Info.offset = 0;
18860 Info.align = Align(16);
18862 Infos.push_back(Info);
18863 return;
18864 case Intrinsic::aarch64_sve_ldnt1: {
18865 Type *ElTy = cast<VectorType>(I.getType())->getElementType();
18866 Info.opc = ISD::INTRINSIC_W_CHAIN;
18867 Info.memVT = MVT::getVT(I.getType());
18868 Info.ptrVal = I.getArgOperand(1);
18869 Info.offset = 0;
18870 Info.align = DL.getABITypeAlign(ElTy);
18872 Infos.push_back(Info);
18873 return;
18874 }
18875 case Intrinsic::aarch64_sve_stnt1: {
18876 Type *ElTy =
18877 cast<VectorType>(I.getArgOperand(0)->getType())->getElementType();
18878 Info.opc = ISD::INTRINSIC_W_CHAIN;
18879 Info.memVT = MVT::getVT(I.getOperand(0)->getType());
18880 Info.ptrVal = I.getArgOperand(2);
18881 Info.offset = 0;
18882 Info.align = DL.getABITypeAlign(ElTy);
18884 Infos.push_back(Info);
18885 return;
18886 }
18887 case Intrinsic::aarch64_mops_memset_tag: {
18888 Value *Dst = I.getArgOperand(0);
18889 Value *Val = I.getArgOperand(1);
18890 Info.opc = ISD::INTRINSIC_W_CHAIN;
18891 Info.memVT = MVT::getVT(Val->getType());
18892 Info.ptrVal = Dst;
18893 Info.offset = 0;
18894 Info.align = I.getParamAlign(0).valueOrOne();
18895 Info.flags = MachineMemOperand::MOStore;
18896 // The size of the memory being operated on is unknown at this point
18897 Info.size = MemoryLocation::UnknownSize;
18898 Infos.push_back(Info);
18899 return;
18900 }
18901 default:
18902 break;
18903 }
18904}
18905
18907 SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT,
18908 std::optional<unsigned> ByteOffset) const {
18909 // TODO: This may be worth removing. Check regression tests for diffs.
18911 ByteOffset))
18912 return false;
18913
18914 // If we're reducing the load width in order to avoid having to use an extra
18915 // instruction to do extension then it's probably a good idea.
18916 if (ExtTy != ISD::NON_EXTLOAD)
18917 return true;
18918 // Don't reduce load width if it would prevent us from combining a shift into
18919 // the offset.
18921 assert(Mem);
18922 const SDValue &Base = Mem->getBasePtr();
18923 if (Base.getOpcode() == ISD::ADD &&
18924 Base.getOperand(1).getOpcode() == ISD::SHL &&
18925 Base.getOperand(1).hasOneUse() &&
18926 Base.getOperand(1).getOperand(1).getOpcode() == ISD::Constant) {
18927 // It's unknown whether a scalable vector has a power-of-2 bitwidth.
18928 if (Mem->getMemoryVT().isScalableVector())
18929 return false;
18930 // The shift can be combined if it matches the size of the value being
18931 // loaded (and so reducing the width would make it not match).
18932 uint64_t ShiftAmount = Base.getOperand(1).getConstantOperandVal(1);
18933 uint64_t LoadBytes = Mem->getMemoryVT().getSizeInBits()/8;
18934 if (ShiftAmount == Log2_32(LoadBytes))
18935 return false;
18936 }
18937 // We have no reason to disallow reducing the load width, so allow it.
18938 return true;
18939}
18940
18941// Treat a sext_inreg(extract(..)) as free if it has multiple uses.
18943 EVT VT = Extend.getValueType();
18944 if ((VT == MVT::i64 || VT == MVT::i32) && Extend->use_size()) {
18945 SDValue Extract = Extend.getOperand(0);
18946 if (Extract.getOpcode() == ISD::ANY_EXTEND && Extract.hasOneUse())
18947 Extract = Extract.getOperand(0);
18948 if (Extract.getOpcode() == ISD::EXTRACT_VECTOR_ELT && Extract.hasOneUse()) {
18949 EVT VecVT = Extract.getOperand(0).getValueType();
18950 if (VecVT.getScalarType() == MVT::i8 || VecVT.getScalarType() == MVT::i16)
18951 return false;
18952 }
18953 }
18954 return true;
18955}
18956
18957// Truncations from 64-bit GPR to 32-bit GPR is free.
18959 if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy())
18960 return false;
18961 uint64_t NumBits1 = Ty1->getPrimitiveSizeInBits().getFixedValue();
18962 uint64_t NumBits2 = Ty2->getPrimitiveSizeInBits().getFixedValue();
18963 return NumBits1 > NumBits2;
18964}
18966 if (VT1.isVector() || VT2.isVector() || !VT1.isInteger() || !VT2.isInteger())
18967 return false;
18968 uint64_t NumBits1 = VT1.getFixedSizeInBits();
18969 uint64_t NumBits2 = VT2.getFixedSizeInBits();
18970 return NumBits1 > NumBits2;
18971}
18972
18973/// Check if it is profitable to hoist instruction in then/else to if.
18974/// Not profitable if I and it's user can form a FMA instruction
18975/// because we prefer FMSUB/FMADD.
18977 if (I->getOpcode() != Instruction::FMul)
18978 return true;
18979
18980 if (!I->hasOneUse())
18981 return true;
18982
18983 Instruction *User = I->user_back();
18984
18985 if (!(User->getOpcode() == Instruction::FSub ||
18986 User->getOpcode() == Instruction::FAdd))
18987 return true;
18988
18989 const Function *F = I->getFunction();
18990 const DataLayout &DL = F->getDataLayout();
18991 Type *Ty = User->getOperand(0)->getType();
18992
18993 return !(isFMAFasterThanFMulAndFAdd(*F, Ty) &&
18995 I->getFastMathFlags().allowContract());
18996}
18997
18998// All 32-bit GPR operations implicitly zero the high-half of the corresponding
18999// 64-bit GPR.
19001 if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy())
19002 return false;
19003 unsigned NumBits1 = Ty1->getPrimitiveSizeInBits();
19004 unsigned NumBits2 = Ty2->getPrimitiveSizeInBits();
19005 return NumBits1 == 32 && NumBits2 == 64;
19006}
19008 if (VT1.isVector() || VT2.isVector() || !VT1.isInteger() || !VT2.isInteger())
19009 return false;
19010 unsigned NumBits1 = VT1.getSizeInBits();
19011 unsigned NumBits2 = VT2.getSizeInBits();
19012 return NumBits1 == 32 && NumBits2 == 64;
19013}
19014
19016 EVT VT1 = Val.getValueType();
19017 if (isZExtFree(VT1, VT2)) {
19018 return true;
19019 }
19020
19021 if (Val.getOpcode() != ISD::LOAD)
19022 return false;
19023
19024 // 8-, 16-, and 32-bit integer loads all implicitly zero-extend.
19025 return (VT1.isSimple() && !VT1.isVector() && VT1.isInteger() &&
19026 VT2.isSimple() && !VT2.isVector() && VT2.isInteger() &&
19027 VT1.getSizeInBits() <= 32);
19028}
19029
19030bool AArch64TargetLowering::isExtFreeImpl(const Instruction *Ext) const {
19031 if (isa<FPExtInst>(Ext))
19032 return false;
19033
19034 // Vector types are not free.
19035 if (Ext->getType()->isVectorTy())
19036 return false;
19037
19038 for (const Use &U : Ext->uses()) {
19039 // The extension is free if we can fold it with a left shift in an
19040 // addressing mode or an arithmetic operation: add, sub, and cmp.
19041
19042 // Is there a shift?
19043 const Instruction *Instr = cast<Instruction>(U.getUser());
19044
19045 // Is this a constant shift?
19046 switch (Instr->getOpcode()) {
19047 case Instruction::Shl:
19048 if (!isa<ConstantInt>(Instr->getOperand(1)))
19049 return false;
19050 break;
19051 case Instruction::GetElementPtr: {
19052 gep_type_iterator GTI = gep_type_begin(Instr);
19053 auto &DL = Ext->getDataLayout();
19054 std::advance(GTI, U.getOperandNo()-1);
19055 Type *IdxTy = GTI.getIndexedType();
19056 // This extension will end up with a shift because of the scaling factor.
19057 // 8-bit sized types have a scaling factor of 1, thus a shift amount of 0.
19058 // Get the shift amount based on the scaling factor:
19059 // log2(sizeof(IdxTy)) - log2(8).
19060 if (IdxTy->isScalableTy())
19061 return false;
19062 uint64_t ShiftAmt =
19063 llvm::countr_zero(DL.getTypeStoreSizeInBits(IdxTy).getFixedValue()) -
19064 3;
19065 // Is the constant foldable in the shift of the addressing mode?
19066 // I.e., shift amount is between 1 and 4 inclusive.
19067 if (ShiftAmt == 0 || ShiftAmt > 4)
19068 return false;
19069 break;
19070 }
19071 case Instruction::Trunc:
19072 // Check if this is a noop.
19073 // trunc(sext ty1 to ty2) to ty1.
19074 if (Instr->getType() == Ext->getOperand(0)->getType())
19075 continue;
19076 [[fallthrough]];
19077 default:
19078 return false;
19079 }
19080
19081 // At this point we can use the bfm family, so this extension is free
19082 // for that use.
19083 }
19084 return true;
19085}
19086
19087static bool createTblShuffleMask(unsigned SrcWidth, unsigned DstWidth,
19088 unsigned NumElts, bool IsLittleEndian,
19089 SmallVectorImpl<int> &Mask) {
19090 if (DstWidth % 8 != 0 || DstWidth <= 16 || DstWidth > 64)
19091 return false;
19092
19093 assert(DstWidth % SrcWidth == 0 &&
19094 "TBL lowering is not supported for a conversion instruction with this "
19095 "source and destination element type.");
19096
19097 unsigned Factor = DstWidth / SrcWidth;
19098 unsigned MaskLen = NumElts * Factor;
19099
19100 Mask.clear();
19101 Mask.resize(MaskLen, NumElts);
19102
19103 unsigned SrcIndex = 0;
19104 for (unsigned I = IsLittleEndian ? 0 : Factor - 1; I < MaskLen; I += Factor)
19105 Mask[I] = SrcIndex++;
19106
19107 return true;
19108}
19109
19111 FixedVectorType *ZExtTy,
19112 FixedVectorType *DstTy,
19113 bool IsLittleEndian) {
19114 auto *SrcTy = cast<FixedVectorType>(Op->getType());
19115 unsigned NumElts = SrcTy->getNumElements();
19116 auto SrcWidth = cast<IntegerType>(SrcTy->getElementType())->getBitWidth();
19117 auto DstWidth = cast<IntegerType>(DstTy->getElementType())->getBitWidth();
19118
19119 SmallVector<int> Mask;
19120 if (!createTblShuffleMask(SrcWidth, DstWidth, NumElts, IsLittleEndian, Mask))
19121 return nullptr;
19122
19123 auto *FirstEltZero = Builder.CreateInsertElement(
19124 PoisonValue::get(SrcTy), Builder.getIntN(SrcWidth, 0), uint64_t(0));
19125 Value *Result = Builder.CreateShuffleVector(Op, FirstEltZero, Mask);
19126 Result = Builder.CreateBitCast(Result, DstTy);
19127 if (DstTy != ZExtTy)
19128 Result = Builder.CreateZExt(Result, ZExtTy);
19129 return Result;
19130}
19131
19133 FixedVectorType *DstTy,
19134 bool IsLittleEndian) {
19135 auto *SrcTy = cast<FixedVectorType>(Op->getType());
19136 auto SrcWidth = cast<IntegerType>(SrcTy->getElementType())->getBitWidth();
19137 auto DstWidth = cast<IntegerType>(DstTy->getElementType())->getBitWidth();
19138
19139 SmallVector<int> Mask;
19140 if (!createTblShuffleMask(SrcWidth, DstWidth, SrcTy->getNumElements(),
19141 !IsLittleEndian, Mask))
19142 return nullptr;
19143
19144 auto *FirstEltZero = Builder.CreateInsertElement(
19145 PoisonValue::get(SrcTy), Builder.getIntN(SrcWidth, 0), uint64_t(0));
19146
19147 return Builder.CreateShuffleVector(Op, FirstEltZero, Mask);
19148}
19149
19150static void createTblForTrunc(TruncInst *TI, bool IsLittleEndian) {
19151 IRBuilder<> Builder(TI);
19153 int NumElements = cast<FixedVectorType>(TI->getType())->getNumElements();
19154 auto *SrcTy = cast<FixedVectorType>(TI->getOperand(0)->getType());
19155 auto *DstTy = cast<FixedVectorType>(TI->getType());
19156 assert(SrcTy->getElementType()->isIntegerTy() &&
19157 "Non-integer type source vector element is not supported");
19158 assert(DstTy->getElementType()->isIntegerTy(8) &&
19159 "Unsupported destination vector element type");
19160 unsigned SrcElemTySz =
19161 cast<IntegerType>(SrcTy->getElementType())->getBitWidth();
19162 unsigned DstElemTySz =
19163 cast<IntegerType>(DstTy->getElementType())->getBitWidth();
19164 assert((SrcElemTySz % DstElemTySz == 0) &&
19165 "Cannot lower truncate to tbl instructions for a source element size "
19166 "that is not divisible by the destination element size");
19167 unsigned TruncFactor = SrcElemTySz / DstElemTySz;
19168 assert((SrcElemTySz == 16 || SrcElemTySz == 32 || SrcElemTySz == 64) &&
19169 "Unsupported source vector element type size");
19170 Type *VecTy = FixedVectorType::get(Builder.getInt8Ty(), 16);
19171
19172 // Create a mask to choose every nth byte from the source vector table of
19173 // bytes to create the truncated destination vector, where 'n' is the truncate
19174 // ratio. For example, for a truncate from Yxi64 to Yxi8, choose
19175 // 0,8,16,..Y*8th bytes for the little-endian format
19177 for (int Itr = 0; Itr < 16; Itr++) {
19178 if (Itr < NumElements)
19179 MaskConst.push_back(Builder.getInt8(
19180 IsLittleEndian ? Itr * TruncFactor
19181 : Itr * TruncFactor + (TruncFactor - 1)));
19182 else
19183 MaskConst.push_back(Builder.getInt8(255));
19184 }
19185
19186 int MaxTblSz = 128 * 4;
19187 int MaxSrcSz = SrcElemTySz * NumElements;
19188 int ElemsPerTbl =
19189 (MaxTblSz > MaxSrcSz) ? NumElements : (MaxTblSz / SrcElemTySz);
19190 assert(ElemsPerTbl <= 16 &&
19191 "Maximum elements selected using TBL instruction cannot exceed 16!");
19192
19193 int ShuffleCount = 128 / SrcElemTySz;
19194 SmallVector<int> ShuffleLanes;
19195 for (int i = 0; i < ShuffleCount; ++i)
19196 ShuffleLanes.push_back(i);
19197
19198 // Create TBL's table of bytes in 1,2,3 or 4 FP/SIMD registers using shuffles
19199 // over the source vector. If TBL's maximum 4 FP/SIMD registers are saturated,
19200 // call TBL & save the result in a vector of TBL results for combining later.
19202 while (ShuffleLanes.back() < NumElements) {
19203 Parts.push_back(Builder.CreateBitCast(
19204 Builder.CreateShuffleVector(TI->getOperand(0), ShuffleLanes), VecTy));
19205
19206 if (Parts.size() == 4) {
19207 Parts.push_back(ConstantVector::get(MaskConst));
19208 Results.push_back(
19209 Builder.CreateIntrinsic(Intrinsic::aarch64_neon_tbl4, VecTy, Parts));
19210 Parts.clear();
19211 }
19212
19213 for (int i = 0; i < ShuffleCount; ++i)
19214 ShuffleLanes[i] += ShuffleCount;
19215 }
19216
19217 assert((Parts.empty() || Results.empty()) &&
19218 "Lowering trunc for vectors requiring different TBL instructions is "
19219 "not supported!");
19220 // Call TBL for the residual table bytes present in 1,2, or 3 FP/SIMD
19221 // registers
19222 if (!Parts.empty()) {
19223 Intrinsic::ID TblID;
19224 switch (Parts.size()) {
19225 case 1:
19226 TblID = Intrinsic::aarch64_neon_tbl1;
19227 break;
19228 case 2:
19229 TblID = Intrinsic::aarch64_neon_tbl2;
19230 break;
19231 case 3:
19232 TblID = Intrinsic::aarch64_neon_tbl3;
19233 break;
19234 }
19235
19236 Parts.push_back(ConstantVector::get(MaskConst));
19237 Results.push_back(Builder.CreateIntrinsic(TblID, VecTy, Parts));
19238 }
19239
19240 // Extract the destination vector from TBL result(s) after combining them
19241 // where applicable. Currently, at most two TBLs are supported.
19242 assert(Results.size() <= 2 && "Trunc lowering does not support generation of "
19243 "more than 2 tbl instructions!");
19244 Value *FinalResult = Results[0];
19245 if (Results.size() == 1) {
19246 if (ElemsPerTbl < 16) {
19247 SmallVector<int> FinalMask(ElemsPerTbl);
19248 std::iota(FinalMask.begin(), FinalMask.end(), 0);
19249 FinalResult = Builder.CreateShuffleVector(Results[0], FinalMask);
19250 }
19251 } else {
19252 SmallVector<int> FinalMask(ElemsPerTbl * Results.size());
19253 if (ElemsPerTbl < 16) {
19254 std::iota(FinalMask.begin(), FinalMask.begin() + ElemsPerTbl, 0);
19255 std::iota(FinalMask.begin() + ElemsPerTbl, FinalMask.end(), 16);
19256 } else {
19257 std::iota(FinalMask.begin(), FinalMask.end(), 0);
19258 }
19259 FinalResult =
19260 Builder.CreateShuffleVector(Results[0], Results[1], FinalMask);
19261 }
19262
19263 TI->replaceAllUsesWith(FinalResult);
19264 TI->eraseFromParent();
19265}
19266
19268 Instruction *I, Loop *L, const TargetTransformInfo &TTI) const {
19269 // shuffle_vector instructions are serialized when targeting SVE,
19270 // see LowerSPLAT_VECTOR. This peephole is not beneficial.
19271 if (!EnableExtToTBL || Subtarget->useSVEForFixedLengthVectors())
19272 return false;
19273
19274 // Try to optimize conversions using tbl. This requires materializing constant
19275 // index vectors, which can increase code size and add loads. Skip the
19276 // transform unless the conversion is in a loop block guaranteed to execute
19277 // and we are not optimizing for size.
19278 Function *F = I->getParent()->getParent();
19279 if (!L || L->getHeader() != I->getParent() || F->hasOptSize())
19280 return false;
19281
19282 auto *SrcTy = dyn_cast<FixedVectorType>(I->getOperand(0)->getType());
19283 auto *DstTy = dyn_cast<FixedVectorType>(I->getType());
19284 if (!SrcTy || !DstTy)
19285 return false;
19286
19287 // Convert 'zext <Y x i8> %x to <Y x i8X>' to a shuffle that can be
19288 // lowered to tbl instructions to insert the original i8 elements
19289 // into i8x lanes. This is enabled for cases where it is beneficial.
19290 auto *ZExt = dyn_cast<ZExtInst>(I);
19291 if (ZExt && SrcTy->getElementType()->isIntegerTy(8)) {
19292 auto DstWidth = DstTy->getElementType()->getScalarSizeInBits();
19293 if (DstWidth % 8 != 0)
19294 return false;
19295
19296 auto *TruncDstType =
19298 // If the ZExt can be lowered to a single ZExt to the next power-of-2 and
19299 // the remaining ZExt folded into the user, don't use tbl lowering.
19300 auto SrcWidth = SrcTy->getElementType()->getScalarSizeInBits();
19301 if (TTI.getCastInstrCost(I->getOpcode(), DstTy, TruncDstType,
19304 if (SrcWidth * 2 >= TruncDstType->getElementType()->getScalarSizeInBits())
19305 return false;
19306
19307 DstTy = TruncDstType;
19308 }
19309
19310 // mul(zext(i8), sext) can be transformed into smull(zext, sext) which
19311 // performs one extend implicitly. If DstWidth is at most 4 * SrcWidth, at
19312 // most one extra extend step is needed and using tbl is not profitable.
19313 // Similarly, bail out if partial_reduce(acc, zext(i8)) can be lowered to a
19314 // udot instruction.
19315 if (SrcWidth * 4 <= DstWidth) {
19316 if (all_of(I->users(), [&](auto *U) {
19317 using namespace llvm::PatternMatch;
19318 auto *SingleUser = cast<Instruction>(&*U);
19319 if (match(SingleUser, m_c_Mul(m_Specific(I), m_SExt(m_Value()))))
19320 return true;
19321 if (match(SingleUser,
19322 m_Intrinsic<Intrinsic::vector_partial_reduce_add>(
19323 m_Value(), m_Specific(I))))
19324 return true;
19325 return false;
19326 }))
19327 return false;
19328 }
19329
19330 if (DstTy->getScalarSizeInBits() >= 64)
19331 return false;
19332
19333 IRBuilder<> Builder(ZExt);
19335 Builder, ZExt->getOperand(0), cast<FixedVectorType>(ZExt->getType()),
19336 DstTy, Subtarget->isLittleEndian());
19337 if (!Result)
19338 return false;
19339 ZExt->replaceAllUsesWith(Result);
19340 ZExt->eraseFromParent();
19341 return true;
19342 }
19343
19344 auto *UIToFP = dyn_cast<UIToFPInst>(I);
19345 if (UIToFP && ((SrcTy->getElementType()->isIntegerTy(8) &&
19346 DstTy->getElementType()->isFloatTy()) ||
19347 (SrcTy->getElementType()->isIntegerTy(16) &&
19348 DstTy->getElementType()->isDoubleTy()))) {
19349 IRBuilder<> Builder(I);
19351 Builder, I->getOperand(0), FixedVectorType::getInteger(DstTy),
19352 FixedVectorType::getInteger(DstTy), Subtarget->isLittleEndian());
19353 assert(ZExt && "Cannot fail for the i8 to float conversion");
19354 auto *UI = Builder.CreateUIToFP(ZExt, DstTy);
19355 I->replaceAllUsesWith(UI);
19356 I->eraseFromParent();
19357 return true;
19358 }
19359
19360 auto *SIToFP = dyn_cast<SIToFPInst>(I);
19361 if (SIToFP && SrcTy->getElementType()->isIntegerTy(8) &&
19362 DstTy->getElementType()->isFloatTy()) {
19363 IRBuilder<> Builder(I);
19364 auto *Shuffle = createTblShuffleForSExt(Builder, I->getOperand(0),
19366 Subtarget->isLittleEndian());
19367 assert(Shuffle && "Cannot fail for the i8 to float conversion");
19368 auto *Cast = Builder.CreateBitCast(Shuffle, VectorType::getInteger(DstTy));
19369 auto *AShr = Builder.CreateAShr(Cast, 24, "", true);
19370 auto *SI = Builder.CreateSIToFP(AShr, DstTy);
19371 I->replaceAllUsesWith(SI);
19372 I->eraseFromParent();
19373 return true;
19374 }
19375
19376 // Convert 'fptoui <(8|16) x float> to <(8|16) x i8>' to a wide fptoui
19377 // followed by a truncate lowered to using tbl.4.
19378 auto *FPToUI = dyn_cast<FPToUIInst>(I);
19379 if (FPToUI &&
19380 (SrcTy->getNumElements() == 8 || SrcTy->getNumElements() == 16) &&
19381 SrcTy->getElementType()->isFloatTy() &&
19382 DstTy->getElementType()->isIntegerTy(8)) {
19383 IRBuilder<> Builder(I);
19384 auto *WideConv = Builder.CreateFPToUI(FPToUI->getOperand(0),
19385 VectorType::getInteger(SrcTy));
19386 auto *TruncI = Builder.CreateTrunc(WideConv, DstTy);
19387 I->replaceAllUsesWith(TruncI);
19388 I->eraseFromParent();
19389 createTblForTrunc(cast<TruncInst>(TruncI), Subtarget->isLittleEndian());
19390 return true;
19391 }
19392
19393 // Convert 'trunc <(8|16) x (i32|i64)> %x to <(8|16) x i8>' to an appropriate
19394 // tbl instruction selecting the lowest/highest (little/big endian) 8 bits
19395 // per lane of the input that is represented using 1,2,3 or 4 128-bit table
19396 // registers
19397 auto *TI = dyn_cast<TruncInst>(I);
19398 if (TI && DstTy->getElementType()->isIntegerTy(8) &&
19399 ((SrcTy->getElementType()->isIntegerTy(32) ||
19400 SrcTy->getElementType()->isIntegerTy(64)) &&
19401 (SrcTy->getNumElements() == 16 || SrcTy->getNumElements() == 8))) {
19402 createTblForTrunc(TI, Subtarget->isLittleEndian());
19403 return true;
19404 }
19405
19406 return false;
19407}
19408
19410 Align &RequiredAlignment) const {
19411 if (!LoadedType.isSimple() ||
19412 (!LoadedType.isInteger() && !LoadedType.isFloatingPoint()))
19413 return false;
19414 // Cyclone supports unaligned accesses.
19415 RequiredAlignment = Align(1);
19416 unsigned NumBits = LoadedType.getSizeInBits();
19417 return NumBits == 32 || NumBits == 64;
19418}
19419
19420/// A helper function for determining the number of interleaved accesses we
19421/// will generate when lowering accesses of the given type.
19423 VectorType *VecTy, const DataLayout &DL, bool UseScalable) const {
19424 unsigned VecSize = 128;
19425 unsigned ElSize = DL.getTypeSizeInBits(VecTy->getElementType());
19426 unsigned MinElts = VecTy->getElementCount().getKnownMinValue();
19427 if (UseScalable && isa<FixedVectorType>(VecTy))
19428 VecSize = std::max(Subtarget->getMinSVEVectorSizeInBits(), 128u);
19429 return std::max<unsigned>(1, (MinElts * ElSize + 127) / VecSize);
19430}
19431
19434 if (Subtarget->getProcFamily() == AArch64Subtarget::Falkor &&
19435 I.hasMetadata(FALKOR_STRIDED_ACCESS_MD))
19436 return MOStridedAccess;
19438}
19439
19441 VectorType *VecTy, const DataLayout &DL, bool &UseScalable) const {
19442 unsigned ElSize = DL.getTypeSizeInBits(VecTy->getElementType());
19443 auto EC = VecTy->getElementCount();
19444 unsigned MinElts = EC.getKnownMinValue();
19445
19446 UseScalable = false;
19447
19448 if (isa<FixedVectorType>(VecTy) && !Subtarget->isNeonAvailable() &&
19449 (!Subtarget->useSVEForFixedLengthVectors() ||
19451 return false;
19452
19453 if (isa<ScalableVectorType>(VecTy) &&
19454 !Subtarget->isSVEorStreamingSVEAvailable())
19455 return false;
19456
19457 // Ensure the number of vector elements is greater than 1.
19458 if (MinElts < 2)
19459 return false;
19460
19461 // Ensure the element type is legal.
19462 if (ElSize != 8 && ElSize != 16 && ElSize != 32 && ElSize != 64)
19463 return false;
19464
19465 if (EC.isScalable()) {
19466 UseScalable = true;
19467 return isPowerOf2_32(MinElts) && (MinElts * ElSize) % 128 == 0;
19468 }
19469
19470 unsigned VecSize = DL.getTypeSizeInBits(VecTy);
19471 if (Subtarget->useSVEForFixedLengthVectors()) {
19472 unsigned MinSVEVectorSize =
19473 std::max(Subtarget->getMinSVEVectorSizeInBits(), 128u);
19474 if (VecSize % MinSVEVectorSize == 0 ||
19475 (VecSize < MinSVEVectorSize && isPowerOf2_32(MinElts) &&
19476 (!Subtarget->isNeonAvailable() || VecSize > 128))) {
19477 UseScalable = true;
19478 return true;
19479 }
19480 }
19481
19482 // Ensure the total vector size is 64 or a multiple of 128. Types larger than
19483 // 128 will be split into multiple interleaved accesses.
19484 return Subtarget->isNeonAvailable() && (VecSize == 64 || VecSize % 128 == 0);
19485}
19486
19488 if (VTy->getElementType() == Type::getDoubleTy(VTy->getContext()))
19489 return ScalableVectorType::get(VTy->getElementType(), 2);
19490
19491 if (VTy->getElementType() == Type::getFloatTy(VTy->getContext()))
19492 return ScalableVectorType::get(VTy->getElementType(), 4);
19493
19494 if (VTy->getElementType() == Type::getBFloatTy(VTy->getContext()))
19495 return ScalableVectorType::get(VTy->getElementType(), 8);
19496
19497 if (VTy->getElementType() == Type::getHalfTy(VTy->getContext()))
19498 return ScalableVectorType::get(VTy->getElementType(), 8);
19499
19500 if (VTy->getElementType() == Type::getInt64Ty(VTy->getContext()))
19501 return ScalableVectorType::get(VTy->getElementType(), 2);
19502
19503 if (VTy->getElementType() == Type::getInt32Ty(VTy->getContext()))
19504 return ScalableVectorType::get(VTy->getElementType(), 4);
19505
19506 if (VTy->getElementType() == Type::getInt16Ty(VTy->getContext()))
19507 return ScalableVectorType::get(VTy->getElementType(), 8);
19508
19509 if (VTy->getElementType() == Type::getInt8Ty(VTy->getContext()))
19510 return ScalableVectorType::get(VTy->getElementType(), 16);
19511
19512 llvm_unreachable("Cannot handle input vector type");
19513}
19514
19515static Function *getStructuredLoadFunction(Module *M, unsigned Factor,
19516 bool Scalable, Type *LDVTy,
19517 Type *PtrTy) {
19518 assert(Factor >= 2 && Factor <= 4 && "Invalid interleave factor");
19519 static const Intrinsic::ID SVELoads[3] = {Intrinsic::aarch64_sve_ld2_sret,
19520 Intrinsic::aarch64_sve_ld3_sret,
19521 Intrinsic::aarch64_sve_ld4_sret};
19522 static const Intrinsic::ID NEONLoads[3] = {Intrinsic::aarch64_neon_ld2,
19523 Intrinsic::aarch64_neon_ld3,
19524 Intrinsic::aarch64_neon_ld4};
19525 if (Scalable)
19526 return Intrinsic::getOrInsertDeclaration(M, SVELoads[Factor - 2],
19527 {LDVTy, PtrTy});
19528
19529 return Intrinsic::getOrInsertDeclaration(M, NEONLoads[Factor - 2],
19530 {LDVTy, PtrTy});
19531}
19532
19533static Function *getStructuredStoreFunction(Module *M, unsigned Factor,
19534 bool Scalable, Type *STVTy,
19535 Type *PtrTy) {
19536 assert(Factor >= 2 && Factor <= 4 && "Invalid interleave factor");
19537 static const Intrinsic::ID SVEStores[3] = {Intrinsic::aarch64_sve_st2,
19538 Intrinsic::aarch64_sve_st3,
19539 Intrinsic::aarch64_sve_st4};
19540 static const Intrinsic::ID NEONStores[3] = {Intrinsic::aarch64_neon_st2,
19541 Intrinsic::aarch64_neon_st3,
19542 Intrinsic::aarch64_neon_st4};
19543 if (Scalable)
19544 return Intrinsic::getOrInsertDeclaration(M, SVEStores[Factor - 2],
19545 {STVTy, PtrTy});
19546
19547 return Intrinsic::getOrInsertDeclaration(M, NEONStores[Factor - 2],
19548 {STVTy, PtrTy});
19549}
19550
19551/// Lower an interleaved load into a ldN intrinsic.
19552///
19553/// E.g. Lower an interleaved load (Factor = 2):
19554/// %wide.vec = load <8 x i32>, <8 x i32>* %ptr
19555/// %v0 = shuffle %wide.vec, undef, <0, 2, 4, 6> ; Extract even elements
19556/// %v1 = shuffle %wide.vec, undef, <1, 3, 5, 7> ; Extract odd elements
19557///
19558/// Into:
19559/// %ld2 = { <4 x i32>, <4 x i32> } call llvm.aarch64.neon.ld2(%ptr)
19560/// %vec0 = extractelement { <4 x i32>, <4 x i32> } %ld2, i32 0
19561/// %vec1 = extractelement { <4 x i32>, <4 x i32> } %ld2, i32 1
19564 ArrayRef<unsigned> Indices, unsigned Factor, const APInt &GapMask) const {
19565 assert(Factor >= 2 && Factor <= getMaxSupportedInterleaveFactor() &&
19566 "Invalid interleave factor");
19567 assert(!Shuffles.empty() && "Empty shufflevector input");
19568 assert(Shuffles.size() == Indices.size() &&
19569 "Unmatched number of shufflevectors and indices");
19570
19571 auto *LI = dyn_cast<LoadInst>(Load);
19572 if (!LI)
19573 return false;
19574 assert(!Mask && GapMask.popcount() == Factor && "Unexpected mask on a load");
19575
19576 const DataLayout &DL = LI->getDataLayout();
19577
19578 VectorType *VTy = Shuffles[0]->getType();
19579
19580 // Skip if we do not have NEON and skip illegal vector types. We can
19581 // "legalize" wide vector types into multiple interleaved accesses as long as
19582 // the vector types are divisible by 128.
19583 bool UseScalable;
19584 if (!isLegalInterleavedAccessType(VTy, DL, UseScalable))
19585 return false;
19586
19587 // Check if the interleave is a zext(shuffle), that can be better optimized
19588 // into shift / and masks. For the moment we do this just for uitofp (not
19589 // zext) to avoid issues with widening instructions.
19590 if (Shuffles.size() == 4 && all_of(Shuffles, [](ShuffleVectorInst *SI) {
19591 using namespace llvm::PatternMatch;
19592 return SI->hasOneUse() && match(SI->user_back(), m_UIToFP(m_Value())) &&
19593 SI->getType()->getScalarSizeInBits() * 4 ==
19594 SI->user_back()->getType()->getScalarSizeInBits();
19595 }))
19596 return false;
19597
19598 unsigned NumLoads = getNumInterleavedAccesses(VTy, DL, UseScalable);
19599
19600 auto *FVTy = cast<FixedVectorType>(VTy);
19601
19602 // A pointer vector can not be the return type of the ldN intrinsics. Need to
19603 // load integer vectors first and then convert to pointer vectors.
19604 Type *EltTy = FVTy->getElementType();
19605 if (EltTy->isPointerTy())
19606 FVTy =
19607 FixedVectorType::get(DL.getIntPtrType(EltTy), FVTy->getNumElements());
19608
19609 // If we're going to generate more than one load, reset the sub-vector type
19610 // to something legal.
19611 FVTy = FixedVectorType::get(FVTy->getElementType(),
19612 FVTy->getNumElements() / NumLoads);
19613
19614 auto *LDVTy =
19615 UseScalable ? cast<VectorType>(getSVEContainerIRType(FVTy)) : FVTy;
19616
19617 IRBuilder<> Builder(LI);
19618
19619 // The base address of the load.
19620 Value *BaseAddr = LI->getPointerOperand();
19621
19622 Type *PtrTy = LI->getPointerOperandType();
19623 Type *PredTy = VectorType::get(Type::getInt1Ty(LDVTy->getContext()),
19624 LDVTy->getElementCount());
19625
19626 Function *LdNFunc = getStructuredLoadFunction(LI->getModule(), Factor,
19627 UseScalable, LDVTy, PtrTy);
19628
19629 // Holds sub-vectors extracted from the load intrinsic return values. The
19630 // sub-vectors are associated with the shufflevector instructions they will
19631 // replace.
19633
19634 Value *PTrue = nullptr;
19635 if (UseScalable) {
19636 if (DL.getTypeSizeInBits(FVTy) != Subtarget->getSVEVectorSizeInBits()) {
19637 std::optional<unsigned> PgPattern =
19638 getSVEPredPatternFromNumElements(FVTy->getNumElements());
19639 PTrue = Builder.CreateIntrinsic(Intrinsic::aarch64_sve_ptrue, PredTy,
19640 Builder.getInt32(*PgPattern));
19641 } else
19642 PTrue = ConstantInt::getTrue(PredTy);
19643 }
19644
19645 for (unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
19646
19647 // If we're generating more than one load, compute the base address of
19648 // subsequent loads as an offset from the previous.
19649 if (LoadCount > 0)
19650 BaseAddr = Builder.CreateConstGEP1_32(LDVTy->getElementType(), BaseAddr,
19651 FVTy->getNumElements() * Factor);
19652
19653 CallInst *LdN;
19654 if (UseScalable)
19655 LdN = Builder.CreateCall(LdNFunc, {PTrue, BaseAddr}, "ldN");
19656 else
19657 LdN = Builder.CreateCall(LdNFunc, BaseAddr, "ldN");
19658
19659 // Extract and store the sub-vectors returned by the load intrinsic.
19660 for (unsigned i = 0; i < Shuffles.size(); i++) {
19661 ShuffleVectorInst *SVI = Shuffles[i];
19662 unsigned Index = Indices[i];
19663
19664 Value *SubVec = Builder.CreateExtractValue(LdN, Index);
19665
19666 if (UseScalable)
19667 SubVec = Builder.CreateExtractVector(FVTy, SubVec, uint64_t(0));
19668
19669 // Convert the integer vector to pointer vector if the element is pointer.
19670 if (EltTy->isPointerTy())
19671 SubVec = Builder.CreateIntToPtr(
19673 FVTy->getNumElements()));
19674
19675 SubVecs[SVI].push_back(SubVec);
19676 }
19677 }
19678
19679 // Replace uses of the shufflevector instructions with the sub-vectors
19680 // returned by the load intrinsic. If a shufflevector instruction is
19681 // associated with more than one sub-vector, those sub-vectors will be
19682 // concatenated into a single wide vector.
19683 for (ShuffleVectorInst *SVI : Shuffles) {
19684 auto &SubVec = SubVecs[SVI];
19685 auto *WideVec =
19686 SubVec.size() > 1 ? concatenateVectors(Builder, SubVec) : SubVec[0];
19687 SVI->replaceAllUsesWith(WideVec);
19688 }
19689
19690 return true;
19691}
19692
19693template <typename Iter>
19694bool hasNearbyPairedStore(Iter It, Iter End, Value *Ptr, const DataLayout &DL) {
19695 int MaxLookupDist = 20;
19696 unsigned IdxWidth = DL.getIndexSizeInBits(0);
19697 APInt OffsetA(IdxWidth, 0), OffsetB(IdxWidth, 0);
19698 const Value *PtrA1 =
19700 /*AllowNonInbounds=*/true);
19701
19702 while (++It != End) {
19703 if (It->isDebugOrPseudoInst())
19704 continue;
19705 if (MaxLookupDist-- == 0)
19706 break;
19707 if (const auto *SI = dyn_cast<StoreInst>(&*It)) {
19708 const Value *PtrB1 =
19709 SI->getPointerOperand()->stripAndAccumulateConstantOffsets(
19710 DL, OffsetB, /*AllowNonInbounds=*/true);
19711 if (PtrA1 == PtrB1 &&
19712 (OffsetA.sextOrTrunc(IdxWidth) - OffsetB.sextOrTrunc(IdxWidth))
19713 .abs() == 16)
19714 return true;
19715 }
19716 }
19717
19718 return false;
19719}
19720
19721/// Lower an interleaved store into a stN intrinsic.
19722///
19723/// E.g. Lower an interleaved store (Factor = 3):
19724/// %i.vec = shuffle <8 x i32> %v0, <8 x i32> %v1,
19725/// <0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11>
19726/// store <12 x i32> %i.vec, <12 x i32>* %ptr
19727///
19728/// Into:
19729/// %sub.v0 = shuffle <8 x i32> %v0, <8 x i32> v1, <0, 1, 2, 3>
19730/// %sub.v1 = shuffle <8 x i32> %v0, <8 x i32> v1, <4, 5, 6, 7>
19731/// %sub.v2 = shuffle <8 x i32> %v0, <8 x i32> v1, <8, 9, 10, 11>
19732/// call void llvm.aarch64.neon.st3(%sub.v0, %sub.v1, %sub.v2, %ptr)
19733///
19734/// Note that the new shufflevectors will be removed and we'll only generate one
19735/// st3 instruction in CodeGen.
19736///
19737/// Example for a more general valid mask (Factor 3). Lower:
19738/// %i.vec = shuffle <32 x i32> %v0, <32 x i32> %v1,
19739/// <4, 32, 16, 5, 33, 17, 6, 34, 18, 7, 35, 19>
19740/// store <12 x i32> %i.vec, <12 x i32>* %ptr
19741///
19742/// Into:
19743/// %sub.v0 = shuffle <32 x i32> %v0, <32 x i32> v1, <4, 5, 6, 7>
19744/// %sub.v1 = shuffle <32 x i32> %v0, <32 x i32> v1, <32, 33, 34, 35>
19745/// %sub.v2 = shuffle <32 x i32> %v0, <32 x i32> v1, <16, 17, 18, 19>
19746/// call void llvm.aarch64.neon.st3(%sub.v0, %sub.v1, %sub.v2, %ptr)
19748 Value *LaneMask,
19749 ShuffleVectorInst *SVI,
19750 unsigned Factor,
19751 const APInt &GapMask) const {
19752
19753 assert(Factor >= 2 && Factor <= getMaxSupportedInterleaveFactor() &&
19754 "Invalid interleave factor");
19755 auto *SI = dyn_cast<StoreInst>(Store);
19756 if (!SI)
19757 return false;
19758 assert(!LaneMask && GapMask.popcount() == Factor &&
19759 "Unexpected mask on store");
19760
19761 auto *VecTy = cast<FixedVectorType>(SVI->getType());
19762 assert(VecTy->getNumElements() % Factor == 0 && "Invalid interleaved store");
19763
19764 unsigned LaneLen = VecTy->getNumElements() / Factor;
19765 Type *EltTy = VecTy->getElementType();
19766 auto *SubVecTy = FixedVectorType::get(EltTy, LaneLen);
19767
19768 const DataLayout &DL = SI->getDataLayout();
19769 bool UseScalable;
19770
19771 // Skip if we do not have NEON and skip illegal vector types. We can
19772 // "legalize" wide vector types into multiple interleaved accesses as long as
19773 // the vector types are divisible by 128.
19774 if (!isLegalInterleavedAccessType(SubVecTy, DL, UseScalable))
19775 return false;
19776
19777 unsigned NumStores = getNumInterleavedAccesses(SubVecTy, DL, UseScalable);
19778
19779 Value *Op0 = SVI->getOperand(0);
19780 Value *Op1 = SVI->getOperand(1);
19781 IRBuilder<> Builder(SI);
19782
19783 // StN intrinsics don't support pointer vectors as arguments. Convert pointer
19784 // vectors to integer vectors.
19785 if (EltTy->isPointerTy()) {
19786 Type *IntTy = DL.getIntPtrType(EltTy);
19787 unsigned NumOpElts =
19788 cast<FixedVectorType>(Op0->getType())->getNumElements();
19789
19790 // Convert to the corresponding integer vector.
19791 auto *IntVecTy = FixedVectorType::get(IntTy, NumOpElts);
19792 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
19793 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
19794
19795 SubVecTy = FixedVectorType::get(IntTy, LaneLen);
19796 }
19797
19798 // If we're going to generate more than one store, reset the lane length
19799 // and sub-vector type to something legal.
19800 LaneLen /= NumStores;
19801 SubVecTy = FixedVectorType::get(SubVecTy->getElementType(), LaneLen);
19802
19803 auto *STVTy = UseScalable ? cast<VectorType>(getSVEContainerIRType(SubVecTy))
19804 : SubVecTy;
19805
19806 // The base address of the store.
19807 Value *BaseAddr = SI->getPointerOperand();
19808
19809 auto Mask = SVI->getShuffleMask();
19810
19811 // Sanity check if all the indices are NOT in range.
19812 // If mask is `poison`, `Mask` may be a vector of -1s.
19813 // If all of them are `poison`, OOB read will happen later.
19814 if (llvm::all_of(Mask, equal_to(PoisonMaskElem))) {
19815 return false;
19816 }
19817 // A 64bit st2 which does not start at element 0 will involved adding extra
19818 // ext elements making the st2 unprofitable, and if there is a nearby store
19819 // that points to BaseAddr+16 or BaseAddr-16 then it can be better left as a
19820 // zip;ldp pair which has higher throughput.
19821 if (Factor == 2 && SubVecTy->getPrimitiveSizeInBits() == 64 &&
19822 (Mask[0] != 0 ||
19823 hasNearbyPairedStore(SI->getIterator(), SI->getParent()->end(), BaseAddr,
19824 DL) ||
19825 hasNearbyPairedStore(SI->getReverseIterator(), SI->getParent()->rend(),
19826 BaseAddr, DL)))
19827 return false;
19828
19829 // Conditionally skip nontemporal stores to prioritize emitting non-temporal
19830 // store instructions, even though AArch64 doesn't have non-temporal
19831 // interleaved stores.
19832 //
19833 // The check is conservative:
19834 //
19835 // - Only when not optimizing for size, as STNP lowering can increase size.
19836 // - Don't skip if the interleaving factor is greater than 2, as the shuffling
19837 // overhead becomes higher.
19838 // - Don't skip if the store value types which are not directly legal.
19839 Function *F = SI->getFunction();
19840 if (Factor == 2 && SI->hasMetadata(LLVMContext::MD_nontemporal) &&
19841 !F->hasOptSize() && !F->hasMinSize() &&
19842 isLegalNTStore(SI->getValueOperand()->getType(), SI->getAlign(), DL))
19843 return false;
19844
19845 Type *PtrTy = SI->getPointerOperandType();
19846 Type *PredTy = VectorType::get(Type::getInt1Ty(STVTy->getContext()),
19847 STVTy->getElementCount());
19848
19849 Function *StNFunc = getStructuredStoreFunction(SI->getModule(), Factor,
19850 UseScalable, STVTy, PtrTy);
19851
19852 Value *PTrue = nullptr;
19853 if (UseScalable) {
19854 if (DL.getTypeSizeInBits(SubVecTy) != Subtarget->getSVEVectorSizeInBits()) {
19855 std::optional<unsigned> PgPattern =
19856 getSVEPredPatternFromNumElements(SubVecTy->getNumElements());
19857 PTrue = Builder.CreateIntrinsic(Intrinsic::aarch64_sve_ptrue, PredTy,
19858 Builder.getInt32(*PgPattern));
19859 } else
19860 PTrue = ConstantInt::getTrue(PredTy);
19861 }
19862
19863 for (unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
19864
19866
19867 // Split the shufflevector operands into sub vectors for the new stN call.
19868 for (unsigned i = 0; i < Factor; i++) {
19869 Value *Shuffle;
19870 unsigned IdxI = StoreCount * LaneLen * Factor + i;
19871 if (Mask[IdxI] >= 0) {
19872 Shuffle = Builder.CreateShuffleVector(
19873 Op0, Op1, createSequentialMask(Mask[IdxI], LaneLen, 0));
19874 } else {
19875 unsigned StartMask = 0;
19876 for (unsigned j = 1; j < LaneLen; j++) {
19877 unsigned IdxJ = StoreCount * LaneLen * Factor + j * Factor + i;
19878 if (Mask[IdxJ] >= 0) {
19879 StartMask = Mask[IdxJ] - j;
19880 break;
19881 }
19882 }
19883 // Note: Filling undef gaps with random elements is ok, since
19884 // those elements were being written anyway (with undefs).
19885 // In the case of all undefs we're defaulting to using elems from 0
19886 // Note: StartMask cannot be negative, it's checked in
19887 // isReInterleaveMask
19888 Shuffle = Builder.CreateShuffleVector(
19889 Op0, Op1, createSequentialMask(StartMask, LaneLen, 0));
19890 }
19891
19892 if (UseScalable)
19893 Shuffle = Builder.CreateInsertVector(STVTy, PoisonValue::get(STVTy),
19894 Shuffle, uint64_t(0));
19895
19896 Ops.push_back(Shuffle);
19897 }
19898
19899 if (UseScalable)
19900 Ops.push_back(PTrue);
19901
19902 // If we generating more than one store, we compute the base address of
19903 // subsequent stores as an offset from the previous.
19904 if (StoreCount > 0)
19905 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
19906 BaseAddr, LaneLen * Factor);
19907
19908 Ops.push_back(BaseAddr);
19909 Builder.CreateCall(StNFunc, Ops);
19910 }
19911 return true;
19912}
19913
19915 Instruction *Load, Value *Mask, IntrinsicInst *DI,
19916 const APInt &GapMask) const {
19917 const unsigned Factor = getDeinterleaveIntrinsicFactor(DI->getIntrinsicID());
19918 assert(GapMask.getBitWidth() == Factor);
19919 if (Factor != 2 && Factor != 3 && Factor != 4) {
19920 LLVM_DEBUG(dbgs() << "Matching ld2, ld3 and ld4 patterns failed\n");
19921 return false;
19922 }
19923 auto *LI = dyn_cast<LoadInst>(Load);
19924 if (!LI)
19925 return false;
19926 assert(!Mask && "Unexpected mask on a load\n");
19927
19928 // Gap mask is currently not supported.
19929 if (!GapMask.isAllOnes())
19930 return false;
19931
19933
19934 const DataLayout &DL = LI->getModule()->getDataLayout();
19935 bool UseScalable;
19936 if (!isLegalInterleavedAccessType(VTy, DL, UseScalable))
19937 return false;
19938
19939 // TODO: Add support for using SVE instructions with fixed types later, using
19940 // the code from lowerInterleavedLoad to obtain the correct container type.
19941 if (UseScalable && !VTy->isScalableTy())
19942 return false;
19943
19944 unsigned NumLoads = getNumInterleavedAccesses(VTy, DL, UseScalable);
19945 VectorType *LdTy =
19947 VTy->getElementCount().divideCoefficientBy(NumLoads));
19948
19949 Type *PtrTy = LI->getPointerOperandType();
19950 Function *LdNFunc = getStructuredLoadFunction(LI->getModule(), Factor,
19951 UseScalable, LdTy, PtrTy);
19952
19953 IRBuilder<> Builder(LI);
19954 Value *Pred = nullptr;
19955 if (UseScalable)
19956 Pred =
19957 Builder.CreateVectorSplat(LdTy->getElementCount(), Builder.getTrue());
19958
19959 Value *BaseAddr = LI->getPointerOperand();
19960 Value *Result = nullptr;
19961 if (NumLoads > 1) {
19962 // Create multiple legal small ldN.
19963 SmallVector<Value *, 4> ExtractedLdValues(Factor, PoisonValue::get(VTy));
19964 for (unsigned I = 0; I < NumLoads; ++I) {
19965 Value *Offset = Builder.getInt64(I * Factor);
19966
19967 Value *Address = Builder.CreateGEP(LdTy, BaseAddr, {Offset});
19968 Value *LdN = nullptr;
19969 if (UseScalable)
19970 LdN = Builder.CreateCall(LdNFunc, {Pred, Address}, "ldN");
19971 else
19972 LdN = Builder.CreateCall(LdNFunc, Address, "ldN");
19973 Value *Idx =
19974 Builder.getInt64(I * LdTy->getElementCount().getKnownMinValue());
19975 for (unsigned J = 0; J < Factor; ++J) {
19976 ExtractedLdValues[J] = Builder.CreateInsertVector(
19977 VTy, ExtractedLdValues[J], Builder.CreateExtractValue(LdN, J), Idx);
19978 }
19979 LLVM_DEBUG(dbgs() << "LdN4 res: "; LdN->dump());
19980 }
19981
19982 // Merge the values from different factors.
19983 Result = PoisonValue::get(DI->getType());
19984 for (unsigned J = 0; J < Factor; ++J)
19985 Result = Builder.CreateInsertValue(Result, ExtractedLdValues[J], J);
19986 } else {
19987 if (UseScalable)
19988 Result = Builder.CreateCall(LdNFunc, {Pred, BaseAddr}, "ldN");
19989 else
19990 Result = Builder.CreateCall(LdNFunc, BaseAddr, "ldN");
19991 }
19992
19993 // Replace output of deinterleave2 intrinsic by output of ldN2/ldN4
19994 DI->replaceAllUsesWith(Result);
19995 return true;
19996}
19997
19999 Instruction *Store, Value *Mask,
20000 ArrayRef<Value *> InterleavedValues) const {
20001 unsigned Factor = InterleavedValues.size();
20002 if (Factor != 2 && Factor != 3 && Factor != 4) {
20003 LLVM_DEBUG(dbgs() << "Matching st2, st3 and st4 patterns failed\n");
20004 return false;
20005 }
20007 if (!SI)
20008 return false;
20009 assert(!Mask && "Unexpected mask on plain store");
20010
20011 VectorType *VTy = cast<VectorType>(InterleavedValues[0]->getType());
20012 const DataLayout &DL = SI->getModule()->getDataLayout();
20013
20014 bool UseScalable;
20015 if (!isLegalInterleavedAccessType(VTy, DL, UseScalable))
20016 return false;
20017
20018 // TODO: Add support for using SVE instructions with fixed types later, using
20019 // the code from lowerInterleavedStore to obtain the correct container type.
20020 if (UseScalable && !VTy->isScalableTy())
20021 return false;
20022
20023 unsigned NumStores = getNumInterleavedAccesses(VTy, DL, UseScalable);
20024
20025 VectorType *StTy =
20027 VTy->getElementCount().divideCoefficientBy(NumStores));
20028
20029 Type *PtrTy = SI->getPointerOperandType();
20030 Function *StNFunc = getStructuredStoreFunction(SI->getModule(), Factor,
20031 UseScalable, StTy, PtrTy);
20032
20033 IRBuilder<> Builder(SI);
20034
20035 Value *BaseAddr = SI->getPointerOperand();
20036 Value *Pred = nullptr;
20037
20038 if (UseScalable)
20039 Pred =
20040 Builder.CreateVectorSplat(StTy->getElementCount(), Builder.getTrue());
20041
20042 auto ExtractedValues = InterleavedValues;
20043 SmallVector<Value *, 4> StoreOperands(InterleavedValues);
20044 if (UseScalable)
20045 StoreOperands.push_back(Pred);
20046 StoreOperands.push_back(BaseAddr);
20047 for (unsigned I = 0; I < NumStores; ++I) {
20048 Value *Address = BaseAddr;
20049 if (NumStores > 1) {
20050 Value *Offset = Builder.getInt64(I * Factor);
20051 Address = Builder.CreateGEP(StTy, BaseAddr, {Offset});
20052 Value *Idx =
20053 Builder.getInt64(I * StTy->getElementCount().getKnownMinValue());
20054 for (unsigned J = 0; J < Factor; J++) {
20055 StoreOperands[J] =
20056 Builder.CreateExtractVector(StTy, ExtractedValues[J], Idx);
20057 }
20058 // update the address
20059 StoreOperands[StoreOperands.size() - 1] = Address;
20060 }
20061 Builder.CreateCall(StNFunc, StoreOperands);
20062 }
20063 return true;
20064}
20065
20067 LLVMContext &Context, const MemOp &Op,
20068 const AttributeList &FuncAttributes) const {
20069 bool CanImplicitFloat = !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat);
20070 bool CanUseNEON = Subtarget->hasNEON() && CanImplicitFloat;
20071 bool CanUseFP = Subtarget->hasFPARMv8() && CanImplicitFloat;
20072 // For zero memset, only use AdvSIMD for 32-byte and above. It would have
20073 // taken one instruction to materialize the v2i64 zero and one store (with
20074 // restrictive addressing mode). Just do i64 stores.
20075 // For non-zero memset, use NEON even for smaller sizes as dup is efficient.
20076 bool IsSmallZeroMemset = Op.isMemset() && Op.size() < 32 && Op.isZeroMemset();
20077 auto AlignmentIsAcceptable = [&](EVT VT, Align AlignCheck) {
20078 if (Op.isAligned(AlignCheck))
20079 return true;
20080 unsigned Fast;
20081 return allowsMisalignedMemoryAccesses(VT, 0, Align(1),
20083 Fast;
20084 };
20085
20086 // For non-zero memset, use NEON even for smaller sizes as dup + scalar store
20087 // is efficient
20088 if (CanUseNEON && Op.isMemset() && !IsSmallZeroMemset &&
20089 AlignmentIsAcceptable(MVT::v16i8, Align(1)))
20090 return MVT::v16i8;
20091 if (CanUseFP && !IsSmallZeroMemset &&
20092 AlignmentIsAcceptable(MVT::f128, Align(16)))
20093 return MVT::f128;
20094 if (Op.size() >= 8 && AlignmentIsAcceptable(MVT::i64, Align(8)))
20095 return MVT::i64;
20096 if (Op.size() >= 4 && AlignmentIsAcceptable(MVT::i32, Align(4)))
20097 return MVT::i32;
20098 return MVT::Other;
20099}
20100
20102 LLVMContext &Context, std::vector<EVT> &MemOps, unsigned Limit,
20103 const MemOp &Op, unsigned DstAS, unsigned SrcAS,
20104 const AttributeList &FuncAttributes, EVT *LargestVT) const {
20105 // For non-zero memset with v16i8, don't downgrade. We can extract smaller
20106 // stores (i64, i32, i16, i8) from the v16i8 splat efficiently.
20107 EVT VT = getOptimalMemOpType(Context, Op, FuncAttributes);
20108 if (VT == MVT::v16i8 && Op.isMemset() && !Op.isZeroMemset() &&
20109 Op.size() < 16) {
20110 unsigned Size = Op.size();
20111 unsigned RemainingSize = Size;
20112
20113 // Break down the size into stores that we can extract from v16i8.
20114 // We support: i64 (8 bytes), i32 (4 bytes), i16 (2 bytes), i8 (1 byte)
20115 // Use the largest possible stores first to minimize the number of
20116 // operations.
20117 while (RemainingSize > 0) {
20118 EVT TargetVT;
20119
20120 // Try largest stores first
20121 if (RemainingSize >= 8) {
20122 TargetVT = MVT::i64;
20123 RemainingSize -= 8;
20124 } else if (RemainingSize >= 4) {
20125 TargetVT = MVT::i32;
20126 RemainingSize -= 4;
20127 } else if (RemainingSize >= 2) {
20128 TargetVT = MVT::i16;
20129 RemainingSize -= 2;
20130 } else if (RemainingSize >= 1) {
20131 TargetVT = MVT::i8;
20132 RemainingSize -= 1;
20133 } else {
20134 // Should not reach here, but fall back to default implementation
20135 break;
20136 }
20137
20138 MemOps.push_back(TargetVT);
20139 }
20140
20141 // If we successfully decomposed the entire size, set LargestVT to v16i8
20142 // to ensure getMemsetValue generates the efficient vector splat (DUP).
20143 // We don't add v16i8 to MemOps since we only need it for value generation.
20144 if (RemainingSize == 0 && !MemOps.empty()) {
20145 if (LargestVT)
20146 *LargestVT = VT; // v16i8 for vector splat generation
20147 return true;
20148 }
20149
20150 // Clear MemOps if we didn't successfully handle everything
20151 MemOps.clear();
20152 }
20153 // Otherwise, use the default implementation
20155 Context, MemOps, Limit, Op, DstAS, SrcAS, FuncAttributes, LargestVT);
20156}
20157
20159 const MemOp &Op, const AttributeList &FuncAttributes) const {
20160 bool CanImplicitFloat = !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat);
20161 bool CanUseNEON = Subtarget->hasNEON() && CanImplicitFloat;
20162 bool CanUseFP = Subtarget->hasFPARMv8() && CanImplicitFloat;
20163 // For zero memset, only use AdvSIMD for 32-byte and above. It would have
20164 // taken one instruction to materialize the v2i64 zero and one store (with
20165 // restrictive addressing mode). Just do i64 stores.
20166 // For non-zero memset, use NEON even for smaller sizes as dup is efficient.
20167 bool IsSmallZeroMemset = Op.isMemset() && Op.size() < 32 && Op.isZeroMemset();
20168 auto AlignmentIsAcceptable = [&](EVT VT, Align AlignCheck) {
20169 if (Op.isAligned(AlignCheck))
20170 return true;
20171 unsigned Fast;
20172 return allowsMisalignedMemoryAccesses(VT, 0, Align(1),
20174 Fast;
20175 };
20176
20177 // For non-zero memset, use NEON for all sizes where it's beneficial.
20178 // NEON dup + scalar store works for any alignment and is efficient.
20179 if (CanUseNEON && Op.isMemset() && !IsSmallZeroMemset &&
20180 AlignmentIsAcceptable(MVT::v16i8, Align(1)))
20181 return LLT::fixed_vector(2, LLT::integer(64));
20182 if (CanUseFP && !IsSmallZeroMemset &&
20183 AlignmentIsAcceptable(MVT::f128, Align(16)))
20184 return LLT::floatIEEE(128);
20185 if (Op.size() >= 8 && AlignmentIsAcceptable(MVT::i64, Align(8)))
20186 return LLT::integer(64);
20187 if (Op.size() >= 4 && AlignmentIsAcceptable(MVT::i32, Align(4)))
20188 return LLT::integer(32);
20189 return LLT();
20190}
20191
20192// 12-bit optionally shifted immediates are legal for adds.
20194 if (Immed == std::numeric_limits<int64_t>::min()) {
20195 return false;
20196 }
20197 // Same encoding for add/sub, just flip the sign.
20198 return AArch64_AM::isLegalArithImmed((uint64_t)std::abs(Immed));
20199}
20200
20202 // We will only emit addvl/inc* instructions if the subtarget allows it.
20203 if (!Subtarget->useScalarIncVL())
20204 return false;
20205
20206 // addvl's immediates are in terms of the number of bytes in a register.
20207 // Since there are 16 in the base supported size (128bits), we need to
20208 // divide the immediate by that much to give us a useful immediate to
20209 // multiply by vscale. We can't have a remainder as a result of this.
20210 if (Imm % 16 == 0)
20211 return isInt<6>(Imm / 16);
20212
20213 // Inc[b|h|w|d] instructions take a pattern and a positive immediate
20214 // multiplier. For now, assume a pattern of 'all'. Incb would be a subset
20215 // of addvl as a result, so only take h|w|d into account.
20216 // Dec[h|w|d] will cover subtractions.
20217 // Immediates are in the range [1,16], so we can't do a 2's complement check.
20218 // FIXME: Can we make use of other patterns to cover other immediates?
20219
20220 // inch|dech
20221 if (Imm % 8 == 0)
20222 return std::abs(Imm / 8) <= 16;
20223 // incw|decw
20224 if (Imm % 4 == 0)
20225 return std::abs(Imm / 4) <= 16;
20226 // incd|decd
20227 if (Imm % 2 == 0)
20228 return std::abs(Imm / 2) <= 16;
20229
20230 return false;
20231}
20232
20233// Return false to prevent folding
20234// (mul (add x, c1), c2) -> (add (mul x, c2), c2*c1) in DAGCombine,
20235// if the folding leads to worse code.
20237 SDValue AddNode, SDValue ConstNode) const {
20238 // Let the DAGCombiner decide for vector types and large types.
20239 const EVT VT = AddNode.getValueType();
20240 if (VT.isVector() || VT.getScalarSizeInBits() > 64)
20241 return true;
20242
20243 // It is worse if c1 is legal add immediate, while c1*c2 is not
20244 // and has to be composed by at least two instructions.
20245 const ConstantSDNode *C1Node = cast<ConstantSDNode>(AddNode.getOperand(1));
20246 const ConstantSDNode *C2Node = cast<ConstantSDNode>(ConstNode);
20247 const int64_t C1 = C1Node->getSExtValue();
20248 const APInt C1C2 = C1Node->getAPIntValue() * C2Node->getAPIntValue();
20250 return true;
20252 // Adapt to the width of a register.
20253 unsigned BitSize = VT.getSizeInBits() <= 32 ? 32 : 64;
20254 AArch64_IMM::expandMOVImm(C1C2.getZExtValue(), BitSize, Insn);
20255 if (Insn.size() > 1)
20256 return false;
20257
20258 // Default to true and let the DAGCombiner decide.
20259 return true;
20260}
20261
20262// Integer comparisons are implemented with ADDS/SUBS, so the range of valid
20263// immediates is the same as for an add or a sub.
20265 return isLegalAddImmediate(Immed);
20266}
20267
20268/// isLegalAddressingMode - Return true if the addressing mode represented
20269/// by AM is legal for this target, for a load/store of the specified type.
20271 const AddrMode &AMode, Type *Ty,
20272 unsigned AS, Instruction *I) const {
20273 // AArch64 has five basic addressing modes:
20274 // reg
20275 // reg + 9-bit signed offset
20276 // reg + SIZE_IN_BYTES * 12-bit unsigned offset
20277 // reg1 + reg2
20278 // reg + SIZE_IN_BYTES * reg
20279
20280 // No global is ever allowed as a base.
20281 if (AMode.BaseGV)
20282 return false;
20283
20284 // No reg+reg+imm addressing.
20285 if (AMode.HasBaseReg && AMode.BaseOffs && AMode.Scale)
20286 return false;
20287
20288 // Canonicalise `1*ScaledReg + imm` into `BaseReg + imm` and
20289 // `2*ScaledReg` into `BaseReg + ScaledReg`
20290 AddrMode AM = AMode;
20291 if (AM.Scale && !AM.HasBaseReg) {
20292 if (AM.Scale == 1) {
20293 AM.HasBaseReg = true;
20294 AM.Scale = 0;
20295 } else if (AM.Scale == 2) {
20296 AM.HasBaseReg = true;
20297 AM.Scale = 1;
20298 } else {
20299 return false;
20300 }
20301 }
20302
20303 // A base register is required in all addressing modes.
20304 if (!AM.HasBaseReg)
20305 return false;
20306
20307 if (Ty->isScalableTy()) {
20308 if (isa<ScalableVectorType>(Ty)) {
20309 // See if we have a foldable vscale-based offset, for vector types which
20310 // are either legal or smaller than the minimum; more work will be
20311 // required if we need to consider addressing for types which need
20312 // legalization by splitting.
20313 uint64_t VecNumBytes = DL.getTypeSizeInBits(Ty).getKnownMinValue() / 8;
20314 if (AM.HasBaseReg && !AM.BaseOffs && AM.ScalableOffset && !AM.Scale &&
20315 (AM.ScalableOffset % VecNumBytes == 0) && VecNumBytes <= 16 &&
20316 isPowerOf2_64(VecNumBytes))
20317 return isInt<4>(AM.ScalableOffset / (int64_t)VecNumBytes);
20318
20319 uint64_t VecElemNumBytes =
20320 DL.getTypeSizeInBits(cast<VectorType>(Ty)->getElementType()) / 8;
20321 return AM.HasBaseReg && !AM.BaseOffs && !AM.ScalableOffset &&
20322 (AM.Scale == 0 || (uint64_t)AM.Scale == VecElemNumBytes);
20323 }
20324
20325 return AM.HasBaseReg && !AM.BaseOffs && !AM.ScalableOffset && !AM.Scale;
20326 }
20327
20328 // No scalable offsets allowed for non-scalable types.
20329 if (AM.ScalableOffset)
20330 return false;
20331
20332 // check reg + imm case:
20333 // i.e., reg + 0, reg + imm9, reg + SIZE_IN_BYTES * uimm12
20334 uint64_t NumBytes = 0;
20335 if (Ty->isSized()) {
20336 uint64_t NumBits = DL.getTypeSizeInBits(Ty);
20337 NumBytes = NumBits / 8;
20338 if (!isPowerOf2_64(NumBits))
20339 NumBytes = 0;
20340 }
20341
20342 return Subtarget->getInstrInfo()->isLegalAddressingMode(NumBytes, AM.BaseOffs,
20343 AM.Scale);
20344}
20345
20346// Check whether the 2 offsets belong to the same imm24 range, and their high
20347// 12bits are same, then their high part can be decoded with the offset of add.
20348int64_t
20350 int64_t MaxOffset) const {
20351 int64_t HighPart = MinOffset & ~0xfffULL;
20352 if (MinOffset >> 12 == MaxOffset >> 12 && isLegalAddImmediate(HighPart)) {
20353 // Rebase the value to an integer multiple of imm12.
20354 return HighPart;
20355 }
20356
20357 return 0;
20358}
20359
20361 // Consider splitting large offset of struct or array.
20362 return true;
20363}
20364
20366 const MachineFunction &MF, EVT VT) const {
20367 EVT ScalarVT = VT.getScalarType();
20368
20369 if (!ScalarVT.isSimple())
20370 return false;
20371
20372 switch (ScalarVT.getSimpleVT().SimpleTy) {
20373 case MVT::f16:
20374 return Subtarget->hasFullFP16();
20375 case MVT::f32:
20376 case MVT::f64:
20377 return Subtarget->hasFPARMv8();
20378 case MVT::bf16:
20379 return VT.isScalableVector() &&
20380 (Subtarget->hasBF16() || Subtarget->hasSVEB16B16());
20381 default:
20382 break;
20383 }
20384
20385 return false;
20386}
20387
20389 Type *Ty) const {
20390 switch (Ty->getScalarType()->getTypeID()) {
20391 case Type::FloatTyID:
20392 case Type::DoubleTyID:
20393 return Subtarget->hasFPARMv8();
20394 default:
20395 return false;
20396 }
20397}
20398
20400 EVT VT, CodeGenOptLevel OptLevel) const {
20401 return (OptLevel >= CodeGenOptLevel::Aggressive) && !VT.isScalableVector() &&
20403}
20404
20405const MCPhysReg *
20407 // LR is a callee-save register, but we must treat it as clobbered by any call
20408 // site. Hence we include LR in the scratch registers, which are in turn added
20409 // as implicit-defs for stackmaps and patchpoints.
20410 static const MCPhysReg ScratchRegs[] = {
20411 AArch64::X16, AArch64::X17, AArch64::LR, 0
20412 };
20413 return ScratchRegs;
20414}
20415
20417 static const MCPhysReg RCRegs[] = {AArch64::FPCR};
20418 return RCRegs;
20419}
20420
20422 EVT DestVT) const {
20423 return isTypeLegal(DestVT) && DestVT.isVector();
20424}
20425
20426bool
20428 CombineLevel Level) const {
20429 assert((N->getOpcode() == ISD::SHL || N->getOpcode() == ISD::SRA ||
20430 N->getOpcode() == ISD::SRL) &&
20431 "Expected shift op");
20432
20433 SDValue ShiftLHS = N->getOperand(0);
20434 EVT VT = N->getValueType(0);
20435
20436 if (!ShiftLHS->hasOneUse())
20437 return false;
20438
20439 if (ShiftLHS.getOpcode() == ISD::SIGN_EXTEND &&
20440 !ShiftLHS.getOperand(0)->hasOneUse())
20441 return false;
20442
20443 // If ShiftLHS is unsigned bit extraction: ((x >> C) & mask), then do not
20444 // combine it with shift 'N' to let it be lowered to UBFX except:
20445 // ((x >> C) & mask) << C.
20446 if (ShiftLHS.getOpcode() == ISD::AND && (VT == MVT::i32 || VT == MVT::i64) &&
20447 isa<ConstantSDNode>(ShiftLHS.getOperand(1))) {
20448 uint64_t TruncMask = ShiftLHS.getConstantOperandVal(1);
20449 if (isMask_64(TruncMask)) {
20450 SDValue AndLHS = ShiftLHS.getOperand(0);
20451 if (AndLHS.getOpcode() == ISD::SRL) {
20452 if (auto *SRLC = dyn_cast<ConstantSDNode>(AndLHS.getOperand(1))) {
20453 if (N->getOpcode() == ISD::SHL)
20454 if (auto *SHLC = dyn_cast<ConstantSDNode>(N->getOperand(1)))
20455 return SRLC->getZExtValue() == SHLC->getZExtValue();
20456 return false;
20457 }
20458 }
20459 }
20460 }
20461 return true;
20462}
20463
20465 const SDNode *N) const {
20466 assert(N->getOpcode() == ISD::XOR &&
20467 (N->getOperand(0).getOpcode() == ISD::SHL ||
20468 N->getOperand(0).getOpcode() == ISD::SRL) &&
20469 "Expected XOR(SHIFT) pattern");
20470
20471 // Only commute if the entire NOT mask is a hidden shifted mask.
20472 auto *XorC = dyn_cast<ConstantSDNode>(N->getOperand(1));
20473 auto *ShiftC = dyn_cast<ConstantSDNode>(N->getOperand(0).getOperand(1));
20474 if (XorC && ShiftC) {
20475 unsigned MaskIdx, MaskLen;
20476 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
20477 unsigned ShiftAmt = ShiftC->getZExtValue();
20478 unsigned BitWidth = N->getValueType(0).getScalarSizeInBits();
20479 if (N->getOperand(0).getOpcode() == ISD::SHL)
20480 return MaskIdx == ShiftAmt && MaskLen == (BitWidth - ShiftAmt);
20481 return MaskIdx == 0 && MaskLen == (BitWidth - ShiftAmt);
20482 }
20483 }
20484
20485 return false;
20486}
20487
20489 const SDNode *N) const {
20490 assert(((N->getOpcode() == ISD::SHL &&
20491 N->getOperand(0).getOpcode() == ISD::SRL) ||
20492 (N->getOpcode() == ISD::SRL &&
20493 N->getOperand(0).getOpcode() == ISD::SHL)) &&
20494 "Expected shift-shift mask");
20495 // Don't allow multiuse shift folding with the same shift amount.
20496 if (!N->getOperand(0)->hasOneUse())
20497 return false;
20498
20499 // Only fold srl(shl(x,c1),c2) iff C1 >= C2 to prevent loss of UBFX patterns.
20500 EVT VT = N->getValueType(0);
20501 if (N->getOpcode() == ISD::SRL && (VT == MVT::i32 || VT == MVT::i64)) {
20502 auto *C1 = dyn_cast<ConstantSDNode>(N->getOperand(0).getOperand(1));
20503 auto *C2 = dyn_cast<ConstantSDNode>(N->getOperand(1));
20504 return (!C1 || !C2 || C1->getZExtValue() >= C2->getZExtValue());
20505 }
20506
20507 // We do not need to fold when this shifting used in specific load case:
20508 // (ldr x, (add x, (shl (srl x, c1) 2)))
20509 if (N->getOpcode() == ISD::SHL && N->hasOneUse()) {
20510 if (auto C2 = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
20511 unsigned ShlAmt = C2->getZExtValue();
20512 if (auto ShouldADD = *N->user_begin();
20513 ShouldADD->getOpcode() == ISD::ADD && ShouldADD->hasOneUse()) {
20514 if (auto Load = dyn_cast<LoadSDNode>(*ShouldADD->user_begin())) {
20515 EVT MemVT = Load->getMemoryVT();
20516
20517 if (Load->getValueType(0).isScalableVector())
20518 return (8ULL << ShlAmt) != MemVT.getScalarSizeInBits();
20519
20520 if (isIndexedLoadLegal(ISD::PRE_INC, MemVT))
20521 return (8ULL << ShlAmt) != MemVT.getFixedSizeInBits();
20522 }
20523 }
20524 }
20525 }
20526
20527 return true;
20528}
20529
20531 unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X,
20532 SDValue Y) const {
20533 return VT.isScalableVector() && isTypeLegal(VT) &&
20534 SelectOpcode == ISD::VSELECT;
20535}
20536
20538 Type *Ty) const {
20539 assert(Ty->isIntegerTy());
20540
20541 unsigned BitSize = Ty->getPrimitiveSizeInBits();
20542 if (BitSize == 0)
20543 return false;
20544
20545 int64_t Val = Imm.getSExtValue();
20546 if (Val == 0 || AArch64_AM::isLogicalImmediate(Val, BitSize))
20547 return true;
20548
20549 if (Val < 0)
20550 Val = ~Val;
20551 if (BitSize == 32)
20552 Val &= (1LL << 32) - 1;
20553
20554 unsigned Shift = llvm::Log2_64((uint64_t)Val) / 16;
20555 // MOVZ is free so return true for one or fewer MOVK.
20556 return Shift < 3;
20557}
20558
20561 unsigned Index) const {
20564
20565 if (Index == 0)
20567
20568 if (Index == ResVT.getVectorMinNumElements())