brintos

brintos / llvm-project-archived public Read only

0
0
Text · 148.9 KiB · 212a57b Raw
3964 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "HexagonISelLowering.h"10#include "HexagonRegisterInfo.h"11#include "HexagonSubtarget.h"12#include "llvm/ADT/SetVector.h"13#include "llvm/ADT/SmallVector.h"14#include "llvm/Analysis/MemoryLocation.h"15#include "llvm/CodeGen/MachineBasicBlock.h"16#include "llvm/CodeGen/MachineFunction.h"17#include "llvm/CodeGen/MachineInstr.h"18#include "llvm/CodeGen/MachineOperand.h"19#include "llvm/CodeGen/MachineRegisterInfo.h"20#include "llvm/CodeGen/TargetInstrInfo.h"21#include "llvm/IR/IntrinsicsHexagon.h"22#include "llvm/Support/CommandLine.h"23 24#include <algorithm>25#include <string>26#include <utility>27 28using namespace llvm;29 30static cl::opt<unsigned> HvxWidenThreshold("hexagon-hvx-widen",31  cl::Hidden, cl::init(16),32  cl::desc("Lower threshold (in bytes) for widening to HVX vectors"));33 34static const MVT LegalV64[] =  { MVT::v64i8,  MVT::v32i16,  MVT::v16i32 };35static const MVT LegalW64[] =  { MVT::v128i8, MVT::v64i16,  MVT::v32i32 };36static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16,  MVT::v32i32 };37static const MVT LegalW128[] = { MVT::v256i8, MVT::v128i16, MVT::v64i32 };38 39static std::tuple<unsigned, unsigned, unsigned> getIEEEProperties(MVT Ty) {40  // For a float scalar type, return (exp-bits, exp-bias, fraction-bits)41  MVT ElemTy = Ty.getScalarType();42  switch (ElemTy.SimpleTy) {43    case MVT::f16:44      return std::make_tuple(5, 15, 10);45    case MVT::f32:46      return std::make_tuple(8, 127, 23);47    case MVT::f64:48      return std::make_tuple(11, 1023, 52);49    default:50      break;51  }52  llvm_unreachable(("Unexpected type: " + EVT(ElemTy).getEVTString()).c_str());53}54 55void56HexagonTargetLowering::initializeHVXLowering() {57  if (Subtarget.useHVX64BOps()) {58    addRegisterClass(MVT::v64i8,  &Hexagon::HvxVRRegClass);59    addRegisterClass(MVT::v32i16, &Hexagon::HvxVRRegClass);60    addRegisterClass(MVT::v16i32, &Hexagon::HvxVRRegClass);61    addRegisterClass(MVT::v128i8, &Hexagon::HvxWRRegClass);62    addRegisterClass(MVT::v64i16, &Hexagon::HvxWRRegClass);63    addRegisterClass(MVT::v32i32, &Hexagon::HvxWRRegClass);64    // These "short" boolean vector types should be legal because65    // they will appear as results of vector compares. If they were66    // not legal, type legalization would try to make them legal67    // and that would require using operations that do not use or68    // produce such types. That, in turn, would imply using custom69    // nodes, which would be unoptimizable by the DAG combiner.70    // The idea is to rely on target-independent operations as much71    // as possible.72    addRegisterClass(MVT::v16i1, &Hexagon::HvxQRRegClass);73    addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass);74    addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass);75  } else if (Subtarget.useHVX128BOps()) {76    addRegisterClass(MVT::v128i8,  &Hexagon::HvxVRRegClass);77    addRegisterClass(MVT::v64i16,  &Hexagon::HvxVRRegClass);78    addRegisterClass(MVT::v32i32,  &Hexagon::HvxVRRegClass);79    addRegisterClass(MVT::v256i8,  &Hexagon::HvxWRRegClass);80    addRegisterClass(MVT::v128i16, &Hexagon::HvxWRRegClass);81    addRegisterClass(MVT::v64i32,  &Hexagon::HvxWRRegClass);82    addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass);83    addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass);84    addRegisterClass(MVT::v128i1, &Hexagon::HvxQRRegClass);85    if (Subtarget.useHVXV68Ops() && Subtarget.useHVXFloatingPoint()) {86      addRegisterClass(MVT::v32f32, &Hexagon::HvxVRRegClass);87      addRegisterClass(MVT::v64f16, &Hexagon::HvxVRRegClass);88      addRegisterClass(MVT::v64f32, &Hexagon::HvxWRRegClass);89      addRegisterClass(MVT::v128f16, &Hexagon::HvxWRRegClass);90    }91    if (Subtarget.useHVXV81Ops()) {92      addRegisterClass(MVT::v64bf16, &Hexagon::HvxVRRegClass);93      addRegisterClass(MVT::v128bf16, &Hexagon::HvxWRRegClass);94    }95  }96 97  // Set up operation actions.98 99  bool Use64b = Subtarget.useHVX64BOps();100  ArrayRef<MVT> LegalV = Use64b ? LegalV64 : LegalV128;101  ArrayRef<MVT> LegalW = Use64b ? LegalW64 : LegalW128;102  MVT ByteV = Use64b ?  MVT::v64i8 : MVT::v128i8;103  MVT WordV = Use64b ? MVT::v16i32 : MVT::v32i32;104  MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8;105 106  auto setPromoteTo = [this] (unsigned Opc, MVT FromTy, MVT ToTy) {107    setOperationAction(Opc, FromTy, Promote);108    AddPromotedToType(Opc, FromTy, ToTy);109  };110 111  // Handle bitcasts of vector predicates to scalars (e.g. v32i1 to i32).112  // Note: v16i1 -> i16 is handled in type legalization instead of op113  // legalization.114  setOperationAction(ISD::BITCAST,              MVT::i16, Custom);115  setOperationAction(ISD::BITCAST,              MVT::i32, Custom);116  setOperationAction(ISD::BITCAST,              MVT::i64, Custom);117  setOperationAction(ISD::BITCAST,            MVT::v16i1, Custom);118  setOperationAction(ISD::BITCAST,           MVT::v128i1, Custom);119  setOperationAction(ISD::BITCAST,             MVT::i128, Custom);120  setOperationAction(ISD::VECTOR_SHUFFLE,          ByteV, Legal);121  setOperationAction(ISD::VECTOR_SHUFFLE,          ByteW, Legal);122  setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);123 124  if (Subtarget.useHVX128BOps()) {125    setOperationAction(ISD::BITCAST, MVT::v32i1, Custom);126    setOperationAction(ISD::BITCAST, MVT::v64i1, Custom);127  }128  if (Subtarget.useHVX128BOps() && Subtarget.useHVXV68Ops() &&129      Subtarget.useHVXFloatingPoint()) {130 131    static const MVT FloatV[] = { MVT::v64f16, MVT::v32f32 };132    static const MVT FloatW[] = { MVT::v128f16, MVT::v64f32 };133 134    for (MVT T : FloatV) {135      setOperationAction(ISD::FADD,              T, Legal);136      setOperationAction(ISD::FSUB,              T, Legal);137      setOperationAction(ISD::FMUL,              T, Legal);138      setOperationAction(ISD::FMINIMUMNUM, T, Legal);139      setOperationAction(ISD::FMAXIMUMNUM, T, Legal);140 141      setOperationAction(ISD::INSERT_SUBVECTOR,  T, Custom);142      setOperationAction(ISD::EXTRACT_SUBVECTOR, T, Custom);143 144      setOperationAction(ISD::SPLAT_VECTOR,      T, Legal);145      setOperationAction(ISD::SPLAT_VECTOR,      T, Legal);146 147      setOperationAction(ISD::MLOAD,             T, Custom);148      setOperationAction(ISD::MSTORE,            T, Custom);149      // Custom-lower BUILD_VECTOR. The standard (target-independent)150      // handling of it would convert it to a load, which is not always151      // the optimal choice.152      setOperationAction(ISD::BUILD_VECTOR,      T, Custom);153    }154 155 156    // BUILD_VECTOR with f16 operands cannot be promoted without157    // promoting the result, so lower the node to vsplat or constant pool158    setOperationAction(ISD::BUILD_VECTOR,      MVT::f16, Custom);159    setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::f16, Custom);160    setOperationAction(ISD::SPLAT_VECTOR,      MVT::f16, Custom);161 162    // Vector shuffle is always promoted to ByteV and a bitcast to f16 is163    // generated.164    setPromoteTo(ISD::VECTOR_SHUFFLE, MVT::v128f16, ByteW);165    setPromoteTo(ISD::VECTOR_SHUFFLE,  MVT::v64f16, ByteV);166    setPromoteTo(ISD::VECTOR_SHUFFLE,  MVT::v64f32, ByteW);167    setPromoteTo(ISD::VECTOR_SHUFFLE,  MVT::v32f32, ByteV);168 169    if (Subtarget.useHVXV81Ops()) {170      setPromoteTo(ISD::VECTOR_SHUFFLE, MVT::v128bf16, ByteW);171      setPromoteTo(ISD::VECTOR_SHUFFLE, MVT::v64bf16, ByteV);172      setPromoteTo(ISD::SETCC, MVT::v64bf16, MVT::v64f32);173      setPromoteTo(ISD::FADD, MVT::v64bf16, MVT::v64f32);174      setPromoteTo(ISD::FSUB, MVT::v64bf16, MVT::v64f32);175      setPromoteTo(ISD::FMUL, MVT::v64bf16, MVT::v64f32);176      setPromoteTo(ISD::FMINNUM, MVT::v64bf16, MVT::v64f32);177      setPromoteTo(ISD::FMAXNUM, MVT::v64bf16, MVT::v64f32);178 179      setOperationAction(ISD::SPLAT_VECTOR, MVT::v64bf16, Legal);180      setOperationAction(ISD::INSERT_SUBVECTOR, MVT::v64bf16, Custom);181      setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v64bf16, Custom);182 183      setOperationAction(ISD::MLOAD, MVT::v64bf16, Custom);184      setOperationAction(ISD::MSTORE, MVT::v64bf16, Custom);185      setOperationAction(ISD::BUILD_VECTOR, MVT::v64bf16, Custom);186      setOperationAction(ISD::CONCAT_VECTORS, MVT::v64bf16, Custom);187 188      setOperationAction(ISD::SPLAT_VECTOR, MVT::bf16, Custom);189      setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::bf16, Custom);190      setOperationAction(ISD::BUILD_VECTOR, MVT::bf16, Custom);191    }192 193    for (MVT P : FloatW) {194      setOperationAction(ISD::LOAD,           P, Custom);195      setOperationAction(ISD::STORE,          P, Custom);196      setOperationAction(ISD::FADD,           P, Custom);197      setOperationAction(ISD::FSUB,           P, Custom);198      setOperationAction(ISD::FMUL,           P, Custom);199      setOperationAction(ISD::FMINIMUMNUM, P, Custom);200      setOperationAction(ISD::FMAXIMUMNUM, P, Custom);201      setOperationAction(ISD::SETCC,          P, Custom);202      setOperationAction(ISD::VSELECT,        P, Custom);203 204      // Custom-lower BUILD_VECTOR. The standard (target-independent)205      // handling of it would convert it to a load, which is not always206      // the optimal choice.207      setOperationAction(ISD::BUILD_VECTOR,   P, Custom);208      // Make concat-vectors custom to handle concats of more than 2 vectors.209      setOperationAction(ISD::CONCAT_VECTORS, P, Custom);210 211      setOperationAction(ISD::MLOAD,          P, Custom);212      setOperationAction(ISD::MSTORE,         P, Custom);213    }214 215    if (Subtarget.useHVXQFloatOps()) {216      setOperationAction(ISD::FP_EXTEND, MVT::v64f32, Custom);217      setOperationAction(ISD::FP_ROUND,  MVT::v64f16, Legal);218    } else if (Subtarget.useHVXIEEEFPOps()) {219      setOperationAction(ISD::FP_EXTEND, MVT::v64f32, Legal);220      setOperationAction(ISD::FP_ROUND,  MVT::v64f16, Legal);221    }222  }223 224  for (MVT T : LegalV) {225    setIndexedLoadAction(ISD::POST_INC,  T, Legal);226    setIndexedStoreAction(ISD::POST_INC, T, Legal);227 228    setOperationAction(ISD::ABS,            T, Legal);229    setOperationAction(ISD::AND,            T, Legal);230    setOperationAction(ISD::OR,             T, Legal);231    setOperationAction(ISD::XOR,            T, Legal);232    setOperationAction(ISD::ADD,            T, Legal);233    setOperationAction(ISD::SUB,            T, Legal);234    setOperationAction(ISD::MUL,            T, Legal);235    setOperationAction(ISD::CTPOP,          T, Legal);236    setOperationAction(ISD::CTLZ,           T, Legal);237    setOperationAction(ISD::SELECT,         T, Legal);238    setOperationAction(ISD::SPLAT_VECTOR,   T, Legal);239    setOperationAction(ISD::UADDSAT, T, Legal);240    setOperationAction(ISD::SADDSAT, T, Legal);241    setOperationAction(ISD::USUBSAT, T, Legal);242    setOperationAction(ISD::SSUBSAT, T, Legal);243    if (T != ByteV) {244      setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Legal);245      setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Legal);246      setOperationAction(ISD::BSWAP,                    T, Legal);247    }248 249    setOperationAction(ISD::SMIN,           T, Legal);250    setOperationAction(ISD::SMAX,           T, Legal);251    if (T.getScalarType() != MVT::i32) {252      setOperationAction(ISD::UMIN,         T, Legal);253      setOperationAction(ISD::UMAX,         T, Legal);254    }255 256    setOperationAction(ISD::CTTZ,               T, Custom);257    setOperationAction(ISD::LOAD,               T, Custom);258    setOperationAction(ISD::MLOAD,              T, Custom);259    setOperationAction(ISD::MSTORE,             T, Custom);260    if (T.getScalarType() != MVT::i32) {261      setOperationAction(ISD::MULHS,              T, Legal);262      setOperationAction(ISD::MULHU,              T, Legal);263    }264 265    setOperationAction(ISD::BUILD_VECTOR,       T, Custom);266    // Make concat-vectors custom to handle concats of more than 2 vectors.267    setOperationAction(ISD::CONCAT_VECTORS,     T, Custom);268    setOperationAction(ISD::INSERT_SUBVECTOR,   T, Custom);269    setOperationAction(ISD::INSERT_VECTOR_ELT,  T, Custom);270    setOperationAction(ISD::EXTRACT_SUBVECTOR,  T, Custom);271    setOperationAction(ISD::EXTRACT_VECTOR_ELT, T, Custom);272    setOperationAction(ISD::ANY_EXTEND,         T, Custom);273    setOperationAction(ISD::SIGN_EXTEND,        T, Custom);274    setOperationAction(ISD::ZERO_EXTEND,        T, Custom);275    setOperationAction(ISD::FSHL,               T, Custom);276    setOperationAction(ISD::FSHR,               T, Custom);277    if (T != ByteV) {278      setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, T, Custom);279      // HVX only has shifts of words and halfwords.280      setOperationAction(ISD::SRA,                     T, Custom);281      setOperationAction(ISD::SHL,                     T, Custom);282      setOperationAction(ISD::SRL,                     T, Custom);283 284      // Promote all shuffles to operate on vectors of bytes.285      setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteV);286    }287 288    if (Subtarget.useHVXFloatingPoint()) {289      // Same action for both QFloat and IEEE.290      setOperationAction(ISD::SINT_TO_FP, T, Custom);291      setOperationAction(ISD::UINT_TO_FP, T, Custom);292      setOperationAction(ISD::FP_TO_SINT, T, Custom);293      setOperationAction(ISD::FP_TO_UINT, T, Custom);294    }295 296    setCondCodeAction(ISD::SETNE,  T, Expand);297    setCondCodeAction(ISD::SETLE,  T, Expand);298    setCondCodeAction(ISD::SETGE,  T, Expand);299    setCondCodeAction(ISD::SETLT,  T, Expand);300    setCondCodeAction(ISD::SETULE, T, Expand);301    setCondCodeAction(ISD::SETUGE, T, Expand);302    setCondCodeAction(ISD::SETULT, T, Expand);303  }304 305  for (MVT T : LegalW) {306    // Custom-lower BUILD_VECTOR for vector pairs. The standard (target-307    // independent) handling of it would convert it to a load, which is308    // not always the optimal choice.309    setOperationAction(ISD::BUILD_VECTOR,   T, Custom);310    // Make concat-vectors custom to handle concats of more than 2 vectors.311    setOperationAction(ISD::CONCAT_VECTORS, T, Custom);312 313    // Custom-lower these operations for pairs. Expand them into a concat314    // of the corresponding operations on individual vectors.315    setOperationAction(ISD::ANY_EXTEND,               T, Custom);316    setOperationAction(ISD::SIGN_EXTEND,              T, Custom);317    setOperationAction(ISD::ZERO_EXTEND,              T, Custom);318    setOperationAction(ISD::SIGN_EXTEND_INREG,        T, Custom);319    setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG,  T, Custom);320    setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Legal);321    setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Legal);322    setOperationAction(ISD::SPLAT_VECTOR,             T, Custom);323 324    setOperationAction(ISD::LOAD,     T, Custom);325    setOperationAction(ISD::STORE,    T, Custom);326    setOperationAction(ISD::MLOAD,    T, Custom);327    setOperationAction(ISD::MSTORE,   T, Custom);328    setOperationAction(ISD::ABS,      T, Custom);329    setOperationAction(ISD::CTLZ,     T, Custom);330    setOperationAction(ISD::CTTZ,     T, Custom);331    setOperationAction(ISD::CTPOP,    T, Custom);332 333    setOperationAction(ISD::ADD,      T, Legal);334    setOperationAction(ISD::UADDSAT, T, Legal);335    setOperationAction(ISD::SADDSAT, T, Legal);336    setOperationAction(ISD::SUB,      T, Legal);337    setOperationAction(ISD::USUBSAT, T, Legal);338    setOperationAction(ISD::SSUBSAT, T, Legal);339    setOperationAction(ISD::MUL,      T, Custom);340    setOperationAction(ISD::MULHS,    T, Custom);341    setOperationAction(ISD::MULHU,    T, Custom);342    setOperationAction(ISD::AND,      T, Custom);343    setOperationAction(ISD::OR,       T, Custom);344    setOperationAction(ISD::XOR,      T, Custom);345    setOperationAction(ISD::SETCC,    T, Custom);346    setOperationAction(ISD::VSELECT,  T, Custom);347    if (T != ByteW) {348      setOperationAction(ISD::SRA,      T, Custom);349      setOperationAction(ISD::SHL,      T, Custom);350      setOperationAction(ISD::SRL,      T, Custom);351 352      // Promote all shuffles to operate on vectors of bytes.353      setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteW);354    }355    setOperationAction(ISD::FSHL,     T, Custom);356    setOperationAction(ISD::FSHR,     T, Custom);357 358    setOperationAction(ISD::SMIN,     T, Custom);359    setOperationAction(ISD::SMAX,     T, Custom);360    if (T.getScalarType() != MVT::i32) {361      setOperationAction(ISD::UMIN,     T, Custom);362      setOperationAction(ISD::UMAX,     T, Custom);363    }364 365    if (Subtarget.useHVXFloatingPoint()) {366      // Same action for both QFloat and IEEE.367      setOperationAction(ISD::SINT_TO_FP, T, Custom);368      setOperationAction(ISD::UINT_TO_FP, T, Custom);369      setOperationAction(ISD::FP_TO_SINT, T, Custom);370      setOperationAction(ISD::FP_TO_UINT, T, Custom);371    }372  }373 374  // Legalize all of these to HexagonISD::[SU]MUL_LOHI.375  setOperationAction(ISD::MULHS,      WordV, Custom); // -> _LOHI376  setOperationAction(ISD::MULHU,      WordV, Custom); // -> _LOHI377  setOperationAction(ISD::SMUL_LOHI,  WordV, Custom);378  setOperationAction(ISD::UMUL_LOHI,  WordV, Custom);379 380  setCondCodeAction(ISD::SETNE,  MVT::v64f16, Expand);381  setCondCodeAction(ISD::SETLE,  MVT::v64f16, Expand);382  setCondCodeAction(ISD::SETGE,  MVT::v64f16, Expand);383  setCondCodeAction(ISD::SETLT,  MVT::v64f16, Expand);384  setCondCodeAction(ISD::SETONE, MVT::v64f16, Expand);385  setCondCodeAction(ISD::SETOLE, MVT::v64f16, Expand);386  setCondCodeAction(ISD::SETOGE, MVT::v64f16, Expand);387  setCondCodeAction(ISD::SETOLT, MVT::v64f16, Expand);388  setCondCodeAction(ISD::SETUNE, MVT::v64f16, Expand);389  setCondCodeAction(ISD::SETULE, MVT::v64f16, Expand);390  setCondCodeAction(ISD::SETUGE, MVT::v64f16, Expand);391  setCondCodeAction(ISD::SETULT, MVT::v64f16, Expand);392  setCondCodeAction(ISD::SETUO, MVT::v64f16, Expand);393  setCondCodeAction(ISD::SETO, MVT::v64f16, Expand);394 395  setCondCodeAction(ISD::SETNE,  MVT::v32f32, Expand);396  setCondCodeAction(ISD::SETLE,  MVT::v32f32, Expand);397  setCondCodeAction(ISD::SETGE,  MVT::v32f32, Expand);398  setCondCodeAction(ISD::SETLT,  MVT::v32f32, Expand);399  setCondCodeAction(ISD::SETONE, MVT::v32f32, Expand);400  setCondCodeAction(ISD::SETOLE, MVT::v32f32, Expand);401  setCondCodeAction(ISD::SETOGE, MVT::v32f32, Expand);402  setCondCodeAction(ISD::SETOLT, MVT::v32f32, Expand);403  setCondCodeAction(ISD::SETUNE, MVT::v32f32, Expand);404  setCondCodeAction(ISD::SETULE, MVT::v32f32, Expand);405  setCondCodeAction(ISD::SETUGE, MVT::v32f32, Expand);406  setCondCodeAction(ISD::SETULT, MVT::v32f32, Expand);407  setCondCodeAction(ISD::SETUO, MVT::v32f32, Expand);408  setCondCodeAction(ISD::SETO, MVT::v32f32, Expand);409 410  // Boolean vectors.411 412  for (MVT T : LegalW) {413    // Boolean types for vector pairs will overlap with the boolean414    // types for single vectors, e.g.415    //   v64i8  -> v64i1 (single)416    //   v64i16 -> v64i1 (pair)417    // Set these actions first, and allow the single actions to overwrite418    // any duplicates.419    MVT BoolW = MVT::getVectorVT(MVT::i1, T.getVectorNumElements());420    setOperationAction(ISD::SETCC,              BoolW, Custom);421    setOperationAction(ISD::AND,                BoolW, Custom);422    setOperationAction(ISD::OR,                 BoolW, Custom);423    setOperationAction(ISD::XOR,                BoolW, Custom);424    // Masked load/store takes a mask that may need splitting.425    setOperationAction(ISD::MLOAD,              BoolW, Custom);426    setOperationAction(ISD::MSTORE,             BoolW, Custom);427  }428 429  for (MVT T : LegalV) {430    MVT BoolV = MVT::getVectorVT(MVT::i1, T.getVectorNumElements());431    setOperationAction(ISD::BUILD_VECTOR,       BoolV, Custom);432    setOperationAction(ISD::CONCAT_VECTORS,     BoolV, Custom);433    setOperationAction(ISD::INSERT_SUBVECTOR,   BoolV, Custom);434    setOperationAction(ISD::INSERT_VECTOR_ELT,  BoolV, Custom);435    setOperationAction(ISD::EXTRACT_SUBVECTOR,  BoolV, Custom);436    setOperationAction(ISD::EXTRACT_VECTOR_ELT, BoolV, Custom);437    setOperationAction(ISD::SELECT,             BoolV, Custom);438    setOperationAction(ISD::AND,                BoolV, Legal);439    setOperationAction(ISD::OR,                 BoolV, Legal);440    setOperationAction(ISD::XOR,                BoolV, Legal);441  }442 443  if (Use64b) {444    for (MVT T: {MVT::v32i8, MVT::v32i16, MVT::v16i8, MVT::v16i16, MVT::v16i32})445      setOperationAction(ISD::SIGN_EXTEND_INREG, T, Legal);446  } else {447    for (MVT T: {MVT::v64i8, MVT::v64i16, MVT::v32i8, MVT::v32i16, MVT::v32i32})448      setOperationAction(ISD::SIGN_EXTEND_INREG, T, Legal);449  }450 451  // Handle store widening for short vectors.452  unsigned HwLen = Subtarget.getVectorLength();453  for (MVT ElemTy : Subtarget.getHVXElementTypes()) {454    if (ElemTy == MVT::i1)455      continue;456    int ElemWidth = ElemTy.getFixedSizeInBits();457    int MaxElems = (8*HwLen) / ElemWidth;458    for (int N = 2; N < MaxElems; N *= 2) {459      MVT VecTy = MVT::getVectorVT(ElemTy, N);460      auto Action = getPreferredVectorAction(VecTy);461      if (Action == TargetLoweringBase::TypeWidenVector) {462        setOperationAction(ISD::LOAD,         VecTy, Custom);463        setOperationAction(ISD::STORE,        VecTy, Custom);464        setOperationAction(ISD::SETCC,        VecTy, Custom);465        setOperationAction(ISD::TRUNCATE,     VecTy, Custom);466        setOperationAction(ISD::ANY_EXTEND,   VecTy, Custom);467        setOperationAction(ISD::SIGN_EXTEND,  VecTy, Custom);468        setOperationAction(ISD::ZERO_EXTEND,  VecTy, Custom);469        if (Subtarget.useHVXFloatingPoint()) {470          setOperationAction(ISD::FP_TO_SINT,   VecTy, Custom);471          setOperationAction(ISD::FP_TO_UINT,   VecTy, Custom);472          setOperationAction(ISD::SINT_TO_FP,   VecTy, Custom);473          setOperationAction(ISD::UINT_TO_FP,   VecTy, Custom);474        }475 476        MVT BoolTy = MVT::getVectorVT(MVT::i1, N);477        if (!isTypeLegal(BoolTy))478          setOperationAction(ISD::SETCC, BoolTy, Custom);479      }480    }481  }482 483  // Include cases which are not hander earlier484  setOperationAction(ISD::UINT_TO_FP, MVT::v32i1, Custom);485  setOperationAction(ISD::UINT_TO_FP, MVT::v64i1, Custom);486  setOperationAction(ISD::SINT_TO_FP, MVT::v32i1, Custom);487 488  setTargetDAGCombine({ISD::CONCAT_VECTORS, ISD::TRUNCATE, ISD::VSELECT});489}490 491unsigned492HexagonTargetLowering::getPreferredHvxVectorAction(MVT VecTy) const {493  // Early exit for invalid input types494  if (!VecTy.isVector())495    return ~0u;496 497  MVT ElemTy = VecTy.getVectorElementType();498  unsigned VecLen = VecTy.getVectorNumElements();499  unsigned HwLen = Subtarget.getVectorLength();500 501  // Split vectors of i1 that exceed byte vector length.502  if (ElemTy == MVT::i1 && VecLen > HwLen)503    return TargetLoweringBase::TypeSplitVector;504 505  ArrayRef<MVT> Tys = Subtarget.getHVXElementTypes();506  // For shorter vectors of i1, widen them if any of the corresponding507  // vectors of integers needs to be widened.508  if (ElemTy == MVT::i1) {509    for (MVT T : Tys) {510      assert(T != MVT::i1);511      auto A = getPreferredHvxVectorAction(MVT::getVectorVT(T, VecLen));512      if (A != ~0u)513        return A;514    }515    return ~0u;516  }517 518  // If the size of VecTy is at least half of the vector length,519  // widen the vector. Note: the threshold was not selected in520  // any scientific way.521  if (llvm::is_contained(Tys, ElemTy)) {522    unsigned VecWidth = VecTy.getSizeInBits();523    unsigned HwWidth = 8*HwLen;524    if (VecWidth > 2*HwWidth)525      return TargetLoweringBase::TypeSplitVector;526 527    bool HaveThreshold = HvxWidenThreshold.getNumOccurrences() > 0;528    if (HaveThreshold && 8*HvxWidenThreshold <= VecWidth)529      return TargetLoweringBase::TypeWidenVector;530    if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)531      return TargetLoweringBase::TypeWidenVector;532  }533 534  // Defer to default.535  return ~0u;536}537 538unsigned539HexagonTargetLowering::getCustomHvxOperationAction(SDNode &Op) const {540  unsigned Opc = Op.getOpcode();541  switch (Opc) {542  case HexagonISD::SMUL_LOHI:543  case HexagonISD::UMUL_LOHI:544  case HexagonISD::USMUL_LOHI:545    return TargetLoweringBase::Custom;546  }547  return TargetLoweringBase::Legal;548}549 550SDValue551HexagonTargetLowering::getInt(unsigned IntId, MVT ResTy, ArrayRef<SDValue> Ops,552                              const SDLoc &dl, SelectionDAG &DAG) const {553  SmallVector<SDValue,4> IntOps;554  IntOps.push_back(DAG.getConstant(IntId, dl, MVT::i32));555  append_range(IntOps, Ops);556  return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, ResTy, IntOps);557}558 559MVT560HexagonTargetLowering::typeJoin(const TypePair &Tys) const {561  assert(Tys.first.getVectorElementType() == Tys.second.getVectorElementType());562 563  MVT ElemTy = Tys.first.getVectorElementType();564  return MVT::getVectorVT(ElemTy, Tys.first.getVectorNumElements() +565                                  Tys.second.getVectorNumElements());566}567 568HexagonTargetLowering::TypePair569HexagonTargetLowering::typeSplit(MVT VecTy) const {570  assert(VecTy.isVector());571  unsigned NumElem = VecTy.getVectorNumElements();572  assert((NumElem % 2) == 0 && "Expecting even-sized vector type");573  MVT HalfTy = MVT::getVectorVT(VecTy.getVectorElementType(), NumElem/2);574  return { HalfTy, HalfTy };575}576 577MVT578HexagonTargetLowering::typeExtElem(MVT VecTy, unsigned Factor) const {579  MVT ElemTy = VecTy.getVectorElementType();580  MVT NewElemTy = MVT::getIntegerVT(ElemTy.getSizeInBits() * Factor);581  return MVT::getVectorVT(NewElemTy, VecTy.getVectorNumElements());582}583 584MVT585HexagonTargetLowering::typeTruncElem(MVT VecTy, unsigned Factor) const {586  MVT ElemTy = VecTy.getVectorElementType();587  MVT NewElemTy = MVT::getIntegerVT(ElemTy.getSizeInBits() / Factor);588  return MVT::getVectorVT(NewElemTy, VecTy.getVectorNumElements());589}590 591SDValue592HexagonTargetLowering::opCastElem(SDValue Vec, MVT ElemTy,593                                  SelectionDAG &DAG) const {594  if (ty(Vec).getVectorElementType() == ElemTy)595    return Vec;596  MVT CastTy = tyVector(Vec.getValueType().getSimpleVT(), ElemTy);597  return DAG.getBitcast(CastTy, Vec);598}599 600SDValue601HexagonTargetLowering::opJoin(const VectorPair &Ops, const SDLoc &dl,602                              SelectionDAG &DAG) const {603  return DAG.getNode(ISD::CONCAT_VECTORS, dl, typeJoin(ty(Ops)),604                     Ops.first, Ops.second);605}606 607HexagonTargetLowering::VectorPair608HexagonTargetLowering::opSplit(SDValue Vec, const SDLoc &dl,609                               SelectionDAG &DAG) const {610  TypePair Tys = typeSplit(ty(Vec));611  if (Vec.getOpcode() == HexagonISD::QCAT)612    return VectorPair(Vec.getOperand(0), Vec.getOperand(1));613  return DAG.SplitVector(Vec, dl, Tys.first, Tys.second);614}615 616bool617HexagonTargetLowering::isHvxSingleTy(MVT Ty) const {618  return Subtarget.isHVXVectorType(Ty) &&619         Ty.getSizeInBits() == 8 * Subtarget.getVectorLength();620}621 622bool623HexagonTargetLowering::isHvxPairTy(MVT Ty) const {624  return Subtarget.isHVXVectorType(Ty) &&625         Ty.getSizeInBits() == 16 * Subtarget.getVectorLength();626}627 628bool629HexagonTargetLowering::isHvxBoolTy(MVT Ty) const {630  return Subtarget.isHVXVectorType(Ty, true) &&631         Ty.getVectorElementType() == MVT::i1;632}633 634bool HexagonTargetLowering::allowsHvxMemoryAccess(635    MVT VecTy, MachineMemOperand::Flags Flags, unsigned *Fast) const {636  // Bool vectors are excluded by default, but make it explicit to637  // emphasize that bool vectors cannot be loaded or stored.638  // Also, disallow double vector stores (to prevent unnecessary639  // store widening in DAG combiner).640  if (VecTy.getSizeInBits() > 8*Subtarget.getVectorLength())641    return false;642  if (!Subtarget.isHVXVectorType(VecTy, /*IncludeBool=*/false))643    return false;644  if (Fast)645    *Fast = 1;646  return true;647}648 649bool HexagonTargetLowering::allowsHvxMisalignedMemoryAccesses(650    MVT VecTy, MachineMemOperand::Flags Flags, unsigned *Fast) const {651  if (!Subtarget.isHVXVectorType(VecTy))652    return false;653  // XXX Should this be false?  vmemu are a bit slower than vmem.654  if (Fast)655    *Fast = 1;656  return true;657}658 659void HexagonTargetLowering::AdjustHvxInstrPostInstrSelection(660    MachineInstr &MI, SDNode *Node) const {661  unsigned Opc = MI.getOpcode();662  const TargetInstrInfo &TII = *Subtarget.getInstrInfo();663  MachineBasicBlock &MB = *MI.getParent();664  MachineFunction &MF = *MB.getParent();665  MachineRegisterInfo &MRI = MF.getRegInfo();666  DebugLoc DL = MI.getDebugLoc();667  auto At = MI.getIterator();668 669  switch (Opc) {670  case Hexagon::PS_vsplatib:671    if (Subtarget.useHVXV62Ops()) {672      // SplatV = A2_tfrsi #imm673      // OutV = V6_lvsplatb SplatV674      Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);675      BuildMI(MB, At, DL, TII.get(Hexagon::A2_tfrsi), SplatV)676        .add(MI.getOperand(1));677      Register OutV = MI.getOperand(0).getReg();678      BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplatb), OutV)679        .addReg(SplatV);680    } else {681      // SplatV = A2_tfrsi #imm:#imm:#imm:#imm682      // OutV = V6_lvsplatw SplatV683      Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);684      const MachineOperand &InpOp = MI.getOperand(1);685      assert(InpOp.isImm());686      uint32_t V = InpOp.getImm() & 0xFF;687      BuildMI(MB, At, DL, TII.get(Hexagon::A2_tfrsi), SplatV)688          .addImm(V << 24 | V << 16 | V << 8 | V);689      Register OutV = MI.getOperand(0).getReg();690      BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplatw), OutV).addReg(SplatV);691    }692    MB.erase(At);693    break;694  case Hexagon::PS_vsplatrb:695    if (Subtarget.useHVXV62Ops()) {696      // OutV = V6_lvsplatb Inp697      Register OutV = MI.getOperand(0).getReg();698      BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplatb), OutV)699        .add(MI.getOperand(1));700    } else {701      Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);702      const MachineOperand &InpOp = MI.getOperand(1);703      BuildMI(MB, At, DL, TII.get(Hexagon::S2_vsplatrb), SplatV)704          .addReg(InpOp.getReg(), 0, InpOp.getSubReg());705      Register OutV = MI.getOperand(0).getReg();706      BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplatw), OutV)707          .addReg(SplatV);708    }709    MB.erase(At);710    break;711  case Hexagon::PS_vsplatih:712    if (Subtarget.useHVXV62Ops()) {713      // SplatV = A2_tfrsi #imm714      // OutV = V6_lvsplath SplatV715      Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);716      BuildMI(MB, At, DL, TII.get(Hexagon::A2_tfrsi), SplatV)717        .add(MI.getOperand(1));718      Register OutV = MI.getOperand(0).getReg();719      BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplath), OutV)720        .addReg(SplatV);721    } else {722      // SplatV = A2_tfrsi #imm:#imm723      // OutV = V6_lvsplatw SplatV724      Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);725      const MachineOperand &InpOp = MI.getOperand(1);726      assert(InpOp.isImm());727      uint32_t V = InpOp.getImm() & 0xFFFF;728      BuildMI(MB, At, DL, TII.get(Hexagon::A2_tfrsi), SplatV)729          .addImm(V << 16 | V);730      Register OutV = MI.getOperand(0).getReg();731      BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplatw), OutV).addReg(SplatV);732    }733    MB.erase(At);734    break;735  case Hexagon::PS_vsplatrh:736    if (Subtarget.useHVXV62Ops()) {737      // OutV = V6_lvsplath Inp738      Register OutV = MI.getOperand(0).getReg();739      BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplath), OutV)740        .add(MI.getOperand(1));741    } else {742      // SplatV = A2_combine_ll Inp, Inp743      // OutV = V6_lvsplatw SplatV744      Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);745      const MachineOperand &InpOp = MI.getOperand(1);746      BuildMI(MB, At, DL, TII.get(Hexagon::A2_combine_ll), SplatV)747          .addReg(InpOp.getReg(), 0, InpOp.getSubReg())748          .addReg(InpOp.getReg(), 0, InpOp.getSubReg());749      Register OutV = MI.getOperand(0).getReg();750      BuildMI(MB, At, DL, TII.get(Hexagon::V6_lvsplatw), OutV).addReg(SplatV);751    }752    MB.erase(At);753    break;754  case Hexagon::PS_vsplatiw:755  case Hexagon::PS_vsplatrw:756    if (Opc == Hexagon::PS_vsplatiw) {757      // SplatV = A2_tfrsi #imm758      Register SplatV = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);759      BuildMI(MB, At, DL, TII.get(Hexagon::A2_tfrsi), SplatV)760        .add(MI.getOperand(1));761      MI.getOperand(1).ChangeToRegister(SplatV, false);762    }763    // OutV = V6_lvsplatw SplatV/Inp764    MI.setDesc(TII.get(Hexagon::V6_lvsplatw));765    break;766  }767}768 769SDValue770HexagonTargetLowering::convertToByteIndex(SDValue ElemIdx, MVT ElemTy,771                                          SelectionDAG &DAG) const {772  if (ElemIdx.getValueType().getSimpleVT() != MVT::i32)773    ElemIdx = DAG.getBitcast(MVT::i32, ElemIdx);774 775  unsigned ElemWidth = ElemTy.getSizeInBits();776  if (ElemWidth == 8)777    return ElemIdx;778 779  unsigned L = Log2_32(ElemWidth/8);780  const SDLoc &dl(ElemIdx);781  return DAG.getNode(ISD::SHL, dl, MVT::i32,782                     {ElemIdx, DAG.getConstant(L, dl, MVT::i32)});783}784 785SDValue786HexagonTargetLowering::getIndexInWord32(SDValue Idx, MVT ElemTy,787                                        SelectionDAG &DAG) const {788  unsigned ElemWidth = ElemTy.getSizeInBits();789  assert(ElemWidth >= 8 && ElemWidth <= 32);790  if (ElemWidth == 32)791    return Idx;792 793  if (ty(Idx) != MVT::i32)794    Idx = DAG.getBitcast(MVT::i32, Idx);795  const SDLoc &dl(Idx);796  SDValue Mask = DAG.getConstant(32/ElemWidth - 1, dl, MVT::i32);797  SDValue SubIdx = DAG.getNode(ISD::AND, dl, MVT::i32, {Idx, Mask});798  return SubIdx;799}800 801SDValue802HexagonTargetLowering::getByteShuffle(const SDLoc &dl, SDValue Op0,803                                      SDValue Op1, ArrayRef<int> Mask,804                                      SelectionDAG &DAG) const {805  MVT OpTy = ty(Op0);806  assert(OpTy == ty(Op1));807 808  MVT ElemTy = OpTy.getVectorElementType();809  if (ElemTy == MVT::i8)810    return DAG.getVectorShuffle(OpTy, dl, Op0, Op1, Mask);811  assert(ElemTy.getSizeInBits() >= 8);812 813  MVT ResTy = tyVector(OpTy, MVT::i8);814  unsigned ElemSize = ElemTy.getSizeInBits() / 8;815 816  SmallVector<int,128> ByteMask;817  for (int M : Mask) {818    if (M < 0) {819      for (unsigned I = 0; I != ElemSize; ++I)820        ByteMask.push_back(-1);821    } else {822      int NewM = M*ElemSize;823      for (unsigned I = 0; I != ElemSize; ++I)824        ByteMask.push_back(NewM+I);825    }826  }827  assert(ResTy.getVectorNumElements() == ByteMask.size());828  return DAG.getVectorShuffle(ResTy, dl, opCastElem(Op0, MVT::i8, DAG),829                              opCastElem(Op1, MVT::i8, DAG), ByteMask);830}831 832SDValue833HexagonTargetLowering::buildHvxVectorReg(ArrayRef<SDValue> Values,834                                         const SDLoc &dl, MVT VecTy,835                                         SelectionDAG &DAG) const {836  unsigned VecLen = Values.size();837  MachineFunction &MF = DAG.getMachineFunction();838  MVT ElemTy = VecTy.getVectorElementType();839  unsigned ElemWidth = ElemTy.getSizeInBits();840  unsigned HwLen = Subtarget.getVectorLength();841 842  unsigned ElemSize = ElemWidth / 8;843  assert(ElemSize*VecLen == HwLen);844  SmallVector<SDValue,32> Words;845 846  if (VecTy.getVectorElementType() != MVT::i32 &&847      !(Subtarget.useHVXFloatingPoint() &&848      VecTy.getVectorElementType() == MVT::f32)) {849    assert((ElemSize == 1 || ElemSize == 2) && "Invalid element size");850    unsigned OpsPerWord = (ElemSize == 1) ? 4 : 2;851    MVT PartVT = MVT::getVectorVT(VecTy.getVectorElementType(), OpsPerWord);852    for (unsigned i = 0; i != VecLen; i += OpsPerWord) {853      SDValue W = buildVector32(Values.slice(i, OpsPerWord), dl, PartVT, DAG);854      Words.push_back(DAG.getBitcast(MVT::i32, W));855    }856  } else {857    for (SDValue V : Values)858      Words.push_back(DAG.getBitcast(MVT::i32, V));859  }860  auto isSplat = [] (ArrayRef<SDValue> Values, SDValue &SplatV) {861    unsigned NumValues = Values.size();862    assert(NumValues > 0);863    bool IsUndef = true;864    for (unsigned i = 0; i != NumValues; ++i) {865      if (Values[i].isUndef())866        continue;867      IsUndef = false;868      if (!SplatV.getNode())869        SplatV = Values[i];870      else if (SplatV != Values[i])871        return false;872    }873    if (IsUndef)874      SplatV = Values[0];875    return true;876  };877 878  unsigned NumWords = Words.size();879  SDValue SplatV;880  bool IsSplat = isSplat(Words, SplatV);881  if (IsSplat && isUndef(SplatV))882    return DAG.getUNDEF(VecTy);883  if (IsSplat) {884    assert(SplatV.getNode());885    if (isNullConstant(SplatV))886      return getZero(dl, VecTy, DAG);887    MVT WordTy = MVT::getVectorVT(MVT::i32, HwLen/4);888    SDValue S = DAG.getNode(ISD::SPLAT_VECTOR, dl, WordTy, SplatV);889    return DAG.getBitcast(VecTy, S);890  }891 892  // Delay recognizing constant vectors until here, so that we can generate893  // a vsplat.894  SmallVector<ConstantInt*, 128> Consts(VecLen);895  bool AllConst = getBuildVectorConstInts(Values, VecTy, DAG, Consts);896  if (AllConst) {897    ArrayRef<Constant*> Tmp((Constant**)Consts.begin(),898                            (Constant**)Consts.end());899    Constant *CV = ConstantVector::get(Tmp);900    Align Alignment(HwLen);901    SDValue CP =902        LowerConstantPool(DAG.getConstantPool(CV, VecTy, Alignment), DAG);903    return DAG.getLoad(VecTy, dl, DAG.getEntryNode(), CP,904                       MachinePointerInfo::getConstantPool(MF), Alignment);905  }906 907  // A special case is a situation where the vector is built entirely from908  // elements extracted from another vector. This could be done via a shuffle909  // more efficiently, but typically, the size of the source vector will not910  // match the size of the vector being built (which precludes the use of a911  // shuffle directly).912  // This only handles a single source vector, and the vector being built913  // should be of a sub-vector type of the source vector type.914  auto IsBuildFromExtracts = [this,&Values] (SDValue &SrcVec,915                                             SmallVectorImpl<int> &SrcIdx) {916    SDValue Vec;917    for (SDValue V : Values) {918      if (isUndef(V)) {919        SrcIdx.push_back(-1);920        continue;921      }922      if (V.getOpcode() != ISD::EXTRACT_VECTOR_ELT)923        return false;924      // All extracts should come from the same vector.925      SDValue T = V.getOperand(0);926      if (Vec.getNode() != nullptr && T.getNode() != Vec.getNode())927        return false;928      Vec = T;929      ConstantSDNode *C = dyn_cast<ConstantSDNode>(V.getOperand(1));930      if (C == nullptr)931        return false;932      int I = C->getSExtValue();933      assert(I >= 0 && "Negative element index");934      SrcIdx.push_back(I);935    }936    SrcVec = Vec;937    return true;938  };939 940  SmallVector<int,128> ExtIdx;941  SDValue ExtVec;942  if (IsBuildFromExtracts(ExtVec, ExtIdx)) {943    MVT ExtTy = ty(ExtVec);944    unsigned ExtLen = ExtTy.getVectorNumElements();945    if (ExtLen == VecLen || ExtLen == 2*VecLen) {946      // Construct a new shuffle mask that will produce a vector with the same947      // number of elements as the input vector, and such that the vector we948      // want will be the initial subvector of it.949      SmallVector<int,128> Mask;950      BitVector Used(ExtLen);951 952      for (int M : ExtIdx) {953        Mask.push_back(M);954        if (M >= 0)955          Used.set(M);956      }957      // Fill the rest of the mask with the unused elements of ExtVec in hopes958      // that it will result in a permutation of ExtVec's elements. It's still959      // fine if it doesn't (e.g. if undefs are present, or elements are960      // repeated), but permutations can always be done efficiently via vdelta961      // and vrdelta.962      for (unsigned I = 0; I != ExtLen; ++I) {963        if (Mask.size() == ExtLen)964          break;965        if (!Used.test(I))966          Mask.push_back(I);967      }968 969      SDValue S = DAG.getVectorShuffle(ExtTy, dl, ExtVec,970                                       DAG.getUNDEF(ExtTy), Mask);971      return ExtLen == VecLen ? S : LoHalf(S, DAG);972    }973  }974 975  // Find most common element to initialize vector with. This is to avoid976  // unnecessary vinsert/valign for cases where the same value is present977  // many times. Creates a histogram of the vector's elements to find the978  // most common element n.979  assert(4*Words.size() == Subtarget.getVectorLength());980  int VecHist[32];981  int n = 0;982  for (unsigned i = 0; i != NumWords; ++i) {983    VecHist[i] = 0;984    if (Words[i].isUndef())985      continue;986    for (unsigned j = i; j != NumWords; ++j)987      if (Words[i] == Words[j])988        VecHist[i]++;989 990    if (VecHist[i] > VecHist[n])991      n = i;992  }993 994  SDValue HalfV = getZero(dl, VecTy, DAG);995  if (VecHist[n] > 1) {996    SDValue SplatV = DAG.getNode(ISD::SPLAT_VECTOR, dl, VecTy, Words[n]);997    HalfV = DAG.getNode(HexagonISD::VALIGN, dl, VecTy,998                       {HalfV, SplatV, DAG.getConstant(HwLen/2, dl, MVT::i32)});999  }1000  SDValue HalfV0 = HalfV;1001  SDValue HalfV1 = HalfV;1002 1003  // Construct two halves in parallel, then or them together. Rn and Rm count1004  // number of rotations needed before the next element. One last rotation is1005  // performed post-loop to position the last element.1006  int Rn = 0, Rm = 0;1007  SDValue Sn, Sm;1008  SDValue N = HalfV0;1009  SDValue M = HalfV1;1010  for (unsigned i = 0; i != NumWords/2; ++i) {1011    // Rotate by element count since last insertion.1012    if (Words[i] != Words[n] || VecHist[n] <= 1) {1013      Sn = DAG.getConstant(Rn, dl, MVT::i32);1014      HalfV0 = DAG.getNode(HexagonISD::VROR, dl, VecTy, {N, Sn});1015      N = DAG.getNode(HexagonISD::VINSERTW0, dl, VecTy,1016                      {HalfV0, Words[i]});1017      Rn = 0;1018    }1019    if (Words[i+NumWords/2] != Words[n] || VecHist[n] <= 1) {1020      Sm = DAG.getConstant(Rm, dl, MVT::i32);1021      HalfV1 = DAG.getNode(HexagonISD::VROR, dl, VecTy, {M, Sm});1022      M = DAG.getNode(HexagonISD::VINSERTW0, dl, VecTy,1023                      {HalfV1, Words[i+NumWords/2]});1024      Rm = 0;1025    }1026    Rn += 4;1027    Rm += 4;1028  }1029  // Perform last rotation.1030  Sn = DAG.getConstant(Rn+HwLen/2, dl, MVT::i32);1031  Sm = DAG.getConstant(Rm, dl, MVT::i32);1032  HalfV0 = DAG.getNode(HexagonISD::VROR, dl, VecTy, {N, Sn});1033  HalfV1 = DAG.getNode(HexagonISD::VROR, dl, VecTy, {M, Sm});1034 1035  SDValue T0 = DAG.getBitcast(tyVector(VecTy, MVT::i32), HalfV0);1036  SDValue T1 = DAG.getBitcast(tyVector(VecTy, MVT::i32), HalfV1);1037 1038  SDValue DstV = DAG.getNode(ISD::OR, dl, ty(T0), {T0, T1});1039 1040  SDValue OutV =1041      DAG.getBitcast(tyVector(ty(DstV), VecTy.getVectorElementType()), DstV);1042  return OutV;1043}1044 1045SDValue1046HexagonTargetLowering::createHvxPrefixPred(SDValue PredV, const SDLoc &dl,1047      unsigned BitBytes, bool ZeroFill, SelectionDAG &DAG) const {1048  MVT PredTy = ty(PredV);1049  unsigned HwLen = Subtarget.getVectorLength();1050  MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);1051 1052  if (Subtarget.isHVXVectorType(PredTy, true)) {1053    // Move the vector predicate SubV to a vector register, and scale it1054    // down to match the representation (bytes per type element) that VecV1055    // uses. The scaling down will pick every 2nd or 4th (every Scale-th1056    // in general) element and put them at the front of the resulting1057    // vector. This subvector will then be inserted into the Q2V of VecV.1058    // To avoid having an operation that generates an illegal type (short1059    // vector), generate a full size vector.1060    //1061    SDValue T = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, PredV);1062    SmallVector<int,128> Mask(HwLen);1063    // Scale = BitBytes(PredV) / Given BitBytes.1064    unsigned Scale = HwLen / (PredTy.getVectorNumElements() * BitBytes);1065    unsigned BlockLen = PredTy.getVectorNumElements() * BitBytes;1066 1067    for (unsigned i = 0; i != HwLen; ++i) {1068      unsigned Num = i % Scale;1069      unsigned Off = i / Scale;1070      Mask[BlockLen*Num + Off] = i;1071    }1072    SDValue S = DAG.getVectorShuffle(ByteTy, dl, T, DAG.getUNDEF(ByteTy), Mask);1073    if (!ZeroFill)1074      return S;1075    // Fill the bytes beyond BlockLen with 0s.1076    // V6_pred_scalar2 cannot fill the entire predicate, so it only works1077    // when BlockLen < HwLen.1078    assert(BlockLen < HwLen && "vsetq(v1) prerequisite");1079    MVT BoolTy = MVT::getVectorVT(MVT::i1, HwLen);1080    SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,1081                         {DAG.getConstant(BlockLen, dl, MVT::i32)}, DAG);1082    SDValue M = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, Q);1083    return DAG.getNode(ISD::AND, dl, ByteTy, S, M);1084  }1085 1086  // Make sure that this is a valid scalar predicate.1087  assert(PredTy == MVT::v2i1 || PredTy == MVT::v4i1 || PredTy == MVT::v8i1);1088 1089  unsigned Bytes = 8 / PredTy.getVectorNumElements();1090  SmallVector<SDValue,4> Words[2];1091  unsigned IdxW = 0;1092 1093  SDValue W0 = isUndef(PredV)1094                  ? DAG.getUNDEF(MVT::i64)1095                  : DAG.getNode(HexagonISD::P2D, dl, MVT::i64, PredV);1096  if (Bytes < BitBytes) {1097    Words[IdxW].push_back(HiHalf(W0, DAG));1098    Words[IdxW].push_back(LoHalf(W0, DAG));1099  } else1100    Words[IdxW].push_back(W0);1101 1102  while (Bytes < BitBytes) {1103    IdxW ^= 1;1104    Words[IdxW].clear();1105 1106    if (Bytes < 4) {1107      for (const SDValue &W : Words[IdxW ^ 1]) {1108        SDValue T = expandPredicate(W, dl, DAG);1109        Words[IdxW].push_back(HiHalf(T, DAG));1110        Words[IdxW].push_back(LoHalf(T, DAG));1111      }1112    } else {1113      for (const SDValue &W : Words[IdxW ^ 1]) {1114        Words[IdxW].push_back(W);1115        Words[IdxW].push_back(W);1116      }1117    }1118    Bytes *= 2;1119  }1120 1121  while (Bytes > BitBytes) {1122    IdxW ^= 1;1123    Words[IdxW].clear();1124 1125    if (Bytes <= 4) {1126      for (const SDValue &W : Words[IdxW ^ 1]) {1127        SDValue T = contractPredicate(W, dl, DAG);1128        Words[IdxW].push_back(T);1129      }1130    } else {1131      for (const SDValue &W : Words[IdxW ^ 1]) {1132        Words[IdxW].push_back(W);1133      }1134    }1135    Bytes /= 2;1136  }1137 1138  assert(Bytes == BitBytes);1139  if (BitBytes == 1 && PredTy == MVT::v2i1)1140    ByteTy = MVT::getVectorVT(MVT::i16, HwLen);1141 1142  SDValue Vec = ZeroFill ? getZero(dl, ByteTy, DAG) : DAG.getUNDEF(ByteTy);1143  SDValue S4 = DAG.getConstant(HwLen-4, dl, MVT::i32);1144  for (const SDValue &W : Words[IdxW]) {1145    Vec = DAG.getNode(HexagonISD::VROR, dl, ByteTy, Vec, S4);1146    Vec = DAG.getNode(HexagonISD::VINSERTW0, dl, ByteTy, Vec, W);1147  }1148 1149  return Vec;1150}1151 1152SDValue1153HexagonTargetLowering::buildHvxVectorPred(ArrayRef<SDValue> Values,1154                                          const SDLoc &dl, MVT VecTy,1155                                          SelectionDAG &DAG) const {1156  // Construct a vector V of bytes, such that a comparison V >u 0 would1157  // produce the required vector predicate.1158  unsigned VecLen = Values.size();1159  unsigned HwLen = Subtarget.getVectorLength();1160  assert(VecLen <= HwLen || VecLen == 8*HwLen);1161  SmallVector<SDValue,128> Bytes;1162  bool AllT = true, AllF = true;1163 1164  auto IsTrue = [] (SDValue V) {1165    if (const auto *N = dyn_cast<ConstantSDNode>(V.getNode()))1166      return !N->isZero();1167    return false;1168  };1169  auto IsFalse = [] (SDValue V) {1170    if (const auto *N = dyn_cast<ConstantSDNode>(V.getNode()))1171      return N->isZero();1172    return false;1173  };1174 1175  if (VecLen <= HwLen) {1176    // In the hardware, each bit of a vector predicate corresponds to a byte1177    // of a vector register. Calculate how many bytes does a bit of VecTy1178    // correspond to.1179    assert(HwLen % VecLen == 0);1180    unsigned BitBytes = HwLen / VecLen;1181    for (SDValue V : Values) {1182      AllT &= IsTrue(V);1183      AllF &= IsFalse(V);1184 1185      SDValue Ext = !V.isUndef() ? DAG.getZExtOrTrunc(V, dl, MVT::i8)1186                                 : DAG.getUNDEF(MVT::i8);1187      for (unsigned B = 0; B != BitBytes; ++B)1188        Bytes.push_back(Ext);1189    }1190  } else {1191    // There are as many i1 values, as there are bits in a vector register.1192    // Divide the values into groups of 8 and check that each group consists1193    // of the same value (ignoring undefs).1194    for (unsigned I = 0; I != VecLen; I += 8) {1195      unsigned B = 0;1196      // Find the first non-undef value in this group.1197      for (; B != 8; ++B) {1198        if (!Values[I+B].isUndef())1199          break;1200      }1201      SDValue F = Values[I+B];1202      AllT &= IsTrue(F);1203      AllF &= IsFalse(F);1204 1205      SDValue Ext = (B < 8) ? DAG.getZExtOrTrunc(F, dl, MVT::i8)1206                            : DAG.getUNDEF(MVT::i8);1207      Bytes.push_back(Ext);1208      // Verify that the rest of values in the group are the same as the1209      // first.1210      for (; B != 8; ++B)1211        assert(Values[I+B].isUndef() || Values[I+B] == F);1212    }1213  }1214 1215  if (AllT)1216    return DAG.getNode(HexagonISD::QTRUE, dl, VecTy);1217  if (AllF)1218    return DAG.getNode(HexagonISD::QFALSE, dl, VecTy);1219 1220  MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);1221  SDValue ByteVec = buildHvxVectorReg(Bytes, dl, ByteTy, DAG);1222  return DAG.getNode(HexagonISD::V2Q, dl, VecTy, ByteVec);1223}1224 1225SDValue1226HexagonTargetLowering::extractHvxElementReg(SDValue VecV, SDValue IdxV,1227      const SDLoc &dl, MVT ResTy, SelectionDAG &DAG) const {1228  MVT ElemTy = ty(VecV).getVectorElementType();1229 1230  unsigned ElemWidth = ElemTy.getSizeInBits();1231  assert(ElemWidth >= 8 && ElemWidth <= 32);1232  (void)ElemWidth;1233 1234  SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);1235  SDValue ExWord = DAG.getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,1236                               {VecV, ByteIdx});1237  if (ElemTy == MVT::i32)1238    return ExWord;1239 1240  // Have an extracted word, need to extract the smaller element out of it.1241  // 1. Extract the bits of (the original) IdxV that correspond to the index1242  //    of the desired element in the 32-bit word.1243  SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);1244  // 2. Extract the element from the word.1245  SDValue ExVec = DAG.getBitcast(tyVector(ty(ExWord), ElemTy), ExWord);1246  return extractVector(ExVec, SubIdx, dl, ElemTy, MVT::i32, DAG);1247}1248 1249SDValue1250HexagonTargetLowering::extractHvxElementPred(SDValue VecV, SDValue IdxV,1251      const SDLoc &dl, MVT ResTy, SelectionDAG &DAG) const {1252  // Implement other return types if necessary.1253  assert(ResTy == MVT::i1);1254 1255  unsigned HwLen = Subtarget.getVectorLength();1256  MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);1257  SDValue ByteVec = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, VecV);1258 1259  unsigned Scale = HwLen / ty(VecV).getVectorNumElements();1260  SDValue ScV = DAG.getConstant(Scale, dl, MVT::i32);1261  IdxV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, ScV);1262 1263  SDValue ExtB = extractHvxElementReg(ByteVec, IdxV, dl, MVT::i32, DAG);1264  SDValue Zero = DAG.getTargetConstant(0, dl, MVT::i32);1265  return getInstr(Hexagon::C2_cmpgtui, dl, MVT::i1, {ExtB, Zero}, DAG);1266}1267 1268SDValue1269HexagonTargetLowering::insertHvxElementReg(SDValue VecV, SDValue IdxV,1270      SDValue ValV, const SDLoc &dl, SelectionDAG &DAG) const {1271  MVT ElemTy = ty(VecV).getVectorElementType();1272 1273  unsigned ElemWidth = ElemTy.getSizeInBits();1274  assert(ElemWidth >= 8 && ElemWidth <= 32);1275  (void)ElemWidth;1276 1277  auto InsertWord = [&DAG,&dl,this] (SDValue VecV, SDValue ValV,1278                                     SDValue ByteIdxV) {1279    MVT VecTy = ty(VecV);1280    unsigned HwLen = Subtarget.getVectorLength();1281    SDValue MaskV =1282        DAG.getNode(ISD::AND, dl, MVT::i32,1283                    {ByteIdxV, DAG.getSignedConstant(-4, dl, MVT::i32)});1284    SDValue RotV = DAG.getNode(HexagonISD::VROR, dl, VecTy, {VecV, MaskV});1285    SDValue InsV = DAG.getNode(HexagonISD::VINSERTW0, dl, VecTy, {RotV, ValV});1286    SDValue SubV = DAG.getNode(ISD::SUB, dl, MVT::i32,1287                               {DAG.getConstant(HwLen, dl, MVT::i32), MaskV});1288    SDValue TorV = DAG.getNode(HexagonISD::VROR, dl, VecTy, {InsV, SubV});1289    return TorV;1290  };1291 1292  SDValue ByteIdx = convertToByteIndex(IdxV, ElemTy, DAG);1293  if (ElemTy == MVT::i32)1294    return InsertWord(VecV, ValV, ByteIdx);1295 1296  // If this is not inserting a 32-bit word, convert it into such a thing.1297  // 1. Extract the existing word from the target vector.1298  SDValue WordIdx = DAG.getNode(ISD::SRL, dl, MVT::i32,1299                                {ByteIdx, DAG.getConstant(2, dl, MVT::i32)});1300  SDValue Ext = extractHvxElementReg(opCastElem(VecV, MVT::i32, DAG), WordIdx,1301                                     dl, MVT::i32, DAG);1302 1303  // 2. Treating the extracted word as a 32-bit vector, insert the given1304  //    value into it.1305  SDValue SubIdx = getIndexInWord32(IdxV, ElemTy, DAG);1306  MVT SubVecTy = tyVector(ty(Ext), ElemTy);1307  SDValue Ins = insertVector(DAG.getBitcast(SubVecTy, Ext),1308                             ValV, SubIdx, dl, ElemTy, DAG);1309 1310  // 3. Insert the 32-bit word back into the original vector.1311  return InsertWord(VecV, Ins, ByteIdx);1312}1313 1314SDValue1315HexagonTargetLowering::insertHvxElementPred(SDValue VecV, SDValue IdxV,1316      SDValue ValV, const SDLoc &dl, SelectionDAG &DAG) const {1317  unsigned HwLen = Subtarget.getVectorLength();1318  MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);1319  SDValue ByteVec = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, VecV);1320 1321  unsigned Scale = HwLen / ty(VecV).getVectorNumElements();1322  SDValue ScV = DAG.getConstant(Scale, dl, MVT::i32);1323  IdxV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, ScV);1324  ValV = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i32, ValV);1325 1326  SDValue InsV = insertHvxElementReg(ByteVec, IdxV, ValV, dl, DAG);1327  return DAG.getNode(HexagonISD::V2Q, dl, ty(VecV), InsV);1328}1329 1330SDValue1331HexagonTargetLowering::extractHvxSubvectorReg(SDValue OrigOp, SDValue VecV,1332      SDValue IdxV, const SDLoc &dl, MVT ResTy, SelectionDAG &DAG) const {1333  MVT VecTy = ty(VecV);1334  unsigned HwLen = Subtarget.getVectorLength();1335  unsigned Idx = IdxV.getNode()->getAsZExtVal();1336  MVT ElemTy = VecTy.getVectorElementType();1337  unsigned ElemWidth = ElemTy.getSizeInBits();1338 1339  // If the source vector is a vector pair, get the single vector containing1340  // the subvector of interest. The subvector will never overlap two single1341  // vectors.1342  if (isHvxPairTy(VecTy)) {1343    unsigned SubIdx = Hexagon::vsub_lo;1344    if (Idx * ElemWidth >= 8 * HwLen) {1345      SubIdx = Hexagon::vsub_hi;1346      Idx -= VecTy.getVectorNumElements() / 2;1347    }1348 1349    VecTy = typeSplit(VecTy).first;1350    VecV = DAG.getTargetExtractSubreg(SubIdx, dl, VecTy, VecV);1351    if (VecTy == ResTy)1352      return VecV;1353  }1354 1355  // The only meaningful subvectors of a single HVX vector are those that1356  // fit in a scalar register.1357  assert(ResTy.getSizeInBits() == 32 || ResTy.getSizeInBits() == 64);1358 1359  MVT WordTy = tyVector(VecTy, MVT::i32);1360  SDValue WordVec = DAG.getBitcast(WordTy, VecV);1361  unsigned WordIdx = (Idx*ElemWidth) / 32;1362 1363  SDValue W0Idx = DAG.getConstant(WordIdx, dl, MVT::i32);1364  SDValue W0 = extractHvxElementReg(WordVec, W0Idx, dl, MVT::i32, DAG);1365  if (ResTy.getSizeInBits() == 32)1366    return DAG.getBitcast(ResTy, W0);1367 1368  SDValue W1Idx = DAG.getConstant(WordIdx+1, dl, MVT::i32);1369  SDValue W1 = extractHvxElementReg(WordVec, W1Idx, dl, MVT::i32, DAG);1370  SDValue WW = getCombine(W1, W0, dl, MVT::i64, DAG);1371  return DAG.getBitcast(ResTy, WW);1372}1373 1374SDValue1375HexagonTargetLowering::extractHvxSubvectorPred(SDValue VecV, SDValue IdxV,1376      const SDLoc &dl, MVT ResTy, SelectionDAG &DAG) const {1377  MVT VecTy = ty(VecV);1378  unsigned HwLen = Subtarget.getVectorLength();1379  MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);1380  SDValue ByteVec = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, VecV);1381  // IdxV is required to be a constant.1382  unsigned Idx = IdxV.getNode()->getAsZExtVal();1383 1384  unsigned ResLen = ResTy.getVectorNumElements();1385  unsigned BitBytes = HwLen / VecTy.getVectorNumElements();1386  unsigned Offset = Idx * BitBytes;1387  SDValue Undef = DAG.getUNDEF(ByteTy);1388  SmallVector<int,128> Mask;1389 1390  if (Subtarget.isHVXVectorType(ResTy, true)) {1391    // Converting between two vector predicates. Since the result is shorter1392    // than the source, it will correspond to a vector predicate with the1393    // relevant bits replicated. The replication count is the ratio of the1394    // source and target vector lengths.1395    unsigned Rep = VecTy.getVectorNumElements() / ResLen;1396    assert(isPowerOf2_32(Rep) && HwLen % Rep == 0);1397    for (unsigned i = 0; i != HwLen/Rep; ++i) {1398      for (unsigned j = 0; j != Rep; ++j)1399        Mask.push_back(i + Offset);1400    }1401    SDValue ShuffV = DAG.getVectorShuffle(ByteTy, dl, ByteVec, Undef, Mask);1402    return DAG.getNode(HexagonISD::V2Q, dl, ResTy, ShuffV);1403  }1404 1405  // Converting between a vector predicate and a scalar predicate. In the1406  // vector predicate, a group of BitBytes bits will correspond to a single1407  // i1 element of the source vector type. Those bits will all have the same1408  // value. The same will be true for ByteVec, where each byte corresponds1409  // to a bit in the vector predicate.1410  // The algorithm is to traverse the ByteVec, going over the i1 values from1411  // the source vector, and generate the corresponding representation in an1412  // 8-byte vector. To avoid repeated extracts from ByteVec, shuffle the1413  // elements so that the interesting 8 bytes will be in the low end of the1414  // vector.1415  unsigned Rep = 8 / ResLen;1416  // Make sure the output fill the entire vector register, so repeat the1417  // 8-byte groups as many times as necessary.1418  for (unsigned r = 0; r != HwLen/ResLen; ++r) {1419    // This will generate the indexes of the 8 interesting bytes.1420    for (unsigned i = 0; i != ResLen; ++i) {1421      for (unsigned j = 0; j != Rep; ++j)1422        Mask.push_back(Offset + i*BitBytes);1423    }1424  }1425 1426  SDValue Zero = getZero(dl, MVT::i32, DAG);1427  SDValue ShuffV = DAG.getVectorShuffle(ByteTy, dl, ByteVec, Undef, Mask);1428  // Combine the two low words from ShuffV into a v8i8, and byte-compare1429  // them against 0.1430  SDValue W0 = DAG.getNode(HexagonISD::VEXTRACTW, dl, MVT::i32, {ShuffV, Zero});1431  SDValue W1 = DAG.getNode(HexagonISD::VEXTRACTW, dl, MVT::i32,1432                           {ShuffV, DAG.getConstant(4, dl, MVT::i32)});1433  SDValue Vec64 = getCombine(W1, W0, dl, MVT::v8i8, DAG);1434  return getInstr(Hexagon::A4_vcmpbgtui, dl, ResTy,1435                  {Vec64, DAG.getTargetConstant(0, dl, MVT::i32)}, DAG);1436}1437 1438SDValue1439HexagonTargetLowering::insertHvxSubvectorReg(SDValue VecV, SDValue SubV,1440      SDValue IdxV, const SDLoc &dl, SelectionDAG &DAG) const {1441  MVT VecTy = ty(VecV);1442  MVT SubTy = ty(SubV);1443  unsigned HwLen = Subtarget.getVectorLength();1444  MVT ElemTy = VecTy.getVectorElementType();1445  unsigned ElemWidth = ElemTy.getSizeInBits();1446 1447  bool IsPair = isHvxPairTy(VecTy);1448  MVT SingleTy = MVT::getVectorVT(ElemTy, (8*HwLen)/ElemWidth);1449  // The two single vectors that VecV consists of, if it's a pair.1450  SDValue V0, V1;1451  SDValue SingleV = VecV;1452  SDValue PickHi;1453 1454  if (IsPair) {1455    V0 = LoHalf(VecV, DAG);1456    V1 = HiHalf(VecV, DAG);1457 1458    SDValue HalfV = DAG.getConstant(SingleTy.getVectorNumElements(),1459                                    dl, MVT::i32);1460    PickHi = DAG.getSetCC(dl, MVT::i1, IdxV, HalfV, ISD::SETUGT);1461    if (isHvxSingleTy(SubTy)) {1462      if (const auto *CN = dyn_cast<const ConstantSDNode>(IdxV.getNode())) {1463        unsigned Idx = CN->getZExtValue();1464        assert(Idx == 0 || Idx == VecTy.getVectorNumElements()/2);1465        unsigned SubIdx = (Idx == 0) ? Hexagon::vsub_lo : Hexagon::vsub_hi;1466        return DAG.getTargetInsertSubreg(SubIdx, dl, VecTy, VecV, SubV);1467      }1468      // If IdxV is not a constant, generate the two variants: with the1469      // SubV as the high and as the low subregister, and select the right1470      // pair based on the IdxV.1471      SDValue InLo = DAG.getNode(ISD::CONCAT_VECTORS, dl, VecTy, {SubV, V1});1472      SDValue InHi = DAG.getNode(ISD::CONCAT_VECTORS, dl, VecTy, {V0, SubV});1473      return DAG.getNode(ISD::SELECT, dl, VecTy, PickHi, InHi, InLo);1474    }1475    // The subvector being inserted must be entirely contained in one of1476    // the vectors V0 or V1. Set SingleV to the correct one, and update1477    // IdxV to be the index relative to the beginning of that vector.1478    SDValue S = DAG.getNode(ISD::SUB, dl, MVT::i32, IdxV, HalfV);1479    IdxV = DAG.getNode(ISD::SELECT, dl, MVT::i32, PickHi, S, IdxV);1480    SingleV = DAG.getNode(ISD::SELECT, dl, SingleTy, PickHi, V1, V0);1481  }1482 1483  // The only meaningful subvectors of a single HVX vector are those that1484  // fit in a scalar register.1485  assert(SubTy.getSizeInBits() == 32 || SubTy.getSizeInBits() == 64);1486  // Convert IdxV to be index in bytes.1487  auto *IdxN = dyn_cast<ConstantSDNode>(IdxV.getNode());1488  if (!IdxN || !IdxN->isZero()) {1489    IdxV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV,1490                       DAG.getConstant(ElemWidth/8, dl, MVT::i32));1491    SingleV = DAG.getNode(HexagonISD::VROR, dl, SingleTy, SingleV, IdxV);1492  }1493  // When inserting a single word, the rotation back to the original position1494  // would be by HwLen-Idx, but if two words are inserted, it will need to be1495  // by (HwLen-4)-Idx.1496  unsigned RolBase = HwLen;1497  if (SubTy.getSizeInBits() == 32) {1498    SDValue V = DAG.getBitcast(MVT::i32, SubV);1499    SingleV = DAG.getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, V);1500  } else {1501    SDValue V = DAG.getBitcast(MVT::i64, SubV);1502    SDValue R0 = LoHalf(V, DAG);1503    SDValue R1 = HiHalf(V, DAG);1504    SingleV = DAG.getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R0);1505    SingleV = DAG.getNode(HexagonISD::VROR, dl, SingleTy, SingleV,1506                          DAG.getConstant(4, dl, MVT::i32));1507    SingleV = DAG.getNode(HexagonISD::VINSERTW0, dl, SingleTy, SingleV, R1);1508    RolBase = HwLen-4;1509  }1510  // If the vector wasn't ror'ed, don't ror it back.1511  if (RolBase != 4 || !IdxN || !IdxN->isZero()) {1512    SDValue RolV = DAG.getNode(ISD::SUB, dl, MVT::i32,1513                               DAG.getConstant(RolBase, dl, MVT::i32), IdxV);1514    SingleV = DAG.getNode(HexagonISD::VROR, dl, SingleTy, SingleV, RolV);1515  }1516 1517  if (IsPair) {1518    SDValue InLo = DAG.getNode(ISD::CONCAT_VECTORS, dl, VecTy, {SingleV, V1});1519    SDValue InHi = DAG.getNode(ISD::CONCAT_VECTORS, dl, VecTy, {V0, SingleV});1520    return DAG.getNode(ISD::SELECT, dl, VecTy, PickHi, InHi, InLo);1521  }1522  return SingleV;1523}1524 1525SDValue1526HexagonTargetLowering::insertHvxSubvectorPred(SDValue VecV, SDValue SubV,1527      SDValue IdxV, const SDLoc &dl, SelectionDAG &DAG) const {1528  MVT VecTy = ty(VecV);1529  MVT SubTy = ty(SubV);1530  assert(Subtarget.isHVXVectorType(VecTy, true));1531  // VecV is an HVX vector predicate. SubV may be either an HVX vector1532  // predicate as well, or it can be a scalar predicate.1533 1534  unsigned VecLen = VecTy.getVectorNumElements();1535  unsigned HwLen = Subtarget.getVectorLength();1536  assert(HwLen % VecLen == 0 && "Unexpected vector type");1537 1538  unsigned Scale = VecLen / SubTy.getVectorNumElements();1539  unsigned BitBytes = HwLen / VecLen;1540  unsigned BlockLen = HwLen / Scale;1541 1542  MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);1543  SDValue ByteVec = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, VecV);1544  SDValue ByteSub = createHvxPrefixPred(SubV, dl, BitBytes, false, DAG);1545  SDValue ByteIdx;1546 1547  auto *IdxN = dyn_cast<ConstantSDNode>(IdxV.getNode());1548  if (!IdxN || !IdxN->isZero()) {1549    ByteIdx = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV,1550                          DAG.getConstant(BitBytes, dl, MVT::i32));1551    ByteVec = DAG.getNode(HexagonISD::VROR, dl, ByteTy, ByteVec, ByteIdx);1552  }1553 1554  // ByteVec is the target vector VecV rotated in such a way that the1555  // subvector should be inserted at index 0. Generate a predicate mask1556  // and use vmux to do the insertion.1557  assert(BlockLen < HwLen && "vsetq(v1) prerequisite");1558  MVT BoolTy = MVT::getVectorVT(MVT::i1, HwLen);1559  SDValue Q = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,1560                       {DAG.getConstant(BlockLen, dl, MVT::i32)}, DAG);1561  ByteVec = getInstr(Hexagon::V6_vmux, dl, ByteTy, {Q, ByteSub, ByteVec}, DAG);1562  // Rotate ByteVec back, and convert to a vector predicate.1563  if (!IdxN || !IdxN->isZero()) {1564    SDValue HwLenV = DAG.getConstant(HwLen, dl, MVT::i32);1565    SDValue ByteXdi = DAG.getNode(ISD::SUB, dl, MVT::i32, HwLenV, ByteIdx);1566    ByteVec = DAG.getNode(HexagonISD::VROR, dl, ByteTy, ByteVec, ByteXdi);1567  }1568  return DAG.getNode(HexagonISD::V2Q, dl, VecTy, ByteVec);1569}1570 1571SDValue1572HexagonTargetLowering::extendHvxVectorPred(SDValue VecV, const SDLoc &dl,1573      MVT ResTy, bool ZeroExt, SelectionDAG &DAG) const {1574  // Sign- and any-extending of a vector predicate to a vector register is1575  // equivalent to Q2V. For zero-extensions, generate a vmux between 0 and1576  // a vector of 1s (where the 1s are of type matching the vector type).1577  assert(Subtarget.isHVXVectorType(ResTy));1578  if (!ZeroExt)1579    return DAG.getNode(HexagonISD::Q2V, dl, ResTy, VecV);1580 1581  assert(ty(VecV).getVectorNumElements() == ResTy.getVectorNumElements());1582  SDValue True = DAG.getNode(ISD::SPLAT_VECTOR, dl, ResTy,1583                             DAG.getConstant(1, dl, MVT::i32));1584  SDValue False = getZero(dl, ResTy, DAG);1585  return DAG.getSelect(dl, ResTy, VecV, True, False);1586}1587 1588SDValue1589HexagonTargetLowering::compressHvxPred(SDValue VecQ, const SDLoc &dl,1590      MVT ResTy, SelectionDAG &DAG) const {1591  // Given a predicate register VecQ, transfer bits VecQ[0..HwLen-1]1592  // (i.e. the entire predicate register) to bits [0..HwLen-1] of a1593  // vector register. The remaining bits of the vector register are1594  // unspecified.1595 1596  MachineFunction &MF = DAG.getMachineFunction();1597  unsigned HwLen = Subtarget.getVectorLength();1598  MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);1599  MVT PredTy = ty(VecQ);1600  unsigned PredLen = PredTy.getVectorNumElements();1601  assert(HwLen % PredLen == 0);1602  MVT VecTy = MVT::getVectorVT(MVT::getIntegerVT(8*HwLen/PredLen), PredLen);1603 1604  Type *Int8Ty = Type::getInt8Ty(*DAG.getContext());1605  SmallVector<Constant*, 128> Tmp;1606  // Create an array of bytes (hex): 01,02,04,08,10,20,40,80, 01,02,04,08,...1607  // These are bytes with the LSB rotated left with respect to their index.1608  for (unsigned i = 0; i != HwLen/8; ++i) {1609    for (unsigned j = 0; j != 8; ++j)1610      Tmp.push_back(ConstantInt::get(Int8Ty, 1ull << j));1611  }1612  Constant *CV = ConstantVector::get(Tmp);1613  Align Alignment(HwLen);1614  SDValue CP =1615      LowerConstantPool(DAG.getConstantPool(CV, ByteTy, Alignment), DAG);1616  SDValue Bytes =1617      DAG.getLoad(ByteTy, dl, DAG.getEntryNode(), CP,1618                  MachinePointerInfo::getConstantPool(MF), Alignment);1619 1620  // Select the bytes that correspond to true bits in the vector predicate.1621  SDValue Sel = DAG.getSelect(dl, VecTy, VecQ, DAG.getBitcast(VecTy, Bytes),1622      getZero(dl, VecTy, DAG));1623  // Calculate the OR of all bytes in each group of 8. That will compress1624  // all the individual bits into a single byte.1625  // First, OR groups of 4, via vrmpy with 0x01010101.1626  SDValue All1 =1627      DAG.getSplatBuildVector(MVT::v4i8, dl, DAG.getConstant(1, dl, MVT::i32));1628  SDValue Vrmpy = getInstr(Hexagon::V6_vrmpyub, dl, ByteTy, {Sel, All1}, DAG);1629  // Then rotate the accumulated vector by 4 bytes, and do the final OR.1630  SDValue Rot = getInstr(Hexagon::V6_valignbi, dl, ByteTy,1631      {Vrmpy, Vrmpy, DAG.getTargetConstant(4, dl, MVT::i32)}, DAG);1632  SDValue Vor = DAG.getNode(ISD::OR, dl, ByteTy, {Vrmpy, Rot});1633 1634  // Pick every 8th byte and coalesce them at the beginning of the output.1635  // For symmetry, coalesce every 1+8th byte after that, then every 2+8th1636  // byte and so on.1637  SmallVector<int,128> Mask;1638  for (unsigned i = 0; i != HwLen; ++i)1639    Mask.push_back((8*i) % HwLen + i/(HwLen/8));1640  SDValue Collect =1641      DAG.getVectorShuffle(ByteTy, dl, Vor, DAG.getUNDEF(ByteTy), Mask);1642  return DAG.getBitcast(ResTy, Collect);1643}1644 1645SDValue1646HexagonTargetLowering::resizeToWidth(SDValue VecV, MVT ResTy, bool Signed,1647                                     const SDLoc &dl, SelectionDAG &DAG) const {1648  // Take a vector and resize the element type to match the given type.1649  MVT InpTy = ty(VecV);1650  if (InpTy == ResTy)1651    return VecV;1652 1653  unsigned InpWidth = InpTy.getSizeInBits();1654  unsigned ResWidth = ResTy.getSizeInBits();1655 1656  if (InpTy.isFloatingPoint()) {1657    return InpWidth < ResWidth1658               ? DAG.getNode(ISD::FP_EXTEND, dl, ResTy, VecV)1659               : DAG.getNode(ISD::FP_ROUND, dl, ResTy, VecV,1660                             DAG.getTargetConstant(0, dl, MVT::i32));1661  }1662 1663  assert(InpTy.isInteger());1664 1665  if (InpWidth < ResWidth) {1666    unsigned ExtOpc = Signed ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;1667    return DAG.getNode(ExtOpc, dl, ResTy, VecV);1668  } else {1669    unsigned NarOpc = Signed ? HexagonISD::SSAT : HexagonISD::USAT;1670    return DAG.getNode(NarOpc, dl, ResTy, VecV, DAG.getValueType(ResTy));1671  }1672}1673 1674SDValue1675HexagonTargetLowering::extractSubvector(SDValue Vec, MVT SubTy, unsigned SubIdx,1676      SelectionDAG &DAG) const {1677  assert(ty(Vec).getSizeInBits() % SubTy.getSizeInBits() == 0);1678 1679  const SDLoc &dl(Vec);1680  unsigned ElemIdx = SubIdx * SubTy.getVectorNumElements();1681  return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubTy,1682                     {Vec, DAG.getConstant(ElemIdx, dl, MVT::i32)});1683}1684 1685SDValue1686HexagonTargetLowering::LowerHvxBuildVector(SDValue Op, SelectionDAG &DAG)1687      const {1688  const SDLoc &dl(Op);1689  MVT VecTy = ty(Op);1690 1691  unsigned Size = Op.getNumOperands();1692  SmallVector<SDValue,128> Ops;1693  for (unsigned i = 0; i != Size; ++i)1694    Ops.push_back(Op.getOperand(i));1695 1696  if (VecTy.getVectorElementType() == MVT::i1)1697    return buildHvxVectorPred(Ops, dl, VecTy, DAG);1698 1699  // In case of MVT::f16 BUILD_VECTOR, since MVT::f16 is1700  // not a legal type, just bitcast the node to use i161701  // types and bitcast the result back to f161702  if (VecTy.getVectorElementType() == MVT::f16 ||1703      VecTy.getVectorElementType() == MVT::bf16) {1704    SmallVector<SDValue, 64> NewOps;1705    for (unsigned i = 0; i != Size; i++)1706      NewOps.push_back(DAG.getBitcast(MVT::i16, Ops[i]));1707 1708    SDValue T0 =1709        DAG.getNode(ISD::BUILD_VECTOR, dl, tyVector(VecTy, MVT::i16), NewOps);1710    return DAG.getBitcast(tyVector(VecTy, VecTy.getVectorElementType()), T0);1711  }1712 1713  // First, split the BUILD_VECTOR for vector pairs. We could generate1714  // some pairs directly (via splat), but splats should be generated1715  // by the combiner prior to getting here.1716  if (VecTy.getSizeInBits() == 16 * Subtarget.getVectorLength()) {1717    ArrayRef<SDValue> A(Ops);1718    MVT SingleTy = typeSplit(VecTy).first;1719    SDValue V0 = buildHvxVectorReg(A.take_front(Size / 2), dl, SingleTy, DAG);1720    SDValue V1 = buildHvxVectorReg(A.drop_front(Size / 2), dl, SingleTy, DAG);1721    return DAG.getNode(ISD::CONCAT_VECTORS, dl, VecTy, V0, V1);1722  }1723 1724  return buildHvxVectorReg(Ops, dl, VecTy, DAG);1725}1726 1727SDValue1728HexagonTargetLowering::LowerHvxSplatVector(SDValue Op, SelectionDAG &DAG)1729      const {1730  const SDLoc &dl(Op);1731  MVT VecTy = ty(Op);1732  MVT ArgTy = ty(Op.getOperand(0));1733 1734  if (ArgTy == MVT::f16 || ArgTy == MVT::bf16) {1735    MVT SplatTy =  MVT::getVectorVT(MVT::i16, VecTy.getVectorNumElements());1736    SDValue ToInt16 = DAG.getBitcast(MVT::i16, Op.getOperand(0));1737    SDValue ToInt32 = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i32, ToInt16);1738    SDValue Splat = DAG.getNode(ISD::SPLAT_VECTOR, dl, SplatTy, ToInt32);1739    return DAG.getBitcast(VecTy, Splat);1740  }1741 1742  return SDValue();1743}1744 1745SDValue1746HexagonTargetLowering::LowerHvxConcatVectors(SDValue Op, SelectionDAG &DAG)1747      const {1748  // Vector concatenation of two integer (non-bool) vectors does not need1749  // special lowering. Custom-lower concats of bool vectors and expand1750  // concats of more than 2 vectors.1751  MVT VecTy = ty(Op);1752  const SDLoc &dl(Op);1753  unsigned NumOp = Op.getNumOperands();1754  if (VecTy.getVectorElementType() != MVT::i1) {1755    if (NumOp == 2)1756      return Op;1757    // Expand the other cases into a build-vector.1758    SmallVector<SDValue,8> Elems;1759    for (SDValue V : Op.getNode()->ops())1760      DAG.ExtractVectorElements(V, Elems);1761    // A vector of i16 will be broken up into a build_vector of i16's.1762    // This is a problem, since at the time of operation legalization,1763    // all operations are expected to be type-legalized, and i16 is not1764    // a legal type. If any of the extracted elements is not of a valid1765    // type, sign-extend it to a valid one.1766    for (SDValue &V : Elems) {1767      MVT Ty = ty(V);1768      if (!isTypeLegal(Ty)) {1769        MVT NTy = typeLegalize(Ty, DAG);1770        if (V.getOpcode() == ISD::EXTRACT_VECTOR_ELT) {1771          V = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, NTy,1772                          DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NTy,1773                                      V.getOperand(0), V.getOperand(1)),1774                          DAG.getValueType(Ty));1775          continue;1776        }1777        // A few less complicated cases.1778        switch (V.getOpcode()) {1779          case ISD::Constant:1780            V = DAG.getSExtOrTrunc(V, dl, NTy);1781            break;1782          case ISD::UNDEF:1783            V = DAG.getUNDEF(NTy);1784            break;1785          case ISD::TRUNCATE:1786            V = V.getOperand(0);1787            break;1788          default:1789            llvm_unreachable("Unexpected vector element");1790        }1791      }1792    }1793    return DAG.getBuildVector(VecTy, dl, Elems);1794  }1795 1796  assert(VecTy.getVectorElementType() == MVT::i1);1797  unsigned HwLen = Subtarget.getVectorLength();1798  assert(isPowerOf2_32(NumOp) && HwLen % NumOp == 0);1799 1800  SDValue Op0 = Op.getOperand(0);1801 1802  // If the operands are HVX types (i.e. not scalar predicates), then1803  // defer the concatenation, and create QCAT instead.1804  if (Subtarget.isHVXVectorType(ty(Op0), true)) {1805    if (NumOp == 2)1806      return DAG.getNode(HexagonISD::QCAT, dl, VecTy, Op0, Op.getOperand(1));1807 1808    ArrayRef<SDUse> U(Op.getNode()->ops());1809    SmallVector<SDValue, 4> SV(U);1810    ArrayRef<SDValue> Ops(SV);1811 1812    MVT HalfTy = typeSplit(VecTy).first;1813    SDValue V0 = DAG.getNode(ISD::CONCAT_VECTORS, dl, HalfTy,1814                             Ops.take_front(NumOp/2));1815    SDValue V1 = DAG.getNode(ISD::CONCAT_VECTORS, dl, HalfTy,1816                             Ops.take_back(NumOp/2));1817    return DAG.getNode(HexagonISD::QCAT, dl, VecTy, V0, V1);1818  }1819 1820  // Count how many bytes (in a vector register) each bit in VecTy1821  // corresponds to.1822  unsigned BitBytes = HwLen / VecTy.getVectorNumElements();1823 1824  SmallVector<SDValue,8> Prefixes;1825  for (SDValue V : Op.getNode()->op_values()) {1826    SDValue P = createHvxPrefixPred(V, dl, BitBytes, true, DAG);1827    Prefixes.push_back(P);1828  }1829 1830  unsigned InpLen = ty(Op.getOperand(0)).getVectorNumElements();1831  MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);1832  SDValue S = DAG.getConstant(HwLen - InpLen*BitBytes, dl, MVT::i32);1833  SDValue Res = getZero(dl, ByteTy, DAG);1834  for (unsigned i = 0, e = Prefixes.size(); i != e; ++i) {1835    Res = DAG.getNode(HexagonISD::VROR, dl, ByteTy, Res, S);1836    Res = DAG.getNode(ISD::OR, dl, ByteTy, Res, Prefixes[e-i-1]);1837  }1838  return DAG.getNode(HexagonISD::V2Q, dl, VecTy, Res);1839}1840 1841SDValue1842HexagonTargetLowering::LowerHvxExtractElement(SDValue Op, SelectionDAG &DAG)1843      const {1844  // Change the type of the extracted element to i32.1845  SDValue VecV = Op.getOperand(0);1846  MVT ElemTy = ty(VecV).getVectorElementType();1847  const SDLoc &dl(Op);1848  SDValue IdxV = Op.getOperand(1);1849  if (ElemTy == MVT::i1)1850    return extractHvxElementPred(VecV, IdxV, dl, ty(Op), DAG);1851 1852  return extractHvxElementReg(VecV, IdxV, dl, ty(Op), DAG);1853}1854 1855SDValue1856HexagonTargetLowering::LowerHvxInsertElement(SDValue Op, SelectionDAG &DAG)1857      const {1858  const SDLoc &dl(Op);1859  MVT VecTy = ty(Op);1860  SDValue VecV = Op.getOperand(0);1861  SDValue ValV = Op.getOperand(1);1862  SDValue IdxV = Op.getOperand(2);1863  MVT ElemTy = ty(VecV).getVectorElementType();1864  if (ElemTy == MVT::i1)1865    return insertHvxElementPred(VecV, IdxV, ValV, dl, DAG);1866 1867  if (ElemTy == MVT::f16 || ElemTy == MVT::bf16) {1868    SDValue T0 = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl,1869        tyVector(VecTy, MVT::i16),1870        DAG.getBitcast(tyVector(VecTy, MVT::i16), VecV),1871        DAG.getBitcast(MVT::i16, ValV), IdxV);1872    return DAG.getBitcast(tyVector(VecTy, ElemTy), T0);1873  }1874 1875  return insertHvxElementReg(VecV, IdxV, ValV, dl, DAG);1876}1877 1878SDValue1879HexagonTargetLowering::LowerHvxExtractSubvector(SDValue Op, SelectionDAG &DAG)1880      const {1881  SDValue SrcV = Op.getOperand(0);1882  MVT SrcTy = ty(SrcV);1883  MVT DstTy = ty(Op);1884  SDValue IdxV = Op.getOperand(1);1885  unsigned Idx = IdxV.getNode()->getAsZExtVal();1886  assert(Idx % DstTy.getVectorNumElements() == 0);1887  (void)Idx;1888  const SDLoc &dl(Op);1889 1890  MVT ElemTy = SrcTy.getVectorElementType();1891  if (ElemTy == MVT::i1)1892    return extractHvxSubvectorPred(SrcV, IdxV, dl, DstTy, DAG);1893 1894  return extractHvxSubvectorReg(Op, SrcV, IdxV, dl, DstTy, DAG);1895}1896 1897SDValue1898HexagonTargetLowering::LowerHvxInsertSubvector(SDValue Op, SelectionDAG &DAG)1899      const {1900  // Idx does not need to be a constant.1901  SDValue VecV = Op.getOperand(0);1902  SDValue ValV = Op.getOperand(1);1903  SDValue IdxV = Op.getOperand(2);1904 1905  const SDLoc &dl(Op);1906  MVT VecTy = ty(VecV);1907  MVT ElemTy = VecTy.getVectorElementType();1908  if (ElemTy == MVT::i1)1909    return insertHvxSubvectorPred(VecV, ValV, IdxV, dl, DAG);1910 1911  return insertHvxSubvectorReg(VecV, ValV, IdxV, dl, DAG);1912}1913 1914SDValue1915HexagonTargetLowering::LowerHvxAnyExt(SDValue Op, SelectionDAG &DAG) const {1916  // Lower any-extends of boolean vectors to sign-extends, since they1917  // translate directly to Q2V. Zero-extending could also be done equally1918  // fast, but Q2V is used/recognized in more places.1919  // For all other vectors, use zero-extend.1920  MVT ResTy = ty(Op);1921  SDValue InpV = Op.getOperand(0);1922  MVT ElemTy = ty(InpV).getVectorElementType();1923  if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))1924    return LowerHvxSignExt(Op, DAG);1925  return DAG.getNode(ISD::ZERO_EXTEND, SDLoc(Op), ResTy, InpV);1926}1927 1928SDValue1929HexagonTargetLowering::LowerHvxSignExt(SDValue Op, SelectionDAG &DAG) const {1930  MVT ResTy = ty(Op);1931  SDValue InpV = Op.getOperand(0);1932  MVT ElemTy = ty(InpV).getVectorElementType();1933  if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))1934    return extendHvxVectorPred(InpV, SDLoc(Op), ty(Op), false, DAG);1935  return Op;1936}1937 1938SDValue1939HexagonTargetLowering::LowerHvxZeroExt(SDValue Op, SelectionDAG &DAG) const {1940  MVT ResTy = ty(Op);1941  SDValue InpV = Op.getOperand(0);1942  MVT ElemTy = ty(InpV).getVectorElementType();1943  if (ElemTy == MVT::i1 && Subtarget.isHVXVectorType(ResTy))1944    return extendHvxVectorPred(InpV, SDLoc(Op), ty(Op), true, DAG);1945  return Op;1946}1947 1948SDValue1949HexagonTargetLowering::LowerHvxCttz(SDValue Op, SelectionDAG &DAG) const {1950  // Lower vector CTTZ into a computation using CTLZ (Hacker's Delight):1951  // cttz(x) = bitwidth(x) - ctlz(~x & (x-1))1952  const SDLoc &dl(Op);1953  MVT ResTy = ty(Op);1954  SDValue InpV = Op.getOperand(0);1955  assert(ResTy == ty(InpV));1956 1957  // Calculate the vectors of 1 and bitwidth(x).1958  MVT ElemTy = ty(InpV).getVectorElementType();1959  unsigned ElemWidth = ElemTy.getSizeInBits();1960 1961  SDValue Vec1 = DAG.getNode(ISD::SPLAT_VECTOR, dl, ResTy,1962                             DAG.getConstant(1, dl, MVT::i32));1963  SDValue VecW = DAG.getNode(ISD::SPLAT_VECTOR, dl, ResTy,1964                             DAG.getConstant(ElemWidth, dl, MVT::i32));1965  SDValue VecN1 = DAG.getNode(ISD::SPLAT_VECTOR, dl, ResTy,1966                              DAG.getAllOnesConstant(dl, MVT::i32));1967 1968  // Do not use DAG.getNOT, because that would create BUILD_VECTOR with1969  // a BITCAST. Here we can skip the BITCAST (so we don't have to handle1970  // it separately in custom combine or selection).1971  SDValue A = DAG.getNode(ISD::AND, dl, ResTy,1972                          {DAG.getNode(ISD::XOR, dl, ResTy, {InpV, VecN1}),1973                           DAG.getNode(ISD::SUB, dl, ResTy, {InpV, Vec1})});1974  return DAG.getNode(ISD::SUB, dl, ResTy,1975                     {VecW, DAG.getNode(ISD::CTLZ, dl, ResTy, A)});1976}1977 1978SDValue1979HexagonTargetLowering::LowerHvxMulh(SDValue Op, SelectionDAG &DAG) const {1980  const SDLoc &dl(Op);1981  MVT ResTy = ty(Op);1982  assert(ResTy.getVectorElementType() == MVT::i32);1983 1984  SDValue Vs = Op.getOperand(0);1985  SDValue Vt = Op.getOperand(1);1986 1987  SDVTList ResTys = DAG.getVTList(ResTy, ResTy);1988  unsigned Opc = Op.getOpcode();1989 1990  // On HVX v62+ producing the full product is cheap, so legalize MULH to LOHI.1991  if (Opc == ISD::MULHU)1992    return DAG.getNode(HexagonISD::UMUL_LOHI, dl, ResTys, {Vs, Vt}).getValue(1);1993  if (Opc == ISD::MULHS)1994    return DAG.getNode(HexagonISD::SMUL_LOHI, dl, ResTys, {Vs, Vt}).getValue(1);1995 1996#ifndef NDEBUG1997  Op.dump(&DAG);1998#endif1999  llvm_unreachable("Unexpected mulh operation");2000}2001 2002SDValue2003HexagonTargetLowering::LowerHvxMulLoHi(SDValue Op, SelectionDAG &DAG) const {2004  const SDLoc &dl(Op);2005  unsigned Opc = Op.getOpcode();2006  SDValue Vu = Op.getOperand(0);2007  SDValue Vv = Op.getOperand(1);2008 2009  // If the HI part is not used, convert it to a regular MUL.2010  if (auto HiVal = Op.getValue(1); HiVal.use_empty()) {2011    // Need to preserve the types and the number of values.2012    SDValue Hi = DAG.getUNDEF(ty(HiVal));2013    SDValue Lo = DAG.getNode(ISD::MUL, dl, ty(Op), {Vu, Vv});2014    return DAG.getMergeValues({Lo, Hi}, dl);2015  }2016 2017  bool SignedVu = Opc == HexagonISD::SMUL_LOHI;2018  bool SignedVv = Opc == HexagonISD::SMUL_LOHI || Opc == HexagonISD::USMUL_LOHI;2019 2020  // Legal on HVX v62+, but lower it here because patterns can't handle multi-2021  // valued nodes.2022  if (Subtarget.useHVXV62Ops())2023    return emitHvxMulLoHiV62(Vu, SignedVu, Vv, SignedVv, dl, DAG);2024 2025  if (Opc == HexagonISD::SMUL_LOHI) {2026    // Direct MULHS expansion is cheaper than doing the whole SMUL_LOHI,2027    // for other signedness LOHI is cheaper.2028    if (auto LoVal = Op.getValue(0); LoVal.use_empty()) {2029      SDValue Hi = emitHvxMulHsV60(Vu, Vv, dl, DAG);2030      SDValue Lo = DAG.getUNDEF(ty(LoVal));2031      return DAG.getMergeValues({Lo, Hi}, dl);2032    }2033  }2034 2035  return emitHvxMulLoHiV60(Vu, SignedVu, Vv, SignedVv, dl, DAG);2036}2037 2038SDValue2039HexagonTargetLowering::LowerHvxBitcast(SDValue Op, SelectionDAG &DAG) const {2040  SDValue Val = Op.getOperand(0);2041  MVT ResTy = ty(Op);2042  MVT ValTy = ty(Val);2043  const SDLoc &dl(Op);2044 2045  if (isHvxBoolTy(ValTy) && ResTy.isScalarInteger()) {2046    unsigned HwLen = Subtarget.getVectorLength();2047    MVT WordTy = MVT::getVectorVT(MVT::i32, HwLen/4);2048    SDValue VQ = compressHvxPred(Val, dl, WordTy, DAG);2049    unsigned BitWidth = ResTy.getSizeInBits();2050 2051    if (BitWidth < 64) {2052      SDValue W0 = extractHvxElementReg(VQ, DAG.getConstant(0, dl, MVT::i32),2053          dl, MVT::i32, DAG);2054      if (BitWidth == 32)2055        return W0;2056      assert(BitWidth < 32u);2057      return DAG.getZExtOrTrunc(W0, dl, ResTy);2058    }2059 2060    // The result is >= 64 bits. The only options are 64 or 128.2061    assert(BitWidth == 64 || BitWidth == 128);2062    SmallVector<SDValue,4> Words;2063    for (unsigned i = 0; i != BitWidth/32; ++i) {2064      SDValue W = extractHvxElementReg(2065          VQ, DAG.getConstant(i, dl, MVT::i32), dl, MVT::i32, DAG);2066      Words.push_back(W);2067    }2068    SmallVector<SDValue,2> Combines;2069    assert(Words.size() % 2 == 0);2070    for (unsigned i = 0, e = Words.size(); i < e; i += 2) {2071      SDValue C = getCombine(Words[i+1], Words[i], dl, MVT::i64, DAG);2072      Combines.push_back(C);2073    }2074 2075    if (BitWidth == 64)2076      return Combines[0];2077 2078    return DAG.getNode(ISD::BUILD_PAIR, dl, ResTy, Combines);2079  }2080 2081  // Handle bitcast from i32, v2i16, and v4i8 to v32i1.2082  // Splat the input into a 32-element i32 vector, then AND each element2083  // with a unique bitmask to isolate individual bits.2084  auto bitcastI32ToV32I1 = [&](SDValue Val32) {2085    assert(Val32.getValueType().getSizeInBits() == 32 &&2086           "Input must be 32 bits");2087    MVT VecTy = MVT::getVectorVT(MVT::i32, 32);2088    SDValue Splat = DAG.getNode(ISD::SPLAT_VECTOR, dl, VecTy, Val32);2089    SmallVector<SDValue, 32> Mask;2090    for (unsigned i = 0; i < 32; ++i)2091      Mask.push_back(DAG.getConstant(1ull << i, dl, MVT::i32));2092 2093    SDValue MaskVec = DAG.getBuildVector(VecTy, dl, Mask);2094    SDValue Anded = DAG.getNode(ISD::AND, dl, VecTy, Splat, MaskVec);2095    return DAG.getNode(HexagonISD::V2Q, dl, MVT::v32i1, Anded);2096  };2097  // === Case: v32i1 ===2098  if (ResTy == MVT::v32i1 &&2099      (ValTy == MVT::i32 || ValTy == MVT::v2i16 || ValTy == MVT::v4i8) &&2100      Subtarget.useHVX128BOps()) {2101    SDValue Val32 = Val;2102    if (ValTy == MVT::v2i16 || ValTy == MVT::v4i8)2103      Val32 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Val);2104    return bitcastI32ToV32I1(Val32);2105  }2106  // === Case: v64i1 ===2107  if (ResTy == MVT::v64i1 && ValTy == MVT::i64 && Subtarget.useHVX128BOps()) {2108    // Split i64 into lo/hi 32-bit halves.2109    SDValue Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Val);2110    SDValue HiShifted = DAG.getNode(ISD::SRL, dl, MVT::i64, Val,2111                                    DAG.getConstant(32, dl, MVT::i64));2112    SDValue Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, HiShifted);2113 2114    // Reuse the same 32-bit logic twice.2115    SDValue LoRes = bitcastI32ToV32I1(Lo);2116    SDValue HiRes = bitcastI32ToV32I1(Hi);2117 2118    // Concatenate into a v64i1 predicate.2119    return DAG.getNode(ISD::CONCAT_VECTORS, dl, MVT::v64i1, LoRes, HiRes);2120  }2121 2122  if (isHvxBoolTy(ResTy) && ValTy.isScalarInteger()) {2123    // Handle bitcast from i128 -> v128i1 and i64 -> v64i1.2124    unsigned BitWidth = ValTy.getSizeInBits();2125    unsigned HwLen = Subtarget.getVectorLength();2126    assert(BitWidth == HwLen);2127 2128    MVT ValAsVecTy = MVT::getVectorVT(MVT::i8, BitWidth / 8);2129    SDValue ValAsVec = DAG.getBitcast(ValAsVecTy, Val);2130    // Splat each byte of Val 8 times.2131    // Bytes = [(b0)x8, (b1)x8, ...., (b15)x8]2132    // where b0, b1,..., b15 are least to most significant bytes of I.2133    SmallVector<SDValue, 128> Bytes;2134    // Tmp: 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80, 0x01,0x02,0x04,0x08,...2135    // These are bytes with the LSB rotated left with respect to their index.2136    SmallVector<SDValue, 128> Tmp;2137    for (unsigned I = 0; I != HwLen / 8; ++I) {2138      SDValue Idx = DAG.getConstant(I, dl, MVT::i32);2139      SDValue Byte =2140          DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i8, ValAsVec, Idx);2141      for (unsigned J = 0; J != 8; ++J) {2142        Bytes.push_back(Byte);2143        Tmp.push_back(DAG.getConstant(1ull << J, dl, MVT::i8));2144      }2145    }2146 2147    MVT ConstantVecTy = MVT::getVectorVT(MVT::i8, HwLen);2148    SDValue ConstantVec = DAG.getBuildVector(ConstantVecTy, dl, Tmp);2149    SDValue I2V = buildHvxVectorReg(Bytes, dl, ConstantVecTy, DAG);2150 2151    // Each Byte in the I2V will be set iff corresponding bit is set in Val.2152    I2V = DAG.getNode(ISD::AND, dl, ConstantVecTy, {I2V, ConstantVec});2153    return DAG.getNode(HexagonISD::V2Q, dl, ResTy, I2V);2154  }2155 2156  return Op;2157}2158 2159SDValue2160HexagonTargetLowering::LowerHvxExtend(SDValue Op, SelectionDAG &DAG) const {2161  // Sign- and zero-extends are legal.2162  assert(Op.getOpcode() == ISD::ANY_EXTEND_VECTOR_INREG);2163  return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, SDLoc(Op), ty(Op),2164                     Op.getOperand(0));2165}2166 2167SDValue2168HexagonTargetLowering::LowerHvxSelect(SDValue Op, SelectionDAG &DAG) const {2169  MVT ResTy = ty(Op);2170  if (ResTy.getVectorElementType() != MVT::i1)2171    return Op;2172 2173  const SDLoc &dl(Op);2174  unsigned HwLen = Subtarget.getVectorLength();2175  unsigned VecLen = ResTy.getVectorNumElements();2176  assert(HwLen % VecLen == 0);2177  unsigned ElemSize = HwLen / VecLen;2178 2179  MVT VecTy = MVT::getVectorVT(MVT::getIntegerVT(ElemSize * 8), VecLen);2180  SDValue S =2181      DAG.getNode(ISD::SELECT, dl, VecTy, Op.getOperand(0),2182                  DAG.getNode(HexagonISD::Q2V, dl, VecTy, Op.getOperand(1)),2183                  DAG.getNode(HexagonISD::Q2V, dl, VecTy, Op.getOperand(2)));2184  return DAG.getNode(HexagonISD::V2Q, dl, ResTy, S);2185}2186 2187SDValue2188HexagonTargetLowering::LowerHvxShift(SDValue Op, SelectionDAG &DAG) const {2189  if (SDValue S = getVectorShiftByInt(Op, DAG))2190    return S;2191  return Op;2192}2193 2194SDValue2195HexagonTargetLowering::LowerHvxFunnelShift(SDValue Op,2196                                           SelectionDAG &DAG) const {2197  unsigned Opc = Op.getOpcode();2198  assert(Opc == ISD::FSHL || Opc == ISD::FSHR);2199 2200  // Make sure the shift amount is within the range of the bitwidth2201  // of the element type.2202  SDValue A = Op.getOperand(0);2203  SDValue B = Op.getOperand(1);2204  SDValue S = Op.getOperand(2);2205 2206  MVT InpTy = ty(A);2207  MVT ElemTy = InpTy.getVectorElementType();2208 2209  const SDLoc &dl(Op);2210  unsigned ElemWidth = ElemTy.getSizeInBits();2211  bool IsLeft = Opc == ISD::FSHL;2212 2213  // The expansion into regular shifts produces worse code for i8 and for2214  // right shift of i32 on v65+.2215  bool UseShifts = ElemTy != MVT::i8;2216  if (Subtarget.useHVXV65Ops() && ElemTy == MVT::i32)2217    UseShifts = false;2218 2219  if (SDValue SplatV = getSplatValue(S, DAG); SplatV && UseShifts) {2220    // If this is a funnel shift by a scalar, lower it into regular shifts.2221    SDValue Mask = DAG.getConstant(ElemWidth - 1, dl, MVT::i32);2222    SDValue ModS =2223        DAG.getNode(ISD::AND, dl, MVT::i32,2224                    {DAG.getZExtOrTrunc(SplatV, dl, MVT::i32), Mask});2225    SDValue NegS =2226        DAG.getNode(ISD::SUB, dl, MVT::i32,2227                    {DAG.getConstant(ElemWidth, dl, MVT::i32), ModS});2228    SDValue IsZero =2229        DAG.getSetCC(dl, MVT::i1, ModS, getZero(dl, MVT::i32, DAG), ISD::SETEQ);2230    // FSHL A, B  =>  A <<  | B >>n2231    // FSHR A, B  =>  A <<n | B >>2232    SDValue Part1 =2233        DAG.getNode(HexagonISD::VASL, dl, InpTy, {A, IsLeft ? ModS : NegS});2234    SDValue Part2 =2235        DAG.getNode(HexagonISD::VLSR, dl, InpTy, {B, IsLeft ? NegS : ModS});2236    SDValue Or = DAG.getNode(ISD::OR, dl, InpTy, {Part1, Part2});2237    // If the shift amount was 0, pick A or B, depending on the direction.2238    // The opposite shift will also be by 0, so the "Or" will be incorrect.2239    return DAG.getNode(ISD::SELECT, dl, InpTy, {IsZero, (IsLeft ? A : B), Or});2240  }2241 2242  SDValue Mask = DAG.getSplatBuildVector(2243      InpTy, dl, DAG.getConstant(ElemWidth - 1, dl, ElemTy));2244 2245  unsigned MOpc = Opc == ISD::FSHL ? HexagonISD::MFSHL : HexagonISD::MFSHR;2246  return DAG.getNode(MOpc, dl, ty(Op),2247                     {A, B, DAG.getNode(ISD::AND, dl, InpTy, {S, Mask})});2248}2249 2250SDValue2251HexagonTargetLowering::LowerHvxIntrinsic(SDValue Op, SelectionDAG &DAG) const {2252  const SDLoc &dl(Op);2253  unsigned IntNo = Op.getConstantOperandVal(0);2254  SmallVector<SDValue> Ops(Op->ops());2255 2256  auto Swap = [&](SDValue P) {2257    return DAG.getMergeValues({P.getValue(1), P.getValue(0)}, dl);2258  };2259 2260  switch (IntNo) {2261  case Intrinsic::hexagon_V6_pred_typecast:2262  case Intrinsic::hexagon_V6_pred_typecast_128B: {2263    MVT ResTy = ty(Op), InpTy = ty(Ops[1]);2264    if (isHvxBoolTy(ResTy) && isHvxBoolTy(InpTy)) {2265      if (ResTy == InpTy)2266        return Ops[1];2267      return DAG.getNode(HexagonISD::TYPECAST, dl, ResTy, Ops[1]);2268    }2269    break;2270  }2271  case Intrinsic::hexagon_V6_vmpyss_parts:2272  case Intrinsic::hexagon_V6_vmpyss_parts_128B:2273    return Swap(DAG.getNode(HexagonISD::SMUL_LOHI, dl, Op->getVTList(),2274                            {Ops[1], Ops[2]}));2275  case Intrinsic::hexagon_V6_vmpyuu_parts:2276  case Intrinsic::hexagon_V6_vmpyuu_parts_128B:2277    return Swap(DAG.getNode(HexagonISD::UMUL_LOHI, dl, Op->getVTList(),2278                            {Ops[1], Ops[2]}));2279  case Intrinsic::hexagon_V6_vmpyus_parts:2280  case Intrinsic::hexagon_V6_vmpyus_parts_128B: {2281    return Swap(DAG.getNode(HexagonISD::USMUL_LOHI, dl, Op->getVTList(),2282                            {Ops[1], Ops[2]}));2283  }2284  } // switch2285 2286  return Op;2287}2288 2289SDValue2290HexagonTargetLowering::LowerHvxMaskedOp(SDValue Op, SelectionDAG &DAG) const {2291  const SDLoc &dl(Op);2292  unsigned HwLen = Subtarget.getVectorLength();2293  MachineFunction &MF = DAG.getMachineFunction();2294  auto *MaskN = cast<MaskedLoadStoreSDNode>(Op.getNode());2295  SDValue Mask = MaskN->getMask();2296  SDValue Chain = MaskN->getChain();2297  SDValue Base = MaskN->getBasePtr();2298  auto *MemOp = MF.getMachineMemOperand(MaskN->getMemOperand(), 0, HwLen);2299 2300  unsigned Opc = Op->getOpcode();2301  assert(Opc == ISD::MLOAD || Opc == ISD::MSTORE);2302 2303  if (Opc == ISD::MLOAD) {2304    MVT ValTy = ty(Op);2305    SDValue Load = DAG.getLoad(ValTy, dl, Chain, Base, MemOp);2306    SDValue Thru = cast<MaskedLoadSDNode>(MaskN)->getPassThru();2307    if (isUndef(Thru))2308      return Load;2309    SDValue VSel = DAG.getNode(ISD::VSELECT, dl, ValTy, Mask, Load, Thru);2310    return DAG.getMergeValues({VSel, Load.getValue(1)}, dl);2311  }2312 2313  // MSTORE2314  // HVX only has aligned masked stores.2315 2316  // TODO: Fold negations of the mask into the store.2317  unsigned StoreOpc = Hexagon::V6_vS32b_qpred_ai;2318  SDValue Value = cast<MaskedStoreSDNode>(MaskN)->getValue();2319  SDValue Offset0 = DAG.getTargetConstant(0, dl, ty(Base));2320 2321  if (MaskN->getAlign().value() % HwLen == 0) {2322    SDValue Store = getInstr(StoreOpc, dl, MVT::Other,2323                             {Mask, Base, Offset0, Value, Chain}, DAG);2324    DAG.setNodeMemRefs(cast<MachineSDNode>(Store.getNode()), {MemOp});2325    return Store;2326  }2327 2328  // Unaligned case.2329  auto StoreAlign = [&](SDValue V, SDValue A) {2330    SDValue Z = getZero(dl, ty(V), DAG);2331    // TODO: use funnel shifts?2332    // vlalign(Vu,Vv,Rt) rotates the pair Vu:Vv left by Rt and takes the2333    // upper half.2334    SDValue LoV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {V, Z, A}, DAG);2335    SDValue HiV = getInstr(Hexagon::V6_vlalignb, dl, ty(V), {Z, V, A}, DAG);2336    return std::make_pair(LoV, HiV);2337  };2338 2339  MVT ByteTy = MVT::getVectorVT(MVT::i8, HwLen);2340  MVT BoolTy = MVT::getVectorVT(MVT::i1, HwLen);2341  SDValue MaskV = DAG.getNode(HexagonISD::Q2V, dl, ByteTy, Mask);2342  VectorPair Tmp = StoreAlign(MaskV, Base);2343  VectorPair MaskU = {DAG.getNode(HexagonISD::V2Q, dl, BoolTy, Tmp.first),2344                      DAG.getNode(HexagonISD::V2Q, dl, BoolTy, Tmp.second)};2345  VectorPair ValueU = StoreAlign(Value, Base);2346 2347  SDValue Offset1 = DAG.getTargetConstant(HwLen, dl, MVT::i32);2348  SDValue StoreLo =2349      getInstr(StoreOpc, dl, MVT::Other,2350               {MaskU.first, Base, Offset0, ValueU.first, Chain}, DAG);2351  SDValue StoreHi =2352      getInstr(StoreOpc, dl, MVT::Other,2353               {MaskU.second, Base, Offset1, ValueU.second, Chain}, DAG);2354  DAG.setNodeMemRefs(cast<MachineSDNode>(StoreLo.getNode()), {MemOp});2355  DAG.setNodeMemRefs(cast<MachineSDNode>(StoreHi.getNode()), {MemOp});2356  return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, {StoreLo, StoreHi});2357}2358 2359SDValue HexagonTargetLowering::LowerHvxFpExtend(SDValue Op,2360                                                SelectionDAG &DAG) const {2361  // This conversion only applies to QFloat. IEEE extension from f16 to f322362  // is legal (done via a pattern).2363  assert(Subtarget.useHVXQFloatOps());2364 2365  assert(Op->getOpcode() == ISD::FP_EXTEND);2366 2367  MVT VecTy = ty(Op);2368  MVT ArgTy = ty(Op.getOperand(0));2369  const SDLoc &dl(Op);2370 2371  if (ArgTy == MVT::v64bf16) {2372    MVT HalfTy = typeSplit(VecTy).first;2373    SDValue BF16Vec = Op.getOperand(0);2374    SDValue Zeroes =2375        getInstr(Hexagon::V6_vxor, dl, HalfTy, {BF16Vec, BF16Vec}, DAG);2376    // Interleave zero vector with the bf16 vector, with zeroes in the lower2377    // half of each 32 bit lane, effectively extending the bf16 values to fp322378    // values.2379    SDValue ShuffVec =2380        getInstr(Hexagon::V6_vshufoeh, dl, VecTy, {BF16Vec, Zeroes}, DAG);2381    VectorPair VecPair = opSplit(ShuffVec, dl, DAG);2382    SDValue Result = getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,2383                              {VecPair.second, VecPair.first,2384                               DAG.getSignedConstant(-4, dl, MVT::i32)},2385                              DAG);2386    return Result;2387  }2388 2389  assert(VecTy == MVT::v64f32 && ArgTy == MVT::v64f16);2390 2391  SDValue F16Vec = Op.getOperand(0);2392 2393  APFloat FloatVal = APFloat(1.0f);2394  bool Ignored;2395  FloatVal.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored);2396  SDValue Fp16Ones = DAG.getConstantFP(FloatVal, dl, ArgTy);2397  SDValue VmpyVec =2398      getInstr(Hexagon::V6_vmpy_qf32_hf, dl, VecTy, {F16Vec, Fp16Ones}, DAG);2399 2400  MVT HalfTy = typeSplit(VecTy).first;2401  VectorPair Pair = opSplit(VmpyVec, dl, DAG);2402  SDValue LoVec =2403      getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.first}, DAG);2404  SDValue HiVec =2405      getInstr(Hexagon::V6_vconv_sf_qf32, dl, HalfTy, {Pair.second}, DAG);2406 2407  SDValue ShuffVec =2408      getInstr(Hexagon::V6_vshuffvdd, dl, VecTy,2409               {HiVec, LoVec, DAG.getSignedConstant(-4, dl, MVT::i32)}, DAG);2410 2411  return ShuffVec;2412}2413 2414SDValue2415HexagonTargetLowering::LowerHvxFpToInt(SDValue Op, SelectionDAG &DAG) const {2416  // Catch invalid conversion ops (just in case).2417  assert(Op.getOpcode() == ISD::FP_TO_SINT ||2418         Op.getOpcode() == ISD::FP_TO_UINT);2419 2420  MVT ResTy = ty(Op);2421  MVT FpTy = ty(Op.getOperand(0)).getVectorElementType();2422  MVT IntTy = ResTy.getVectorElementType();2423 2424  if (Subtarget.useHVXIEEEFPOps()) {2425    // There are only conversions from f16.2426    if (FpTy == MVT::f16) {2427      // Other int types aren't legal in HVX, so we shouldn't see them here.2428      assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);2429      // Conversions to i8 and i16 are legal.2430      if (IntTy == MVT::i8 || IntTy == MVT::i16)2431        return Op;2432    }2433  }2434 2435  if (IntTy.getSizeInBits() != FpTy.getSizeInBits())2436    return EqualizeFpIntConversion(Op, DAG);2437 2438  return ExpandHvxFpToInt(Op, DAG);2439}2440 2441// For vector type v32i1 uint_to_fp/sint_to_fp to v32f32:2442// R1 = #1, R2 holds the v32i1 param2443// V1 = vsplat(R1)2444// V2 = vsplat(R2)2445// Q0 = vand(V1,R1)2446// V0.w=prefixsum(Q0)2447// V0.w=vsub(V0.w,V1.w)2448// V2.w = vlsr(V2.w,V0.w)2449// V2 = vand(V2,V1)2450// V2.sf = V2.w2451SDValue HexagonTargetLowering::LowerHvxPred32ToFp(SDValue PredOp,2452                                                  SelectionDAG &DAG) const {2453 2454  MVT ResTy = ty(PredOp);2455  const SDLoc &dl(PredOp);2456 2457  SDValue Const = DAG.getTargetConstant(0x1, dl, MVT::i32);2458  SDNode *RegConst = DAG.getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);2459  SDNode *SplatConst = DAG.getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,2460                                          SDValue(RegConst, 0));2461  SDNode *PredTransfer =2462      DAG.getMachineNode(Hexagon::V6_vandvrt, dl, MVT::v32i1,2463                         SDValue(SplatConst, 0), SDValue(RegConst, 0));2464  SDNode *PrefixSum = DAG.getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,2465                                         SDValue(PredTransfer, 0));2466  SDNode *SplatParam = DAG.getMachineNode(2467      Hexagon::V6_lvsplatw, dl, MVT::v32i32,2468      DAG.getNode(ISD::BITCAST, dl, MVT::i32, PredOp.getOperand(0)));2469  SDNode *Vsub =2470      DAG.getMachineNode(Hexagon::V6_vsubw, dl, MVT::v32i32,2471                         SDValue(PrefixSum, 0), SDValue(SplatConst, 0));2472  SDNode *IndexShift =2473      DAG.getMachineNode(Hexagon::V6_vlsrwv, dl, MVT::v32i32,2474                         SDValue(SplatParam, 0), SDValue(Vsub, 0));2475  SDNode *MaskOff =2476      DAG.getMachineNode(Hexagon::V6_vand, dl, MVT::v32i32,2477                         SDValue(IndexShift, 0), SDValue(SplatConst, 0));2478  SDNode *Convert = DAG.getMachineNode(Hexagon::V6_vconv_sf_w, dl, ResTy,2479                                       SDValue(MaskOff, 0));2480  return SDValue(Convert, 0);2481}2482 2483// For vector type v64i1 uint_to_fo to v64f16:2484// i64 R32 = bitcast v64i1 R3:2 (R3:2 holds v64i1)2485// R3 = subreg_high (R32)2486// R2 = subreg_low (R32)2487// R1 = #12488// V1 = vsplat(R1)2489// V2 = vsplat(R2)2490// V3 = vsplat(R3)2491// Q0 = vand(V1,R1)2492// V0.w=prefixsum(Q0)2493// V0.w=vsub(V0.w,V1.w)2494// V2.w = vlsr(V2.w,V0.w)2495// V3.w = vlsr(V3.w,V0.w)2496// V2 = vand(V2,V1)2497// V3 = vand(V3,V1)2498// V2.h = vpacke(V3.w,V2.w)2499// V2.hf = V2.h2500SDValue HexagonTargetLowering::LowerHvxPred64ToFp(SDValue PredOp,2501                                                  SelectionDAG &DAG) const {2502 2503  MVT ResTy = ty(PredOp);2504  const SDLoc &dl(PredOp);2505 2506  SDValue Inp = DAG.getNode(ISD::BITCAST, dl, MVT::i64, PredOp.getOperand(0));2507  // Get the hi and lo regs2508  SDValue HiReg =2509      DAG.getTargetExtractSubreg(Hexagon::isub_hi, dl, MVT::i32, Inp);2510  SDValue LoReg =2511      DAG.getTargetExtractSubreg(Hexagon::isub_lo, dl, MVT::i32, Inp);2512  // Get constant #1 and splat into vector V12513  SDValue Const = DAG.getTargetConstant(0x1, dl, MVT::i32);2514  SDNode *RegConst = DAG.getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, Const);2515  SDNode *SplatConst = DAG.getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,2516                                          SDValue(RegConst, 0));2517  // Splat the hi and lo args2518  SDNode *SplatHi =2519      DAG.getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,2520                         DAG.getNode(ISD::BITCAST, dl, MVT::i32, HiReg));2521  SDNode *SplatLo =2522      DAG.getMachineNode(Hexagon::V6_lvsplatw, dl, MVT::v32i32,2523                         DAG.getNode(ISD::BITCAST, dl, MVT::i32, LoReg));2524  // vand between splatted const and const2525  SDNode *PredTransfer =2526      DAG.getMachineNode(Hexagon::V6_vandvrt, dl, MVT::v32i1,2527                         SDValue(SplatConst, 0), SDValue(RegConst, 0));2528  // Get the prefixsum2529  SDNode *PrefixSum = DAG.getMachineNode(Hexagon::V6_vprefixqw, dl, MVT::v32i32,2530                                         SDValue(PredTransfer, 0));2531  // Get the vsub2532  SDNode *Vsub =2533      DAG.getMachineNode(Hexagon::V6_vsubw, dl, MVT::v32i32,2534                         SDValue(PrefixSum, 0), SDValue(SplatConst, 0));2535  // Get vlsr for hi and lo2536  SDNode *IndexShift_hi =2537      DAG.getMachineNode(Hexagon::V6_vlsrwv, dl, MVT::v32i32,2538                         SDValue(SplatHi, 0), SDValue(Vsub, 0));2539  SDNode *IndexShift_lo =2540      DAG.getMachineNode(Hexagon::V6_vlsrwv, dl, MVT::v32i32,2541                         SDValue(SplatLo, 0), SDValue(Vsub, 0));2542  // Get vand of hi and lo2543  SDNode *MaskOff_hi =2544      DAG.getMachineNode(Hexagon::V6_vand, dl, MVT::v32i32,2545                         SDValue(IndexShift_hi, 0), SDValue(SplatConst, 0));2546  SDNode *MaskOff_lo =2547      DAG.getMachineNode(Hexagon::V6_vand, dl, MVT::v32i32,2548                         SDValue(IndexShift_lo, 0), SDValue(SplatConst, 0));2549  // Pack them2550  SDNode *Pack =2551      DAG.getMachineNode(Hexagon::V6_vpackeh, dl, MVT::v64i16,2552                         SDValue(MaskOff_hi, 0), SDValue(MaskOff_lo, 0));2553  SDNode *Convert =2554      DAG.getMachineNode(Hexagon::V6_vconv_hf_h, dl, ResTy, SDValue(Pack, 0));2555  return SDValue(Convert, 0);2556}2557 2558SDValue2559HexagonTargetLowering::LowerHvxIntToFp(SDValue Op, SelectionDAG &DAG) const {2560  // Catch invalid conversion ops (just in case).2561  assert(Op.getOpcode() == ISD::SINT_TO_FP ||2562         Op.getOpcode() == ISD::UINT_TO_FP);2563 2564  MVT ResTy = ty(Op);2565  MVT IntTy = ty(Op.getOperand(0)).getVectorElementType();2566  MVT FpTy = ResTy.getVectorElementType();2567 2568  if (Op.getOpcode() == ISD::UINT_TO_FP || Op.getOpcode() == ISD::SINT_TO_FP) {2569    if (ResTy == MVT::v32f32 && ty(Op.getOperand(0)) == MVT::v32i1)2570      return LowerHvxPred32ToFp(Op, DAG);2571    if (ResTy == MVT::v64f16 && ty(Op.getOperand(0)) == MVT::v64i1)2572      return LowerHvxPred64ToFp(Op, DAG);2573  }2574 2575  if (Subtarget.useHVXIEEEFPOps()) {2576    // There are only conversions to f16.2577    if (FpTy == MVT::f16) {2578      // Other int types aren't legal in HVX, so we shouldn't see them here.2579      assert(IntTy == MVT::i8 || IntTy == MVT::i16 || IntTy == MVT::i32);2580      // i8, i16 -> f16 is legal.2581      if (IntTy == MVT::i8 || IntTy == MVT::i16)2582        return Op;2583    }2584  }2585 2586  if (IntTy.getSizeInBits() != FpTy.getSizeInBits())2587    return EqualizeFpIntConversion(Op, DAG);2588 2589  return ExpandHvxIntToFp(Op, DAG);2590}2591 2592HexagonTargetLowering::TypePair2593HexagonTargetLowering::typeExtendToWider(MVT Ty0, MVT Ty1) const {2594  // Compare the widths of elements of the two types, and extend the narrower2595  // type to match the with of the wider type. For vector types, apply this2596  // to the element type.2597  assert(Ty0.isVector() == Ty1.isVector());2598 2599  MVT ElemTy0 = Ty0.getScalarType();2600  MVT ElemTy1 = Ty1.getScalarType();2601 2602  unsigned Width0 = ElemTy0.getSizeInBits();2603  unsigned Width1 = ElemTy1.getSizeInBits();2604  unsigned MaxWidth = std::max(Width0, Width1);2605 2606  auto getScalarWithWidth = [](MVT ScalarTy, unsigned Width) {2607    if (ScalarTy.isInteger())2608      return MVT::getIntegerVT(Width);2609    assert(ScalarTy.isFloatingPoint());2610    return MVT::getFloatingPointVT(Width);2611  };2612 2613  MVT WideETy0 = getScalarWithWidth(ElemTy0, MaxWidth);2614  MVT WideETy1 = getScalarWithWidth(ElemTy1, MaxWidth);2615 2616  if (!Ty0.isVector()) {2617    // Both types are scalars.2618    return {WideETy0, WideETy1};2619  }2620 2621  // Vector types.2622  unsigned NumElem = Ty0.getVectorNumElements();2623  assert(NumElem == Ty1.getVectorNumElements());2624 2625  return {MVT::getVectorVT(WideETy0, NumElem),2626          MVT::getVectorVT(WideETy1, NumElem)};2627}2628 2629HexagonTargetLowering::TypePair2630HexagonTargetLowering::typeWidenToWider(MVT Ty0, MVT Ty1) const {2631  // Compare the numbers of elements of two vector types, and widen the2632  // narrower one to match the number of elements in the wider one.2633  assert(Ty0.isVector() && Ty1.isVector());2634 2635  unsigned Len0 = Ty0.getVectorNumElements();2636  unsigned Len1 = Ty1.getVectorNumElements();2637  if (Len0 == Len1)2638    return {Ty0, Ty1};2639 2640  unsigned MaxLen = std::max(Len0, Len1);2641  return {MVT::getVectorVT(Ty0.getVectorElementType(), MaxLen),2642          MVT::getVectorVT(Ty1.getVectorElementType(), MaxLen)};2643}2644 2645MVT2646HexagonTargetLowering::typeLegalize(MVT Ty, SelectionDAG &DAG) const {2647  EVT LegalTy = getTypeToTransformTo(*DAG.getContext(), Ty);2648  assert(LegalTy.isSimple());2649  return LegalTy.getSimpleVT();2650}2651 2652MVT2653HexagonTargetLowering::typeWidenToHvx(MVT Ty) const {2654  unsigned HwWidth = 8 * Subtarget.getVectorLength();2655  assert(Ty.getSizeInBits() <= HwWidth);2656  if (Ty.getSizeInBits() == HwWidth)2657    return Ty;2658 2659  MVT ElemTy = Ty.getScalarType();2660  return MVT::getVectorVT(ElemTy, HwWidth / ElemTy.getSizeInBits());2661}2662 2663HexagonTargetLowering::VectorPair2664HexagonTargetLowering::emitHvxAddWithOverflow(SDValue A, SDValue B,2665      const SDLoc &dl, bool Signed, SelectionDAG &DAG) const {2666  // Compute A+B, return {A+B, O}, where O = vector predicate indicating2667  // whether an overflow has occurred.2668  MVT ResTy = ty(A);2669  assert(ResTy == ty(B));2670  MVT PredTy = MVT::getVectorVT(MVT::i1, ResTy.getVectorNumElements());2671 2672  if (!Signed) {2673    // V62+ has V6_vaddcarry, but it requires input predicate, so it doesn't2674    // save any instructions.2675    SDValue Add = DAG.getNode(ISD::ADD, dl, ResTy, {A, B});2676    SDValue Ovf = DAG.getSetCC(dl, PredTy, Add, A, ISD::SETULT);2677    return {Add, Ovf};2678  }2679 2680  // Signed overflow has happened, if:2681  // (A, B have the same sign) and (A+B has a different sign from either)2682  // i.e. (~A xor B) & ((A+B) xor B), then check the sign bit2683  SDValue Add = DAG.getNode(ISD::ADD, dl, ResTy, {A, B});2684  SDValue NotA =2685      DAG.getNode(ISD::XOR, dl, ResTy, {A, DAG.getAllOnesConstant(dl, ResTy)});2686  SDValue Xor0 = DAG.getNode(ISD::XOR, dl, ResTy, {NotA, B});2687  SDValue Xor1 = DAG.getNode(ISD::XOR, dl, ResTy, {Add, B});2688  SDValue And = DAG.getNode(ISD::AND, dl, ResTy, {Xor0, Xor1});2689  SDValue MSB =2690      DAG.getSetCC(dl, PredTy, And, getZero(dl, ResTy, DAG), ISD::SETLT);2691  return {Add, MSB};2692}2693 2694HexagonTargetLowering::VectorPair2695HexagonTargetLowering::emitHvxShiftRightRnd(SDValue Val, unsigned Amt,2696      bool Signed, SelectionDAG &DAG) const {2697  // Shift Val right by Amt bits, round the result to the nearest integer,2698  // tie-break by rounding halves to even integer.2699 2700  const SDLoc &dl(Val);2701  MVT ValTy = ty(Val);2702 2703  // This should also work for signed integers.2704  //2705  //   uint tmp0 = inp + ((1 << (Amt-1)) - 1);2706  //   bool ovf = (inp > tmp0);2707  //   uint rup = inp & (1 << (Amt+1));2708  //2709  //   uint tmp1 = inp >> (Amt-1);    // tmp1 == tmp2 iff2710  //   uint tmp2 = tmp0 >> (Amt-1);   // the Amt-1 lower bits were all 02711  //   uint tmp3 = tmp2 + rup;2712  //   uint frac = (tmp1 != tmp2) ? tmp2 >> 1 : tmp3 >> 1;2713  unsigned ElemWidth = ValTy.getVectorElementType().getSizeInBits();2714  MVT ElemTy = MVT::getIntegerVT(ElemWidth);2715  MVT IntTy = tyVector(ValTy, ElemTy);2716  MVT PredTy = MVT::getVectorVT(MVT::i1, IntTy.getVectorNumElements());2717  unsigned ShRight = Signed ? ISD::SRA : ISD::SRL;2718 2719  SDValue Inp = DAG.getBitcast(IntTy, Val);2720  SDValue LowBits = DAG.getConstant((1ull << (Amt - 1)) - 1, dl, IntTy);2721 2722  SDValue AmtP1 = DAG.getConstant(1ull << Amt, dl, IntTy);2723  SDValue And = DAG.getNode(ISD::AND, dl, IntTy, {Inp, AmtP1});2724  SDValue Zero = getZero(dl, IntTy, DAG);2725  SDValue Bit = DAG.getSetCC(dl, PredTy, And, Zero, ISD::SETNE);2726  SDValue Rup = DAG.getZExtOrTrunc(Bit, dl, IntTy);2727  auto [Tmp0, Ovf] = emitHvxAddWithOverflow(Inp, LowBits, dl, Signed, DAG);2728 2729  SDValue AmtM1 = DAG.getConstant(Amt - 1, dl, IntTy);2730  SDValue Tmp1 = DAG.getNode(ShRight, dl, IntTy, Inp, AmtM1);2731  SDValue Tmp2 = DAG.getNode(ShRight, dl, IntTy, Tmp0, AmtM1);2732  SDValue Tmp3 = DAG.getNode(ISD::ADD, dl, IntTy, Tmp2, Rup);2733 2734  SDValue Eq = DAG.getSetCC(dl, PredTy, Tmp1, Tmp2, ISD::SETEQ);2735  SDValue One = DAG.getConstant(1, dl, IntTy);2736  SDValue Tmp4 = DAG.getNode(ShRight, dl, IntTy, {Tmp2, One});2737  SDValue Tmp5 = DAG.getNode(ShRight, dl, IntTy, {Tmp3, One});2738  SDValue Mux = DAG.getNode(ISD::VSELECT, dl, IntTy, {Eq, Tmp5, Tmp4});2739  return {Mux, Ovf};2740}2741 2742SDValue2743HexagonTargetLowering::emitHvxMulHsV60(SDValue A, SDValue B, const SDLoc &dl,2744                                       SelectionDAG &DAG) const {2745  MVT VecTy = ty(A);2746  MVT PairTy = typeJoin({VecTy, VecTy});2747  assert(VecTy.getVectorElementType() == MVT::i32);2748 2749  SDValue S16 = DAG.getConstant(16, dl, MVT::i32);2750 2751  // mulhs(A,B) =2752  //   = [(Hi(A)*2^16 + Lo(A)) *s (Hi(B)*2^16 + Lo(B))] >> 322753  //   = [Hi(A)*2^16 *s Hi(B)*2^16 + Hi(A) *su Lo(B)*2^162754  //      + Lo(A) *us (Hi(B)*2^16 + Lo(B))] >> 322755  //   = [Hi(A) *s Hi(B)*2^32 + Hi(A) *su Lo(B)*2^16 + Lo(A) *us B] >> 322756  // The low half of Lo(A)*Lo(B) will be discarded (it's not added to2757  // anything, so it cannot produce any carry over to higher bits),2758  // so everything in [] can be shifted by 16 without loss of precision.2759  //   = [Hi(A) *s Hi(B)*2^16 + Hi(A)*su Lo(B) + Lo(A)*B >> 16] >> 162760  //   = [Hi(A) *s Hi(B)*2^16 + Hi(A)*su Lo(B) + V6_vmpyewuh(A,B)] >> 162761  // The final additions need to make sure to properly maintain any carry-2762  // out bits.2763  //2764  //                Hi(B) Lo(B)2765  //                Hi(A) Lo(A)2766  //               --------------2767  //                Lo(B)*Lo(A)  | T0 = V6_vmpyewuh(B,A) does this,2768  //         Hi(B)*Lo(A)         |      + dropping the low 16 bits2769  //         Hi(A)*Lo(B)   | T22770  //  Hi(B)*Hi(A)2771 2772  SDValue T0 = getInstr(Hexagon::V6_vmpyewuh, dl, VecTy, {B, A}, DAG);2773  // T1 = get Hi(A) into low halves.2774  SDValue T1 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {A, S16}, DAG);2775  // P0 = interleaved T1.h*B.uh (full precision product)2776  SDValue P0 = getInstr(Hexagon::V6_vmpyhus, dl, PairTy, {T1, B}, DAG);2777  // T2 = T1.even(h) * B.even(uh), i.e. Hi(A)*Lo(B)2778  SDValue T2 = LoHalf(P0, DAG);2779  // We need to add T0+T2, recording the carry-out, which will be 1<<162780  // added to the final sum.2781  // P1 = interleaved even/odd 32-bit (unsigned) sums of 16-bit halves2782  SDValue P1 = getInstr(Hexagon::V6_vadduhw, dl, PairTy, {T0, T2}, DAG);2783  // P2 = interleaved even/odd 32-bit (signed) sums of 16-bit halves2784  SDValue P2 = getInstr(Hexagon::V6_vaddhw, dl, PairTy, {T0, T2}, DAG);2785  // T3 = full-precision(T0+T2) >> 162786  // The low halves are added-unsigned, the high ones are added-signed.2787  SDValue T3 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,2788                        {HiHalf(P2, DAG), LoHalf(P1, DAG), S16}, DAG);2789  SDValue T4 = getInstr(Hexagon::V6_vasrw, dl, VecTy, {B, S16}, DAG);2790  // P3 = interleaved Hi(B)*Hi(A) (full precision),2791  // which is now Lo(T1)*Lo(T4), so we want to keep the even product.2792  SDValue P3 = getInstr(Hexagon::V6_vmpyhv, dl, PairTy, {T1, T4}, DAG);2793  SDValue T5 = LoHalf(P3, DAG);2794  // Add:2795  SDValue T6 = DAG.getNode(ISD::ADD, dl, VecTy, {T3, T5});2796  return T6;2797}2798 2799SDValue2800HexagonTargetLowering::emitHvxMulLoHiV60(SDValue A, bool SignedA, SDValue B,2801                                         bool SignedB, const SDLoc &dl,2802                                         SelectionDAG &DAG) const {2803  MVT VecTy = ty(A);2804  MVT PairTy = typeJoin({VecTy, VecTy});2805  assert(VecTy.getVectorElementType() == MVT::i32);2806 2807  SDValue S16 = DAG.getConstant(16, dl, MVT::i32);2808 2809  if (SignedA && !SignedB) {2810    // Make A:unsigned, B:signed.2811    std::swap(A, B);2812    std::swap(SignedA, SignedB);2813  }2814 2815  // Do halfword-wise multiplications for unsigned*unsigned product, then2816  // add corrections for signed and unsigned*signed.2817 2818  SDValue Lo, Hi;2819 2820  // P0:lo = (uu) products of low halves of A and B,2821  // P0:hi = (uu) products of high halves.2822  SDValue P0 = getInstr(Hexagon::V6_vmpyuhv, dl, PairTy, {A, B}, DAG);2823 2824  // Swap low/high halves in B2825  SDValue T0 = getInstr(Hexagon::V6_lvsplatw, dl, VecTy,2826                        {DAG.getConstant(0x02020202, dl, MVT::i32)}, DAG);2827  SDValue T1 = getInstr(Hexagon::V6_vdelta, dl, VecTy, {B, T0}, DAG);2828  // P1 = products of even/odd halfwords.2829  // P1:lo = (uu) products of even(A.uh) * odd(B.uh)2830  // P1:hi = (uu) products of odd(A.uh) * even(B.uh)2831  SDValue P1 = getInstr(Hexagon::V6_vmpyuhv, dl, PairTy, {A, T1}, DAG);2832 2833  // P2:lo = low halves of P1:lo + P1:hi,2834  // P2:hi = high halves of P1:lo + P1:hi.2835  SDValue P2 = getInstr(Hexagon::V6_vadduhw, dl, PairTy,2836                        {HiHalf(P1, DAG), LoHalf(P1, DAG)}, DAG);2837  // Still need to add the high halves of P0:lo to P2:lo2838  SDValue T2 =2839      getInstr(Hexagon::V6_vlsrw, dl, VecTy, {LoHalf(P0, DAG), S16}, DAG);2840  SDValue T3 = DAG.getNode(ISD::ADD, dl, VecTy, {LoHalf(P2, DAG), T2});2841 2842  // The high halves of T3 will contribute to the HI part of LOHI.2843  SDValue T4 = getInstr(Hexagon::V6_vasrw_acc, dl, VecTy,2844                        {HiHalf(P2, DAG), T3, S16}, DAG);2845 2846  // The low halves of P2 need to be added to high halves of the LO part.2847  Lo = getInstr(Hexagon::V6_vaslw_acc, dl, VecTy,2848                {LoHalf(P0, DAG), LoHalf(P2, DAG), S16}, DAG);2849  Hi = DAG.getNode(ISD::ADD, dl, VecTy, {HiHalf(P0, DAG), T4});2850 2851  if (SignedA) {2852    assert(SignedB && "Signed A and unsigned B should have been inverted");2853 2854    MVT PredTy = MVT::getVectorVT(MVT::i1, VecTy.getVectorNumElements());2855    SDValue Zero = getZero(dl, VecTy, DAG);2856    SDValue Q0 = DAG.getSetCC(dl, PredTy, A, Zero, ISD::SETLT);2857    SDValue Q1 = DAG.getSetCC(dl, PredTy, B, Zero, ISD::SETLT);2858    SDValue X0 = DAG.getNode(ISD::VSELECT, dl, VecTy, {Q0, B, Zero});2859    SDValue X1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, X0, A}, DAG);2860    Hi = getInstr(Hexagon::V6_vsubw, dl, VecTy, {Hi, X1}, DAG);2861  } else if (SignedB) {2862    // Same correction as for mulhus:2863    // mulhus(A.uw,B.w) = mulhu(A.uw,B.uw) - (A.w if B < 0)2864    MVT PredTy = MVT::getVectorVT(MVT::i1, VecTy.getVectorNumElements());2865    SDValue Zero = getZero(dl, VecTy, DAG);2866    SDValue Q1 = DAG.getSetCC(dl, PredTy, B, Zero, ISD::SETLT);2867    Hi = getInstr(Hexagon::V6_vsubwq, dl, VecTy, {Q1, Hi, A}, DAG);2868  } else {2869    assert(!SignedA && !SignedB);2870  }2871 2872  return DAG.getMergeValues({Lo, Hi}, dl);2873}2874 2875SDValue2876HexagonTargetLowering::emitHvxMulLoHiV62(SDValue A, bool SignedA,2877                                         SDValue B, bool SignedB,2878                                         const SDLoc &dl,2879                                         SelectionDAG &DAG) const {2880  MVT VecTy = ty(A);2881  MVT PairTy = typeJoin({VecTy, VecTy});2882  assert(VecTy.getVectorElementType() == MVT::i32);2883 2884  if (SignedA && !SignedB) {2885    // Make A:unsigned, B:signed.2886    std::swap(A, B);2887    std::swap(SignedA, SignedB);2888  }2889 2890  // Do S*S first, then make corrections for U*S or U*U if needed.2891  SDValue P0 = getInstr(Hexagon::V6_vmpyewuh_64, dl, PairTy, {A, B}, DAG);2892  SDValue P1 =2893      getInstr(Hexagon::V6_vmpyowh_64_acc, dl, PairTy, {P0, A, B}, DAG);2894  SDValue Lo = LoHalf(P1, DAG);2895  SDValue Hi = HiHalf(P1, DAG);2896 2897  if (!SignedB) {2898    assert(!SignedA && "Signed A and unsigned B should have been inverted");2899    SDValue Zero = getZero(dl, VecTy, DAG);2900    MVT PredTy = MVT::getVectorVT(MVT::i1, VecTy.getVectorNumElements());2901 2902    // Mulhu(X, Y) = Mulhs(X, Y) + (X, if Y < 0) + (Y, if X < 0).2903    // def: Pat<(VecI32 (mulhu HVI32:$A, HVI32:$B)),2904    //          (V6_vaddw (HiHalf (Muls64O $A, $B)),2905    //                    (V6_vaddwq (V6_vgtw (V6_vd0), $B),2906    //                               (V6_vandvqv (V6_vgtw (V6_vd0), $A), $B),2907    //                               $A))>;2908    SDValue Q0 = DAG.getSetCC(dl, PredTy, A, Zero, ISD::SETLT);2909    SDValue Q1 = DAG.getSetCC(dl, PredTy, B, Zero, ISD::SETLT);2910    SDValue T0 = getInstr(Hexagon::V6_vandvqv, dl, VecTy, {Q0, B}, DAG);2911    SDValue T1 = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q1, T0, A}, DAG);2912    Hi = getInstr(Hexagon::V6_vaddw, dl, VecTy, {Hi, T1}, DAG);2913  } else if (!SignedA) {2914    SDValue Zero = getZero(dl, VecTy, DAG);2915    MVT PredTy = MVT::getVectorVT(MVT::i1, VecTy.getVectorNumElements());2916 2917    // Mulhus(unsigned X, signed Y) = Mulhs(X, Y) + (Y, if X < 0).2918    // def: Pat<(VecI32 (HexagonMULHUS HVI32:$A, HVI32:$B)),2919    //          (V6_vaddwq (V6_vgtw (V6_vd0), $A),2920    //                     (HiHalf (Muls64O $A, $B)),2921    //                     $B)>;2922    SDValue Q0 = DAG.getSetCC(dl, PredTy, A, Zero, ISD::SETLT);2923    Hi = getInstr(Hexagon::V6_vaddwq, dl, VecTy, {Q0, Hi, B}, DAG);2924  }2925 2926  return DAG.getMergeValues({Lo, Hi}, dl);2927}2928 2929SDValue2930HexagonTargetLowering::EqualizeFpIntConversion(SDValue Op, SelectionDAG &DAG)2931      const {2932  // Rewrite conversion between integer and floating-point in such a way that2933  // the integer type is extended/narrowed to match the bitwidth of the2934  // floating-point type, combined with additional integer-integer extensions2935  // or narrowings to match the original input/result types.2936  // E.g.  f32 -> i8  ==>  f32 -> i32 -> i82937  //2938  // The input/result types are not required to be legal, but if they are2939  // legal, this function should not introduce illegal types.2940 2941  unsigned Opc = Op.getOpcode();2942  assert(Opc == ISD::FP_TO_SINT || Opc == ISD::FP_TO_UINT ||2943         Opc == ISD::SINT_TO_FP || Opc == ISD::UINT_TO_FP);2944 2945  SDValue Inp = Op.getOperand(0);2946  MVT InpTy = ty(Inp);2947  MVT ResTy = ty(Op);2948 2949  if (InpTy == ResTy)2950    return Op;2951 2952  const SDLoc &dl(Op);2953  bool Signed = Opc == ISD::FP_TO_SINT || Opc == ISD::SINT_TO_FP;2954 2955  auto [WInpTy, WResTy] = typeExtendToWider(InpTy, ResTy);2956  SDValue WInp = resizeToWidth(Inp, WInpTy, Signed, dl, DAG);2957  SDValue Conv = DAG.getNode(Opc, dl, WResTy, WInp);2958  SDValue Res = resizeToWidth(Conv, ResTy, Signed, dl, DAG);2959  return Res;2960}2961 2962SDValue2963HexagonTargetLowering::ExpandHvxFpToInt(SDValue Op, SelectionDAG &DAG) const {2964  unsigned Opc = Op.getOpcode();2965  assert(Opc == ISD::FP_TO_SINT || Opc == ISD::FP_TO_UINT);2966 2967  const SDLoc &dl(Op);2968  SDValue Op0 = Op.getOperand(0);2969  MVT InpTy = ty(Op0);2970  MVT ResTy = ty(Op);2971  assert(InpTy.changeTypeToInteger() == ResTy);2972 2973  // int32_t conv_f32_to_i32(uint32_t inp) {2974  //   // s | exp8 | frac232975  //2976  //   int neg = (int32_t)inp < 0;2977  //2978  //   // "expm1" is the actual exponent minus 1: instead of "bias", subtract2979  //   // "bias+1". When the encoded exp is "all-1" (i.e. inf/nan), this will2980  //   // produce a large positive "expm1", which will result in max u/int.2981  //   // In all IEEE formats, bias is the largest positive number that can be2982  //   // represented in bias-width bits (i.e. 011..1).2983  //   int32_t expm1 = (inp << 1) - 0x80000000;2984  //   expm1 >>= 24;2985  //2986  //   // Always insert the "implicit 1". Subnormal numbers will become 02987  //   // regardless.2988  //   uint32_t frac = (inp << 8) | 0x80000000;2989  //2990  //   // "frac" is the fraction part represented as Q1.31. If it was2991  //   // interpreted as uint32_t, it would be the fraction part multiplied2992  //   // by 2^31.2993  //2994  //   // Calculate the amount of right shift, since shifting further to the2995  //   // left would lose significant bits. Limit it to 32, because we want2996  //   // shifts by 32+ to produce 0, whereas V6_vlsrwv treats the shift2997  //   // amount as a 6-bit signed value (so 33 is same as -31, i.e. shift2998  //   // left by 31). "rsh" can be negative.2999  //   int32_t rsh = min(31 - (expm1 + 1), 32);3000  //3001  //   frac >>= rsh;   // rsh == 32 will produce 03002  //3003  //   // Everything up to this point is the same for conversion to signed3004  //   // unsigned integer.3005  //3006  //   if (neg)                 // Only for signed int3007  //     frac = -frac;          //3008  //   if (rsh <= 0 && neg)     //   bound = neg ? 0x80000000 : 0x7fffffff3009  //     frac = 0x80000000;     //   frac = rsh <= 0 ? bound : frac3010  //   if (rsh <= 0 && !neg)    //3011  //     frac = 0x7fffffff;     //3012  //3013  //   if (neg)                 // Only for unsigned int3014  //     frac = 0;              //3015  //   if (rsh < 0 && !neg)     //   frac = rsh < 0 ? 0x7fffffff : frac;3016  //     frac = 0x7fffffff;     //   frac = neg ? 0 : frac;3017  //3018  //   return frac;3019  // }3020 3021  MVT PredTy = MVT::getVectorVT(MVT::i1, ResTy.getVectorElementCount());3022 3023  // Zero = V6_vd0();3024  // Neg = V6_vgtw(Zero, Inp);3025  // One = V6_lvsplatw(1);3026  // M80 = V6_lvsplatw(0x80000000);3027  // Exp00 = V6_vaslwv(Inp, One);3028  // Exp01 = V6_vsubw(Exp00, M80);3029  // ExpM1 = V6_vasrw(Exp01, 24);3030  // Frc00 = V6_vaslw(Inp, 8);3031  // Frc01 = V6_vor(Frc00, M80);3032  // Rsh00 = V6_vsubw(V6_lvsplatw(30), ExpM1);3033  // Rsh01 = V6_vminw(Rsh00, V6_lvsplatw(32));3034  // Frc02 = V6_vlsrwv(Frc01, Rsh01);3035 3036  // if signed int:3037  // Bnd = V6_vmux(Neg, M80, V6_lvsplatw(0x7fffffff))3038  // Pos = V6_vgtw(Rsh01, Zero);3039  // Frc13 = V6_vsubw(Zero, Frc02);3040  // Frc14 = V6_vmux(Neg, Frc13, Frc02);3041  // Int = V6_vmux(Pos, Frc14, Bnd);3042  //3043  // if unsigned int:3044  // Rsn = V6_vgtw(Zero, Rsh01)3045  // Frc23 = V6_vmux(Rsn, V6_lvsplatw(0x7fffffff), Frc02)3046  // Int = V6_vmux(Neg, Zero, Frc23)3047 3048  auto [ExpWidth, ExpBias, FracWidth] = getIEEEProperties(InpTy);3049  unsigned ElemWidth = 1 + ExpWidth + FracWidth;3050  assert((1ull << (ExpWidth - 1)) == (1 + ExpBias));3051 3052  SDValue Inp = DAG.getBitcast(ResTy, Op0);3053  SDValue Zero = getZero(dl, ResTy, DAG);3054  SDValue Neg = DAG.getSetCC(dl, PredTy, Inp, Zero, ISD::SETLT);3055  SDValue M80 = DAG.getConstant(1ull << (ElemWidth - 1), dl, ResTy);3056  SDValue M7F = DAG.getConstant((1ull << (ElemWidth - 1)) - 1, dl, ResTy);3057  SDValue One = DAG.getConstant(1, dl, ResTy);3058  SDValue Exp00 = DAG.getNode(ISD::SHL, dl, ResTy, {Inp, One});3059  SDValue Exp01 = DAG.getNode(ISD::SUB, dl, ResTy, {Exp00, M80});3060  SDValue MNE = DAG.getConstant(ElemWidth - ExpWidth, dl, ResTy);3061  SDValue ExpM1 = DAG.getNode(ISD::SRA, dl, ResTy, {Exp01, MNE});3062 3063  SDValue ExpW = DAG.getConstant(ExpWidth, dl, ResTy);3064  SDValue Frc00 = DAG.getNode(ISD::SHL, dl, ResTy, {Inp, ExpW});3065  SDValue Frc01 = DAG.getNode(ISD::OR, dl, ResTy, {Frc00, M80});3066 3067  SDValue MN2 = DAG.getConstant(ElemWidth - 2, dl, ResTy);3068  SDValue Rsh00 = DAG.getNode(ISD::SUB, dl, ResTy, {MN2, ExpM1});3069  SDValue MW = DAG.getConstant(ElemWidth, dl, ResTy);3070  SDValue Rsh01 = DAG.getNode(ISD::SMIN, dl, ResTy, {Rsh00, MW});3071  SDValue Frc02 = DAG.getNode(ISD::SRL, dl, ResTy, {Frc01, Rsh01});3072 3073  SDValue Int;3074 3075  if (Opc == ISD::FP_TO_SINT) {3076    SDValue Bnd = DAG.getNode(ISD::VSELECT, dl, ResTy, {Neg, M80, M7F});3077    SDValue Pos = DAG.getSetCC(dl, PredTy, Rsh01, Zero, ISD::SETGT);3078    SDValue Frc13 = DAG.getNode(ISD::SUB, dl, ResTy, {Zero, Frc02});3079    SDValue Frc14 = DAG.getNode(ISD::VSELECT, dl, ResTy, {Neg, Frc13, Frc02});3080    Int = DAG.getNode(ISD::VSELECT, dl, ResTy, {Pos, Frc14, Bnd});3081  } else {3082    assert(Opc == ISD::FP_TO_UINT);3083    SDValue Rsn = DAG.getSetCC(dl, PredTy, Rsh01, Zero, ISD::SETLT);3084    SDValue Frc23 = DAG.getNode(ISD::VSELECT, dl, ResTy, Rsn, M7F, Frc02);3085    Int = DAG.getNode(ISD::VSELECT, dl, ResTy, Neg, Zero, Frc23);3086  }3087 3088  return Int;3089}3090 3091SDValue3092HexagonTargetLowering::ExpandHvxIntToFp(SDValue Op, SelectionDAG &DAG) const {3093  unsigned Opc = Op.getOpcode();3094  assert(Opc == ISD::SINT_TO_FP || Opc == ISD::UINT_TO_FP);3095 3096  const SDLoc &dl(Op);3097  SDValue Op0 = Op.getOperand(0);3098  MVT InpTy = ty(Op0);3099  MVT ResTy = ty(Op);3100  assert(ResTy.changeTypeToInteger() == InpTy);3101 3102  // uint32_t vnoc1_rnd(int32_t w) {3103  //   int32_t iszero = w == 0;3104  //   int32_t isneg = w < 0;3105  //   uint32_t u = __builtin_HEXAGON_A2_abs(w);3106  //3107  //   uint32_t norm_left = __builtin_HEXAGON_S2_cl0(u) + 1;3108  //   uint32_t frac0 = (uint64_t)u << norm_left;3109  //3110  //   // Rounding:3111  //   uint32_t frac1 = frac0 + ((1 << 8) - 1);3112  //   uint32_t renorm = (frac0 > frac1);3113  //   uint32_t rup = (int)(frac0 << 22) < 0;3114  //3115  //   uint32_t frac2 = frac0 >> 8;3116  //   uint32_t frac3 = frac1 >> 8;3117  //   uint32_t frac = (frac2 != frac3) ? frac3 >> 1 : (frac3 + rup) >> 1;3118  //3119  //   int32_t exp = 32 - norm_left + renorm + 127;3120  //   exp <<= 23;3121  //3122  //   uint32_t sign = 0x80000000 * isneg;3123  //   uint32_t f = sign | exp | frac;3124  //   return iszero ? 0 : f;3125  // }3126 3127  MVT PredTy = MVT::getVectorVT(MVT::i1, InpTy.getVectorElementCount());3128  bool Signed = Opc == ISD::SINT_TO_FP;3129 3130  auto [ExpWidth, ExpBias, FracWidth] = getIEEEProperties(ResTy);3131  unsigned ElemWidth = 1 + ExpWidth + FracWidth;3132 3133  SDValue Zero = getZero(dl, InpTy, DAG);3134  SDValue One = DAG.getConstant(1, dl, InpTy);3135  SDValue IsZero = DAG.getSetCC(dl, PredTy, Op0, Zero, ISD::SETEQ);3136  SDValue Abs = Signed ? DAG.getNode(ISD::ABS, dl, InpTy, Op0) : Op0;3137  SDValue Clz = DAG.getNode(ISD::CTLZ, dl, InpTy, Abs);3138  SDValue NLeft = DAG.getNode(ISD::ADD, dl, InpTy, {Clz, One});3139  SDValue Frac0 = DAG.getNode(ISD::SHL, dl, InpTy, {Abs, NLeft});3140 3141  auto [Frac, Ovf] = emitHvxShiftRightRnd(Frac0, ExpWidth + 1, false, DAG);3142  if (Signed) {3143    SDValue IsNeg = DAG.getSetCC(dl, PredTy, Op0, Zero, ISD::SETLT);3144    SDValue M80 = DAG.getConstant(1ull << (ElemWidth - 1), dl, InpTy);3145    SDValue Sign = DAG.getNode(ISD::VSELECT, dl, InpTy, {IsNeg, M80, Zero});3146    Frac = DAG.getNode(ISD::OR, dl, InpTy, {Sign, Frac});3147  }3148 3149  SDValue Rnrm = DAG.getZExtOrTrunc(Ovf, dl, InpTy);3150  SDValue Exp0 = DAG.getConstant(ElemWidth + ExpBias, dl, InpTy);3151  SDValue Exp1 = DAG.getNode(ISD::ADD, dl, InpTy, {Rnrm, Exp0});3152  SDValue Exp2 = DAG.getNode(ISD::SUB, dl, InpTy, {Exp1, NLeft});3153  SDValue Exp3 = DAG.getNode(ISD::SHL, dl, InpTy,3154                             {Exp2, DAG.getConstant(FracWidth, dl, InpTy)});3155  SDValue Flt0 = DAG.getNode(ISD::OR, dl, InpTy, {Frac, Exp3});3156  SDValue Flt1 = DAG.getNode(ISD::VSELECT, dl, InpTy, {IsZero, Zero, Flt0});3157  SDValue Flt = DAG.getBitcast(ResTy, Flt1);3158 3159  return Flt;3160}3161 3162SDValue3163HexagonTargetLowering::CreateTLWrapper(SDValue Op, SelectionDAG &DAG) const {3164  unsigned Opc = Op.getOpcode();3165  unsigned TLOpc;3166  switch (Opc) {3167  case ISD::ANY_EXTEND:3168  case ISD::SIGN_EXTEND:3169  case ISD::ZERO_EXTEND:3170    TLOpc = HexagonISD::TL_EXTEND;3171    break;3172  case ISD::TRUNCATE:3173    TLOpc = HexagonISD::TL_TRUNCATE;3174    break;3175#ifndef NDEBUG3176    Op.dump(&DAG);3177#endif3178    llvm_unreachable("Unexpected operator");3179  }3180 3181  const SDLoc &dl(Op);3182  return DAG.getNode(TLOpc, dl, ty(Op), Op.getOperand(0),3183                     DAG.getUNDEF(MVT::i128), // illegal type3184                     DAG.getConstant(Opc, dl, MVT::i32));3185}3186 3187SDValue3188HexagonTargetLowering::RemoveTLWrapper(SDValue Op, SelectionDAG &DAG) const {3189  assert(Op.getOpcode() == HexagonISD::TL_EXTEND ||3190         Op.getOpcode() == HexagonISD::TL_TRUNCATE);3191  unsigned Opc = Op.getConstantOperandVal(2);3192  return DAG.getNode(Opc, SDLoc(Op), ty(Op), Op.getOperand(0));3193}3194 3195HexagonTargetLowering::VectorPair3196HexagonTargetLowering::SplitVectorOp(SDValue Op, SelectionDAG &DAG) const {3197  assert(!Op.isMachineOpcode());3198  SmallVector<SDValue, 2> OpsL, OpsH;3199  const SDLoc &dl(Op);3200 3201  auto SplitVTNode = [&DAG, this](const VTSDNode *N) {3202    MVT Ty = typeSplit(N->getVT().getSimpleVT()).first;3203    SDValue TV = DAG.getValueType(Ty);3204    return std::make_pair(TV, TV);3205  };3206 3207  for (SDValue A : Op.getNode()->ops()) {3208    auto [Lo, Hi] =3209        ty(A).isVector() ? opSplit(A, dl, DAG) : std::make_pair(A, A);3210    // Special case for type operand.3211    switch (Op.getOpcode()) {3212      case ISD::SIGN_EXTEND_INREG:3213      case HexagonISD::SSAT:3214      case HexagonISD::USAT:3215        if (const auto *N = dyn_cast<const VTSDNode>(A.getNode()))3216          std::tie(Lo, Hi) = SplitVTNode(N);3217      break;3218    }3219    OpsL.push_back(Lo);3220    OpsH.push_back(Hi);3221  }3222 3223  MVT ResTy = ty(Op);3224  MVT HalfTy = typeSplit(ResTy).first;3225  SDValue L = DAG.getNode(Op.getOpcode(), dl, HalfTy, OpsL);3226  SDValue H = DAG.getNode(Op.getOpcode(), dl, HalfTy, OpsH);3227  return {L, H};3228}3229 3230SDValue3231HexagonTargetLowering::SplitHvxMemOp(SDValue Op, SelectionDAG &DAG) const {3232  auto *MemN = cast<MemSDNode>(Op.getNode());3233 3234  if (!MemN->getMemoryVT().isSimple())3235    return Op;3236 3237  MVT MemTy = MemN->getMemoryVT().getSimpleVT();3238  if (!isHvxPairTy(MemTy))3239    return Op;3240 3241  const SDLoc &dl(Op);3242  unsigned HwLen = Subtarget.getVectorLength();3243  MVT SingleTy = typeSplit(MemTy).first;3244  SDValue Chain = MemN->getChain();3245  SDValue Base0 = MemN->getBasePtr();3246  SDValue Base1 =3247      DAG.getMemBasePlusOffset(Base0, TypeSize::getFixed(HwLen), dl);3248  unsigned MemOpc = MemN->getOpcode();3249 3250  MachineMemOperand *MOp0 = nullptr, *MOp1 = nullptr;3251  if (MachineMemOperand *MMO = MemN->getMemOperand()) {3252    MachineFunction &MF = DAG.getMachineFunction();3253    uint64_t MemSize = (MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE)3254                           ? (uint64_t)MemoryLocation::UnknownSize3255                           : HwLen;3256    MOp0 = MF.getMachineMemOperand(MMO, 0, MemSize);3257    MOp1 = MF.getMachineMemOperand(MMO, HwLen, MemSize);3258  }3259 3260  if (MemOpc == ISD::LOAD) {3261    assert(cast<LoadSDNode>(Op)->isUnindexed());3262    SDValue Load0 = DAG.getLoad(SingleTy, dl, Chain, Base0, MOp0);3263    SDValue Load1 = DAG.getLoad(SingleTy, dl, Chain, Base1, MOp1);3264    return DAG.getMergeValues(3265        { DAG.getNode(ISD::CONCAT_VECTORS, dl, MemTy, Load0, Load1),3266          DAG.getNode(ISD::TokenFactor, dl, MVT::Other,3267                      Load0.getValue(1), Load1.getValue(1)) }, dl);3268  }3269  if (MemOpc == ISD::STORE) {3270    assert(cast<StoreSDNode>(Op)->isUnindexed());3271    VectorPair Vals = opSplit(cast<StoreSDNode>(Op)->getValue(), dl, DAG);3272    SDValue Store0 = DAG.getStore(Chain, dl, Vals.first, Base0, MOp0);3273    SDValue Store1 = DAG.getStore(Chain, dl, Vals.second, Base1, MOp1);3274    return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store0, Store1);3275  }3276 3277  assert(MemOpc == ISD::MLOAD || MemOpc == ISD::MSTORE);3278 3279  auto MaskN = cast<MaskedLoadStoreSDNode>(Op);3280  assert(MaskN->isUnindexed());3281  VectorPair Masks = opSplit(MaskN->getMask(), dl, DAG);3282  SDValue Offset = DAG.getUNDEF(MVT::i32);3283 3284  if (MemOpc == ISD::MLOAD) {3285    VectorPair Thru =3286        opSplit(cast<MaskedLoadSDNode>(Op)->getPassThru(), dl, DAG);3287    SDValue MLoad0 =3288        DAG.getMaskedLoad(SingleTy, dl, Chain, Base0, Offset, Masks.first,3289                          Thru.first, SingleTy, MOp0, ISD::UNINDEXED,3290                          ISD::NON_EXTLOAD, false);3291    SDValue MLoad1 =3292        DAG.getMaskedLoad(SingleTy, dl, Chain, Base1, Offset, Masks.second,3293                          Thru.second, SingleTy, MOp1, ISD::UNINDEXED,3294                          ISD::NON_EXTLOAD, false);3295    return DAG.getMergeValues(3296        { DAG.getNode(ISD::CONCAT_VECTORS, dl, MemTy, MLoad0, MLoad1),3297          DAG.getNode(ISD::TokenFactor, dl, MVT::Other,3298                      MLoad0.getValue(1), MLoad1.getValue(1)) }, dl);3299  }3300  if (MemOpc == ISD::MSTORE) {3301    VectorPair Vals = opSplit(cast<MaskedStoreSDNode>(Op)->getValue(), dl, DAG);3302    SDValue MStore0 = DAG.getMaskedStore(Chain, dl, Vals.first, Base0, Offset,3303                                         Masks.first, SingleTy, MOp0,3304                                         ISD::UNINDEXED, false, false);3305    SDValue MStore1 = DAG.getMaskedStore(Chain, dl, Vals.second, Base1, Offset,3306                                         Masks.second, SingleTy, MOp1,3307                                         ISD::UNINDEXED, false, false);3308    return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MStore0, MStore1);3309  }3310 3311  std::string Name = "Unexpected operation: " + Op->getOperationName(&DAG);3312  llvm_unreachable(Name.c_str());3313}3314 3315SDValue3316HexagonTargetLowering::WidenHvxLoad(SDValue Op, SelectionDAG &DAG) const {3317  const SDLoc &dl(Op);3318  auto *LoadN = cast<LoadSDNode>(Op.getNode());3319  assert(LoadN->isUnindexed() && "Not widening indexed loads yet");3320  assert(LoadN->getMemoryVT().getVectorElementType() != MVT::i1 &&3321         "Not widening loads of i1 yet");3322 3323  SDValue Chain = LoadN->getChain();3324  SDValue Base = LoadN->getBasePtr();3325  SDValue Offset = DAG.getUNDEF(MVT::i32);3326 3327  MVT ResTy = ty(Op);3328  unsigned HwLen = Subtarget.getVectorLength();3329  unsigned ResLen = ResTy.getStoreSize();3330  assert(ResLen < HwLen && "vsetq(v1) prerequisite");3331 3332  MVT BoolTy = MVT::getVectorVT(MVT::i1, HwLen);3333  SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,3334                          {DAG.getConstant(ResLen, dl, MVT::i32)}, DAG);3335 3336  MVT LoadTy = MVT::getVectorVT(MVT::i8, HwLen);3337  MachineFunction &MF = DAG.getMachineFunction();3338  auto *MemOp = MF.getMachineMemOperand(LoadN->getMemOperand(), 0, HwLen);3339 3340  SDValue Load = DAG.getMaskedLoad(LoadTy, dl, Chain, Base, Offset, Mask,3341                                   DAG.getUNDEF(LoadTy), LoadTy, MemOp,3342                                   ISD::UNINDEXED, ISD::NON_EXTLOAD, false);3343  SDValue Value = opCastElem(Load, ResTy.getVectorElementType(), DAG);3344  return DAG.getMergeValues({Value, Load.getValue(1)}, dl);3345}3346 3347SDValue3348HexagonTargetLowering::WidenHvxStore(SDValue Op, SelectionDAG &DAG) const {3349  const SDLoc &dl(Op);3350  auto *StoreN = cast<StoreSDNode>(Op.getNode());3351  assert(StoreN->isUnindexed() && "Not widening indexed stores yet");3352  assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&3353         "Not widening stores of i1 yet");3354 3355  SDValue Chain = StoreN->getChain();3356  SDValue Base = StoreN->getBasePtr();3357  SDValue Offset = DAG.getUNDEF(MVT::i32);3358 3359  SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);3360  MVT ValueTy = ty(Value);3361  unsigned ValueLen = ValueTy.getVectorNumElements();3362  unsigned HwLen = Subtarget.getVectorLength();3363  assert(isPowerOf2_32(ValueLen));3364 3365  for (unsigned Len = ValueLen; Len < HwLen; ) {3366    Value = opJoin({Value, DAG.getUNDEF(ty(Value))}, dl, DAG);3367    Len = ty(Value).getVectorNumElements(); // This is Len *= 23368  }3369  assert(ty(Value).getVectorNumElements() == HwLen);  // Paranoia3370 3371  assert(ValueLen < HwLen && "vsetq(v1) prerequisite");3372  MVT BoolTy = MVT::getVectorVT(MVT::i1, HwLen);3373  SDValue Mask = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,3374                          {DAG.getConstant(ValueLen, dl, MVT::i32)}, DAG);3375  MachineFunction &MF = DAG.getMachineFunction();3376  auto *MemOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);3377  return DAG.getMaskedStore(Chain, dl, Value, Base, Offset, Mask, ty(Value),3378                            MemOp, ISD::UNINDEXED, false, false);3379}3380 3381SDValue3382HexagonTargetLowering::WidenHvxSetCC(SDValue Op, SelectionDAG &DAG) const {3383  const SDLoc &dl(Op);3384  SDValue Op0 = Op.getOperand(0), Op1 = Op.getOperand(1);3385  MVT ElemTy = ty(Op0).getVectorElementType();3386  unsigned HwLen = Subtarget.getVectorLength();3387 3388  unsigned WideOpLen = (8 * HwLen) / ElemTy.getSizeInBits();3389  assert(WideOpLen * ElemTy.getSizeInBits() == 8 * HwLen);3390  MVT WideOpTy = MVT::getVectorVT(ElemTy, WideOpLen);3391  if (!Subtarget.isHVXVectorType(WideOpTy, true))3392    return SDValue();3393 3394  SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG);3395  SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG);3396  EVT ResTy =3397      getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), WideOpTy);3398  SDValue SetCC = DAG.getNode(ISD::SETCC, dl, ResTy,3399                              {WideOp0, WideOp1, Op.getOperand(2)});3400 3401  EVT RetTy = typeLegalize(ty(Op), DAG);3402  return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, RetTy,3403                     {SetCC, getZero(dl, MVT::i32, DAG)});3404}3405 3406SDValue3407HexagonTargetLowering::LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const {3408  unsigned Opc = Op.getOpcode();3409  bool IsPairOp = isHvxPairTy(ty(Op)) ||3410                  llvm::any_of(Op.getNode()->ops(), [this] (SDValue V) {3411                    return isHvxPairTy(ty(V));3412                  });3413 3414  if (IsPairOp) {3415    switch (Opc) {3416      default:3417        break;3418      case ISD::LOAD:3419      case ISD::STORE:3420      case ISD::MLOAD:3421      case ISD::MSTORE:3422        return SplitHvxMemOp(Op, DAG);3423      case ISD::SINT_TO_FP:3424      case ISD::UINT_TO_FP:3425      case ISD::FP_TO_SINT:3426      case ISD::FP_TO_UINT:3427        if (ty(Op).getSizeInBits() == ty(Op.getOperand(0)).getSizeInBits())3428          return opJoin(SplitVectorOp(Op, DAG), SDLoc(Op), DAG);3429        break;3430      case ISD::ABS:3431      case ISD::CTPOP:3432      case ISD::CTLZ:3433      case ISD::CTTZ:3434      case ISD::MUL:3435      case ISD::FADD:3436      case ISD::FSUB:3437      case ISD::FMUL:3438      case ISD::FMINIMUMNUM:3439      case ISD::FMAXIMUMNUM:3440      case ISD::MULHS:3441      case ISD::MULHU:3442      case ISD::AND:3443      case ISD::OR:3444      case ISD::XOR:3445      case ISD::SRA:3446      case ISD::SHL:3447      case ISD::SRL:3448      case ISD::FSHL:3449      case ISD::FSHR:3450      case ISD::SMIN:3451      case ISD::SMAX:3452      case ISD::UMIN:3453      case ISD::UMAX:3454      case ISD::SETCC:3455      case ISD::VSELECT:3456      case ISD::SIGN_EXTEND_INREG:3457      case ISD::SPLAT_VECTOR:3458        return opJoin(SplitVectorOp(Op, DAG), SDLoc(Op), DAG);3459      case ISD::SIGN_EXTEND:3460      case ISD::ZERO_EXTEND:3461        // In general, sign- and zero-extends can't be split and still3462        // be legal. The only exception is extending bool vectors.3463        if (ty(Op.getOperand(0)).getVectorElementType() == MVT::i1)3464          return opJoin(SplitVectorOp(Op, DAG), SDLoc(Op), DAG);3465        break;3466    }3467  }3468 3469  switch (Opc) {3470    default:3471      break;3472    case ISD::BUILD_VECTOR:            return LowerHvxBuildVector(Op, DAG);3473    case ISD::SPLAT_VECTOR:            return LowerHvxSplatVector(Op, DAG);3474    case ISD::CONCAT_VECTORS:          return LowerHvxConcatVectors(Op, DAG);3475    case ISD::INSERT_SUBVECTOR:        return LowerHvxInsertSubvector(Op, DAG);3476    case ISD::INSERT_VECTOR_ELT:       return LowerHvxInsertElement(Op, DAG);3477    case ISD::EXTRACT_SUBVECTOR:       return LowerHvxExtractSubvector(Op, DAG);3478    case ISD::EXTRACT_VECTOR_ELT:      return LowerHvxExtractElement(Op, DAG);3479    case ISD::BITCAST:                 return LowerHvxBitcast(Op, DAG);3480    case ISD::ANY_EXTEND:              return LowerHvxAnyExt(Op, DAG);3481    case ISD::SIGN_EXTEND:             return LowerHvxSignExt(Op, DAG);3482    case ISD::ZERO_EXTEND:             return LowerHvxZeroExt(Op, DAG);3483    case ISD::CTTZ:                    return LowerHvxCttz(Op, DAG);3484    case ISD::SELECT:                  return LowerHvxSelect(Op, DAG);3485    case ISD::SRA:3486    case ISD::SHL:3487    case ISD::SRL:                     return LowerHvxShift(Op, DAG);3488    case ISD::FSHL:3489    case ISD::FSHR:                    return LowerHvxFunnelShift(Op, DAG);3490    case ISD::MULHS:3491    case ISD::MULHU:                   return LowerHvxMulh(Op, DAG);3492    case ISD::SMUL_LOHI:3493    case ISD::UMUL_LOHI:               return LowerHvxMulLoHi(Op, DAG);3494    case ISD::ANY_EXTEND_VECTOR_INREG: return LowerHvxExtend(Op, DAG);3495    case ISD::SETCC:3496    case ISD::INTRINSIC_VOID:          return Op;3497    case ISD::INTRINSIC_WO_CHAIN:      return LowerHvxIntrinsic(Op, DAG);3498    case ISD::MLOAD:3499    case ISD::MSTORE:                  return LowerHvxMaskedOp(Op, DAG);3500    // Unaligned loads will be handled by the default lowering.3501    case ISD::LOAD:                    return SDValue();3502    case ISD::FP_EXTEND:               return LowerHvxFpExtend(Op, DAG);3503    case ISD::FP_TO_SINT:3504    case ISD::FP_TO_UINT:              return LowerHvxFpToInt(Op, DAG);3505    case ISD::SINT_TO_FP:3506    case ISD::UINT_TO_FP:              return LowerHvxIntToFp(Op, DAG);3507 3508    // Special nodes:3509    case HexagonISD::SMUL_LOHI:3510    case HexagonISD::UMUL_LOHI:3511    case HexagonISD::USMUL_LOHI:       return LowerHvxMulLoHi(Op, DAG);3512  }3513#ifndef NDEBUG3514  Op.dumpr(&DAG);3515#endif3516  llvm_unreachable("Unhandled HVX operation");3517}3518 3519SDValue3520HexagonTargetLowering::ExpandHvxResizeIntoSteps(SDValue Op, SelectionDAG &DAG)3521      const {3522  // Rewrite the extension/truncation/saturation op into steps where each3523  // step changes the type widths by a factor of 2.3524  // E.g.  i8 -> i16 remains unchanged, but i8 -> i32  ==>  i8 -> i16 -> i32.3525  //3526  // Some of the vector types in Op may not be legal.3527 3528  unsigned Opc = Op.getOpcode();3529  switch (Opc) {3530    case HexagonISD::SSAT:3531    case HexagonISD::USAT:3532    case HexagonISD::TL_EXTEND:3533    case HexagonISD::TL_TRUNCATE:3534      break;3535    case ISD::ANY_EXTEND:3536    case ISD::ZERO_EXTEND:3537    case ISD::SIGN_EXTEND:3538    case ISD::TRUNCATE:3539      llvm_unreachable("ISD:: ops will be auto-folded");3540      break;3541#ifndef NDEBUG3542    Op.dump(&DAG);3543#endif3544    llvm_unreachable("Unexpected operation");3545  }3546 3547  SDValue Inp = Op.getOperand(0);3548  MVT InpTy = ty(Inp);3549  MVT ResTy = ty(Op);3550 3551  unsigned InpWidth = InpTy.getVectorElementType().getSizeInBits();3552  unsigned ResWidth = ResTy.getVectorElementType().getSizeInBits();3553  assert(InpWidth != ResWidth);3554 3555  if (InpWidth == 2 * ResWidth || ResWidth == 2 * InpWidth)3556    return Op;3557 3558  const SDLoc &dl(Op);3559  unsigned NumElems = InpTy.getVectorNumElements();3560  assert(NumElems == ResTy.getVectorNumElements());3561 3562  auto repeatOp = [&](unsigned NewWidth, SDValue Arg) {3563    MVT Ty = MVT::getVectorVT(MVT::getIntegerVT(NewWidth), NumElems);3564    switch (Opc) {3565      case HexagonISD::SSAT:3566      case HexagonISD::USAT:3567        return DAG.getNode(Opc, dl, Ty, {Arg, DAG.getValueType(Ty)});3568      case HexagonISD::TL_EXTEND:3569      case HexagonISD::TL_TRUNCATE:3570        return DAG.getNode(Opc, dl, Ty, {Arg, Op.getOperand(1), Op.getOperand(2)});3571      default:3572        llvm_unreachable("Unexpected opcode");3573    }3574  };3575 3576  SDValue S = Inp;3577  if (InpWidth < ResWidth) {3578    assert(ResWidth % InpWidth == 0 && isPowerOf2_32(ResWidth / InpWidth));3579    while (InpWidth * 2 <= ResWidth)3580      S = repeatOp(InpWidth *= 2, S);3581  } else {3582    // InpWidth > ResWidth3583    assert(InpWidth % ResWidth == 0 && isPowerOf2_32(InpWidth / ResWidth));3584    while (InpWidth / 2 >= ResWidth)3585      S = repeatOp(InpWidth /= 2, S);3586  }3587  return S;3588}3589 3590SDValue3591HexagonTargetLowering::LegalizeHvxResize(SDValue Op, SelectionDAG &DAG) const {3592  SDValue Inp0 = Op.getOperand(0);3593  MVT InpTy = ty(Inp0);3594  MVT ResTy = ty(Op);3595  unsigned InpWidth = InpTy.getSizeInBits();3596  unsigned ResWidth = ResTy.getSizeInBits();3597  unsigned Opc = Op.getOpcode();3598 3599  if (shouldWidenToHvx(InpTy, DAG) || shouldWidenToHvx(ResTy, DAG)) {3600    // First, make sure that the narrower type is widened to HVX.3601    // This may cause the result to be wider than what the legalizer3602    // expects, so insert EXTRACT_SUBVECTOR to bring it back to the3603    // desired type.3604    auto [WInpTy, WResTy] =3605        InpWidth < ResWidth ? typeWidenToWider(typeWidenToHvx(InpTy), ResTy)3606                            : typeWidenToWider(InpTy, typeWidenToHvx(ResTy));3607    SDValue W = appendUndef(Inp0, WInpTy, DAG);3608    SDValue S;3609    if (Opc == HexagonISD::TL_EXTEND || Opc == HexagonISD::TL_TRUNCATE) {3610      S = DAG.getNode(Opc, SDLoc(Op), WResTy, W, Op.getOperand(1),3611                      Op.getOperand(2));3612    } else {3613      S = DAG.getNode(Opc, SDLoc(Op), WResTy, W, DAG.getValueType(WResTy));3614    }3615    SDValue T = ExpandHvxResizeIntoSteps(S, DAG);3616    return extractSubvector(T, typeLegalize(ResTy, DAG), 0, DAG);3617  } else if (shouldSplitToHvx(InpWidth < ResWidth ? ResTy : InpTy, DAG)) {3618    return opJoin(SplitVectorOp(Op, DAG), SDLoc(Op), DAG);3619  } else {3620    assert(isTypeLegal(InpTy) && isTypeLegal(ResTy));3621    return RemoveTLWrapper(Op, DAG);3622  }3623  llvm_unreachable("Unexpected situation");3624}3625 3626void3627HexagonTargetLowering::LowerHvxOperationWrapper(SDNode *N,3628      SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const {3629  unsigned Opc = N->getOpcode();3630  SDValue Op(N, 0);3631  SDValue Inp0;   // Optional first argument.3632  if (N->getNumOperands() > 0)3633    Inp0 = Op.getOperand(0);3634 3635  switch (Opc) {3636    case ISD::ANY_EXTEND:3637    case ISD::SIGN_EXTEND:3638    case ISD::ZERO_EXTEND:3639    case ISD::TRUNCATE:3640      if (Subtarget.isHVXElementType(ty(Op)) &&3641          Subtarget.isHVXElementType(ty(Inp0))) {3642        Results.push_back(CreateTLWrapper(Op, DAG));3643      }3644      break;3645    case ISD::SETCC:3646      if (shouldWidenToHvx(ty(Inp0), DAG)) {3647        if (SDValue T = WidenHvxSetCC(Op, DAG))3648          Results.push_back(T);3649      }3650      break;3651    case ISD::STORE: {3652      if (shouldWidenToHvx(ty(cast<StoreSDNode>(N)->getValue()), DAG)) {3653        SDValue Store = WidenHvxStore(Op, DAG);3654        Results.push_back(Store);3655      }3656      break;3657    }3658    case ISD::MLOAD:3659      if (isHvxPairTy(ty(Op))) {3660        SDValue S = SplitHvxMemOp(Op, DAG);3661        assert(S->getOpcode() == ISD::MERGE_VALUES);3662        Results.push_back(S.getOperand(0));3663        Results.push_back(S.getOperand(1));3664      }3665      break;3666    case ISD::MSTORE:3667      if (isHvxPairTy(ty(Op->getOperand(1)))) {    // Stored value3668        SDValue S = SplitHvxMemOp(Op, DAG);3669        Results.push_back(S);3670      }3671      break;3672    case ISD::SINT_TO_FP:3673    case ISD::UINT_TO_FP:3674    case ISD::FP_TO_SINT:3675    case ISD::FP_TO_UINT:3676      if (ty(Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {3677        SDValue T = EqualizeFpIntConversion(Op, DAG);3678        Results.push_back(T);3679      }3680      break;3681    case HexagonISD::SSAT:3682    case HexagonISD::USAT:3683    case HexagonISD::TL_EXTEND:3684    case HexagonISD::TL_TRUNCATE:3685      Results.push_back(LegalizeHvxResize(Op, DAG));3686      break;3687    default:3688      break;3689  }3690}3691 3692void3693HexagonTargetLowering::ReplaceHvxNodeResults(SDNode *N,3694      SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const {3695  unsigned Opc = N->getOpcode();3696  SDValue Op(N, 0);3697  SDValue Inp0;   // Optional first argument.3698  if (N->getNumOperands() > 0)3699    Inp0 = Op.getOperand(0);3700 3701  switch (Opc) {3702    case ISD::ANY_EXTEND:3703    case ISD::SIGN_EXTEND:3704    case ISD::ZERO_EXTEND:3705    case ISD::TRUNCATE:3706      if (Subtarget.isHVXElementType(ty(Op)) &&3707          Subtarget.isHVXElementType(ty(Inp0))) {3708        Results.push_back(CreateTLWrapper(Op, DAG));3709      }3710      break;3711    case ISD::SETCC:3712      if (shouldWidenToHvx(ty(Op), DAG)) {3713        if (SDValue T = WidenHvxSetCC(Op, DAG))3714          Results.push_back(T);3715      }3716      break;3717    case ISD::LOAD: {3718      if (shouldWidenToHvx(ty(Op), DAG)) {3719        SDValue Load = WidenHvxLoad(Op, DAG);3720        assert(Load->getOpcode() == ISD::MERGE_VALUES);3721        Results.push_back(Load.getOperand(0));3722        Results.push_back(Load.getOperand(1));3723      }3724      break;3725    }3726    case ISD::BITCAST:3727      if (isHvxBoolTy(ty(Inp0))) {3728        SDValue C = LowerHvxBitcast(Op, DAG);3729        Results.push_back(C);3730      }3731      break;3732    case ISD::FP_TO_SINT:3733    case ISD::FP_TO_UINT:3734      if (ty(Op).getSizeInBits() != ty(Inp0).getSizeInBits()) {3735        SDValue T = EqualizeFpIntConversion(Op, DAG);3736        Results.push_back(T);3737      }3738      break;3739    case HexagonISD::SSAT:3740    case HexagonISD::USAT:3741    case HexagonISD::TL_EXTEND:3742    case HexagonISD::TL_TRUNCATE:3743      Results.push_back(LegalizeHvxResize(Op, DAG));3744      break;3745    default:3746      break;3747  }3748}3749 3750SDValue3751HexagonTargetLowering::combineTruncateBeforeLegal(SDValue Op,3752                                                  DAGCombinerInfo &DCI) const {3753  // Simplify V:v2NiB --(bitcast)--> vNi2B --(truncate)--> vNiB3754  // to extract-subvector (shuffle V, pick even, pick odd)3755 3756  assert(Op.getOpcode() == ISD::TRUNCATE);3757  SelectionDAG &DAG = DCI.DAG;3758  const SDLoc &dl(Op);3759 3760  if (Op.getOperand(0).getOpcode() == ISD::BITCAST)3761    return SDValue();3762  SDValue Cast = Op.getOperand(0);3763  SDValue Src = Cast.getOperand(0);3764 3765  EVT TruncTy = Op.getValueType();3766  EVT CastTy = Cast.getValueType();3767  EVT SrcTy = Src.getValueType();3768  if (SrcTy.isSimple())3769    return SDValue();3770  if (SrcTy.getVectorElementType() != TruncTy.getVectorElementType())3771    return SDValue();3772  unsigned SrcLen = SrcTy.getVectorNumElements();3773  unsigned CastLen = CastTy.getVectorNumElements();3774  if (2 * CastLen != SrcLen)3775    return SDValue();3776 3777  SmallVector<int, 128> Mask(SrcLen);3778  for (int i = 0; i != static_cast<int>(CastLen); ++i) {3779    Mask[i] = 2 * i;3780    Mask[i + CastLen] = 2 * i + 1;3781  }3782  SDValue Deal =3783      DAG.getVectorShuffle(SrcTy, dl, Src, DAG.getUNDEF(SrcTy), Mask);3784  return opSplit(Deal, dl, DAG).first;3785}3786 3787SDValue3788HexagonTargetLowering::combineConcatVectorsBeforeLegal(3789    SDValue Op, DAGCombinerInfo &DCI) const {3790  // Fold3791  //   concat (shuffle x, y, m1), (shuffle x, y, m2)3792  // into3793  //   shuffle (concat x, y), undef, m33794  if (Op.getNumOperands() != 2)3795    return SDValue();3796 3797  SelectionDAG &DAG = DCI.DAG;3798  const SDLoc &dl(Op);3799  SDValue V0 = Op.getOperand(0);3800  SDValue V1 = Op.getOperand(1);3801 3802  if (V0.getOpcode() != ISD::VECTOR_SHUFFLE)3803    return SDValue();3804  if (V1.getOpcode() != ISD::VECTOR_SHUFFLE)3805    return SDValue();3806 3807  SetVector<SDValue> Order;3808  Order.insert(V0.getOperand(0));3809  Order.insert(V0.getOperand(1));3810  Order.insert(V1.getOperand(0));3811  Order.insert(V1.getOperand(1));3812 3813  if (Order.size() > 2)3814    return SDValue();3815 3816  // In ISD::VECTOR_SHUFFLE, the types of each input and the type of the3817  // result must be the same.3818  EVT InpTy = V0.getValueType();3819  assert(InpTy.isVector());3820  unsigned InpLen = InpTy.getVectorNumElements();3821 3822  SmallVector<int, 128> LongMask;3823  auto AppendToMask = [&](SDValue Shuffle) {3824    auto *SV = cast<ShuffleVectorSDNode>(Shuffle.getNode());3825    ArrayRef<int> Mask = SV->getMask();3826    SDValue X = Shuffle.getOperand(0);3827    SDValue Y = Shuffle.getOperand(1);3828    for (int M : Mask) {3829      if (M == -1) {3830        LongMask.push_back(M);3831        continue;3832      }3833      SDValue Src = static_cast<unsigned>(M) < InpLen ? X : Y;3834      if (static_cast<unsigned>(M) >= InpLen)3835        M -= InpLen;3836 3837      int OutOffset = Order[0] == Src ? 0 : InpLen;3838      LongMask.push_back(M + OutOffset);3839    }3840  };3841 3842  AppendToMask(V0);3843  AppendToMask(V1);3844 3845  SDValue C0 = Order.front();3846  SDValue C1 = Order.back();  // Can be same as front3847  EVT LongTy = InpTy.getDoubleNumVectorElementsVT(*DAG.getContext());3848 3849  SDValue Cat = DAG.getNode(ISD::CONCAT_VECTORS, dl, LongTy, {C0, C1});3850  return DAG.getVectorShuffle(LongTy, dl, Cat, DAG.getUNDEF(LongTy), LongMask);3851}3852 3853SDValue3854HexagonTargetLowering::PerformHvxDAGCombine(SDNode *N, DAGCombinerInfo &DCI)3855      const {3856  const SDLoc &dl(N);3857  SelectionDAG &DAG = DCI.DAG;3858  SDValue Op(N, 0);3859  unsigned Opc = Op.getOpcode();3860 3861  SmallVector<SDValue, 4> Ops(N->ops());3862 3863  if (Opc == ISD::TRUNCATE)3864    return combineTruncateBeforeLegal(Op, DCI);3865  if (Opc == ISD::CONCAT_VECTORS)3866    return combineConcatVectorsBeforeLegal(Op, DCI);3867 3868  if (DCI.isBeforeLegalizeOps())3869    return SDValue();3870 3871  switch (Opc) {3872    case ISD::VSELECT: {3873      // (vselect (xor x, qtrue), v0, v1) -> (vselect x, v1, v0)3874      SDValue Cond = Ops[0];3875      if (Cond->getOpcode() == ISD::XOR) {3876        SDValue C0 = Cond.getOperand(0), C1 = Cond.getOperand(1);3877        if (C1->getOpcode() == HexagonISD::QTRUE)3878          return DAG.getNode(ISD::VSELECT, dl, ty(Op), C0, Ops[2], Ops[1]);3879      }3880      break;3881    }3882    case HexagonISD::V2Q:3883      if (Ops[0].getOpcode() == ISD::SPLAT_VECTOR) {3884        if (const auto *C = dyn_cast<ConstantSDNode>(Ops[0].getOperand(0)))3885          return C->isZero() ? DAG.getNode(HexagonISD::QFALSE, dl, ty(Op))3886                             : DAG.getNode(HexagonISD::QTRUE, dl, ty(Op));3887      }3888      break;3889    case HexagonISD::Q2V:3890      if (Ops[0].getOpcode() == HexagonISD::QTRUE)3891        return DAG.getNode(ISD::SPLAT_VECTOR, dl, ty(Op),3892                           DAG.getAllOnesConstant(dl, MVT::i32));3893      if (Ops[0].getOpcode() == HexagonISD::QFALSE)3894        return getZero(dl, ty(Op), DAG);3895      break;3896    case HexagonISD::VINSERTW0:3897      if (isUndef(Ops[1]))3898        return Ops[0];3899      break;3900    case HexagonISD::VROR: {3901      if (Ops[0].getOpcode() == HexagonISD::VROR) {3902        SDValue Vec = Ops[0].getOperand(0);3903        SDValue Rot0 = Ops[1], Rot1 = Ops[0].getOperand(1);3904        SDValue Rot = DAG.getNode(ISD::ADD, dl, ty(Rot0), {Rot0, Rot1});3905        return DAG.getNode(HexagonISD::VROR, dl, ty(Op), {Vec, Rot});3906      }3907      break;3908    }3909  }3910 3911  return SDValue();3912}3913 3914bool3915HexagonTargetLowering::shouldSplitToHvx(MVT Ty, SelectionDAG &DAG) const {3916  if (Subtarget.isHVXVectorType(Ty, true))3917    return false;3918  auto Action = getPreferredHvxVectorAction(Ty);3919  if (Action == TargetLoweringBase::TypeSplitVector)3920    return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG), true);3921  return false;3922}3923 3924bool3925HexagonTargetLowering::shouldWidenToHvx(MVT Ty, SelectionDAG &DAG) const {3926  if (Subtarget.isHVXVectorType(Ty, true))3927    return false;3928  auto Action = getPreferredHvxVectorAction(Ty);3929  if (Action == TargetLoweringBase::TypeWidenVector)3930    return Subtarget.isHVXVectorType(typeLegalize(Ty, DAG), true);3931  return false;3932}3933 3934bool3935HexagonTargetLowering::isHvxOperation(SDNode *N, SelectionDAG &DAG) const {3936  if (!Subtarget.useHVXOps())3937    return false;3938  // If the type of any result, or any operand type are HVX vector types,3939  // this is an HVX operation.3940  auto IsHvxTy = [this](EVT Ty) {3941    return Ty.isSimple() && Subtarget.isHVXVectorType(Ty.getSimpleVT(), true);3942  };3943  auto IsHvxOp = [this](SDValue Op) {3944    return Op.getValueType().isSimple() &&3945           Subtarget.isHVXVectorType(ty(Op), true);3946  };3947  if (llvm::any_of(N->values(), IsHvxTy) || llvm::any_of(N->ops(), IsHvxOp))3948    return true;3949 3950  // Check if this could be an HVX operation after type widening.3951  auto IsWidenedToHvx = [this, &DAG](SDValue Op) {3952    if (!Op.getValueType().isSimple())3953      return false;3954    MVT ValTy = ty(Op);3955    return ValTy.isVector() && shouldWidenToHvx(ValTy, DAG);3956  };3957 3958  for (int i = 0, e = N->getNumValues(); i != e; ++i) {3959    if (IsWidenedToHvx(SDValue(N, i)))3960      return true;3961  }3962  return llvm::any_of(N->ops(), IsWidenedToHvx);3963}3964