LLVM 24.0.0git
HexagonISelLoweringHVX.cpp
Go to the documentation of this file.
1//===-- HexagonISelLoweringHVX.cpp --- Lowering HVX operations ------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "HexagonRegisterInfo.h"
11#include "HexagonSubtarget.h"
12#include "llvm/ADT/SetVector.h"
21#include "llvm/IR/IntrinsicsHexagon.h"
23
24#include <algorithm>
25#include <string>
26#include <utility>
27
28using namespace llvm;
29
30static cl::opt<unsigned> HvxWidenThreshold("hexagon-hvx-widen",
32 cl::desc("Lower threshold (in bytes) for widening to HVX vectors"));
33
34static cl::opt<bool>
35 EnableFpFastConvert("hexagon-fp-fast-convert", cl::Hidden, cl::init(false),
36 cl::desc("Enable FP fast conversion routine."));
37
38static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 };
39static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
40static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
41static const MVT LegalW128[] = { MVT::v256i8, MVT::v128i16, MVT::v64i32 };
42
43static const unsigned MaxExpandMLA = 8;
44
45static std::tuple<unsigned, unsigned, unsigned> getIEEEProperties(MVT Ty) {
46 // For a float scalar type, return (exp-bits, exp-bias, fraction-bits)
47 MVT ElemTy = Ty.getScalarType();
48 switch (ElemTy.SimpleTy) {
49 case MVT::f16:
50 return std::make_tuple(5, 15, 10);
51 case MVT::f32:
52 return std::make_tuple(8, 127, 23);
53 case MVT::f64:
54 return std::make_tuple(11, 1023, 52);
55 default:
56 break;
57 }
58 llvm_unreachable(("Unexpected type: " + EVT(ElemTy).getEVTString()).c_str());
59}
60
61void
62HexagonTargetLowering::initializeHVXLowering() {
63 if (Subtarget.useHVX64BOps()) {
64 addRegisterClass(MVT::v64i8, &Hexagon::HvxVRRegClass);
65 addRegisterClass(MVT::v32i16, &Hexagon::HvxVRRegClass);
66 addRegisterClass(MVT::v16i32, &Hexagon::HvxVRRegClass);
67 addRegisterClass(MVT::v128i8, &Hexagon::HvxWRRegClass);
68 addRegisterClass(MVT::v64i16, &Hexagon::HvxWRRegClass);
69 addRegisterClass(MVT::v32i32, &Hexagon::HvxWRRegClass);
70 // These "short" boolean vector types should be legal because
71 // they will appear as results of vector compares. If they were
72 // not legal, type legalization would try to make them legal
73 // and that would require using operations that do not use or
74 // produce such types. That, in turn, would imply using custom
75 // nodes, which would be unoptimizable by the DAG combiner.
76 // The idea is to rely on target-independent operations as much
77 // as possible.
78 addRegisterClass(MVT::v16i1, &Hexagon::HvxQRRegClass);
79 addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass);
80 addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass);
81 } else if (Subtarget.useHVX128BOps()) {
82 addRegisterClass(MVT::v128i8, &Hexagon::HvxVRRegClass);
83 addRegisterClass(MVT::v64i16, &Hexagon::HvxVRRegClass);
84 addRegisterClass(MVT::v32i32, &Hexagon::HvxVRRegClass);
85 addRegisterClass(MVT::v256i8, &Hexagon::HvxWRRegClass);
86 addRegisterClass(MVT::v128i16, &Hexagon::HvxWRRegClass);
87 addRegisterClass(MVT::v64i32, &Hexagon::HvxWRRegClass);
88 addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass);
89 addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass);
90 addRegisterClass(MVT::v128i1, &Hexagon::HvxQRRegClass);
91 if (Subtarget.useHVXV68Ops() && Subtarget.useHVXFloatingPoint()) {
92 addRegisterClass(MVT::v32f32, &Hexagon::HvxVRRegClass);
93 addRegisterClass(MVT::v64f16, &Hexagon::HvxVRRegClass);
94 addRegisterClass(MVT::v64f32, &Hexagon::HvxWRRegClass);
95 addRegisterClass(MVT::v128f16, &Hexagon::HvxWRRegClass);
96 }
97 if (Subtarget.useHVXV81Ops()) {
98 addRegisterClass(MVT::v64bf16, &Hexagon::HvxVRRegClass);
99 addRegisterClass(MVT::v128bf16, &Hexagon::HvxWRRegClass);
100 }
101 }
102
103 // Set up operation actions.
104
105 bool Use64b = Subtarget.useHVX64BOps();
106 ArrayRef<MVT> LegalV = Use64b ? LegalV64 : LegalV128;
107 ArrayRef<MVT> LegalW = Use64b ? LegalW64 : LegalW128;
108 MVT ByteV = Use64b ? MVT::v64i8 : MVT::v128i8;
109 MVT WordV = Use64b ? MVT::v16i32 : MVT::v32i32;
110 MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8;
111
112 auto setPromoteTo = [this] (unsigned Opc, MVT FromTy, MVT ToTy) {
114 AddPromotedToType(Opc, FromTy, ToTy);
115 };
116
117 // Handle bitcasts of vector predicates to scalars (e.g. v32i1 to i32).
118 // Note: v16i1 -> i16 is handled in type legalization instead of op
119 // legalization.
129
130 if (Subtarget.useHVX128BOps()) {
134 setOperationAction(ISD::LOAD, MVT::v32i1, Custom);
136 setOperationAction(ISD::LOAD, MVT::v64i1, Custom);
137 setOperationAction(ISD::STORE, MVT::v128i1, Custom);
138 setOperationAction(ISD::LOAD, MVT::v128i1, Custom);
139 }
140 if (Subtarget.useHVX128BOps() && Subtarget.useHVXV68Ops() &&
141 Subtarget.useHVXFloatingPoint()) {
142
143 static const MVT FloatV[] = { MVT::v64f16, MVT::v32f32 };
144 static const MVT FloatW[] = { MVT::v128f16, MVT::v64f32 };
145
146 for (MVT T : FloatV) {
160
163
166
169 // Custom-lower BUILD_VECTOR. The standard (target-independent)
170 // handling of it would convert it to a load, which is not always
171 // the optimal choice.
173 }
174
175
176 // BUILD_VECTOR with f16 operands cannot be promoted without
177 // promoting the result, so lower the node to vsplat or constant pool
181
182 // Vector shuffle is always promoted to ByteV and a bitcast to f16 is
183 // generated.
184 setPromoteTo(ISD::VECTOR_SHUFFLE, MVT::v128f16, ByteW);
185 setPromoteTo(ISD::VECTOR_SHUFFLE, MVT::v64f16, ByteV);
186 setPromoteTo(ISD::VECTOR_SHUFFLE, MVT::v64f32, ByteW);
187 setPromoteTo(ISD::VECTOR_SHUFFLE, MVT::v32f32, ByteV);
188
189 // For HVX <v81 there is no hardware float-equality instruction; only
190 // float-GT (V6_vgtsf/V6_vgthf) is available. The integer-equality
191 // fallback (V6_veqw/V6_veqh) silently treats NaN as equal to itself
192 // because the bit patterns match. Mark SETCC as Custom for the
193 // single-vector float types so we can synthesise the correct
194 // ordered-equal predicate in LowerHvxFpSetoeq.
195 if (!Subtarget.useHVXV81Ops())
196 for (MVT T : FloatV)
198
199 if (Subtarget.useHVXV81Ops()) {
200 setPromoteTo(ISD::VECTOR_SHUFFLE, MVT::v128bf16, ByteW);
201 setPromoteTo(ISD::VECTOR_SHUFFLE, MVT::v64bf16, ByteV);
202 setPromoteTo(ISD::SETCC, MVT::v64bf16, MVT::v64f32);
203 setPromoteTo(ISD::FADD, MVT::v64bf16, MVT::v64f32);
204 setPromoteTo(ISD::FSUB, MVT::v64bf16, MVT::v64f32);
205 setPromoteTo(ISD::FMUL, MVT::v64bf16, MVT::v64f32);
206 setPromoteTo(ISD::FMINNUM, MVT::v64bf16, MVT::v64f32);
207 setPromoteTo(ISD::FMAXNUM, MVT::v64bf16, MVT::v64f32);
208
212
213 setOperationAction(ISD::LOAD, MVT::v128bf16, Custom);
214 setOperationAction(ISD::STORE, MVT::v128bf16, Custom);
215
216 setOperationAction(ISD::MLOAD, MVT::v64bf16, Custom);
217 setOperationAction(ISD::MSTORE, MVT::v64bf16, Custom);
220
221 setOperationAction(ISD::MLOAD, MVT::v128bf16, Custom);
222 setOperationAction(ISD::MSTORE, MVT::v128bf16, Custom);
225
229 }
230
231 for (MVT P : FloatW) {
249
250 // Custom-lower BUILD_VECTOR. The standard (target-independent)
251 // handling of it would convert it to a load, which is not always
252 // the optimal choice.
254 // Make concat-vectors custom to handle concats of more than 2 vectors.
256
259 }
260
261 if (Subtarget.useHVXQFloatOps()) {
264 } else if (Subtarget.useHVXIEEEFPOps()) {
267 }
268 }
269
270 for (MVT T : LegalV) {
273
289 if (T != ByteV) {
293 }
294
297 if (T.getScalarType() != MVT::i32) {
300 }
301
306 if (T.getScalarType() != MVT::i32) {
309 }
310
312 // Make concat-vectors custom to handle concats of more than 2 vectors.
323 if (T != ByteV) {
325 // HVX only has shifts of words and halfwords.
329
330 // Promote all shuffles to operate on vectors of bytes.
331 setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteV);
332 }
333
334 if (Subtarget.useHVXFloatingPoint()) {
335 // Same action for both QFloat and IEEE.
340 }
341
349 }
350
351 for (MVT T : LegalW) {
352 // Custom-lower BUILD_VECTOR for vector pairs. The standard (target-
353 // independent) handling of it would convert it to a load, which is
354 // not always the optimal choice.
356 // Make concat-vectors custom to handle concats of more than 2 vectors.
358
359 // Custom-lower these operations for pairs. Expand them into a concat
360 // of the corresponding operations on individual vectors.
369
378
393 if (T != ByteW) {
397
398 // Promote all shuffles to operate on vectors of bytes.
399 setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteW);
400 }
403
406 if (T.getScalarType() != MVT::i32) {
409 }
410
411 if (Subtarget.useHVXFloatingPoint()) {
412 // Same action for both QFloat and IEEE.
417 }
418 }
419
420 // Legalize all of these to HexagonISD::[SU]MUL_LOHI.
421 setOperationAction(ISD::MULHS, WordV, Custom); // -> _LOHI
422 setOperationAction(ISD::MULHU, WordV, Custom); // -> _LOHI
425
426 setCondCodeAction(ISD::SETNE, MVT::v64f16, Expand);
427 setCondCodeAction(ISD::SETLE, MVT::v64f16, Expand);
428 setCondCodeAction(ISD::SETGE, MVT::v64f16, Expand);
429 setCondCodeAction(ISD::SETLT, MVT::v64f16, Expand);
430 setCondCodeAction(ISD::SETONE, MVT::v64f16, Expand);
431 setCondCodeAction(ISD::SETOLE, MVT::v64f16, Expand);
432 setCondCodeAction(ISD::SETOGE, MVT::v64f16, Expand);
433 setCondCodeAction(ISD::SETOLT, MVT::v64f16, Expand);
434 setCondCodeAction(ISD::SETUNE, MVT::v64f16, Expand);
435 setCondCodeAction(ISD::SETULE, MVT::v64f16, Expand);
436 setCondCodeAction(ISD::SETUGE, MVT::v64f16, Expand);
437 setCondCodeAction(ISD::SETULT, MVT::v64f16, Expand);
438 setCondCodeAction(ISD::SETUO, MVT::v64f16, Expand);
439 setCondCodeAction(ISD::SETO, MVT::v64f16, Expand);
440
441 setCondCodeAction(ISD::SETNE, MVT::v32f32, Expand);
442 setCondCodeAction(ISD::SETLE, MVT::v32f32, Expand);
443 setCondCodeAction(ISD::SETGE, MVT::v32f32, Expand);
444 setCondCodeAction(ISD::SETLT, MVT::v32f32, Expand);
445 setCondCodeAction(ISD::SETONE, MVT::v32f32, Expand);
446 setCondCodeAction(ISD::SETOLE, MVT::v32f32, Expand);
447 setCondCodeAction(ISD::SETOGE, MVT::v32f32, Expand);
448 setCondCodeAction(ISD::SETOLT, MVT::v32f32, Expand);
449 setCondCodeAction(ISD::SETUNE, MVT::v32f32, Expand);
450 setCondCodeAction(ISD::SETULE, MVT::v32f32, Expand);
451 setCondCodeAction(ISD::SETUGE, MVT::v32f32, Expand);
452 setCondCodeAction(ISD::SETULT, MVT::v32f32, Expand);
453 setCondCodeAction(ISD::SETUO, MVT::v32f32, Expand);
454 setCondCodeAction(ISD::SETO, MVT::v32f32, Expand);
455
456 // Boolean vectors.
457
458 for (MVT T : LegalW) {
459 // Boolean types for vector pairs will overlap with the boolean
460 // types for single vectors, e.g.
461 // v64i8 -> v64i1 (single)
462 // v64i16 -> v64i1 (pair)
463 // Set these actions first, and allow the single actions to overwrite
464 // any duplicates.
465 MVT BoolW = MVT::getVectorVT(MVT::i1, T.getVectorNumElements());
470 // Masked load/store takes a mask that may need splitting.
473 }
474
475 for (MVT T : LegalV) {
476 MVT BoolV = MVT::getVectorVT(MVT::i1, T.getVectorNumElements());
487 }
488
489 if (Use64b) {
490 for (MVT T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})
492 } else {
493 for (MVT T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})
495 }
496
497 // Handle store widening for short vectors.
498 unsigned HwLen = Subtarget.getVectorLength();
499 for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
500 if (ElemTy == MVT::i1)
501 continue;
502 int ElemWidth = ElemTy.getFixedSizeInBits();
503 int MaxElems = (8*HwLen) / ElemWidth;
504 for (int N = 2; N < MaxElems; N *= 2) {
505 MVT VecTy = MVT::getVectorVT(ElemTy, N);
506 auto Action = getPreferredVectorAction(VecTy);
515 if (Subtarget.useHVXFloatingPoint()) {
520 }
521
522 MVT BoolTy = MVT::getVectorVT(MVT::i1, N);
523 if (!isTypeLegal(BoolTy))
525 }
526 }
527 }
528
529 // Include cases which are not hander earlier
533
535
538
539 // Partial MLA reductions.
540 {
541 static const unsigned MLAOps[] = {ISD::PARTIAL_REDUCE_SMLA,
544
545 auto HvxType = [=](MVT ScalarT, unsigned Factor = 1) {
546 return MVT::getVectorVT(ScalarT, Subtarget.getVectorLength() * Factor *
547 8 / ScalarT.getSizeInBits());
548 };
549
550 // Tuple of (Acc element type, input element type, vector pair).
551 // The assumption is both the input and reduction result are of the same
552 // size so the reduction ratio is the same as the ratio of element type
553 // sizes. This may not hold for all available instructions.
554 typedef std::tuple<MVT, MVT, bool> ReductionSignature;
555
556 static const std::vector<ReductionSignature> NativeReductions = {
557 {MVT::i32, MVT::i8, false},
558 };
559
560 for (const auto &R : NativeReductions) {
561
562 MVT AccType = std::get<0>(R);
563 MVT InputType = std::get<1>(R);
564 unsigned Factor = std::get<2>(R) ? 2 : 1;
565
566 // The native size is legal.
567 setPartialReduceMLAAction(MLAOps, HvxType(AccType), HvxType(InputType),
568 Legal);
569
570 // Allow custom partial MLA reductions on larger vectors than legally
571 // supported. These reduction must be declared as Custom (or Legal)
572 // for foldPartialReduceMLAMulOp() to fold the multiply by one pattern
573 // inserted when the partial reduction intrinsic is converted to
574 // PARTIAL_REDUCE_U/S/SUMLA. Otherwise, the Split action will apply
575 // on the original pattern, including the extensions and multiplies,
576 // which will make it impossible to match.
577 // There are two independent ways to extend the
578 // input size: 1. to concatenate the result - output vector is
579 // proportionally extended, 2) to reduce the result - the output vector
580 // size stays the same. We limit allowed combinations so that the total
581 // number of generated reduction instructions is limited by a constant
582 // number. This limit is arbitrary and can be revised. On one hand, it is
583 // convenient to have more choices; on the other hand, there is a
584 // diminishing benefit of very long sequences, which should probably be
585 // written as loops instead.
586 for (unsigned ConcatFactor = 1; ConcatFactor <= MaxExpandMLA;
587 ConcatFactor <<= 1)
588 for (unsigned ReductionFactor = 1; ReductionFactor <= MaxExpandMLA;
589 ReductionFactor <<= 1)
590 if (ConcatFactor * ReductionFactor != 1 &&
591 ConcatFactor * ReductionFactor <= MaxExpandMLA)
593 MLAOps, HvxType(AccType, Factor * ConcatFactor),
594 HvxType(InputType, Factor * ConcatFactor * ReductionFactor),
595 Custom);
596 }
597 }
598}
599
600unsigned
601HexagonTargetLowering::getPreferredHvxVectorAction(MVT VecTy) const {
602 // Early exit for invalid input types
603 if (!VecTy.isVector())
604 return ~0u;
605
606 MVT ElemTy = VecTy.getVectorElementType();
607 unsigned VecLen = VecTy.getVectorNumElements();
608 unsigned HwLen = Subtarget.getVectorLength();
609
610 // Split vectors of i1 that exceed byte vector length.
611 if (ElemTy == MVT::i1 && VecLen > HwLen)
613
614 ArrayRef<MVT> Tys = Subtarget.getHVXElementTypes();
615 // For shorter vectors of i1, widen them if any of the corresponding
616 // vectors of integers needs to be widened.
617 if (ElemTy == MVT::i1) {
618 for (MVT T : Tys) {
619 assert(T != MVT::i1);
620 auto A = getPreferredHvxVectorAction(MVT::getVectorVT(T, VecLen));
621 if (A != ~0u)
622 return A;
623 }
624 return ~0u;
625 }
626
627 // If the size of VecTy is at least half of the vector length,
628 // widen the vector. Note: the threshold was not selected in
629 // any scientific way.
630 if (llvm::is_contained(Tys, ElemTy)) {
631 unsigned VecWidth = VecTy.getSizeInBits();
632 unsigned HwWidth = 8*HwLen;
633 if (VecWidth > 2*HwWidth)
635
636 bool HaveThreshold = HvxWidenThreshold.getNumOccurrences() > 0;
637 if (HaveThreshold && 8*HvxWidenThreshold <= VecWidth)
639 if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
641 }
642
643 // Defer to default.
644 return ~0u;
645}
646
647unsigned
648HexagonTargetLowering::getCustomHvxOperationAction(SDNode &Op) const {
649 unsigned Opc = Op.getOpcode();
650 switch (Opc) {
651 case HexagonISD::SMUL_LOHI:
652 case HexagonISD::UMUL_LOHI:
653 case HexagonISD::USMUL_LOHI:
655 }
657}
658
660HexagonTargetLowering::getInt(unsigned IntId, MVT ResTy, ArrayRef<SDValue> Ops,
661 const SDLoc &dl, SelectionDAG &DAG) const {
663 IntOps.push_back(DAG.getConstant(IntId, dl, MVT::i32));
664 append_range(IntOps, Ops);
665 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, ResTy, IntOps);
666}
667
668MVT
669HexagonTargetLowering::typeJoin(const TypePair &Tys) const {
670 assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());
671
672 MVT ElemTy = Tys.first.getVectorElementType();
673 return MVT::getVectorVT(ElemTy, Tys.first.getVectorNumElements() +
674 Tys.second.getVectorNumElements());
675}
676
677HexagonTargetLowering::TypePair
678HexagonTargetLowering::typeSplit(MVT VecTy) const {
679 assert(VecTy.isVector());
680 unsigned NumElem = VecTy.getVectorNumElements();
681 assert((NumElem % 2) == 0 && "Expecting even-sized vector type");
682 MVT HalfTy = MVT::getVectorVT(VecTy.getVectorElementType(), NumElem/2);
683 return { HalfTy, HalfTy };
684}
685
686MVT
687HexagonTargetLowering::typeExtElem(MVT VecTy, unsigned Factor) const {
688 MVT ElemTy = VecTy.getVectorElementType();
689 MVT NewElemTy = MVT::getIntegerVT(ElemTy.getSizeInBits() * Factor);
690 return MVT::getVectorVT(NewElemTy, VecTy.getVectorNumElements());
691}
692
693MVT
694HexagonTargetLowering::typeTruncElem(MVT VecTy, unsigned Factor) const {
695 MVT ElemTy = VecTy.getVectorElementType();
696 MVT NewElemTy = MVT::getIntegerVT(ElemTy.getSizeInBits() / Factor);
697 return MVT::getVectorVT(NewElemTy, VecTy.getVectorNumElements());
698}
699
701HexagonTargetLowering::opCastElem(SDValue Vec, MVT ElemTy,
702 SelectionDAG &DAG) const {
703 if (ty(Vec).getVectorElementType() == ElemTy)
704 return Vec;
705 MVT CastTy = tyVector(Vec.getValueType().getSimpleVT(), ElemTy);
706 return DAG.getBitcast(CastTy, Vec);
707}
708
710HexagonTargetLowering::opJoin(const VectorPair &Ops, const SDLoc &dl,
711 SelectionDAG &DAG) const {
712 return DAG.getNode(ISD::CONCAT_VECTORS, dl, typeJoin(ty(Ops)),
713 Ops.first, Ops.second);
714}
715
716HexagonTargetLowering::VectorPair
717HexagonTargetLowering::opSplit(SDValue Vec, const SDLoc &dl,
718 SelectionDAG &DAG) const {
719 TypePair Tys = typeSplit(ty(Vec));
720 if (Vec.getOpcode() == HexagonISD::QCAT)
721 return VectorPair(Vec.getOperand(0), Vec.getOperand(1));
722 return DAG.SplitVector(Vec, dl, Tys.first, Tys.second);
723}
724
725bool
726HexagonTargetLowering::isHvxSingleTy(MVT Ty) const {
727 return Subtarget.isHVXVectorType(Ty) &&
728 Ty.getSizeInBits() == 8 * Subtarget.getVectorLength();
729}
730
731bool
732HexagonTargetLowering::isHvxPairTy(MVT Ty) const {
733 return Subtarget.isHVXVectorType(Ty) &&
734 Ty.getSizeInBits() == 16 * Subtarget.getVectorLength();
735}
736
737bool
738HexagonTargetLowering::isHvxBoolTy(MVT Ty) const {
739 return Subtarget.isHVXVectorType(Ty, true) &&
740 Ty.getVectorElementType() == MVT::i1;
741}
742
743bool HexagonTargetLowering::allowsHvxMemoryAccess(
744 MVT VecTy, MachineMemOperand::Flags Flags, unsigned *Fast) const {
745 // Bool vectors are excluded by default, but make it explicit to
746 // emphasize that bool vectors cannot be loaded or stored.
747 // Also, disallow double vector stores (to prevent unnecessary
748 // store widening in DAG combiner).
749 if (VecTy.getSizeInBits() > 8*Subtarget.getVectorLength())
750 return false;
751 if (!Subtarget.isHVXVectorType(VecTy, /*IncludeBool=*/false))
752 return false;
753 if (Fast)
754 *Fast = 1;
755 return true;
756}
757
758bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(
759 MVT VecTy, MachineMemOperand::Flags Flags, unsigned *Fast) const {
760 if (!Subtarget.isHVXVectorType(VecTy))
761 return false;
762 // XXX Should this be false? vmemu are a bit slower than vmem.
763 if (Fast)
764 *Fast = 1;
765 return true;
766}
767
768void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(
769 MachineInstr &MI, SDNode *Node) const {
770 unsigned Opc = MI.getOpcode();
771 const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
772 MachineBasicBlock &MB = *MI.getParent();
773 MachineFunction &MF = *MB.getParent();
774 MachineRegisterInfo &MRI = MF.getRegInfo();
775 DebugLoc DL = MI.getDebugLoc();
776 auto At = MI.getIterator();
777
778 switch (Opc) {
779 case Hexagon::PS_vsplatib:
780 if (Subtarget.useHVXV62Ops()) {
781 // SplatV = A2_tfrsi #imm
782 // OutV = V6_lvsplatb SplatV
783 Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
784 BuildMI(MB, At, DL, TII.get(Hexagon::A2_tfrsi), SplatV)
785 .add(MI.getOperand(1));
786 Register OutV = MI.getOperand(0).getReg();
787 BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplatb), OutV)
788 .addReg(SplatV);
789 } else {
790 // SplatV = A2_tfrsi #imm:#imm:#imm:#imm
791 // OutV = V6_lvsplatw SplatV
792 Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
793 const MachineOperand &InpOp = MI.getOperand(1);
794 assert(InpOp.isImm());
795 uint32_t V = InpOp.getImm() & 0xFF;
796 BuildMI(MB, At, DL, TII.get(Hexagon::A2_tfrsi), SplatV)
797 .addImm(V << 24 | V << 16 | V << 8 | V);
798 Register OutV = MI.getOperand(0).getReg();
799 BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplatw), OutV).addReg(SplatV);
800 }
801 MB.erase(At);
802 break;
803 case Hexagon::PS_vsplatrb:
804 if (Subtarget.useHVXV62Ops()) {
805 // OutV = V6_lvsplatb Inp
806 Register OutV = MI.getOperand(0).getReg();
807 BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplatb), OutV)
808 .add(MI.getOperand(1));
809 } else {
810 Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
811 const MachineOperand &InpOp = MI.getOperand(1);
812 BuildMI(MB, At, DL, TII.get(Hexagon::S2_vsplatrb), SplatV)
813 .addReg(InpOp.getReg(), {}, InpOp.getSubReg());
814 Register OutV = MI.getOperand(0).getReg();
815 BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplatw), OutV)
816 .addReg(SplatV);
817 }
818 MB.erase(At);
819 break;
820 case Hexagon::PS_vsplatih:
821 if (Subtarget.useHVXV62Ops()) {
822 // SplatV = A2_tfrsi #imm
823 // OutV = V6_lvsplath SplatV
824 Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
825 BuildMI(MB, At, DL, TII.get(Hexagon::A2_tfrsi), SplatV)
826 .add(MI.getOperand(1));
827 Register OutV = MI.getOperand(0).getReg();
828 BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplath), OutV)
829 .addReg(SplatV);
830 } else {
831 // SplatV = A2_tfrsi #imm:#imm
832 // OutV = V6_lvsplatw SplatV
833 Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
834 const MachineOperand &InpOp = MI.getOperand(1);
835 assert(InpOp.isImm());
836 uint32_t V = InpOp.getImm() & 0xFFFF;
837 BuildMI(MB, At, DL, TII.get(Hexagon::A2_tfrsi), SplatV)
838 .addImm(V << 16 | V);
839 Register OutV = MI.getOperand(0).getReg();
840 BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplatw), OutV).addReg(SplatV);
841 }
842 MB.erase(At);
843 break;
844 case Hexagon::PS_vsplatrh:
845 if (Subtarget.useHVXV62Ops()) {
846 // OutV = V6_lvsplath Inp
847 Register OutV = MI.getOperand(0).getReg();
848 BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplath), OutV)
849 .add(MI.getOperand(1));
850 } else {
851 // SplatV = A2_combine_ll Inp, Inp
852 // OutV = V6_lvsplatw SplatV
853 Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
854 const MachineOperand &InpOp = MI.getOperand(1);
855 BuildMI(MB, At, DL, TII.get(Hexagon::A2_combine_ll), SplatV)
856 .addReg(InpOp.getReg(), {}, InpOp.getSubReg())
857 .addReg(InpOp.getReg(), {}, InpOp.getSubReg());
858 Register OutV = MI.getOperand(0).getReg();
859 BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplatw), OutV).addReg(SplatV);
860 }
861 MB.erase(At);
862 break;
863 case Hexagon::PS_vsplatiw:
864 case Hexagon::PS_vsplatrw:
865 if (Opc == Hexagon::PS_vsplatiw) {
866 // SplatV = A2_tfrsi #imm
867 Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
868 BuildMI(MB, At, DL, TII.get(Hexagon::A2_tfrsi), SplatV)
869 .add(MI.getOperand(1));
870 MI.getOperand(1).ChangeToRegister(SplatV, false);
871 }
872 // OutV = V6_lvsplatw SplatV/Inp
873 MI.setDesc(TII.get(Hexagon::V6_lvsplatw));
874 break;
875 }
876}
877
879HexagonTargetLowering::convertToByteIndex(SDValue ElemIdx, MVT ElemTy,
880 SelectionDAG &DAG) const {
881 if (ElemIdx.getValueType().getSimpleVT() != MVT::i32)
882 ElemIdx = DAG.getBitcast(MVT::i32, ElemIdx);
883
884 unsigned ElemWidth = ElemTy.getSizeInBits();
885 if (ElemWidth == 8)
886 return ElemIdx;
887
888 unsigned L = Log2_32(ElemWidth/8);
889 const SDLoc &dl(ElemIdx);
890 return DAG.getNode(ISD::SHL, dl, MVT::i32,
891 {ElemIdx, DAG.getConstant(L, dl, MVT::i32)});
892}
893
895HexagonTargetLowering::getIndexInWord32(SDValue Idx, MVT ElemTy,
896 SelectionDAG &DAG) const {
897 unsigned ElemWidth = ElemTy.getSizeInBits();
898 assert(ElemWidth >= 8 && ElemWidth <= 32);
899 if (ElemWidth == 32)
900 return Idx;
901
902 if (ty(Idx) != MVT::i32)
903 Idx = DAG.getBitcast(MVT::i32, Idx);
904 const SDLoc &dl(Idx);
905 SDValue Mask = DAG.getConstant(32/ElemWidth - 1, dl, MVT::i32);
906 SDValue SubIdx = DAG.getNode(ISD::AND, dl, MVT::i32, {Idx, Mask});
907 return SubIdx;
908}
909
911HexagonTargetLowering::getByteShuffle(const SDLoc &dl, SDValue Op0,
912 SDValue Op1, ArrayRef<int> Mask,
913 SelectionDAG &DAG) const {
914 MVT OpTy = ty(Op0);
915 assert(OpTy == ty(Op1));
916
917 MVT ElemTy = OpTy.getVectorElementType();
918 if (ElemTy == MVT::i8)
919 return DAG.getVectorShuffle(OpTy, dl, Op0, Op1, Mask);
920 assert(ElemTy.getSizeInBits() >= 8);
921
922 MVT ResTy = tyVector(OpTy, MVT::i8);
923 unsigned ElemSize = ElemTy.getSizeInBits() / 8;
924
925 SmallVector<int,128> ByteMask;
926 for (int M : Mask) {
927 if (M < 0) {
928 for (unsigned I = 0; I != ElemSize; ++I)
929 ByteMask.push_back(-1);
930 } else {
931 int NewM = M*ElemSize;
932 for (unsigned I = 0; I != ElemSize; ++I)
933 ByteMask.push_back(NewM+I);
934 }
935 }
936 assert(ResTy.getVectorNumElements() == ByteMask.size());
937 return DAG.getVectorShuffle(ResTy, dl, opCastElem(Op0, MVT::i8, DAG),
938 opCastElem(Op1, MVT::i8, DAG), ByteMask);
939}
940
942HexagonTargetLowering::buildHvxVectorReg(ArrayRef<SDValue> Values,
943 const SDLoc &dl, MVT VecTy,
944 SelectionDAG &DAG) const {
945 unsigned VecLen = Values.size();
947 MVT ElemTy = VecTy.getVectorElementType();
948 unsigned ElemWidth = ElemTy.getSizeInBits();
949 unsigned HwLen = Subtarget.getVectorLength();
950
951 unsigned ElemSize = ElemWidth / 8;
952 assert(ElemSize*VecLen == HwLen);
954
955 if (VecTy.getVectorElementType() != MVT::i32 &&
956 !(Subtarget.useHVXFloatingPoint() &&
957 VecTy.getVectorElementType() == MVT::f32)) {
958 assert((ElemSize == 1 || ElemSize == 2) && "Invalid element size");
959 unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;
960 MVT PartVT = MVT::getVectorVT(VecTy.getVectorElementType(), OpsPerWord);
961 for (unsigned i = 0; i != VecLen; i += OpsPerWord) {
962 SDValue W = buildVector32(Values.slice(i, OpsPerWord), dl, PartVT, DAG);
963 Words.push_back(DAG.getBitcast(MVT::i32, W));
964 }
965 } else {
966 for (SDValue V : Values)
967 Words.push_back(DAG.getBitcast(MVT::i32, V));
968 }
969 auto isSplat = [] (ArrayRef<SDValue> Values, SDValue &SplatV) {
970 unsigned NumValues = Values.size();
971 assert(NumValues > 0);
972 bool IsUndef = true;
973 for (unsigned i = 0; i != NumValues; ++i) {
974 if (Values[i].isUndef())
975 continue;
976 IsUndef = false;
977 if (!SplatV.getNode())
978 SplatV = Values[i];
979 else if (SplatV != Values[i])
980 return false;
981 }
982 if (IsUndef)
983 SplatV = Values[0];
984 return true;
985 };
986
987 unsigned NumWords = Words.size();
988 SDValue SplatV;
989 bool IsSplat = isSplat(Words, SplatV);
990 if (IsSplat && isUndef(SplatV))
991 return DAG.getUNDEF(VecTy);
992 if (IsSplat) {
993 assert(SplatV.getNode());
994 if (isNullConstant(SplatV))
995 return getZero(dl, VecTy, DAG);
996 MVT WordTy = MVT::getVectorVT(MVT::i32, HwLen/4);
997 SDValue S = DAG.getNode(ISD::SPLAT_VECTOR, dl, WordTy, SplatV);
998 return DAG.getBitcast(VecTy, S);
999 }
1000
1001 // Delay recognizing constant vectors until here, so that we can generate
1002 // a vsplat.
1003 SmallVector<ConstantInt*, 128> Consts(VecLen);
1004 bool AllConst = getBuildVectorConstInts(Values, VecTy, DAG, Consts);
1005 if (AllConst) {
1006 ArrayRef<Constant*> Tmp((Constant**)Consts.begin(),
1007 (Constant**)Consts.end());
1008 Constant *CV = ConstantVector::get(Tmp);
1009 Align Alignment(HwLen);
1011 DAG.getConstantPool(CV, getPointerTy(DAG.getDataLayout()), Alignment),
1012 DAG);
1013 return DAG.getLoad(VecTy, dl, DAG.getEntryNode(), CP,
1015 }
1016
1017 // A special case is a situation where the vector is built entirely from
1018 // elements extracted from another vector. This could be done via a shuffle
1019 // more efficiently, but typically, the size of the source vector will not
1020 // match the size of the vector being built (which precludes the use of a
1021 // shuffle directly).
1022 // This only handles a single source vector, and the vector being built
1023 // should be of a sub-vector type of the source vector type.
1024 auto IsBuildFromExtracts = [this,&Values] (SDValue &SrcVec,
1025 SmallVectorImpl<int> &SrcIdx) {
1026 SDValue Vec;
1027 for (SDValue V : Values) {
1028 if (isUndef(V)) {
1029 SrcIdx.push_back(-1);
1030 continue;
1031 }
1032 if (V.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
1033 return false;
1034 // All extracts should come from the same vector.
1035 SDValue T = V.getOperand(0);
1036 if (Vec.getNode() != nullptr && T.getNode() != Vec.getNode())
1037 return false;
1038 Vec = T;
1039 ConstantSDNode *C = dyn_cast<ConstantSDNode>(V.getOperand(1));
1040 if (C == nullptr)
1041 return false;
1042 int I = C->getSExtValue();
1043 assert(I >= 0 && "Negative element index");
1044 SrcIdx.push_back(I);
1045 }
1046 SrcVec = Vec;
1047 return true;
1048 };
1049
1050 SmallVector<int,128> ExtIdx;
1051 SDValue ExtVec;
1052 if (IsBuildFromExtracts(ExtVec, ExtIdx)) {
1053 MVT ExtTy = ty(ExtVec);
1054 unsigned ExtLen = ExtTy.getVectorNumElements();
1055 if (ExtLen == VecLen || ExtLen == 2*VecLen) {
1056 // Construct a new shuffle mask that will produce a vector with the same
1057 // number of elements as the input vector, and such that the vector we
1058 // want will be the initial subvector of it.
1059 SmallVector<int,128> Mask;
1060 BitVector Used(ExtLen);
1061
1062 for (int M : ExtIdx) {
1063 Mask.push_back(M);
1064 if (M >= 0)
1065 Used.set(M);
1066 }
1067 // Fill the rest of the mask with the unused elements of ExtVec in hopes
1068 // that it will result in a permutation of ExtVec's elements. It's still
1069 // fine if it doesn't (e.g. if undefs are present, or elements are
1070 // repeated), but permutations can always be done efficiently via vdelta
1071 // and vrdelta.
1072 for (unsigned I = 0; I != ExtLen; ++I) {
1073 if (Mask.size() == ExtLen)
1074 break;
1075 if (!Used.test(I))
1076 Mask.push_back(I);
1077 }
1078
1079 SDValue S = DAG.getVectorShuffle(ExtTy, dl, ExtVec,
1080 DAG.getUNDEF(ExtTy), Mask);
1081 return ExtLen == VecLen ? S : LoHalf(S, DAG);
1082 }
1083 }
1084
1085 // Find most common element to initialize vector with. This is to avoid
1086 // unnecessary vinsert/valign for cases where the same value is present
1087 // many times. Creates a histogram of the vector's elements to find the
1088 // most common element n.
1089 assert(4*Words.size() == Subtarget.getVectorLength());
1090 int VecHist[32];
1091 int n = 0;
1092 for (unsigned i = 0; i != NumWords; ++i) {
1093 VecHist[i] = 0;
1094 if (Words[i].isUndef())
1095 continue;
1096 for (unsigned j = i; j != NumWords; ++j)
1097 if (Words[i] == Words[j])
1098 VecHist[i]++;
1099
1100 if (VecHist[i] > VecHist[n])
1101 n = i;
1102 }
1103
1104 SDValue HalfV = getZero(dl, VecTy, DAG);
1105 if (VecHist[n] > 1) {
1106 // Always splat at word (i32) granularity so that the SPLAT_VECTOR node
1107 // is selected as PS_vsplatrw (word broadcast) rather than PS_vsplatrb
1108 // (byte broadcast of the low byte only), which would corrupt multi-byte
1109 // element types.
1110 MVT WordVecTy = MVT::getVectorVT(MVT::i32, HwLen / 4);
1111 SDValue WordSplat = DAG.getNode(ISD::SPLAT_VECTOR, dl, WordVecTy, Words[n]);
1112 SDValue SplatV = DAG.getBitcast(VecTy, WordSplat);
1113 HalfV = DAG.getNode(HexagonISD::VALIGN, dl, VecTy,
1114 {HalfV, SplatV, DAG.getConstant(HwLen/2, dl, MVT::i32)});
1115 }
1116 SDValue HalfV0 = HalfV;
1117 SDValue HalfV1 = HalfV;
1118
1119 // Construct two halves in parallel, then or them together. Rn and Rm count
1120 // number of rotations needed before the next element. One last rotation is
1121 // performed post-loop to position the last element.
1122 int Rn = 0, Rm = 0;
1123 SDValue Sn, Sm;
1124 SDValue N = HalfV0;
1125 SDValue M = HalfV1;
1126 for (unsigned i = 0; i != NumWords/2; ++i) {
1127 // Rotate by element count since last insertion.
1128 if (Words[i] != Words[n] || VecHist[n] <= 1) {
1129 Sn = DAG.getConstant(Rn, dl, MVT::i32);
1130 HalfV0 = DAG.getNode(HexagonISD::VROR, dl, VecTy, {N, Sn});
1131 N = DAG.getNode(HexagonISD::VINSERTW0, dl, VecTy,
1132 {HalfV0, Words[i]});
1133 Rn = 0;
1134 }
1135 if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {
1136 Sm = DAG.getConstant(Rm, dl, MVT::i32);
1137 HalfV1 = DAG.getNode(HexagonISD::VROR, dl, VecTy, {M, Sm});
1138 M = DAG.getNode(HexagonISD::VINSERTW0, dl, VecTy,
1139 {HalfV1, Words[i+NumWords/2]});
1140 Rm = 0;
1141 }
1142 Rn += 4;
1143 Rm += 4;
1144 }
1145 // Perform last rotation.
1146 Sn = DAG.getConstant(Rn+HwLen/2, dl, MVT::i32);
1147 Sm = DAG.getConstant(Rm, dl, MVT::i32);
1148 HalfV0 = DAG.getNode(HexagonISD::VROR, dl, VecTy, {N, Sn});
1149 HalfV1 = DAG.getNode(HexagonISD::VROR, dl, VecTy, {M, Sm});
1150
1151 SDValue T0 = DAG.getBitcast(tyVector(VecTy, MVT::i32), HalfV0);
1152 SDValue T1 = DAG.getBitcast(tyVector(VecTy, MVT::i32), HalfV1);
1153
1154 SDValue DstV = DAG.getNode(ISD::OR, dl, ty(T0), {T0, T1});
1155
1156 SDValue OutV =
1157 DAG.getBitcast(tyVector(ty(DstV), VecTy.getVectorElementType()), DstV);
1158 return OutV;
1159}
1160
1161SDValue
1162HexagonTargetLowering::createHvxPrefixPred(SDValue PredV, const SDLoc &dl,
1163 unsigned BitBytes, bool ZeroFill, SelectionDAG &DAG) const {
1164 MVT PredTy = ty(PredV);
1165 unsigned HwLen = Subtarget.getVectorLength();
1166 MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);
1167
1168 if (Subtarget.isHVXVectorType(PredTy, true)) {
1169 // Move the vector predicate SubV to a vector register, and scale it
1170 // down to match the representation (bytes per type element) that VecV
1171 // uses. The scaling down will pick every 2nd or 4th (every Scale-th
1172 // in general) element and put them at the front of the resulting
1173 // vector. This subvector will then be inserted into the Q2V of VecV.
1174 // To avoid having an operation that generates an illegal type (short
1175 // vector), generate a full size vector.
1176 //
1177 SDValue T = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, PredV);
1178 SmallVector<int,128> Mask(HwLen);
1179 // Scale = BitBytes(PredV) / Given BitBytes.
1180 unsigned Scale = HwLen / (PredTy.getVectorNumElements() * BitBytes);
1181 unsigned BlockLen = PredTy.getVectorNumElements() * BitBytes;
1182
1183 for (unsigned i = 0; i != HwLen; ++i) {
1184 unsigned Num = i % Scale;
1185 unsigned Off = i / Scale;
1186 Mask[BlockLen*Num + Off] = i;
1187 }
1188 SDValue S = DAG.getVectorShuffle(ByteTy, dl, T, DAG.getUNDEF(ByteTy), Mask);
1189 if (!ZeroFill)
1190 return S;
1191 // Fill the bytes beyond BlockLen with 0s.
1192 // V6_pred_scalar2 cannot fill the entire predicate, so it only works
1193 // when BlockLen < HwLen.
1194 assert(BlockLen < HwLen && "vsetq(v1) prerequisite");
1195 MVT BoolTy = MVT::getVectorVT(MVT::i1, HwLen);
1196 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1197 {DAG.getConstant(BlockLen, dl, MVT::i32)}, DAG);
1198 SDValue M = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, Q);
1199 return DAG.getNode(ISD::AND, dl, ByteTy, S, M);
1200 }
1201
1202 // Make sure that this is a valid scalar predicate.
1203 assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);
1204
1205 unsigned Bytes = 8 / PredTy.getVectorNumElements();
1206 SmallVector<SDValue,4> Words[2];
1207 unsigned IdxW = 0;
1208
1209 SDValue W0 = isUndef(PredV)
1210 ? DAG.getUNDEF(MVT::i64)
1211 : DAG.getNode(HexagonISD::P2D, dl, MVT::i64, PredV);
1212 Words[IdxW].push_back(HiHalf(W0, DAG));
1213 Words[IdxW].push_back(LoHalf(W0, DAG));
1214
1215 while (Bytes < BitBytes) {
1216 IdxW ^= 1;
1217 Words[IdxW].clear();
1218
1219 if (Bytes < 4) {
1220 for (const SDValue &W : Words[IdxW ^ 1]) {
1221 SDValue T = expandPredicate(W, dl, DAG);
1222 Words[IdxW].push_back(HiHalf(T, DAG));
1223 Words[IdxW].push_back(LoHalf(T, DAG));
1224 }
1225 } else {
1226 for (const SDValue &W : Words[IdxW ^ 1]) {
1227 Words[IdxW].push_back(W);
1228 Words[IdxW].push_back(W);
1229 }
1230 }
1231 Bytes *= 2;
1232 }
1233
1234 assert(Bytes == BitBytes);
1235 SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);
1236 SDValue S4 = DAG.getConstant(HwLen-4, dl, MVT::i32);
1237 for (const SDValue &W : Words[IdxW]) {
1238 Vec = DAG.getNode(HexagonISD::VROR, dl, ByteTy, Vec, S4);
1239 Vec = DAG.getNode(HexagonISD::VINSERTW0, dl, ByteTy, Vec, W);
1240 }
1241
1242 return Vec;
1243}
1244
1245SDValue
1246HexagonTargetLowering::buildHvxVectorPred(ArrayRef<SDValue> Values,
1247 const SDLoc &dl, MVT VecTy,
1248 SelectionDAG &DAG) const {
1249 // Construct a vector V of bytes, such that a comparison V >u 0 would
1250 // produce the required vector predicate.
1251 unsigned VecLen = Values.size();
1252 unsigned HwLen = Subtarget.getVectorLength();
1253 assert(VecLen <= HwLen || VecLen == 8*HwLen);
1255 bool AllT = true, AllF = true;
1256
1257 auto IsTrue = [] (SDValue V) {
1258 if (const auto *N = dyn_cast<ConstantSDNode>(V.getNode()))
1259 return !N->isZero();
1260 return false;
1261 };
1262 auto IsFalse = [] (SDValue V) {
1263 if (const auto *N = dyn_cast<ConstantSDNode>(V.getNode()))
1264 return N->isZero();
1265 return false;
1266 };
1267
1268 if (VecLen <= HwLen) {
1269 // In the hardware, each bit of a vector predicate corresponds to a byte
1270 // of a vector register. Calculate how many bytes does a bit of VecTy
1271 // correspond to.
1272 assert(HwLen % VecLen == 0);
1273 unsigned BitBytes = HwLen / VecLen;
1274 for (SDValue V : Values) {
1275 AllT &= IsTrue(V);
1276 AllF &= IsFalse(V);
1277
1278 SDValue Ext = !V.isUndef() ? DAG.getZExtOrTrunc(V, dl, MVT::i8)
1279 : DAG.getUNDEF(MVT::i8);
1280 for (unsigned B = 0; B != BitBytes; ++B)
1281 Bytes.push_back(Ext);
1282 }
1283 } else {
1284 // There are as many i1 values, as there are bits in a vector register.
1285 // Divide the values into groups of 8 and check that each group consists
1286 // of the same value (ignoring undefs).
1287 for (unsigned I = 0; I != VecLen; I += 8) {
1288 unsigned B = 0;
1289 // Find the first non-undef value in this group.
1290 for (; B != 8; ++B) {
1291 if (!Values[I+B].isUndef())
1292 break;
1293 }
1294 SDValue F = Values[I+B];
1295 AllT &= IsTrue(F);
1296 AllF &= IsFalse(F);
1297
1298 SDValue Ext = (B < 8) ? DAG.getZExtOrTrunc(F, dl, MVT::i8)
1299 : DAG.getUNDEF(MVT::i8);
1300 Bytes.push_back(Ext);
1301 // Verify that the rest of values in the group are the same as the
1302 // first.
1303 for (; B != 8; ++B)
1304 assert(Values[I+B].isUndef() || Values[I+B] == F);
1305 }
1306 }
1307
1308 if (AllT)
1309 return DAG.getNode(HexagonISD::QTRUE, dl, VecTy);
1310 if (AllF)
1311 return DAG.getNode(HexagonISD::QFALSE, dl, VecTy);
1312
1313 MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);
1314 SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);
1315 return DAG.getNode(HexagonISD::V2Q, dl, VecTy, ByteVec);
1316}
1317
1318SDValue
1319HexagonTargetLowering::extractHvxElementReg(SDValue VecV, SDValue IdxV,
1320 const SDLoc &dl, MVT ResTy, SelectionDAG &DAG) const {
1321 MVT ElemTy = ty(VecV).getVectorElementType();
1322
1323 unsigned ElemWidth = ElemTy.getSizeInBits();
1324 assert(ElemWidth >= 8 && ElemWidth <= 32);
1325 (void)ElemWidth;
1326
1327 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1328 SDValue ExWord = DAG.getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,
1329 {VecV, ByteIdx});
1330 if (ElemTy == MVT::i32)
1331 return ExWord;
1332
1333 // Have an extracted word, need to extract the smaller element out of it.
1334 // 1. Extract the bits of (the original) IdxV that correspond to the index
1335 // of the desired element in the 32-bit word.
1336 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1337 // 2. Extract the element from the word.
1338 SDValue ExVec = DAG.getBitcast(tyVector(ty(ExWord), ElemTy), ExWord);
1339 return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);
1340}
1341
1342SDValue
1343HexagonTargetLowering::extractHvxElementPred(SDValue VecV, SDValue IdxV,
1344 const SDLoc &dl, MVT ResTy, SelectionDAG &DAG) const {
1345 // Implement other return types if necessary.
1346 assert(ResTy == MVT::i1);
1347
1348 unsigned HwLen = Subtarget.getVectorLength();
1349 MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);
1350 SDValue ByteVec = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, VecV);
1351
1352 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1353 SDValue ScV = DAG.getConstant(Scale, dl, MVT::i32);
1354 IdxV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, ScV);
1355
1356 SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);
1357 SDValue Zero = DAG.getTargetConstant(0, dl, MVT::i32);
1358 return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB, Zero}, DAG);
1359}
1360
1361SDValue
1362HexagonTargetLowering::insertHvxElementReg(SDValue VecV, SDValue IdxV,
1363 SDValue ValV, const SDLoc &dl, SelectionDAG &DAG) const {
1364 MVT ElemTy = ty(VecV).getVectorElementType();
1365
1366 unsigned ElemWidth = ElemTy.getSizeInBits();
1367 assert(ElemWidth >= 8 && ElemWidth <= 32);
1368 (void)ElemWidth;
1369
1370 auto InsertWord = [&DAG,&dl,this] (SDValue VecV, SDValue ValV,
1371 SDValue ByteIdxV) {
1372 MVT VecTy = ty(VecV);
1373 unsigned HwLen = Subtarget.getVectorLength();
1374 SDValue MaskV =
1375 DAG.getNode(ISD::AND, dl, MVT::i32,
1376 {ByteIdxV, DAG.getSignedConstant(-4, dl, MVT::i32)});
1377 SDValue RotV = DAG.getNode(HexagonISD::VROR, dl, VecTy, {VecV, MaskV});
1378 SDValue InsV = DAG.getNode(HexagonISD::VINSERTW0, dl, VecTy, {RotV, ValV});
1379 SDValue SubV = DAG.getNode(ISD::SUB, dl, MVT::i32,
1380 {DAG.getConstant(HwLen, dl, MVT::i32), MaskV});
1381 SDValue TorV = DAG.getNode(HexagonISD::VROR, dl, VecTy, {InsV, SubV});
1382 return TorV;
1383 };
1384
1385 SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);
1386 if (ElemTy == MVT::i32)
1387 return InsertWord(VecV, ValV, ByteIdx);
1388
1389 // If this is not inserting a 32-bit word, convert it into such a thing.
1390 // 1. Extract the existing word from the target vector.
1391 SDValue WordIdx = DAG.getNode(ISD::SRL, dl, MVT::i32,
1392 {ByteIdx, DAG.getConstant(2, dl, MVT::i32)});
1393 SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,
1394 dl, MVT::i32, DAG);
1395
1396 // 2. Treating the extracted word as a 32-bit vector, insert the given
1397 // value into it.
1398 SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);
1399 MVT SubVecTy = tyVector(ty(Ext), ElemTy);
1400 SDValue Ins = insertVector(DAG.getBitcast(SubVecTy, Ext),
1401 ValV, SubIdx, dl, ElemTy, DAG);
1402
1403 // 3. Insert the 32-bit word back into the original vector.
1404 return InsertWord(VecV, Ins, ByteIdx);
1405}
1406
1407SDValue
1408HexagonTargetLowering::insertHvxElementPred(SDValue VecV, SDValue IdxV,
1409 SDValue ValV, const SDLoc &dl, SelectionDAG &DAG) const {
1410 unsigned HwLen = Subtarget.getVectorLength();
1411 MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);
1412 SDValue ByteVec = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, VecV);
1413
1414 unsigned Scale = HwLen / ty(VecV).getVectorNumElements();
1415 SDValue ScV = DAG.getConstant(Scale, dl, MVT::i32);
1416 IdxV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, ScV);
1417 ValV = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i32, ValV);
1418
1419 SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);
1420 return DAG.getNode(HexagonISD::V2Q, dl, ty(VecV), InsV);
1421}
1422
1423SDValue
1424HexagonTargetLowering::extractHvxSubvectorReg(SDValue OrigOp, SDValue VecV,
1425 SDValue IdxV, const SDLoc &dl, MVT ResTy, SelectionDAG &DAG) const {
1426 MVT VecTy = ty(VecV);
1427 unsigned HwLen = Subtarget.getVectorLength();
1428 unsigned Idx = IdxV.getNode()->getAsZExtVal();
1429 MVT ElemTy = VecTy.getVectorElementType();
1430 unsigned ElemWidth = ElemTy.getSizeInBits();
1431
1432 // If the source vector is a vector pair, get the single vector containing
1433 // the subvector of interest. The subvector will never overlap two single
1434 // vectors.
1435 if (isHvxPairTy(VecTy)) {
1436 unsigned SubIdx = Hexagon::vsub_lo;
1437 if (Idx * ElemWidth >= 8 * HwLen) {
1438 SubIdx = Hexagon::vsub_hi;
1439 Idx -= VecTy.getVectorNumElements() / 2;
1440 }
1441
1442 VecTy = typeSplit(VecTy).first;
1443 VecV = DAG.getTargetExtractSubreg(SubIdx, dl, VecTy, VecV);
1444 if (VecTy == ResTy)
1445 return VecV;
1446 }
1447
1448 // The only meaningful subvectors of a single HVX vector are those that
1449 // fit in a scalar register.
1450 assert(ResTy.getSizeInBits() == 32 || ResTy.getSizeInBits() == 64);
1451
1452 MVT WordTy = tyVector(VecTy, MVT::i32);
1453 SDValue WordVec = DAG.getBitcast(WordTy, VecV);
1454 unsigned WordIdx = (Idx*ElemWidth) / 32;
1455
1456 SDValue W0Idx = DAG.getConstant(WordIdx, dl, MVT::i32);
1457 SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);
1458 if (ResTy.getSizeInBits() == 32)
1459 return DAG.getBitcast(ResTy, W0);
1460
1461 SDValue W1Idx = DAG.getConstant(WordIdx+1, dl, MVT::i32);
1462 SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);
1463 SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);
1464 return DAG.getBitcast(ResTy, WW);
1465}
1466
1467SDValue
1468HexagonTargetLowering::extractHvxSubvectorPred(SDValue VecV, SDValue IdxV,
1469 const SDLoc &dl, MVT ResTy, SelectionDAG &DAG) const {
1470 MVT VecTy = ty(VecV);
1471 unsigned HwLen = Subtarget.getVectorLength();
1472 MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);
1473 SDValue ByteVec = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, VecV);
1474 // IdxV is required to be a constant.
1475 unsigned Idx = IdxV.getNode()->getAsZExtVal();
1476
1477 unsigned ResLen = ResTy.getVectorNumElements();
1478 unsigned BitBytes = HwLen / VecTy.getVectorNumElements();
1479 unsigned Offset = Idx * BitBytes;
1480 SDValue Undef = DAG.getUNDEF(ByteTy);
1481 SmallVector<int,128> Mask;
1482
1483 if (Subtarget.isHVXVectorType(ResTy, true)) {
1484 // Converting between two vector predicates. Since the result is shorter
1485 // than the source, it will correspond to a vector predicate with the
1486 // relevant bits replicated. The replication count is the ratio of the
1487 // source and target vector lengths.
1488 unsigned Rep = VecTy.getVectorNumElements() / ResLen;
1489 assert(isPowerOf2_32(Rep) && HwLen % Rep == 0);
1490 for (unsigned i = 0; i != HwLen/Rep; ++i) {
1491 for (unsigned j = 0; j != Rep; ++j)
1492 Mask.push_back(i + Offset);
1493 }
1494 SDValue ShuffV = DAG.getVectorShuffle(ByteTy, dl, ByteVec, Undef, Mask);
1495 return DAG.getNode(HexagonISD::V2Q, dl, ResTy, ShuffV);
1496 }
1497
1498 // Converting between a vector predicate and a scalar predicate. In the
1499 // vector predicate, a group of BitBytes bits will correspond to a single
1500 // i1 element of the source vector type. Those bits will all have the same
1501 // value. The same will be true for ByteVec, where each byte corresponds
1502 // to a bit in the vector predicate.
1503 // The algorithm is to traverse the ByteVec, going over the i1 values from
1504 // the source vector, and generate the corresponding representation in an
1505 // 8-byte vector. To avoid repeated extracts from ByteVec, shuffle the
1506 // elements so that the interesting 8 bytes will be in the low end of the
1507 // vector.
1508 unsigned Rep = 8 / ResLen;
1509 // Make sure the output fill the entire vector register, so repeat the
1510 // 8-byte groups as many times as necessary.
1511 for (unsigned r = 0; r != HwLen / 8; ++r) {
1512 // This will generate the indexes of the 8 interesting bytes.
1513 for (unsigned i = 0; i != ResLen; ++i) {
1514 for (unsigned j = 0; j != Rep; ++j)
1515 Mask.push_back(Offset + i*BitBytes);
1516 }
1517 }
1518
1519 SDValue Zero = getZero(dl, MVT::i32, DAG);
1520 SDValue ShuffV = DAG.getVectorShuffle(ByteTy, dl, ByteVec, Undef, Mask);
1521 // Combine the two low words from ShuffV into a v8i8, and byte-compare
1522 // them against 0.
1523 SDValue W0 = DAG.getNode(HexagonISD::VEXTRACTW, dl, MVT::i32, {ShuffV, Zero});
1524 SDValue W1 = DAG.getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,
1525 {ShuffV, DAG.getConstant(4, dl, MVT::i32)});
1526 SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);
1527 return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,
1528 {Vec64, DAG.getTargetConstant(0, dl, MVT::i32)}, DAG);
1529}
1530
1531SDValue
1532HexagonTargetLowering::insertHvxSubvectorReg(SDValue VecV, SDValue SubV,
1533 SDValue IdxV, const SDLoc &dl, SelectionDAG &DAG) const {
1534 MVT VecTy = ty(VecV);
1535 MVT SubTy = ty(SubV);
1536 unsigned HwLen = Subtarget.getVectorLength();
1537 MVT ElemTy = VecTy.getVectorElementType();
1538 unsigned ElemWidth = ElemTy.getSizeInBits();
1539
1540 bool IsPair = isHvxPairTy(VecTy);
1541 MVT SingleTy = MVT::getVectorVT(ElemTy, (8*HwLen)/ElemWidth);
1542 // The two single vectors that VecV consists of, if it's a pair.
1543 SDValue V0, V1;
1544 SDValue SingleV = VecV;
1545 SDValue PickHi;
1546
1547 if (IsPair) {
1548 V0 = LoHalf(VecV, DAG);
1549 V1 = HiHalf(VecV, DAG);
1550
1551 SDValue HalfV = DAG.getConstant(SingleTy.getVectorNumElements(),
1552 dl, MVT::i32);
1553 PickHi = DAG.getSetCC(dl, MVT::i1, IdxV, HalfV, ISD::SETUGT);
1554 if (isHvxSingleTy(SubTy)) {
1555 if (const auto *CN = dyn_cast<const ConstantSDNode>(IdxV.getNode())) {
1556 unsigned Idx = CN->getZExtValue();
1557 assert(Idx == 0 || Idx == VecTy.getVectorNumElements()/2);
1558 unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;
1559 return DAG.getTargetInsertSubreg(SubIdx, dl, VecTy, VecV, SubV);
1560 }
1561 // If IdxV is not a constant, generate the two variants: with the
1562 // SubV as the high and as the low subregister, and select the right
1563 // pair based on the IdxV.
1564 SDValue InLo = DAG.getNode(ISD::CONCAT_VECTORS, dl, VecTy, {SubV, V1});
1565 SDValue InHi = DAG.getNode(ISD::CONCAT_VECTORS, dl, VecTy, {V0, SubV});
1566 return DAG.getNode(ISD::SELECT, dl, VecTy, PickHi, InHi, InLo);
1567 }
1568 // The subvector being inserted must be entirely contained in one of
1569 // the vectors V0 or V1. Set SingleV to the correct one, and update
1570 // IdxV to be the index relative to the beginning of that vector.
1571 SDValue S = DAG.getNode(ISD::SUB, dl, MVT::i32, IdxV, HalfV);
1572 IdxV = DAG.getNode(ISD::SELECT, dl, MVT::i32, PickHi, S, IdxV);
1573 SingleV = DAG.getNode(ISD::SELECT, dl, SingleTy, PickHi, V1, V0);
1574 }
1575
1576 // The only meaningful subvectors of a single HVX vector are those that
1577 // fit in a scalar register.
1578 assert(SubTy.getSizeInBits() == 32 || SubTy.getSizeInBits() == 64);
1579 // Convert IdxV to be index in bytes.
1580 auto *IdxN = dyn_cast<ConstantSDNode>(IdxV.getNode());
1581 if (!IdxN || !IdxN->isZero()) {
1582 IdxV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV,
1583 DAG.getConstant(ElemWidth/8, dl, MVT::i32));
1584 SingleV = DAG.getNode(HexagonISD::VROR, dl, SingleTy, SingleV, IdxV);
1585 }
1586 // When inserting a single word, the rotation back to the original position
1587 // would be by HwLen-Idx, but if two words are inserted, it will need to be
1588 // by (HwLen-4)-Idx.
1589 unsigned RolBase = HwLen;
1590 if (SubTy.getSizeInBits() == 32) {
1591 SDValue V = DAG.getBitcast(MVT::i32, SubV);
1592 SingleV = DAG.getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, V);
1593 } else {
1594 SDValue V = DAG.getBitcast(MVT::i64, SubV);
1595 SDValue R0 = LoHalf(V, DAG);
1596 SDValue R1 = HiHalf(V, DAG);
1597 SingleV = DAG.getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R0);
1598 SingleV = DAG.getNode(HexagonISD::VROR, dl, SingleTy, SingleV,
1599 DAG.getConstant(4, dl, MVT::i32));
1600 SingleV = DAG.getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R1);
1601 RolBase = HwLen-4;
1602 }
1603 // If the vector wasn't ror'ed, don't ror it back.
1604 if (RolBase != 4 || !IdxN || !IdxN->isZero()) {
1605 SDValue RolV = DAG.getNode(ISD::SUB, dl, MVT::i32,
1606 DAG.getConstant(RolBase, dl, MVT::i32), IdxV);
1607 SingleV = DAG.getNode(HexagonISD::VROR, dl, SingleTy, SingleV, RolV);
1608 }
1609
1610 if (IsPair) {
1611 SDValue InLo = DAG.getNode(ISD::CONCAT_VECTORS, dl, VecTy, {SingleV, V1});
1612 SDValue InHi = DAG.getNode(ISD::CONCAT_VECTORS, dl, VecTy, {V0, SingleV});
1613 return DAG.getNode(ISD::SELECT, dl, VecTy, PickHi, InHi, InLo);
1614 }
1615 return SingleV;
1616}
1617
1618SDValue
1619HexagonTargetLowering::insertHvxSubvectorPred(SDValue VecV, SDValue SubV,
1620 SDValue IdxV, const SDLoc &dl, SelectionDAG &DAG) const {
1621 MVT VecTy = ty(VecV);
1622 MVT SubTy = ty(SubV);
1623 assert(Subtarget.isHVXVectorType(VecTy, true));
1624 // VecV is an HVX vector predicate. SubV may be either an HVX vector
1625 // predicate as well, or it can be a scalar predicate.
1626
1627 unsigned VecLen = VecTy.getVectorNumElements();
1628 unsigned HwLen = Subtarget.getVectorLength();
1629 assert(HwLen % VecLen == 0 && "Unexpected vector type");
1630
1631 unsigned Scale = VecLen / SubTy.getVectorNumElements();
1632 unsigned BitBytes = HwLen / VecLen;
1633 unsigned BlockLen = HwLen / Scale;
1634
1635 MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);
1636 SDValue ByteVec = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, VecV);
1637 SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes, false, DAG);
1638 SDValue ByteIdx;
1639
1640 auto *IdxN = dyn_cast<ConstantSDNode>(IdxV.getNode());
1641 if (!IdxN || !IdxN->isZero()) {
1642 ByteIdx = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV,
1643 DAG.getConstant(BitBytes, dl, MVT::i32));
1644 ByteVec = DAG.getNode(HexagonISD::VROR, dl, ByteTy, ByteVec, ByteIdx);
1645 }
1646
1647 // ByteVec is the target vector VecV rotated in such a way that the
1648 // subvector should be inserted at index 0. Generate a predicate mask
1649 // and use vmux to do the insertion.
1650 assert(BlockLen < HwLen && "vsetq(v1) prerequisite");
1651 MVT BoolTy = MVT::getVectorVT(MVT::i1, HwLen);
1652 SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1653 {DAG.getConstant(BlockLen, dl, MVT::i32)}, DAG);
1654 ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);
1655 // Rotate ByteVec back, and convert to a vector predicate.
1656 if (!IdxN || !IdxN->isZero()) {
1657 SDValue HwLenV = DAG.getConstant(HwLen, dl, MVT::i32);
1658 SDValue ByteXdi = DAG.getNode(ISD::SUB, dl, MVT::i32, HwLenV, ByteIdx);
1659 ByteVec = DAG.getNode(HexagonISD::VROR, dl, ByteTy, ByteVec, ByteXdi);
1660 }
1661 return DAG.getNode(HexagonISD::V2Q, dl, VecTy, ByteVec);
1662}
1663
1664SDValue
1665HexagonTargetLowering::extendHvxVectorPred(SDValue VecV, const SDLoc &dl,
1666 MVT ResTy, bool ZeroExt, SelectionDAG &DAG) const {
1667 // Sign- and any-extending of a vector predicate to a vector register is
1668 // equivalent to Q2V. For zero-extensions, generate a vmux between 0 and
1669 // a vector of 1s (where the 1s are of type matching the vector type).
1670 assert(Subtarget.isHVXVectorType(ResTy));
1671 if (!ZeroExt)
1672 return DAG.getNode(HexagonISD::Q2V, dl, ResTy, VecV);
1673
1674 assert(ty(VecV).getVectorNumElements() == ResTy.getVectorNumElements());
1675 SDValue True = DAG.getNode(ISD::SPLAT_VECTOR, dl, ResTy,
1676 DAG.getConstant(1, dl, MVT::i32));
1677 SDValue False = getZero(dl, ResTy, DAG);
1678 return DAG.getSelect(dl, ResTy, VecV, True, False);
1679}
1680
1681SDValue
1682HexagonTargetLowering::compressHvxPred(SDValue VecQ, const SDLoc &dl,
1683 MVT ResTy, SelectionDAG &DAG) const {
1684 // Given a predicate register VecQ, transfer bits VecQ[0..HwLen-1]
1685 // (i.e. the entire predicate register) to bits [0..HwLen-1] of a
1686 // vector register. The remaining bits of the vector register are
1687 // unspecified.
1688
1690 unsigned HwLen = Subtarget.getVectorLength();
1691 MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);
1692 MVT PredTy = ty(VecQ);
1693 unsigned PredLen = PredTy.getVectorNumElements();
1694 assert(HwLen % PredLen == 0);
1695 MVT VecTy = MVT::getVectorVT(MVT::getIntegerVT(8*HwLen/PredLen), PredLen);
1696
1697 Type *Int8Ty = Type::getInt8Ty(*DAG.getContext());
1699 // Create an array of bytes (hex): 01,02,04,08,10,20,40,80, 01,02,04,08,...
1700 // These are bytes with the LSB rotated left with respect to their index.
1701 for (unsigned i = 0; i != HwLen/8; ++i) {
1702 for (unsigned j = 0; j != 8; ++j)
1703 Tmp.push_back(ConstantInt::get(Int8Ty, 1ull << j));
1704 }
1705 Constant *CV = ConstantVector::get(Tmp);
1706 Align Alignment(HwLen);
1708 DAG.getConstantPool(CV, getPointerTy(DAG.getDataLayout()), Alignment),
1709 DAG);
1710 SDValue Bytes =
1711 DAG.getLoad(ByteTy, dl, DAG.getEntryNode(), CP,
1713
1714 // Select the bytes that correspond to true bits in the vector predicate.
1715 SDValue Sel = DAG.getSelect(dl, VecTy, VecQ, DAG.getBitcast(VecTy, Bytes),
1716 getZero(dl, VecTy, DAG));
1717 // Calculate the OR of all bytes in each group of 8. That will compress
1718 // all the individual bits into a single byte.
1719 // First, OR groups of 4, via vrmpy with 0x01010101.
1720 SDValue All1 =
1721 DAG.getSplatBuildVector(MVT::v4i8, dl, DAG.getConstant(1, dl, MVT::i32));
1722 SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);
1723 // Then rotate the accumulated vector by 4 bytes, and do the final OR.
1724 SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,
1725 {Vrmpy, Vrmpy, DAG.getTargetConstant(4, dl, MVT::i32)}, DAG);
1726 SDValue Vor = DAG.getNode(ISD::OR, dl, ByteTy, {Vrmpy, Rot});
1727
1728 // Pick every 8th byte and coalesce them at the beginning of the output.
1729 // For symmetry, coalesce every 1+8th byte after that, then every 2+8th
1730 // byte and so on.
1731 SmallVector<int,128> Mask;
1732 for (unsigned i = 0; i != HwLen; ++i)
1733 Mask.push_back((8*i) % HwLen + i/(HwLen/8));
1734 SDValue Collect =
1735 DAG.getVectorShuffle(ByteTy, dl, Vor, DAG.getUNDEF(ByteTy), Mask);
1736 return DAG.getBitcast(ResTy, Collect);
1737}
1738
1739SDValue
1740HexagonTargetLowering::resizeToWidth(SDValue VecV, MVT ResTy, bool Signed,
1741 const SDLoc &dl, SelectionDAG &DAG) const {
1742 // Take a vector and resize the element type to match the given type.
1743 MVT InpTy = ty(VecV);
1744 if (InpTy == ResTy)
1745 return VecV;
1746
1747 unsigned InpWidth = InpTy.getSizeInBits();
1748 unsigned ResWidth = ResTy.getSizeInBits();
1749
1750 if (InpTy.isFloatingPoint()) {
1751 return InpWidth < ResWidth
1752 ? DAG.getNode(ISD::FP_EXTEND, dl, ResTy, VecV)
1753 : DAG.getNode(ISD::FP_ROUND, dl, ResTy, VecV,
1754 DAG.getTargetConstant(0, dl, MVT::i32));
1755 }
1756
1757 assert(InpTy.isInteger());
1758
1759 if (InpWidth < ResWidth) {
1760 unsigned ExtOpc = Signed ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
1761 return DAG.getNode(ExtOpc, dl, ResTy, VecV);
1762 } else {
1763 unsigned NarOpc = Signed ? HexagonISD::SSAT : HexagonISD::USAT;
1764 return DAG.getNode(NarOpc, dl, ResTy, VecV, DAG.getValueType(ResTy));
1765 }
1766}
1767
1768SDValue
1769HexagonTargetLowering::extractSubvector(SDValue Vec, MVT SubTy, unsigned SubIdx,
1770 SelectionDAG &DAG) const {
1771 assert(ty(Vec).getSizeInBits() % SubTy.getSizeInBits() == 0);
1772
1773 const SDLoc &dl(Vec);
1774 unsigned ElemIdx = SubIdx * SubTy.getVectorNumElements();
1775 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubTy,
1776 {Vec, DAG.getConstant(ElemIdx, dl, MVT::i32)});
1777}
1778
1779SDValue
1780HexagonTargetLowering::LowerHvxBuildVector(SDValue Op, SelectionDAG &DAG)
1781 const {
1782 const SDLoc &dl(Op);
1783 MVT VecTy = ty(Op);
1784
1785 unsigned Size = Op.getNumOperands();
1787 for (unsigned i = 0; i != Size; ++i)
1788 Ops.push_back(Op.getOperand(i));
1789
1790 if (VecTy.getVectorElementType() == MVT::i1)
1791 return buildHvxVectorPred(Ops, dl, VecTy, DAG);
1792
1793 // In case of MVT::f16 BUILD_VECTOR, since MVT::f16 is
1794 // not a legal type, just bitcast the node to use i16
1795 // types and bitcast the result back to f16
1796 if (VecTy.getVectorElementType() == MVT::f16 ||
1797 VecTy.getVectorElementType() == MVT::bf16) {
1799 for (unsigned i = 0; i != Size; i++)
1800 NewOps.push_back(DAG.getBitcast(MVT::i16, Ops[i]));
1801
1802 SDValue T0 =
1803 DAG.getNode(ISD::BUILD_VECTOR, dl, tyVector(VecTy, MVT::i16), NewOps);
1804 return DAG.getBitcast(tyVector(VecTy, VecTy.getVectorElementType()), T0);
1805 }
1806
1807 // First, split the BUILD_VECTOR for vector pairs. We could generate
1808 // some pairs directly (via splat), but splats should be generated
1809 // by the combiner prior to getting here.
1810 if (VecTy.getSizeInBits() == 16 * Subtarget.getVectorLength()) {
1812 MVT SingleTy = typeSplit(VecTy).first;
1813 SDValue V0 = buildHvxVectorReg(A.take_front(Size / 2), dl, SingleTy, DAG);
1814 SDValue V1 = buildHvxVectorReg(A.drop_front(Size / 2), dl, SingleTy, DAG);
1815 return DAG.getNode(ISD::CONCAT_VECTORS, dl, VecTy, V0, V1);
1816 }
1817
1818 return buildHvxVectorReg(Ops, dl, VecTy, DAG);
1819}
1820
1821SDValue
1822HexagonTargetLowering::LowerHvxSplatVector(SDValue Op, SelectionDAG &DAG)
1823 const {
1824 const SDLoc &dl(Op);
1825 MVT VecTy = ty(Op);
1826 MVT ArgTy = ty(Op.getOperand(0));
1827
1828 if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {
1829 MVT SplatTy = MVT::getVectorVT(MVT::i16, VecTy.getVectorNumElements());
1830 SDValue ToInt16 = DAG.getBitcast(MVT::i16, Op.getOperand(0));
1831 SDValue ToInt32 = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i32, ToInt16);
1832 SDValue Splat = DAG.getNode(ISD::SPLAT_VECTOR, dl, SplatTy, ToInt32);
1833 return DAG.getBitcast(VecTy, Splat);
1834 }
1835
1836 return SDValue();
1837}
1838
1839SDValue
1840HexagonTargetLowering::LowerHvxConcatVectors(SDValue Op, SelectionDAG &DAG)
1841 const {
1842 // Vector concatenation of two integer (non-bool) vectors does not need
1843 // special lowering. Custom-lower concats of bool vectors and expand
1844 // concats of more than 2 vectors.
1845 MVT VecTy = ty(Op);
1846 const SDLoc &dl(Op);
1847 unsigned NumOp = Op.getNumOperands();
1848 if (VecTy.getVectorElementType() != MVT::i1) {
1849 if (NumOp == 2)
1850 return Op;
1851 // Expand the other cases into a build-vector.
1853 for (SDValue V : Op.getNode()->ops())
1854 DAG.ExtractVectorElements(V, Elems);
1855 // A vector of i16 will be broken up into a build_vector of i16's.
1856 // This is a problem, since at the time of operation legalization,
1857 // all operations are expected to be type-legalized, and i16 is not
1858 // a legal type. If any of the extracted elements is not of a valid
1859 // type, sign-extend it to a valid one.
1860 for (SDValue &V : Elems) {
1861 MVT Ty = ty(V);
1862 if (!isTypeLegal(Ty)) {
1863 MVT NTy = typeLegalize(Ty, DAG);
1864 if (V.getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
1865 V = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, NTy,
1866 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NTy,
1867 V.getOperand(0), V.getOperand(1)),
1868 DAG.getValueType(Ty));
1869 continue;
1870 }
1871 // A few less complicated cases.
1872 switch (V.getOpcode()) {
1873 case ISD::Constant:
1874 V = DAG.getSExtOrTrunc(V, dl, NTy);
1875 break;
1876 case ISD::UNDEF:
1877 V = DAG.getUNDEF(NTy);
1878 break;
1879 case ISD::TRUNCATE:
1880 V = V.getOperand(0);
1881 break;
1882 default:
1883 llvm_unreachable("Unexpected vector element");
1884 }
1885 }
1886 }
1887 return DAG.getBuildVector(VecTy, dl, Elems);
1888 }
1889
1890 assert(VecTy.getVectorElementType() == MVT::i1);
1891 unsigned HwLen = Subtarget.getVectorLength();
1892 assert(isPowerOf2_32(NumOp) && HwLen % NumOp == 0);
1893
1894 SDValue Op0 = Op.getOperand(0);
1895
1896 // If the operands are HVX types (i.e. not scalar predicates), then
1897 // defer the concatenation, and create QCAT instead.
1898 if (Subtarget.isHVXVectorType(ty(Op0), true)) {
1899 if (NumOp == 2)
1900 return DAG.getNode(HexagonISD::QCAT, dl, VecTy, Op0, Op.getOperand(1));
1901
1902 ArrayRef<SDUse> U(Op.getNode()->ops());
1905
1906 MVT HalfTy = typeSplit(VecTy).first;
1907 SDValue V0 = DAG.getNode(ISD::CONCAT_VECTORS, dl, HalfTy,
1908 Ops.take_front(NumOp/2));
1909 SDValue V1 = DAG.getNode(ISD::CONCAT_VECTORS, dl, HalfTy,
1910 Ops.take_back(NumOp/2));
1911 return DAG.getNode(HexagonISD::QCAT, dl, VecTy, V0, V1);
1912 }
1913
1914 // Count how many bytes (in a vector register) each bit in VecTy
1915 // corresponds to.
1916 unsigned BitBytes = HwLen / VecTy.getVectorNumElements();
1917
1918 // Make sure that createHvxPrefixPred will only ever need to expand
1919 // the predicate, i.e. bytes-per-bit in the input is not greater than
1920 // the target bytes-per-bit in the result.
1921 SDValue Combined = combineConcatOfScalarPreds(Op, BitBytes, DAG);
1922 SmallVector<SDValue,8> Prefixes;
1923 for (SDValue V : Combined.getNode()->op_values()) {
1924 SDValue P = createHvxPrefixPred(V, dl, BitBytes, true, DAG);
1925 Prefixes.push_back(P);
1926 }
1927
1928 unsigned InpLen = ty(Combined.getOperand(0)).getVectorNumElements();
1929 MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);
1930 SDValue S = DAG.getConstant(HwLen - InpLen*BitBytes, dl, MVT::i32);
1931 SDValue Res = getZero(dl, ByteTy, DAG);
1932 for (unsigned i = 0, e = Prefixes.size(); i != e; ++i) {
1933 Res = DAG.getNode(HexagonISD::VROR, dl, ByteTy, Res, S);
1934 Res = DAG.getNode(ISD::OR, dl, ByteTy, Res, Prefixes[e-i-1]);
1935 }
1936 return DAG.getNode(HexagonISD::V2Q, dl, VecTy, Res);
1937}
1938
1939SDValue
1940HexagonTargetLowering::LowerHvxExtractElement(SDValue Op, SelectionDAG &DAG)
1941 const {
1942 // Change the type of the extracted element to i32.
1943 SDValue VecV = Op.getOperand(0);
1944 MVT ElemTy = ty(VecV).getVectorElementType();
1945 const SDLoc &dl(Op);
1946 SDValue IdxV = Op.getOperand(1);
1947 if (ElemTy == MVT::i1)
1948 return extractHvxElementPred(VecV, IdxV, dl, ty(Op), DAG);
1949
1950 return extractHvxElementReg(VecV, IdxV, dl, ty(Op), DAG);
1951}
1952
1953SDValue
1954HexagonTargetLowering::LowerHvxInsertElement(SDValue Op, SelectionDAG &DAG)
1955 const {
1956 const SDLoc &dl(Op);
1957 MVT VecTy = ty(Op);
1958 SDValue VecV = Op.getOperand(0);
1959 SDValue ValV = Op.getOperand(1);
1960 SDValue IdxV = Op.getOperand(2);
1961 MVT ElemTy = ty(VecV).getVectorElementType();
1962 if (ElemTy == MVT::i1)
1963 return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);
1964
1965 if (ElemTy == MVT::f16 || ElemTy == MVT::bf16) {
1967 tyVector(VecTy, MVT::i16),
1968 DAG.getBitcast(tyVector(VecTy, MVT::i16), VecV),
1969 DAG.getBitcast(MVT::i16, ValV), IdxV);
1970 return DAG.getBitcast(tyVector(VecTy, ElemTy), T0);
1971 }
1972
1973 return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);
1974}
1975
1976SDValue
1977HexagonTargetLowering::LowerHvxExtractSubvector(SDValue Op, SelectionDAG &DAG)
1978 const {
1979 SDValue SrcV = Op.getOperand(0);
1980 MVT SrcTy = ty(SrcV);
1981 MVT DstTy = ty(Op);
1982 SDValue IdxV = Op.getOperand(1);
1983 unsigned Idx = IdxV.getNode()->getAsZExtVal();
1984 assert(Idx % DstTy.getVectorNumElements() == 0);
1985 (void)Idx;
1986 const SDLoc &dl(Op);
1987
1988 MVT ElemTy = SrcTy.getVectorElementType();
1989 if (ElemTy == MVT::i1)
1990 return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);
1991
1992 return extractHvxSubvectorReg(Op, SrcV, IdxV, dl, DstTy, DAG);
1993}
1994
1995SDValue
1996HexagonTargetLowering::LowerHvxInsertSubvector(SDValue Op, SelectionDAG &DAG)
1997 const {
1998 // Idx does not need to be a constant.
1999 SDValue VecV = Op.getOperand(0);
2000 SDValue ValV = Op.getOperand(1);
2001 SDValue IdxV = Op.getOperand(2);
2002
2003 const SDLoc &dl(Op);
2004 MVT VecTy = ty(VecV);
2005 MVT ElemTy = VecTy.getVectorElementType();
2006 if (ElemTy == MVT::i1)
2007 return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);
2008
2009 return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);
2010}
2011
2012SDValue
2013HexagonTargetLowering::LowerHvxAnyExt(SDValue Op, SelectionDAG &DAG) const {
2014 // Lower any-extends of boolean vectors to sign-extends, since they
2015 // translate directly to Q2V. Zero-extending could also be done equally
2016 // fast, but Q2V is used/recognized in more places.
2017 // For all other vectors, use zero-extend.
2018 MVT ResTy = ty(Op);
2019 SDValue InpV = Op.getOperand(0);
2020 MVT ElemTy = ty(InpV).getVectorElementType();
2021 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2022 return LowerHvxSignExt(Op, DAG);
2023 return DAG.getNode(ISD::ZERO_EXTEND, SDLoc(Op), ResTy, InpV);
2024}
2025
2026SDValue
2027HexagonTargetLowering::LowerHvxSignExt(SDValue Op, SelectionDAG &DAG) const {
2028 MVT ResTy = ty(Op);
2029 SDValue InpV = Op.getOperand(0);
2030 MVT ElemTy = ty(InpV).getVectorElementType();
2031 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2032 return extendHvxVectorPred(InpV, SDLoc(Op), ty(Op), false, DAG);
2033 return Op;
2034}
2035
2036SDValue
2037HexagonTargetLowering::LowerHvxZeroExt(SDValue Op, SelectionDAG &DAG) const {
2038 MVT ResTy = ty(Op);
2039 SDValue InpV = Op.getOperand(0);
2040 MVT ElemTy = ty(InpV).getVectorElementType();
2041 if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))
2042 return extendHvxVectorPred(InpV, SDLoc(Op), ty(Op), true, DAG);
2043 return Op;
2044}
2045
2046SDValue
2047HexagonTargetLowering::LowerHvxCttz(SDValue Op, SelectionDAG &DAG) const {
2048 // Lower vector CTTZ into a computation using CTLZ (Hacker's Delight):
2049 // cttz(x) = bitwidth(x) - ctlz(~x & (x-1))
2050 const SDLoc &dl(Op);
2051 MVT ResTy = ty(Op);
2052 SDValue InpV = Op.getOperand(0);
2053 assert(ResTy == ty(InpV));
2054
2055 // Calculate the vectors of 1 and bitwidth(x).
2056 MVT ElemTy = ty(InpV).getVectorElementType();
2057 unsigned ElemWidth = ElemTy.getSizeInBits();
2058
2059 SDValue Vec1 = DAG.getNode(ISD::SPLAT_VECTOR, dl, ResTy,
2060 DAG.getConstant(1, dl, MVT::i32));
2061 SDValue VecW = DAG.getNode(ISD::SPLAT_VECTOR, dl, ResTy,
2062 DAG.getConstant(ElemWidth, dl, MVT::i32));
2063 SDValue VecN1 = DAG.getNode(ISD::SPLAT_VECTOR, dl, ResTy,
2064 DAG.getAllOnesConstant(dl, MVT::i32));
2065
2066 // Do not use DAG.getNOT, because that would create BUILD_VECTOR with
2067 // a BITCAST. Here we can skip the BITCAST (so we don't have to handle
2068 // it separately in custom combine or selection).
2069 SDValue A = DAG.getNode(ISD::AND, dl, ResTy,
2070 {DAG.getNode(ISD::XOR, dl, ResTy, {InpV, VecN1}),
2071 DAG.getNode(ISD::SUB, dl, ResTy, {InpV, Vec1})});
2072 return DAG.getNode(ISD::SUB, dl, ResTy,
2073 {VecW, DAG.getNode(ISD::CTLZ, dl, ResTy, A)});
2074}
2075
2076SDValue
2077HexagonTargetLowering::LowerHvxMulh(SDValue Op, SelectionDAG &DAG) const {
2078 const SDLoc &dl(Op);
2079 MVT ResTy = ty(Op);
2080 assert(ResTy.getVectorElementType() == MVT::i32);
2081
2082 SDValue Vs = Op.getOperand(0);
2083 SDValue Vt = Op.getOperand(1);
2084
2085 SDVTList ResTys = DAG.getVTList(ResTy, ResTy);
2086 unsigned Opc = Op.getOpcode();
2087
2088 // On HVX v62+ producing the full product is cheap, so legalize MULH to LOHI.
2089 if (Opc == ISD::MULHU)
2090 return DAG.getNode(HexagonISD::UMUL_LOHI, dl, ResTys, {Vs, Vt}).getValue(1);
2091 if (Opc == ISD::MULHS)
2092 return DAG.getNode(HexagonISD::SMUL_LOHI, dl, ResTys, {Vs, Vt}).getValue(1);
2093
2094#ifndef NDEBUG
2095 Op.dump(&DAG);
2096#endif
2097 llvm_unreachable("Unexpected mulh operation");
2098}
2099
2100SDValue
2101HexagonTargetLowering::LowerHvxMulLoHi(SDValue Op, SelectionDAG &DAG) const {
2102 const SDLoc &dl(Op);
2103 unsigned Opc = Op.getOpcode();
2104 SDValue Vu = Op.getOperand(0);
2105 SDValue Vv = Op.getOperand(1);
2106
2107 // If the HI part is not used, convert it to a regular MUL.
2108 if (auto HiVal = Op.getValue(1); HiVal.use_empty()) {
2109 // Need to preserve the types and the number of values.
2110 SDValue Hi = DAG.getUNDEF(ty(HiVal));
2111 SDValue Lo = DAG.getNode(ISD::MUL, dl, ty(Op), {Vu, Vv});
2112 return DAG.getMergeValues({Lo, Hi}, dl);
2113 }
2114
2115 bool SignedVu = Opc == HexagonISD::SMUL_LOHI;
2116 bool SignedVv = Opc == HexagonISD::SMUL_LOHI || Opc == HexagonISD::USMUL_LOHI;
2117
2118 // Legal on HVX v62+, but lower it here because patterns can't handle multi-
2119 // valued nodes.
2120 if (Subtarget.useHVXV62Ops())
2121 return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2122
2123 if (Opc == HexagonISD::SMUL_LOHI) {
2124 // Direct MULHS expansion is cheaper than doing the whole SMUL_LOHI,
2125 // for other signedness LOHI is cheaper.
2126 if (auto LoVal = Op.getValue(0); LoVal.use_empty()) {
2127 SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);
2128 SDValue Lo = DAG.getUNDEF(ty(LoVal));
2129 return DAG.getMergeValues({Lo, Hi}, dl);
2130 }
2131 }
2132
2133 return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);
2134}
2135
2136SDValue
2137HexagonTargetLowering::LowerHvxBitcast(SDValue Op, SelectionDAG &DAG) const {
2138 SDValue Val = Op.getOperand(0);
2139 MVT ResTy = ty(Op);
2140 MVT ValTy = ty(Val);
2141 const SDLoc &dl(Op);
2142
2143 if (isHvxBoolTy(ValTy) && ResTy.isScalarInteger()) {
2144 unsigned HwLen = Subtarget.getVectorLength();
2145 MVT WordTy = MVT::getVectorVT(MVT::i32, HwLen/4);
2146
2147 // When the predicate is shorter than the predicate register, each boolean
2148 // is represented by multiple consecutive bits in the input register.
2149 // Condense the bits so each boolean is represented by one bit. This only
2150 // handles 2x and 4x compaction ratios.
2151 unsigned PredLen = ValTy.getVectorNumElements();
2152 if (PredLen < HwLen) {
2153 MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);
2154 Val = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, Val);
2155 if (HwLen > PredLen * 2) {
2156 assert(HwLen == PredLen * 4);
2157 PredLen *= 2;
2158 Val = getInstr(Hexagon::V6_vdealh, dl, ByteTy, Val, DAG);
2159 }
2160 if (HwLen > PredLen) {
2161 assert(HwLen == PredLen * 2);
2162 Val = getInstr(Hexagon::V6_vdealb, dl, ByteTy, Val, DAG);
2163 }
2164 Val = DAG.getNode(HexagonISD::V2Q, dl, ValTy, Val);
2165 }
2166
2167 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2168 unsigned BitWidth = ResTy.getSizeInBits();
2169
2170 if (BitWidth < 64) {
2171 SDValue W0 = extractHvxElementReg(VQ, DAG.getConstant(0, dl, MVT::i32),
2172 dl, MVT::i32, DAG);
2173 if (BitWidth == 32)
2174 return W0;
2175 assert(BitWidth < 32u);
2176 return DAG.getZExtOrTrunc(W0, dl, ResTy);
2177 }
2178
2179 // The result is >= 64 bits. The only options are 64 or 128.
2180 assert(BitWidth == 64 || BitWidth == 128);
2182 for (unsigned i = 0; i != BitWidth/32; ++i) {
2183 SDValue W = extractHvxElementReg(
2184 VQ, DAG.getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);
2185 Words.push_back(W);
2186 }
2187 SmallVector<SDValue,2> Combines;
2188 assert(Words.size() % 2 == 0);
2189 for (unsigned i = 0, e = Words.size(); i < e; i += 2) {
2190 SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);
2191 Combines.push_back(C);
2192 }
2193
2194 if (BitWidth == 64)
2195 return Combines[0];
2196
2197 return DAG.getNode(ISD::BUILD_PAIR, dl, ResTy, Combines);
2198 }
2199
2200 // Handle bitcast from i32, v2i16, and v4i8 to v32i1.
2201 // Splat the input into a 32-element i32 vector, then AND each element
2202 // with a unique bitmask to isolate individual bits.
2203 auto bitcastI32ToV32I1 = [&](SDValue Val32) {
2204 assert(Val32.getValueType().getSizeInBits() == 32 &&
2205 "Input must be 32 bits");
2206 MVT VecTy = MVT::getVectorVT(MVT::i32, 32);
2207 SDValue Splat = DAG.getNode(ISD::SPLAT_VECTOR, dl, VecTy, Val32);
2209 for (unsigned i = 0; i < 32; ++i)
2210 Mask.push_back(DAG.getConstant(1ull << i, dl, MVT::i32));
2211
2212 SDValue MaskVec = DAG.getBuildVector(VecTy, dl, Mask);
2213 SDValue Anded = DAG.getNode(ISD::AND, dl, VecTy, Splat, MaskVec);
2214 return DAG.getNode(HexagonISD::V2Q, dl, MVT::v32i1, Anded);
2215 };
2216 // === Case: v32i1 ===
2217 if (ResTy == MVT::v32i1 &&
2218 (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&
2219 Subtarget.useHVX128BOps()) {
2220 SDValue Val32 = Val;
2221 if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)
2222 Val32 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Val);
2223 return bitcastI32ToV32I1(Val32);
2224 }
2225 // === Case: v64i1 ===
2226 if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {
2227 // Split i64 into lo/hi 32-bit halves.
2228 SDValue Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Val);
2229 SDValue HiShifted = DAG.getNode(ISD::SRL, dl, MVT::i64, Val,
2230 DAG.getConstant(32, dl, MVT::i64));
2231 SDValue Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, HiShifted);
2232
2233 // Reuse the same 32-bit logic twice.
2234 SDValue LoRes = bitcastI32ToV32I1(Lo);
2235 SDValue HiRes = bitcastI32ToV32I1(Hi);
2236
2237 // Concatenate into a v64i1 predicate.
2238 return DAG.getNode(ISD::CONCAT_VECTORS, dl, MVT::v64i1, LoRes, HiRes);
2239 }
2240
2241 if (isHvxBoolTy(ResTy) && ValTy.isScalarInteger()) {
2242 // Handle bitcast from i128 -> v128i1 and i64 -> v64i1.
2243 unsigned BitWidth = ValTy.getSizeInBits();
2244 unsigned HwLen = Subtarget.getVectorLength();
2245 assert(BitWidth == HwLen);
2246
2247 MVT ValAsVecTy = MVT::getVectorVT(MVT::i8, BitWidth / 8);
2248 SDValue ValAsVec = DAG.getBitcast(ValAsVecTy, Val);
2249 // Splat each byte of Val 8 times.
2250 // Bytes = [(b0)x8, (b1)x8, ...., (b15)x8]
2251 // where b0, b1,..., b15 are least to most significant bytes of I.
2253 // Tmp: 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80, 0x01,0x02,0x04,0x08,...
2254 // These are bytes with the LSB rotated left with respect to their index.
2256 for (unsigned I = 0; I != HwLen / 8; ++I) {
2257 SDValue Idx = DAG.getConstant(I, dl, MVT::i32);
2258 SDValue Byte =
2259 DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i8, ValAsVec, Idx);
2260 for (unsigned J = 0; J != 8; ++J) {
2261 Bytes.push_back(Byte);
2262 Tmp.push_back(DAG.getConstant(1ull << J, dl, MVT::i8));
2263 }
2264 }
2265
2266 MVT ConstantVecTy = MVT::getVectorVT(MVT::i8, HwLen);
2267 SDValue ConstantVec = DAG.getBuildVector(ConstantVecTy, dl, Tmp);
2268 SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);
2269
2270 // Each Byte in the I2V will be set iff corresponding bit is set in Val.
2271 I2V = DAG.getNode(ISD::AND, dl, ConstantVecTy, {I2V, ConstantVec});
2272 return DAG.getNode(HexagonISD::V2Q, dl, ResTy, I2V);
2273 }
2274
2275 return Op;
2276}
2277
2278SDValue HexagonTargetLowering::LowerHvxStore(SDValue Op,
2279 SelectionDAG &DAG) const {
2280 const SDLoc &dl(Op);
2281 StoreSDNode *SN = cast<StoreSDNode>(Op.getNode());
2282 SDValue Val = SN->getValue();
2283 MVT ValTy = ty(Val);
2284
2285 // Check if this is a store of an HVX bool vector (predicate)
2286 if (!isHvxBoolTy(ValTy))
2287 return SDValue();
2288
2289 unsigned NumBits = ValTy.getVectorNumElements();
2290 MachineMemOperand *MMO = SN->getMemOperand();
2291
2292 // Check alignment requirements based on predicate size
2293 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2294 if (MMO->getBaseAlign().value() % RequiredAlign != 0)
2295 return SDValue();
2296
2297 unsigned HwLen = Subtarget.getVectorLength();
2298 MVT WordTy = MVT::getVectorVT(MVT::i32, HwLen / 4);
2299
2300 // Compress the predicate into a vector register
2301 SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);
2302
2303 // Extract words from the compressed vector
2305 for (unsigned i = 0; i != NumBits / 32; ++i) {
2306 SDValue W = extractHvxElementReg(VQ, DAG.getConstant(i, dl, MVT::i32), dl,
2307 MVT::i32, DAG);
2308 Words.push_back(W);
2309 }
2310
2311 SDValue Chain = SN->getChain();
2312 SDValue BasePtr = SN->getBasePtr();
2313 MachinePointerInfo PtrInfo = MMO->getPointerInfo();
2314
2315 if (NumBits == 32)
2316 return DAG.getStore(Chain, dl, Words[0], BasePtr, PtrInfo,
2317 MMO->getBaseAlign());
2318
2319 if (NumBits == 64) {
2320 SDValue W64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2321 return DAG.getStore(Chain, dl, W64, BasePtr, PtrInfo, MMO->getBaseAlign());
2322 }
2323
2324 if (NumBits == 128) {
2325 SDValue Lo64 = getCombine(Words[1], Words[0], dl, MVT::i64, DAG);
2326 SDValue Hi64 = getCombine(Words[3], Words[2], dl, MVT::i64, DAG);
2327
2328 Chain =
2329 DAG.getStore(Chain, dl, Lo64, BasePtr, PtrInfo, MMO->getBaseAlign());
2330
2331 SDValue Offset8 = DAG.getConstant(8, dl, MVT::i32);
2332 SDValue Ptr8 = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr, Offset8);
2333 return DAG.getStore(Chain, dl, Hi64, Ptr8, PtrInfo.getWithOffset(8),
2334 Align(8));
2335 }
2336
2337 return SDValue();
2338}
2339
2340SDValue HexagonTargetLowering::LowerHvxLoad(SDValue Op,
2341 SelectionDAG &DAG) const {
2342 const SDLoc &dl(Op);
2343 LoadSDNode *LN = cast<LoadSDNode>(Op.getNode());
2344 MVT ResTy = ty(Op);
2345
2346 // Check if this is a load of an HVX bool vector (predicate)
2347 if (!isHvxBoolTy(ResTy))
2348 return SDValue();
2349
2350 unsigned NumBits = ResTy.getVectorNumElements();
2351 MachineMemOperand *MMO = LN->getMemOperand();
2352
2353 unsigned RequiredAlign = (NumBits == 32) ? 4 : 8;
2354 if (MMO->getBaseAlign().value() % RequiredAlign != 0)
2355 return SDValue();
2356
2357 SDValue Chain = LN->getChain();
2358 SDValue BasePtr = LN->getBasePtr();
2359 MachinePointerInfo PtrInfo = MMO->getPointerInfo();
2360
2361 if (NumBits == 32) {
2362 SDValue W32 =
2363 DAG.getLoad(MVT::i32, dl, Chain, BasePtr, PtrInfo, MMO->getBaseAlign());
2364 SDValue Pred = DAG.getNode(ISD::BITCAST, dl, MVT::v32i1, W32);
2365 SDValue Ops[] = {Pred, W32.getValue(1)};
2366 return DAG.getMergeValues(Ops, dl);
2367 }
2368
2369 if (NumBits == 64) {
2370 SDValue W64 =
2371 DAG.getLoad(MVT::i64, dl, Chain, BasePtr, PtrInfo, MMO->getBaseAlign());
2372 SDValue Pred = DAG.getNode(ISD::BITCAST, dl, MVT::v64i1, W64);
2373 SDValue Ops[] = {Pred, W64.getValue(1)};
2374 return DAG.getMergeValues(Ops, dl);
2375 }
2376
2377 if (NumBits == 128) {
2378 SDValue Lo64 =
2379 DAG.getLoad(MVT::i64, dl, Chain, BasePtr, PtrInfo, MMO->getBaseAlign());
2380 Chain = Lo64.getValue(1);
2381
2382 SDValue Offset8 = DAG.getConstant(8, dl, MVT::i32);
2383 SDValue Ptr8 = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr, Offset8);
2384 SDValue Hi64 = DAG.getLoad(MVT::i64, dl, Chain, Ptr8,
2385 PtrInfo.getWithOffset(8), Align(8));
2386
2387 SDValue LoPred = DAG.getNode(ISD::BITCAST, dl, MVT::v64i1, Lo64);
2388 SDValue HiPred = DAG.getNode(ISD::BITCAST, dl, MVT::v64i1, Hi64);
2389 SDValue Pred =
2390 DAG.getNode(ISD::CONCAT_VECTORS, dl, MVT::v128i1, LoPred, HiPred);
2391
2392 SDValue Ops[] = {Pred, Hi64.getValue(1)};
2393 return DAG.getMergeValues(Ops, dl);
2394 }
2395
2396 return SDValue();
2397}
2398
2399SDValue
2400HexagonTargetLowering::LowerHvxExtend(SDValue Op, SelectionDAG &DAG) const {
2401 // Sign- and zero-extends are legal.
2402 assert(Op.getOpcode() == ISD::ANY_EXTEND_VECTOR_INREG);
2403 return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, SDLoc(Op), ty(Op),
2404 Op.getOperand(0));
2405}
2406
2407SDValue
2408HexagonTargetLowering::LowerHvxSelect(SDValue Op, SelectionDAG &DAG) const {
2409 MVT ResTy = ty(Op);
2410 if (ResTy.getVectorElementType() != MVT::i1)
2411 return Op;
2412
2413 const SDLoc &dl(Op);
2414 unsigned HwLen = Subtarget.getVectorLength();
2415 unsigned VecLen = ResTy.getVectorNumElements();
2416 assert(HwLen % VecLen == 0);
2417 unsigned ElemSize = HwLen / VecLen;
2418
2419 MVT VecTy = MVT::getVectorVT(MVT::getIntegerVT(ElemSize * 8), VecLen);
2420 SDValue S =
2421 DAG.getNode(ISD::SELECT, dl, VecTy, Op.getOperand(0),
2422 DAG.getNode(HexagonISD::Q2V, dl, VecTy, Op.getOperand(1)),
2423 DAG.getNode(HexagonISD::Q2V, dl, VecTy, Op.getOperand(2)));
2424 return DAG.getNode(HexagonISD::V2Q, dl, ResTy, S);
2425}
2426
2427SDValue
2428HexagonTargetLowering::LowerHvxShift(SDValue Op, SelectionDAG &DAG) const {
2429 if (SDValue S = getVectorShiftByInt(Op, DAG))
2430 return S;
2431 return Op;
2432}
2433
2434SDValue
2435HexagonTargetLowering::LowerHvxFunnelShift(SDValue Op,
2436 SelectionDAG &DAG) const {
2437 unsigned Opc = Op.getOpcode();
2438 assert(Opc == ISD::FSHL || Opc == ISD::FSHR);
2439
2440 // Make sure the shift amount is within the range of the bitwidth
2441 // of the element type.
2442 SDValue A = Op.getOperand(0);
2443 SDValue B = Op.getOperand(1);
2444 SDValue S = Op.getOperand(2);
2445
2446 MVT InpTy = ty(A);
2447 MVT ElemTy = InpTy.getVectorElementType();
2448
2449 const SDLoc &dl(Op);
2450 unsigned ElemWidth = ElemTy.getSizeInBits();
2451 bool IsLeft = Opc == ISD::FSHL;
2452
2453 // The expansion into regular shifts produces worse code for i8 and for
2454 // right shift of i32 on v65+.
2455 bool UseShifts = ElemTy != MVT::i8;
2456 if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)
2457 UseShifts = false;
2458
2459 if (SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {
2460 // If this is a funnel shift by a scalar, lower it into regular shifts.
2461 SDValue Mask = DAG.getConstant(ElemWidth - 1, dl, MVT::i32);
2462 SDValue ModS =
2463 DAG.getNode(ISD::AND, dl, MVT::i32,
2464 {DAG.getZExtOrTrunc(SplatV, dl, MVT::i32), Mask});
2465 SDValue NegS =
2466 DAG.getNode(ISD::SUB, dl, MVT::i32,
2467 {DAG.getConstant(ElemWidth, dl, MVT::i32), ModS});
2468 SDValue IsZero =
2469 DAG.getSetCC(dl, MVT::i1, ModS, getZero(dl, MVT::i32, DAG), ISD::SETEQ);
2470 // FSHL A, B => A << | B >>n
2471 // FSHR A, B => A <<n | B >>
2472 SDValue Part1 =
2473 DAG.getNode(HexagonISD::VASL, dl, InpTy, {A, IsLeft ? ModS : NegS});
2474 SDValue Part2 =
2475 DAG.getNode(HexagonISD::VLSR, dl, InpTy, {B, IsLeft ? NegS : ModS});
2476 SDValue Or = DAG.getNode(ISD::OR, dl, InpTy, {Part1, Part2});
2477 // If the shift amount was 0, pick A or B, depending on the direction.
2478 // The opposite shift will also be by 0, so the "Or" will be incorrect.
2479 return DAG.getNode(ISD::SELECT, dl, InpTy, {IsZero, (IsLeft ? A : B), Or});
2480 }
2481
2483 InpTy, dl, DAG.getConstant(ElemWidth - 1, dl, ElemTy));
2484
2485 unsigned MOpc = Opc == ISD::FSHL ? HexagonISD::MFSHL : HexagonISD::MFSHR;
2486 return DAG.getNode(MOpc, dl, ty(Op),
2487 {A, B, DAG.getNode(ISD::AND, dl, InpTy, {S, Mask})});
2488}
2489
2490SDValue
2491HexagonTargetLowering::LowerHvxIntrinsic(SDValue Op, SelectionDAG &DAG) const {
2492 const SDLoc &dl(Op);
2493 unsigned IntNo = Op.getConstantOperandVal(0);
2494 SmallVector<SDValue> Ops(Op->ops());
2495
2496 auto Swap = [&](SDValue P) {
2497 return DAG.getMergeValues({P.getValue(1), P.getValue(0)}, dl);
2498 };
2499
2500 switch (IntNo) {
2501 case Intrinsic::hexagon_V6_pred_typecast:
2502 case Intrinsic::hexagon_V6_pred_typecast_128B: {
2503 MVT ResTy = ty(Op), InpTy = ty(Ops[1]);
2504 if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {
2505 if (ResTy == InpTy)
2506 return Ops[1];
2507 return DAG.getNode(HexagonISD::TYPECAST, dl, ResTy, Ops[1]);
2508 }
2509 break;
2510 }
2511 case Intrinsic::hexagon_V6_vmpyss_parts:
2512 case Intrinsic::hexagon_V6_vmpyss_parts_128B:
2513 return Swap(DAG.getNode(HexagonISD::SMUL_LOHI, dl, Op->getVTList(),
2514 {Ops[1], Ops[2]}));
2515 case Intrinsic::hexagon_V6_vmpyuu_parts:
2516 case Intrinsic::hexagon_V6_vmpyuu_parts_128B:
2517 return Swap(DAG.getNode(HexagonISD::UMUL_LOHI, dl, Op->getVTList(),
2518 {Ops[1], Ops[2]}));
2519 case Intrinsic::hexagon_V6_vmpyus_parts:
2520 case Intrinsic::hexagon_V6_vmpyus_parts_128B: {
2521 return Swap(DAG.getNode(HexagonISD::USMUL_LOHI, dl, Op->getVTList(),
2522 {Ops[1], Ops[2]}));
2523 }
2524 } // switch
2525
2526 return Op;
2527}
2528
2529SDValue
2530HexagonTargetLowering::LowerHvxMaskedOp(SDValue Op, SelectionDAG &DAG) const {
2531 const SDLoc &dl(Op);
2532 unsigned HwLen = Subtarget.getVectorLength();
2534 auto *MaskN = cast<MaskedLoadStoreSDNode>(Op.getNode());
2535 SDValue Mask = MaskN->getMask();
2536 SDValue Chain = MaskN->getChain();
2537 SDValue Base = MaskN->getBasePtr();
2538 auto *MemOp = MF.getMachineMemOperand(MaskN->getMemOperand(), 0, HwLen);
2539
2540 unsigned Opc = Op->getOpcode();
2542
2543 if (Opc == ISD::MLOAD) {
2544 MVT ValTy = ty(Op);
2545 SDValue Load = DAG.getLoad(ValTy, dl, Chain, Base, MemOp);
2546 SDValue Thru = cast<MaskedLoadSDNode>(MaskN)->getPassThru();
2547 if (isUndef(Thru))
2548 return Load;
2549 SDValue VSel = DAG.getNode(ISD::VSELECT, dl, ValTy, Mask, Load, Thru);
2550 return DAG.getMergeValues({VSel, Load.getValue(1)}, dl);
2551 }
2552
2553 // MSTORE
2554 // HVX only has aligned masked stores.
2555
2556 // TODO: Fold negations of the mask into the store.
2557 unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;
2558 SDValue Value = cast<MaskedStoreSDNode>(MaskN)->getValue();
2559 SDValue Offset0 = DAG.getTargetConstant(0, dl, ty(Base));
2560
2561 if (MaskN->getAlign().value() % HwLen == 0) {
2562 SDValue Store = getInstr(StoreOpc, dl, MVT::Other,
2563 {Mask, Base, Offset0, Value, Chain}, DAG);
2564 DAG.setNodeMemRefs(cast<MachineSDNode>(Store.getNode()), {MemOp});
2565 return Store;
2566 }
2567
2568 // Unaligned case.
2569 auto StoreAlign = [&](SDValue V, SDValue A) {
2570 SDValue Z = getZero(dl, ty(V), DAG);
2571 // TODO: use funnel shifts?
2572 // vlalign(Vu,Vv,Rt) rotates the pair Vu:Vv left by Rt and takes the
2573 // upper half.
2574 SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {V, Z, A}, DAG);
2575 SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {Z, V, A}, DAG);
2576 return std::make_pair(LoV, HiV);
2577 };
2578
2579 MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);
2580 MVT BoolTy = MVT::getVectorVT(MVT::i1, HwLen);
2581 SDValue MaskV = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, Mask);
2582 VectorPair Tmp = StoreAlign(MaskV, Base);
2583 VectorPair MaskU = {DAG.getNode(HexagonISD::V2Q, dl, BoolTy, Tmp.first),
2584 DAG.getNode(HexagonISD::V2Q, dl, BoolTy, Tmp.second)};
2585 VectorPair ValueU = StoreAlign(Value, Base);
2586
2587 SDValue Offset1 = DAG.getTargetConstant(HwLen, dl, MVT::i32);
2588 SDValue StoreLo =
2589 getInstr(StoreOpc, dl, MVT::Other,
2590 {MaskU.first, Base, Offset0, ValueU.first, Chain}, DAG);
2591 DAG.setNodeMemRefs(cast<MachineSDNode>(StoreLo.getNode()), {MemOp});
2592
2593 // If the store fits within one HwLen-aligned block, the high half's predicate
2594 // is always all-zeros and the vmem(Base+HwLen) can be elided entirely.
2595 // Proof: addr % StoreAlign == 0 and StoreMemSize <= StoreAlign implies
2596 // addr % HwLen <= HwLen - StoreAlign, so addr % HwLen + StoreMemSize
2597 // <= HwLen.
2598 // Without this guard, Hexagon v73+ probes the TLB for vmem(Base+HwLen) even
2599 // when the predicate is all-zeros, causing a TLBMISS if that page is
2600 // unmapped.
2601 uint64_t StoreMemSize = MaskN->getMemoryVT().getStoreSize().getFixedValue();
2602 if (StoreMemSize <= MaskN->getAlign().value())
2603 return StoreLo;
2604
2605 SDValue StoreHi =
2606 getInstr(StoreOpc, dl, MVT::Other,
2607 {MaskU.second, Base, Offset1, ValueU.second, Chain}, DAG);
2608 DAG.setNodeMemRefs(cast<MachineSDNode>(StoreHi.getNode()), {MemOp});
2609 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, {StoreLo, StoreHi});
2610}
2611
2612SDValue HexagonTargetLowering::LowerHvxFpExtend(SDValue Op,
2613 SelectionDAG &DAG) const {
2614 // This conversion only applies to QFloat. IEEE extension from f16 to f32
2615 // is legal (done via a pattern).
2616 assert(Subtarget.useHVXQFloatOps());
2617
2618 assert(Op->getOpcode() == ISD::FP_EXTEND);
2619
2620 MVT VecTy = ty(Op);
2621 MVT ArgTy = ty(Op.getOperand(0));
2622 const SDLoc &dl(Op);
2623
2624 if (ArgTy == MVT::v64bf16) {
2625 MVT HalfTy = typeSplit(VecTy).first;
2626 SDValue BF16Vec = Op.getOperand(0);
2627 SDValue Zeroes =
2628 getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);
2629 // Interleave zero vector with the bf16 vector, with zeroes in the lower
2630 // half of each 32 bit lane, effectively extending the bf16 values to fp32
2631 // values.
2632 SDValue ShuffVec =
2633 getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);
2634 VectorPair VecPair = opSplit(ShuffVec, dl, DAG);
2635 SDValue Result = getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2636 {VecPair.second, VecPair.first,
2637 DAG.getSignedConstant(-4, dl, MVT::i32)},
2638 DAG);
2639 return Result;
2640 }
2641
2642 assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);
2643
2644 SDValue F16Vec = Op.getOperand(0);
2645
2646 APFloat FloatVal = APFloat(1.0f);
2647 bool Ignored;
2649 SDValue Fp16Ones = DAG.getConstantFP(FloatVal, dl, ArgTy);
2650 SDValue VmpyVec =
2651 getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);
2652
2653 MVT HalfTy = typeSplit(VecTy).first;
2654 VectorPair Pair = opSplit(VmpyVec, dl, DAG);
2655 SDValue LoVec =
2656 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);
2657 SDValue HiVec =
2658 getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);
2659
2660 SDValue ShuffVec =
2661 getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,
2662 {HiVec, LoVec, DAG.getSignedConstant(-4, dl, MVT::i32)}, DAG);
2663
2664 return ShuffVec;
2665}
2666
2667SDValue
2668HexagonTargetLowering::LowerHvxFpToInt(SDValue Op, SelectionDAG &DAG) const {
2669 // Catch invalid conversion ops (just in case).
2670 assert(Op.getOpcode() == ISD::FP_TO_SINT ||
2671 Op.getOpcode() == ISD::FP_TO_UINT);
2672
2673 MVT ResTy = ty(Op);
2674 MVT FpTy = ty(Op.getOperand(0)).getVectorElementType();
2675 MVT IntTy = ResTy.getVectorElementType();
2676
2677 if (Subtarget.useHVXIEEEFPOps()) {
2678 // There are only conversions from f16.
2679 if (FpTy == MVT::f16) {
2680 // Other int types aren't legal in HVX, so we shouldn't see them here.
2681 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2682 // Conversions to i8 and i16 are legal.
2683 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2684 return Op;
2685 }
2686 }
2687
2688 if (IntTy.getSizeInBits() != FpTy.getSizeInBits())
2689 return EqualizeFpIntConversion(Op, DAG);
2690
2691 return ExpandHvxFpToInt(Op, DAG);
2692}
2693
2694// For vector type v32i1 uint_to_fp/sint_to_fp to v32f32:
2695// R1 = #1, R2 holds the v32i1 param
2696// V1 = vsplat(R1)
2697// V2 = vsplat(R2)
2698// Q0 = vand(V1,R1)
2699// V0.w=prefixsum(Q0)
2700// V0.w=vsub(V0.w,V1.w)
2701// V2.w = vlsr(V2.w,V0.w)
2702// V2 = vand(V2,V1)
2703// V2.sf = V2.w
2704SDValue HexagonTargetLowering::LowerHvxPred32ToFp(SDValue PredOp,
2705 SelectionDAG &DAG) const {
2706
2707 MVT ResTy = ty(PredOp);
2708 const SDLoc &dl(PredOp);
2709
2710 SDValue Const = DAG.getTargetConstant(0x1, dl, MVT::i32);
2711 SDNode *RegConst = DAG.getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2712 SDNode *SplatConst = DAG.getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2713 SDValue(RegConst, 0));
2714 SDNode *PredTransfer =
2715 DAG.getMachineNode(Hexagon::V6_vandvrt, dl, MVT::v32i1,
2716 SDValue(SplatConst, 0), SDValue(RegConst, 0));
2717 SDNode *PrefixSum = DAG.getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2718 SDValue(PredTransfer, 0));
2719 SDNode *SplatParam = DAG.getMachineNode(
2720 Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2721 DAG.getNode(ISD::BITCAST, dl, MVT::i32, PredOp.getOperand(0)));
2722 SDNode *Vsub =
2723 DAG.getMachineNode(Hexagon::V6_vsubw, dl, MVT::v32i32,
2724 SDValue(PrefixSum, 0), SDValue(SplatConst, 0));
2725 SDNode *IndexShift =
2726 DAG.getMachineNode(Hexagon::V6_vlsrwv, dl, MVT::v32i32,
2727 SDValue(SplatParam, 0), SDValue(Vsub, 0));
2728 SDNode *MaskOff =
2729 DAG.getMachineNode(Hexagon::V6_vand, dl, MVT::v32i32,
2730 SDValue(IndexShift, 0), SDValue(SplatConst, 0));
2731 SDNode *Convert = DAG.getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,
2732 SDValue(MaskOff, 0));
2733 return SDValue(Convert, 0);
2734}
2735
2736// For vector type v64i1 uint_to_fo to v64f16:
2737// i64 R32 = bitcast v64i1 R3:2 (R3:2 holds v64i1)
2738// R3 = subreg_high (R32)
2739// R2 = subreg_low (R32)
2740// R1 = #1
2741// V1 = vsplat(R1)
2742// V2 = vsplat(R2)
2743// V3 = vsplat(R3)
2744// Q0 = vand(V1,R1)
2745// V0.w=prefixsum(Q0)
2746// V0.w=vsub(V0.w,V1.w)
2747// V2.w = vlsr(V2.w,V0.w)
2748// V3.w = vlsr(V3.w,V0.w)
2749// V2 = vand(V2,V1)
2750// V3 = vand(V3,V1)
2751// V2.h = vpacke(V3.w,V2.w)
2752// V2.hf = V2.h
2753SDValue HexagonTargetLowering::LowerHvxPred64ToFp(SDValue PredOp,
2754 SelectionDAG &DAG) const {
2755
2756 MVT ResTy = ty(PredOp);
2757 const SDLoc &dl(PredOp);
2758
2759 SDValue Inp = DAG.getNode(ISD::BITCAST, dl, MVT::i64, PredOp.getOperand(0));
2760 // Get the hi and lo regs
2761 SDValue HiReg =
2762 DAG.getTargetExtractSubreg(Hexagon::isub_hi, dl, MVT::i32, Inp);
2763 SDValue LoReg =
2764 DAG.getTargetExtractSubreg(Hexagon::isub_lo, dl, MVT::i32, Inp);
2765 // Get constant #1 and splat into vector V1
2766 SDValue Const = DAG.getTargetConstant(0x1, dl, MVT::i32);
2767 SDNode *RegConst = DAG.getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);
2768 SDNode *SplatConst = DAG.getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2769 SDValue(RegConst, 0));
2770 // Splat the hi and lo args
2771 SDNode *SplatHi =
2772 DAG.getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2773 DAG.getNode(ISD::BITCAST, dl, MVT::i32, HiReg));
2774 SDNode *SplatLo =
2775 DAG.getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,
2776 DAG.getNode(ISD::BITCAST, dl, MVT::i32, LoReg));
2777 // vand between splatted const and const
2778 SDNode *PredTransfer =
2779 DAG.getMachineNode(Hexagon::V6_vandvrt, dl, MVT::v32i1,
2780 SDValue(SplatConst, 0), SDValue(RegConst, 0));
2781 // Get the prefixsum
2782 SDNode *PrefixSum = DAG.getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,
2783 SDValue(PredTransfer, 0));
2784 // Get the vsub
2785 SDNode *Vsub =
2786 DAG.getMachineNode(Hexagon::V6_vsubw, dl, MVT::v32i32,
2787 SDValue(PrefixSum, 0), SDValue(SplatConst, 0));
2788 // Get vlsr for hi and lo
2789 SDNode *IndexShift_hi =
2790 DAG.getMachineNode(Hexagon::V6_vlsrwv, dl, MVT::v32i32,
2791 SDValue(SplatHi, 0), SDValue(Vsub, 0));
2792 SDNode *IndexShift_lo =
2793 DAG.getMachineNode(Hexagon::V6_vlsrwv, dl, MVT::v32i32,
2794 SDValue(SplatLo, 0), SDValue(Vsub, 0));
2795 // Get vand of hi and lo
2796 SDNode *MaskOff_hi =
2797 DAG.getMachineNode(Hexagon::V6_vand, dl, MVT::v32i32,
2798 SDValue(IndexShift_hi, 0), SDValue(SplatConst, 0));
2799 SDNode *MaskOff_lo =
2800 DAG.getMachineNode(Hexagon::V6_vand, dl, MVT::v32i32,
2801 SDValue(IndexShift_lo, 0), SDValue(SplatConst, 0));
2802 // Pack them
2803 SDNode *Pack =
2804 DAG.getMachineNode(Hexagon::V6_vpackeh, dl, MVT::v64i16,
2805 SDValue(MaskOff_hi, 0), SDValue(MaskOff_lo, 0));
2806 SDNode *Convert =
2807 DAG.getMachineNode(Hexagon::V6_vconv_hf_h, dl, ResTy, SDValue(Pack, 0));
2808 return SDValue(Convert, 0);
2809}
2810
2811SDValue
2812HexagonTargetLowering::LowerHvxIntToFp(SDValue Op, SelectionDAG &DAG) const {
2813 // Catch invalid conversion ops (just in case).
2814 assert(Op.getOpcode() == ISD::SINT_TO_FP ||
2815 Op.getOpcode() == ISD::UINT_TO_FP);
2816
2817 MVT ResTy = ty(Op);
2818 MVT IntTy = ty(Op.getOperand(0)).getVectorElementType();
2819 MVT FpTy = ResTy.getVectorElementType();
2820
2821 if (Op.getOpcode() == ISD::UINT_TO_FP || Op.getOpcode() == ISD::SINT_TO_FP) {
2822 if (ResTy == MVT::v32f32 && ty(Op.getOperand(0)) == MVT::v32i1)
2823 return LowerHvxPred32ToFp(Op, DAG);
2824 if (ResTy == MVT::v64f16 && ty(Op.getOperand(0)) == MVT::v64i1)
2825 return LowerHvxPred64ToFp(Op, DAG);
2826 }
2827
2828 if (Subtarget.useHVXIEEEFPOps()) {
2829 // There are only conversions to f16.
2830 if (FpTy == MVT::f16) {
2831 // Other int types aren't legal in HVX, so we shouldn't see them here.
2832 assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);
2833 // i8, i16 -> f16 is legal.
2834 if (IntTy == MVT::i8 || IntTy == MVT::i16)
2835 return Op;
2836 }
2837 }
2838
2839 if (IntTy.getSizeInBits() != FpTy.getSizeInBits())
2840 return EqualizeFpIntConversion(Op, DAG);
2841
2842 return ExpandHvxIntToFp(Op, DAG);
2843}
2844
2845HexagonTargetLowering::TypePair
2846HexagonTargetLowering::typeExtendToWider(MVT Ty0, MVT Ty1) const {
2847 // Compare the widths of elements of the two types, and extend the narrower
2848 // type to match the with of the wider type. For vector types, apply this
2849 // to the element type.
2850 assert(Ty0.isVector() == Ty1.isVector());
2851
2852 MVT ElemTy0 = Ty0.getScalarType();
2853 MVT ElemTy1 = Ty1.getScalarType();
2854
2855 unsigned Width0 = ElemTy0.getSizeInBits();
2856 unsigned Width1 = ElemTy1.getSizeInBits();
2857 unsigned MaxWidth = std::max(Width0, Width1);
2858
2859 auto getScalarWithWidth = [](MVT ScalarTy, unsigned Width) {
2860 if (ScalarTy.isInteger())
2861 return MVT::getIntegerVT(Width);
2862 assert(ScalarTy.isFloatingPoint());
2863 return MVT::getFloatingPointVT(Width);
2864 };
2865
2866 MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);
2867 MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);
2868
2869 if (!Ty0.isVector()) {
2870 // Both types are scalars.
2871 return {WideETy0, WideETy1};
2872 }
2873
2874 // Vector types.
2875 unsigned NumElem = Ty0.getVectorNumElements();
2876 assert(NumElem == Ty1.getVectorNumElements());
2877
2878 return {MVT::getVectorVT(WideETy0, NumElem),
2879 MVT::getVectorVT(WideETy1, NumElem)};
2880}
2881
2882HexagonTargetLowering::TypePair
2883HexagonTargetLowering::typeWidenToWider(MVT Ty0, MVT Ty1) const {
2884 // Compare the numbers of elements of two vector types, and widen the
2885 // narrower one to match the number of elements in the wider one.
2886 assert(Ty0.isVector() && Ty1.isVector());
2887
2888 unsigned Len0 = Ty0.getVectorNumElements();
2889 unsigned Len1 = Ty1.getVectorNumElements();
2890 if (Len0 == Len1)
2891 return {Ty0, Ty1};
2892
2893 unsigned MaxLen = std::max(Len0, Len1);
2894 return {MVT::getVectorVT(Ty0.getVectorElementType(), MaxLen),
2895 MVT::getVectorVT(Ty1.getVectorElementType(), MaxLen)};
2896}
2897
2898MVT
2899HexagonTargetLowering::typeLegalize(MVT Ty, SelectionDAG &DAG) const {
2900 EVT LegalTy = getTypeToTransformTo(*DAG.getContext(), Ty);
2901 assert(LegalTy.isSimple());
2902 return LegalTy.getSimpleVT();
2903}
2904
2905MVT
2906HexagonTargetLowering::typeWidenToHvx(MVT Ty) const {
2907 unsigned HwWidth = 8 * Subtarget.getVectorLength();
2908 assert(Ty.getSizeInBits() <= HwWidth);
2909 if (Ty.getSizeInBits() == HwWidth)
2910 return Ty;
2911
2912 MVT ElemTy = Ty.getScalarType();
2913 return MVT::getVectorVT(ElemTy, HwWidth / ElemTy.getSizeInBits());
2914}
2915
2916HexagonTargetLowering::VectorPair
2917HexagonTargetLowering::emitHvxAddWithOverflow(SDValue A, SDValue B,
2918 const SDLoc &dl, bool Signed, SelectionDAG &DAG) const {
2919 // Compute A+B, return {A+B, O}, where O = vector predicate indicating
2920 // whether an overflow has occurred.
2921 MVT ResTy = ty(A);
2922 assert(ResTy == ty(B));
2923 MVT PredTy = MVT::getVectorVT(MVT::i1, ResTy.getVectorNumElements());
2924
2925 if (!Signed) {
2926 // V62+ has V6_vaddcarry, but it requires input predicate, so it doesn't
2927 // save any instructions.
2928 SDValue Add = DAG.getNode(ISD::ADD, dl, ResTy, {A, B});
2929 SDValue Ovf = DAG.getSetCC(dl, PredTy, Add, A, ISD::SETULT);
2930 return {Add, Ovf};
2931 }
2932
2933 // Signed overflow has happened, if:
2934 // (A, B have the same sign) and (A+B has a different sign from either)
2935 // i.e. (~A xor B) & ((A+B) xor B), then check the sign bit
2936 SDValue Add = DAG.getNode(ISD::ADD, dl, ResTy, {A, B});
2937 SDValue NotA =
2938 DAG.getNode(ISD::XOR, dl, ResTy, {A, DAG.getAllOnesConstant(dl, ResTy)});
2939 SDValue Xor0 = DAG.getNode(ISD::XOR, dl, ResTy, {NotA, B});
2940 SDValue Xor1 = DAG.getNode(ISD::XOR, dl, ResTy, {Add, B});
2941 SDValue And = DAG.getNode(ISD::AND, dl, ResTy, {Xor0, Xor1});
2942 SDValue MSB =
2943 DAG.getSetCC(dl, PredTy, And, getZero(dl, ResTy, DAG), ISD::SETLT);
2944 return {Add, MSB};
2945}
2946
2947HexagonTargetLowering::VectorPair
2948HexagonTargetLowering::emitHvxShiftRightRnd(SDValue Val, unsigned Amt,
2949 bool Signed, SelectionDAG &DAG) const {
2950 // Shift Val right by Amt bits, round the result to the nearest integer,
2951 // tie-break by rounding halves to even integer.
2952
2953 const SDLoc &dl(Val);
2954 MVT ValTy = ty(Val);
2955
2956 // This should also work for signed integers.
2957 //
2958 // uint tmp0 = inp + ((1 << (Amt-1)) - 1);
2959 // bool ovf = (inp > tmp0);
2960 // uint rup = inp & (1 << (Amt+1));
2961 //
2962 // uint tmp1 = inp >> (Amt-1); // tmp1 == tmp2 iff
2963 // uint tmp2 = tmp0 >> (Amt-1); // the Amt-1 lower bits were all 0
2964 // uint tmp3 = tmp2 + rup;
2965 // uint frac = (tmp1 != tmp2) ? tmp2 >> 1 : tmp3 >> 1;
2966 unsigned ElemWidth = ValTy.getVectorElementType().getSizeInBits();
2967 MVT ElemTy = MVT::getIntegerVT(ElemWidth);
2968 MVT IntTy = tyVector(ValTy, ElemTy);
2969 MVT PredTy = MVT::getVectorVT(MVT::i1, IntTy.getVectorNumElements());
2970 unsigned ShRight = Signed ? ISD::SRA : ISD::SRL;
2971
2972 SDValue Inp = DAG.getBitcast(IntTy, Val);
2973 SDValue LowBits = DAG.getConstant((1ull << (Amt - 1)) - 1, dl, IntTy);
2974
2975 SDValue AmtP1 = DAG.getConstant(1ull << Amt, dl, IntTy);
2976 SDValue And = DAG.getNode(ISD::AND, dl, IntTy, {Inp, AmtP1});
2977 SDValue Zero = getZero(dl, IntTy, DAG);
2978 SDValue Bit = DAG.getSetCC(dl, PredTy, And, Zero, ISD::SETNE);
2979 SDValue Rup = DAG.getZExtOrTrunc(Bit, dl, IntTy);
2980 auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl, Signed, DAG);
2981
2982 SDValue AmtM1 = DAG.getConstant(Amt - 1, dl, IntTy);
2983 SDValue Tmp1 = DAG.getNode(ShRight, dl, IntTy, Inp, AmtM1);
2984 SDValue Tmp2 = DAG.getNode(ShRight, dl, IntTy, Tmp0, AmtM1);
2985 SDValue Tmp3 = DAG.getNode(ISD::ADD, dl, IntTy, Tmp2, Rup);
2986
2987 SDValue Eq = DAG.getSetCC(dl, PredTy, Tmp1, Tmp2, ISD::SETEQ);
2988 SDValue One = DAG.getConstant(1, dl, IntTy);
2989 SDValue Tmp4 = DAG.getNode(ShRight, dl, IntTy, {Tmp2, One});
2990 SDValue Tmp5 = DAG.getNode(ShRight, dl, IntTy, {Tmp3, One});
2991 SDValue Mux = DAG.getNode(ISD::VSELECT, dl, IntTy, {Eq, Tmp5, Tmp4});
2992 return {Mux, Ovf};
2993}
2994
2995SDValue
2996HexagonTargetLowering::emitHvxMulHsV60(SDValue A, SDValue B, const SDLoc &dl,
2997 SelectionDAG &DAG) const {
2998 MVT VecTy = ty(A);
2999 MVT PairTy = typeJoin({VecTy, VecTy});
3000 assert(VecTy.getVectorElementType() == MVT::i32);
3001
3002 SDValue S16 = DAG.getConstant(16, dl, MVT::i32);
3003
3004 // mulhs(A,B) =
3005 // = [(Hi(A)*2^16 + Lo(A)) *s (Hi(B)*2^16 + Lo(B))] >> 32
3006 // = [Hi(A)*2^16 *s Hi(B)*2^16 + Hi(A) *su Lo(B)*2^16
3007 // + Lo(A) *us (Hi(B)*2^16 + Lo(B))] >> 32
3008 // = [Hi(A) *s Hi(B)*2^32 + Hi(A) *su Lo(B)*2^16 + Lo(A) *us B] >> 32
3009 // The low half of Lo(A)*Lo(B) will be discarded (it's not added to
3010 // anything, so it cannot produce any carry over to higher bits),
3011 // so everything in [] can be shifted by 16 without loss of precision.
3012 // = [Hi(A) *s Hi(B)*2^16 + Hi(A)*su Lo(B) + Lo(A)*B >> 16] >> 16
3013 // = [Hi(A) *s Hi(B)*2^16 + Hi(A)*su Lo(B) + V6_vmpyewuh(A,B)] >> 16
3014 // The final additions need to make sure to properly maintain any carry-
3015 // out bits.
3016 //
3017 // Hi(B) Lo(B)
3018 // Hi(A) Lo(A)
3019 // --------------
3020 // Lo(B)*Lo(A) | T0 = V6_vmpyewuh(B,A) does this,
3021 // Hi(B)*Lo(A) | + dropping the low 16 bits
3022 // Hi(A)*Lo(B) | T2
3023 // Hi(B)*Hi(A)
3024
3025 SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {B, A}, DAG);
3026 // T1 = get Hi(A) into low halves.
3027 SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {A, S16}, DAG);
3028 // P0 = interleaved T1.h*B.uh (full precision product)
3029 SDValue P0 = getInstr(Hexagon::V6_vmpyhus, dl, PairTy, {T1, B}, DAG);
3030 // T2 = T1.even(h) * B.even(uh), i.e. Hi(A)*Lo(B)
3031 SDValue T2 = LoHalf(P0, DAG);
3032 // We need to add T0+T2, recording the carry-out, which will be 1<<16
3033 // added to the final sum.
3034 // P1 = interleaved even/odd 32-bit (unsigned) sums of 16-bit halves
3035 SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl, PairTy, {T0, T2}, DAG);
3036 // P2 = interleaved even/odd 32-bit (signed) sums of 16-bit halves
3037 SDValue P2 = getInstr(Hexagon::V6_vaddhw, dl, PairTy, {T0, T2}, DAG);
3038 // T3 = full-precision(T0+T2) >> 16
3039 // The low halves are added-unsigned, the high ones are added-signed.
3040 SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3041 {HiHalf(P2, DAG), LoHalf(P1, DAG), S16}, DAG);
3042 SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {B, S16}, DAG);
3043 // P3 = interleaved Hi(B)*Hi(A) (full precision),
3044 // which is now Lo(T1)*Lo(T4), so we want to keep the even product.
3045 SDValue P3 = getInstr(Hexagon::V6_vmpyhv, dl, PairTy, {T1, T4}, DAG);
3046 SDValue T5 = LoHalf(P3, DAG);
3047 // Add:
3048 SDValue T6 = DAG.getNode(ISD::ADD, dl, VecTy, {T3, T5});
3049 return T6;
3050}
3051
3052SDValue
3053HexagonTargetLowering::emitHvxMulLoHiV60(SDValue A, bool SignedA, SDValue B,
3054 bool SignedB, const SDLoc &dl,
3055 SelectionDAG &DAG) const {
3056 MVT VecTy = ty(A);
3057 MVT PairTy = typeJoin({VecTy, VecTy});
3058 assert(VecTy.getVectorElementType() == MVT::i32);
3059
3060 SDValue S16 = DAG.getConstant(16, dl, MVT::i32);
3061
3062 if (SignedA && !SignedB) {
3063 // Make A:unsigned, B:signed.
3064 std::swap(A, B);
3065 std::swap(SignedA, SignedB);
3066 }
3067
3068 // Do halfword-wise multiplications for unsigned*unsigned product, then
3069 // add corrections for signed and unsigned*signed.
3070
3071 SDValue Lo, Hi;
3072
3073 // P0:lo = (uu) products of low halves of A and B,
3074 // P0:hi = (uu) products of high halves.
3075 SDValue P0 = getInstr(Hexagon::V6_vmpyuhv, dl, PairTy, {A, B}, DAG);
3076
3077 // Swap low/high halves in B
3078 SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,
3079 {DAG.getConstant(0x02020202, dl, MVT::i32)}, DAG);
3080 SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {B, T0}, DAG);
3081 // P1 = products of even/odd halfwords.
3082 // P1:lo = (uu) products of even(A.uh) * odd(B.uh)
3083 // P1:hi = (uu) products of odd(A.uh) * even(B.uh)
3084 SDValue P1 = getInstr(Hexagon::V6_vmpyuhv, dl, PairTy, {A, T1}, DAG);
3085
3086 // P2:lo = low halves of P1:lo + P1:hi,
3087 // P2:hi = high halves of P1:lo + P1:hi.
3088 SDValue P2 = getInstr(Hexagon::V6_vadduhw, dl, PairTy,
3089 {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);
3090 // Still need to add the high halves of P0:lo to P2:lo
3091 SDValue T2 =
3092 getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG), S16}, DAG);
3093 SDValue T3 = DAG.getNode(ISD::ADD, dl, VecTy, {LoHalf(P2, DAG), T2});
3094
3095 // The high halves of T3 will contribute to the HI part of LOHI.
3096 SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,
3097 {HiHalf(P2, DAG), T3, S16}, DAG);
3098
3099 // The low halves of P2 need to be added to high halves of the LO part.
3100 Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,
3101 {LoHalf(P0, DAG), LoHalf(P2, DAG), S16}, DAG);
3102 Hi = DAG.getNode(ISD::ADD, dl, VecTy, {HiHalf(P0, DAG), T4});
3103
3104 if (SignedA) {
3105 assert(SignedB && "Signed A and unsigned B should have been inverted");
3106
3107 MVT PredTy = MVT::getVectorVT(MVT::i1, VecTy.getVectorNumElements());
3108 SDValue Zero = getZero(dl, VecTy, DAG);
3109 SDValue Q0 = DAG.getSetCC(dl, PredTy, A, Zero, ISD::SETLT);
3110 SDValue Q1 = DAG.getSetCC(dl, PredTy, B, Zero, ISD::SETLT);
3111 SDValue X0 = DAG.getNode(ISD::VSELECT, dl, VecTy, {Q0, B, Zero});
3112 SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0, A}, DAG);
3113 Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {Hi, X1}, DAG);
3114 } else if (SignedB) {
3115 // Same correction as for mulhus:
3116 // mulhus(A.uw,B.w) = mulhu(A.uw,B.uw) - (A.w if B < 0)
3117 MVT PredTy = MVT::getVectorVT(MVT::i1, VecTy.getVectorNumElements());
3118 SDValue Zero = getZero(dl, VecTy, DAG);
3119 SDValue Q1 = DAG.getSetCC(dl, PredTy, B, Zero, ISD::SETLT);
3120 Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1, Hi, A}, DAG);
3121 } else {
3122 assert(!SignedA && !SignedB);
3123 }
3124
3125 return DAG.getMergeValues({Lo, Hi}, dl);
3126}
3127
3128SDValue
3129HexagonTargetLowering::emitHvxMulLoHiV62(SDValue A, bool SignedA,
3130 SDValue B, bool SignedB,
3131 const SDLoc &dl,
3132 SelectionDAG &DAG) const {
3133 MVT VecTy = ty(A);
3134 MVT PairTy = typeJoin({VecTy, VecTy});
3135 assert(VecTy.getVectorElementType() == MVT::i32);
3136
3137 if (SignedA && !SignedB) {
3138 // Make A:unsigned, B:signed.
3139 std::swap(A, B);
3140 std::swap(SignedA, SignedB);
3141 }
3142
3143 // Do S*S first, then make corrections for U*S or U*U if needed.
3144 SDValue P0 = getInstr(Hexagon::V6_vmpyewuh_64, dl, PairTy, {A, B}, DAG);
3145 SDValue P1 =
3146 getInstr(Hexagon::V6_vmpyowh_64_acc, dl, PairTy, {P0, A, B}, DAG);
3147 SDValue Lo = LoHalf(P1, DAG);
3148 SDValue Hi = HiHalf(P1, DAG);
3149
3150 if (!SignedB) {
3151 assert(!SignedA && "Signed A and unsigned B should have been inverted");
3152 SDValue Zero = getZero(dl, VecTy, DAG);
3153 MVT PredTy = MVT::getVectorVT(MVT::i1, VecTy.getVectorNumElements());
3154
3155 // Mulhu(X, Y) = Mulhs(X, Y) + (X, if Y < 0) + (Y, if X < 0).
3156 // def: Pat<(VecI32 (mulhu HVI32:$A, HVI32:$B)),
3157 // (V6_vaddw (HiHalf (Muls64O $A, $B)),
3158 // (V6_vaddwq (V6_vgtw (V6_vd0), $B),
3159 // (V6_vandvqv (V6_vgtw (V6_vd0), $A), $B),
3160 // $A))>;
3161 SDValue Q0 = DAG.getSetCC(dl, PredTy, A, Zero, ISD::SETLT);
3162 SDValue Q1 = DAG.getSetCC(dl, PredTy, B, Zero, ISD::SETLT);
3163 SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0, B}, DAG);
3164 SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0, A}, DAG);
3165 Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {Hi, T1}, DAG);
3166 } else if (!SignedA) {
3167 SDValue Zero = getZero(dl, VecTy, DAG);
3168 MVT PredTy = MVT::getVectorVT(MVT::i1, VecTy.getVectorNumElements());
3169
3170 // Mulhus(unsigned X, signed Y) = Mulhs(X, Y) + (Y, if X < 0).
3171 // def: Pat<(VecI32 (HexagonMULHUS HVI32:$A, HVI32:$B)),
3172 // (V6_vaddwq (V6_vgtw (V6_vd0), $A),
3173 // (HiHalf (Muls64O $A, $B)),
3174 // $B)>;
3175 SDValue Q0 = DAG.getSetCC(dl, PredTy, A, Zero, ISD::SETLT);
3176 Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0, Hi, B}, DAG);
3177 }
3178
3179 return DAG.getMergeValues({Lo, Hi}, dl);
3180}
3181
3182SDValue
3183HexagonTargetLowering::EqualizeFpIntConversion(SDValue Op, SelectionDAG &DAG)
3184 const {
3185 // Rewrite conversion between integer and floating-point in such a way that
3186 // the integer type is extended/narrowed to match the bitwidth of the
3187 // floating-point type, combined with additional integer-integer extensions
3188 // or narrowings to match the original input/result types.
3189 // E.g. f32 -> i8 ==> f32 -> i32 -> i8
3190 //
3191 // The input/result types are not required to be legal, but if they are
3192 // legal, this function should not introduce illegal types.
3193
3194 unsigned Opc = Op.getOpcode();
3197
3198 SDValue Inp = Op.getOperand(0);
3199 MVT InpTy = ty(Inp);
3200 MVT ResTy = ty(Op);
3201
3202 if (InpTy == ResTy)
3203 return Op;
3204
3205 const SDLoc &dl(Op);
3207
3208 auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);
3209 SDValue WInp = resizeToWidth(Inp, WInpTy, Signed, dl, DAG);
3210 SDValue Conv = DAG.getNode(Opc, dl, WResTy, WInp);
3211 SDValue Res = resizeToWidth(Conv, ResTy, Signed, dl, DAG);
3212 return Res;
3213}
3214
3215SDValue
3216HexagonTargetLowering::ExpandHvxFpToInt(SDValue Op, SelectionDAG &DAG) const {
3217 unsigned Opc = Op.getOpcode();
3219
3220 const SDLoc &dl(Op);
3221 SDValue Op0 = Op.getOperand(0);
3222 MVT InpTy = ty(Op0);
3223 MVT ResTy = ty(Op);
3224 assert(InpTy.changeTypeToInteger() == ResTy);
3225
3226 // At this point this is an experiment under a flag.
3227 // In arch before V81 the rounding mode is towards nearest value.
3228 // The C/C++ standard requires rounding towards zero:
3229 // C (C99 and later): ISO/IEC 9899:2018 (C18), section 6.3.1.4 — "When a
3230 // finite value of real floating type is converted to an integer type, the
3231 // fractional part is discarded (i.e., the value is truncated toward zero)."
3232 // C++: ISO/IEC 14882:2020 (C++20), section 7.3.7 — "A prvalue of a
3233 // floating-point type can be converted to a prvalue of an integer type. The
3234 // conversion truncates; that is, the fractional part is discarded."
3235 if (InpTy == MVT::v64f16) {
3236 if (Subtarget.useHVXV81Ops()) {
3237 // This is c/c++ compliant
3238 SDValue ConvVec =
3239 getInstr(Hexagon::V6_vconv_h_hf_rnd, dl, ResTy, {Op0}, DAG);
3240 return ConvVec;
3241 } else if (EnableFpFastConvert) {
3242 // Vd32.h=Vu32.hf same as Q6_Vh_equals_Vhf
3243 SDValue ConvVec = getInstr(Hexagon::V6_vconv_h_hf, dl, ResTy, {Op0}, DAG);
3244 return ConvVec;
3245 }
3246 } else if (EnableFpFastConvert && InpTy == MVT::v32f32) {
3247 // Vd32.w=Vu32.sf same as Q6_Vw_equals_Vsf
3248 SDValue ConvVec = getInstr(Hexagon::V6_vconv_w_sf, dl, ResTy, {Op0}, DAG);
3249 return ConvVec;
3250 }
3251
3252 // int32_t conv_f32_to_i32(uint32_t inp) {
3253 // // s | exp8 | frac23
3254 //
3255 // int neg = (int32_t)inp < 0;
3256 //
3257 // // "expm1" is the actual exponent minus 1: instead of "bias", subtract
3258 // // "bias+1". When the encoded exp is "all-1" (i.e. inf/nan), this will
3259 // // produce a large positive "expm1", which will result in max u/int.
3260 // // In all IEEE formats, bias is the largest positive number that can be
3261 // // represented in bias-width bits (i.e. 011..1).
3262 // int32_t expm1 = (inp << 1) - 0x80000000;
3263 // expm1 >>= 24;
3264 //
3265 // // Always insert the "implicit 1". Subnormal numbers will become 0
3266 // // regardless.
3267 // uint32_t frac = (inp << 8) | 0x80000000;
3268 //
3269 // // "frac" is the fraction part represented as Q1.31. If it was
3270 // // interpreted as uint32_t, it would be the fraction part multiplied
3271 // // by 2^31.
3272 //
3273 // // Calculate the amount of right shift, since shifting further to the
3274 // // left would lose significant bits. Limit it to 32, because we want
3275 // // shifts by 32+ to produce 0, whereas V6_vlsrwv treats the shift
3276 // // amount as a 6-bit signed value (so 33 is same as -31, i.e. shift
3277 // // left by 31). "rsh" can be negative.
3278 // int32_t rsh = min(31 - (expm1 + 1), 32);
3279 //
3280 // frac >>= rsh; // rsh == 32 will produce 0
3281 //
3282 // // Everything up to this point is the same for conversion to signed
3283 // // unsigned integer.
3284 //
3285 // if (neg) // Only for signed int
3286 // frac = -frac; //
3287 // if (rsh <= 0 && neg) // bound = neg ? 0x80000000 : 0x7fffffff
3288 // frac = 0x80000000; // frac = rsh <= 0 ? bound : frac
3289 // if (rsh <= 0 && !neg) //
3290 // frac = 0x7fffffff; //
3291 //
3292 // if (neg) // Only for unsigned int
3293 // frac = 0; //
3294 // if (rsh < 0 && !neg) // frac = rsh < 0 ? 0x7fffffff : frac;
3295 // frac = 0x7fffffff; // frac = neg ? 0 : frac;
3296 //
3297 // return frac;
3298 // }
3299
3300 MVT PredTy = MVT::getVectorVT(MVT::i1, ResTy.getVectorElementCount());
3301
3302 // Zero = V6_vd0();
3303 // Neg = V6_vgtw(Zero, Inp);
3304 // One = V6_lvsplatw(1);
3305 // M80 = V6_lvsplatw(0x80000000);
3306 // Exp00 = V6_vaslwv(Inp, One);
3307 // Exp01 = V6_vsubw(Exp00, M80);
3308 // ExpM1 = V6_vasrw(Exp01, 24);
3309 // Frc00 = V6_vaslw(Inp, 8);
3310 // Frc01 = V6_vor(Frc00, M80);
3311 // Rsh00 = V6_vsubw(V6_lvsplatw(30), ExpM1);
3312 // Rsh01 = V6_vminw(Rsh00, V6_lvsplatw(32));
3313 // Frc02 = V6_vlsrwv(Frc01, Rsh01);
3314
3315 // if signed int:
3316 // Bnd = V6_vmux(Neg, M80, V6_lvsplatw(0x7fffffff))
3317 // Pos = V6_vgtw(Rsh01, Zero);
3318 // Frc13 = V6_vsubw(Zero, Frc02);
3319 // Frc14 = V6_vmux(Neg, Frc13, Frc02);
3320 // Int = V6_vmux(Pos, Frc14, Bnd);
3321 //
3322 // if unsigned int:
3323 // Rsn = V6_vgtw(Zero, Rsh01)
3324 // Frc23 = V6_vmux(Rsn, V6_lvsplatw(0x7fffffff), Frc02)
3325 // Int = V6_vmux(Neg, Zero, Frc23)
3326
3327 auto [ExpWidth, ExpBias, FracWidth] = getIEEEProperties(InpTy);
3328 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3329 assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));
3330
3331 SDValue Inp = DAG.getBitcast(ResTy, Op0);
3332 SDValue Zero = getZero(dl, ResTy, DAG);
3333 SDValue Neg = DAG.getSetCC(dl, PredTy, Inp, Zero, ISD::SETLT);
3334 SDValue M80 = DAG.getConstant(1ull << (ElemWidth - 1), dl, ResTy);
3335 SDValue M7F = DAG.getConstant((1ull << (ElemWidth - 1)) - 1, dl, ResTy);
3336 SDValue One = DAG.getConstant(1, dl, ResTy);
3337 SDValue Exp00 = DAG.getNode(ISD::SHL, dl, ResTy, {Inp, One});
3338 SDValue Exp01 = DAG.getNode(ISD::SUB, dl, ResTy, {Exp00, M80});
3339 SDValue MNE = DAG.getConstant(ElemWidth - ExpWidth, dl, ResTy);
3340 SDValue ExpM1 = DAG.getNode(ISD::SRA, dl, ResTy, {Exp01, MNE});
3341
3342 SDValue ExpW = DAG.getConstant(ExpWidth, dl, ResTy);
3343 SDValue Frc00 = DAG.getNode(ISD::SHL, dl, ResTy, {Inp, ExpW});
3344 SDValue Frc01 = DAG.getNode(ISD::OR, dl, ResTy, {Frc00, M80});
3345
3346 SDValue MN2 = DAG.getConstant(ElemWidth - 2, dl, ResTy);
3347 SDValue Rsh00 = DAG.getNode(ISD::SUB, dl, ResTy, {MN2, ExpM1});
3348 SDValue MW = DAG.getConstant(ElemWidth, dl, ResTy);
3349 SDValue Rsh01 = DAG.getNode(ISD::SMIN, dl, ResTy, {Rsh00, MW});
3350 SDValue Frc02 = DAG.getNode(ISD::SRL, dl, ResTy, {Frc01, Rsh01});
3351
3352 SDValue Int;
3353
3354 if (Opc == ISD::FP_TO_SINT) {
3355 SDValue Bnd = DAG.getNode(ISD::VSELECT, dl, ResTy, {Neg, M80, M7F});
3356 SDValue Pos = DAG.getSetCC(dl, PredTy, Rsh01, Zero, ISD::SETGT);
3357 SDValue Frc13 = DAG.getNode(ISD::SUB, dl, ResTy, {Zero, Frc02});
3358 SDValue Frc14 = DAG.getNode(ISD::VSELECT, dl, ResTy, {Neg, Frc13, Frc02});
3359 Int = DAG.getNode(ISD::VSELECT, dl, ResTy, {Pos, Frc14, Bnd});
3360 } else {
3362 SDValue Rsn = DAG.getSetCC(dl, PredTy, Rsh01, Zero, ISD::SETLT);
3363 SDValue Frc23 = DAG.getNode(ISD::VSELECT, dl, ResTy, Rsn, M7F, Frc02);
3364 Int = DAG.getNode(ISD::VSELECT, dl, ResTy, Neg, Zero, Frc23);
3365 }
3366
3367 return Int;
3368}
3369
3370SDValue
3371HexagonTargetLowering::ExpandHvxIntToFp(SDValue Op, SelectionDAG &DAG) const {
3372 unsigned Opc = Op.getOpcode();
3374
3375 const SDLoc &dl(Op);
3376 SDValue Op0 = Op.getOperand(0);
3377 MVT InpTy = ty(Op0);
3378 MVT ResTy = ty(Op);
3379 assert(ResTy.changeTypeToInteger() == InpTy);
3380
3381 // uint32_t vnoc1_rnd(int32_t w) {
3382 // int32_t iszero = w == 0;
3383 // int32_t isneg = w < 0;
3384 // uint32_t u = __builtin_HEXAGON_A2_abs(w);
3385 //
3386 // uint32_t norm_left = __builtin_HEXAGON_S2_cl0(u) + 1;
3387 // uint32_t frac0 = (uint64_t)u << norm_left;
3388 //
3389 // // Rounding:
3390 // uint32_t frac1 = frac0 + ((1 << 8) - 1);
3391 // uint32_t renorm = (frac0 > frac1);
3392 // uint32_t rup = (int)(frac0 << 22) < 0;
3393 //
3394 // uint32_t frac2 = frac0 >> 8;
3395 // uint32_t frac3 = frac1 >> 8;
3396 // uint32_t frac = (frac2 != frac3) ? frac3 >> 1 : (frac3 + rup) >> 1;
3397 //
3398 // int32_t exp = 32 - norm_left + renorm + 127;
3399 // exp <<= 23;
3400 //
3401 // uint32_t sign = 0x80000000 * isneg;
3402 // uint32_t f = sign | exp | frac;
3403 // return iszero ? 0 : f;
3404 // }
3405
3406 MVT PredTy = MVT::getVectorVT(MVT::i1, InpTy.getVectorElementCount());
3407 bool Signed = Opc == ISD::SINT_TO_FP;
3408
3409 auto [ExpWidth, ExpBias, FracWidth] = getIEEEProperties(ResTy);
3410 unsigned ElemWidth = 1 + ExpWidth + FracWidth;
3411
3412 SDValue Zero = getZero(dl, InpTy, DAG);
3413 SDValue One = DAG.getConstant(1, dl, InpTy);
3414 SDValue IsZero = DAG.getSetCC(dl, PredTy, Op0, Zero, ISD::SETEQ);
3415 SDValue Abs = Signed ? DAG.getNode(ISD::ABS, dl, InpTy, Op0) : Op0;
3416 SDValue Clz = DAG.getNode(ISD::CTLZ, dl, InpTy, Abs);
3417 SDValue NLeft = DAG.getNode(ISD::ADD, dl, InpTy, {Clz, One});
3418 SDValue Frac0 = DAG.getNode(ISD::SHL, dl, InpTy, {Abs, NLeft});
3419
3420 auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1, false, DAG);
3421 if (Signed) {
3422 SDValue IsNeg = DAG.getSetCC(dl, PredTy, Op0, Zero, ISD::SETLT);
3423 SDValue M80 = DAG.getConstant(1ull << (ElemWidth - 1), dl, InpTy);
3424 SDValue Sign = DAG.getNode(ISD::VSELECT, dl, InpTy, {IsNeg, M80, Zero});
3425 Frac = DAG.getNode(ISD::OR, dl, InpTy, {Sign, Frac});
3426 }
3427
3428 SDValue Rnrm = DAG.getZExtOrTrunc(Ovf, dl, InpTy);
3429 SDValue Exp0 = DAG.getConstant(ElemWidth + ExpBias, dl, InpTy);
3430 SDValue Exp1 = DAG.getNode(ISD::ADD, dl, InpTy, {Rnrm, Exp0});
3431 SDValue Exp2 = DAG.getNode(ISD::SUB, dl, InpTy, {Exp1, NLeft});
3432 SDValue Exp3 = DAG.getNode(ISD::SHL, dl, InpTy,
3433 {Exp2, DAG.getConstant(FracWidth, dl, InpTy)});
3434 SDValue Flt0 = DAG.getNode(ISD::OR, dl, InpTy, {Frac, Exp3});
3435 SDValue Flt1 = DAG.getNode(ISD::VSELECT, dl, InpTy, {IsZero, Zero, Flt0});
3436 SDValue Flt = DAG.getBitcast(ResTy, Flt1);
3437
3438 return Flt;
3439}
3440
3441SDValue
3442HexagonTargetLowering::CreateTLWrapper(SDValue Op, SelectionDAG &DAG) const {
3443 unsigned Opc = Op.getOpcode();
3444 unsigned TLOpc;
3445 switch (Opc) {
3446 case ISD::ANY_EXTEND:
3447 case ISD::SIGN_EXTEND:
3448 case ISD::ZERO_EXTEND:
3449 TLOpc = HexagonISD::TL_EXTEND;
3450 break;
3451 case ISD::TRUNCATE:
3453 break;
3454#ifndef NDEBUG
3455 Op.dump(&DAG);
3456#endif
3457 llvm_unreachable("Unexpected operator");
3458 }
3459
3460 const SDLoc &dl(Op);
3461 return DAG.getNode(TLOpc, dl, ty(Op), Op.getOperand(0),
3462 DAG.getUNDEF(MVT::i128), // illegal type
3463 DAG.getConstant(Opc, dl, MVT::i32));
3464}
3465
3466SDValue
3467HexagonTargetLowering::RemoveTLWrapper(SDValue Op, SelectionDAG &DAG) const {
3468 assert(Op.getOpcode() == HexagonISD::TL_EXTEND ||
3469 Op.getOpcode() == HexagonISD::TL_TRUNCATE);
3470 unsigned Opc = Op.getConstantOperandVal(2);
3471 return DAG.getNode(Opc, SDLoc(Op), ty(Op), Op.getOperand(0));
3472}
3473
3474HexagonTargetLowering::VectorPair
3475HexagonTargetLowering::SplitVectorOp(SDValue Op, SelectionDAG &DAG) const {
3476 assert(!Op.isMachineOpcode());
3477 SmallVector<SDValue, 2> OpsL, OpsH;
3478 const SDLoc &dl(Op);
3479
3480 auto SplitVTNode = [&DAG, this](const VTSDNode *N) {
3481 MVT Ty = typeSplit(N->getVT().getSimpleVT()).first;
3482 SDValue TV = DAG.getValueType(Ty);
3483 return std::make_pair(TV, TV);
3484 };
3485
3486 for (SDValue A : Op.getNode()->ops()) {
3487 auto [Lo, Hi] =
3488 ty(A).isVector() ? opSplit(A, dl, DAG) : std::make_pair(A, A);
3489 // Special case for type operand.
3490 switch (Op.getOpcode()) {
3491 case ISD::SIGN_EXTEND_INREG:
3492 case HexagonISD::SSAT:
3493 case HexagonISD::USAT:
3494 if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))
3495 std::tie(Lo, Hi) = SplitVTNode(N);
3496 break;
3497 }
3498 OpsL.push_back(Lo);
3499 OpsH.push_back(Hi);
3500 }
3501
3502 MVT ResTy = ty(Op);
3503 MVT HalfTy = typeSplit(ResTy).first;
3504 SDValue L = DAG.getNode(Op.getOpcode(), dl, HalfTy, OpsL);
3505 SDValue H = DAG.getNode(Op.getOpcode(), dl, HalfTy, OpsH);
3506 return {L, H};
3507}
3508
3509SDValue
3510HexagonTargetLowering::SplitHvxMemOp(SDValue Op, SelectionDAG &DAG) const {
3511 auto *MemN = cast<MemSDNode>(Op.getNode());
3512 unsigned MemOpc = MemN->getOpcode();
3513 EVT MemTy = MemN->getMemoryVT();
3514
3515 if ((MemOpc == ISD::STORE || MemOpc == ISD::LOAD) &&
3516 (!MemTy.isSimple() || !isHvxPairTy(MemTy.getSimpleVT())))
3517 return Op;
3518
3519 EVT ValueType;
3520 if (MemOpc == ISD::STORE)
3522 else if (MemOpc == ISD::MSTORE)
3524 else // ISD::LOAD, ISD::MLOAD.
3525 ValueType = MemN->getValueType(0);
3526
3527 EVT LoVT, HiVT;
3528 std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(ValueType);
3529
3530 EVT LoMemVT, HiMemVT;
3531 bool HiIsEmpty = false;
3532 std::tie(LoMemVT, HiMemVT) =
3533 DAG.GetDependentSplitDestVTs(MemTy, LoVT, &HiIsEmpty);
3534
3535 uint64_t LoSize = LoMemVT.getSizeInBits().getFixedValue() / 8;
3536 uint64_t HiSize = HiMemVT.getSizeInBits().getFixedValue() / 8;
3537
3538 const SDLoc &dl(Op);
3539 SDValue Chain = MemN->getChain();
3540 SDValue Base0 = MemN->getBasePtr();
3541 SDValue Base1 =
3542 DAG.getMemBasePlusOffset(Base0, TypeSize::getFixed(LoSize), dl);
3543
3544 MachineMemOperand *MOp0 = nullptr, *MOp1 = nullptr;
3545 if (MachineMemOperand *MMO = MemN->getMemOperand()) {
3547 auto MemSize = [=](uint64_t Size) {
3548 return (MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE)
3550 : Size;
3551 };
3552 // MOp1 will not be used if HiIsEmpty for masked loads and stores (MLOAD and
3553 // MSTORE). Non-masked loads and store are always of double-vector size (see
3554 // isHvxPairTy() check above).
3555 MOp0 = MF.getMachineMemOperand(MMO, 0, MemSize(LoSize));
3556 MOp1 = MF.getMachineMemOperand(MMO, LoSize, MemSize(HiSize));
3557 }
3558
3559 if (MemOpc == ISD::LOAD) {
3560 assert(cast<LoadSDNode>(Op)->isUnindexed());
3561 SDValue Load0 = DAG.getLoad(LoVT, dl, Chain, Base0, MOp0);
3562 SDValue Load1 = DAG.getLoad(HiVT, dl, Chain, Base1, MOp1);
3563 return DAG.getMergeValues(
3564 {DAG.getNode(ISD::CONCAT_VECTORS, dl, MemN->getValueType(0), Load0,
3565 Load1),
3566 DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Load0.getValue(1),
3567 Load1.getValue(1))},
3568 dl);
3569 }
3570 if (MemOpc == ISD::STORE) {
3571 assert(cast<StoreSDNode>(Op)->isUnindexed());
3572 VectorPair Vals = opSplit(cast<StoreSDNode>(Op)->getValue(), dl, DAG);
3573 SDValue Store0 = DAG.getStore(Chain, dl, Vals.first, Base0, MOp0);
3574 SDValue Store1 = DAG.getStore(Chain, dl, Vals.second, Base1, MOp1);
3575 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store0, Store1);
3576 }
3577
3578 assert(MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE);
3579
3580 auto MaskN = cast<MaskedLoadStoreSDNode>(Op);
3581 assert(MaskN->isUnindexed());
3582 VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);
3583 SDValue Offset = DAG.getPOISON(MVT::i32);
3584
3585 if (MemOpc == ISD::MLOAD) {
3586 VectorPair Thru =
3587 opSplit(cast<MaskedLoadSDNode>(Op)->getPassThru(), dl, DAG);
3588 SDValue MLoad0 = DAG.getMaskedLoad(LoVT, dl, Chain, Base0, Offset,
3589 Masks.first, Thru.first, LoMemVT, MOp0,
3591
3592 // The hi masked load has zero storage size. We therefore simply set it to
3593 // the low masked load and rely on subsequent removal from the chain as it
3594 // is unused. See DAGTypeLegalizer::SplitVecRes_MLOAD() for the same logic.
3595 SDValue MLoad1 =
3596 HiIsEmpty ? MLoad0
3597 : DAG.getMaskedLoad(HiVT, dl, Chain, Base1, Offset,
3598 Masks.second, Thru.second, HiMemVT, MOp1,
3600 return DAG.getMergeValues(
3601 {DAG.getNode(ISD::CONCAT_VECTORS, dl, MemN->getValueType(0), MLoad0,
3602 MLoad1),
3603 DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MLoad0.getValue(1),
3604 MLoad1.getValue(1))},
3605 dl);
3606 }
3607 if (MemOpc == ISD::MSTORE) {
3608 VectorPair Vals = opSplit(cast<MaskedStoreSDNode>(Op)->getValue(), dl, DAG);
3609 SDValue MStore0 =
3610 DAG.getMaskedStore(Chain, dl, Vals.first, Base0, Offset, Masks.first,
3611 LoMemVT, MOp0, ISD::UNINDEXED, false, false);
3612 if (HiIsEmpty)
3613 return MStore0;
3614 SDValue MStore1 =
3615 DAG.getMaskedStore(Chain, dl, Vals.second, Base1, Offset, Masks.second,
3616 HiMemVT, MOp1, ISD::UNINDEXED, false, false);
3617 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MStore0, MStore1);
3618 }
3619
3620 std::string Name = "Unexpected operation: " + Op->getOperationName(&DAG);
3621 llvm_unreachable(Name.c_str());
3622}
3623
3624SDValue
3625HexagonTargetLowering::WidenHvxLoad(SDValue Op, SelectionDAG &DAG) const {
3626 const SDLoc &dl(Op);
3627 auto *LoadN = cast<LoadSDNode>(Op.getNode());
3628 assert(LoadN->isUnindexed() && "Not widening indexed loads yet");
3629 assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3630 "Not widening loads of i1 yet");
3631
3632 SDValue Chain = LoadN->getChain();
3633 SDValue Base = LoadN->getBasePtr();
3634 SDValue Offset = DAG.getPOISON(MVT::i32);
3635
3636 MVT ResTy = ty(Op);
3637 unsigned HwLen = Subtarget.getVectorLength();
3638 unsigned ResLen = ResTy.getStoreSize();
3639 assert(ResLen < HwLen && "vsetq(v1) prerequisite");
3640
3641 MVT BoolTy = MVT::getVectorVT(MVT::i1, HwLen);
3642 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3643 {DAG.getConstant(ResLen, dl, MVT::i32)}, DAG);
3644
3645 MVT LoadTy = MVT::getVectorVT(MVT::i8, HwLen);
3647 auto *MemOp = MF.getMachineMemOperand(LoadN->getMemOperand(), 0, HwLen);
3648
3649 SDValue Load = DAG.getMaskedLoad(LoadTy, dl, Chain, Base, Offset, Mask,
3650 DAG.getUNDEF(LoadTy), LoadTy, MemOp,
3652 SDValue Value = opCastElem(Load, ResTy.getVectorElementType(), DAG);
3653 return DAG.getMergeValues({Value, Load.getValue(1)}, dl);
3654}
3655
3656SDValue
3657HexagonTargetLowering::WidenHvxStore(SDValue Op, SelectionDAG &DAG) const {
3658 const SDLoc &dl(Op);
3659 auto *StoreN = cast<StoreSDNode>(Op.getNode());
3660 assert(StoreN->isUnindexed() && "Not widening indexed stores yet");
3661 assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
3662 "Not widening stores of i1 yet");
3663
3664 SDValue Chain = StoreN->getChain();
3665 SDValue Base = StoreN->getBasePtr();
3666 SDValue Offset = DAG.getPOISON(MVT::i32);
3667
3668 SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
3669 MVT ValueTy = ty(Value);
3670 unsigned ValueLen = ValueTy.getVectorNumElements();
3671 unsigned HwLen = Subtarget.getVectorLength();
3672 assert(isPowerOf2_32(ValueLen));
3673
3674 for (unsigned Len = ValueLen; Len < HwLen; ) {
3675 Value = opJoin({Value, DAG.getUNDEF(ty(Value))}, dl, DAG);
3676 Len = ty(Value).getVectorNumElements(); // This is Len *= 2
3677 }
3678 assert(ty(Value).getVectorNumElements() == HwLen); // Paranoia
3679
3680 assert(ValueLen < HwLen && "vsetq(v1) prerequisite");
3681 MVT BoolTy = MVT::getVectorVT(MVT::i1, HwLen);
3682 SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
3683 {DAG.getConstant(ValueLen, dl, MVT::i32)}, DAG);
3685 auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
3686 return DAG.getMaskedStore(Chain, dl, Value, Base, Offset, Mask,
3687 StoreN->getMemoryVT(), MemOp, ISD::UNINDEXED, false,
3688 false);
3689}
3690
3691SDValue
3692HexagonTargetLowering::WidenHvxSetCC(SDValue Op, SelectionDAG &DAG) const {
3693 const SDLoc &dl(Op);
3694 SDValue Op0 = Op.getOperand(0), Op1 = Op.getOperand(1);
3695 MVT ElemTy = ty(Op0).getVectorElementType();
3696 unsigned HwLen = Subtarget.getVectorLength();
3697
3698 unsigned WideOpLen = (8 * HwLen) / ElemTy.getSizeInBits();
3699 assert(WideOpLen * ElemTy.getSizeInBits() == 8 * HwLen);
3700 MVT WideOpTy = MVT::getVectorVT(ElemTy, WideOpLen);
3701 if (!Subtarget.isHVXVectorType(WideOpTy, true))
3702 return SDValue();
3703
3704 SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);
3705 SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);
3706 EVT ResTy =
3707 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), WideOpTy);
3708 SDValue SetCC = DAG.getNode(ISD::SETCC, dl, ResTy,
3709 {WideOp0, WideOp1, Op.getOperand(2)});
3710
3711 EVT RetTy = typeLegalize(ty(Op), DAG);
3712 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, RetTy,
3713 {SetCC, getZero(dl, MVT::i32, DAG)});
3714}
3715
3716SDValue HexagonTargetLowering::WidenHvxTruncateToBool(SDValue Op,
3717 SelectionDAG &DAG) const {
3718 // Handle truncation to boolean vector where the result boolean type
3719 // needs widening (e.g., v16i32 -> v16i1 where v16i1 is not a standard
3720 // HVX predicate type, or v16i8 -> v16i1 in 128-byte mode).
3721 // Widen the input to HVX width, perform the truncate to the widened
3722 // boolean type, then extract the result.
3723 const SDLoc &dl(Op);
3724 SDValue Inp = Op.getOperand(0);
3725 MVT InpTy = ty(Inp);
3726 MVT ResTy = ty(Op);
3727
3728 assert(ResTy.getVectorElementType() == MVT::i1 &&
3729 "Expected boolean result type");
3730
3731 MVT ElemTy = InpTy.getVectorElementType();
3732 unsigned HwLen = Subtarget.getVectorLength();
3733
3734 // Calculate the widened input type that fills the HVX register.
3735 unsigned WideLen = (8 * HwLen) / ElemTy.getSizeInBits();
3736 MVT WideInpTy = MVT::getVectorVT(ElemTy, WideLen);
3737 if (!Subtarget.isHVXVectorType(WideInpTy, false))
3738 return SDValue();
3739
3740 // Widen the input to HVX width.
3741 SDValue WideInp = appendUndef(Inp, WideInpTy, DAG);
3742
3743 // Perform the truncate to widened boolean type.
3744 MVT WideBoolTy = MVT::getVectorVT(MVT::i1, WideLen);
3745 SDValue WideTrunc = DAG.getNode(ISD::TRUNCATE, dl, WideBoolTy, WideInp);
3746
3747 // Extract the result.
3748 EVT RetTy = typeLegalize(ResTy, DAG);
3749 return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, RetTy,
3750 {WideTrunc, getZero(dl, MVT::i32, DAG)});
3751}
3752
3753SDValue
3754HexagonTargetLowering::LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const {
3755 unsigned Opc = Op.getOpcode();
3756 bool IsPairOp = isHvxPairTy(ty(Op)) ||
3757 llvm::any_of(Op.getNode()->ops(), [this] (SDValue V) {
3758 return isHvxPairTy(ty(V));
3759 });
3760
3761 if (IsPairOp) {
3762 switch (Opc) {
3763 default:
3764 break;
3765 case ISD::LOAD:
3766 case ISD::STORE:
3767 case ISD::MLOAD:
3768 case ISD::MSTORE:
3769 return SplitHvxMemOp(Op, DAG);
3770 case ISD::SINT_TO_FP:
3771 case ISD::UINT_TO_FP:
3772 case ISD::FP_TO_SINT:
3773 case ISD::FP_TO_UINT:
3774 if (ty(Op).getSizeInBits() == ty(Op.getOperand(0)).getSizeInBits())
3775 return opJoin(SplitVectorOp(Op, DAG), SDLoc(Op), DAG);
3776 break;
3777 case ISD::ABS:
3778 case ISD::CTPOP:
3779 case ISD::CTLZ:
3780 case ISD::CTTZ:
3781 case ISD::MUL:
3782 case ISD::FADD:
3783 case ISD::FSUB:
3784 case ISD::FMUL:
3785 case ISD::FMINIMUMNUM:
3786 case ISD::FMAXIMUMNUM:
3787 case ISD::FMINIMUM:
3788 case ISD::FMAXIMUM:
3789 case ISD::FMINNUM:
3790 case ISD::FMAXNUM:
3791 case ISD::MULHS:
3792 case ISD::MULHU:
3793 case ISD::AND:
3794 case ISD::OR:
3795 case ISD::XOR:
3796 case ISD::SRA:
3797 case ISD::SHL:
3798 case ISD::SRL:
3799 case ISD::FSHL:
3800 case ISD::FSHR:
3801 case ISD::SMIN:
3802 case ISD::SMAX:
3803 case ISD::UMIN:
3804 case ISD::UMAX:
3805 case ISD::SETCC:
3806 case ISD::VSELECT:
3808 case ISD::SPLAT_VECTOR:
3809 return opJoin(SplitVectorOp(Op, DAG), SDLoc(Op), DAG);
3810 case ISD::SIGN_EXTEND:
3811 case ISD::ZERO_EXTEND:
3812 // In general, sign- and zero-extends can't be split and still
3813 // be legal. The only exception is extending bool vectors.
3814 if (ty(Op.getOperand(0)).getVectorElementType() == MVT::i1)
3815 return opJoin(SplitVectorOp(Op, DAG), SDLoc(Op), DAG);
3816 break;
3817 }
3818 }
3819
3820 switch (Opc) {
3821 default:
3822 break;
3823 // clang-format off
3824 case ISD::BUILD_VECTOR: return LowerHvxBuildVector(Op, DAG);
3825 case ISD::SPLAT_VECTOR: return LowerHvxSplatVector(Op, DAG);
3826 case ISD::CONCAT_VECTORS: return LowerHvxConcatVectors(Op, DAG);
3827 case ISD::INSERT_SUBVECTOR: return LowerHvxInsertSubvector(Op, DAG);
3828 case ISD::INSERT_VECTOR_ELT: return LowerHvxInsertElement(Op, DAG);
3829 case ISD::EXTRACT_SUBVECTOR: return LowerHvxExtractSubvector(Op, DAG);
3830 case ISD::EXTRACT_VECTOR_ELT: return LowerHvxExtractElement(Op, DAG);
3831 case ISD::BITCAST: return LowerHvxBitcast(Op, DAG);
3832 case ISD::ANY_EXTEND: return LowerHvxAnyExt(Op, DAG);
3833 case ISD::SIGN_EXTEND: return LowerHvxSignExt(Op, DAG);
3834 case ISD::ZERO_EXTEND: return LowerHvxZeroExt(Op, DAG);
3835 case ISD::CTTZ: return LowerHvxCttz(Op, DAG);
3836 case ISD::SELECT: return LowerHvxSelect(Op, DAG);
3837 case ISD::SRA:
3838 case ISD::SHL:
3839 case ISD::SRL: return LowerHvxShift(Op, DAG);
3840 case ISD::FSHL:
3841 case ISD::FSHR: return LowerHvxFunnelShift(Op, DAG);
3842 case ISD::MULHS:
3843 case ISD::MULHU: return LowerHvxMulh(Op, DAG);
3844 case ISD::SMUL_LOHI:
3845 case ISD::UMUL_LOHI: return LowerHvxMulLoHi(Op, DAG);
3846 case ISD::ANY_EXTEND_VECTOR_INREG: return LowerHvxExtend(Op, DAG);
3847 case ISD::SETCC: {
3848 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
3849 if (CC == ISD::SETOEQ &&
3850 ty(Op.getOperand(0)).getScalarType().isFloatingPoint())
3851 return LowerHvxFpSetoeq(Op, DAG);
3852 return Op;
3853 }
3854 case ISD::INTRINSIC_VOID: return Op;
3855 case ISD::INTRINSIC_WO_CHAIN: return LowerHvxIntrinsic(Op, DAG);
3856 case ISD::MLOAD:
3857 case ISD::MSTORE: return LowerHvxMaskedOp(Op, DAG);
3858 // Unaligned loads will be handled by the default lowering.
3859 case ISD::LOAD: return LowerHvxLoad(Op, DAG);
3860 case ISD::STORE: return LowerHvxStore(Op, DAG);
3861 case ISD::FP_EXTEND: return LowerHvxFpExtend(Op, DAG);
3862 case ISD::FP_TO_SINT:
3863 case ISD::FP_TO_UINT: return LowerHvxFpToInt(Op, DAG);
3864 case ISD::SINT_TO_FP:
3865 case ISD::UINT_TO_FP: return LowerHvxIntToFp(Op, DAG);
3866
3867 // Special nodes:
3868 case HexagonISD::SMUL_LOHI:
3869 case HexagonISD::UMUL_LOHI:
3870 case HexagonISD::USMUL_LOHI: return LowerHvxMulLoHi(Op, DAG);
3871
3875 return LowerHvxPartialReduceMLA(Op, DAG);
3877 return LowerHvxVecReduceFMin(Op, DAG);
3879 return LowerHvxVecReduceFMax(Op, DAG);
3881 return LowerHvxVecReduceFMinimum(Op, DAG);
3883 return LowerHvxVecReduceFMaximum(Op, DAG);
3884 case ISD::FMINNUM:
3885 return LowerHvxFMinNum(Op, DAG);
3886 case ISD::FMAXNUM:
3887 return LowerHvxFMaxNum(Op, DAG);
3888 // clang-format on
3889 }
3890#ifndef NDEBUG
3891 Op.dumpr(&DAG);
3892#endif
3893 llvm_unreachable("Unhandled HVX operation");
3894}
3895
3896SDValue
3897HexagonTargetLowering::ExpandHvxResizeIntoSteps(SDValue Op, SelectionDAG &DAG)
3898 const {
3899 // Rewrite the extension/truncation/saturation op into steps where each
3900 // step changes the type widths by a factor of 2.
3901 // E.g. i8 -> i16 remains unchanged, but i8 -> i32 ==> i8 -> i16 -> i32.
3902 //
3903 // Some of the vector types in Op may not be legal.
3904
3905 unsigned Opc = Op.getOpcode();
3906 switch (Opc) {
3907 case HexagonISD::SSAT:
3908 case HexagonISD::USAT:
3911 break;
3912 case ISD::ANY_EXTEND:
3913 case ISD::ZERO_EXTEND:
3914 case ISD::SIGN_EXTEND:
3915 case ISD::TRUNCATE:
3916 llvm_unreachable("ISD:: ops will be auto-folded");
3917 break;
3918#ifndef NDEBUG
3919 Op.dump(&DAG);
3920#endif
3921 llvm_unreachable("Unexpected operation");
3922 }
3923
3924 SDValue Inp = Op.getOperand(0);
3925 MVT InpTy = ty(Inp);
3926 MVT ResTy = ty(Op);
3927
3928 unsigned InpWidth = InpTy.getVectorElementType().getSizeInBits();
3929 unsigned ResWidth = ResTy.getVectorElementType().getSizeInBits();
3930 assert(InpWidth != ResWidth);
3931
3932 if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)
3933 return Op;
3934
3935 const SDLoc &dl(Op);
3936 unsigned NumElems = InpTy.getVectorNumElements();
3937 assert(NumElems == ResTy.getVectorNumElements());
3938
3939 auto repeatOp = [&](unsigned NewWidth, SDValue Arg) {
3940 MVT Ty = MVT::getVectorVT(MVT::getIntegerVT(NewWidth), NumElems);
3941 switch (Opc) {
3942 case HexagonISD::SSAT:
3943 case HexagonISD::USAT:
3944 return DAG.getNode(Opc, dl, Ty, {Arg, DAG.getValueType(Ty)});
3947 return DAG.getNode(Opc, dl, Ty, {Arg, Op.getOperand(1), Op.getOperand(2)});
3948 default:
3949 llvm_unreachable("Unexpected opcode");
3950 }
3951 };
3952
3953 SDValue S = Inp;
3954 if (InpWidth < ResWidth) {
3955 assert(ResWidth % InpWidth == 0 && isPowerOf2_32(ResWidth / InpWidth));
3956 while (InpWidth * 2 <= ResWidth)
3957 S = repeatOp(InpWidth *= 2, S);
3958 } else {
3959 // InpWidth > ResWidth
3960 assert(InpWidth % ResWidth == 0 && isPowerOf2_32(InpWidth / ResWidth));
3961 while (InpWidth / 2 >= ResWidth)
3962 S = repeatOp(InpWidth /= 2, S);
3963 }
3964 return S;
3965}
3966
3967SDValue
3968HexagonTargetLowering::LegalizeHvxResize(SDValue Op, SelectionDAG &DAG) const {
3969 SDValue Inp0 = Op.getOperand(0);
3970 MVT InpTy = ty(Inp0);
3971 MVT ResTy = ty(Op);
3972 unsigned InpWidth = InpTy.getSizeInBits();
3973 unsigned ResWidth = ResTy.getSizeInBits();
3974 unsigned Opc = Op.getOpcode();
3975
3976 if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {
3977 // First, make sure that the narrower type is widened to HVX.
3978 // This may cause the result to be wider than what the legalizer
3979 // expects, so insert EXTRACT_SUBVECTOR to bring it back to the
3980 // desired type.
3981 auto [WInpTy, WResTy] =
3982 InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)
3983 : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));
3984 SDValue W = appendUndef(Inp0, WInpTy, DAG);
3985 SDValue S;
3987 S = DAG.getNode(Opc, SDLoc(Op), WResTy, W, Op.getOperand(1),
3988 Op.getOperand(2));
3989 } else {
3990 S = DAG.getNode(Opc, SDLoc(Op), WResTy, W, DAG.getValueType(WResTy));
3991 }
3992 SDValue T = ExpandHvxResizeIntoSteps(S, DAG);
3993 return extractSubvector(T, typeLegalize(ResTy, DAG), 0, DAG);
3994 } else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {
3995 // For multi-step extends/truncates (e.g., i8->i32), expand into
3996 // single-step operations first. Splitting a multi-step TL_EXTEND
3997 // would halve the operand type to a sub-HVX size (e.g., v128i8 ->
3998 // v64i8), creating illegal types that cause issues in the type
3999 // legalizer's map tracking. Single-step operations (e.g., i16->i32)
4000 // are safe to split because their halved operand types remain legal.
4001 SDValue T = ExpandHvxResizeIntoSteps(Op, DAG);
4002 if (T != Op)
4003 return T;
4004 return opJoin(SplitVectorOp(Op, DAG), SDLoc(Op), DAG);
4005 } else {
4006 assert(isTypeLegal(InpTy) && isTypeLegal(ResTy));
4007 return RemoveTLWrapper(Op, DAG);
4008 }
4009 llvm_unreachable("Unexpected situation");
4010}
4011
4012void
4013HexagonTargetLowering::LowerHvxOperationWrapper(SDNode *N,
4015 unsigned Opc = N->getOpcode();
4016 SDValue Op(N, 0);
4017 SDValue Inp0; // Optional first argument.
4018 if (N->getNumOperands() > 0)
4019 Inp0 = Op.getOperand(0);
4020
4021 switch (Opc) {
4022 case ISD::ANY_EXTEND:
4023 case ISD::SIGN_EXTEND:
4024 case ISD::ZERO_EXTEND:
4025 if (Subtarget.isHVXElementType(ty(Op)) &&
4026 Subtarget.isHVXElementType(ty(Inp0))) {
4027 Results.push_back(CreateTLWrapper(Op, DAG));
4028 }
4029 break;
4030 case ISD::TRUNCATE:
4031 // Handle truncate to boolean vector when the input is not a
4032 // standard HVX vector type (single or pair). This covers cases
4033 // where the input needs widening (e.g., v64i8 -> v64i1 in
4034 // 128-byte mode) and cases where the result boolean type itself
4035 // needs widening (e.g., v16i32 -> v16i1). When the input is
4036 // already an HVX type, tablegen patterns handle the truncation
4037 // directly (e.g., v64i16 -> v64i1 via V6_vandvrt).
4038 if (ty(Op).getVectorElementType() == MVT::i1 &&
4039 !Subtarget.isHVXVectorType(ty(Inp0), false)) {
4040 if (SDValue T = WidenHvxTruncateToBool(Op, DAG))
4041 Results.push_back(T);
4042 } else if (Subtarget.isHVXElementType(ty(Op)) &&
4043 Subtarget.isHVXElementType(ty(Inp0))) {
4044 Results.push_back(CreateTLWrapper(Op, DAG));
4045 }
4046 break;
4047 case ISD::SETCC:
4048 if (shouldWidenToHvx(ty(Inp0), DAG)) {
4049 if (SDValue T = WidenHvxSetCC(Op, DAG))
4050 Results.push_back(T);
4051 }
4052 break;
4053 case ISD::STORE: {
4054 if (shouldWidenToHvx(ty(cast<StoreSDNode>(N)->getValue()), DAG)) {
4055 SDValue Store = WidenHvxStore(Op, DAG);
4056 Results.push_back(Store);
4057 }
4058 break;
4059 }
4060 case ISD::MLOAD:
4061 if (isHvxPairTy(ty(Op))) {
4062 SDValue S = SplitHvxMemOp(Op, DAG);
4064 Results.push_back(S.getOperand(0));
4065 Results.push_back(S.getOperand(1));
4066 }
4067 break;
4068 case ISD::MSTORE:
4069 if (isHvxPairTy(ty(Op->getOperand(1)))) { // Stored value
4070 SDValue S = SplitHvxMemOp(Op, DAG);
4071 Results.push_back(S);
4072 }
4073 break;
4074 case ISD::SINT_TO_FP:
4075 case ISD::UINT_TO_FP:
4076 case ISD::FP_TO_SINT:
4077 case ISD::FP_TO_UINT:
4078 if (ty(Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4079 SDValue T = EqualizeFpIntConversion(Op, DAG);
4080 Results.push_back(T);
4081 }
4082 break;
4083 case HexagonISD::SSAT:
4084 case HexagonISD::USAT:
4087 Results.push_back(LegalizeHvxResize(Op, DAG));
4088 break;
4089 default:
4090 break;
4091 }
4092}
4093
4094void
4095HexagonTargetLowering::ReplaceHvxNodeResults(SDNode *N,
4097 unsigned Opc = N->getOpcode();
4098 SDValue Op(N, 0);
4099 SDValue Inp0; // Optional first argument.
4100 if (N->getNumOperands() > 0)
4101 Inp0 = Op.getOperand(0);
4102
4103 switch (Opc) {
4104 case ISD::ANY_EXTEND:
4105 case ISD::SIGN_EXTEND:
4106 case ISD::ZERO_EXTEND:
4107 if (Subtarget.isHVXElementType(ty(Op)) &&
4108 Subtarget.isHVXElementType(ty(Inp0))) {
4109 Results.push_back(CreateTLWrapper(Op, DAG));
4110 }
4111 break;
4112 case ISD::TRUNCATE:
4113 // Handle truncate to boolean vector when the input is not a
4114 // standard HVX vector type. See comment in LowerHvxOperationWrapper.
4115 if (ty(Op).getVectorElementType() == MVT::i1 &&
4116 !Subtarget.isHVXVectorType(ty(Inp0), false)) {
4117 if (SDValue T = WidenHvxTruncateToBool(Op, DAG))
4118 Results.push_back(T);
4119 } else if (Subtarget.isHVXElementType(ty(Op)) &&
4120 Subtarget.isHVXElementType(ty(Inp0))) {
4121 Results.push_back(CreateTLWrapper(Op, DAG));
4122 }
4123 break;
4124 case ISD::SETCC:
4125 if (shouldWidenToHvx(ty(Op), DAG)) {
4126 if (SDValue T = WidenHvxSetCC(Op, DAG))
4127 Results.push_back(T);
4128 }
4129 break;
4130 case ISD::LOAD: {
4131 if (shouldWidenToHvx(ty(Op), DAG)) {
4132 SDValue Load = WidenHvxLoad(Op, DAG);
4133 assert(Load->getOpcode() == ISD::MERGE_VALUES);
4134 Results.push_back(Load.getOperand(0));
4135 Results.push_back(Load.getOperand(1));
4136 }
4137 break;
4138 }
4139 case ISD::BITCAST:
4140 if (isHvxBoolTy(ty(Inp0))) {
4141 SDValue C = LowerHvxBitcast(Op, DAG);
4142 Results.push_back(C);
4143 }
4144 break;
4145 case ISD::FP_TO_SINT:
4146 case ISD::FP_TO_UINT:
4147 if (ty(Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {
4148 SDValue T = EqualizeFpIntConversion(Op, DAG);
4149 Results.push_back(T);
4150 }
4151 break;
4152 case HexagonISD::SSAT:
4153 case HexagonISD::USAT:
4156 Results.push_back(LegalizeHvxResize(Op, DAG));
4157 break;
4158 default:
4159 break;
4160 }
4161}
4162
4163SDValue
4164HexagonTargetLowering::combineTruncateBeforeLegal(SDValue Op,
4165 DAGCombinerInfo &DCI) const {
4166 // Simplify V:v2NiB --(bitcast)--> vNi2B --(truncate)--> vNiB
4167 // to extract-subvector (shuffle V, pick even, pick odd)
4168
4169 assert(Op.getOpcode() == ISD::TRUNCATE);
4170 SelectionDAG &DAG = DCI.DAG;
4171 const SDLoc &dl(Op);
4172
4173 if (Op.getOperand(0).getOpcode() == ISD::BITCAST)
4174 return SDValue();
4175 SDValue Cast = Op.getOperand(0);
4176 SDValue Src = Cast.getOperand(0);
4177
4178 EVT TruncTy = Op.getValueType();
4179 EVT CastTy = Cast.getValueType();
4180 EVT SrcTy = Src.getValueType();
4181 if (SrcTy.isSimple())
4182 return SDValue();
4183 if (SrcTy.getVectorElementType() != TruncTy.getVectorElementType())
4184 return SDValue();
4185 unsigned SrcLen = SrcTy.getVectorNumElements();
4186 unsigned CastLen = CastTy.getVectorNumElements();
4187 if (2 * CastLen != SrcLen)
4188 return SDValue();
4189
4190 SmallVector<int, 128> Mask(SrcLen);
4191 for (int i = 0; i != static_cast<int>(CastLen); ++i) {
4192 Mask[i] = 2 * i;
4193 Mask[i + CastLen] = 2 * i + 1;
4194 }
4195 SDValue Deal =
4196 DAG.getVectorShuffle(SrcTy, dl, Src, DAG.getUNDEF(SrcTy), Mask);
4197 return opSplit(Deal, dl, DAG).first;
4198}
4199
4200SDValue
4201HexagonTargetLowering::combineConcatOfShuffles(SDValue Op,
4202 SelectionDAG &DAG) const {
4203 // Fold
4204 // concat (shuffle x, y, m1), (shuffle x, y, m2)
4205 // into
4206 // shuffle (concat x, y), undef, m3
4207 if (Op.getNumOperands() != 2)
4208 return SDValue();
4209
4210 const SDLoc &dl(Op);
4211 SDValue V0 = Op.getOperand(0);
4212 SDValue V1 = Op.getOperand(1);
4213
4214 if (V0.getOpcode() != ISD::VECTOR_SHUFFLE)
4215 return SDValue();
4216 if (V1.getOpcode() != ISD::VECTOR_SHUFFLE)
4217 return SDValue();
4218
4219 SetVector<SDValue> Order;
4220 Order.insert(V0.getOperand(0));
4221 Order.insert(V0.getOperand(1));
4222 Order.insert(V1.getOperand(0));
4223 Order.insert(V1.getOperand(1));
4224
4225 if (Order.size() > 2)
4226 return SDValue();
4227
4228 // In ISD::VECTOR_SHUFFLE, the types of each input and the type of the
4229 // result must be the same.
4230 EVT InpTy = V0.getValueType();
4231 assert(InpTy.isVector());
4232 unsigned InpLen = InpTy.getVectorNumElements();
4233
4234 SmallVector<int, 128> LongMask;
4235 auto AppendToMask = [&](SDValue Shuffle) {
4236 auto *SV = cast<ShuffleVectorSDNode>(Shuffle.getNode());
4237 ArrayRef<int> Mask = SV->getMask();
4238 SDValue X = Shuffle.getOperand(0);
4239 SDValue Y = Shuffle.getOperand(1);
4240 for (int M : Mask) {
4241 if (M == -1) {
4242 LongMask.push_back(M);
4243 continue;
4244 }
4245 SDValue Src = static_cast<unsigned>(M) < InpLen ? X : Y;
4246 if (static_cast<unsigned>(M) >= InpLen)
4247 M -= InpLen;
4248
4249 int OutOffset = Order[0] == Src ? 0 : InpLen;
4250 LongMask.push_back(M + OutOffset);
4251 }
4252 };
4253
4254 AppendToMask(V0);
4255 AppendToMask(V1);
4256
4257 SDValue C0 = Order.front();
4258 SDValue C1 = Order.back(); // Can be same as front
4259 EVT LongTy = InpTy.getDoubleNumVectorElementsVT(*DAG.getContext());
4260
4261 SDValue Cat = DAG.getNode(ISD::CONCAT_VECTORS, dl, LongTy, {C0, C1});
4262 return DAG.getVectorShuffle(LongTy, dl, Cat, DAG.getUNDEF(LongTy), LongMask);
4263}
4264
4265// Reassociate concat(p1, p2, ...) into
4266// concat(concat(p1, ...), concat(pi, ...), ...)
4267// where each inner concat produces a predicate where each bit corresponds
4268// to at most BitBytes bytes.
4269// Concatenating predicates decreases the number of bytes per each predicate
4270// bit.
4271SDValue
4272HexagonTargetLowering::combineConcatOfScalarPreds(SDValue Op, unsigned BitBytes,
4273 SelectionDAG &DAG) const {
4274 const SDLoc &dl(Op);
4275 SmallVector<SDValue> Ops(Op->ops());
4276 MVT ResTy = ty(Op);
4277 MVT InpTy = ty(Ops[0]);
4278 unsigned InpLen = InpTy.getVectorNumElements(); // Scalar predicate
4279 unsigned ResLen = ResTy.getVectorNumElements(); // HVX vector predicate
4280 assert(InpLen <= 8 && "Too long for scalar predicate");
4281 assert(ResLen > 8 && "Too short for HVX vector predicate");
4282
4283 unsigned Bytes = 8 / InpLen; // Bytes-per-bit in input
4284
4285 // Already in the right form?
4286 if (Bytes <= BitBytes)
4287 return Op;
4288
4289 ArrayRef<SDValue> Inputs(Ops);
4290 unsigned SliceLen = Bytes / BitBytes;
4291
4293 // (8 / BitBytes) is the desired length of the result of the inner concat.
4294 MVT InnerTy = MVT::getVectorVT(MVT::i1, 8 / BitBytes);
4295 for (unsigned i = 0; i != ResLen / (8 / BitBytes); ++i) {
4296 SDValue Cat = DAG.getNode(ISD::CONCAT_VECTORS, dl, InnerTy,
4297 Inputs.slice(SliceLen * i, SliceLen));
4298 Cats.push_back(Cat);
4299 }
4300
4301 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResTy, Cats);
4302}
4303
4304SDValue HexagonTargetLowering::combineConcatVectorsBeforeLegal(
4305 SDValue Op, DAGCombinerInfo &DCI) const {
4306 MVT ResTy = ty(Op);
4307 MVT ElemTy = ResTy.getVectorElementType();
4308
4309 if (ElemTy != MVT::i1) {
4310 return combineConcatOfShuffles(Op, DCI.DAG);
4311 }
4312 return SDValue();
4313}
4314
4315// Create the inner partial reduction MLA that can be efficiently lowered. This
4316// function is used by partial and full reductions.
4317SDValue HexagonTargetLowering::createExtendingPartialReduceMLA(
4318 unsigned Opcode, EVT AccEltType, unsigned AccNumElements, EVT InputType,
4319 const SDValue &A, const SDValue &B, unsigned &RemainingReductionRatio,
4320 const SDLoc &DL, SelectionDAG &DAG) const {
4321 const auto &Subtarget = DAG.getSubtarget<HexagonSubtarget>();
4322 if (!Subtarget.useHVXOps())
4323 return SDValue();
4324
4325 EVT InputEltType = InputType.getVectorElementType();
4326
4327 // Find if an optimized instruction for the sub-reduction is available.
4328 unsigned NativeRatio;
4329 if (AccEltType == MVT::i32 && InputEltType == MVT::i8)
4330 NativeRatio = 4;
4331 else
4332 return SDValue();
4333
4334 // We only handle the case when additional reduction will be needed, i.e.
4335 // input is longer by a larger factor than the result.
4336 ElementCount InputEC = InputType.getVectorElementCount();
4337 if (!InputEC.isKnownMultipleOf(AccNumElements * NativeRatio))
4338 return SDValue();
4339
4340 unsigned InputNumElements = InputEC.getFixedValue();
4341 RemainingReductionRatio = InputNumElements / (AccNumElements * NativeRatio);
4342 if (RemainingReductionRatio == 1)
4343 return SDValue();
4344
4345 // Create a reduction by the natively supported factor.
4346 EVT IntermediateType = EVT::getVectorVT(*DAG.getContext(), AccEltType,
4347 InputNumElements / NativeRatio);
4348
4349 SDValue Zero = DAG.getConstant(0, DL, IntermediateType);
4350 return DAG.getNode(Opcode, DL, IntermediateType, Zero, A, B);
4351}
4352
4353static bool DetectExtendingMultiply(const SDValue &N, EVT ScalarType,
4354 unsigned &Opcode, SDValue &A, SDValue &B) {
4355 SDValue Mul = N;
4356 EVT AccType = Mul.getValueType(); // Vector input type after extension.
4357 if (ScalarType != AccType.getVectorElementType())
4358 return false;
4359 bool swap = false;
4360 if (Mul->getOpcode() != ISD::MUL)
4361 return false;
4362 A = Mul->getOperand(0);
4363 B = Mul->getOperand(1);
4364 if (A.getOpcode() == ISD::ZERO_EXTEND) {
4365 if (B.getOpcode() == ISD::ZERO_EXTEND)
4366 Opcode = ISD::PARTIAL_REDUCE_UMLA;
4367 else if (B.getOpcode() == ISD::SIGN_EXTEND) {
4368 swap = true;
4370 } else
4371 return false;
4372 } else if (A.getOpcode() == ISD::SIGN_EXTEND) {
4373 if (B.getOpcode() == ISD::ZERO_EXTEND)
4375 else if (B.getOpcode() == ISD::SIGN_EXTEND)
4376 Opcode = ISD::PARTIAL_REDUCE_SMLA;
4377 else
4378 return false;
4379 } else
4380 return false;
4381
4382 // Get multiplication arguments before extension.
4383 A = A->getOperand(0);
4384 B = B->getOperand(0);
4385 if (A.getValueType() != B.getValueType())
4386 return false;
4387
4388 if (swap)
4389 std::swap(A, B);
4390
4391 return true;
4392}
4393
4394SDValue HexagonTargetLowering::splitVecReduceAdd(SDNode *N,
4395 SelectionDAG &DAG) const {
4396 if (!Subtarget.useHVXOps())
4397 return SDValue();
4398
4399 EVT ScalarType = N->getValueType(0);
4400 unsigned Opcode;
4401 SDValue A, B;
4402 if (!DetectExtendingMultiply(N->getOperand(0), ScalarType, Opcode, A, B))
4403 return SDValue();
4404
4405 SDLoc DL(N);
4406 unsigned RemainingReductionRatio;
4407 SDValue Partial =
4408 createExtendingPartialReduceMLA(Opcode, ScalarType, 1, A.getValueType(),
4409 A, B, RemainingReductionRatio, DL, DAG);
4410 if (!Partial)
4411 return SDValue();
4412
4413 // We could have inserted a trivial MLA and rely on the folding action,
4414 // similar to how vector_partial_reduce_add is lowered to an MLA in
4415 // SelectionDAGBuilder. However, we just replace the final result since we
4416 // have analyzed the input completely.
4417 return DAG.getNode(ISD::VECREDUCE_ADD, DL, ScalarType, Partial);
4418}
4419
4420// Shared helper for VECREDUCE_FMIN/FMAX/FMINIMUM/FMAXIMUM on HVX float
4421// vector types. IgnoreNaN=true (FMIN/FMAX): NaN elements are replaced with
4422// the neutral value before the reduction so they don't corrupt the result
4423// even when the hardware pairwise instruction propagates NaN.
4424// IgnoreNaN=false (FMINIMUM/FMAXIMUM): NaN propagates naturally.
4425SDValue HexagonTargetLowering::LowerHvxVecReduceFMinMax(
4426 SDValue Op, unsigned PairwiseOpc, bool IgnoreNaN, SelectionDAG &DAG) const {
4427 SDLoc DL(Op);
4428 SDValue Vec = Op.getOperand(0);
4429 MVT VecTy = ty(Vec);
4430 SDNodeFlags Flags = Op->getFlags();
4431 bool ShouldStripNaN = IgnoreNaN && !Flags.hasNoNaNs();
4432
4433 // Save original input before NaN stripping; needed for the all-NaN fixup.
4434 SDValue OrigVec = Vec;
4435 MVT OrigVecTy = VecTy;
4436
4437 // Replace NaN elements in V with +/-Inf so the tree reduction ignores them.
4438 bool IsMax = (Op.getOpcode() == ISD::VECREDUCE_FMAX);
4439 auto ReplaceNaN = [&](SDValue V, MVT Ty) -> SDValue {
4441 Ty.getVectorElementType().getFltSemantics(), /*Negative=*/IsMax);
4442 SDValue NeutralVec = DAG.getConstantFP(Neutral, DL, Ty);
4443 EVT BoolTy = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), Ty);
4444 SDValue IsNaN = DAG.getSetCC(DL, BoolTy, V, V, ISD::SETUO);
4445 return DAG.getNode(ISD::VSELECT, DL, Ty, IsNaN, NeutralVec, V);
4446 };
4447
4448 // For a pair vector, strip NaN from each half before the cross-half
4449 // pairwise reduction so a NaN in one half can't corrupt the other.
4450 if (isHvxPairTy(VecTy)) {
4451 auto [Lo, Hi] = opSplit(Vec, DL, DAG);
4452 MVT SingleTy = ty(Lo);
4453 if (ShouldStripNaN) {
4454 Lo = ReplaceNaN(Lo, SingleTy);
4455 Hi = ReplaceNaN(Hi, SingleTy);
4456 }
4457 Vec = DAG.getNode(PairwiseOpc, DL, SingleTy, Lo, Hi, Flags);
4458 VecTy = SingleTy;
4459 } else if (ShouldStripNaN) {
4460 Vec = ReplaceNaN(Vec, VecTy);
4461 }
4462
4463 // Tree reduction using VROR + pairwise op. Each iteration rotates the vector
4464 // by half the remaining element count (in bytes) and takes element-wise
4465 // min/max, halving the active width until element 0 holds the result.
4466 unsigned ElemBytes = VecTy.getScalarSizeInBits() / 8;
4467 unsigned HwLen = Subtarget.getVectorLength();
4468 unsigned NumElems = HwLen / ElemBytes;
4469
4470 SDValue Curr = Vec;
4471 for (unsigned Width = NumElems / 2; Width >= 1; Width /= 2) {
4472 SDValue RotAmt = DAG.getConstant(Width * ElemBytes, DL, MVT::i32);
4473 SDValue Rotated = DAG.getNode(HexagonISD::VROR, DL, VecTy, Curr, RotAmt);
4474 Curr = DAG.getNode(PairwiseOpc, DL, VecTy, Curr, Rotated, Flags);
4475 }
4476
4477 // Extract element 0 as the scalar result.
4478 MVT ScalarTy = Op.getSimpleValueType();
4479 SDValue Result = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, ScalarTy, Curr,
4480 DAG.getConstant(0, DL, MVT::i32));
4481
4482 // Per llvm.maxnum/minnum semantics, all-NaN input must return NaN. The
4483 // NaN-stripping above replaced every NaN with the neutral value, so an
4484 // all-NaN vector produces the neutral value instead. Fix: if no element
4485 // in the original vector was non-NaN, return NaN.
4486 if (ShouldStripNaN) {
4487 EVT BoolVecTy =
4488 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), OrigVecTy);
4489 // IsOrd[i] == 1 iff OrigVec[i] is not NaN.
4490 SDValue IsOrd = DAG.getSetCC(DL, BoolVecTy, OrigVec, OrigVec, ISD::SETO);
4491 // BoolVecTy is vNi1 with exactly N bits; bitcast to an integer and
4492 // check != 0 to detect whether any element was non-NaN.
4493 unsigned NumBits = BoolVecTy.getSizeInBits();
4494 MVT IntTy = MVT::getIntegerVT(NumBits);
4495 SDValue IsOrdInt = DAG.getBitcast(IntTy, IsOrd);
4496 SDValue AnyNonNaN = DAG.getSetCC(DL, MVT::i1, IsOrdInt,
4497 DAG.getConstant(0, DL, IntTy), ISD::SETNE);
4499 DL, ScalarTy);
4500 Result = DAG.getSelect(DL, ScalarTy, AnyNonNaN, Result, NaN);
4501 }
4502
4503 return Result;
4504}
4505
4506SDValue HexagonTargetLowering::LowerHvxVecReduceFMin(SDValue Op,
4507 SelectionDAG &DAG) const {
4508 return LowerHvxVecReduceFMinMax(Op, ISD::FMINNUM, /*IgnoreNaN=*/true, DAG);
4509}
4510
4511SDValue HexagonTargetLowering::LowerHvxVecReduceFMax(SDValue Op,
4512 SelectionDAG &DAG) const {
4513 return LowerHvxVecReduceFMinMax(Op, ISD::FMAXNUM, /*IgnoreNaN=*/true, DAG);
4514}
4515
4516SDValue
4517HexagonTargetLowering::LowerHvxVecReduceFMinimum(SDValue Op,
4518 SelectionDAG &DAG) const {
4519 return LowerHvxVecReduceFMinMax(Op, ISD::FMINIMUM, /*IgnoreNaN=*/false, DAG);
4520}
4521
4522SDValue
4523HexagonTargetLowering::LowerHvxVecReduceFMaximum(SDValue Op,
4524 SelectionDAG &DAG) const {
4525 return LowerHvxVecReduceFMinMax(Op, ISD::FMAXIMUM, /*IgnoreNaN=*/false, DAG);
4526}
4527
4528// Lower FMINNUM/FMAXNUM on a single HVX float vector. These ops must ignore
4529// NaN (return the non-NaN operand). Because the hardware vmin/vmax may
4530// propagate NaN, replace NaN in each operand with the neutral value (+/-Inf)
4531// before delegating to FMINIMUM/FMAXIMUM.
4532SDValue HexagonTargetLowering::LowerHvxFMinNum(SDValue Op,
4533 SelectionDAG &DAG) const {
4534 SDLoc DL(Op);
4535 auto A = Op.getOperand(0), B = Op.getOperand(1);
4536 auto Ty = ty(Op);
4537 auto Flags = Op->getFlags();
4538
4539 if (!Flags.hasNoNaNs()) {
4540 auto &Sem = Ty.getVectorElementType().getFltSemantics();
4541 auto PosInf = DAG.getConstantFP(APFloat::getInf(Sem, false), DL, Ty);
4542 auto BoolTy =
4543 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), Ty);
4544 auto IsNaN_A = DAG.getSetCC(DL, BoolTy, A, A, ISD::SETUO);
4545 auto IsNaN_B = DAG.getSetCC(DL, BoolTy, B, B, ISD::SETUO);
4546 // Per llvm.minnum: if both operands are NaN, return NaN. Replace NaN
4547 // with +Inf so the hardware min ignores single-operand NaN, then restore
4548 // NaN for lanes where both inputs were NaN.
4549 auto BothNaN = DAG.getNode(ISD::AND, DL, BoolTy, IsNaN_A, IsNaN_B);
4550 A = DAG.getNode(ISD::VSELECT, DL, Ty, IsNaN_A, PosInf, A);
4551 B = DAG.getNode(ISD::VSELECT, DL, Ty, IsNaN_B, PosInf, B);
4552 auto Res = DAG.getNode(ISD::FMINIMUM, DL, Ty, A, B, Flags);
4553 auto NaN = DAG.getConstantFP(APFloat::getNaN(Sem), DL, Ty);
4554 return DAG.getNode(ISD::VSELECT, DL, Ty, BothNaN, NaN, Res);
4555 }
4556 return DAG.getNode(ISD::FMINIMUM, DL, Ty, A, B, Flags);
4557}
4558
4559SDValue HexagonTargetLowering::LowerHvxFMaxNum(SDValue Op,
4560 SelectionDAG &DAG) const {
4561 SDLoc DL(Op);
4562 auto A = Op.getOperand(0), B = Op.getOperand(1);
4563 auto Ty = ty(Op);
4564 auto Flags = Op->getFlags();
4565
4566 if (!Flags.hasNoNaNs()) {
4567 auto &Sem = Ty.getVectorElementType().getFltSemantics();
4568 auto NegInf = DAG.getConstantFP(APFloat::getInf(Sem, true), DL, Ty);
4569 auto BoolTy =
4570 getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), Ty);
4571 auto IsNaN_A = DAG.getSetCC(DL, BoolTy, A, A, ISD::SETUO);
4572 auto IsNaN_B = DAG.getSetCC(DL, BoolTy, B, B, ISD::SETUO);
4573 // Per llvm.maxnum: if both operands are NaN, return NaN. Replace NaN
4574 // with -Inf so the hardware max ignores single-operand NaN, then restore
4575 // NaN for lanes where both inputs were NaN.
4576 auto BothNaN = DAG.getNode(ISD::AND, DL, BoolTy, IsNaN_A, IsNaN_B);
4577 A = DAG.getNode(ISD::VSELECT, DL, Ty, IsNaN_A, NegInf, A);
4578 B = DAG.getNode(ISD::VSELECT, DL, Ty, IsNaN_B, NegInf, B);
4579 auto Res = DAG.getNode(ISD::FMAXIMUM, DL, Ty, A, B, Flags);
4580 auto NaN = DAG.getConstantFP(APFloat::getNaN(Sem), DL, Ty);
4581 return DAG.getNode(ISD::VSELECT, DL, Ty, BothNaN, NaN, Res);
4582 }
4583 return DAG.getNode(ISD::FMAXIMUM, DL, Ty, A, B, Flags);
4584}
4585
4586// When possible, separate an MLA reduction with extended operands but
4587// unsupported reduction factor into an extending partial reduction that
4588// can be efficiently lowered, and a follow-up partial reduction.
4589// partial_reduce_mla(a, x, y) ->
4590// partial_reduce_mla(a, partial_reduce_mla(0, x, y), 1)
4591SDValue
4592HexagonTargetLowering::splitExtendingPartialReduceMLA(SDNode *N,
4593 SelectionDAG &DAG) const {
4594 if (!Subtarget.useHVXOps())
4595 return SDValue();
4596
4597 SDValue Acc = N->getOperand(0);
4598 SDValue A = N->getOperand(1);
4599 SDValue B = N->getOperand(2);
4600 if (A.getValueType() != B.getValueType())
4601 return SDValue();
4602
4603 // The types should be declared as custom, but do not split already legal
4604 // operation.
4605 EVT AccType = Acc.getValueType();
4606 EVT InputType = A.getValueType();
4607 if (getPartialReduceMLAAction(N->getOpcode(), AccType, InputType) != Custom)
4608 return SDValue();
4609
4610 SDLoc DL(N);
4611 unsigned RemainingReductionRatio;
4612 SDValue Partial = createExtendingPartialReduceMLA(
4613 N->getOpcode(), AccType.getVectorElementType(),
4614 AccType.getVectorNumElements(), InputType, A, B, RemainingReductionRatio,
4615 DL, DAG);
4616 if (!Partial)
4617 return SDValue();
4618 assert(RemainingReductionRatio <= MaxExpandMLA);
4619
4620 // Create the reduction for the remaining ratio.
4621 EVT IntermediateType = Partial->getOperand(0).getValueType();
4622 SDValue One = DAG.getConstant(1, DL, IntermediateType);
4623 return DAG.getNode(N->getOpcode() == ISD::PARTIAL_REDUCE_UMLA
4626 DL, AccType, Acc, Partial, One);
4627}
4628
4629SDValue
4630HexagonTargetLowering::LowerHvxPartialReduceMLA(SDValue Op,
4631 SelectionDAG &DAG) const {
4632 const SDLoc &DL(Op);
4633 SDValue Acc = Op.getOperand(0);
4634 SDValue A = Op.getOperand(1);
4635 SDValue B = Op.getOperand(2);
4636
4637 // Split the input vectors into units of one HVX vector length.
4638 unsigned HwVectorSizeInBits = Subtarget.getVectorLength() * 8;
4639
4640 EVT AccType = Acc.getValueType();
4641 EVT AccEltType = AccType.getVectorElementType();
4642 unsigned AccSubvectorNumElements =
4643 HwVectorSizeInBits / AccEltType.getSizeInBits();
4644 EVT AccSubvectorType =
4645 EVT::getVectorVT(*DAG.getContext(), AccEltType, AccSubvectorNumElements);
4646
4647 EVT InputType = A.getValueType();
4648 assert(InputType.getSizeInBits() % HwVectorSizeInBits == 0);
4649 EVT InputEltType = InputType.getVectorElementType();
4650 unsigned InputSubvectorNumElements =
4651 HwVectorSizeInBits / InputEltType.getSizeInBits();
4652 EVT InputSubvectorType = EVT::getVectorVT(*DAG.getContext(), InputEltType,
4653 InputSubvectorNumElements);
4654
4655 unsigned SubvectorNum = InputType.getFixedSizeInBits() / HwVectorSizeInBits;
4657
4658 for (unsigned I = 0; I != SubvectorNum; ++I) {
4659 SDValue SubvectorAcc = DAG.getExtractSubvector(DL, AccSubvectorType, Acc,
4660 I * AccSubvectorNumElements);
4661 SDValue SubvectorA = DAG.getExtractSubvector(DL, InputSubvectorType, A,
4662 I * InputSubvectorNumElements);
4663 SDValue SubvectorB = DAG.getExtractSubvector(DL, InputSubvectorType, B,
4664 I * InputSubvectorNumElements);
4665 SDValue SubvectorMLA = DAG.getNode(Op.getOpcode(), DL, AccSubvectorType,
4666 SubvectorAcc, SubvectorA, SubvectorB);
4667 Subvectors.push_back(SubvectorMLA);
4668 }
4669
4670 return DAG.getNode(ISD::CONCAT_VECTORS, DL, AccType, Subvectors);
4671}
4672
4673// Lower fcmp oeq on HVX float vectors for architectures before v81, which
4674// lack a dedicated floating-point equality instruction.
4675//
4676// Correct IEEE-754 semantics: oeq(a,b) is true iff a==b and neither is NaN.
4677// We use the available float-GT instruction (V6_vgtsf/V6_vgthf) for the
4678// inequality check and bit manipulation for NaN detection:
4679//
4680// oeq(a, b) = NOT(ogt(a,b) OR ogt(b,a) OR isNaN(a) OR isNaN(b))
4681//
4682// where isNaN(x) = ((int_bits(x) & AbsMask) > NaNThreshold)
4683// f32: AbsMask=0x7FFFFFFF, NaNThreshold=0x7F800000
4684// f16: AbsMask=0x7FFF, NaNThreshold=0x7C00
4685//
4686// This handles +0/-0 correctly because float-GT treats them as equal, so
4687// neither ogt(+0,-0) nor ogt(-0,+0) is ever true.
4688//
4689// Example f32 assembly (no NaNs case):
4690// q0 = vcmp.eq(v0.w, v1.w) // bitwise comparison should just work
4691//
4692// Example f32 assembly (NaN-present case):
4693// q0 = vcmp.gt(v0.sf, v1.sf) // ogt(a,b)
4694// q0 |= vcmp.gt(v1.sf, v0.sf) // |= ogt(b,a)
4695// r0 = ##0x7FFFFFFF
4696// v2 = vsplat(r0) // AbsMask broadcast
4697// r1 = ##0x7F800000
4698// v3 = vsplat(r1) // NaNThresh broadcast
4699// v4 = vand(v0, v2) // int_bits(a) & AbsMask
4700// v5 = vand(v1, v2) // int_bits(b) & AbsMask
4701// q0 |= vcmp.gt(v4.w, v3.w) // |= isNaN(a)
4702// q0 |= vcmp.gt(v5.w, v3.w) // |= isNaN(b)
4703// // q0 now holds AnyFalse; result = XOR(q0, allones) = oeq
4704SDValue HexagonTargetLowering::LowerHvxFpSetoeq(SDValue Op,
4705 SelectionDAG &DAG) const {
4706 auto ResTy = ty(Op);
4707 auto A = Op.getOperand(0), B = Op->getOperand(1);
4708 MVT FloatTy = ty(A);
4709 MVT ElemTy = FloatTy.getVectorElementType();
4710 bool IsF32 = (ElemTy == MVT::f32);
4711 if (!IsF32) {
4712 assert((ElemTy == MVT::f16));
4713 }
4714 const SDLoc &DL(Op);
4715 MVT IntElemTy = IsF32 ? MVT::i32 : MVT::i16;
4716 MVT IntVecTy = tyVector(FloatTy, IntElemTy);
4717
4718 // Under nnan semantics NaN cannot appear, so integer equality is both
4719 // correct and cheaper (one instruction vs the float-GT sequence).
4720 bool NoNaN = Op->getFlags().hasNoNaNs();
4721 if (NoNaN) {
4722 SDValue IA = DAG.getNode(ISD::BITCAST, DL, IntVecTy, A);
4723 SDValue IB = DAG.getNode(ISD::BITCAST, DL, IntVecTy, B);
4724 return DAG.getSetCC(DL, ResTy, IA, IB, ISD::SETEQ);
4725 }
4726
4727 // Float GT comparisons (IEEE-754: false whenever either operand is NaN).
4728 SDValue QAgtB = DAG.getSetCC(DL, ResTy, A, B, ISD::SETOGT);
4729 SDValue QBgtA = DAG.getSetCC(DL, ResTy, B, A, ISD::SETOGT);
4730
4731 // OR all "false" conditions together, then invert.
4732 SDValue AnyFalse = DAG.getNode(ISD::OR, DL, ResTy, QAgtB, QBgtA);
4733
4734 // Detect NaN by checking whether the unbiased exponent/mantissa field
4735 // exceeds the largest finite value.
4736 // f32: (bits & 0x7FFFFFFF) > 0x7F800000
4737 // f16: (bits & 0x7FFF) > 0x7C00
4738 uint64_t AbsMask = IsF32 ? 0x7FFFFFFFull : 0x7FFFull;
4739 uint64_t NaNThresh = IsF32 ? 0x7F800000ull : 0x7C00ull;
4740
4741 SDValue IA = DAG.getNode(ISD::BITCAST, DL, IntVecTy, A);
4742 SDValue IB = DAG.getNode(ISD::BITCAST, DL, IntVecTy, B);
4743 SDValue MaskVec = DAG.getConstant(AbsMask, DL, IntVecTy);
4744 SDValue ThreshVec = DAG.getConstant(NaNThresh, DL, IntVecTy);
4745 SDValue QNanA =
4746 DAG.getSetCC(DL, ResTy, DAG.getNode(ISD::AND, DL, IntVecTy, IA, MaskVec),
4747 ThreshVec, ISD::SETGT);
4748 SDValue QNanB =
4749 DAG.getSetCC(DL, ResTy, DAG.getNode(ISD::AND, DL, IntVecTy, IB, MaskVec),
4750 ThreshVec, ISD::SETGT);
4751 AnyFalse = DAG.getNode(ISD::OR, DL, ResTy, AnyFalse, QNanA);
4752 AnyFalse = DAG.getNode(ISD::OR, DL, ResTy, AnyFalse, QNanB);
4753
4754 // Result = NOT(<Is A gt B>, <IS B gt A>, <IS A NaN>, <IS B NaN>)
4755 // Use XOR with ones to simulate logical not.
4756 return DAG.getNode(ISD::XOR, DL, ResTy, AnyFalse,
4757 DAG.getConstant(1, DL, ResTy));
4758}
4759
4760SDValue
4761HexagonTargetLowering::PerformHvxDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
4762 const {
4763 const SDLoc &dl(N);
4764 SelectionDAG &DAG = DCI.DAG;
4765 SDValue Op(N, 0);
4766 unsigned Opc = Op.getOpcode();
4767
4769
4770 if (Opc == ISD::TRUNCATE)
4771 return combineTruncateBeforeLegal(Op, DCI);
4772 if (Opc == ISD::CONCAT_VECTORS)
4773 return combineConcatVectorsBeforeLegal(Op, DCI);
4774
4775 if (DCI.isBeforeLegalizeOps())
4776 return SDValue();
4777
4778 switch (Opc) {
4779 case HexagonISD::V2Q:
4780 if (Ops[0].getOpcode() == ISD::SPLAT_VECTOR) {
4781 if (const auto *C = dyn_cast<ConstantSDNode>(Ops[0].getOperand(0)))
4782 return C->isZero() ? DAG.getNode(HexagonISD::QFALSE, dl, ty(Op))
4783 : DAG.getNode(HexagonISD::QTRUE, dl, ty(Op));
4784 }
4785 break;
4786 case HexagonISD::Q2V:
4787 if (Ops[0].getOpcode() == HexagonISD::QTRUE)
4788 return DAG.getNode(ISD::SPLAT_VECTOR, dl, ty(Op),
4789 DAG.getAllOnesConstant(dl, MVT::i32));
4790 if (Ops[0].getOpcode() == HexagonISD::QFALSE)
4791 return getZero(dl, ty(Op), DAG);
4792 break;
4793 case HexagonISD::VINSERTW0:
4794 if (isUndef(Ops[1]))
4795 return Ops[0];
4796 break;
4797 case HexagonISD::VROR: {
4798 if (Ops[0].getOpcode() == HexagonISD::VROR) {
4799 SDValue Vec = Ops[0].getOperand(0);
4800 SDValue Rot0 = Ops[1], Rot1 = Ops[0].getOperand(1);
4801 SDValue Rot = DAG.getNode(ISD::ADD, dl, ty(Rot0), {Rot0, Rot1});
4802 return DAG.getNode(HexagonISD::VROR, dl, ty(Op), {Vec, Rot});
4803 }
4804 break;
4805 }
4806 }
4807
4808 return SDValue();
4809}
4810
4811bool
4812HexagonTargetLowering::shouldSplitToHvx(MVT Ty, SelectionDAG &DAG) const {
4813 if (Subtarget.isHVXVectorType(Ty, true))
4814 return false;
4815 auto Action = getPreferredHvxVectorAction(Ty);
4817 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG), true);
4818 return false;
4819}
4820
4821bool
4822HexagonTargetLowering::shouldWidenToHvx(MVT Ty, SelectionDAG &DAG) const {
4823 if (Subtarget.isHVXVectorType(Ty, true))
4824 return false;
4825 auto Action = getPreferredHvxVectorAction(Ty);
4827 return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG), true);
4828 return false;
4829}
4830
4831bool
4832HexagonTargetLowering::isHvxOperation(SDNode *N, SelectionDAG &DAG) const {
4833 if (!Subtarget.useHVXOps())
4834 return false;
4835 // If the type of any result, or any operand type are HVX vector types,
4836 // this is an HVX operation.
4837 auto IsHvxTy = [this](EVT Ty) {
4838 return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(), true);
4839 };
4840 auto IsHvxOp = [this](SDValue Op) {
4841 return Op.getValueType().isSimple() &&
4842 Subtarget.isHVXVectorType(ty(Op), true);
4843 };
4844 if (llvm::any_of(N->values(), IsHvxTy) || llvm::any_of(N->ops(), IsHvxOp))
4845 return true;
4846
4847 // Check if this could be an HVX operation after type widening.
4848 auto IsWidenedToHvx = [this, &DAG](SDValue Op) {
4849 if (!Op.getValueType().isSimple())
4850 return false;
4851 MVT ValTy = ty(Op);
4852 return ValTy.isVector() && shouldWidenToHvx(ValTy, DAG);
4853 };
4854
4855 for (int i = 0, e = N->getNumValues(); i != e; ++i) {
4856 if (IsWidenedToHvx(SDValue(N, i)))
4857 return true;
4858 }
4859 return llvm::any_of(N->ops(), IsWidenedToHvx);
4860}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
constexpr LLT S16
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
static std::tuple< unsigned, unsigned, unsigned > getIEEEProperties(MVT Ty)
static const unsigned MaxExpandMLA
static const MVT LegalV128[]
static const MVT LegalW128[]
static const MVT LegalW64[]
static const MVT LegalV64[]
static bool DetectExtendingMultiply(const SDValue &N, EVT ScalarType, unsigned &Opcode, SDValue &A, SDValue &B)
static cl::opt< unsigned > HvxWidenThreshold("hexagon-hvx-widen", cl::Hidden, cl::init(16), cl::desc("Lower threshold (in bytes) for widening to HVX vectors"))
static cl::opt< bool > EnableFpFastConvert("hexagon-fp-fast-convert", cl::Hidden, cl::init(false), cl::desc("Enable FP fast conversion routine."))
static MaybeAlign getAlign(Value *Ptr)
IRTranslator LLVM IR MI
static constexpr Value * getValue(Ty &ValueOrUse)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isSplat(Value *V)
Return true if V is a splat of a value (which is used when multiplying a matrix with a scalar).
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define H(x, y, z)
Definition MD5.cpp:56
std::pair< MCSymbol *, MachineModuleInfoImpl::StubValueTy > PairTy
Promote Memory to Register
Definition Mem2Reg.cpp:110
This file provides utility analysis objects describing memory locations.
#define T
#define T1
#define P(N)
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static llvm::Type * getVectorElementType(llvm::Type *Ty)
BinaryOperator * Mul
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:361
static const fltSemantics & IEEEhalf()
Definition APFloat.h:302
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:6010
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Definition APFloat.h:1202
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Definition APFloat.h:1213
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const
EVT getSetCCResultType(const DataLayout &, LLVMContext &C, EVT VT) const override
Return the ValueType of the result of SETCC operations.
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
const SDValue & getBasePtr() const
Machine Value Type.
static MVT getFloatingPointVT(unsigned BitWidth)
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
MVT changeTypeToInteger()
Return the type converted to an equivalently sized integer or vector with integer element type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
ElementCount getVectorElementCount() const
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
Flags
Flags values. These may be or'd together.
const MachinePointerInfo & getPointerInfo() const
Align getBaseAlign() const
Return the minimum known alignment in bytes of the base address, without the offset.
unsigned getSubReg() const
int64_t getImm() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
iterator_range< value_op_iterator > op_values() const
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
const SDValue & getOperand(unsigned Num) const
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
const TargetSubtargetInfo & getSubtarget() const
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
LLVM_ABI SDValue getConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offs=0, bool isT=false, unsigned TargetFlags=0)
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
LLVM_ABI std::pair< SDValue, SDValue > SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT)
Split the vector with EXTRACT_SUBVECTOR using the provided VTs and return the low/high part.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
MachineFunction & getMachineFunction() const
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVMContext * getContext() const
LLVM_ABI std::pair< EVT, EVT > GetDependentSplitDestVTs(const EVT &VT, const EVT &EnvVT, bool *HiIsEmpty) const
Compute the VTs needed for the low/hi parts of a type, dependent on an enveloping VT that has been sp...
LLVM_ABI SDValue getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand, SDValue Subreg)
A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes.
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
const value_type & front() const
Return the first element of the SetVector.
Definition SetVector.h:138
const value_type & back() const
Return the last element of the SetVector.
Definition SetVector.h:144
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
const SDValue & getBasePtr() const
const SDValue & getValue() const
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPartialReduceMLAAction(unsigned Opc, MVT AccVT, MVT InputVT, LegalizeAction Action)
Indicate how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treate...
LegalizeAction getPartialReduceMLAAction(unsigned Opc, EVT AccVT, EVT InputVT) const
Return how a PARTIAL_REDUCE_U/SMLA node with Acc type AccVT and Input type InputVT should be treated.
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:339
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:297
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
Definition TypeSize.h:180
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
self_iterator getIterator()
Definition ilist_node.h:123
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:829
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
Definition ISDOpcodes.h:261
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition ISDOpcodes.h:275
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:602
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:789
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:863
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition ISDOpcodes.h:220
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:890
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:586
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:417
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:749
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
Definition ISDOpcodes.h:920
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
Definition ISDOpcodes.h:254
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
Definition ISDOpcodes.h:374
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:806
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:233
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition ISDOpcodes.h:674
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:706
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:651
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:616
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:578
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
Definition ISDOpcodes.h:909
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:898
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:729
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
Definition ISDOpcodes.h:988
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:815
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:936
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:205
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:567
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
Definition ISDOpcodes.h:969
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
Definition ISDOpcodes.h:931
@ VECREDUCE_FMINIMUM
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:866
@ PARTIAL_REDUCE_SUMLA
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:365
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:558
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
initializer< Ty > init(const Ty &Val)
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2208
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Or
Bitwise or logical OR of integers.
@ And
Bitwise or logical AND of integers.
@ Add
Sum of integers.
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
Extended Value Type.
Definition ValueTypes.h:35
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h:145
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
Definition ValueTypes.h:70
ElementCount getVectorElementCount() const
Definition ValueTypes.h:373
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
Definition ValueTypes.h:494
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
Definition ValueTypes.h:404
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const