brintos

brintos / llvm-project-archived public Read only

0
0
Text · 372.1 KiB · ba9d068 Raw
9791 lines · cpp
1//=- LoongArchISelLowering.cpp - LoongArch DAG Lowering Implementation  ---===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines the interfaces that LoongArch uses to lower LLVM code into10// a selection DAG.11//12//===----------------------------------------------------------------------===//13 14#include "LoongArchISelLowering.h"15#include "LoongArch.h"16#include "LoongArchMachineFunctionInfo.h"17#include "LoongArchRegisterInfo.h"18#include "LoongArchSelectionDAGInfo.h"19#include "LoongArchSubtarget.h"20#include "MCTargetDesc/LoongArchBaseInfo.h"21#include "MCTargetDesc/LoongArchMCTargetDesc.h"22#include "MCTargetDesc/LoongArchMatInt.h"23#include "llvm/ADT/SmallSet.h"24#include "llvm/ADT/Statistic.h"25#include "llvm/ADT/StringExtras.h"26#include "llvm/CodeGen/ISDOpcodes.h"27#include "llvm/CodeGen/MachineInstrBuilder.h"28#include "llvm/CodeGen/RuntimeLibcallUtil.h"29#include "llvm/CodeGen/SelectionDAGNodes.h"30#include "llvm/IR/IRBuilder.h"31#include "llvm/IR/IntrinsicInst.h"32#include "llvm/IR/IntrinsicsLoongArch.h"33#include "llvm/Support/CodeGen.h"34#include "llvm/Support/Debug.h"35#include "llvm/Support/ErrorHandling.h"36#include "llvm/Support/KnownBits.h"37#include "llvm/Support/MathExtras.h"38#include <llvm/Analysis/VectorUtils.h>39 40using namespace llvm;41 42#define DEBUG_TYPE "loongarch-isel-lowering"43 44STATISTIC(NumTailCalls, "Number of tail calls");45 46enum MaterializeFPImm {47  NoMaterializeFPImm = 0,48  MaterializeFPImm2Ins = 2,49  MaterializeFPImm3Ins = 3,50  MaterializeFPImm4Ins = 4,51  MaterializeFPImm5Ins = 5,52  MaterializeFPImm6Ins = 653};54 55static cl::opt<MaterializeFPImm> MaterializeFPImmInsNum(56    "loongarch-materialize-float-imm", cl::Hidden,57    cl::desc("Maximum number of instructions used (including code sequence "58             "to generate the value and moving the value to FPR) when "59             "materializing floating-point immediates (default = 3)"),60    cl::init(MaterializeFPImm3Ins),61    cl::values(clEnumValN(NoMaterializeFPImm, "0", "Use constant pool"),62               clEnumValN(MaterializeFPImm2Ins, "2",63                          "Materialize FP immediate within 2 instructions"),64               clEnumValN(MaterializeFPImm3Ins, "3",65                          "Materialize FP immediate within 3 instructions"),66               clEnumValN(MaterializeFPImm4Ins, "4",67                          "Materialize FP immediate within 4 instructions"),68               clEnumValN(MaterializeFPImm5Ins, "5",69                          "Materialize FP immediate within 5 instructions"),70               clEnumValN(MaterializeFPImm6Ins, "6",71                          "Materialize FP immediate within 6 instructions "72                          "(behaves same as 5 on loongarch64)")));73 74static cl::opt<bool> ZeroDivCheck("loongarch-check-zero-division", cl::Hidden,75                                  cl::desc("Trap on integer division by zero."),76                                  cl::init(false));77 78LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,79                                                 const LoongArchSubtarget &STI)80    : TargetLowering(TM, STI), Subtarget(STI) {81 82  MVT GRLenVT = Subtarget.getGRLenVT();83 84  // Set up the register classes.85 86  addRegisterClass(GRLenVT, &LoongArch::GPRRegClass);87  if (Subtarget.hasBasicF())88    addRegisterClass(MVT::f32, &LoongArch::FPR32RegClass);89  if (Subtarget.hasBasicD())90    addRegisterClass(MVT::f64, &LoongArch::FPR64RegClass);91 92  static const MVT::SimpleValueType LSXVTs[] = {93      MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64};94  static const MVT::SimpleValueType LASXVTs[] = {95      MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v8f32, MVT::v4f64};96 97  if (Subtarget.hasExtLSX())98    for (MVT VT : LSXVTs)99      addRegisterClass(VT, &LoongArch::LSX128RegClass);100 101  if (Subtarget.hasExtLASX())102    for (MVT VT : LASXVTs)103      addRegisterClass(VT, &LoongArch::LASX256RegClass);104 105  // Set operations for LA32 and LA64.106 107  setLoadExtAction({ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}, GRLenVT,108                   MVT::i1, Promote);109 110  setOperationAction(ISD::SHL_PARTS, GRLenVT, Custom);111  setOperationAction(ISD::SRA_PARTS, GRLenVT, Custom);112  setOperationAction(ISD::SRL_PARTS, GRLenVT, Custom);113  setOperationAction(ISD::FP_TO_SINT, GRLenVT, Custom);114  setOperationAction(ISD::ROTL, GRLenVT, Expand);115  setOperationAction(ISD::CTPOP, GRLenVT, Expand);116 117  setOperationAction({ISD::GlobalAddress, ISD::BlockAddress, ISD::ConstantPool,118                      ISD::JumpTable, ISD::GlobalTLSAddress},119                     GRLenVT, Custom);120 121  setOperationAction(ISD::EH_DWARF_CFA, GRLenVT, Custom);122 123  setOperationAction(ISD::DYNAMIC_STACKALLOC, GRLenVT, Expand);124  setOperationAction({ISD::STACKSAVE, ISD::STACKRESTORE}, MVT::Other, Expand);125  setOperationAction(ISD::VASTART, MVT::Other, Custom);126  setOperationAction({ISD::VAARG, ISD::VACOPY, ISD::VAEND}, MVT::Other, Expand);127 128  setOperationAction(ISD::DEBUGTRAP, MVT::Other, Legal);129  setOperationAction(ISD::TRAP, MVT::Other, Legal);130 131  setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);132  setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);133  setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);134 135  setOperationAction(ISD::PREFETCH, MVT::Other, Custom);136 137  // BITREV/REVB requires the 32S feature.138  if (STI.has32S()) {139    // Expand bitreverse.i16 with native-width bitrev and shift for now, before140    // we get to know which of sll and revb.2h is faster.141    setOperationAction(ISD::BITREVERSE, MVT::i8, Custom);142    setOperationAction(ISD::BITREVERSE, GRLenVT, Legal);143 144    // LA32 does not have REVB.2W and REVB.D due to the 64-bit operands, and145    // the narrower REVB.W does not exist. But LA32 does have REVB.2H, so i16146    // and i32 could still be byte-swapped relatively cheaply.147    setOperationAction(ISD::BSWAP, MVT::i16, Custom);148  } else {149    setOperationAction(ISD::BSWAP, GRLenVT, Expand);150    setOperationAction(ISD::CTTZ, GRLenVT, Expand);151    setOperationAction(ISD::CTLZ, GRLenVT, Expand);152    setOperationAction(ISD::ROTR, GRLenVT, Expand);153    setOperationAction(ISD::SELECT, GRLenVT, Custom);154    setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand);155    setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);156  }157 158  setOperationAction(ISD::BR_JT, MVT::Other, Expand);159  setOperationAction(ISD::BR_CC, GRLenVT, Expand);160  setOperationAction(ISD::BRCOND, MVT::Other, Custom);161  setOperationAction(ISD::SELECT_CC, GRLenVT, Expand);162  setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);163  setOperationAction({ISD::SMUL_LOHI, ISD::UMUL_LOHI}, GRLenVT, Expand);164 165  setOperationAction(ISD::FP_TO_UINT, GRLenVT, Custom);166  setOperationAction(ISD::UINT_TO_FP, GRLenVT, Expand);167 168  // Set operations for LA64 only.169 170  if (Subtarget.is64Bit()) {171    setOperationAction(ISD::ADD, MVT::i32, Custom);172    setOperationAction(ISD::SUB, MVT::i32, Custom);173    setOperationAction(ISD::SHL, MVT::i32, Custom);174    setOperationAction(ISD::SRA, MVT::i32, Custom);175    setOperationAction(ISD::SRL, MVT::i32, Custom);176    setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);177    setOperationAction(ISD::BITCAST, MVT::i32, Custom);178    setOperationAction(ISD::ROTR, MVT::i32, Custom);179    setOperationAction(ISD::ROTL, MVT::i32, Custom);180    setOperationAction(ISD::CTTZ, MVT::i32, Custom);181    setOperationAction(ISD::CTLZ, MVT::i32, Custom);182    setOperationAction(ISD::EH_DWARF_CFA, MVT::i32, Custom);183    setOperationAction(ISD::READ_REGISTER, MVT::i32, Custom);184    setOperationAction(ISD::WRITE_REGISTER, MVT::i32, Custom);185    setOperationAction(ISD::INTRINSIC_VOID, MVT::i32, Custom);186    setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i32, Custom);187    setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i32, Custom);188 189    setOperationAction(ISD::BITREVERSE, MVT::i32, Custom);190    setOperationAction(ISD::BSWAP, MVT::i32, Custom);191    setOperationAction({ISD::SDIV, ISD::UDIV, ISD::SREM, ISD::UREM}, MVT::i32,192                       Custom);193    setOperationAction(ISD::LROUND, MVT::i32, Custom);194  }195 196  // Set operations for LA32 only.197 198  if (!Subtarget.is64Bit()) {199    setOperationAction(ISD::READ_REGISTER, MVT::i64, Custom);200    setOperationAction(ISD::WRITE_REGISTER, MVT::i64, Custom);201    setOperationAction(ISD::INTRINSIC_VOID, MVT::i64, Custom);202    setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom);203    setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom);204    if (Subtarget.hasBasicD())205      setOperationAction(ISD::BITCAST, MVT::i64, Custom);206  }207 208  setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);209 210  static const ISD::CondCode FPCCToExpand[] = {211      ISD::SETOGT, ISD::SETOGE, ISD::SETUGT, ISD::SETUGE,212      ISD::SETGE,  ISD::SETNE,  ISD::SETGT};213 214  // Set operations for 'F' feature.215 216  if (Subtarget.hasBasicF()) {217    setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);218    setTruncStoreAction(MVT::f32, MVT::f16, Expand);219    setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::bf16, Expand);220    setTruncStoreAction(MVT::f32, MVT::bf16, Expand);221    setCondCodeAction(FPCCToExpand, MVT::f32, Expand);222 223    setOperationAction(ISD::ConstantFP, MVT::f32, Custom);224    setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);225    setOperationAction(ISD::BR_CC, MVT::f32, Expand);226    setOperationAction(ISD::FMA, MVT::f32, Legal);227    setOperationAction(ISD::FMINNUM_IEEE, MVT::f32, Legal);228    setOperationAction(ISD::FMINNUM, MVT::f32, Legal);229    setOperationAction(ISD::FMAXNUM_IEEE, MVT::f32, Legal);230    setOperationAction(ISD::FMAXNUM, MVT::f32, Legal);231    setOperationAction(ISD::FCANONICALIZE, MVT::f32, Legal);232    setOperationAction(ISD::STRICT_FSETCCS, MVT::f32, Legal);233    setOperationAction(ISD::STRICT_FSETCC, MVT::f32, Legal);234    setOperationAction(ISD::IS_FPCLASS, MVT::f32, Legal);235    setOperationAction(ISD::FSIN, MVT::f32, Expand);236    setOperationAction(ISD::FCOS, MVT::f32, Expand);237    setOperationAction(ISD::FSINCOS, MVT::f32, Expand);238    setOperationAction(ISD::FPOW, MVT::f32, Expand);239    setOperationAction(ISD::FREM, MVT::f32, Expand);240    setOperationAction(ISD::FP16_TO_FP, MVT::f32,241                       Subtarget.isSoftFPABI() ? LibCall : Custom);242    setOperationAction(ISD::FP_TO_FP16, MVT::f32,243                       Subtarget.isSoftFPABI() ? LibCall : Custom);244    setOperationAction(ISD::BF16_TO_FP, MVT::f32, Custom);245    setOperationAction(ISD::FP_TO_BF16, MVT::f32,246                       Subtarget.isSoftFPABI() ? LibCall : Custom);247 248    if (Subtarget.is64Bit()) {249      setOperationAction(ISD::FRINT, MVT::f32, Legal);250      setOperationAction(ISD::FLOG2, MVT::f32, Legal);251    }252 253    if (!Subtarget.hasBasicD()) {254      setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);255      if (Subtarget.is64Bit()) {256        setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);257        setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);258      }259    }260  }261 262  // Set operations for 'D' feature.263 264  if (Subtarget.hasBasicD()) {265    setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);266    setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);267    setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::bf16, Expand);268    setTruncStoreAction(MVT::f64, MVT::bf16, Expand);269    setTruncStoreAction(MVT::f64, MVT::f16, Expand);270    setTruncStoreAction(MVT::f64, MVT::f32, Expand);271    setCondCodeAction(FPCCToExpand, MVT::f64, Expand);272 273    setOperationAction(ISD::ConstantFP, MVT::f64, Custom);274    setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);275    setOperationAction(ISD::BR_CC, MVT::f64, Expand);276    setOperationAction(ISD::STRICT_FSETCCS, MVT::f64, Legal);277    setOperationAction(ISD::STRICT_FSETCC, MVT::f64, Legal);278    setOperationAction(ISD::FMA, MVT::f64, Legal);279    setOperationAction(ISD::FMINNUM_IEEE, MVT::f64, Legal);280    setOperationAction(ISD::FMINNUM, MVT::f64, Legal);281    setOperationAction(ISD::FMAXNUM_IEEE, MVT::f64, Legal);282    setOperationAction(ISD::FCANONICALIZE, MVT::f64, Legal);283    setOperationAction(ISD::FMAXNUM, MVT::f64, Legal);284    setOperationAction(ISD::IS_FPCLASS, MVT::f64, Legal);285    setOperationAction(ISD::FSIN, MVT::f64, Expand);286    setOperationAction(ISD::FCOS, MVT::f64, Expand);287    setOperationAction(ISD::FSINCOS, MVT::f64, Expand);288    setOperationAction(ISD::FPOW, MVT::f64, Expand);289    setOperationAction(ISD::FREM, MVT::f64, Expand);290    setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand);291    setOperationAction(ISD::FP_TO_FP16, MVT::f64,292                       Subtarget.isSoftFPABI() ? LibCall : Custom);293    setOperationAction(ISD::BF16_TO_FP, MVT::f64, Custom);294    setOperationAction(ISD::FP_TO_BF16, MVT::f64,295                       Subtarget.isSoftFPABI() ? LibCall : Custom);296 297    if (Subtarget.is64Bit()) {298      setOperationAction(ISD::FRINT, MVT::f64, Legal);299      setOperationAction(ISD::FLOG2, MVT::f64, Legal);300    }301  }302 303  // Set operations for 'LSX' feature.304 305  if (Subtarget.hasExtLSX()) {306    for (MVT VT : MVT::fixedlen_vector_valuetypes()) {307      // Expand all truncating stores and extending loads.308      for (MVT InnerVT : MVT::fixedlen_vector_valuetypes()) {309        setTruncStoreAction(VT, InnerVT, Expand);310        setLoadExtAction(ISD::SEXTLOAD, VT, InnerVT, Expand);311        setLoadExtAction(ISD::ZEXTLOAD, VT, InnerVT, Expand);312        setLoadExtAction(ISD::EXTLOAD, VT, InnerVT, Expand);313      }314      // By default everything must be expanded. Then we will selectively turn315      // on ones that can be effectively codegen'd.316      for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op)317        setOperationAction(Op, VT, Expand);318    }319 320    for (MVT VT : LSXVTs) {321      setOperationAction({ISD::LOAD, ISD::STORE}, VT, Legal);322      setOperationAction(ISD::BITCAST, VT, Legal);323      setOperationAction(ISD::UNDEF, VT, Legal);324 325      setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);326      setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Legal);327      setOperationAction(ISD::BUILD_VECTOR, VT, Custom);328 329      setOperationAction(ISD::SETCC, VT, Legal);330      setOperationAction(ISD::VSELECT, VT, Legal);331      setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);332      setOperationAction(ISD::EXTRACT_SUBVECTOR, VT, Legal);333    }334    for (MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64}) {335      setOperationAction({ISD::ADD, ISD::SUB}, VT, Legal);336      setOperationAction({ISD::UMAX, ISD::UMIN, ISD::SMAX, ISD::SMIN}, VT,337                         Legal);338      setOperationAction({ISD::MUL, ISD::SDIV, ISD::SREM, ISD::UDIV, ISD::UREM},339                         VT, Legal);340      setOperationAction({ISD::AND, ISD::OR, ISD::XOR}, VT, Legal);341      setOperationAction({ISD::SHL, ISD::SRA, ISD::SRL}, VT, Legal);342      setOperationAction({ISD::CTPOP, ISD::CTLZ}, VT, Legal);343      setOperationAction({ISD::MULHS, ISD::MULHU}, VT, Legal);344      setCondCodeAction(345          {ISD::SETNE, ISD::SETGE, ISD::SETGT, ISD::SETUGE, ISD::SETUGT}, VT,346          Expand);347      setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);348      setOperationAction(ISD::ABS, VT, Legal);349      setOperationAction(ISD::ABDS, VT, Legal);350      setOperationAction(ISD::ABDU, VT, Legal);351      setOperationAction(ISD::SADDSAT, VT, Legal);352      setOperationAction(ISD::SSUBSAT, VT, Legal);353      setOperationAction(ISD::UADDSAT, VT, Legal);354      setOperationAction(ISD::USUBSAT, VT, Legal);355      setOperationAction(ISD::ROTL, VT, Custom);356      setOperationAction(ISD::ROTR, VT, Custom);357    }358    for (MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})359      setOperationAction(ISD::BITREVERSE, VT, Custom);360    for (MVT VT : {MVT::v8i16, MVT::v4i32, MVT::v2i64})361      setOperationAction(ISD::BSWAP, VT, Legal);362    for (MVT VT : {MVT::v4i32, MVT::v2i64}) {363      setOperationAction({ISD::SINT_TO_FP, ISD::UINT_TO_FP}, VT, Legal);364      setOperationAction({ISD::FP_TO_SINT, ISD::FP_TO_UINT}, VT, Legal);365    }366    for (MVT VT : {MVT::v4f32, MVT::v2f64}) {367      setOperationAction({ISD::FADD, ISD::FSUB}, VT, Legal);368      setOperationAction({ISD::FMUL, ISD::FDIV}, VT, Legal);369      setOperationAction(ISD::FMA, VT, Legal);370      setOperationAction(ISD::FSQRT, VT, Legal);371      setOperationAction(ISD::FNEG, VT, Legal);372      setOperationAction(ISD::FLOG2, VT, Legal);373      setCondCodeAction({ISD::SETGE, ISD::SETGT, ISD::SETOGE, ISD::SETOGT,374                         ISD::SETUGE, ISD::SETUGT},375                        VT, Expand);376      setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Legal);377      setOperationAction(ISD::FCEIL, VT, Legal);378      setOperationAction(ISD::FFLOOR, VT, Legal);379      setOperationAction(ISD::FTRUNC, VT, Legal);380      setOperationAction(ISD::FROUNDEVEN, VT, Legal);381      setOperationAction(ISD::FMINNUM, VT, Legal);382      setOperationAction(ISD::FMAXNUM, VT, Legal);383    }384    setOperationAction(ISD::CTPOP, GRLenVT, Legal);385    setOperationAction(ISD::FCEIL, {MVT::f32, MVT::f64}, Legal);386    setOperationAction(ISD::FFLOOR, {MVT::f32, MVT::f64}, Legal);387    setOperationAction(ISD::FTRUNC, {MVT::f32, MVT::f64}, Legal);388    setOperationAction(ISD::FROUNDEVEN, {MVT::f32, MVT::f64}, Legal);389 390    for (MVT VT :391         {MVT::v16i8, MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v8i16, MVT::v4i16,392          MVT::v2i16, MVT::v4i32, MVT::v2i32, MVT::v2i64}) {393      setOperationAction(ISD::TRUNCATE, VT, Custom);394      setOperationAction(ISD::VECREDUCE_ADD, VT, Custom);395      setOperationAction(ISD::VECREDUCE_AND, VT, Custom);396      setOperationAction(ISD::VECREDUCE_OR, VT, Custom);397      setOperationAction(ISD::VECREDUCE_XOR, VT, Custom);398      setOperationAction(ISD::VECREDUCE_SMAX, VT, Custom);399      setOperationAction(ISD::VECREDUCE_SMIN, VT, Custom);400      setOperationAction(ISD::VECREDUCE_UMAX, VT, Custom);401      setOperationAction(ISD::VECREDUCE_UMIN, VT, Custom);402    }403  }404 405  // Set operations for 'LASX' feature.406 407  if (Subtarget.hasExtLASX()) {408    for (MVT VT : LASXVTs) {409      setOperationAction({ISD::LOAD, ISD::STORE}, VT, Legal);410      setOperationAction(ISD::BITCAST, VT, Legal);411      setOperationAction(ISD::UNDEF, VT, Legal);412 413      setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);414      setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);415      setOperationAction(ISD::BUILD_VECTOR, VT, Custom);416      setOperationAction(ISD::CONCAT_VECTORS, VT, Custom);417      setOperationAction(ISD::INSERT_SUBVECTOR, VT, Legal);418 419      setOperationAction(ISD::SETCC, VT, Legal);420      setOperationAction(ISD::VSELECT, VT, Legal);421      setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);422    }423    for (MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16, MVT::v32i8}) {424      setOperationAction({ISD::ADD, ISD::SUB}, VT, Legal);425      setOperationAction({ISD::UMAX, ISD::UMIN, ISD::SMAX, ISD::SMIN}, VT,426                         Legal);427      setOperationAction({ISD::MUL, ISD::SDIV, ISD::SREM, ISD::UDIV, ISD::UREM},428                         VT, Legal);429      setOperationAction({ISD::AND, ISD::OR, ISD::XOR}, VT, Legal);430      setOperationAction({ISD::SHL, ISD::SRA, ISD::SRL}, VT, Legal);431      setOperationAction({ISD::CTPOP, ISD::CTLZ}, VT, Legal);432      setOperationAction({ISD::MULHS, ISD::MULHU}, VT, Legal);433      setCondCodeAction(434          {ISD::SETNE, ISD::SETGE, ISD::SETGT, ISD::SETUGE, ISD::SETUGT}, VT,435          Expand);436      setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);437      setOperationAction(ISD::ABS, VT, Legal);438      setOperationAction(ISD::ABDS, VT, Legal);439      setOperationAction(ISD::ABDU, VT, Legal);440      setOperationAction(ISD::SADDSAT, VT, Legal);441      setOperationAction(ISD::SSUBSAT, VT, Legal);442      setOperationAction(ISD::UADDSAT, VT, Legal);443      setOperationAction(ISD::USUBSAT, VT, Legal);444      setOperationAction(ISD::VECREDUCE_ADD, VT, Custom);445      setOperationAction(ISD::ROTL, VT, Custom);446      setOperationAction(ISD::ROTR, VT, Custom);447    }448    for (MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})449      setOperationAction(ISD::BITREVERSE, VT, Custom);450    for (MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64})451      setOperationAction(ISD::BSWAP, VT, Legal);452    for (MVT VT : {MVT::v8i32, MVT::v4i32, MVT::v4i64}) {453      setOperationAction({ISD::SINT_TO_FP, ISD::UINT_TO_FP}, VT, Legal);454      setOperationAction({ISD::FP_TO_SINT, ISD::FP_TO_UINT}, VT, Legal);455    }456    for (MVT VT : {MVT::v8f32, MVT::v4f64}) {457      setOperationAction({ISD::FADD, ISD::FSUB}, VT, Legal);458      setOperationAction({ISD::FMUL, ISD::FDIV}, VT, Legal);459      setOperationAction(ISD::FMA, VT, Legal);460      setOperationAction(ISD::FSQRT, VT, Legal);461      setOperationAction(ISD::FNEG, VT, Legal);462      setOperationAction(ISD::FLOG2, VT, Legal);463      setCondCodeAction({ISD::SETGE, ISD::SETGT, ISD::SETOGE, ISD::SETOGT,464                         ISD::SETUGE, ISD::SETUGT},465                        VT, Expand);466      setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Legal);467      setOperationAction(ISD::FCEIL, VT, Legal);468      setOperationAction(ISD::FFLOOR, VT, Legal);469      setOperationAction(ISD::FTRUNC, VT, Legal);470      setOperationAction(ISD::FROUNDEVEN, VT, Legal);471      setOperationAction(ISD::FMINNUM, VT, Legal);472      setOperationAction(ISD::FMAXNUM, VT, Legal);473    }474  }475 476  // Set DAG combine for LA32 and LA64.477 478  setTargetDAGCombine(ISD::AND);479  setTargetDAGCombine(ISD::OR);480  setTargetDAGCombine(ISD::SRL);481  setTargetDAGCombine(ISD::SETCC);482 483  // Set DAG combine for 'LSX' feature.484 485  if (Subtarget.hasExtLSX()) {486    setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN);487    setTargetDAGCombine(ISD::BITCAST);488  }489 490  // Set DAG combine for 'LASX' feature.491 492  if (Subtarget.hasExtLASX())493    setTargetDAGCombine(ISD::EXTRACT_VECTOR_ELT);494 495  // Compute derived properties from the register classes.496  computeRegisterProperties(Subtarget.getRegisterInfo());497 498  setStackPointerRegisterToSaveRestore(LoongArch::R3);499 500  setBooleanContents(ZeroOrOneBooleanContent);501  setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);502 503  setMaxAtomicSizeInBitsSupported(Subtarget.getGRLen());504 505  setMinCmpXchgSizeInBits(32);506 507  // Function alignments.508  setMinFunctionAlignment(Align(4));509  // Set preferred alignments.510  setPrefFunctionAlignment(Subtarget.getPrefFunctionAlignment());511  setPrefLoopAlignment(Subtarget.getPrefLoopAlignment());512  setMaxBytesForAlignment(Subtarget.getMaxBytesForAlignment());513 514  // cmpxchg sizes down to 8 bits become legal if LAMCAS is available.515  if (Subtarget.hasLAMCAS())516    setMinCmpXchgSizeInBits(8);517 518  if (Subtarget.hasSCQ()) {519    setMaxAtomicSizeInBitsSupported(128);520    setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i128, Custom);521  }522}523 524bool LoongArchTargetLowering::isOffsetFoldingLegal(525    const GlobalAddressSDNode *GA) const {526  // In order to maximise the opportunity for common subexpression elimination,527  // keep a separate ADD node for the global address offset instead of folding528  // it in the global address node. Later peephole optimisations may choose to529  // fold it back in when profitable.530  return false;531}532 533SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,534                                                SelectionDAG &DAG) const {535  switch (Op.getOpcode()) {536  case ISD::ATOMIC_FENCE:537    return lowerATOMIC_FENCE(Op, DAG);538  case ISD::EH_DWARF_CFA:539    return lowerEH_DWARF_CFA(Op, DAG);540  case ISD::GlobalAddress:541    return lowerGlobalAddress(Op, DAG);542  case ISD::GlobalTLSAddress:543    return lowerGlobalTLSAddress(Op, DAG);544  case ISD::INTRINSIC_WO_CHAIN:545    return lowerINTRINSIC_WO_CHAIN(Op, DAG);546  case ISD::INTRINSIC_W_CHAIN:547    return lowerINTRINSIC_W_CHAIN(Op, DAG);548  case ISD::INTRINSIC_VOID:549    return lowerINTRINSIC_VOID(Op, DAG);550  case ISD::BlockAddress:551    return lowerBlockAddress(Op, DAG);552  case ISD::JumpTable:553    return lowerJumpTable(Op, DAG);554  case ISD::SHL_PARTS:555    return lowerShiftLeftParts(Op, DAG);556  case ISD::SRA_PARTS:557    return lowerShiftRightParts(Op, DAG, true);558  case ISD::SRL_PARTS:559    return lowerShiftRightParts(Op, DAG, false);560  case ISD::ConstantPool:561    return lowerConstantPool(Op, DAG);562  case ISD::FP_TO_SINT:563    return lowerFP_TO_SINT(Op, DAG);564  case ISD::BITCAST:565    return lowerBITCAST(Op, DAG);566  case ISD::UINT_TO_FP:567    return lowerUINT_TO_FP(Op, DAG);568  case ISD::SINT_TO_FP:569    return lowerSINT_TO_FP(Op, DAG);570  case ISD::VASTART:571    return lowerVASTART(Op, DAG);572  case ISD::FRAMEADDR:573    return lowerFRAMEADDR(Op, DAG);574  case ISD::RETURNADDR:575    return lowerRETURNADDR(Op, DAG);576  case ISD::WRITE_REGISTER:577    return lowerWRITE_REGISTER(Op, DAG);578  case ISD::INSERT_VECTOR_ELT:579    return lowerINSERT_VECTOR_ELT(Op, DAG);580  case ISD::EXTRACT_VECTOR_ELT:581    return lowerEXTRACT_VECTOR_ELT(Op, DAG);582  case ISD::BUILD_VECTOR:583    return lowerBUILD_VECTOR(Op, DAG);584  case ISD::CONCAT_VECTORS:585    return lowerCONCAT_VECTORS(Op, DAG);586  case ISD::VECTOR_SHUFFLE:587    return lowerVECTOR_SHUFFLE(Op, DAG);588  case ISD::BITREVERSE:589    return lowerBITREVERSE(Op, DAG);590  case ISD::SCALAR_TO_VECTOR:591    return lowerSCALAR_TO_VECTOR(Op, DAG);592  case ISD::PREFETCH:593    return lowerPREFETCH(Op, DAG);594  case ISD::SELECT:595    return lowerSELECT(Op, DAG);596  case ISD::BRCOND:597    return lowerBRCOND(Op, DAG);598  case ISD::FP_TO_FP16:599    return lowerFP_TO_FP16(Op, DAG);600  case ISD::FP16_TO_FP:601    return lowerFP16_TO_FP(Op, DAG);602  case ISD::FP_TO_BF16:603    return lowerFP_TO_BF16(Op, DAG);604  case ISD::BF16_TO_FP:605    return lowerBF16_TO_FP(Op, DAG);606  case ISD::VECREDUCE_ADD:607    return lowerVECREDUCE_ADD(Op, DAG);608  case ISD::ROTL:609  case ISD::ROTR:610    return lowerRotate(Op, DAG);611  case ISD::VECREDUCE_AND:612  case ISD::VECREDUCE_OR:613  case ISD::VECREDUCE_XOR:614  case ISD::VECREDUCE_SMAX:615  case ISD::VECREDUCE_SMIN:616  case ISD::VECREDUCE_UMAX:617  case ISD::VECREDUCE_UMIN:618    return lowerVECREDUCE(Op, DAG);619  case ISD::ConstantFP:620    return lowerConstantFP(Op, DAG);621  }622  return SDValue();623}624 625// Helper to attempt to return a cheaper, bit-inverted version of \p V.626static SDValue isNOT(SDValue V, SelectionDAG &DAG) {627  // TODO: don't always ignore oneuse constraints.628  V = peekThroughBitcasts(V);629  EVT VT = V.getValueType();630 631  // Match not(xor X, -1) -> X.632  if (V.getOpcode() == ISD::XOR &&633      (ISD::isBuildVectorAllOnes(V.getOperand(1).getNode()) ||634       isAllOnesConstant(V.getOperand(1))))635    return V.getOperand(0);636 637  // Match not(extract_subvector(not(X)) -> extract_subvector(X).638  if (V.getOpcode() == ISD::EXTRACT_SUBVECTOR &&639      (isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) {640    if (SDValue Not = isNOT(V.getOperand(0), DAG)) {641      Not = DAG.getBitcast(V.getOperand(0).getValueType(), Not);642      return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(Not), VT, Not,643                         V.getOperand(1));644    }645  }646 647  // Match not(SplatVector(not(X)) -> SplatVector(X).648  if (V.getOpcode() == ISD::BUILD_VECTOR) {649    if (SDValue SplatValue =650            cast<BuildVectorSDNode>(V.getNode())->getSplatValue()) {651      if (!V->isOnlyUserOf(SplatValue.getNode()))652        return SDValue();653 654      if (SDValue Not = isNOT(SplatValue, DAG)) {655        Not = DAG.getBitcast(V.getOperand(0).getValueType(), Not);656        return DAG.getSplat(VT, SDLoc(Not), Not);657      }658    }659  }660 661  // Match not(or(not(X),not(Y))) -> and(X, Y).662  if (V.getOpcode() == ISD::OR && DAG.getTargetLoweringInfo().isTypeLegal(VT) &&663      V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) {664    // TODO: Handle cases with single NOT operand -> VANDN665    if (SDValue Op1 = isNOT(V.getOperand(1), DAG))666      if (SDValue Op0 = isNOT(V.getOperand(0), DAG))667        return DAG.getNode(ISD::AND, SDLoc(V), VT, DAG.getBitcast(VT, Op0),668                           DAG.getBitcast(VT, Op1));669  }670 671  // TODO: Add more matching patterns. Such as,672  // not(concat_vectors(not(X), not(Y))) -> concat_vectors(X, Y).673  // not(slt(C, X)) -> slt(X - 1, C)674 675  return SDValue();676}677 678SDValue LoongArchTargetLowering::lowerConstantFP(SDValue Op,679                                                 SelectionDAG &DAG) const {680  EVT VT = Op.getValueType();681  ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Op);682  const APFloat &FPVal = CFP->getValueAPF();683  SDLoc DL(CFP);684 685  assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||686         (VT == MVT::f64 && Subtarget.hasBasicD()));687 688  // If value is 0.0 or -0.0, just ignore it.689  if (FPVal.isZero())690    return SDValue();691 692  // If lsx enabled, use cheaper 'vldi' instruction if possible.693  if (isFPImmVLDILegal(FPVal, VT))694    return SDValue();695 696  // Construct as integer, and move to float register.697  APInt INTVal = FPVal.bitcastToAPInt();698 699  // If more than MaterializeFPImmInsNum instructions will be used to700  // generate the INTVal and move it to float register, fallback to701  // use floating point load from the constant pool.702  auto Seq = LoongArchMatInt::generateInstSeq(INTVal.getSExtValue());703  int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);704  if (InsNum > MaterializeFPImmInsNum && !FPVal.isExactlyValue(+1.0))705    return SDValue();706 707  switch (VT.getSimpleVT().SimpleTy) {708  default:709    llvm_unreachable("Unexpected floating point type!");710    break;711  case MVT::f32: {712    SDValue NewVal = DAG.getConstant(INTVal, DL, MVT::i32);713    if (Subtarget.is64Bit())714      NewVal = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, NewVal);715    return DAG.getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64716                                           : LoongArchISD::MOVGR2FR_W,717                       DL, VT, NewVal);718  }719  case MVT::f64: {720    if (Subtarget.is64Bit()) {721      SDValue NewVal = DAG.getConstant(INTVal, DL, MVT::i64);722      return DAG.getNode(LoongArchISD::MOVGR2FR_D, DL, VT, NewVal);723    }724    SDValue Lo = DAG.getConstant(INTVal.trunc(32), DL, MVT::i32);725    SDValue Hi = DAG.getConstant(INTVal.lshr(32).trunc(32), DL, MVT::i32);726    return DAG.getNode(LoongArchISD::MOVGR2FR_D_LO_HI, DL, VT, Lo, Hi);727  }728  }729 730  return SDValue();731}732 733// Lower vecreduce_add using vhaddw instructions.734// For Example:735//  call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %a)736// can be lowered to:737//  VHADDW_D_W    vr0, vr0, vr0738//  VHADDW_Q_D    vr0, vr0, vr0739//  VPICKVE2GR_D  a0,  vr0, 0740//  ADDI_W        a0,  a0,  0741SDValue LoongArchTargetLowering::lowerVECREDUCE_ADD(SDValue Op,742                                                    SelectionDAG &DAG) const {743 744  SDLoc DL(Op);745  MVT OpVT = Op.getSimpleValueType();746  SDValue Val = Op.getOperand(0);747 748  unsigned NumEles = Val.getSimpleValueType().getVectorNumElements();749  unsigned EleBits = Val.getSimpleValueType().getScalarSizeInBits();750  unsigned ResBits = OpVT.getScalarSizeInBits();751 752  unsigned LegalVecSize = 128;753  bool isLASX256Vector =754      Subtarget.hasExtLASX() && Val.getValueSizeInBits() == 256;755 756  // Ensure operand type legal or enable it legal.757  while (!isTypeLegal(Val.getSimpleValueType())) {758    Val = DAG.WidenVector(Val, DL);759  }760 761  // NumEles is designed for iterations count, v4i32 for LSX762  // and v8i32 for LASX should have the same count.763  if (isLASX256Vector) {764    NumEles /= 2;765    LegalVecSize = 256;766  }767 768  for (unsigned i = 1; i < NumEles; i *= 2, EleBits *= 2) {769    MVT IntTy = MVT::getIntegerVT(EleBits);770    MVT VecTy = MVT::getVectorVT(IntTy, LegalVecSize / EleBits);771    Val = DAG.getNode(LoongArchISD::VHADDW, DL, VecTy, Val, Val);772  }773 774  if (isLASX256Vector) {775    SDValue Tmp = DAG.getNode(LoongArchISD::XVPERMI, DL, MVT::v4i64, Val,776                              DAG.getConstant(2, DL, Subtarget.getGRLenVT()));777    Val = DAG.getNode(ISD::ADD, DL, MVT::v4i64, Tmp, Val);778  }779 780  Val = DAG.getBitcast(MVT::getVectorVT(OpVT, LegalVecSize / ResBits), Val);781  return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, OpVT, Val,782                     DAG.getConstant(0, DL, Subtarget.getGRLenVT()));783}784 785// Lower vecreduce_and/or/xor/[s/u]max/[s/u]min.786// For Example:787//  call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> %a)788// can be lowered to:789//  VBSRL_V       vr1, vr0, 8790//  VMAX_W        vr0, vr1, vr0791//  VBSRL_V       vr1, vr0, 4792//  VMAX_W        vr0, vr1, vr0793//  VPICKVE2GR_W  a0,  vr0, 0794// For 256 bit vector, it is illegal and will be spilt into795// two 128 bit vector by default then processed by this.796SDValue LoongArchTargetLowering::lowerVECREDUCE(SDValue Op,797                                                SelectionDAG &DAG) const {798  SDLoc DL(Op);799 800  MVT OpVT = Op.getSimpleValueType();801  SDValue Val = Op.getOperand(0);802 803  unsigned NumEles = Val.getSimpleValueType().getVectorNumElements();804  unsigned EleBits = Val.getSimpleValueType().getScalarSizeInBits();805 806  // Ensure operand type legal or enable it legal.807  while (!isTypeLegal(Val.getSimpleValueType())) {808    Val = DAG.WidenVector(Val, DL);809  }810 811  unsigned Opcode = ISD::getVecReduceBaseOpcode(Op.getOpcode());812  MVT VecTy = Val.getSimpleValueType();813  MVT GRLenVT = Subtarget.getGRLenVT();814 815  for (int i = NumEles; i > 1; i /= 2) {816    SDValue ShiftAmt = DAG.getConstant(i * EleBits / 16, DL, GRLenVT);817    SDValue Tmp = DAG.getNode(LoongArchISD::VBSRL, DL, VecTy, Val, ShiftAmt);818    Val = DAG.getNode(Opcode, DL, VecTy, Tmp, Val);819  }820 821  return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, OpVT, Val,822                     DAG.getConstant(0, DL, GRLenVT));823}824 825SDValue LoongArchTargetLowering::lowerPREFETCH(SDValue Op,826                                               SelectionDAG &DAG) const {827  unsigned IsData = Op.getConstantOperandVal(4);828 829  // We don't support non-data prefetch.830  // Just preserve the chain.831  if (!IsData)832    return Op.getOperand(0);833 834  return Op;835}836 837SDValue LoongArchTargetLowering::lowerRotate(SDValue Op,838                                             SelectionDAG &DAG) const {839  MVT VT = Op.getSimpleValueType();840  assert(VT.isVector() && "Unexpected type");841 842  SDLoc DL(Op);843  SDValue R = Op.getOperand(0);844  SDValue Amt = Op.getOperand(1);845  unsigned Opcode = Op.getOpcode();846  unsigned EltSizeInBits = VT.getScalarSizeInBits();847 848  auto checkCstSplat = [](SDValue V, APInt &CstSplatValue) {849    if (V.getOpcode() != ISD::BUILD_VECTOR)850      return false;851    if (SDValue SplatValue =852            cast<BuildVectorSDNode>(V.getNode())->getSplatValue()) {853      if (auto *C = dyn_cast<ConstantSDNode>(SplatValue)) {854        CstSplatValue = C->getAPIntValue();855        return true;856      }857    }858    return false;859  };860 861  // Check for constant splat rotation amount.862  APInt CstSplatValue;863  bool IsCstSplat = checkCstSplat(Amt, CstSplatValue);864  bool isROTL = Opcode == ISD::ROTL;865 866  // Check for splat rotate by zero.867  if (IsCstSplat && CstSplatValue.urem(EltSizeInBits) == 0)868    return R;869 870  // LoongArch targets always prefer ISD::ROTR.871  if (isROTL) {872    SDValue Zero = DAG.getConstant(0, DL, VT);873    return DAG.getNode(ISD::ROTR, DL, VT, R,874                       DAG.getNode(ISD::SUB, DL, VT, Zero, Amt));875  }876 877  // Rotate by a immediate.878  if (IsCstSplat) {879    // ISD::ROTR: Attemp to rotate by a positive immediate.880    SDValue Bits = DAG.getConstant(EltSizeInBits, DL, VT);881    if (SDValue Urem =882            DAG.FoldConstantArithmetic(ISD::UREM, DL, VT, {Amt, Bits}))883      return DAG.getNode(Opcode, DL, VT, R, Urem);884  }885 886  return Op;887}888 889// Return true if Val is equal to (setcc LHS, RHS, CC).890// Return false if Val is the inverse of (setcc LHS, RHS, CC).891// Otherwise, return std::nullopt.892static std::optional<bool> matchSetCC(SDValue LHS, SDValue RHS,893                                      ISD::CondCode CC, SDValue Val) {894  assert(Val->getOpcode() == ISD::SETCC);895  SDValue LHS2 = Val.getOperand(0);896  SDValue RHS2 = Val.getOperand(1);897  ISD::CondCode CC2 = cast<CondCodeSDNode>(Val.getOperand(2))->get();898 899  if (LHS == LHS2 && RHS == RHS2) {900    if (CC == CC2)901      return true;902    if (CC == ISD::getSetCCInverse(CC2, LHS2.getValueType()))903      return false;904  } else if (LHS == RHS2 && RHS == LHS2) {905    CC2 = ISD::getSetCCSwappedOperands(CC2);906    if (CC == CC2)907      return true;908    if (CC == ISD::getSetCCInverse(CC2, LHS2.getValueType()))909      return false;910  }911 912  return std::nullopt;913}914 915static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG,916                                    const LoongArchSubtarget &Subtarget) {917  SDValue CondV = N->getOperand(0);918  SDValue TrueV = N->getOperand(1);919  SDValue FalseV = N->getOperand(2);920  MVT VT = N->getSimpleValueType(0);921  SDLoc DL(N);922 923  // (select c, -1, y) -> -c | y924  if (isAllOnesConstant(TrueV)) {925    SDValue Neg = DAG.getNegative(CondV, DL, VT);926    return DAG.getNode(ISD::OR, DL, VT, Neg, DAG.getFreeze(FalseV));927  }928  // (select c, y, -1) -> (c-1) | y929  if (isAllOnesConstant(FalseV)) {930    SDValue Neg =931        DAG.getNode(ISD::ADD, DL, VT, CondV, DAG.getAllOnesConstant(DL, VT));932    return DAG.getNode(ISD::OR, DL, VT, Neg, DAG.getFreeze(TrueV));933  }934 935  // (select c, 0, y) -> (c-1) & y936  if (isNullConstant(TrueV)) {937    SDValue Neg =938        DAG.getNode(ISD::ADD, DL, VT, CondV, DAG.getAllOnesConstant(DL, VT));939    return DAG.getNode(ISD::AND, DL, VT, Neg, DAG.getFreeze(FalseV));940  }941  // (select c, y, 0) -> -c & y942  if (isNullConstant(FalseV)) {943    SDValue Neg = DAG.getNegative(CondV, DL, VT);944    return DAG.getNode(ISD::AND, DL, VT, Neg, DAG.getFreeze(TrueV));945  }946 947  // select c, ~x, x --> xor -c, x948  if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV)) {949    const APInt &TrueVal = TrueV->getAsAPIntVal();950    const APInt &FalseVal = FalseV->getAsAPIntVal();951    if (~TrueVal == FalseVal) {952      SDValue Neg = DAG.getNegative(CondV, DL, VT);953      return DAG.getNode(ISD::XOR, DL, VT, Neg, FalseV);954    }955  }956 957  // Try to fold (select (setcc lhs, rhs, cc), truev, falsev) into bitwise ops958  // when both truev and falsev are also setcc.959  if (CondV.getOpcode() == ISD::SETCC && TrueV.getOpcode() == ISD::SETCC &&960      FalseV.getOpcode() == ISD::SETCC) {961    SDValue LHS = CondV.getOperand(0);962    SDValue RHS = CondV.getOperand(1);963    ISD::CondCode CC = cast<CondCodeSDNode>(CondV.getOperand(2))->get();964 965    // (select x, x, y) -> x | y966    // (select !x, x, y) -> x & y967    if (std::optional<bool> MatchResult = matchSetCC(LHS, RHS, CC, TrueV)) {968      return DAG.getNode(*MatchResult ? ISD::OR : ISD::AND, DL, VT, TrueV,969                         DAG.getFreeze(FalseV));970    }971    // (select x, y, x) -> x & y972    // (select !x, y, x) -> x | y973    if (std::optional<bool> MatchResult = matchSetCC(LHS, RHS, CC, FalseV)) {974      return DAG.getNode(*MatchResult ? ISD::AND : ISD::OR, DL, VT,975                         DAG.getFreeze(TrueV), FalseV);976    }977  }978 979  return SDValue();980}981 982// Transform `binOp (select cond, x, c0), c1` where `c0` and `c1` are constants983// into `select cond, binOp(x, c1), binOp(c0, c1)` if profitable.984// For now we only consider transformation profitable if `binOp(c0, c1)` ends up985// being `0` or `-1`. In such cases we can replace `select` with `and`.986// TODO: Should we also do this if `binOp(c0, c1)` is cheaper to materialize987// than `c0`?988static SDValue989foldBinOpIntoSelectIfProfitable(SDNode *BO, SelectionDAG &DAG,990                                const LoongArchSubtarget &Subtarget) {991  unsigned SelOpNo = 0;992  SDValue Sel = BO->getOperand(0);993  if (Sel.getOpcode() != ISD::SELECT || !Sel.hasOneUse()) {994    SelOpNo = 1;995    Sel = BO->getOperand(1);996  }997 998  if (Sel.getOpcode() != ISD::SELECT || !Sel.hasOneUse())999    return SDValue();1000 1001  unsigned ConstSelOpNo = 1;1002  unsigned OtherSelOpNo = 2;1003  if (!isa<ConstantSDNode>(Sel->getOperand(ConstSelOpNo))) {1004    ConstSelOpNo = 2;1005    OtherSelOpNo = 1;1006  }1007  SDValue ConstSelOp = Sel->getOperand(ConstSelOpNo);1008  ConstantSDNode *ConstSelOpNode = dyn_cast<ConstantSDNode>(ConstSelOp);1009  if (!ConstSelOpNode || ConstSelOpNode->isOpaque())1010    return SDValue();1011 1012  SDValue ConstBinOp = BO->getOperand(SelOpNo ^ 1);1013  ConstantSDNode *ConstBinOpNode = dyn_cast<ConstantSDNode>(ConstBinOp);1014  if (!ConstBinOpNode || ConstBinOpNode->isOpaque())1015    return SDValue();1016 1017  SDLoc DL(Sel);1018  EVT VT = BO->getValueType(0);1019 1020  SDValue NewConstOps[2] = {ConstSelOp, ConstBinOp};1021  if (SelOpNo == 1)1022    std::swap(NewConstOps[0], NewConstOps[1]);1023 1024  SDValue NewConstOp =1025      DAG.FoldConstantArithmetic(BO->getOpcode(), DL, VT, NewConstOps);1026  if (!NewConstOp)1027    return SDValue();1028 1029  const APInt &NewConstAPInt = NewConstOp->getAsAPIntVal();1030  if (!NewConstAPInt.isZero() && !NewConstAPInt.isAllOnes())1031    return SDValue();1032 1033  SDValue OtherSelOp = Sel->getOperand(OtherSelOpNo);1034  SDValue NewNonConstOps[2] = {OtherSelOp, ConstBinOp};1035  if (SelOpNo == 1)1036    std::swap(NewNonConstOps[0], NewNonConstOps[1]);1037  SDValue NewNonConstOp = DAG.getNode(BO->getOpcode(), DL, VT, NewNonConstOps);1038 1039  SDValue NewT = (ConstSelOpNo == 1) ? NewConstOp : NewNonConstOp;1040  SDValue NewF = (ConstSelOpNo == 1) ? NewNonConstOp : NewConstOp;1041  return DAG.getSelect(DL, VT, Sel.getOperand(0), NewT, NewF);1042}1043 1044// Changes the condition code and swaps operands if necessary, so the SetCC1045// operation matches one of the comparisons supported directly by branches1046// in the LoongArch ISA. May adjust compares to favor compare with 0 over1047// compare with 1/-1.1048static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS,1049                                    ISD::CondCode &CC, SelectionDAG &DAG) {1050  // If this is a single bit test that can't be handled by ANDI, shift the1051  // bit to be tested to the MSB and perform a signed compare with 0.1052  if (isIntEqualitySetCC(CC) && isNullConstant(RHS) &&1053      LHS.getOpcode() == ISD::AND && LHS.hasOneUse() &&1054      isa<ConstantSDNode>(LHS.getOperand(1))) {1055    uint64_t Mask = LHS.getConstantOperandVal(1);1056    if ((isPowerOf2_64(Mask) || isMask_64(Mask)) && !isInt<12>(Mask)) {1057      unsigned ShAmt = 0;1058      if (isPowerOf2_64(Mask)) {1059        CC = CC == ISD::SETEQ ? ISD::SETGE : ISD::SETLT;1060        ShAmt = LHS.getValueSizeInBits() - 1 - Log2_64(Mask);1061      } else {1062        ShAmt = LHS.getValueSizeInBits() - llvm::bit_width(Mask);1063      }1064 1065      LHS = LHS.getOperand(0);1066      if (ShAmt != 0)1067        LHS = DAG.getNode(ISD::SHL, DL, LHS.getValueType(), LHS,1068                          DAG.getConstant(ShAmt, DL, LHS.getValueType()));1069      return;1070    }1071  }1072 1073  if (auto *RHSC = dyn_cast<ConstantSDNode>(RHS)) {1074    int64_t C = RHSC->getSExtValue();1075    switch (CC) {1076    default:1077      break;1078    case ISD::SETGT:1079      // Convert X > -1 to X >= 0.1080      if (C == -1) {1081        RHS = DAG.getConstant(0, DL, RHS.getValueType());1082        CC = ISD::SETGE;1083        return;1084      }1085      break;1086    case ISD::SETLT:1087      // Convert X < 1 to 0 >= X.1088      if (C == 1) {1089        RHS = LHS;1090        LHS = DAG.getConstant(0, DL, RHS.getValueType());1091        CC = ISD::SETGE;1092        return;1093      }1094      break;1095    }1096  }1097 1098  switch (CC) {1099  default:1100    break;1101  case ISD::SETGT:1102  case ISD::SETLE:1103  case ISD::SETUGT:1104  case ISD::SETULE:1105    CC = ISD::getSetCCSwappedOperands(CC);1106    std::swap(LHS, RHS);1107    break;1108  }1109}1110 1111SDValue LoongArchTargetLowering::lowerSELECT(SDValue Op,1112                                             SelectionDAG &DAG) const {1113  SDValue CondV = Op.getOperand(0);1114  SDValue TrueV = Op.getOperand(1);1115  SDValue FalseV = Op.getOperand(2);1116  SDLoc DL(Op);1117  MVT VT = Op.getSimpleValueType();1118  MVT GRLenVT = Subtarget.getGRLenVT();1119 1120  if (SDValue V = combineSelectToBinOp(Op.getNode(), DAG, Subtarget))1121    return V;1122 1123  if (Op.hasOneUse()) {1124    unsigned UseOpc = Op->user_begin()->getOpcode();1125    if (isBinOp(UseOpc) && DAG.isSafeToSpeculativelyExecute(UseOpc)) {1126      SDNode *BinOp = *Op->user_begin();1127      if (SDValue NewSel = foldBinOpIntoSelectIfProfitable(*Op->user_begin(),1128                                                           DAG, Subtarget)) {1129        DAG.ReplaceAllUsesWith(BinOp, &NewSel);1130        // Opcode check is necessary because foldBinOpIntoSelectIfProfitable1131        // may return a constant node and cause crash in lowerSELECT.1132        if (NewSel.getOpcode() == ISD::SELECT)1133          return lowerSELECT(NewSel, DAG);1134        return NewSel;1135      }1136    }1137  }1138 1139  // If the condition is not an integer SETCC which operates on GRLenVT, we need1140  // to emit a LoongArchISD::SELECT_CC comparing the condition to zero. i.e.:1141  // (select condv, truev, falsev)1142  // -> (loongarchisd::select_cc condv, zero, setne, truev, falsev)1143  if (CondV.getOpcode() != ISD::SETCC ||1144      CondV.getOperand(0).getSimpleValueType() != GRLenVT) {1145    SDValue Zero = DAG.getConstant(0, DL, GRLenVT);1146    SDValue SetNE = DAG.getCondCode(ISD::SETNE);1147 1148    SDValue Ops[] = {CondV, Zero, SetNE, TrueV, FalseV};1149 1150    return DAG.getNode(LoongArchISD::SELECT_CC, DL, VT, Ops);1151  }1152 1153  // If the CondV is the output of a SETCC node which operates on GRLenVT1154  // inputs, then merge the SETCC node into the lowered LoongArchISD::SELECT_CC1155  // to take advantage of the integer compare+branch instructions. i.e.: (select1156  // (setcc lhs, rhs, cc), truev, falsev)1157  // -> (loongarchisd::select_cc lhs, rhs, cc, truev, falsev)1158  SDValue LHS = CondV.getOperand(0);1159  SDValue RHS = CondV.getOperand(1);1160  ISD::CondCode CCVal = cast<CondCodeSDNode>(CondV.getOperand(2))->get();1161 1162  // Special case for a select of 2 constants that have a difference of 1.1163  // Normally this is done by DAGCombine, but if the select is introduced by1164  // type legalization or op legalization, we miss it. Restricting to SETLT1165  // case for now because that is what signed saturating add/sub need.1166  // FIXME: We don't need the condition to be SETLT or even a SETCC,1167  // but we would probably want to swap the true/false values if the condition1168  // is SETGE/SETLE to avoid an XORI.1169  if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&1170      CCVal == ISD::SETLT) {1171    const APInt &TrueVal = TrueV->getAsAPIntVal();1172    const APInt &FalseVal = FalseV->getAsAPIntVal();1173    if (TrueVal - 1 == FalseVal)1174      return DAG.getNode(ISD::ADD, DL, VT, CondV, FalseV);1175    if (TrueVal + 1 == FalseVal)1176      return DAG.getNode(ISD::SUB, DL, VT, FalseV, CondV);1177  }1178 1179  translateSetCCForBranch(DL, LHS, RHS, CCVal, DAG);1180  // 1 < x ? x : 1 -> 0 < x ? x : 11181  if (isOneConstant(LHS) && (CCVal == ISD::SETLT || CCVal == ISD::SETULT) &&1182      RHS == TrueV && LHS == FalseV) {1183    LHS = DAG.getConstant(0, DL, VT);1184    // 0 <u x is the same as x != 0.1185    if (CCVal == ISD::SETULT) {1186      std::swap(LHS, RHS);1187      CCVal = ISD::SETNE;1188    }1189  }1190 1191  // x <s -1 ? x : -1 -> x <s 0 ? x : -11192  if (isAllOnesConstant(RHS) && CCVal == ISD::SETLT && LHS == TrueV &&1193      RHS == FalseV) {1194    RHS = DAG.getConstant(0, DL, VT);1195  }1196 1197  SDValue TargetCC = DAG.getCondCode(CCVal);1198 1199  if (isa<ConstantSDNode>(TrueV) && !isa<ConstantSDNode>(FalseV)) {1200    // (select (setcc lhs, rhs, CC), constant, falsev)1201    // -> (select (setcc lhs, rhs, InverseCC), falsev, constant)1202    std::swap(TrueV, FalseV);1203    TargetCC = DAG.getCondCode(ISD::getSetCCInverse(CCVal, LHS.getValueType()));1204  }1205 1206  SDValue Ops[] = {LHS, RHS, TargetCC, TrueV, FalseV};1207  return DAG.getNode(LoongArchISD::SELECT_CC, DL, VT, Ops);1208}1209 1210SDValue LoongArchTargetLowering::lowerBRCOND(SDValue Op,1211                                             SelectionDAG &DAG) const {1212  SDValue CondV = Op.getOperand(1);1213  SDLoc DL(Op);1214  MVT GRLenVT = Subtarget.getGRLenVT();1215 1216  if (CondV.getOpcode() == ISD::SETCC) {1217    if (CondV.getOperand(0).getValueType() == GRLenVT) {1218      SDValue LHS = CondV.getOperand(0);1219      SDValue RHS = CondV.getOperand(1);1220      ISD::CondCode CCVal = cast<CondCodeSDNode>(CondV.getOperand(2))->get();1221 1222      translateSetCCForBranch(DL, LHS, RHS, CCVal, DAG);1223 1224      SDValue TargetCC = DAG.getCondCode(CCVal);1225      return DAG.getNode(LoongArchISD::BR_CC, DL, Op.getValueType(),1226                         Op.getOperand(0), LHS, RHS, TargetCC,1227                         Op.getOperand(2));1228    } else if (CondV.getOperand(0).getValueType().isFloatingPoint()) {1229      return DAG.getNode(LoongArchISD::BRCOND, DL, Op.getValueType(),1230                         Op.getOperand(0), CondV, Op.getOperand(2));1231    }1232  }1233 1234  return DAG.getNode(LoongArchISD::BR_CC, DL, Op.getValueType(),1235                     Op.getOperand(0), CondV, DAG.getConstant(0, DL, GRLenVT),1236                     DAG.getCondCode(ISD::SETNE), Op.getOperand(2));1237}1238 1239SDValue1240LoongArchTargetLowering::lowerSCALAR_TO_VECTOR(SDValue Op,1241                                               SelectionDAG &DAG) const {1242  SDLoc DL(Op);1243  MVT OpVT = Op.getSimpleValueType();1244 1245  SDValue Vector = DAG.getUNDEF(OpVT);1246  SDValue Val = Op.getOperand(0);1247  SDValue Idx = DAG.getConstant(0, DL, Subtarget.getGRLenVT());1248 1249  return DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, OpVT, Vector, Val, Idx);1250}1251 1252SDValue LoongArchTargetLowering::lowerBITREVERSE(SDValue Op,1253                                                 SelectionDAG &DAG) const {1254  EVT ResTy = Op->getValueType(0);1255  SDValue Src = Op->getOperand(0);1256  SDLoc DL(Op);1257 1258  // LoongArchISD::BITREV_8B is not supported on LA32.1259  if (!Subtarget.is64Bit() && (ResTy == MVT::v16i8 || ResTy == MVT::v32i8))1260    return SDValue();1261 1262  EVT NewVT = ResTy.is128BitVector() ? MVT::v2i64 : MVT::v4i64;1263  unsigned int OrigEltNum = ResTy.getVectorNumElements();1264  unsigned int NewEltNum = NewVT.getVectorNumElements();1265 1266  SDValue NewSrc = DAG.getNode(ISD::BITCAST, DL, NewVT, Src);1267 1268  SmallVector<SDValue, 8> Ops;1269  for (unsigned int i = 0; i < NewEltNum; i++) {1270    SDValue Op = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i64, NewSrc,1271                             DAG.getConstant(i, DL, Subtarget.getGRLenVT()));1272    unsigned RevOp = (ResTy == MVT::v16i8 || ResTy == MVT::v32i8)1273                         ? (unsigned)LoongArchISD::BITREV_8B1274                         : (unsigned)ISD::BITREVERSE;1275    Ops.push_back(DAG.getNode(RevOp, DL, MVT::i64, Op));1276  }1277  SDValue Res =1278      DAG.getNode(ISD::BITCAST, DL, ResTy, DAG.getBuildVector(NewVT, DL, Ops));1279 1280  switch (ResTy.getSimpleVT().SimpleTy) {1281  default:1282    return SDValue();1283  case MVT::v16i8:1284  case MVT::v32i8:1285    return Res;1286  case MVT::v8i16:1287  case MVT::v16i16:1288  case MVT::v4i32:1289  case MVT::v8i32: {1290    SmallVector<int, 32> Mask;1291    for (unsigned int i = 0; i < NewEltNum; i++)1292      for (int j = OrigEltNum / NewEltNum - 1; j >= 0; j--)1293        Mask.push_back(j + (OrigEltNum / NewEltNum) * i);1294    return DAG.getVectorShuffle(ResTy, DL, Res, DAG.getUNDEF(ResTy), Mask);1295  }1296  }1297}1298 1299// Widen element type to get a new mask value (if possible).1300// For example:1301//  shufflevector <4 x i32> %a, <4 x i32> %b,1302//                <4 x i32> <i32 6, i32 7, i32 2, i32 3>1303// is equivalent to:1304//  shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 3, i32 1>1305// can be lowered to:1306//  VPACKOD_D vr0, vr0, vr11307static SDValue widenShuffleMask(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,1308                                SDValue V1, SDValue V2, SelectionDAG &DAG) {1309  unsigned EltBits = VT.getScalarSizeInBits();1310 1311  if (EltBits > 32 || EltBits == 1)1312    return SDValue();1313 1314  SmallVector<int, 8> NewMask;1315  if (widenShuffleMaskElts(Mask, NewMask)) {1316    MVT NewEltVT = VT.isFloatingPoint() ? MVT::getFloatingPointVT(EltBits * 2)1317                                        : MVT::getIntegerVT(EltBits * 2);1318    MVT NewVT = MVT::getVectorVT(NewEltVT, VT.getVectorNumElements() / 2);1319    if (DAG.getTargetLoweringInfo().isTypeLegal(NewVT)) {1320      SDValue NewV1 = DAG.getBitcast(NewVT, V1);1321      SDValue NewV2 = DAG.getBitcast(NewVT, V2);1322      return DAG.getBitcast(1323          VT, DAG.getVectorShuffle(NewVT, DL, NewV1, NewV2, NewMask));1324    }1325  }1326 1327  return SDValue();1328}1329 1330/// Attempts to match a shuffle mask against the VBSLL, VBSRL, VSLLI and VSRLI1331/// instruction.1332// The funciton matches elements from one of the input vector shuffled to the1333// left or right with zeroable elements 'shifted in'. It handles both the1334// strictly bit-wise element shifts and the byte shfit across an entire 128-bit1335// lane.1336// Mostly copied from X86.1337static int matchShuffleAsShift(MVT &ShiftVT, unsigned &Opcode,1338                               unsigned ScalarSizeInBits, ArrayRef<int> Mask,1339                               int MaskOffset, const APInt &Zeroable) {1340  int Size = Mask.size();1341  unsigned SizeInBits = Size * ScalarSizeInBits;1342 1343  auto CheckZeros = [&](int Shift, int Scale, bool Left) {1344    for (int i = 0; i < Size; i += Scale)1345      for (int j = 0; j < Shift; ++j)1346        if (!Zeroable[i + j + (Left ? 0 : (Scale - Shift))])1347          return false;1348 1349    return true;1350  };1351 1352  auto isSequentialOrUndefInRange = [&](unsigned Pos, unsigned Size, int Low,1353                                        int Step = 1) {1354    for (unsigned i = Pos, e = Pos + Size; i != e; ++i, Low += Step)1355      if (!(Mask[i] == -1 || Mask[i] == Low))1356        return false;1357    return true;1358  };1359 1360  auto MatchShift = [&](int Shift, int Scale, bool Left) {1361    for (int i = 0; i != Size; i += Scale) {1362      unsigned Pos = Left ? i + Shift : i;1363      unsigned Low = Left ? i : i + Shift;1364      unsigned Len = Scale - Shift;1365      if (!isSequentialOrUndefInRange(Pos, Len, Low + MaskOffset))1366        return -1;1367    }1368 1369    int ShiftEltBits = ScalarSizeInBits * Scale;1370    bool ByteShift = ShiftEltBits > 64;1371    Opcode = Left ? (ByteShift ? LoongArchISD::VBSLL : LoongArchISD::VSLLI)1372                  : (ByteShift ? LoongArchISD::VBSRL : LoongArchISD::VSRLI);1373    int ShiftAmt = Shift * ScalarSizeInBits / (ByteShift ? 8 : 1);1374 1375    // Normalize the scale for byte shifts to still produce an i64 element1376    // type.1377    Scale = ByteShift ? Scale / 2 : Scale;1378 1379    // We need to round trip through the appropriate type for the shift.1380    MVT ShiftSVT = MVT::getIntegerVT(ScalarSizeInBits * Scale);1381    ShiftVT = ByteShift ? MVT::getVectorVT(MVT::i8, SizeInBits / 8)1382                        : MVT::getVectorVT(ShiftSVT, Size / Scale);1383    return (int)ShiftAmt;1384  };1385 1386  unsigned MaxWidth = 128;1387  for (int Scale = 2; Scale * ScalarSizeInBits <= MaxWidth; Scale *= 2)1388    for (int Shift = 1; Shift != Scale; ++Shift)1389      for (bool Left : {true, false})1390        if (CheckZeros(Shift, Scale, Left)) {1391          int ShiftAmt = MatchShift(Shift, Scale, Left);1392          if (0 < ShiftAmt)1393            return ShiftAmt;1394        }1395 1396  // no match1397  return -1;1398}1399 1400/// Lower VECTOR_SHUFFLE as shift (if possible).1401///1402/// For example:1403///   %2 = shufflevector <4 x i32> %0, <4 x i32> zeroinitializer,1404///                      <4 x i32> <i32 4, i32 0, i32 1, i32 2>1405/// is lowered to:1406///     (VBSLL_V $v0, $v0, 4)1407///1408///   %2 = shufflevector <4 x i32> %0, <4 x i32> zeroinitializer,1409///                      <4 x i32> <i32 4, i32 0, i32 4, i32 2>1410/// is lowered to:1411///     (VSLLI_D $v0, $v0, 32)1412static SDValue lowerVECTOR_SHUFFLEAsShift(const SDLoc &DL, ArrayRef<int> Mask,1413                                          MVT VT, SDValue V1, SDValue V2,1414                                          SelectionDAG &DAG,1415                                          const LoongArchSubtarget &Subtarget,1416                                          const APInt &Zeroable) {1417  int Size = Mask.size();1418  assert(Size == (int)VT.getVectorNumElements() && "Unexpected mask size");1419 1420  MVT ShiftVT;1421  SDValue V = V1;1422  unsigned Opcode;1423 1424  // Try to match shuffle against V1 shift.1425  int ShiftAmt = matchShuffleAsShift(ShiftVT, Opcode, VT.getScalarSizeInBits(),1426                                     Mask, 0, Zeroable);1427 1428  // If V1 failed, try to match shuffle against V2 shift.1429  if (ShiftAmt < 0) {1430    ShiftAmt = matchShuffleAsShift(ShiftVT, Opcode, VT.getScalarSizeInBits(),1431                                   Mask, Size, Zeroable);1432    V = V2;1433  }1434 1435  if (ShiftAmt < 0)1436    return SDValue();1437 1438  assert(DAG.getTargetLoweringInfo().isTypeLegal(ShiftVT) &&1439         "Illegal integer vector type");1440  V = DAG.getBitcast(ShiftVT, V);1441  V = DAG.getNode(Opcode, DL, ShiftVT, V,1442                  DAG.getConstant(ShiftAmt, DL, Subtarget.getGRLenVT()));1443  return DAG.getBitcast(VT, V);1444}1445 1446/// Determine whether a range fits a regular pattern of values.1447/// This function accounts for the possibility of jumping over the End iterator.1448template <typename ValType>1449static bool1450fitsRegularPattern(typename SmallVectorImpl<ValType>::const_iterator Begin,1451                   unsigned CheckStride,1452                   typename SmallVectorImpl<ValType>::const_iterator End,1453                   ValType ExpectedIndex, unsigned ExpectedIndexStride) {1454  auto &I = Begin;1455 1456  while (I != End) {1457    if (*I != -1 && *I != ExpectedIndex)1458      return false;1459    ExpectedIndex += ExpectedIndexStride;1460 1461    // Incrementing past End is undefined behaviour so we must increment one1462    // step at a time and check for End at each step.1463    for (unsigned n = 0; n < CheckStride && I != End; ++n, ++I)1464      ; // Empty loop body.1465  }1466  return true;1467}1468 1469/// Compute whether each element of a shuffle is zeroable.1470///1471/// A "zeroable" vector shuffle element is one which can be lowered to zero.1472static void computeZeroableShuffleElements(ArrayRef<int> Mask, SDValue V1,1473                                           SDValue V2, APInt &KnownUndef,1474                                           APInt &KnownZero) {1475  int Size = Mask.size();1476  KnownUndef = KnownZero = APInt::getZero(Size);1477 1478  V1 = peekThroughBitcasts(V1);1479  V2 = peekThroughBitcasts(V2);1480 1481  bool V1IsZero = ISD::isBuildVectorAllZeros(V1.getNode());1482  bool V2IsZero = ISD::isBuildVectorAllZeros(V2.getNode());1483 1484  int VectorSizeInBits = V1.getValueSizeInBits();1485  int ScalarSizeInBits = VectorSizeInBits / Size;1486  assert(!(VectorSizeInBits % ScalarSizeInBits) && "Illegal shuffle mask size");1487  (void)ScalarSizeInBits;1488 1489  for (int i = 0; i < Size; ++i) {1490    int M = Mask[i];1491    if (M < 0) {1492      KnownUndef.setBit(i);1493      continue;1494    }1495    if ((M >= 0 && M < Size && V1IsZero) || (M >= Size && V2IsZero)) {1496      KnownZero.setBit(i);1497      continue;1498    }1499  }1500}1501 1502/// Test whether a shuffle mask is equivalent within each sub-lane.1503///1504/// The specific repeated shuffle mask is populated in \p RepeatedMask, as it is1505/// non-trivial to compute in the face of undef lanes. The representation is1506/// suitable for use with existing 128-bit shuffles as entries from the second1507/// vector have been remapped to [LaneSize, 2*LaneSize).1508static bool isRepeatedShuffleMask(unsigned LaneSizeInBits, MVT VT,1509                                  ArrayRef<int> Mask,1510                                  SmallVectorImpl<int> &RepeatedMask) {1511  auto LaneSize = LaneSizeInBits / VT.getScalarSizeInBits();1512  RepeatedMask.assign(LaneSize, -1);1513  int Size = Mask.size();1514  for (int i = 0; i < Size; ++i) {1515    assert(Mask[i] == -1 || Mask[i] >= 0);1516    if (Mask[i] < 0)1517      continue;1518    if ((Mask[i] % Size) / LaneSize != i / LaneSize)1519      // This entry crosses lanes, so there is no way to model this shuffle.1520      return false;1521 1522    // Ok, handle the in-lane shuffles by detecting if and when they repeat.1523    // Adjust second vector indices to start at LaneSize instead of Size.1524    int LocalM =1525        Mask[i] < Size ? Mask[i] % LaneSize : Mask[i] % LaneSize + LaneSize;1526    if (RepeatedMask[i % LaneSize] < 0)1527      // This is the first non-undef entry in this slot of a 128-bit lane.1528      RepeatedMask[i % LaneSize] = LocalM;1529    else if (RepeatedMask[i % LaneSize] != LocalM)1530      // Found a mismatch with the repeated mask.1531      return false;1532  }1533  return true;1534}1535 1536/// Attempts to match vector shuffle as byte rotation.1537static int matchShuffleAsByteRotate(MVT VT, SDValue &V1, SDValue &V2,1538                                    ArrayRef<int> Mask) {1539 1540  SDValue Lo, Hi;1541  SmallVector<int, 16> RepeatedMask;1542 1543  if (!isRepeatedShuffleMask(128, VT, Mask, RepeatedMask))1544    return -1;1545 1546  int NumElts = RepeatedMask.size();1547  int Rotation = 0;1548  int Scale = 16 / NumElts;1549 1550  for (int i = 0; i < NumElts; ++i) {1551    int M = RepeatedMask[i];1552    assert((M == -1 || (0 <= M && M < (2 * NumElts))) &&1553           "Unexpected mask index.");1554    if (M < 0)1555      continue;1556 1557    // Determine where a rotated vector would have started.1558    int StartIdx = i - (M % NumElts);1559    if (StartIdx == 0)1560      return -1;1561 1562    // If we found the tail of a vector the rotation must be the missing1563    // front. If we found the head of a vector, it must be how much of the1564    // head.1565    int CandidateRotation = StartIdx < 0 ? -StartIdx : NumElts - StartIdx;1566 1567    if (Rotation == 0)1568      Rotation = CandidateRotation;1569    else if (Rotation != CandidateRotation)1570      return -1;1571 1572    // Compute which value this mask is pointing at.1573    SDValue MaskV = M < NumElts ? V1 : V2;1574 1575    // Compute which of the two target values this index should be assigned1576    // to. This reflects whether the high elements are remaining or the low1577    // elements are remaining.1578    SDValue &TargetV = StartIdx < 0 ? Hi : Lo;1579 1580    // Either set up this value if we've not encountered it before, or check1581    // that it remains consistent.1582    if (!TargetV)1583      TargetV = MaskV;1584    else if (TargetV != MaskV)1585      return -1;1586  }1587 1588  // Check that we successfully analyzed the mask, and normalize the results.1589  assert(Rotation != 0 && "Failed to locate a viable rotation!");1590  assert((Lo || Hi) && "Failed to find a rotated input vector!");1591  if (!Lo)1592    Lo = Hi;1593  else if (!Hi)1594    Hi = Lo;1595 1596  V1 = Lo;1597  V2 = Hi;1598 1599  return Rotation * Scale;1600}1601 1602/// Lower VECTOR_SHUFFLE as byte rotate (if possible).1603///1604/// For example:1605///   %shuffle = shufflevector <2 x i64> %a, <2 x i64> %b,1606///                            <2 x i32> <i32 3, i32 0>1607/// is lowered to:1608///      (VBSRL_V $v1, $v1, 8)1609///      (VBSLL_V $v0, $v0, 8)1610///      (VOR_V $v0, $V0, $v1)1611static SDValue1612lowerVECTOR_SHUFFLEAsByteRotate(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,1613                                SDValue V1, SDValue V2, SelectionDAG &DAG,1614                                const LoongArchSubtarget &Subtarget) {1615 1616  SDValue Lo = V1, Hi = V2;1617  int ByteRotation = matchShuffleAsByteRotate(VT, Lo, Hi, Mask);1618  if (ByteRotation <= 0)1619    return SDValue();1620 1621  MVT ByteVT = MVT::getVectorVT(MVT::i8, VT.getSizeInBits() / 8);1622  Lo = DAG.getBitcast(ByteVT, Lo);1623  Hi = DAG.getBitcast(ByteVT, Hi);1624 1625  int LoByteShift = 16 - ByteRotation;1626  int HiByteShift = ByteRotation;1627  MVT GRLenVT = Subtarget.getGRLenVT();1628 1629  SDValue LoShift = DAG.getNode(LoongArchISD::VBSLL, DL, ByteVT, Lo,1630                                DAG.getConstant(LoByteShift, DL, GRLenVT));1631  SDValue HiShift = DAG.getNode(LoongArchISD::VBSRL, DL, ByteVT, Hi,1632                                DAG.getConstant(HiByteShift, DL, GRLenVT));1633  return DAG.getBitcast(VT, DAG.getNode(ISD::OR, DL, ByteVT, LoShift, HiShift));1634}1635 1636/// Lower VECTOR_SHUFFLE as ZERO_EXTEND Or ANY_EXTEND (if possible).1637///1638/// For example:1639///   %2 = shufflevector <4 x i32> %0, <4 x i32> zeroinitializer,1640///                      <4 x i32> <i32 0, i32 4, i32 1, i32 4>1641///   %3 = bitcast <4 x i32> %2 to <2 x i64>1642/// is lowered to:1643///     (VREPLI $v1, 0)1644///     (VILVL $v0, $v1, $v0)1645static SDValue lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(const SDLoc &DL,1646                                                    ArrayRef<int> Mask, MVT VT,1647                                                    SDValue V1, SDValue V2,1648                                                    SelectionDAG &DAG,1649                                                    const APInt &Zeroable) {1650  int Bits = VT.getSizeInBits();1651  int EltBits = VT.getScalarSizeInBits();1652  int NumElements = VT.getVectorNumElements();1653 1654  if (Zeroable.isAllOnes())1655    return DAG.getConstant(0, DL, VT);1656 1657  // Define a helper function to check a particular ext-scale and lower to it if1658  // valid.1659  auto Lower = [&](int Scale) -> SDValue {1660    SDValue InputV;1661    bool AnyExt = true;1662    int Offset = 0;1663    for (int i = 0; i < NumElements; i++) {1664      int M = Mask[i];1665      if (M < 0)1666        continue;1667      if (i % Scale != 0) {1668        // Each of the extended elements need to be zeroable.1669        if (!Zeroable[i])1670          return SDValue();1671 1672        AnyExt = false;1673        continue;1674      }1675 1676      // Each of the base elements needs to be consecutive indices into the1677      // same input vector.1678      SDValue V = M < NumElements ? V1 : V2;1679      M = M % NumElements;1680      if (!InputV) {1681        InputV = V;1682        Offset = M - (i / Scale);1683 1684        // These offset can't be handled1685        if (Offset % (NumElements / Scale))1686          return SDValue();1687      } else if (InputV != V)1688        return SDValue();1689 1690      if (M != (Offset + (i / Scale)))1691        return SDValue(); // Non-consecutive strided elements.1692    }1693 1694    // If we fail to find an input, we have a zero-shuffle which should always1695    // have already been handled.1696    if (!InputV)1697      return SDValue();1698 1699    do {1700      unsigned VilVLoHi = LoongArchISD::VILVL;1701      if (Offset >= (NumElements / 2)) {1702        VilVLoHi = LoongArchISD::VILVH;1703        Offset -= (NumElements / 2);1704      }1705 1706      MVT InputVT = MVT::getVectorVT(MVT::getIntegerVT(EltBits), NumElements);1707      SDValue Ext =1708          AnyExt ? DAG.getFreeze(InputV) : DAG.getConstant(0, DL, InputVT);1709      InputV = DAG.getBitcast(InputVT, InputV);1710      InputV = DAG.getNode(VilVLoHi, DL, InputVT, Ext, InputV);1711      Scale /= 2;1712      EltBits *= 2;1713      NumElements /= 2;1714    } while (Scale > 1);1715    return DAG.getBitcast(VT, InputV);1716  };1717 1718  // Each iteration, try extending the elements half as much, but into twice as1719  // many elements.1720  for (int NumExtElements = Bits / 64; NumExtElements < NumElements;1721       NumExtElements *= 2) {1722    if (SDValue V = Lower(NumElements / NumExtElements))1723      return V;1724  }1725  return SDValue();1726}1727 1728/// Lower VECTOR_SHUFFLE into VREPLVEI (if possible).1729///1730/// VREPLVEI performs vector broadcast based on an element specified by an1731/// integer immediate, with its mask being similar to:1732///   <x, x, x, ...>1733/// where x is any valid index.1734///1735/// When undef's appear in the mask they are treated as if they were whatever1736/// value is necessary in order to fit the above form.1737static SDValue1738lowerVECTOR_SHUFFLE_VREPLVEI(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,1739                             SDValue V1, SelectionDAG &DAG,1740                             const LoongArchSubtarget &Subtarget) {1741  int SplatIndex = -1;1742  for (const auto &M : Mask) {1743    if (M != -1) {1744      SplatIndex = M;1745      break;1746    }1747  }1748 1749  if (SplatIndex == -1)1750    return DAG.getUNDEF(VT);1751 1752  assert(SplatIndex < (int)Mask.size() && "Out of bounds mask index");1753  if (fitsRegularPattern<int>(Mask.begin(), 1, Mask.end(), SplatIndex, 0)) {1754    return DAG.getNode(LoongArchISD::VREPLVEI, DL, VT, V1,1755                       DAG.getConstant(SplatIndex, DL, Subtarget.getGRLenVT()));1756  }1757 1758  return SDValue();1759}1760 1761/// Lower VECTOR_SHUFFLE into VSHUF4I (if possible).1762///1763/// VSHUF4I splits the vector into blocks of four elements, then shuffles these1764/// elements according to a <4 x i2> constant (encoded as an integer immediate).1765///1766/// It is therefore possible to lower into VSHUF4I when the mask takes the form:1767///   <a, b, c, d, a+4, b+4, c+4, d+4, a+8, b+8, c+8, d+8, ...>1768/// When undef's appear they are treated as if they were whatever value is1769/// necessary in order to fit the above forms.1770///1771/// For example:1772///   %2 = shufflevector <8 x i16> %0, <8 x i16> undef,1773///                      <8 x i32> <i32 3, i32 2, i32 1, i32 0,1774///                                 i32 7, i32 6, i32 5, i32 4>1775/// is lowered to:1776///   (VSHUF4I_H $v0, $v1, 27)1777/// where the 27 comes from:1778///   3 + (2 << 2) + (1 << 4) + (0 << 6)1779static SDValue1780lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,1781                            SDValue V1, SDValue V2, SelectionDAG &DAG,1782                            const LoongArchSubtarget &Subtarget) {1783 1784  unsigned SubVecSize = 4;1785  if (VT == MVT::v2f64 || VT == MVT::v2i64)1786    SubVecSize = 2;1787 1788  int SubMask[4] = {-1, -1, -1, -1};1789  for (unsigned i = 0; i < SubVecSize; ++i) {1790    for (unsigned j = i; j < Mask.size(); j += SubVecSize) {1791      int M = Mask[j];1792 1793      // Convert from vector index to 4-element subvector index1794      // If an index refers to an element outside of the subvector then give up1795      if (M != -1) {1796        M -= 4 * (j / SubVecSize);1797        if (M < 0 || M >= 4)1798          return SDValue();1799      }1800 1801      // If the mask has an undef, replace it with the current index.1802      // Note that it might still be undef if the current index is also undef1803      if (SubMask[i] == -1)1804        SubMask[i] = M;1805      // Check that non-undef values are the same as in the mask. If they1806      // aren't then give up1807      else if (M != -1 && M != SubMask[i])1808        return SDValue();1809    }1810  }1811 1812  // Calculate the immediate. Replace any remaining undefs with zero1813  int Imm = 0;1814  for (int i = SubVecSize - 1; i >= 0; --i) {1815    int M = SubMask[i];1816 1817    if (M == -1)1818      M = 0;1819 1820    Imm <<= 2;1821    Imm |= M & 0x3;1822  }1823 1824  MVT GRLenVT = Subtarget.getGRLenVT();1825 1826  // Return vshuf4i.d1827  if (VT == MVT::v2f64 || VT == MVT::v2i64)1828    return DAG.getNode(LoongArchISD::VSHUF4I_D, DL, VT, V1, V2,1829                       DAG.getConstant(Imm, DL, GRLenVT));1830 1831  return DAG.getNode(LoongArchISD::VSHUF4I, DL, VT, V1,1832                     DAG.getConstant(Imm, DL, GRLenVT));1833}1834 1835/// Lower VECTOR_SHUFFLE whose result is the reversed source vector.1836///1837/// It is possible to do optimization for VECTOR_SHUFFLE performing vector1838/// reverse whose mask likes:1839///   <7, 6, 5, 4, 3, 2, 1, 0>1840///1841/// When undef's appear in the mask they are treated as if they were whatever1842/// value is necessary in order to fit the above forms.1843static SDValue1844lowerVECTOR_SHUFFLE_IsReverse(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,1845                              SDValue V1, SelectionDAG &DAG,1846                              const LoongArchSubtarget &Subtarget) {1847  // Only vectors with i8/i16 elements which cannot match other patterns1848  // directly needs to do this.1849  if (VT != MVT::v16i8 && VT != MVT::v8i16 && VT != MVT::v32i8 &&1850      VT != MVT::v16i16)1851    return SDValue();1852 1853  if (!ShuffleVectorInst::isReverseMask(Mask, Mask.size()))1854    return SDValue();1855 1856  int WidenNumElts = VT.getVectorNumElements() / 4;1857  SmallVector<int, 16> WidenMask(WidenNumElts, -1);1858  for (int i = 0; i < WidenNumElts; ++i)1859    WidenMask[i] = WidenNumElts - 1 - i;1860 1861  MVT WidenVT = MVT::getVectorVT(1862      VT.getVectorElementType() == MVT::i8 ? MVT::i32 : MVT::i64, WidenNumElts);1863  SDValue NewV1 = DAG.getBitcast(WidenVT, V1);1864  SDValue WidenRev = DAG.getVectorShuffle(WidenVT, DL, NewV1,1865                                          DAG.getUNDEF(WidenVT), WidenMask);1866 1867  return DAG.getNode(LoongArchISD::VSHUF4I, DL, VT,1868                     DAG.getBitcast(VT, WidenRev),1869                     DAG.getConstant(27, DL, Subtarget.getGRLenVT()));1870}1871 1872/// Lower VECTOR_SHUFFLE into VPACKEV (if possible).1873///1874/// VPACKEV interleaves the even elements from each vector.1875///1876/// It is possible to lower into VPACKEV when the mask consists of two of the1877/// following forms interleaved:1878///   <0, 2, 4, ...>1879///   <n, n+2, n+4, ...>1880/// where n is the number of elements in the vector.1881/// For example:1882///   <0, 0, 2, 2, 4, 4, ...>1883///   <0, n, 2, n+2, 4, n+4, ...>1884///1885/// When undef's appear in the mask they are treated as if they were whatever1886/// value is necessary in order to fit the above forms.1887static SDValue lowerVECTOR_SHUFFLE_VPACKEV(const SDLoc &DL, ArrayRef<int> Mask,1888                                           MVT VT, SDValue V1, SDValue V2,1889                                           SelectionDAG &DAG) {1890 1891  const auto &Begin = Mask.begin();1892  const auto &End = Mask.end();1893  SDValue OriV1 = V1, OriV2 = V2;1894 1895  if (fitsRegularPattern<int>(Begin, 2, End, 0, 2))1896    V1 = OriV1;1897  else if (fitsRegularPattern<int>(Begin, 2, End, Mask.size(), 2))1898    V1 = OriV2;1899  else1900    return SDValue();1901 1902  if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 2))1903    V2 = OriV1;1904  else if (fitsRegularPattern<int>(Begin + 1, 2, End, Mask.size(), 2))1905    V2 = OriV2;1906  else1907    return SDValue();1908 1909  return DAG.getNode(LoongArchISD::VPACKEV, DL, VT, V2, V1);1910}1911 1912/// Lower VECTOR_SHUFFLE into VPACKOD (if possible).1913///1914/// VPACKOD interleaves the odd elements from each vector.1915///1916/// It is possible to lower into VPACKOD when the mask consists of two of the1917/// following forms interleaved:1918///   <1, 3, 5, ...>1919///   <n+1, n+3, n+5, ...>1920/// where n is the number of elements in the vector.1921/// For example:1922///   <1, 1, 3, 3, 5, 5, ...>1923///   <1, n+1, 3, n+3, 5, n+5, ...>1924///1925/// When undef's appear in the mask they are treated as if they were whatever1926/// value is necessary in order to fit the above forms.1927static SDValue lowerVECTOR_SHUFFLE_VPACKOD(const SDLoc &DL, ArrayRef<int> Mask,1928                                           MVT VT, SDValue V1, SDValue V2,1929                                           SelectionDAG &DAG) {1930 1931  const auto &Begin = Mask.begin();1932  const auto &End = Mask.end();1933  SDValue OriV1 = V1, OriV2 = V2;1934 1935  if (fitsRegularPattern<int>(Begin, 2, End, 1, 2))1936    V1 = OriV1;1937  else if (fitsRegularPattern<int>(Begin, 2, End, Mask.size() + 1, 2))1938    V1 = OriV2;1939  else1940    return SDValue();1941 1942  if (fitsRegularPattern<int>(Begin + 1, 2, End, 1, 2))1943    V2 = OriV1;1944  else if (fitsRegularPattern<int>(Begin + 1, 2, End, Mask.size() + 1, 2))1945    V2 = OriV2;1946  else1947    return SDValue();1948 1949  return DAG.getNode(LoongArchISD::VPACKOD, DL, VT, V2, V1);1950}1951 1952/// Lower VECTOR_SHUFFLE into VILVH (if possible).1953///1954/// VILVH interleaves consecutive elements from the left (highest-indexed) half1955/// of each vector.1956///1957/// It is possible to lower into VILVH when the mask consists of two of the1958/// following forms interleaved:1959///   <x, x+1, x+2, ...>1960///   <n+x, n+x+1, n+x+2, ...>1961/// where n is the number of elements in the vector and x is half n.1962/// For example:1963///   <x, x, x+1, x+1, x+2, x+2, ...>1964///   <x, n+x, x+1, n+x+1, x+2, n+x+2, ...>1965///1966/// When undef's appear in the mask they are treated as if they were whatever1967/// value is necessary in order to fit the above forms.1968static SDValue lowerVECTOR_SHUFFLE_VILVH(const SDLoc &DL, ArrayRef<int> Mask,1969                                         MVT VT, SDValue V1, SDValue V2,1970                                         SelectionDAG &DAG) {1971 1972  const auto &Begin = Mask.begin();1973  const auto &End = Mask.end();1974  unsigned HalfSize = Mask.size() / 2;1975  SDValue OriV1 = V1, OriV2 = V2;1976 1977  if (fitsRegularPattern<int>(Begin, 2, End, HalfSize, 1))1978    V1 = OriV1;1979  else if (fitsRegularPattern<int>(Begin, 2, End, Mask.size() + HalfSize, 1))1980    V1 = OriV2;1981  else1982    return SDValue();1983 1984  if (fitsRegularPattern<int>(Begin + 1, 2, End, HalfSize, 1))1985    V2 = OriV1;1986  else if (fitsRegularPattern<int>(Begin + 1, 2, End, Mask.size() + HalfSize,1987                                   1))1988    V2 = OriV2;1989  else1990    return SDValue();1991 1992  return DAG.getNode(LoongArchISD::VILVH, DL, VT, V2, V1);1993}1994 1995/// Lower VECTOR_SHUFFLE into VILVL (if possible).1996///1997/// VILVL interleaves consecutive elements from the right (lowest-indexed) half1998/// of each vector.1999///2000/// It is possible to lower into VILVL when the mask consists of two of the2001/// following forms interleaved:2002///   <0, 1, 2, ...>2003///   <n, n+1, n+2, ...>2004/// where n is the number of elements in the vector.2005/// For example:2006///   <0, 0, 1, 1, 2, 2, ...>2007///   <0, n, 1, n+1, 2, n+2, ...>2008///2009/// When undef's appear in the mask they are treated as if they were whatever2010/// value is necessary in order to fit the above forms.2011static SDValue lowerVECTOR_SHUFFLE_VILVL(const SDLoc &DL, ArrayRef<int> Mask,2012                                         MVT VT, SDValue V1, SDValue V2,2013                                         SelectionDAG &DAG) {2014 2015  const auto &Begin = Mask.begin();2016  const auto &End = Mask.end();2017  SDValue OriV1 = V1, OriV2 = V2;2018 2019  if (fitsRegularPattern<int>(Begin, 2, End, 0, 1))2020    V1 = OriV1;2021  else if (fitsRegularPattern<int>(Begin, 2, End, Mask.size(), 1))2022    V1 = OriV2;2023  else2024    return SDValue();2025 2026  if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 1))2027    V2 = OriV1;2028  else if (fitsRegularPattern<int>(Begin + 1, 2, End, Mask.size(), 1))2029    V2 = OriV2;2030  else2031    return SDValue();2032 2033  return DAG.getNode(LoongArchISD::VILVL, DL, VT, V2, V1);2034}2035 2036/// Lower VECTOR_SHUFFLE into VPICKEV (if possible).2037///2038/// VPICKEV copies the even elements of each vector into the result vector.2039///2040/// It is possible to lower into VPICKEV when the mask consists of two of the2041/// following forms concatenated:2042///   <0, 2, 4, ...>2043///   <n, n+2, n+4, ...>2044/// where n is the number of elements in the vector.2045/// For example:2046///   <0, 2, 4, ..., 0, 2, 4, ...>2047///   <0, 2, 4, ..., n, n+2, n+4, ...>2048///2049/// When undef's appear in the mask they are treated as if they were whatever2050/// value is necessary in order to fit the above forms.2051static SDValue lowerVECTOR_SHUFFLE_VPICKEV(const SDLoc &DL, ArrayRef<int> Mask,2052                                           MVT VT, SDValue V1, SDValue V2,2053                                           SelectionDAG &DAG) {2054 2055  const auto &Begin = Mask.begin();2056  const auto &Mid = Mask.begin() + Mask.size() / 2;2057  const auto &End = Mask.end();2058  SDValue OriV1 = V1, OriV2 = V2;2059 2060  if (fitsRegularPattern<int>(Begin, 1, Mid, 0, 2))2061    V1 = OriV1;2062  else if (fitsRegularPattern<int>(Begin, 1, Mid, Mask.size(), 2))2063    V1 = OriV2;2064  else2065    return SDValue();2066 2067  if (fitsRegularPattern<int>(Mid, 1, End, 0, 2))2068    V2 = OriV1;2069  else if (fitsRegularPattern<int>(Mid, 1, End, Mask.size(), 2))2070    V2 = OriV2;2071 2072  else2073    return SDValue();2074 2075  return DAG.getNode(LoongArchISD::VPICKEV, DL, VT, V2, V1);2076}2077 2078/// Lower VECTOR_SHUFFLE into VPICKOD (if possible).2079///2080/// VPICKOD copies the odd elements of each vector into the result vector.2081///2082/// It is possible to lower into VPICKOD when the mask consists of two of the2083/// following forms concatenated:2084///   <1, 3, 5, ...>2085///   <n+1, n+3, n+5, ...>2086/// where n is the number of elements in the vector.2087/// For example:2088///   <1, 3, 5, ..., 1, 3, 5, ...>2089///   <1, 3, 5, ..., n+1, n+3, n+5, ...>2090///2091/// When undef's appear in the mask they are treated as if they were whatever2092/// value is necessary in order to fit the above forms.2093static SDValue lowerVECTOR_SHUFFLE_VPICKOD(const SDLoc &DL, ArrayRef<int> Mask,2094                                           MVT VT, SDValue V1, SDValue V2,2095                                           SelectionDAG &DAG) {2096 2097  const auto &Begin = Mask.begin();2098  const auto &Mid = Mask.begin() + Mask.size() / 2;2099  const auto &End = Mask.end();2100  SDValue OriV1 = V1, OriV2 = V2;2101 2102  if (fitsRegularPattern<int>(Begin, 1, Mid, 1, 2))2103    V1 = OriV1;2104  else if (fitsRegularPattern<int>(Begin, 1, Mid, Mask.size() + 1, 2))2105    V1 = OriV2;2106  else2107    return SDValue();2108 2109  if (fitsRegularPattern<int>(Mid, 1, End, 1, 2))2110    V2 = OriV1;2111  else if (fitsRegularPattern<int>(Mid, 1, End, Mask.size() + 1, 2))2112    V2 = OriV2;2113  else2114    return SDValue();2115 2116  return DAG.getNode(LoongArchISD::VPICKOD, DL, VT, V2, V1);2117}2118 2119/// Lower VECTOR_SHUFFLE into VSHUF.2120///2121/// This mostly consists of converting the shuffle mask into a BUILD_VECTOR and2122/// adding it as an operand to the resulting VSHUF.2123static SDValue lowerVECTOR_SHUFFLE_VSHUF(const SDLoc &DL, ArrayRef<int> Mask,2124                                         MVT VT, SDValue V1, SDValue V2,2125                                         SelectionDAG &DAG,2126                                         const LoongArchSubtarget &Subtarget) {2127 2128  SmallVector<SDValue, 16> Ops;2129  for (auto M : Mask)2130    Ops.push_back(DAG.getSignedConstant(M, DL, Subtarget.getGRLenVT()));2131 2132  EVT MaskVecTy = VT.changeVectorElementTypeToInteger();2133  SDValue MaskVec = DAG.getBuildVector(MaskVecTy, DL, Ops);2134 2135  // VECTOR_SHUFFLE concatenates the vectors in an vectorwise fashion.2136  // <0b00, 0b01> + <0b10, 0b11> -> <0b00, 0b01, 0b10, 0b11>2137  // VSHF concatenates the vectors in a bitwise fashion:2138  // <0b00, 0b01> + <0b10, 0b11> ->2139  // 0b0100       + 0b1110       -> 0b010011102140  //                                <0b10, 0b11, 0b00, 0b01>2141  // We must therefore swap the operands to get the correct result.2142  return DAG.getNode(LoongArchISD::VSHUF, DL, VT, MaskVec, V2, V1);2143}2144 2145/// Dispatching routine to lower various 128-bit LoongArch vector shuffles.2146///2147/// This routine breaks down the specific type of 128-bit shuffle and2148/// dispatches to the lowering routines accordingly.2149static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,2150                                  SDValue V1, SDValue V2, SelectionDAG &DAG,2151                                  const LoongArchSubtarget &Subtarget) {2152  assert((VT.SimpleTy == MVT::v16i8 || VT.SimpleTy == MVT::v8i16 ||2153          VT.SimpleTy == MVT::v4i32 || VT.SimpleTy == MVT::v2i64 ||2154          VT.SimpleTy == MVT::v4f32 || VT.SimpleTy == MVT::v2f64) &&2155         "Vector type is unsupported for lsx!");2156  assert(V1.getSimpleValueType() == V2.getSimpleValueType() &&2157         "Two operands have different types!");2158  assert(VT.getVectorNumElements() == Mask.size() &&2159         "Unexpected mask size for shuffle!");2160  assert(Mask.size() % 2 == 0 && "Expected even mask size.");2161 2162  APInt KnownUndef, KnownZero;2163  computeZeroableShuffleElements(Mask, V1, V2, KnownUndef, KnownZero);2164  APInt Zeroable = KnownUndef | KnownZero;2165 2166  SDValue Result;2167  // TODO: Add more comparison patterns.2168  if (V2.isUndef()) {2169    if ((Result =2170             lowerVECTOR_SHUFFLE_VREPLVEI(DL, Mask, VT, V1, DAG, Subtarget)))2171      return Result;2172    if ((Result =2173             lowerVECTOR_SHUFFLE_VSHUF4I(DL, Mask, VT, V1, V2, DAG, Subtarget)))2174      return Result;2175    if ((Result =2176             lowerVECTOR_SHUFFLE_IsReverse(DL, Mask, VT, V1, DAG, Subtarget)))2177      return Result;2178 2179    // TODO: This comment may be enabled in the future to better match the2180    // pattern for instruction selection.2181    /* V2 = V1; */2182  }2183 2184  // It is recommended not to change the pattern comparison order for better2185  // performance.2186  if ((Result = lowerVECTOR_SHUFFLE_VPACKEV(DL, Mask, VT, V1, V2, DAG)))2187    return Result;2188  if ((Result = lowerVECTOR_SHUFFLE_VPACKOD(DL, Mask, VT, V1, V2, DAG)))2189    return Result;2190  if ((Result = lowerVECTOR_SHUFFLE_VILVH(DL, Mask, VT, V1, V2, DAG)))2191    return Result;2192  if ((Result = lowerVECTOR_SHUFFLE_VILVL(DL, Mask, VT, V1, V2, DAG)))2193    return Result;2194  if ((Result = lowerVECTOR_SHUFFLE_VPICKEV(DL, Mask, VT, V1, V2, DAG)))2195    return Result;2196  if ((Result = lowerVECTOR_SHUFFLE_VPICKOD(DL, Mask, VT, V1, V2, DAG)))2197    return Result;2198  if ((VT.SimpleTy == MVT::v2i64 || VT.SimpleTy == MVT::v2f64) &&2199      (Result =2200           lowerVECTOR_SHUFFLE_VSHUF4I(DL, Mask, VT, V1, V2, DAG, Subtarget)))2201    return Result;2202  if ((Result = lowerVECTOR_SHUFFLEAsZeroOrAnyExtend(DL, Mask, VT, V1, V2, DAG,2203                                                     Zeroable)))2204    return Result;2205  if ((Result = lowerVECTOR_SHUFFLEAsShift(DL, Mask, VT, V1, V2, DAG, Subtarget,2206                                           Zeroable)))2207    return Result;2208  if ((Result = lowerVECTOR_SHUFFLEAsByteRotate(DL, Mask, VT, V1, V2, DAG,2209                                                Subtarget)))2210    return Result;2211  if (SDValue NewShuffle = widenShuffleMask(DL, Mask, VT, V1, V2, DAG))2212    return NewShuffle;2213  if ((Result =2214           lowerVECTOR_SHUFFLE_VSHUF(DL, Mask, VT, V1, V2, DAG, Subtarget)))2215    return Result;2216  return SDValue();2217}2218 2219/// Lower VECTOR_SHUFFLE into XVREPLVEI (if possible).2220///2221/// It is a XVREPLVEI when the mask is:2222///   <x, x, x, ..., x+n, x+n, x+n, ...>2223/// where the number of x is equal to n and n is half the length of vector.2224///2225/// When undef's appear in the mask they are treated as if they were whatever2226/// value is necessary in order to fit the above form.2227static SDValue2228lowerVECTOR_SHUFFLE_XVREPLVEI(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,2229                              SDValue V1, SelectionDAG &DAG,2230                              const LoongArchSubtarget &Subtarget) {2231  int SplatIndex = -1;2232  for (const auto &M : Mask) {2233    if (M != -1) {2234      SplatIndex = M;2235      break;2236    }2237  }2238 2239  if (SplatIndex == -1)2240    return DAG.getUNDEF(VT);2241 2242  const auto &Begin = Mask.begin();2243  const auto &End = Mask.end();2244  int HalfSize = Mask.size() / 2;2245 2246  if (SplatIndex >= HalfSize)2247    return SDValue();2248 2249  assert(SplatIndex < (int)Mask.size() && "Out of bounds mask index");2250  if (fitsRegularPattern<int>(Begin, 1, End - HalfSize, SplatIndex, 0) &&2251      fitsRegularPattern<int>(Begin + HalfSize, 1, End, SplatIndex + HalfSize,2252                              0)) {2253    return DAG.getNode(LoongArchISD::VREPLVEI, DL, VT, V1,2254                       DAG.getConstant(SplatIndex, DL, Subtarget.getGRLenVT()));2255  }2256 2257  return SDValue();2258}2259 2260/// Lower VECTOR_SHUFFLE into XVSHUF4I (if possible).2261static SDValue2262lowerVECTOR_SHUFFLE_XVSHUF4I(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,2263                             SDValue V1, SDValue V2, SelectionDAG &DAG,2264                             const LoongArchSubtarget &Subtarget) {2265  // When the size is less than or equal to 4, lower cost instructions may be2266  // used.2267  if (Mask.size() <= 4)2268    return SDValue();2269  return lowerVECTOR_SHUFFLE_VSHUF4I(DL, Mask, VT, V1, V2, DAG, Subtarget);2270}2271 2272/// Lower VECTOR_SHUFFLE into XVPERMI (if possible).2273static SDValue2274lowerVECTOR_SHUFFLE_XVPERMI(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,2275                            SDValue V1, SelectionDAG &DAG,2276                            const LoongArchSubtarget &Subtarget) {2277  // Only consider XVPERMI_D.2278  if (Mask.size() != 4 || (VT != MVT::v4i64 && VT != MVT::v4f64))2279    return SDValue();2280 2281  unsigned MaskImm = 0;2282  for (unsigned i = 0; i < Mask.size(); ++i) {2283    if (Mask[i] == -1)2284      continue;2285    MaskImm |= Mask[i] << (i * 2);2286  }2287 2288  return DAG.getNode(LoongArchISD::XVPERMI, DL, VT, V1,2289                     DAG.getConstant(MaskImm, DL, Subtarget.getGRLenVT()));2290}2291 2292/// Lower VECTOR_SHUFFLE into XVPERM (if possible).2293static SDValue lowerVECTOR_SHUFFLE_XVPERM(const SDLoc &DL, ArrayRef<int> Mask,2294                                          MVT VT, SDValue V1, SelectionDAG &DAG,2295                                          const LoongArchSubtarget &Subtarget) {2296  // LoongArch LASX only have XVPERM_W.2297  if (Mask.size() != 8 || (VT != MVT::v8i32 && VT != MVT::v8f32))2298    return SDValue();2299 2300  unsigned NumElts = VT.getVectorNumElements();2301  unsigned HalfSize = NumElts / 2;2302  bool FrontLo = true, FrontHi = true;2303  bool BackLo = true, BackHi = true;2304 2305  auto inRange = [](int val, int low, int high) {2306    return (val == -1) || (val >= low && val < high);2307  };2308 2309  for (unsigned i = 0; i < HalfSize; ++i) {2310    int Fronti = Mask[i];2311    int Backi = Mask[i + HalfSize];2312 2313    FrontLo &= inRange(Fronti, 0, HalfSize);2314    FrontHi &= inRange(Fronti, HalfSize, NumElts);2315    BackLo &= inRange(Backi, 0, HalfSize);2316    BackHi &= inRange(Backi, HalfSize, NumElts);2317  }2318 2319  // If both the lower and upper 128-bit parts access only one half of the2320  // vector (either lower or upper), avoid using xvperm.w. The latency of2321  // xvperm.w(3) is higher than using xvshuf(1) and xvori(1).2322  if ((FrontLo || FrontHi) && (BackLo || BackHi))2323    return SDValue();2324 2325  SmallVector<SDValue, 8> Masks;2326  MVT GRLenVT = Subtarget.getGRLenVT();2327  for (unsigned i = 0; i < NumElts; ++i)2328    Masks.push_back(Mask[i] == -1 ? DAG.getUNDEF(GRLenVT)2329                                  : DAG.getConstant(Mask[i], DL, GRLenVT));2330  SDValue MaskVec = DAG.getBuildVector(MVT::v8i32, DL, Masks);2331 2332  return DAG.getNode(LoongArchISD::XVPERM, DL, VT, V1, MaskVec);2333}2334 2335/// Lower VECTOR_SHUFFLE into XVPACKEV (if possible).2336static SDValue lowerVECTOR_SHUFFLE_XVPACKEV(const SDLoc &DL, ArrayRef<int> Mask,2337                                            MVT VT, SDValue V1, SDValue V2,2338                                            SelectionDAG &DAG) {2339  return lowerVECTOR_SHUFFLE_VPACKEV(DL, Mask, VT, V1, V2, DAG);2340}2341 2342/// Lower VECTOR_SHUFFLE into XVPACKOD (if possible).2343static SDValue lowerVECTOR_SHUFFLE_XVPACKOD(const SDLoc &DL, ArrayRef<int> Mask,2344                                            MVT VT, SDValue V1, SDValue V2,2345                                            SelectionDAG &DAG) {2346  return lowerVECTOR_SHUFFLE_VPACKOD(DL, Mask, VT, V1, V2, DAG);2347}2348 2349/// Lower VECTOR_SHUFFLE into XVILVH (if possible).2350static SDValue lowerVECTOR_SHUFFLE_XVILVH(const SDLoc &DL, ArrayRef<int> Mask,2351                                          MVT VT, SDValue V1, SDValue V2,2352                                          SelectionDAG &DAG) {2353 2354  const auto &Begin = Mask.begin();2355  const auto &End = Mask.end();2356  unsigned HalfSize = Mask.size() / 2;2357  unsigned LeftSize = HalfSize / 2;2358  SDValue OriV1 = V1, OriV2 = V2;2359 2360  if (fitsRegularPattern<int>(Begin, 2, End - HalfSize, HalfSize - LeftSize,2361                              1) &&2362      fitsRegularPattern<int>(Begin + HalfSize, 2, End, HalfSize + LeftSize, 1))2363    V1 = OriV1;2364  else if (fitsRegularPattern<int>(Begin, 2, End - HalfSize,2365                                   Mask.size() + HalfSize - LeftSize, 1) &&2366           fitsRegularPattern<int>(Begin + HalfSize, 2, End,2367                                   Mask.size() + HalfSize + LeftSize, 1))2368    V1 = OriV2;2369  else2370    return SDValue();2371 2372  if (fitsRegularPattern<int>(Begin + 1, 2, End - HalfSize, HalfSize - LeftSize,2373                              1) &&2374      fitsRegularPattern<int>(Begin + 1 + HalfSize, 2, End, HalfSize + LeftSize,2375                              1))2376    V2 = OriV1;2377  else if (fitsRegularPattern<int>(Begin + 1, 2, End - HalfSize,2378                                   Mask.size() + HalfSize - LeftSize, 1) &&2379           fitsRegularPattern<int>(Begin + 1 + HalfSize, 2, End,2380                                   Mask.size() + HalfSize + LeftSize, 1))2381    V2 = OriV2;2382  else2383    return SDValue();2384 2385  return DAG.getNode(LoongArchISD::VILVH, DL, VT, V2, V1);2386}2387 2388/// Lower VECTOR_SHUFFLE into XVILVL (if possible).2389static SDValue lowerVECTOR_SHUFFLE_XVILVL(const SDLoc &DL, ArrayRef<int> Mask,2390                                          MVT VT, SDValue V1, SDValue V2,2391                                          SelectionDAG &DAG) {2392 2393  const auto &Begin = Mask.begin();2394  const auto &End = Mask.end();2395  unsigned HalfSize = Mask.size() / 2;2396  SDValue OriV1 = V1, OriV2 = V2;2397 2398  if (fitsRegularPattern<int>(Begin, 2, End - HalfSize, 0, 1) &&2399      fitsRegularPattern<int>(Begin + HalfSize, 2, End, HalfSize, 1))2400    V1 = OriV1;2401  else if (fitsRegularPattern<int>(Begin, 2, End - HalfSize, Mask.size(), 1) &&2402           fitsRegularPattern<int>(Begin + HalfSize, 2, End,2403                                   Mask.size() + HalfSize, 1))2404    V1 = OriV2;2405  else2406    return SDValue();2407 2408  if (fitsRegularPattern<int>(Begin + 1, 2, End - HalfSize, 0, 1) &&2409      fitsRegularPattern<int>(Begin + 1 + HalfSize, 2, End, HalfSize, 1))2410    V2 = OriV1;2411  else if (fitsRegularPattern<int>(Begin + 1, 2, End - HalfSize, Mask.size(),2412                                   1) &&2413           fitsRegularPattern<int>(Begin + 1 + HalfSize, 2, End,2414                                   Mask.size() + HalfSize, 1))2415    V2 = OriV2;2416  else2417    return SDValue();2418 2419  return DAG.getNode(LoongArchISD::VILVL, DL, VT, V2, V1);2420}2421 2422/// Lower VECTOR_SHUFFLE into XVPICKEV (if possible).2423static SDValue lowerVECTOR_SHUFFLE_XVPICKEV(const SDLoc &DL, ArrayRef<int> Mask,2424                                            MVT VT, SDValue V1, SDValue V2,2425                                            SelectionDAG &DAG) {2426 2427  const auto &Begin = Mask.begin();2428  const auto &LeftMid = Mask.begin() + Mask.size() / 4;2429  const auto &Mid = Mask.begin() + Mask.size() / 2;2430  const auto &RightMid = Mask.end() - Mask.size() / 4;2431  const auto &End = Mask.end();2432  unsigned HalfSize = Mask.size() / 2;2433  SDValue OriV1 = V1, OriV2 = V2;2434 2435  if (fitsRegularPattern<int>(Begin, 1, LeftMid, 0, 2) &&2436      fitsRegularPattern<int>(Mid, 1, RightMid, HalfSize, 2))2437    V1 = OriV1;2438  else if (fitsRegularPattern<int>(Begin, 1, LeftMid, Mask.size(), 2) &&2439           fitsRegularPattern<int>(Mid, 1, RightMid, Mask.size() + HalfSize, 2))2440    V1 = OriV2;2441  else2442    return SDValue();2443 2444  if (fitsRegularPattern<int>(LeftMid, 1, Mid, 0, 2) &&2445      fitsRegularPattern<int>(RightMid, 1, End, HalfSize, 2))2446    V2 = OriV1;2447  else if (fitsRegularPattern<int>(LeftMid, 1, Mid, Mask.size(), 2) &&2448           fitsRegularPattern<int>(RightMid, 1, End, Mask.size() + HalfSize, 2))2449    V2 = OriV2;2450 2451  else2452    return SDValue();2453 2454  return DAG.getNode(LoongArchISD::VPICKEV, DL, VT, V2, V1);2455}2456 2457/// Lower VECTOR_SHUFFLE into XVPICKOD (if possible).2458static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(const SDLoc &DL, ArrayRef<int> Mask,2459                                            MVT VT, SDValue V1, SDValue V2,2460                                            SelectionDAG &DAG) {2461 2462  const auto &Begin = Mask.begin();2463  const auto &LeftMid = Mask.begin() + Mask.size() / 4;2464  const auto &Mid = Mask.begin() + Mask.size() / 2;2465  const auto &RightMid = Mask.end() - Mask.size() / 4;2466  const auto &End = Mask.end();2467  unsigned HalfSize = Mask.size() / 2;2468  SDValue OriV1 = V1, OriV2 = V2;2469 2470  if (fitsRegularPattern<int>(Begin, 1, LeftMid, 1, 2) &&2471      fitsRegularPattern<int>(Mid, 1, RightMid, HalfSize + 1, 2))2472    V1 = OriV1;2473  else if (fitsRegularPattern<int>(Begin, 1, LeftMid, Mask.size() + 1, 2) &&2474           fitsRegularPattern<int>(Mid, 1, RightMid, Mask.size() + HalfSize + 1,2475                                   2))2476    V1 = OriV2;2477  else2478    return SDValue();2479 2480  if (fitsRegularPattern<int>(LeftMid, 1, Mid, 1, 2) &&2481      fitsRegularPattern<int>(RightMid, 1, End, HalfSize + 1, 2))2482    V2 = OriV1;2483  else if (fitsRegularPattern<int>(LeftMid, 1, Mid, Mask.size() + 1, 2) &&2484           fitsRegularPattern<int>(RightMid, 1, End, Mask.size() + HalfSize + 1,2485                                   2))2486    V2 = OriV2;2487  else2488    return SDValue();2489 2490  return DAG.getNode(LoongArchISD::VPICKOD, DL, VT, V2, V1);2491}2492 2493/// Lower VECTOR_SHUFFLE into XVINSVE0 (if possible).2494static SDValue2495lowerVECTOR_SHUFFLE_XVINSVE0(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,2496                             SDValue V1, SDValue V2, SelectionDAG &DAG,2497                             const LoongArchSubtarget &Subtarget) {2498  // LoongArch LASX only supports xvinsve0.{w/d}.2499  if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&2500      VT != MVT::v4f64)2501    return SDValue();2502 2503  MVT GRLenVT = Subtarget.getGRLenVT();2504  int MaskSize = Mask.size();2505  assert(MaskSize == (int)VT.getVectorNumElements() && "Unexpected mask size");2506 2507  // Check if exactly one element of the Mask is replaced by 'Replaced', while2508  // all other elements are either 'Base + i' or undef (-1). On success, return2509  // the index of the replaced element. Otherwise, just return -1.2510  auto checkReplaceOne = [&](int Base, int Replaced) -> int {2511    int Idx = -1;2512    for (int i = 0; i < MaskSize; ++i) {2513      if (Mask[i] == Base + i || Mask[i] == -1)2514        continue;2515      if (Mask[i] != Replaced)2516        return -1;2517      if (Idx == -1)2518        Idx = i;2519      else2520        return -1;2521    }2522    return Idx;2523  };2524 2525  // Case 1: the lowest element of V2 replaces one element in V1.2526  int Idx = checkReplaceOne(0, MaskSize);2527  if (Idx != -1)2528    return DAG.getNode(LoongArchISD::XVINSVE0, DL, VT, V1, V2,2529                       DAG.getConstant(Idx, DL, GRLenVT));2530 2531  // Case 2: the lowest element of V1 replaces one element in V2.2532  Idx = checkReplaceOne(MaskSize, 0);2533  if (Idx != -1)2534    return DAG.getNode(LoongArchISD::XVINSVE0, DL, VT, V2, V1,2535                       DAG.getConstant(Idx, DL, GRLenVT));2536 2537  return SDValue();2538}2539 2540/// Lower VECTOR_SHUFFLE into XVSHUF (if possible).2541static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, ArrayRef<int> Mask,2542                                          MVT VT, SDValue V1, SDValue V2,2543                                          SelectionDAG &DAG) {2544 2545  int MaskSize = Mask.size();2546  int HalfSize = Mask.size() / 2;2547  const auto &Begin = Mask.begin();2548  const auto &Mid = Mask.begin() + HalfSize;2549  const auto &End = Mask.end();2550 2551  // VECTOR_SHUFFLE concatenates the vectors:2552  //  <0, 1, 2, 3, 4, 5, 6, 7> + <8, 9, 10, 11, 12, 13, 14, 15>2553  //  shuffling ->2554  //  <0, 1, 2, 3, 8, 9, 10, 11> <4, 5, 6, 7, 12, 13, 14, 15>2555  //2556  // XVSHUF concatenates the vectors:2557  //  <a0, a1, a2, a3, b0, b1, b2, b3> + <a4, a5, a6, a7, b4, b5, b6, b7>2558  //  shuffling ->2559  //  <a0, a1, a2, a3, a4, a5, a6, a7> + <b0, b1, b2, b3, b4, b5, b6, b7>2560  SmallVector<SDValue, 8> MaskAlloc;2561  for (auto it = Begin; it < Mid; it++) {2562    if (*it < 0) // UNDEF2563      MaskAlloc.push_back(DAG.getTargetConstant(0, DL, MVT::i64));2564    else if ((*it >= 0 && *it < HalfSize) ||2565             (*it >= MaskSize && *it < MaskSize + HalfSize)) {2566      int M = *it < HalfSize ? *it : *it - HalfSize;2567      MaskAlloc.push_back(DAG.getTargetConstant(M, DL, MVT::i64));2568    } else2569      return SDValue();2570  }2571  assert((int)MaskAlloc.size() == HalfSize && "xvshuf convert failed!");2572 2573  for (auto it = Mid; it < End; it++) {2574    if (*it < 0) // UNDEF2575      MaskAlloc.push_back(DAG.getTargetConstant(0, DL, MVT::i64));2576    else if ((*it >= HalfSize && *it < MaskSize) ||2577             (*it >= MaskSize + HalfSize && *it < MaskSize * 2)) {2578      int M = *it < MaskSize ? *it - HalfSize : *it - MaskSize;2579      MaskAlloc.push_back(DAG.getTargetConstant(M, DL, MVT::i64));2580    } else2581      return SDValue();2582  }2583  assert((int)MaskAlloc.size() == MaskSize && "xvshuf convert failed!");2584 2585  EVT MaskVecTy = VT.changeVectorElementTypeToInteger();2586  SDValue MaskVec = DAG.getBuildVector(MaskVecTy, DL, MaskAlloc);2587  return DAG.getNode(LoongArchISD::VSHUF, DL, VT, MaskVec, V2, V1);2588}2589 2590/// Shuffle vectors by lane to generate more optimized instructions.2591/// 256-bit shuffles are always considered as 2-lane 128-bit shuffles.2592///2593/// Therefore, except for the following four cases, other cases are regarded2594/// as cross-lane shuffles, where optimization is relatively limited.2595///2596/// - Shuffle high, low lanes of two inputs vector2597///   <0, 1, 2, 3> + <4, 5, 6, 7> --- <0, 5, 3, 6>2598/// - Shuffle low, high lanes of two inputs vector2599///   <0, 1, 2, 3> + <4, 5, 6, 7> --- <3, 6, 0, 5>2600/// - Shuffle low, low lanes of two inputs vector2601///   <0, 1, 2, 3> + <4, 5, 6, 7> --- <3, 6, 3, 6>2602/// - Shuffle high, high lanes of two inputs vector2603///   <0, 1, 2, 3> + <4, 5, 6, 7> --- <0, 5, 0, 5>2604///2605/// The first case is the closest to LoongArch instructions and the other2606/// cases need to be converted to it for processing.2607///2608/// This function will return true for the last three cases above and will2609/// modify V1, V2 and Mask. Otherwise, return false for the first case and2610/// cross-lane shuffle cases.2611static bool canonicalizeShuffleVectorByLane(2612    const SDLoc &DL, MutableArrayRef<int> Mask, MVT VT, SDValue &V1,2613    SDValue &V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget) {2614 2615  enum HalfMaskType { HighLaneTy, LowLaneTy, None };2616 2617  int MaskSize = Mask.size();2618  int HalfSize = Mask.size() / 2;2619  MVT GRLenVT = Subtarget.getGRLenVT();2620 2621  HalfMaskType preMask = None, postMask = None;2622 2623  if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](int M) {2624        return M < 0 || (M >= 0 && M < HalfSize) ||2625               (M >= MaskSize && M < MaskSize + HalfSize);2626      }))2627    preMask = HighLaneTy;2628  else if (std::all_of(Mask.begin(), Mask.begin() + HalfSize, [&](int M) {2629             return M < 0 || (M >= HalfSize && M < MaskSize) ||2630                    (M >= MaskSize + HalfSize && M < MaskSize * 2);2631           }))2632    preMask = LowLaneTy;2633 2634  if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](int M) {2635        return M < 0 || (M >= HalfSize && M < MaskSize) ||2636               (M >= MaskSize + HalfSize && M < MaskSize * 2);2637      }))2638    postMask = LowLaneTy;2639  else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](int M) {2640             return M < 0 || (M >= 0 && M < HalfSize) ||2641                    (M >= MaskSize && M < MaskSize + HalfSize);2642           }))2643    postMask = HighLaneTy;2644 2645  // The pre-half of mask is high lane type, and the post-half of mask2646  // is low lane type, which is closest to the LoongArch instructions.2647  //2648  // Note: In the LoongArch architecture, the high lane of mask corresponds2649  // to the lower 128-bit of vector register, and the low lane of mask2650  // corresponds the higher 128-bit of vector register.2651  if (preMask == HighLaneTy && postMask == LowLaneTy) {2652    return false;2653  }2654  if (preMask == LowLaneTy && postMask == HighLaneTy) {2655    V1 = DAG.getBitcast(MVT::v4i64, V1);2656    V1 = DAG.getNode(LoongArchISD::XVPERMI, DL, MVT::v4i64, V1,2657                     DAG.getConstant(0b01001110, DL, GRLenVT));2658    V1 = DAG.getBitcast(VT, V1);2659 2660    if (!V2.isUndef()) {2661      V2 = DAG.getBitcast(MVT::v4i64, V2);2662      V2 = DAG.getNode(LoongArchISD::XVPERMI, DL, MVT::v4i64, V2,2663                       DAG.getConstant(0b01001110, DL, GRLenVT));2664      V2 = DAG.getBitcast(VT, V2);2665    }2666 2667    for (auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {2668      *it = *it < 0 ? *it : *it - HalfSize;2669    }2670    for (auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {2671      *it = *it < 0 ? *it : *it + HalfSize;2672    }2673  } else if (preMask == LowLaneTy && postMask == LowLaneTy) {2674    V1 = DAG.getBitcast(MVT::v4i64, V1);2675    V1 = DAG.getNode(LoongArchISD::XVPERMI, DL, MVT::v4i64, V1,2676                     DAG.getConstant(0b11101110, DL, GRLenVT));2677    V1 = DAG.getBitcast(VT, V1);2678 2679    if (!V2.isUndef()) {2680      V2 = DAG.getBitcast(MVT::v4i64, V2);2681      V2 = DAG.getNode(LoongArchISD::XVPERMI, DL, MVT::v4i64, V2,2682                       DAG.getConstant(0b11101110, DL, GRLenVT));2683      V2 = DAG.getBitcast(VT, V2);2684    }2685 2686    for (auto it = Mask.begin(); it < Mask.begin() + HalfSize; it++) {2687      *it = *it < 0 ? *it : *it - HalfSize;2688    }2689  } else if (preMask == HighLaneTy && postMask == HighLaneTy) {2690    V1 = DAG.getBitcast(MVT::v4i64, V1);2691    V1 = DAG.getNode(LoongArchISD::XVPERMI, DL, MVT::v4i64, V1,2692                     DAG.getConstant(0b01000100, DL, GRLenVT));2693    V1 = DAG.getBitcast(VT, V1);2694 2695    if (!V2.isUndef()) {2696      V2 = DAG.getBitcast(MVT::v4i64, V2);2697      V2 = DAG.getNode(LoongArchISD::XVPERMI, DL, MVT::v4i64, V2,2698                       DAG.getConstant(0b01000100, DL, GRLenVT));2699      V2 = DAG.getBitcast(VT, V2);2700    }2701 2702    for (auto it = Mask.begin() + HalfSize; it < Mask.end(); it++) {2703      *it = *it < 0 ? *it : *it + HalfSize;2704    }2705  } else { // cross-lane2706    return false;2707  }2708 2709  return true;2710}2711 2712/// Lower VECTOR_SHUFFLE as lane permute and then shuffle (if possible).2713/// Only for 256-bit vector.2714///2715/// For example:2716/// %2 = shufflevector <4 x i64> %0, <4 x i64> posion,2717///                    <4 x i64> <i32 0, i32 3, i32 2, i32 0>2718/// is lowerded to:2719///     (XVPERMI $xr2, $xr0, 78)2720///     (XVSHUF  $xr1, $xr2, $xr0)2721///     (XVORI   $xr0, $xr1, 0)2722static SDValue lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(const SDLoc &DL,2723                                                          ArrayRef<int> Mask,2724                                                          MVT VT, SDValue V1,2725                                                          SDValue V2,2726                                                          SelectionDAG &DAG) {2727  assert(VT.is256BitVector() && "Only for 256-bit vector shuffles!");2728  int Size = Mask.size();2729  int LaneSize = Size / 2;2730 2731  bool LaneCrossing[2] = {false, false};2732  for (int i = 0; i < Size; ++i)2733    if (Mask[i] >= 0 && ((Mask[i] % Size) / LaneSize) != (i / LaneSize))2734      LaneCrossing[(Mask[i] % Size) / LaneSize] = true;2735 2736  // Ensure that all lanes ared involved.2737  if (!LaneCrossing[0] && !LaneCrossing[1])2738    return SDValue();2739 2740  SmallVector<int> InLaneMask;2741  InLaneMask.assign(Mask.begin(), Mask.end());2742  for (int i = 0; i < Size; ++i) {2743    int &M = InLaneMask[i];2744    if (M < 0)2745      continue;2746    if (((M % Size) / LaneSize) != (i / LaneSize))2747      M = (M % LaneSize) + ((i / LaneSize) * LaneSize) + Size;2748  }2749 2750  SDValue Flipped = DAG.getBitcast(MVT::v4i64, V1);2751  Flipped = DAG.getVectorShuffle(MVT::v4i64, DL, Flipped,2752                                 DAG.getUNDEF(MVT::v4i64), {2, 3, 0, 1});2753  Flipped = DAG.getBitcast(VT, Flipped);2754  return DAG.getVectorShuffle(VT, DL, V1, Flipped, InLaneMask);2755}2756 2757/// Dispatching routine to lower various 256-bit LoongArch vector shuffles.2758///2759/// This routine breaks down the specific type of 256-bit shuffle and2760/// dispatches to the lowering routines accordingly.2761static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,2762                                  SDValue V1, SDValue V2, SelectionDAG &DAG,2763                                  const LoongArchSubtarget &Subtarget) {2764  assert((VT.SimpleTy == MVT::v32i8 || VT.SimpleTy == MVT::v16i16 ||2765          VT.SimpleTy == MVT::v8i32 || VT.SimpleTy == MVT::v4i64 ||2766          VT.SimpleTy == MVT::v8f32 || VT.SimpleTy == MVT::v4f64) &&2767         "Vector type is unsupported for lasx!");2768  assert(V1.getSimpleValueType() == V2.getSimpleValueType() &&2769         "Two operands have different types!");2770  assert(VT.getVectorNumElements() == Mask.size() &&2771         "Unexpected mask size for shuffle!");2772  assert(Mask.size() % 2 == 0 && "Expected even mask size.");2773  assert(Mask.size() >= 4 && "Mask size is less than 4.");2774 2775  APInt KnownUndef, KnownZero;2776  computeZeroableShuffleElements(Mask, V1, V2, KnownUndef, KnownZero);2777  APInt Zeroable = KnownUndef | KnownZero;2778 2779  SDValue Result;2780  // TODO: Add more comparison patterns.2781  if (V2.isUndef()) {2782    if ((Result =2783             lowerVECTOR_SHUFFLE_XVREPLVEI(DL, Mask, VT, V1, DAG, Subtarget)))2784      return Result;2785    if ((Result = lowerVECTOR_SHUFFLE_XVSHUF4I(DL, Mask, VT, V1, V2, DAG,2786                                               Subtarget)))2787      return Result;2788    // Try to widen vectors to gain more optimization opportunities.2789    if (SDValue NewShuffle = widenShuffleMask(DL, Mask, VT, V1, V2, DAG))2790      return NewShuffle;2791    if ((Result =2792             lowerVECTOR_SHUFFLE_XVPERMI(DL, Mask, VT, V1, DAG, Subtarget)))2793      return Result;2794    if ((Result = lowerVECTOR_SHUFFLE_XVPERM(DL, Mask, VT, V1, DAG, Subtarget)))2795      return Result;2796    if ((Result =2797             lowerVECTOR_SHUFFLE_IsReverse(DL, Mask, VT, V1, DAG, Subtarget)))2798      return Result;2799 2800    // TODO: This comment may be enabled in the future to better match the2801    // pattern for instruction selection.2802    /* V2 = V1; */2803  }2804 2805  // It is recommended not to change the pattern comparison order for better2806  // performance.2807  if ((Result = lowerVECTOR_SHUFFLE_XVPACKEV(DL, Mask, VT, V1, V2, DAG)))2808    return Result;2809  if ((Result = lowerVECTOR_SHUFFLE_XVPACKOD(DL, Mask, VT, V1, V2, DAG)))2810    return Result;2811  if ((Result = lowerVECTOR_SHUFFLE_XVILVH(DL, Mask, VT, V1, V2, DAG)))2812    return Result;2813  if ((Result = lowerVECTOR_SHUFFLE_XVILVL(DL, Mask, VT, V1, V2, DAG)))2814    return Result;2815  if ((Result = lowerVECTOR_SHUFFLE_XVPICKEV(DL, Mask, VT, V1, V2, DAG)))2816    return Result;2817  if ((Result = lowerVECTOR_SHUFFLE_XVPICKOD(DL, Mask, VT, V1, V2, DAG)))2818    return Result;2819  if ((Result = lowerVECTOR_SHUFFLEAsShift(DL, Mask, VT, V1, V2, DAG, Subtarget,2820                                           Zeroable)))2821    return Result;2822  if ((Result =2823           lowerVECTOR_SHUFFLE_XVINSVE0(DL, Mask, VT, V1, V2, DAG, Subtarget)))2824    return Result;2825  if ((Result = lowerVECTOR_SHUFFLEAsByteRotate(DL, Mask, VT, V1, V2, DAG,2826                                                Subtarget)))2827    return Result;2828 2829  // canonicalize non cross-lane shuffle vector2830  SmallVector<int> NewMask(Mask);2831  if (canonicalizeShuffleVectorByLane(DL, NewMask, VT, V1, V2, DAG, Subtarget))2832    return lower256BitShuffle(DL, NewMask, VT, V1, V2, DAG, Subtarget);2833 2834  // FIXME: Handling the remaining cases earlier can degrade performance2835  // in some situations. Further analysis is required to enable more2836  // effective optimizations.2837  if (V2.isUndef()) {2838    if ((Result = lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(DL, NewMask, VT,2839                                                             V1, V2, DAG)))2840      return Result;2841  }2842 2843  if (SDValue NewShuffle = widenShuffleMask(DL, NewMask, VT, V1, V2, DAG))2844    return NewShuffle;2845  if ((Result = lowerVECTOR_SHUFFLE_XVSHUF(DL, NewMask, VT, V1, V2, DAG)))2846    return Result;2847 2848  return SDValue();2849}2850 2851SDValue LoongArchTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,2852                                                     SelectionDAG &DAG) const {2853  ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(Op);2854  ArrayRef<int> OrigMask = SVOp->getMask();2855  SDValue V1 = Op.getOperand(0);2856  SDValue V2 = Op.getOperand(1);2857  MVT VT = Op.getSimpleValueType();2858  int NumElements = VT.getVectorNumElements();2859  SDLoc DL(Op);2860 2861  bool V1IsUndef = V1.isUndef();2862  bool V2IsUndef = V2.isUndef();2863  if (V1IsUndef && V2IsUndef)2864    return DAG.getUNDEF(VT);2865 2866  // When we create a shuffle node we put the UNDEF node to second operand,2867  // but in some cases the first operand may be transformed to UNDEF.2868  // In this case we should just commute the node.2869  if (V1IsUndef)2870    return DAG.getCommutedVectorShuffle(*SVOp);2871 2872  // Check for non-undef masks pointing at an undef vector and make the masks2873  // undef as well. This makes it easier to match the shuffle based solely on2874  // the mask.2875  if (V2IsUndef &&2876      any_of(OrigMask, [NumElements](int M) { return M >= NumElements; })) {2877    SmallVector<int, 8> NewMask(OrigMask);2878    for (int &M : NewMask)2879      if (M >= NumElements)2880        M = -1;2881    return DAG.getVectorShuffle(VT, DL, V1, V2, NewMask);2882  }2883 2884  // Check for illegal shuffle mask element index values.2885  int MaskUpperLimit = OrigMask.size() * (V2IsUndef ? 1 : 2);2886  (void)MaskUpperLimit;2887  assert(llvm::all_of(OrigMask,2888                      [&](int M) { return -1 <= M && M < MaskUpperLimit; }) &&2889         "Out of bounds shuffle index");2890 2891  // For each vector width, delegate to a specialized lowering routine.2892  if (VT.is128BitVector())2893    return lower128BitShuffle(DL, OrigMask, VT, V1, V2, DAG, Subtarget);2894 2895  if (VT.is256BitVector())2896    return lower256BitShuffle(DL, OrigMask, VT, V1, V2, DAG, Subtarget);2897 2898  return SDValue();2899}2900 2901SDValue LoongArchTargetLowering::lowerFP_TO_FP16(SDValue Op,2902                                                 SelectionDAG &DAG) const {2903  // Custom lower to ensure the libcall return is passed in an FPR on hard2904  // float ABIs.2905  SDLoc DL(Op);2906  MakeLibCallOptions CallOptions;2907  SDValue Op0 = Op.getOperand(0);2908  SDValue Chain = SDValue();2909  RTLIB::Libcall LC = RTLIB::getFPROUND(Op0.getValueType(), MVT::f16);2910  SDValue Res;2911  std::tie(Res, Chain) =2912      makeLibCall(DAG, LC, MVT::f32, Op0, CallOptions, DL, Chain);2913  if (Subtarget.is64Bit())2914    return DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Res);2915  return DAG.getBitcast(MVT::i32, Res);2916}2917 2918SDValue LoongArchTargetLowering::lowerFP16_TO_FP(SDValue Op,2919                                                 SelectionDAG &DAG) const {2920  // Custom lower to ensure the libcall argument is passed in an FPR on hard2921  // float ABIs.2922  SDLoc DL(Op);2923  MakeLibCallOptions CallOptions;2924  SDValue Op0 = Op.getOperand(0);2925  SDValue Chain = SDValue();2926  SDValue Arg = Subtarget.is64Bit() ? DAG.getNode(LoongArchISD::MOVGR2FR_W_LA64,2927                                                  DL, MVT::f32, Op0)2928                                    : DAG.getBitcast(MVT::f32, Op0);2929  SDValue Res;2930  std::tie(Res, Chain) = makeLibCall(DAG, RTLIB::FPEXT_F16_F32, MVT::f32, Arg,2931                                     CallOptions, DL, Chain);2932  return Res;2933}2934 2935SDValue LoongArchTargetLowering::lowerFP_TO_BF16(SDValue Op,2936                                                 SelectionDAG &DAG) const {2937  assert(Subtarget.hasBasicF() && "Unexpected custom legalization");2938  SDLoc DL(Op);2939  MakeLibCallOptions CallOptions;2940  RTLIB::Libcall LC =2941      RTLIB::getFPROUND(Op.getOperand(0).getValueType(), MVT::bf16);2942  SDValue Res =2943      makeLibCall(DAG, LC, MVT::f32, Op.getOperand(0), CallOptions, DL).first;2944  if (Subtarget.is64Bit())2945    return DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Res);2946  return DAG.getBitcast(MVT::i32, Res);2947}2948 2949SDValue LoongArchTargetLowering::lowerBF16_TO_FP(SDValue Op,2950                                                 SelectionDAG &DAG) const {2951  assert(Subtarget.hasBasicF() && "Unexpected custom legalization");2952  MVT VT = Op.getSimpleValueType();2953  SDLoc DL(Op);2954  Op = DAG.getNode(2955      ISD::SHL, DL, Op.getOperand(0).getValueType(), Op.getOperand(0),2956      DAG.getShiftAmountConstant(16, Op.getOperand(0).getValueType(), DL));2957  SDValue Res = Subtarget.is64Bit() ? DAG.getNode(LoongArchISD::MOVGR2FR_W_LA64,2958                                                  DL, MVT::f32, Op)2959                                    : DAG.getBitcast(MVT::f32, Op);2960  if (VT != MVT::f32)2961    return DAG.getNode(ISD::FP_EXTEND, DL, VT, Res);2962  return Res;2963}2964 2965// Lower BUILD_VECTOR as broadcast load (if possible).2966// For example:2967//   %a = load i8, ptr %ptr2968//   %b = build_vector %a, %a, %a, %a2969// is lowered to :2970//   (VLDREPL_B $a0, 0)2971static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp,2972                                                const SDLoc &DL,2973                                                SelectionDAG &DAG) {2974  MVT VT = BVOp->getSimpleValueType(0);2975  int NumOps = BVOp->getNumOperands();2976 2977  assert((VT.is128BitVector() || VT.is256BitVector()) &&2978         "Unsupported vector type for broadcast.");2979 2980  SDValue IdentitySrc;2981  bool IsIdeneity = true;2982 2983  for (int i = 0; i != NumOps; i++) {2984    SDValue Op = BVOp->getOperand(i);2985    if (Op.getOpcode() != ISD::LOAD || (IdentitySrc && Op != IdentitySrc)) {2986      IsIdeneity = false;2987      break;2988    }2989    IdentitySrc = BVOp->getOperand(0);2990  }2991 2992  // make sure that this load is valid and only has one user.2993  if (!IsIdeneity || !IdentitySrc || !BVOp->isOnlyUserOf(IdentitySrc.getNode()))2994    return SDValue();2995 2996  auto *LN = cast<LoadSDNode>(IdentitySrc);2997  auto ExtType = LN->getExtensionType();2998 2999  if ((ExtType == ISD::EXTLOAD || ExtType == ISD::NON_EXTLOAD) &&3000      VT.getScalarSizeInBits() == LN->getMemoryVT().getScalarSizeInBits()) {3001    // Indexed loads and stores are not supported on LoongArch.3002    assert(LN->isUnindexed() && "Unexpected indexed load.");3003 3004    SDVTList Tys = DAG.getVTList(VT, MVT::Other);3005    // The offset operand of unindexed load is always undefined, so there is3006    // no need to pass it to VLDREPL.3007    SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};3008    SDValue BCast = DAG.getNode(LoongArchISD::VLDREPL, DL, Tys, Ops);3009    DAG.ReplaceAllUsesOfValueWith(SDValue(LN, 1), BCast.getValue(1));3010    return BCast;3011  }3012  return SDValue();3013}3014 3015// Sequentially insert elements from Ops into Vector, from low to high indices.3016// Note: Ops can have fewer elements than Vector.3017static void fillVector(ArrayRef<SDValue> Ops, SelectionDAG &DAG, SDLoc DL,3018                       const LoongArchSubtarget &Subtarget, SDValue &Vector,3019                       EVT ResTy) {3020  assert(Ops.size() <= ResTy.getVectorNumElements());3021 3022  SDValue Op0 = Ops[0];3023  if (!Op0.isUndef())3024    Vector = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, ResTy, Op0);3025  for (unsigned i = 1; i < Ops.size(); ++i) {3026    SDValue Opi = Ops[i];3027    if (Opi.isUndef())3028      continue;3029    Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, ResTy, Vector, Opi,3030                         DAG.getConstant(i, DL, Subtarget.getGRLenVT()));3031  }3032}3033 3034// Build a ResTy subvector from Node, taking NumElts elements starting at index3035// 'first'.3036static SDValue fillSubVectorFromBuildVector(BuildVectorSDNode *Node,3037                                            SelectionDAG &DAG, SDLoc DL,3038                                            const LoongArchSubtarget &Subtarget,3039                                            EVT ResTy, unsigned first) {3040  unsigned NumElts = ResTy.getVectorNumElements();3041 3042  assert(first + NumElts <= Node->getSimpleValueType(0).getVectorNumElements());3043 3044  SmallVector<SDValue, 16> Ops(Node->op_begin() + first,3045                               Node->op_begin() + first + NumElts);3046  SDValue Vector = DAG.getUNDEF(ResTy);3047  fillVector(Ops, DAG, DL, Subtarget, Vector, ResTy);3048  return Vector;3049}3050 3051SDValue LoongArchTargetLowering::lowerBUILD_VECTOR(SDValue Op,3052                                                   SelectionDAG &DAG) const {3053  BuildVectorSDNode *Node = cast<BuildVectorSDNode>(Op);3054  MVT VT = Node->getSimpleValueType(0);3055  EVT ResTy = Op->getValueType(0);3056  unsigned NumElts = ResTy.getVectorNumElements();3057  SDLoc DL(Op);3058  APInt SplatValue, SplatUndef;3059  unsigned SplatBitSize;3060  bool HasAnyUndefs;3061  bool IsConstant = false;3062  bool UseSameConstant = true;3063  SDValue ConstantValue;3064  bool Is128Vec = ResTy.is128BitVector();3065  bool Is256Vec = ResTy.is256BitVector();3066 3067  if ((!Subtarget.hasExtLSX() || !Is128Vec) &&3068      (!Subtarget.hasExtLASX() || !Is256Vec))3069    return SDValue();3070 3071  if (SDValue Result = lowerBUILD_VECTORAsBroadCastLoad(Node, DL, DAG))3072    return Result;3073 3074  if (Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,3075                            /*MinSplatBits=*/8) &&3076      SplatBitSize <= 64) {3077    // We can only cope with 8, 16, 32, or 64-bit elements.3078    if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&3079        SplatBitSize != 64)3080      return SDValue();3081 3082    if (SplatBitSize == 64 && !Subtarget.is64Bit()) {3083      // We can only handle 64-bit elements that are within3084      // the signed 10-bit range or match vldi patterns on 32-bit targets.3085      // See the BUILD_VECTOR case in LoongArchDAGToDAGISel::Select().3086      if (!SplatValue.isSignedIntN(10) &&3087          !isImmVLDILegalForMode1(SplatValue, SplatBitSize).first)3088        return SDValue();3089      if ((Is128Vec && ResTy == MVT::v4i32) ||3090          (Is256Vec && ResTy == MVT::v8i32))3091        return Op;3092    }3093 3094    EVT ViaVecTy;3095 3096    switch (SplatBitSize) {3097    default:3098      return SDValue();3099    case 8:3100      ViaVecTy = Is128Vec ? MVT::v16i8 : MVT::v32i8;3101      break;3102    case 16:3103      ViaVecTy = Is128Vec ? MVT::v8i16 : MVT::v16i16;3104      break;3105    case 32:3106      ViaVecTy = Is128Vec ? MVT::v4i32 : MVT::v8i32;3107      break;3108    case 64:3109      ViaVecTy = Is128Vec ? MVT::v2i64 : MVT::v4i64;3110      break;3111    }3112 3113    // SelectionDAG::getConstant will promote SplatValue appropriately.3114    SDValue Result = DAG.getConstant(SplatValue, DL, ViaVecTy);3115 3116    // Bitcast to the type we originally wanted.3117    if (ViaVecTy != ResTy)3118      Result = DAG.getNode(ISD::BITCAST, SDLoc(Node), ResTy, Result);3119 3120    return Result;3121  }3122 3123  if (DAG.isSplatValue(Op, /*AllowUndefs=*/false))3124    return Op;3125 3126  for (unsigned i = 0; i < NumElts; ++i) {3127    SDValue Opi = Node->getOperand(i);3128    if (isIntOrFPConstant(Opi)) {3129      IsConstant = true;3130      if (!ConstantValue.getNode())3131        ConstantValue = Opi;3132      else if (ConstantValue != Opi)3133        UseSameConstant = false;3134    }3135  }3136 3137  // If the type of BUILD_VECTOR is v2f64, custom legalizing it has no benefits.3138  if (IsConstant && UseSameConstant && ResTy != MVT::v2f64) {3139    SDValue Result = DAG.getSplatBuildVector(ResTy, DL, ConstantValue);3140    for (unsigned i = 0; i < NumElts; ++i) {3141      SDValue Opi = Node->getOperand(i);3142      if (!isIntOrFPConstant(Opi))3143        Result = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, ResTy, Result, Opi,3144                             DAG.getConstant(i, DL, Subtarget.getGRLenVT()));3145    }3146    return Result;3147  }3148 3149  if (!IsConstant) {3150    // If the BUILD_VECTOR has a repeated pattern, use INSERT_VECTOR_ELT to fill3151    // the sub-sequence of the vector and then broadcast the sub-sequence.3152    //3153    // TODO: If the BUILD_VECTOR contains undef elements, consider falling3154    // back to use INSERT_VECTOR_ELT to materialize the vector, because it3155    // generates worse code in some cases. This could be further optimized3156    // with more consideration.3157    SmallVector<SDValue> Sequence;3158    BitVector UndefElements;3159    if (Node->getRepeatedSequence(Sequence, &UndefElements) &&3160        UndefElements.count() == 0) {3161      // Using LSX instructions to fill the sub-sequence of 256-bits vector,3162      // because the high part can be simply treated as undef.3163      SDValue Vector = DAG.getUNDEF(ResTy);3164      EVT FillTy = Is256Vec3165                       ? ResTy.getHalfNumVectorElementsVT(*DAG.getContext())3166                       : ResTy;3167      SDValue FillVec =3168          Is256Vec ? DAG.getExtractSubvector(DL, FillTy, Vector, 0) : Vector;3169 3170      fillVector(Sequence, DAG, DL, Subtarget, FillVec, FillTy);3171 3172      unsigned SeqLen = Sequence.size();3173      unsigned SplatLen = NumElts / SeqLen;3174      MVT SplatEltTy = MVT::getIntegerVT(VT.getScalarSizeInBits() * SeqLen);3175      MVT SplatTy = MVT::getVectorVT(SplatEltTy, SplatLen);3176 3177      // If size of the sub-sequence is half of a 256-bits vector, bitcast the3178      // vector to v4i64 type in order to match the pattern of XVREPLVE0Q.3179      if (SplatEltTy == MVT::i128)3180        SplatTy = MVT::v4i64;3181 3182      SDValue SplatVec;3183      SDValue SrcVec = DAG.getBitcast(3184          SplatTy,3185          Is256Vec ? DAG.getInsertSubvector(DL, Vector, FillVec, 0) : FillVec);3186      if (Is256Vec) {3187        SplatVec =3188            DAG.getNode((SplatEltTy == MVT::i128) ? LoongArchISD::XVREPLVE0Q3189                                                  : LoongArchISD::XVREPLVE0,3190                        DL, SplatTy, SrcVec);3191      } else {3192        SplatVec = DAG.getNode(LoongArchISD::VREPLVEI, DL, SplatTy, SrcVec,3193                               DAG.getConstant(0, DL, Subtarget.getGRLenVT()));3194      }3195 3196      return DAG.getBitcast(ResTy, SplatVec);3197    }3198 3199    // Use INSERT_VECTOR_ELT operations rather than expand to stores, because3200    // using memory operations is much lower.3201    //3202    // For 256-bit vectors, normally split into two halves and concatenate.3203    // Special case: for v8i32/v8f32/v4i64/v4f64, if the upper half has only3204    // one non-undef element, skip spliting to avoid a worse result.3205    if (ResTy == MVT::v8i32 || ResTy == MVT::v8f32 || ResTy == MVT::v4i64 ||3206        ResTy == MVT::v4f64) {3207      unsigned NonUndefCount = 0;3208      for (unsigned i = NumElts / 2; i < NumElts; ++i) {3209        if (!Node->getOperand(i).isUndef()) {3210          ++NonUndefCount;3211          if (NonUndefCount > 1)3212            break;3213        }3214      }3215      if (NonUndefCount == 1)3216        return fillSubVectorFromBuildVector(Node, DAG, DL, Subtarget, ResTy, 0);3217    }3218 3219    EVT VecTy =3220        Is256Vec ? ResTy.getHalfNumVectorElementsVT(*DAG.getContext()) : ResTy;3221    SDValue Vector =3222        fillSubVectorFromBuildVector(Node, DAG, DL, Subtarget, VecTy, 0);3223 3224    if (Is128Vec)3225      return Vector;3226 3227    SDValue VectorHi = fillSubVectorFromBuildVector(Node, DAG, DL, Subtarget,3228                                                    VecTy, NumElts / 2);3229 3230    return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResTy, Vector, VectorHi);3231  }3232 3233  return SDValue();3234}3235 3236SDValue LoongArchTargetLowering::lowerCONCAT_VECTORS(SDValue Op,3237                                                     SelectionDAG &DAG) const {3238  SDLoc DL(Op);3239  MVT ResVT = Op.getSimpleValueType();3240  assert(ResVT.is256BitVector() && Op.getNumOperands() == 2);3241 3242  unsigned NumOperands = Op.getNumOperands();3243  unsigned NumFreezeUndef = 0;3244  unsigned NumZero = 0;3245  unsigned NumNonZero = 0;3246  unsigned NonZeros = 0;3247  SmallSet<SDValue, 4> Undefs;3248  for (unsigned i = 0; i != NumOperands; ++i) {3249    SDValue SubVec = Op.getOperand(i);3250    if (SubVec.isUndef())3251      continue;3252    if (ISD::isFreezeUndef(SubVec.getNode())) {3253      // If the freeze(undef) has multiple uses then we must fold to zero.3254      if (SubVec.hasOneUse()) {3255        ++NumFreezeUndef;3256      } else {3257        ++NumZero;3258        Undefs.insert(SubVec);3259      }3260    } else if (ISD::isBuildVectorAllZeros(SubVec.getNode()))3261      ++NumZero;3262    else {3263      assert(i < sizeof(NonZeros) * CHAR_BIT); // Ensure the shift is in range.3264      NonZeros |= 1 << i;3265      ++NumNonZero;3266    }3267  }3268 3269  // If we have more than 2 non-zeros, build each half separately.3270  if (NumNonZero > 2) {3271    MVT HalfVT = ResVT.getHalfNumVectorElementsVT();3272    ArrayRef<SDUse> Ops = Op->ops();3273    SDValue Lo = DAG.getNode(ISD::CONCAT_VECTORS, DL, HalfVT,3274                             Ops.slice(0, NumOperands / 2));3275    SDValue Hi = DAG.getNode(ISD::CONCAT_VECTORS, DL, HalfVT,3276                             Ops.slice(NumOperands / 2));3277    return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Lo, Hi);3278  }3279 3280  // Otherwise, build it up through insert_subvectors.3281  SDValue Vec = NumZero ? DAG.getConstant(0, DL, ResVT)3282                        : (NumFreezeUndef ? DAG.getFreeze(DAG.getUNDEF(ResVT))3283                                          : DAG.getUNDEF(ResVT));3284 3285  // Replace Undef operands with ZeroVector.3286  for (SDValue U : Undefs)3287    DAG.ReplaceAllUsesWith(U, DAG.getConstant(0, DL, U.getSimpleValueType()));3288 3289  MVT SubVT = Op.getOperand(0).getSimpleValueType();3290  unsigned NumSubElems = SubVT.getVectorNumElements();3291  for (unsigned i = 0; i != NumOperands; ++i) {3292    if ((NonZeros & (1 << i)) == 0)3293      continue;3294 3295    Vec = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, ResVT, Vec, Op.getOperand(i),3296                      DAG.getVectorIdxConstant(i * NumSubElems, DL));3297  }3298 3299  return Vec;3300}3301 3302SDValue3303LoongArchTargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op,3304                                                 SelectionDAG &DAG) const {3305  MVT EltVT = Op.getSimpleValueType();3306  SDValue Vec = Op->getOperand(0);3307  EVT VecTy = Vec->getValueType(0);3308  SDValue Idx = Op->getOperand(1);3309  SDLoc DL(Op);3310  MVT GRLenVT = Subtarget.getGRLenVT();3311 3312  assert(VecTy.is256BitVector() && "Unexpected EXTRACT_VECTOR_ELT vector type");3313 3314  if (isa<ConstantSDNode>(Idx))3315    return Op;3316 3317  switch (VecTy.getSimpleVT().SimpleTy) {3318  default:3319    llvm_unreachable("Unexpected type");3320  case MVT::v32i8:3321  case MVT::v16i16:3322  case MVT::v4i64:3323  case MVT::v4f64: {3324    // Extract the high half subvector and place it to the low half of a new3325    // vector. It doesn't matter what the high half of the new vector is.3326    EVT HalfTy = VecTy.getHalfNumVectorElementsVT(*DAG.getContext());3327    SDValue VecHi =3328        DAG.getExtractSubvector(DL, HalfTy, Vec, HalfTy.getVectorNumElements());3329    SDValue TmpVec =3330        DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VecTy, DAG.getUNDEF(VecTy),3331                    VecHi, DAG.getConstant(0, DL, GRLenVT));3332 3333    // Shuffle the origin Vec and the TmpVec using MaskVec, the lowest element3334    // of MaskVec is Idx, the rest do not matter. ResVec[0] will hold the3335    // desired element.3336    SDValue IdxCp =3337        Subtarget.is64Bit()3338            ? DAG.getNode(LoongArchISD::MOVGR2FR_W_LA64, DL, MVT::f32, Idx)3339            : DAG.getBitcast(MVT::f32, Idx);3340    SDValue IdxVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v8f32, IdxCp);3341    SDValue MaskVec =3342        DAG.getBitcast((VecTy == MVT::v4f64) ? MVT::v4i64 : VecTy, IdxVec);3343    SDValue ResVec =3344        DAG.getNode(LoongArchISD::VSHUF, DL, VecTy, MaskVec, TmpVec, Vec);3345 3346    return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, ResVec,3347                       DAG.getConstant(0, DL, GRLenVT));3348  }3349  case MVT::v8i32:3350  case MVT::v8f32: {3351    SDValue SplatIdx = DAG.getSplatBuildVector(MVT::v8i32, DL, Idx);3352    SDValue SplatValue =3353        DAG.getNode(LoongArchISD::XVPERM, DL, VecTy, Vec, SplatIdx);3354 3355    return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, SplatValue,3356                       DAG.getConstant(0, DL, GRLenVT));3357  }3358  }3359}3360 3361SDValue3362LoongArchTargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op,3363                                                SelectionDAG &DAG) const {3364  MVT VT = Op.getSimpleValueType();3365  MVT EltVT = VT.getVectorElementType();3366  unsigned NumElts = VT.getVectorNumElements();3367  unsigned EltSizeInBits = EltVT.getScalarSizeInBits();3368  SDLoc DL(Op);3369  SDValue Op0 = Op.getOperand(0);3370  SDValue Op1 = Op.getOperand(1);3371  SDValue Op2 = Op.getOperand(2);3372 3373  if (isa<ConstantSDNode>(Op2))3374    return Op;3375 3376  MVT IdxTy = MVT::getIntegerVT(EltSizeInBits);3377  MVT IdxVTy = MVT::getVectorVT(IdxTy, NumElts);3378 3379  if (!isTypeLegal(VT) || !isTypeLegal(IdxVTy))3380    return SDValue();3381 3382  SDValue SplatElt = DAG.getSplatBuildVector(VT, DL, Op1);3383  SmallVector<SDValue, 32> RawIndices;3384  SDValue SplatIdx;3385  SDValue Indices;3386 3387  if (!Subtarget.is64Bit() && IdxTy == MVT::i64) {3388    MVT PairVTy = MVT::getVectorVT(MVT::i32, NumElts * 2);3389    for (unsigned i = 0; i < NumElts; ++i) {3390      RawIndices.push_back(Op2);3391      RawIndices.push_back(DAG.getConstant(0, DL, MVT::i32));3392    }3393    SplatIdx = DAG.getBuildVector(PairVTy, DL, RawIndices);3394    SplatIdx = DAG.getBitcast(IdxVTy, SplatIdx);3395 3396    RawIndices.clear();3397    for (unsigned i = 0; i < NumElts; ++i) {3398      RawIndices.push_back(DAG.getConstant(i, DL, MVT::i32));3399      RawIndices.push_back(DAG.getConstant(0, DL, MVT::i32));3400    }3401    Indices = DAG.getBuildVector(PairVTy, DL, RawIndices);3402    Indices = DAG.getBitcast(IdxVTy, Indices);3403  } else {3404    SplatIdx = DAG.getSplatBuildVector(IdxVTy, DL, Op2);3405 3406    for (unsigned i = 0; i < NumElts; ++i)3407      RawIndices.push_back(DAG.getConstant(i, DL, Subtarget.getGRLenVT()));3408    Indices = DAG.getBuildVector(IdxVTy, DL, RawIndices);3409  }3410 3411  // insert vec, elt, idx3412  // =>3413  // select (splatidx == {0,1,2...}) ? splatelt : vec3414  SDValue SelectCC =3415      DAG.getSetCC(DL, IdxVTy, SplatIdx, Indices, ISD::CondCode::SETEQ);3416  return DAG.getNode(ISD::VSELECT, DL, VT, SelectCC, SplatElt, Op0);3417}3418 3419SDValue LoongArchTargetLowering::lowerATOMIC_FENCE(SDValue Op,3420                                                   SelectionDAG &DAG) const {3421  SDLoc DL(Op);3422  SyncScope::ID FenceSSID =3423      static_cast<SyncScope::ID>(Op.getConstantOperandVal(2));3424 3425  // singlethread fences only synchronize with signal handlers on the same3426  // thread and thus only need to preserve instruction order, not actually3427  // enforce memory ordering.3428  if (FenceSSID == SyncScope::SingleThread)3429    // MEMBARRIER is a compiler barrier; it codegens to a no-op.3430    return DAG.getNode(ISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0));3431 3432  return Op;3433}3434 3435SDValue LoongArchTargetLowering::lowerWRITE_REGISTER(SDValue Op,3436                                                     SelectionDAG &DAG) const {3437 3438  if (Subtarget.is64Bit() && Op.getOperand(2).getValueType() == MVT::i32) {3439    DAG.getContext()->emitError(3440        "On LA64, only 64-bit registers can be written.");3441    return Op.getOperand(0);3442  }3443 3444  if (!Subtarget.is64Bit() && Op.getOperand(2).getValueType() == MVT::i64) {3445    DAG.getContext()->emitError(3446        "On LA32, only 32-bit registers can be written.");3447    return Op.getOperand(0);3448  }3449 3450  return Op;3451}3452 3453SDValue LoongArchTargetLowering::lowerFRAMEADDR(SDValue Op,3454                                                SelectionDAG &DAG) const {3455  if (!isa<ConstantSDNode>(Op.getOperand(0))) {3456    DAG.getContext()->emitError("argument to '__builtin_frame_address' must "3457                                "be a constant integer");3458    return SDValue();3459  }3460 3461  MachineFunction &MF = DAG.getMachineFunction();3462  MF.getFrameInfo().setFrameAddressIsTaken(true);3463  Register FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);3464  EVT VT = Op.getValueType();3465  SDLoc DL(Op);3466  SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), DL, FrameReg, VT);3467  unsigned Depth = Op.getConstantOperandVal(0);3468  int GRLenInBytes = Subtarget.getGRLen() / 8;3469 3470  while (Depth--) {3471    int Offset = -(GRLenInBytes * 2);3472    SDValue Ptr = DAG.getNode(ISD::ADD, DL, VT, FrameAddr,3473                              DAG.getSignedConstant(Offset, DL, VT));3474    FrameAddr =3475        DAG.getLoad(VT, DL, DAG.getEntryNode(), Ptr, MachinePointerInfo());3476  }3477  return FrameAddr;3478}3479 3480SDValue LoongArchTargetLowering::lowerRETURNADDR(SDValue Op,3481                                                 SelectionDAG &DAG) const {3482  // Currently only support lowering return address for current frame.3483  if (Op.getConstantOperandVal(0) != 0) {3484    DAG.getContext()->emitError(3485        "return address can only be determined for the current frame");3486    return SDValue();3487  }3488 3489  MachineFunction &MF = DAG.getMachineFunction();3490  MF.getFrameInfo().setReturnAddressIsTaken(true);3491  MVT GRLenVT = Subtarget.getGRLenVT();3492 3493  // Return the value of the return address register, marking it an implicit3494  // live-in.3495  Register Reg = MF.addLiveIn(Subtarget.getRegisterInfo()->getRARegister(),3496                              getRegClassFor(GRLenVT));3497  return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), Reg, GRLenVT);3498}3499 3500SDValue LoongArchTargetLowering::lowerEH_DWARF_CFA(SDValue Op,3501                                                   SelectionDAG &DAG) const {3502  MachineFunction &MF = DAG.getMachineFunction();3503  auto Size = Subtarget.getGRLen() / 8;3504  auto FI = MF.getFrameInfo().CreateFixedObject(Size, 0, false);3505  return DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));3506}3507 3508SDValue LoongArchTargetLowering::lowerVASTART(SDValue Op,3509                                              SelectionDAG &DAG) const {3510  MachineFunction &MF = DAG.getMachineFunction();3511  auto *FuncInfo = MF.getInfo<LoongArchMachineFunctionInfo>();3512 3513  SDLoc DL(Op);3514  SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(),3515                                 getPointerTy(MF.getDataLayout()));3516 3517  // vastart just stores the address of the VarArgsFrameIndex slot into the3518  // memory location argument.3519  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();3520  return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1),3521                      MachinePointerInfo(SV));3522}3523 3524SDValue LoongArchTargetLowering::lowerUINT_TO_FP(SDValue Op,3525                                                 SelectionDAG &DAG) const {3526  assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&3527         !Subtarget.hasBasicD() && "unexpected target features");3528 3529  SDLoc DL(Op);3530  SDValue Op0 = Op.getOperand(0);3531  if (Op0->getOpcode() == ISD::AND) {3532    auto *C = dyn_cast<ConstantSDNode>(Op0.getOperand(1));3533    if (C && C->getZExtValue() < UINT64_C(0xFFFFFFFF))3534      return Op;3535  }3536 3537  if (Op0->getOpcode() == LoongArchISD::BSTRPICK &&3538      Op0.getConstantOperandVal(1) < UINT64_C(0X1F) &&3539      Op0.getConstantOperandVal(2) == UINT64_C(0))3540    return Op;3541 3542  if (Op0.getOpcode() == ISD::AssertZext &&3543      dyn_cast<VTSDNode>(Op0.getOperand(1))->getVT().bitsLT(MVT::i32))3544    return Op;3545 3546  EVT OpVT = Op0.getValueType();3547  EVT RetVT = Op.getValueType();3548  RTLIB::Libcall LC = RTLIB::getUINTTOFP(OpVT, RetVT);3549  MakeLibCallOptions CallOptions;3550  CallOptions.setTypeListBeforeSoften(OpVT, RetVT);3551  SDValue Chain = SDValue();3552  SDValue Result;3553  std::tie(Result, Chain) =3554      makeLibCall(DAG, LC, Op.getValueType(), Op0, CallOptions, DL, Chain);3555  return Result;3556}3557 3558SDValue LoongArchTargetLowering::lowerSINT_TO_FP(SDValue Op,3559                                                 SelectionDAG &DAG) const {3560  assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&3561         !Subtarget.hasBasicD() && "unexpected target features");3562 3563  SDLoc DL(Op);3564  SDValue Op0 = Op.getOperand(0);3565 3566  if ((Op0.getOpcode() == ISD::AssertSext ||3567       Op0.getOpcode() == ISD::SIGN_EXTEND_INREG) &&3568      dyn_cast<VTSDNode>(Op0.getOperand(1))->getVT().bitsLE(MVT::i32))3569    return Op;3570 3571  EVT OpVT = Op0.getValueType();3572  EVT RetVT = Op.getValueType();3573  RTLIB::Libcall LC = RTLIB::getSINTTOFP(OpVT, RetVT);3574  MakeLibCallOptions CallOptions;3575  CallOptions.setTypeListBeforeSoften(OpVT, RetVT);3576  SDValue Chain = SDValue();3577  SDValue Result;3578  std::tie(Result, Chain) =3579      makeLibCall(DAG, LC, Op.getValueType(), Op0, CallOptions, DL, Chain);3580  return Result;3581}3582 3583SDValue LoongArchTargetLowering::lowerBITCAST(SDValue Op,3584                                              SelectionDAG &DAG) const {3585 3586  SDLoc DL(Op);3587  EVT VT = Op.getValueType();3588  SDValue Op0 = Op.getOperand(0);3589  EVT Op0VT = Op0.getValueType();3590 3591  if (Op.getValueType() == MVT::f32 && Op0VT == MVT::i32 &&3592      Subtarget.is64Bit() && Subtarget.hasBasicF()) {3593    SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op0);3594    return DAG.getNode(LoongArchISD::MOVGR2FR_W_LA64, DL, MVT::f32, NewOp0);3595  }3596  if (VT == MVT::f64 && Op0VT == MVT::i64 && !Subtarget.is64Bit()) {3597    SDValue Lo, Hi;3598    std::tie(Lo, Hi) = DAG.SplitScalar(Op0, DL, MVT::i32, MVT::i32);3599    return DAG.getNode(LoongArchISD::BUILD_PAIR_F64, DL, MVT::f64, Lo, Hi);3600  }3601  return Op;3602}3603 3604SDValue LoongArchTargetLowering::lowerFP_TO_SINT(SDValue Op,3605                                                 SelectionDAG &DAG) const {3606 3607  SDLoc DL(Op);3608  SDValue Op0 = Op.getOperand(0);3609 3610  if (Op0.getValueType() == MVT::f16)3611    Op0 = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Op0);3612 3613  if (Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() &&3614      !Subtarget.hasBasicD()) {3615    SDValue Dst = DAG.getNode(LoongArchISD::FTINT, DL, MVT::f32, Op0);3616    return DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Dst);3617  }3618 3619  EVT FPTy = EVT::getFloatingPointVT(Op.getValueSizeInBits());3620  SDValue Trunc = DAG.getNode(LoongArchISD::FTINT, DL, FPTy, Op0);3621  return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Trunc);3622}3623 3624static SDValue getTargetNode(GlobalAddressSDNode *N, SDLoc DL, EVT Ty,3625                             SelectionDAG &DAG, unsigned Flags) {3626  return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags);3627}3628 3629static SDValue getTargetNode(BlockAddressSDNode *N, SDLoc DL, EVT Ty,3630                             SelectionDAG &DAG, unsigned Flags) {3631  return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(),3632                                   Flags);3633}3634 3635static SDValue getTargetNode(ConstantPoolSDNode *N, SDLoc DL, EVT Ty,3636                             SelectionDAG &DAG, unsigned Flags) {3637  return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(),3638                                   N->getOffset(), Flags);3639}3640 3641static SDValue getTargetNode(JumpTableSDNode *N, SDLoc DL, EVT Ty,3642                             SelectionDAG &DAG, unsigned Flags) {3643  return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags);3644}3645 3646template <class NodeTy>3647SDValue LoongArchTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,3648                                         CodeModel::Model M,3649                                         bool IsLocal) const {3650  SDLoc DL(N);3651  EVT Ty = getPointerTy(DAG.getDataLayout());3652  SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);3653  SDValue Load;3654 3655  switch (M) {3656  default:3657    report_fatal_error("Unsupported code model");3658 3659  case CodeModel::Large: {3660    assert(Subtarget.is64Bit() && "Large code model requires LA64");3661 3662    // This is not actually used, but is necessary for successfully matching3663    // the PseudoLA_*_LARGE nodes.3664    SDValue Tmp = DAG.getConstant(0, DL, Ty);3665    if (IsLocal) {3666      // This generates the pattern (PseudoLA_PCREL_LARGE tmp sym), that3667      // eventually becomes the desired 5-insn code sequence.3668      Load = SDValue(DAG.getMachineNode(LoongArch::PseudoLA_PCREL_LARGE, DL, Ty,3669                                        Tmp, Addr),3670                     0);3671    } else {3672      // This generates the pattern (PseudoLA_GOT_LARGE tmp sym), that3673      // eventually becomes the desired 5-insn code sequence.3674      Load = SDValue(3675          DAG.getMachineNode(LoongArch::PseudoLA_GOT_LARGE, DL, Ty, Tmp, Addr),3676          0);3677    }3678    break;3679  }3680 3681  case CodeModel::Small:3682  case CodeModel::Medium:3683    if (IsLocal) {3684      // This generates the pattern (PseudoLA_PCREL sym), which expands to3685      // (addi.w/d (pcalau12i %pc_hi20(sym)) %pc_lo12(sym)).3686      Load = SDValue(3687          DAG.getMachineNode(LoongArch::PseudoLA_PCREL, DL, Ty, Addr), 0);3688    } else {3689      // This generates the pattern (PseudoLA_GOT sym), which expands to (ld.w/d3690      // (pcalau12i %got_pc_hi20(sym)) %got_pc_lo12(sym)).3691      Load =3692          SDValue(DAG.getMachineNode(LoongArch::PseudoLA_GOT, DL, Ty, Addr), 0);3693    }3694  }3695 3696  if (!IsLocal) {3697    // Mark the load instruction as invariant to enable hoisting in MachineLICM.3698    MachineFunction &MF = DAG.getMachineFunction();3699    MachineMemOperand *MemOp = MF.getMachineMemOperand(3700        MachinePointerInfo::getGOT(MF),3701        MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |3702            MachineMemOperand::MOInvariant,3703        LLT(Ty.getSimpleVT()), Align(Ty.getFixedSizeInBits() / 8));3704    DAG.setNodeMemRefs(cast<MachineSDNode>(Load.getNode()), {MemOp});3705  }3706 3707  return Load;3708}3709 3710SDValue LoongArchTargetLowering::lowerBlockAddress(SDValue Op,3711                                                   SelectionDAG &DAG) const {3712  return getAddr(cast<BlockAddressSDNode>(Op), DAG,3713                 DAG.getTarget().getCodeModel());3714}3715 3716SDValue LoongArchTargetLowering::lowerJumpTable(SDValue Op,3717                                                SelectionDAG &DAG) const {3718  return getAddr(cast<JumpTableSDNode>(Op), DAG,3719                 DAG.getTarget().getCodeModel());3720}3721 3722SDValue LoongArchTargetLowering::lowerConstantPool(SDValue Op,3723                                                   SelectionDAG &DAG) const {3724  return getAddr(cast<ConstantPoolSDNode>(Op), DAG,3725                 DAG.getTarget().getCodeModel());3726}3727 3728SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op,3729                                                    SelectionDAG &DAG) const {3730  GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);3731  assert(N->getOffset() == 0 && "unexpected offset in global node");3732  auto CM = DAG.getTarget().getCodeModel();3733  const GlobalValue *GV = N->getGlobal();3734 3735  if (GV->isDSOLocal() && isa<GlobalVariable>(GV)) {3736    if (auto GCM = dyn_cast<GlobalVariable>(GV)->getCodeModel())3737      CM = *GCM;3738  }3739 3740  return getAddr(N, DAG, CM, GV->isDSOLocal());3741}3742 3743SDValue LoongArchTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N,3744                                                  SelectionDAG &DAG,3745                                                  unsigned Opc, bool UseGOT,3746                                                  bool Large) const {3747  SDLoc DL(N);3748  EVT Ty = getPointerTy(DAG.getDataLayout());3749  MVT GRLenVT = Subtarget.getGRLenVT();3750 3751  // This is not actually used, but is necessary for successfully matching the3752  // PseudoLA_*_LARGE nodes.3753  SDValue Tmp = DAG.getConstant(0, DL, Ty);3754  SDValue Addr = DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, 0);3755 3756  // Only IE needs an extra argument for large code model.3757  SDValue Offset = Opc == LoongArch::PseudoLA_TLS_IE_LARGE3758                       ? SDValue(DAG.getMachineNode(Opc, DL, Ty, Tmp, Addr), 0)3759                       : SDValue(DAG.getMachineNode(Opc, DL, Ty, Addr), 0);3760 3761  // If it is LE for normal/medium code model, the add tp operation will occur3762  // during the pseudo-instruction expansion.3763  if (Opc == LoongArch::PseudoLA_TLS_LE && !Large)3764    return Offset;3765 3766  if (UseGOT) {3767    // Mark the load instruction as invariant to enable hoisting in MachineLICM.3768    MachineFunction &MF = DAG.getMachineFunction();3769    MachineMemOperand *MemOp = MF.getMachineMemOperand(3770        MachinePointerInfo::getGOT(MF),3771        MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |3772            MachineMemOperand::MOInvariant,3773        LLT(Ty.getSimpleVT()), Align(Ty.getFixedSizeInBits() / 8));3774    DAG.setNodeMemRefs(cast<MachineSDNode>(Offset.getNode()), {MemOp});3775  }3776 3777  // Add the thread pointer.3778  return DAG.getNode(ISD::ADD, DL, Ty, Offset,3779                     DAG.getRegister(LoongArch::R2, GRLenVT));3780}3781 3782SDValue LoongArchTargetLowering::getDynamicTLSAddr(GlobalAddressSDNode *N,3783                                                   SelectionDAG &DAG,3784                                                   unsigned Opc,3785                                                   bool Large) const {3786  SDLoc DL(N);3787  EVT Ty = getPointerTy(DAG.getDataLayout());3788  IntegerType *CallTy = Type::getIntNTy(*DAG.getContext(), Ty.getSizeInBits());3789 3790  // This is not actually used, but is necessary for successfully matching the3791  // PseudoLA_*_LARGE nodes.3792  SDValue Tmp = DAG.getConstant(0, DL, Ty);3793 3794  // Use a PC-relative addressing mode to access the dynamic GOT address.3795  SDValue Addr = DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, 0);3796  SDValue Load = Large ? SDValue(DAG.getMachineNode(Opc, DL, Ty, Tmp, Addr), 0)3797                       : SDValue(DAG.getMachineNode(Opc, DL, Ty, Addr), 0);3798 3799  // Prepare argument list to generate call.3800  ArgListTy Args;3801  Args.emplace_back(Load, CallTy);3802 3803  // Setup call to __tls_get_addr.3804  TargetLowering::CallLoweringInfo CLI(DAG);3805  CLI.setDebugLoc(DL)3806      .setChain(DAG.getEntryNode())3807      .setLibCallee(CallingConv::C, CallTy,3808                    DAG.getExternalSymbol("__tls_get_addr", Ty),3809                    std::move(Args));3810 3811  return LowerCallTo(CLI).first;3812}3813 3814SDValue LoongArchTargetLowering::getTLSDescAddr(GlobalAddressSDNode *N,3815                                                SelectionDAG &DAG, unsigned Opc,3816                                                bool Large) const {3817  SDLoc DL(N);3818  EVT Ty = getPointerTy(DAG.getDataLayout());3819  const GlobalValue *GV = N->getGlobal();3820 3821  // This is not actually used, but is necessary for successfully matching the3822  // PseudoLA_*_LARGE nodes.3823  SDValue Tmp = DAG.getConstant(0, DL, Ty);3824 3825  // Use a PC-relative addressing mode to access the global dynamic GOT address.3826  // This generates the pattern (PseudoLA_TLS_DESC_PC{,LARGE} sym).3827  SDValue Addr = DAG.getTargetGlobalAddress(GV, DL, Ty, 0, 0);3828  return Large ? SDValue(DAG.getMachineNode(Opc, DL, Ty, Tmp, Addr), 0)3829               : SDValue(DAG.getMachineNode(Opc, DL, Ty, Addr), 0);3830}3831 3832SDValue3833LoongArchTargetLowering::lowerGlobalTLSAddress(SDValue Op,3834                                               SelectionDAG &DAG) const {3835  if (DAG.getMachineFunction().getFunction().getCallingConv() ==3836      CallingConv::GHC)3837    report_fatal_error("In GHC calling convention TLS is not supported");3838 3839  bool Large = DAG.getTarget().getCodeModel() == CodeModel::Large;3840  assert((!Large || Subtarget.is64Bit()) && "Large code model requires LA64");3841 3842  GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);3843  assert(N->getOffset() == 0 && "unexpected offset in global node");3844 3845  if (DAG.getTarget().useEmulatedTLS())3846    reportFatalUsageError("the emulated TLS is prohibited");3847 3848  bool IsDesc = DAG.getTarget().useTLSDESC();3849 3850  switch (getTargetMachine().getTLSModel(N->getGlobal())) {3851  case TLSModel::GeneralDynamic:3852    // In this model, application code calls the dynamic linker function3853    // __tls_get_addr to locate TLS offsets into the dynamic thread vector at3854    // runtime.3855    if (!IsDesc)3856      return getDynamicTLSAddr(N, DAG,3857                               Large ? LoongArch::PseudoLA_TLS_GD_LARGE3858                                     : LoongArch::PseudoLA_TLS_GD,3859                               Large);3860    break;3861  case TLSModel::LocalDynamic:3862    // Same as GeneralDynamic, except for assembly modifiers and relocation3863    // records.3864    if (!IsDesc)3865      return getDynamicTLSAddr(N, DAG,3866                               Large ? LoongArch::PseudoLA_TLS_LD_LARGE3867                                     : LoongArch::PseudoLA_TLS_LD,3868                               Large);3869    break;3870  case TLSModel::InitialExec:3871    // This model uses the GOT to resolve TLS offsets.3872    return getStaticTLSAddr(N, DAG,3873                            Large ? LoongArch::PseudoLA_TLS_IE_LARGE3874                                  : LoongArch::PseudoLA_TLS_IE,3875                            /*UseGOT=*/true, Large);3876  case TLSModel::LocalExec:3877    // This model is used when static linking as the TLS offsets are resolved3878    // during program linking.3879    //3880    // This node doesn't need an extra argument for the large code model.3881    return getStaticTLSAddr(N, DAG, LoongArch::PseudoLA_TLS_LE,3882                            /*UseGOT=*/false, Large);3883  }3884 3885  return getTLSDescAddr(N, DAG,3886                        Large ? LoongArch::PseudoLA_TLS_DESC_LARGE3887                              : LoongArch::PseudoLA_TLS_DESC,3888                        Large);3889}3890 3891template <unsigned N>3892static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp,3893                                    SelectionDAG &DAG, bool IsSigned = false) {3894  auto *CImm = cast<ConstantSDNode>(Op->getOperand(ImmOp));3895  // Check the ImmArg.3896  if ((IsSigned && !isInt<N>(CImm->getSExtValue())) ||3897      (!IsSigned && !isUInt<N>(CImm->getZExtValue()))) {3898    DAG.getContext()->emitError(Op->getOperationName(0) +3899                                ": argument out of range.");3900    return DAG.getNode(ISD::UNDEF, SDLoc(Op), Op.getValueType());3901  }3902  return SDValue();3903}3904 3905SDValue3906LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,3907                                                 SelectionDAG &DAG) const {3908  switch (Op.getConstantOperandVal(0)) {3909  default:3910    return SDValue(); // Don't custom lower most intrinsics.3911  case Intrinsic::thread_pointer: {3912    EVT PtrVT = getPointerTy(DAG.getDataLayout());3913    return DAG.getRegister(LoongArch::R2, PtrVT);3914  }3915  case Intrinsic::loongarch_lsx_vpickve2gr_d:3916  case Intrinsic::loongarch_lsx_vpickve2gr_du:3917  case Intrinsic::loongarch_lsx_vreplvei_d:3918  case Intrinsic::loongarch_lasx_xvrepl128vei_d:3919    return checkIntrinsicImmArg<1>(Op, 2, DAG);3920  case Intrinsic::loongarch_lsx_vreplvei_w:3921  case Intrinsic::loongarch_lasx_xvrepl128vei_w:3922  case Intrinsic::loongarch_lasx_xvpickve2gr_d:3923  case Intrinsic::loongarch_lasx_xvpickve2gr_du:3924  case Intrinsic::loongarch_lasx_xvpickve_d:3925  case Intrinsic::loongarch_lasx_xvpickve_d_f:3926    return checkIntrinsicImmArg<2>(Op, 2, DAG);3927  case Intrinsic::loongarch_lasx_xvinsve0_d:3928    return checkIntrinsicImmArg<2>(Op, 3, DAG);3929  case Intrinsic::loongarch_lsx_vsat_b:3930  case Intrinsic::loongarch_lsx_vsat_bu:3931  case Intrinsic::loongarch_lsx_vrotri_b:3932  case Intrinsic::loongarch_lsx_vsllwil_h_b:3933  case Intrinsic::loongarch_lsx_vsllwil_hu_bu:3934  case Intrinsic::loongarch_lsx_vsrlri_b:3935  case Intrinsic::loongarch_lsx_vsrari_b:3936  case Intrinsic::loongarch_lsx_vreplvei_h:3937  case Intrinsic::loongarch_lasx_xvsat_b:3938  case Intrinsic::loongarch_lasx_xvsat_bu:3939  case Intrinsic::loongarch_lasx_xvrotri_b:3940  case Intrinsic::loongarch_lasx_xvsllwil_h_b:3941  case Intrinsic::loongarch_lasx_xvsllwil_hu_bu:3942  case Intrinsic::loongarch_lasx_xvsrlri_b:3943  case Intrinsic::loongarch_lasx_xvsrari_b:3944  case Intrinsic::loongarch_lasx_xvrepl128vei_h:3945  case Intrinsic::loongarch_lasx_xvpickve_w:3946  case Intrinsic::loongarch_lasx_xvpickve_w_f:3947    return checkIntrinsicImmArg<3>(Op, 2, DAG);3948  case Intrinsic::loongarch_lasx_xvinsve0_w:3949    return checkIntrinsicImmArg<3>(Op, 3, DAG);3950  case Intrinsic::loongarch_lsx_vsat_h:3951  case Intrinsic::loongarch_lsx_vsat_hu:3952  case Intrinsic::loongarch_lsx_vrotri_h:3953  case Intrinsic::loongarch_lsx_vsllwil_w_h:3954  case Intrinsic::loongarch_lsx_vsllwil_wu_hu:3955  case Intrinsic::loongarch_lsx_vsrlri_h:3956  case Intrinsic::loongarch_lsx_vsrari_h:3957  case Intrinsic::loongarch_lsx_vreplvei_b:3958  case Intrinsic::loongarch_lasx_xvsat_h:3959  case Intrinsic::loongarch_lasx_xvsat_hu:3960  case Intrinsic::loongarch_lasx_xvrotri_h:3961  case Intrinsic::loongarch_lasx_xvsllwil_w_h:3962  case Intrinsic::loongarch_lasx_xvsllwil_wu_hu:3963  case Intrinsic::loongarch_lasx_xvsrlri_h:3964  case Intrinsic::loongarch_lasx_xvsrari_h:3965  case Intrinsic::loongarch_lasx_xvrepl128vei_b:3966    return checkIntrinsicImmArg<4>(Op, 2, DAG);3967  case Intrinsic::loongarch_lsx_vsrlni_b_h:3968  case Intrinsic::loongarch_lsx_vsrani_b_h:3969  case Intrinsic::loongarch_lsx_vsrlrni_b_h:3970  case Intrinsic::loongarch_lsx_vsrarni_b_h:3971  case Intrinsic::loongarch_lsx_vssrlni_b_h:3972  case Intrinsic::loongarch_lsx_vssrani_b_h:3973  case Intrinsic::loongarch_lsx_vssrlni_bu_h:3974  case Intrinsic::loongarch_lsx_vssrani_bu_h:3975  case Intrinsic::loongarch_lsx_vssrlrni_b_h:3976  case Intrinsic::loongarch_lsx_vssrarni_b_h:3977  case Intrinsic::loongarch_lsx_vssrlrni_bu_h:3978  case Intrinsic::loongarch_lsx_vssrarni_bu_h:3979  case Intrinsic::loongarch_lasx_xvsrlni_b_h:3980  case Intrinsic::loongarch_lasx_xvsrani_b_h:3981  case Intrinsic::loongarch_lasx_xvsrlrni_b_h:3982  case Intrinsic::loongarch_lasx_xvsrarni_b_h:3983  case Intrinsic::loongarch_lasx_xvssrlni_b_h:3984  case Intrinsic::loongarch_lasx_xvssrani_b_h:3985  case Intrinsic::loongarch_lasx_xvssrlni_bu_h:3986  case Intrinsic::loongarch_lasx_xvssrani_bu_h:3987  case Intrinsic::loongarch_lasx_xvssrlrni_b_h:3988  case Intrinsic::loongarch_lasx_xvssrarni_b_h:3989  case Intrinsic::loongarch_lasx_xvssrlrni_bu_h:3990  case Intrinsic::loongarch_lasx_xvssrarni_bu_h:3991    return checkIntrinsicImmArg<4>(Op, 3, DAG);3992  case Intrinsic::loongarch_lsx_vsat_w:3993  case Intrinsic::loongarch_lsx_vsat_wu:3994  case Intrinsic::loongarch_lsx_vrotri_w:3995  case Intrinsic::loongarch_lsx_vsllwil_d_w:3996  case Intrinsic::loongarch_lsx_vsllwil_du_wu:3997  case Intrinsic::loongarch_lsx_vsrlri_w:3998  case Intrinsic::loongarch_lsx_vsrari_w:3999  case Intrinsic::loongarch_lsx_vslei_bu:4000  case Intrinsic::loongarch_lsx_vslei_hu:4001  case Intrinsic::loongarch_lsx_vslei_wu:4002  case Intrinsic::loongarch_lsx_vslei_du:4003  case Intrinsic::loongarch_lsx_vslti_bu:4004  case Intrinsic::loongarch_lsx_vslti_hu:4005  case Intrinsic::loongarch_lsx_vslti_wu:4006  case Intrinsic::loongarch_lsx_vslti_du:4007  case Intrinsic::loongarch_lsx_vbsll_v:4008  case Intrinsic::loongarch_lsx_vbsrl_v:4009  case Intrinsic::loongarch_lasx_xvsat_w:4010  case Intrinsic::loongarch_lasx_xvsat_wu:4011  case Intrinsic::loongarch_lasx_xvrotri_w:4012  case Intrinsic::loongarch_lasx_xvsllwil_d_w:4013  case Intrinsic::loongarch_lasx_xvsllwil_du_wu:4014  case Intrinsic::loongarch_lasx_xvsrlri_w:4015  case Intrinsic::loongarch_lasx_xvsrari_w:4016  case Intrinsic::loongarch_lasx_xvslei_bu:4017  case Intrinsic::loongarch_lasx_xvslei_hu:4018  case Intrinsic::loongarch_lasx_xvslei_wu:4019  case Intrinsic::loongarch_lasx_xvslei_du:4020  case Intrinsic::loongarch_lasx_xvslti_bu:4021  case Intrinsic::loongarch_lasx_xvslti_hu:4022  case Intrinsic::loongarch_lasx_xvslti_wu:4023  case Intrinsic::loongarch_lasx_xvslti_du:4024  case Intrinsic::loongarch_lasx_xvbsll_v:4025  case Intrinsic::loongarch_lasx_xvbsrl_v:4026    return checkIntrinsicImmArg<5>(Op, 2, DAG);4027  case Intrinsic::loongarch_lsx_vseqi_b:4028  case Intrinsic::loongarch_lsx_vseqi_h:4029  case Intrinsic::loongarch_lsx_vseqi_w:4030  case Intrinsic::loongarch_lsx_vseqi_d:4031  case Intrinsic::loongarch_lsx_vslei_b:4032  case Intrinsic::loongarch_lsx_vslei_h:4033  case Intrinsic::loongarch_lsx_vslei_w:4034  case Intrinsic::loongarch_lsx_vslei_d:4035  case Intrinsic::loongarch_lsx_vslti_b:4036  case Intrinsic::loongarch_lsx_vslti_h:4037  case Intrinsic::loongarch_lsx_vslti_w:4038  case Intrinsic::loongarch_lsx_vslti_d:4039  case Intrinsic::loongarch_lasx_xvseqi_b:4040  case Intrinsic::loongarch_lasx_xvseqi_h:4041  case Intrinsic::loongarch_lasx_xvseqi_w:4042  case Intrinsic::loongarch_lasx_xvseqi_d:4043  case Intrinsic::loongarch_lasx_xvslei_b:4044  case Intrinsic::loongarch_lasx_xvslei_h:4045  case Intrinsic::loongarch_lasx_xvslei_w:4046  case Intrinsic::loongarch_lasx_xvslei_d:4047  case Intrinsic::loongarch_lasx_xvslti_b:4048  case Intrinsic::loongarch_lasx_xvslti_h:4049  case Intrinsic::loongarch_lasx_xvslti_w:4050  case Intrinsic::loongarch_lasx_xvslti_d:4051    return checkIntrinsicImmArg<5>(Op, 2, DAG, /*IsSigned=*/true);4052  case Intrinsic::loongarch_lsx_vsrlni_h_w:4053  case Intrinsic::loongarch_lsx_vsrani_h_w:4054  case Intrinsic::loongarch_lsx_vsrlrni_h_w:4055  case Intrinsic::loongarch_lsx_vsrarni_h_w:4056  case Intrinsic::loongarch_lsx_vssrlni_h_w:4057  case Intrinsic::loongarch_lsx_vssrani_h_w:4058  case Intrinsic::loongarch_lsx_vssrlni_hu_w:4059  case Intrinsic::loongarch_lsx_vssrani_hu_w:4060  case Intrinsic::loongarch_lsx_vssrlrni_h_w:4061  case Intrinsic::loongarch_lsx_vssrarni_h_w:4062  case Intrinsic::loongarch_lsx_vssrlrni_hu_w:4063  case Intrinsic::loongarch_lsx_vssrarni_hu_w:4064  case Intrinsic::loongarch_lsx_vfrstpi_b:4065  case Intrinsic::loongarch_lsx_vfrstpi_h:4066  case Intrinsic::loongarch_lasx_xvsrlni_h_w:4067  case Intrinsic::loongarch_lasx_xvsrani_h_w:4068  case Intrinsic::loongarch_lasx_xvsrlrni_h_w:4069  case Intrinsic::loongarch_lasx_xvsrarni_h_w:4070  case Intrinsic::loongarch_lasx_xvssrlni_h_w:4071  case Intrinsic::loongarch_lasx_xvssrani_h_w:4072  case Intrinsic::loongarch_lasx_xvssrlni_hu_w:4073  case Intrinsic::loongarch_lasx_xvssrani_hu_w:4074  case Intrinsic::loongarch_lasx_xvssrlrni_h_w:4075  case Intrinsic::loongarch_lasx_xvssrarni_h_w:4076  case Intrinsic::loongarch_lasx_xvssrlrni_hu_w:4077  case Intrinsic::loongarch_lasx_xvssrarni_hu_w:4078  case Intrinsic::loongarch_lasx_xvfrstpi_b:4079  case Intrinsic::loongarch_lasx_xvfrstpi_h:4080    return checkIntrinsicImmArg<5>(Op, 3, DAG);4081  case Intrinsic::loongarch_lsx_vsat_d:4082  case Intrinsic::loongarch_lsx_vsat_du:4083  case Intrinsic::loongarch_lsx_vrotri_d:4084  case Intrinsic::loongarch_lsx_vsrlri_d:4085  case Intrinsic::loongarch_lsx_vsrari_d:4086  case Intrinsic::loongarch_lasx_xvsat_d:4087  case Intrinsic::loongarch_lasx_xvsat_du:4088  case Intrinsic::loongarch_lasx_xvrotri_d:4089  case Intrinsic::loongarch_lasx_xvsrlri_d:4090  case Intrinsic::loongarch_lasx_xvsrari_d:4091    return checkIntrinsicImmArg<6>(Op, 2, DAG);4092  case Intrinsic::loongarch_lsx_vsrlni_w_d:4093  case Intrinsic::loongarch_lsx_vsrani_w_d:4094  case Intrinsic::loongarch_lsx_vsrlrni_w_d:4095  case Intrinsic::loongarch_lsx_vsrarni_w_d:4096  case Intrinsic::loongarch_lsx_vssrlni_w_d:4097  case Intrinsic::loongarch_lsx_vssrani_w_d:4098  case Intrinsic::loongarch_lsx_vssrlni_wu_d:4099  case Intrinsic::loongarch_lsx_vssrani_wu_d:4100  case Intrinsic::loongarch_lsx_vssrlrni_w_d:4101  case Intrinsic::loongarch_lsx_vssrarni_w_d:4102  case Intrinsic::loongarch_lsx_vssrlrni_wu_d:4103  case Intrinsic::loongarch_lsx_vssrarni_wu_d:4104  case Intrinsic::loongarch_lasx_xvsrlni_w_d:4105  case Intrinsic::loongarch_lasx_xvsrani_w_d:4106  case Intrinsic::loongarch_lasx_xvsrlrni_w_d:4107  case Intrinsic::loongarch_lasx_xvsrarni_w_d:4108  case Intrinsic::loongarch_lasx_xvssrlni_w_d:4109  case Intrinsic::loongarch_lasx_xvssrani_w_d:4110  case Intrinsic::loongarch_lasx_xvssrlni_wu_d:4111  case Intrinsic::loongarch_lasx_xvssrani_wu_d:4112  case Intrinsic::loongarch_lasx_xvssrlrni_w_d:4113  case Intrinsic::loongarch_lasx_xvssrarni_w_d:4114  case Intrinsic::loongarch_lasx_xvssrlrni_wu_d:4115  case Intrinsic::loongarch_lasx_xvssrarni_wu_d:4116    return checkIntrinsicImmArg<6>(Op, 3, DAG);4117  case Intrinsic::loongarch_lsx_vsrlni_d_q:4118  case Intrinsic::loongarch_lsx_vsrani_d_q:4119  case Intrinsic::loongarch_lsx_vsrlrni_d_q:4120  case Intrinsic::loongarch_lsx_vsrarni_d_q:4121  case Intrinsic::loongarch_lsx_vssrlni_d_q:4122  case Intrinsic::loongarch_lsx_vssrani_d_q:4123  case Intrinsic::loongarch_lsx_vssrlni_du_q:4124  case Intrinsic::loongarch_lsx_vssrani_du_q:4125  case Intrinsic::loongarch_lsx_vssrlrni_d_q:4126  case Intrinsic::loongarch_lsx_vssrarni_d_q:4127  case Intrinsic::loongarch_lsx_vssrlrni_du_q:4128  case Intrinsic::loongarch_lsx_vssrarni_du_q:4129  case Intrinsic::loongarch_lasx_xvsrlni_d_q:4130  case Intrinsic::loongarch_lasx_xvsrani_d_q:4131  case Intrinsic::loongarch_lasx_xvsrlrni_d_q:4132  case Intrinsic::loongarch_lasx_xvsrarni_d_q:4133  case Intrinsic::loongarch_lasx_xvssrlni_d_q:4134  case Intrinsic::loongarch_lasx_xvssrani_d_q:4135  case Intrinsic::loongarch_lasx_xvssrlni_du_q:4136  case Intrinsic::loongarch_lasx_xvssrani_du_q:4137  case Intrinsic::loongarch_lasx_xvssrlrni_d_q:4138  case Intrinsic::loongarch_lasx_xvssrarni_d_q:4139  case Intrinsic::loongarch_lasx_xvssrlrni_du_q:4140  case Intrinsic::loongarch_lasx_xvssrarni_du_q:4141    return checkIntrinsicImmArg<7>(Op, 3, DAG);4142  case Intrinsic::loongarch_lsx_vnori_b:4143  case Intrinsic::loongarch_lsx_vshuf4i_b:4144  case Intrinsic::loongarch_lsx_vshuf4i_h:4145  case Intrinsic::loongarch_lsx_vshuf4i_w:4146  case Intrinsic::loongarch_lasx_xvnori_b:4147  case Intrinsic::loongarch_lasx_xvshuf4i_b:4148  case Intrinsic::loongarch_lasx_xvshuf4i_h:4149  case Intrinsic::loongarch_lasx_xvshuf4i_w:4150  case Intrinsic::loongarch_lasx_xvpermi_d:4151    return checkIntrinsicImmArg<8>(Op, 2, DAG);4152  case Intrinsic::loongarch_lsx_vshuf4i_d:4153  case Intrinsic::loongarch_lsx_vpermi_w:4154  case Intrinsic::loongarch_lsx_vbitseli_b:4155  case Intrinsic::loongarch_lsx_vextrins_b:4156  case Intrinsic::loongarch_lsx_vextrins_h:4157  case Intrinsic::loongarch_lsx_vextrins_w:4158  case Intrinsic::loongarch_lsx_vextrins_d:4159  case Intrinsic::loongarch_lasx_xvshuf4i_d:4160  case Intrinsic::loongarch_lasx_xvpermi_w:4161  case Intrinsic::loongarch_lasx_xvpermi_q:4162  case Intrinsic::loongarch_lasx_xvbitseli_b:4163  case Intrinsic::loongarch_lasx_xvextrins_b:4164  case Intrinsic::loongarch_lasx_xvextrins_h:4165  case Intrinsic::loongarch_lasx_xvextrins_w:4166  case Intrinsic::loongarch_lasx_xvextrins_d:4167    return checkIntrinsicImmArg<8>(Op, 3, DAG);4168  case Intrinsic::loongarch_lsx_vrepli_b:4169  case Intrinsic::loongarch_lsx_vrepli_h:4170  case Intrinsic::loongarch_lsx_vrepli_w:4171  case Intrinsic::loongarch_lsx_vrepli_d:4172  case Intrinsic::loongarch_lasx_xvrepli_b:4173  case Intrinsic::loongarch_lasx_xvrepli_h:4174  case Intrinsic::loongarch_lasx_xvrepli_w:4175  case Intrinsic::loongarch_lasx_xvrepli_d:4176    return checkIntrinsicImmArg<10>(Op, 1, DAG, /*IsSigned=*/true);4177  case Intrinsic::loongarch_lsx_vldi:4178  case Intrinsic::loongarch_lasx_xvldi:4179    return checkIntrinsicImmArg<13>(Op, 1, DAG, /*IsSigned=*/true);4180  }4181}4182 4183// Helper function that emits error message for intrinsics with chain and return4184// merge values of a UNDEF and the chain.4185static SDValue emitIntrinsicWithChainErrorMessage(SDValue Op,4186                                                  StringRef ErrorMsg,4187                                                  SelectionDAG &DAG) {4188  DAG.getContext()->emitError(Op->getOperationName(0) + ": " + ErrorMsg + ".");4189  return DAG.getMergeValues({DAG.getUNDEF(Op.getValueType()), Op.getOperand(0)},4190                            SDLoc(Op));4191}4192 4193SDValue4194LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,4195                                                SelectionDAG &DAG) const {4196  SDLoc DL(Op);4197  MVT GRLenVT = Subtarget.getGRLenVT();4198  EVT VT = Op.getValueType();4199  SDValue Chain = Op.getOperand(0);4200  const StringRef ErrorMsgOOR = "argument out of range";4201  const StringRef ErrorMsgReqLA64 = "requires loongarch64";4202  const StringRef ErrorMsgReqF = "requires basic 'f' target feature";4203 4204  switch (Op.getConstantOperandVal(1)) {4205  default:4206    return Op;4207  case Intrinsic::loongarch_crc_w_b_w:4208  case Intrinsic::loongarch_crc_w_h_w:4209  case Intrinsic::loongarch_crc_w_w_w:4210  case Intrinsic::loongarch_crc_w_d_w:4211  case Intrinsic::loongarch_crcc_w_b_w:4212  case Intrinsic::loongarch_crcc_w_h_w:4213  case Intrinsic::loongarch_crcc_w_w_w:4214  case Intrinsic::loongarch_crcc_w_d_w:4215    return emitIntrinsicWithChainErrorMessage(Op, ErrorMsgReqLA64, DAG);4216  case Intrinsic::loongarch_csrrd_w:4217  case Intrinsic::loongarch_csrrd_d: {4218    unsigned Imm = Op.getConstantOperandVal(2);4219    return !isUInt<14>(Imm)4220               ? emitIntrinsicWithChainErrorMessage(Op, ErrorMsgOOR, DAG)4221               : DAG.getNode(LoongArchISD::CSRRD, DL, {GRLenVT, MVT::Other},4222                             {Chain, DAG.getConstant(Imm, DL, GRLenVT)});4223  }4224  case Intrinsic::loongarch_csrwr_w:4225  case Intrinsic::loongarch_csrwr_d: {4226    unsigned Imm = Op.getConstantOperandVal(3);4227    return !isUInt<14>(Imm)4228               ? emitIntrinsicWithChainErrorMessage(Op, ErrorMsgOOR, DAG)4229               : DAG.getNode(LoongArchISD::CSRWR, DL, {GRLenVT, MVT::Other},4230                             {Chain, Op.getOperand(2),4231                              DAG.getConstant(Imm, DL, GRLenVT)});4232  }4233  case Intrinsic::loongarch_csrxchg_w:4234  case Intrinsic::loongarch_csrxchg_d: {4235    unsigned Imm = Op.getConstantOperandVal(4);4236    return !isUInt<14>(Imm)4237               ? emitIntrinsicWithChainErrorMessage(Op, ErrorMsgOOR, DAG)4238               : DAG.getNode(LoongArchISD::CSRXCHG, DL, {GRLenVT, MVT::Other},4239                             {Chain, Op.getOperand(2), Op.getOperand(3),4240                              DAG.getConstant(Imm, DL, GRLenVT)});4241  }4242  case Intrinsic::loongarch_iocsrrd_d: {4243    return DAG.getNode(4244        LoongArchISD::IOCSRRD_D, DL, {GRLenVT, MVT::Other},4245        {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op.getOperand(2))});4246  }4247#define IOCSRRD_CASE(NAME, NODE)                                               \4248  case Intrinsic::loongarch_##NAME: {                                          \4249    return DAG.getNode(LoongArchISD::NODE, DL, {GRLenVT, MVT::Other},          \4250                       {Chain, Op.getOperand(2)});                             \4251  }4252    IOCSRRD_CASE(iocsrrd_b, IOCSRRD_B);4253    IOCSRRD_CASE(iocsrrd_h, IOCSRRD_H);4254    IOCSRRD_CASE(iocsrrd_w, IOCSRRD_W);4255#undef IOCSRRD_CASE4256  case Intrinsic::loongarch_cpucfg: {4257    return DAG.getNode(LoongArchISD::CPUCFG, DL, {GRLenVT, MVT::Other},4258                       {Chain, Op.getOperand(2)});4259  }4260  case Intrinsic::loongarch_lddir_d: {4261    unsigned Imm = Op.getConstantOperandVal(3);4262    return !isUInt<8>(Imm)4263               ? emitIntrinsicWithChainErrorMessage(Op, ErrorMsgOOR, DAG)4264               : Op;4265  }4266  case Intrinsic::loongarch_movfcsr2gr: {4267    if (!Subtarget.hasBasicF())4268      return emitIntrinsicWithChainErrorMessage(Op, ErrorMsgReqF, DAG);4269    unsigned Imm = Op.getConstantOperandVal(2);4270    return !isUInt<2>(Imm)4271               ? emitIntrinsicWithChainErrorMessage(Op, ErrorMsgOOR, DAG)4272               : DAG.getNode(LoongArchISD::MOVFCSR2GR, DL, {VT, MVT::Other},4273                             {Chain, DAG.getConstant(Imm, DL, GRLenVT)});4274  }4275  case Intrinsic::loongarch_lsx_vld:4276  case Intrinsic::loongarch_lsx_vldrepl_b:4277  case Intrinsic::loongarch_lasx_xvld:4278  case Intrinsic::loongarch_lasx_xvldrepl_b:4279    return !isInt<12>(cast<ConstantSDNode>(Op.getOperand(3))->getSExtValue())4280               ? emitIntrinsicWithChainErrorMessage(Op, ErrorMsgOOR, DAG)4281               : SDValue();4282  case Intrinsic::loongarch_lsx_vldrepl_h:4283  case Intrinsic::loongarch_lasx_xvldrepl_h:4284    return !isShiftedInt<11, 1>(4285               cast<ConstantSDNode>(Op.getOperand(3))->getSExtValue())4286               ? emitIntrinsicWithChainErrorMessage(4287                     Op, "argument out of range or not a multiple of 2", DAG)4288               : SDValue();4289  case Intrinsic::loongarch_lsx_vldrepl_w:4290  case Intrinsic::loongarch_lasx_xvldrepl_w:4291    return !isShiftedInt<10, 2>(4292               cast<ConstantSDNode>(Op.getOperand(3))->getSExtValue())4293               ? emitIntrinsicWithChainErrorMessage(4294                     Op, "argument out of range or not a multiple of 4", DAG)4295               : SDValue();4296  case Intrinsic::loongarch_lsx_vldrepl_d:4297  case Intrinsic::loongarch_lasx_xvldrepl_d:4298    return !isShiftedInt<9, 3>(4299               cast<ConstantSDNode>(Op.getOperand(3))->getSExtValue())4300               ? emitIntrinsicWithChainErrorMessage(4301                     Op, "argument out of range or not a multiple of 8", DAG)4302               : SDValue();4303  }4304}4305 4306// Helper function that emits error message for intrinsics with void return4307// value and return the chain.4308static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef ErrorMsg,4309                                         SelectionDAG &DAG) {4310 4311  DAG.getContext()->emitError(Op->getOperationName(0) + ": " + ErrorMsg + ".");4312  return Op.getOperand(0);4313}4314 4315SDValue LoongArchTargetLowering::lowerINTRINSIC_VOID(SDValue Op,4316                                                     SelectionDAG &DAG) const {4317  SDLoc DL(Op);4318  MVT GRLenVT = Subtarget.getGRLenVT();4319  SDValue Chain = Op.getOperand(0);4320  uint64_t IntrinsicEnum = Op.getConstantOperandVal(1);4321  SDValue Op2 = Op.getOperand(2);4322  const StringRef ErrorMsgOOR = "argument out of range";4323  const StringRef ErrorMsgReqLA64 = "requires loongarch64";4324  const StringRef ErrorMsgReqLA32 = "requires loongarch32";4325  const StringRef ErrorMsgReqF = "requires basic 'f' target feature";4326 4327  switch (IntrinsicEnum) {4328  default:4329    // TODO: Add more Intrinsics.4330    return SDValue();4331  case Intrinsic::loongarch_cacop_d:4332  case Intrinsic::loongarch_cacop_w: {4333    if (IntrinsicEnum == Intrinsic::loongarch_cacop_d && !Subtarget.is64Bit())4334      return emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG);4335    if (IntrinsicEnum == Intrinsic::loongarch_cacop_w && Subtarget.is64Bit())4336      return emitIntrinsicErrorMessage(Op, ErrorMsgReqLA32, DAG);4337    // call void @llvm.loongarch.cacop.[d/w](uimm5, rj, simm12)4338    unsigned Imm1 = Op2->getAsZExtVal();4339    int Imm2 = cast<ConstantSDNode>(Op.getOperand(4))->getSExtValue();4340    if (!isUInt<5>(Imm1) || !isInt<12>(Imm2))4341      return emitIntrinsicErrorMessage(Op, ErrorMsgOOR, DAG);4342    return Op;4343  }4344  case Intrinsic::loongarch_dbar: {4345    unsigned Imm = Op2->getAsZExtVal();4346    return !isUInt<15>(Imm)4347               ? emitIntrinsicErrorMessage(Op, ErrorMsgOOR, DAG)4348               : DAG.getNode(LoongArchISD::DBAR, DL, MVT::Other, Chain,4349                             DAG.getConstant(Imm, DL, GRLenVT));4350  }4351  case Intrinsic::loongarch_ibar: {4352    unsigned Imm = Op2->getAsZExtVal();4353    return !isUInt<15>(Imm)4354               ? emitIntrinsicErrorMessage(Op, ErrorMsgOOR, DAG)4355               : DAG.getNode(LoongArchISD::IBAR, DL, MVT::Other, Chain,4356                             DAG.getConstant(Imm, DL, GRLenVT));4357  }4358  case Intrinsic::loongarch_break: {4359    unsigned Imm = Op2->getAsZExtVal();4360    return !isUInt<15>(Imm)4361               ? emitIntrinsicErrorMessage(Op, ErrorMsgOOR, DAG)4362               : DAG.getNode(LoongArchISD::BREAK, DL, MVT::Other, Chain,4363                             DAG.getConstant(Imm, DL, GRLenVT));4364  }4365  case Intrinsic::loongarch_movgr2fcsr: {4366    if (!Subtarget.hasBasicF())4367      return emitIntrinsicErrorMessage(Op, ErrorMsgReqF, DAG);4368    unsigned Imm = Op2->getAsZExtVal();4369    return !isUInt<2>(Imm)4370               ? emitIntrinsicErrorMessage(Op, ErrorMsgOOR, DAG)4371               : DAG.getNode(LoongArchISD::MOVGR2FCSR, DL, MVT::Other, Chain,4372                             DAG.getConstant(Imm, DL, GRLenVT),4373                             DAG.getNode(ISD::ANY_EXTEND, DL, GRLenVT,4374                                         Op.getOperand(3)));4375  }4376  case Intrinsic::loongarch_syscall: {4377    unsigned Imm = Op2->getAsZExtVal();4378    return !isUInt<15>(Imm)4379               ? emitIntrinsicErrorMessage(Op, ErrorMsgOOR, DAG)4380               : DAG.getNode(LoongArchISD::SYSCALL, DL, MVT::Other, Chain,4381                             DAG.getConstant(Imm, DL, GRLenVT));4382  }4383#define IOCSRWR_CASE(NAME, NODE)                                               \4384  case Intrinsic::loongarch_##NAME: {                                          \4385    SDValue Op3 = Op.getOperand(3);                                            \4386    return Subtarget.is64Bit()                                                 \4387               ? DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain,        \4388                             DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2),  \4389                             DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op3))  \4390               : DAG.getNode(LoongArchISD::NODE, DL, MVT::Other, Chain, Op2,   \4391                             Op3);                                             \4392  }4393    IOCSRWR_CASE(iocsrwr_b, IOCSRWR_B);4394    IOCSRWR_CASE(iocsrwr_h, IOCSRWR_H);4395    IOCSRWR_CASE(iocsrwr_w, IOCSRWR_W);4396#undef IOCSRWR_CASE4397  case Intrinsic::loongarch_iocsrwr_d: {4398    return !Subtarget.is64Bit()4399               ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG)4400               : DAG.getNode(LoongArchISD::IOCSRWR_D, DL, MVT::Other, Chain,4401                             Op2,4402                             DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64,4403                                         Op.getOperand(3)));4404  }4405#define ASRT_LE_GT_CASE(NAME)                                                  \4406  case Intrinsic::loongarch_##NAME: {                                          \4407    return !Subtarget.is64Bit()                                                \4408               ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG)           \4409               : Op;                                                           \4410  }4411    ASRT_LE_GT_CASE(asrtle_d)4412    ASRT_LE_GT_CASE(asrtgt_d)4413#undef ASRT_LE_GT_CASE4414  case Intrinsic::loongarch_ldpte_d: {4415    unsigned Imm = Op.getConstantOperandVal(3);4416    return !Subtarget.is64Bit()4417               ? emitIntrinsicErrorMessage(Op, ErrorMsgReqLA64, DAG)4418           : !isUInt<8>(Imm) ? emitIntrinsicErrorMessage(Op, ErrorMsgOOR, DAG)4419                             : Op;4420  }4421  case Intrinsic::loongarch_lsx_vst:4422  case Intrinsic::loongarch_lasx_xvst:4423    return !isInt<12>(cast<ConstantSDNode>(Op.getOperand(4))->getSExtValue())4424               ? emitIntrinsicErrorMessage(Op, ErrorMsgOOR, DAG)4425               : SDValue();4426  case Intrinsic::loongarch_lasx_xvstelm_b:4427    return (!isInt<8>(cast<ConstantSDNode>(Op.getOperand(4))->getSExtValue()) ||4428            !isUInt<5>(Op.getConstantOperandVal(5)))4429               ? emitIntrinsicErrorMessage(Op, ErrorMsgOOR, DAG)4430               : SDValue();4431  case Intrinsic::loongarch_lsx_vstelm_b:4432    return (!isInt<8>(cast<ConstantSDNode>(Op.getOperand(4))->getSExtValue()) ||4433            !isUInt<4>(Op.getConstantOperandVal(5)))4434               ? emitIntrinsicErrorMessage(Op, ErrorMsgOOR, DAG)4435               : SDValue();4436  case Intrinsic::loongarch_lasx_xvstelm_h:4437    return (!isShiftedInt<8, 1>(4438                cast<ConstantSDNode>(Op.getOperand(4))->getSExtValue()) ||4439            !isUInt<4>(Op.getConstantOperandVal(5)))4440               ? emitIntrinsicErrorMessage(4441                     Op, "argument out of range or not a multiple of 2", DAG)4442               : SDValue();4443  case Intrinsic::loongarch_lsx_vstelm_h:4444    return (!isShiftedInt<8, 1>(4445                cast<ConstantSDNode>(Op.getOperand(4))->getSExtValue()) ||4446            !isUInt<3>(Op.getConstantOperandVal(5)))4447               ? emitIntrinsicErrorMessage(4448                     Op, "argument out of range or not a multiple of 2", DAG)4449               : SDValue();4450  case Intrinsic::loongarch_lasx_xvstelm_w:4451    return (!isShiftedInt<8, 2>(4452                cast<ConstantSDNode>(Op.getOperand(4))->getSExtValue()) ||4453            !isUInt<3>(Op.getConstantOperandVal(5)))4454               ? emitIntrinsicErrorMessage(4455                     Op, "argument out of range or not a multiple of 4", DAG)4456               : SDValue();4457  case Intrinsic::loongarch_lsx_vstelm_w:4458    return (!isShiftedInt<8, 2>(4459                cast<ConstantSDNode>(Op.getOperand(4))->getSExtValue()) ||4460            !isUInt<2>(Op.getConstantOperandVal(5)))4461               ? emitIntrinsicErrorMessage(4462                     Op, "argument out of range or not a multiple of 4", DAG)4463               : SDValue();4464  case Intrinsic::loongarch_lasx_xvstelm_d:4465    return (!isShiftedInt<8, 3>(4466                cast<ConstantSDNode>(Op.getOperand(4))->getSExtValue()) ||4467            !isUInt<2>(Op.getConstantOperandVal(5)))4468               ? emitIntrinsicErrorMessage(4469                     Op, "argument out of range or not a multiple of 8", DAG)4470               : SDValue();4471  case Intrinsic::loongarch_lsx_vstelm_d:4472    return (!isShiftedInt<8, 3>(4473                cast<ConstantSDNode>(Op.getOperand(4))->getSExtValue()) ||4474            !isUInt<1>(Op.getConstantOperandVal(5)))4475               ? emitIntrinsicErrorMessage(4476                     Op, "argument out of range or not a multiple of 8", DAG)4477               : SDValue();4478  }4479}4480 4481SDValue LoongArchTargetLowering::lowerShiftLeftParts(SDValue Op,4482                                                     SelectionDAG &DAG) const {4483  SDLoc DL(Op);4484  SDValue Lo = Op.getOperand(0);4485  SDValue Hi = Op.getOperand(1);4486  SDValue Shamt = Op.getOperand(2);4487  EVT VT = Lo.getValueType();4488 4489  // if Shamt-GRLen < 0: // Shamt < GRLen4490  //   Lo = Lo << Shamt4491  //   Hi = (Hi << Shamt) | ((Lo >>u 1) >>u (GRLen-1 ^ Shamt))4492  // else:4493  //   Lo = 04494  //   Hi = Lo << (Shamt-GRLen)4495 4496  SDValue Zero = DAG.getConstant(0, DL, VT);4497  SDValue One = DAG.getConstant(1, DL, VT);4498  SDValue MinusGRLen =4499      DAG.getSignedConstant(-(int)Subtarget.getGRLen(), DL, VT);4500  SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT);4501  SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen);4502  SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1);4503 4504  SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt);4505  SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, One);4506  SDValue ShiftRightLo =4507      DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, GRLenMinus1Shamt);4508  SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt);4509  SDValue HiTrue = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo);4510  SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusGRLen);4511 4512  SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT);4513 4514  Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, Zero);4515  Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse);4516 4517  SDValue Parts[2] = {Lo, Hi};4518  return DAG.getMergeValues(Parts, DL);4519}4520 4521SDValue LoongArchTargetLowering::lowerShiftRightParts(SDValue Op,4522                                                      SelectionDAG &DAG,4523                                                      bool IsSRA) const {4524  SDLoc DL(Op);4525  SDValue Lo = Op.getOperand(0);4526  SDValue Hi = Op.getOperand(1);4527  SDValue Shamt = Op.getOperand(2);4528  EVT VT = Lo.getValueType();4529 4530  // SRA expansion:4531  //   if Shamt-GRLen < 0: // Shamt < GRLen4532  //     Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1))4533  //     Hi = Hi >>s Shamt4534  //   else:4535  //     Lo = Hi >>s (Shamt-GRLen);4536  //     Hi = Hi >>s (GRLen-1)4537  //4538  // SRL expansion:4539  //   if Shamt-GRLen < 0: // Shamt < GRLen4540  //     Lo = (Lo >>u Shamt) | ((Hi << 1) << (ShAmt ^ GRLen-1))4541  //     Hi = Hi >>u Shamt4542  //   else:4543  //     Lo = Hi >>u (Shamt-GRLen);4544  //     Hi = 0;4545 4546  unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL;4547 4548  SDValue Zero = DAG.getConstant(0, DL, VT);4549  SDValue One = DAG.getConstant(1, DL, VT);4550  SDValue MinusGRLen =4551      DAG.getSignedConstant(-(int)Subtarget.getGRLen(), DL, VT);4552  SDValue GRLenMinus1 = DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT);4553  SDValue ShamtMinusGRLen = DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusGRLen);4554  SDValue GRLenMinus1Shamt = DAG.getNode(ISD::XOR, DL, VT, Shamt, GRLenMinus1);4555 4556  SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt);4557  SDValue ShiftLeftHi1 = DAG.getNode(ISD::SHL, DL, VT, Hi, One);4558  SDValue ShiftLeftHi =4559      DAG.getNode(ISD::SHL, DL, VT, ShiftLeftHi1, GRLenMinus1Shamt);4560  SDValue LoTrue = DAG.getNode(ISD::OR, DL, VT, ShiftRightLo, ShiftLeftHi);4561  SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt);4562  SDValue LoFalse = DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusGRLen);4563  SDValue HiFalse =4564      IsSRA ? DAG.getNode(ISD::SRA, DL, VT, Hi, GRLenMinus1) : Zero;4565 4566  SDValue CC = DAG.getSetCC(DL, VT, ShamtMinusGRLen, Zero, ISD::SETLT);4567 4568  Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, LoFalse);4569  Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse);4570 4571  SDValue Parts[2] = {Lo, Hi};4572  return DAG.getMergeValues(Parts, DL);4573}4574 4575// Returns the opcode of the target-specific SDNode that implements the 32-bit4576// form of the given Opcode.4577static unsigned getLoongArchWOpcode(unsigned Opcode) {4578  switch (Opcode) {4579  default:4580    llvm_unreachable("Unexpected opcode");4581  case ISD::SDIV:4582    return LoongArchISD::DIV_W;4583  case ISD::UDIV:4584    return LoongArchISD::DIV_WU;4585  case ISD::SREM:4586    return LoongArchISD::MOD_W;4587  case ISD::UREM:4588    return LoongArchISD::MOD_WU;4589  case ISD::SHL:4590    return LoongArchISD::SLL_W;4591  case ISD::SRA:4592    return LoongArchISD::SRA_W;4593  case ISD::SRL:4594    return LoongArchISD::SRL_W;4595  case ISD::ROTL:4596  case ISD::ROTR:4597    return LoongArchISD::ROTR_W;4598  case ISD::CTTZ:4599    return LoongArchISD::CTZ_W;4600  case ISD::CTLZ:4601    return LoongArchISD::CLZ_W;4602  }4603}4604 4605// Converts the given i8/i16/i32 operation to a target-specific SelectionDAG4606// node. Because i8/i16/i32 isn't a legal type for LA64, these operations would4607// otherwise be promoted to i64, making it difficult to select the4608// SLL_W/.../*W later one because the fact the operation was originally of4609// type i8/i16/i32 is lost.4610static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp,4611                                   unsigned ExtOpc = ISD::ANY_EXTEND) {4612  SDLoc DL(N);4613  unsigned WOpcode = getLoongArchWOpcode(N->getOpcode());4614  SDValue NewOp0, NewRes;4615 4616  switch (NumOp) {4617  default:4618    llvm_unreachable("Unexpected NumOp");4619  case 1: {4620    NewOp0 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(0));4621    NewRes = DAG.getNode(WOpcode, DL, MVT::i64, NewOp0);4622    break;4623  }4624  case 2: {4625    NewOp0 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(0));4626    SDValue NewOp1 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(1));4627    if (N->getOpcode() == ISD::ROTL) {4628      SDValue TmpOp = DAG.getConstant(32, DL, MVT::i64);4629      NewOp1 = DAG.getNode(ISD::SUB, DL, MVT::i64, TmpOp, NewOp1);4630    }4631    NewRes = DAG.getNode(WOpcode, DL, MVT::i64, NewOp0, NewOp1);4632    break;4633  }4634    // TODO:Handle more NumOp.4635  }4636 4637  // ReplaceNodeResults requires we maintain the same type for the return4638  // value.4639  return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewRes);4640}4641 4642// Converts the given 32-bit operation to a i64 operation with signed extension4643// semantic to reduce the signed extension instructions.4644static SDValue customLegalizeToWOpWithSExt(SDNode *N, SelectionDAG &DAG) {4645  SDLoc DL(N);4646  SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(0));4647  SDValue NewOp1 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(1));4648  SDValue NewWOp = DAG.getNode(N->getOpcode(), DL, MVT::i64, NewOp0, NewOp1);4649  SDValue NewRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, NewWOp,4650                               DAG.getValueType(MVT::i32));4651  return DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, NewRes);4652}4653 4654// Helper function that emits error message for intrinsics with/without chain4655// and return a UNDEF or and the chain as the results.4656static void emitErrorAndReplaceIntrinsicResults(4657    SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG,4658    StringRef ErrorMsg, bool WithChain = true) {4659  DAG.getContext()->emitError(N->getOperationName(0) + ": " + ErrorMsg + ".");4660  Results.push_back(DAG.getUNDEF(N->getValueType(0)));4661  if (!WithChain)4662    return;4663  Results.push_back(N->getOperand(0));4664}4665 4666template <unsigned N>4667static void4668replaceVPICKVE2GRResults(SDNode *Node, SmallVectorImpl<SDValue> &Results,4669                         SelectionDAG &DAG, const LoongArchSubtarget &Subtarget,4670                         unsigned ResOp) {4671  const StringRef ErrorMsgOOR = "argument out of range";4672  unsigned Imm = Node->getConstantOperandVal(2);4673  if (!isUInt<N>(Imm)) {4674    emitErrorAndReplaceIntrinsicResults(Node, Results, DAG, ErrorMsgOOR,4675                                        /*WithChain=*/false);4676    return;4677  }4678  SDLoc DL(Node);4679  SDValue Vec = Node->getOperand(1);4680 4681  SDValue PickElt =4682      DAG.getNode(ResOp, DL, Subtarget.getGRLenVT(), Vec,4683                  DAG.getConstant(Imm, DL, Subtarget.getGRLenVT()),4684                  DAG.getValueType(Vec.getValueType().getVectorElementType()));4685  Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, Node->getValueType(0),4686                                PickElt.getValue(0)));4687}4688 4689static void replaceVecCondBranchResults(SDNode *N,4690                                        SmallVectorImpl<SDValue> &Results,4691                                        SelectionDAG &DAG,4692                                        const LoongArchSubtarget &Subtarget,4693                                        unsigned ResOp) {4694  SDLoc DL(N);4695  SDValue Vec = N->getOperand(1);4696 4697  SDValue CB = DAG.getNode(ResOp, DL, Subtarget.getGRLenVT(), Vec);4698  Results.push_back(4699      DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), CB.getValue(0)));4700}4701 4702static void4703replaceINTRINSIC_WO_CHAINResults(SDNode *N, SmallVectorImpl<SDValue> &Results,4704                                 SelectionDAG &DAG,4705                                 const LoongArchSubtarget &Subtarget) {4706  switch (N->getConstantOperandVal(0)) {4707  default:4708    llvm_unreachable("Unexpected Intrinsic.");4709  case Intrinsic::loongarch_lsx_vpickve2gr_b:4710    replaceVPICKVE2GRResults<4>(N, Results, DAG, Subtarget,4711                                LoongArchISD::VPICK_SEXT_ELT);4712    break;4713  case Intrinsic::loongarch_lsx_vpickve2gr_h:4714  case Intrinsic::loongarch_lasx_xvpickve2gr_w:4715    replaceVPICKVE2GRResults<3>(N, Results, DAG, Subtarget,4716                                LoongArchISD::VPICK_SEXT_ELT);4717    break;4718  case Intrinsic::loongarch_lsx_vpickve2gr_w:4719    replaceVPICKVE2GRResults<2>(N, Results, DAG, Subtarget,4720                                LoongArchISD::VPICK_SEXT_ELT);4721    break;4722  case Intrinsic::loongarch_lsx_vpickve2gr_bu:4723    replaceVPICKVE2GRResults<4>(N, Results, DAG, Subtarget,4724                                LoongArchISD::VPICK_ZEXT_ELT);4725    break;4726  case Intrinsic::loongarch_lsx_vpickve2gr_hu:4727  case Intrinsic::loongarch_lasx_xvpickve2gr_wu:4728    replaceVPICKVE2GRResults<3>(N, Results, DAG, Subtarget,4729                                LoongArchISD::VPICK_ZEXT_ELT);4730    break;4731  case Intrinsic::loongarch_lsx_vpickve2gr_wu:4732    replaceVPICKVE2GRResults<2>(N, Results, DAG, Subtarget,4733                                LoongArchISD::VPICK_ZEXT_ELT);4734    break;4735  case Intrinsic::loongarch_lsx_bz_b:4736  case Intrinsic::loongarch_lsx_bz_h:4737  case Intrinsic::loongarch_lsx_bz_w:4738  case Intrinsic::loongarch_lsx_bz_d:4739  case Intrinsic::loongarch_lasx_xbz_b:4740  case Intrinsic::loongarch_lasx_xbz_h:4741  case Intrinsic::loongarch_lasx_xbz_w:4742  case Intrinsic::loongarch_lasx_xbz_d:4743    replaceVecCondBranchResults(N, Results, DAG, Subtarget,4744                                LoongArchISD::VALL_ZERO);4745    break;4746  case Intrinsic::loongarch_lsx_bz_v:4747  case Intrinsic::loongarch_lasx_xbz_v:4748    replaceVecCondBranchResults(N, Results, DAG, Subtarget,4749                                LoongArchISD::VANY_ZERO);4750    break;4751  case Intrinsic::loongarch_lsx_bnz_b:4752  case Intrinsic::loongarch_lsx_bnz_h:4753  case Intrinsic::loongarch_lsx_bnz_w:4754  case Intrinsic::loongarch_lsx_bnz_d:4755  case Intrinsic::loongarch_lasx_xbnz_b:4756  case Intrinsic::loongarch_lasx_xbnz_h:4757  case Intrinsic::loongarch_lasx_xbnz_w:4758  case Intrinsic::loongarch_lasx_xbnz_d:4759    replaceVecCondBranchResults(N, Results, DAG, Subtarget,4760                                LoongArchISD::VALL_NONZERO);4761    break;4762  case Intrinsic::loongarch_lsx_bnz_v:4763  case Intrinsic::loongarch_lasx_xbnz_v:4764    replaceVecCondBranchResults(N, Results, DAG, Subtarget,4765                                LoongArchISD::VANY_NONZERO);4766    break;4767  }4768}4769 4770static void replaceCMP_XCHG_128Results(SDNode *N,4771                                       SmallVectorImpl<SDValue> &Results,4772                                       SelectionDAG &DAG) {4773  assert(N->getValueType(0) == MVT::i128 &&4774         "AtomicCmpSwap on types less than 128 should be legal");4775  MachineMemOperand *MemOp = cast<MemSDNode>(N)->getMemOperand();4776 4777  unsigned Opcode;4778  switch (MemOp->getMergedOrdering()) {4779  case AtomicOrdering::Acquire:4780  case AtomicOrdering::AcquireRelease:4781  case AtomicOrdering::SequentiallyConsistent:4782    Opcode = LoongArch::PseudoCmpXchg128Acquire;4783    break;4784  case AtomicOrdering::Monotonic:4785  case AtomicOrdering::Release:4786    Opcode = LoongArch::PseudoCmpXchg128;4787    break;4788  default:4789    llvm_unreachable("Unexpected ordering!");4790  }4791 4792  SDLoc DL(N);4793  auto CmpVal = DAG.SplitScalar(N->getOperand(2), DL, MVT::i64, MVT::i64);4794  auto NewVal = DAG.SplitScalar(N->getOperand(3), DL, MVT::i64, MVT::i64);4795  SDValue Ops[] = {N->getOperand(1), CmpVal.first,  CmpVal.second,4796                   NewVal.first,     NewVal.second, N->getOperand(0)};4797 4798  SDNode *CmpSwap = DAG.getMachineNode(4799      Opcode, SDLoc(N), DAG.getVTList(MVT::i64, MVT::i64, MVT::i64, MVT::Other),4800      Ops);4801  DAG.setNodeMemRefs(cast<MachineSDNode>(CmpSwap), {MemOp});4802  Results.push_back(DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i128,4803                                SDValue(CmpSwap, 0), SDValue(CmpSwap, 1)));4804  Results.push_back(SDValue(CmpSwap, 3));4805}4806 4807void LoongArchTargetLowering::ReplaceNodeResults(4808    SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const {4809  SDLoc DL(N);4810  EVT VT = N->getValueType(0);4811  switch (N->getOpcode()) {4812  default:4813    llvm_unreachable("Don't know how to legalize this operation");4814  case ISD::ADD:4815  case ISD::SUB:4816    assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&4817           "Unexpected custom legalisation");4818    Results.push_back(customLegalizeToWOpWithSExt(N, DAG));4819    break;4820  case ISD::SDIV:4821  case ISD::UDIV:4822  case ISD::SREM:4823  case ISD::UREM:4824    assert(VT == MVT::i32 && Subtarget.is64Bit() &&4825           "Unexpected custom legalisation");4826    Results.push_back(customLegalizeToWOp(N, DAG, 2,4827                                          Subtarget.hasDiv32() && VT == MVT::i324828                                              ? ISD::ANY_EXTEND4829                                              : ISD::SIGN_EXTEND));4830    break;4831  case ISD::SHL:4832  case ISD::SRA:4833  case ISD::SRL:4834    assert(VT == MVT::i32 && Subtarget.is64Bit() &&4835           "Unexpected custom legalisation");4836    if (N->getOperand(1).getOpcode() != ISD::Constant) {4837      Results.push_back(customLegalizeToWOp(N, DAG, 2));4838      break;4839    }4840    break;4841  case ISD::ROTL:4842  case ISD::ROTR:4843    assert(VT == MVT::i32 && Subtarget.is64Bit() &&4844           "Unexpected custom legalisation");4845    Results.push_back(customLegalizeToWOp(N, DAG, 2));4846    break;4847  case ISD::FP_TO_SINT: {4848    assert(VT == MVT::i32 && Subtarget.is64Bit() &&4849           "Unexpected custom legalisation");4850    SDValue Src = N->getOperand(0);4851    EVT FVT = EVT::getFloatingPointVT(N->getValueSizeInBits(0));4852    if (getTypeAction(*DAG.getContext(), Src.getValueType()) !=4853        TargetLowering::TypeSoftenFloat) {4854      if (!isTypeLegal(Src.getValueType()))4855        return;4856      if (Src.getValueType() == MVT::f16)4857        Src = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Src);4858      SDValue Dst = DAG.getNode(LoongArchISD::FTINT, DL, FVT, Src);4859      Results.push_back(DAG.getNode(ISD::BITCAST, DL, VT, Dst));4860      return;4861    }4862    // If the FP type needs to be softened, emit a library call using the 'si'4863    // version. If we left it to default legalization we'd end up with 'di'.4864    RTLIB::Libcall LC;4865    LC = RTLIB::getFPTOSINT(Src.getValueType(), VT);4866    MakeLibCallOptions CallOptions;4867    EVT OpVT = Src.getValueType();4868    CallOptions.setTypeListBeforeSoften(OpVT, VT);4869    SDValue Chain = SDValue();4870    SDValue Result;4871    std::tie(Result, Chain) =4872        makeLibCall(DAG, LC, VT, Src, CallOptions, DL, Chain);4873    Results.push_back(Result);4874    break;4875  }4876  case ISD::BITCAST: {4877    SDValue Src = N->getOperand(0);4878    EVT SrcVT = Src.getValueType();4879    if (VT == MVT::i32 && SrcVT == MVT::f32 && Subtarget.is64Bit() &&4880        Subtarget.hasBasicF()) {4881      SDValue Dst =4882          DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Src);4883      Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Dst));4884    } else if (VT == MVT::i64 && SrcVT == MVT::f64 && !Subtarget.is64Bit()) {4885      SDValue NewReg = DAG.getNode(LoongArchISD::SPLIT_PAIR_F64, DL,4886                                   DAG.getVTList(MVT::i32, MVT::i32), Src);4887      SDValue RetReg = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64,4888                                   NewReg.getValue(0), NewReg.getValue(1));4889      Results.push_back(RetReg);4890    }4891    break;4892  }4893  case ISD::FP_TO_UINT: {4894    assert(VT == MVT::i32 && Subtarget.is64Bit() &&4895           "Unexpected custom legalisation");4896    auto &TLI = DAG.getTargetLoweringInfo();4897    SDValue Tmp1, Tmp2;4898    TLI.expandFP_TO_UINT(N, Tmp1, Tmp2, DAG);4899    Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Tmp1));4900    break;4901  }4902  case ISD::BSWAP: {4903    SDValue Src = N->getOperand(0);4904    assert((VT == MVT::i16 || VT == MVT::i32) &&4905           "Unexpected custom legalization");4906    MVT GRLenVT = Subtarget.getGRLenVT();4907    SDValue NewSrc = DAG.getNode(ISD::ANY_EXTEND, DL, GRLenVT, Src);4908    SDValue Tmp;4909    switch (VT.getSizeInBits()) {4910    default:4911      llvm_unreachable("Unexpected operand width");4912    case 16:4913      Tmp = DAG.getNode(LoongArchISD::REVB_2H, DL, GRLenVT, NewSrc);4914      break;4915    case 32:4916      // Only LA64 will get to here due to the size mismatch between VT and4917      // GRLenVT, LA32 lowering is directly defined in LoongArchInstrInfo.4918      Tmp = DAG.getNode(LoongArchISD::REVB_2W, DL, GRLenVT, NewSrc);4919      break;4920    }4921    Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, Tmp));4922    break;4923  }4924  case ISD::BITREVERSE: {4925    SDValue Src = N->getOperand(0);4926    assert((VT == MVT::i8 || (VT == MVT::i32 && Subtarget.is64Bit())) &&4927           "Unexpected custom legalization");4928    MVT GRLenVT = Subtarget.getGRLenVT();4929    SDValue NewSrc = DAG.getNode(ISD::ANY_EXTEND, DL, GRLenVT, Src);4930    SDValue Tmp;4931    switch (VT.getSizeInBits()) {4932    default:4933      llvm_unreachable("Unexpected operand width");4934    case 8:4935      Tmp = DAG.getNode(LoongArchISD::BITREV_4B, DL, GRLenVT, NewSrc);4936      break;4937    case 32:4938      Tmp = DAG.getNode(LoongArchISD::BITREV_W, DL, GRLenVT, NewSrc);4939      break;4940    }4941    Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, Tmp));4942    break;4943  }4944  case ISD::CTLZ:4945  case ISD::CTTZ: {4946    assert(VT == MVT::i32 && Subtarget.is64Bit() &&4947           "Unexpected custom legalisation");4948    Results.push_back(customLegalizeToWOp(N, DAG, 1));4949    break;4950  }4951  case ISD::INTRINSIC_W_CHAIN: {4952    SDValue Chain = N->getOperand(0);4953    SDValue Op2 = N->getOperand(2);4954    MVT GRLenVT = Subtarget.getGRLenVT();4955    const StringRef ErrorMsgOOR = "argument out of range";4956    const StringRef ErrorMsgReqLA64 = "requires loongarch64";4957    const StringRef ErrorMsgReqF = "requires basic 'f' target feature";4958 4959    switch (N->getConstantOperandVal(1)) {4960    default:4961      llvm_unreachable("Unexpected Intrinsic.");4962    case Intrinsic::loongarch_movfcsr2gr: {4963      if (!Subtarget.hasBasicF()) {4964        emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqF);4965        return;4966      }4967      unsigned Imm = Op2->getAsZExtVal();4968      if (!isUInt<2>(Imm)) {4969        emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgOOR);4970        return;4971      }4972      SDValue MOVFCSR2GRResults = DAG.getNode(4973          LoongArchISD::MOVFCSR2GR, SDLoc(N), {MVT::i64, MVT::Other},4974          {Chain, DAG.getConstant(Imm, DL, GRLenVT)});4975      Results.push_back(4976          DAG.getNode(ISD::TRUNCATE, DL, VT, MOVFCSR2GRResults.getValue(0)));4977      Results.push_back(MOVFCSR2GRResults.getValue(1));4978      break;4979    }4980#define CRC_CASE_EXT_BINARYOP(NAME, NODE)                                      \4981  case Intrinsic::loongarch_##NAME: {                                          \4982    SDValue NODE = DAG.getNode(                                                \4983        LoongArchISD::NODE, DL, {MVT::i64, MVT::Other},                        \4984        {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2),               \4985         DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))});       \4986    Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0)));   \4987    Results.push_back(NODE.getValue(1));                                       \4988    break;                                                                     \4989  }4990      CRC_CASE_EXT_BINARYOP(crc_w_b_w, CRC_W_B_W)4991      CRC_CASE_EXT_BINARYOP(crc_w_h_w, CRC_W_H_W)4992      CRC_CASE_EXT_BINARYOP(crc_w_w_w, CRC_W_W_W)4993      CRC_CASE_EXT_BINARYOP(crcc_w_b_w, CRCC_W_B_W)4994      CRC_CASE_EXT_BINARYOP(crcc_w_h_w, CRCC_W_H_W)4995      CRC_CASE_EXT_BINARYOP(crcc_w_w_w, CRCC_W_W_W)4996#undef CRC_CASE_EXT_BINARYOP4997 4998#define CRC_CASE_EXT_UNARYOP(NAME, NODE)                                       \4999  case Intrinsic::loongarch_##NAME: {                                          \5000    SDValue NODE = DAG.getNode(                                                \5001        LoongArchISD::NODE, DL, {MVT::i64, MVT::Other},                        \5002        {Chain, Op2,                                                           \5003         DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3))});       \5004    Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, NODE.getValue(0)));   \5005    Results.push_back(NODE.getValue(1));                                       \5006    break;                                                                     \5007  }5008      CRC_CASE_EXT_UNARYOP(crc_w_d_w, CRC_W_D_W)5009      CRC_CASE_EXT_UNARYOP(crcc_w_d_w, CRCC_W_D_W)5010#undef CRC_CASE_EXT_UNARYOP5011#define CSR_CASE(ID)                                                           \5012  case Intrinsic::loongarch_##ID: {                                            \5013    if (!Subtarget.is64Bit())                                                  \5014      emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64);   \5015    break;                                                                     \5016  }5017      CSR_CASE(csrrd_d);5018      CSR_CASE(csrwr_d);5019      CSR_CASE(csrxchg_d);5020      CSR_CASE(iocsrrd_d);5021#undef CSR_CASE5022    case Intrinsic::loongarch_csrrd_w: {5023      unsigned Imm = Op2->getAsZExtVal();5024      if (!isUInt<14>(Imm)) {5025        emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgOOR);5026        return;5027      }5028      SDValue CSRRDResults =5029          DAG.getNode(LoongArchISD::CSRRD, DL, {GRLenVT, MVT::Other},5030                      {Chain, DAG.getConstant(Imm, DL, GRLenVT)});5031      Results.push_back(5032          DAG.getNode(ISD::TRUNCATE, DL, VT, CSRRDResults.getValue(0)));5033      Results.push_back(CSRRDResults.getValue(1));5034      break;5035    }5036    case Intrinsic::loongarch_csrwr_w: {5037      unsigned Imm = N->getConstantOperandVal(3);5038      if (!isUInt<14>(Imm)) {5039        emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgOOR);5040        return;5041      }5042      SDValue CSRWRResults =5043          DAG.getNode(LoongArchISD::CSRWR, DL, {GRLenVT, MVT::Other},5044                      {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2),5045                       DAG.getConstant(Imm, DL, GRLenVT)});5046      Results.push_back(5047          DAG.getNode(ISD::TRUNCATE, DL, VT, CSRWRResults.getValue(0)));5048      Results.push_back(CSRWRResults.getValue(1));5049      break;5050    }5051    case Intrinsic::loongarch_csrxchg_w: {5052      unsigned Imm = N->getConstantOperandVal(4);5053      if (!isUInt<14>(Imm)) {5054        emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgOOR);5055        return;5056      }5057      SDValue CSRXCHGResults = DAG.getNode(5058          LoongArchISD::CSRXCHG, DL, {GRLenVT, MVT::Other},5059          {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2),5060           DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3)),5061           DAG.getConstant(Imm, DL, GRLenVT)});5062      Results.push_back(5063          DAG.getNode(ISD::TRUNCATE, DL, VT, CSRXCHGResults.getValue(0)));5064      Results.push_back(CSRXCHGResults.getValue(1));5065      break;5066    }5067#define IOCSRRD_CASE(NAME, NODE)                                               \5068  case Intrinsic::loongarch_##NAME: {                                          \5069    SDValue IOCSRRDResults =                                                   \5070        DAG.getNode(LoongArchISD::NODE, DL, {MVT::i64, MVT::Other},            \5071                    {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)}); \5072    Results.push_back(                                                         \5073        DAG.getNode(ISD::TRUNCATE, DL, VT, IOCSRRDResults.getValue(0)));       \5074    Results.push_back(IOCSRRDResults.getValue(1));                             \5075    break;                                                                     \5076  }5077      IOCSRRD_CASE(iocsrrd_b, IOCSRRD_B);5078      IOCSRRD_CASE(iocsrrd_h, IOCSRRD_H);5079      IOCSRRD_CASE(iocsrrd_w, IOCSRRD_W);5080#undef IOCSRRD_CASE5081    case Intrinsic::loongarch_cpucfg: {5082      SDValue CPUCFGResults =5083          DAG.getNode(LoongArchISD::CPUCFG, DL, {GRLenVT, MVT::Other},5084                      {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2)});5085      Results.push_back(5086          DAG.getNode(ISD::TRUNCATE, DL, VT, CPUCFGResults.getValue(0)));5087      Results.push_back(CPUCFGResults.getValue(1));5088      break;5089    }5090    case Intrinsic::loongarch_lddir_d: {5091      if (!Subtarget.is64Bit()) {5092        emitErrorAndReplaceIntrinsicResults(N, Results, DAG, ErrorMsgReqLA64);5093        return;5094      }5095      break;5096    }5097    }5098    break;5099  }5100  case ISD::READ_REGISTER: {5101    if (Subtarget.is64Bit())5102      DAG.getContext()->emitError(5103          "On LA64, only 64-bit registers can be read.");5104    else5105      DAG.getContext()->emitError(5106          "On LA32, only 32-bit registers can be read.");5107    Results.push_back(DAG.getUNDEF(VT));5108    Results.push_back(N->getOperand(0));5109    break;5110  }5111  case ISD::INTRINSIC_WO_CHAIN: {5112    replaceINTRINSIC_WO_CHAINResults(N, Results, DAG, Subtarget);5113    break;5114  }5115  case ISD::LROUND: {5116    SDValue Op0 = N->getOperand(0);5117    EVT OpVT = Op0.getValueType();5118    RTLIB::Libcall LC =5119        OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32;5120    MakeLibCallOptions CallOptions;5121    CallOptions.setTypeListBeforeSoften(OpVT, MVT::i64);5122    SDValue Result = makeLibCall(DAG, LC, MVT::i64, Op0, CallOptions, DL).first;5123    Result = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Result);5124    Results.push_back(Result);5125    break;5126  }5127  case ISD::ATOMIC_CMP_SWAP: {5128    replaceCMP_XCHG_128Results(N, Results, DAG);5129    break;5130  }5131  case ISD::TRUNCATE: {5132    MVT VT = N->getSimpleValueType(0);5133    if (getTypeAction(*DAG.getContext(), VT) != TypeWidenVector)5134      return;5135 5136    MVT WidenVT = getTypeToTransformTo(*DAG.getContext(), VT).getSimpleVT();5137    SDValue In = N->getOperand(0);5138    EVT InVT = In.getValueType();5139    EVT InEltVT = InVT.getVectorElementType();5140    EVT EltVT = VT.getVectorElementType();5141    unsigned MinElts = VT.getVectorNumElements();5142    unsigned WidenNumElts = WidenVT.getVectorNumElements();5143    unsigned InBits = InVT.getSizeInBits();5144 5145    if ((128 % InBits) == 0 && WidenVT.is128BitVector()) {5146      if ((InEltVT.getSizeInBits() % EltVT.getSizeInBits()) == 0) {5147        int Scale = InEltVT.getSizeInBits() / EltVT.getSizeInBits();5148        SmallVector<int, 16> TruncMask(WidenNumElts, -1);5149        for (unsigned I = 0; I < MinElts; ++I)5150          TruncMask[I] = Scale * I;5151 5152        unsigned WidenNumElts = 128 / In.getScalarValueSizeInBits();5153        MVT SVT = In.getSimpleValueType().getScalarType();5154        MVT VT = MVT::getVectorVT(SVT, WidenNumElts);5155        SDValue WidenIn =5156            DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, DAG.getUNDEF(VT), In,5157                        DAG.getVectorIdxConstant(0, DL));5158        assert(isTypeLegal(WidenVT) && isTypeLegal(WidenIn.getValueType()) &&5159               "Illegal vector type in truncation");5160        WidenIn = DAG.getBitcast(WidenVT, WidenIn);5161        Results.push_back(5162            DAG.getVectorShuffle(WidenVT, DL, WidenIn, WidenIn, TruncMask));5163        return;5164      }5165    }5166 5167    break;5168  }5169  }5170}5171 5172/// Try to fold: (and (xor X, -1), Y) -> (vandn X, Y).5173static SDValue combineAndNotIntoVANDN(SDNode *N, const SDLoc &DL,5174                                      SelectionDAG &DAG) {5175  assert(N->getOpcode() == ISD::AND && "Unexpected opcode combine into ANDN");5176 5177  MVT VT = N->getSimpleValueType(0);5178  if (!VT.is128BitVector() && !VT.is256BitVector())5179    return SDValue();5180 5181  SDValue X, Y;5182  SDValue N0 = N->getOperand(0);5183  SDValue N1 = N->getOperand(1);5184 5185  if (SDValue Not = isNOT(N0, DAG)) {5186    X = Not;5187    Y = N1;5188  } else if (SDValue Not = isNOT(N1, DAG)) {5189    X = Not;5190    Y = N0;5191  } else5192    return SDValue();5193 5194  X = DAG.getBitcast(VT, X);5195  Y = DAG.getBitcast(VT, Y);5196  return DAG.getNode(LoongArchISD::VANDN, DL, VT, X, Y);5197}5198 5199static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,5200                                 TargetLowering::DAGCombinerInfo &DCI,5201                                 const LoongArchSubtarget &Subtarget) {5202  if (DCI.isBeforeLegalizeOps())5203    return SDValue();5204 5205  SDValue FirstOperand = N->getOperand(0);5206  SDValue SecondOperand = N->getOperand(1);5207  unsigned FirstOperandOpc = FirstOperand.getOpcode();5208  EVT ValTy = N->getValueType(0);5209  SDLoc DL(N);5210  uint64_t lsb, msb;5211  unsigned SMIdx, SMLen;5212  ConstantSDNode *CN;5213  SDValue NewOperand;5214  MVT GRLenVT = Subtarget.getGRLenVT();5215 5216  if (SDValue R = combineAndNotIntoVANDN(N, DL, DAG))5217    return R;5218 5219  // BSTRPICK requires the 32S feature.5220  if (!Subtarget.has32S())5221    return SDValue();5222 5223  // Op's second operand must be a shifted mask.5224  if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand)) ||5225      !isShiftedMask_64(CN->getZExtValue(), SMIdx, SMLen))5226    return SDValue();5227 5228  if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL) {5229    // Pattern match BSTRPICK.5230    //  $dst = and ((sra or srl) $src , lsb), (2**len - 1)5231    //  => BSTRPICK $dst, $src, msb, lsb5232    //  where msb = lsb + len - 15233 5234    // The second operand of the shift must be an immediate.5235    if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))))5236      return SDValue();5237 5238    lsb = CN->getZExtValue();5239 5240    // Return if the shifted mask does not start at bit 0 or the sum of its5241    // length and lsb exceeds the word's size.5242    if (SMIdx != 0 || lsb + SMLen > ValTy.getSizeInBits())5243      return SDValue();5244 5245    NewOperand = FirstOperand.getOperand(0);5246  } else {5247    // Pattern match BSTRPICK.5248    //  $dst = and $src, (2**len- 1) , if len > 125249    //  => BSTRPICK $dst, $src, msb, lsb5250    //  where lsb = 0 and msb = len - 15251 5252    // If the mask is <= 0xfff, andi can be used instead.5253    if (CN->getZExtValue() <= 0xfff)5254      return SDValue();5255 5256    // Return if the MSB exceeds.5257    if (SMIdx + SMLen > ValTy.getSizeInBits())5258      return SDValue();5259 5260    if (SMIdx > 0) {5261      // Omit if the constant has more than 2 uses. This a conservative5262      // decision. Whether it is a win depends on the HW microarchitecture.5263      // However it should always be better for 1 and 2 uses.5264      if (CN->use_size() > 2)5265        return SDValue();5266      // Return if the constant can be composed by a single LU12I.W.5267      if ((CN->getZExtValue() & 0xfff) == 0)5268        return SDValue();5269      // Return if the constand can be composed by a single ADDI with5270      // the zero register.5271      if (CN->getSExtValue() >= -2048 && CN->getSExtValue() < 0)5272        return SDValue();5273    }5274 5275    lsb = SMIdx;5276    NewOperand = FirstOperand;5277  }5278 5279  msb = lsb + SMLen - 1;5280  SDValue NR0 = DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, NewOperand,5281                            DAG.getConstant(msb, DL, GRLenVT),5282                            DAG.getConstant(lsb, DL, GRLenVT));5283  if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL || lsb == 0)5284    return NR0;5285  // Try to optimize to5286  //   bstrpick $Rd, $Rs, msb, lsb5287  //   slli     $Rd, $Rd, lsb5288  return DAG.getNode(ISD::SHL, DL, ValTy, NR0,5289                     DAG.getConstant(lsb, DL, GRLenVT));5290}5291 5292static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG,5293                                 TargetLowering::DAGCombinerInfo &DCI,5294                                 const LoongArchSubtarget &Subtarget) {5295  // BSTRPICK requires the 32S feature.5296  if (!Subtarget.has32S())5297    return SDValue();5298 5299  if (DCI.isBeforeLegalizeOps())5300    return SDValue();5301 5302  // $dst = srl (and $src, Mask), Shamt5303  // =>5304  // BSTRPICK $dst, $src, MaskIdx+MaskLen-1, Shamt5305  // when Mask is a shifted mask, and MaskIdx <= Shamt <= MaskIdx+MaskLen-15306  //5307 5308  SDValue FirstOperand = N->getOperand(0);5309  ConstantSDNode *CN;5310  EVT ValTy = N->getValueType(0);5311  SDLoc DL(N);5312  MVT GRLenVT = Subtarget.getGRLenVT();5313  unsigned MaskIdx, MaskLen;5314  uint64_t Shamt;5315 5316  // The first operand must be an AND and the second operand of the AND must be5317  // a shifted mask.5318  if (FirstOperand.getOpcode() != ISD::AND ||5319      !(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))) ||5320      !isShiftedMask_64(CN->getZExtValue(), MaskIdx, MaskLen))5321    return SDValue();5322 5323  // The second operand (shift amount) must be an immediate.5324  if (!(CN = dyn_cast<ConstantSDNode>(N->getOperand(1))))5325    return SDValue();5326 5327  Shamt = CN->getZExtValue();5328  if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)5329    return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy,5330                       FirstOperand->getOperand(0),5331                       DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT),5332                       DAG.getConstant(Shamt, DL, GRLenVT));5333 5334  return SDValue();5335}5336 5337// Helper to peek through bitops/trunc/setcc to determine size of source vector.5338// Allows BITCASTCombine to determine what size vector generated a <X x i1>.5339static bool checkBitcastSrcVectorSize(SDValue Src, unsigned Size,5340                                      unsigned Depth) {5341  // Limit recursion.5342  if (Depth >= SelectionDAG::MaxRecursionDepth)5343    return false;5344  switch (Src.getOpcode()) {5345  case ISD::SETCC:5346  case ISD::TRUNCATE:5347    return Src.getOperand(0).getValueSizeInBits() == Size;5348  case ISD::FREEZE:5349    return checkBitcastSrcVectorSize(Src.getOperand(0), Size, Depth + 1);5350  case ISD::AND:5351  case ISD::XOR:5352  case ISD::OR:5353    return checkBitcastSrcVectorSize(Src.getOperand(0), Size, Depth + 1) &&5354           checkBitcastSrcVectorSize(Src.getOperand(1), Size, Depth + 1);5355  case ISD::SELECT:5356  case ISD::VSELECT:5357    return Src.getOperand(0).getScalarValueSizeInBits() == 1 &&5358           checkBitcastSrcVectorSize(Src.getOperand(1), Size, Depth + 1) &&5359           checkBitcastSrcVectorSize(Src.getOperand(2), Size, Depth + 1);5360  case ISD::BUILD_VECTOR:5361    return ISD::isBuildVectorAllZeros(Src.getNode()) ||5362           ISD::isBuildVectorAllOnes(Src.getNode());5363  }5364  return false;5365}5366 5367// Helper to push sign extension of vXi1 SETCC result through bitops.5368static SDValue signExtendBitcastSrcVector(SelectionDAG &DAG, EVT SExtVT,5369                                          SDValue Src, const SDLoc &DL) {5370  switch (Src.getOpcode()) {5371  case ISD::SETCC:5372  case ISD::FREEZE:5373  case ISD::TRUNCATE:5374  case ISD::BUILD_VECTOR:5375    return DAG.getNode(ISD::SIGN_EXTEND, DL, SExtVT, Src);5376  case ISD::AND:5377  case ISD::XOR:5378  case ISD::OR:5379    return DAG.getNode(5380        Src.getOpcode(), DL, SExtVT,5381        signExtendBitcastSrcVector(DAG, SExtVT, Src.getOperand(0), DL),5382        signExtendBitcastSrcVector(DAG, SExtVT, Src.getOperand(1), DL));5383  case ISD::SELECT:5384  case ISD::VSELECT:5385    return DAG.getSelect(5386        DL, SExtVT, Src.getOperand(0),5387        signExtendBitcastSrcVector(DAG, SExtVT, Src.getOperand(1), DL),5388        signExtendBitcastSrcVector(DAG, SExtVT, Src.getOperand(2), DL));5389  }5390  llvm_unreachable("Unexpected node type for vXi1 sign extension");5391}5392 5393static SDValue5394performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG,5395                            TargetLowering::DAGCombinerInfo &DCI,5396                            const LoongArchSubtarget &Subtarget) {5397  SDLoc DL(N);5398  EVT VT = N->getValueType(0);5399  SDValue Src = N->getOperand(0);5400  EVT SrcVT = Src.getValueType();5401 5402  if (Src.getOpcode() != ISD::SETCC || !Src.hasOneUse())5403    return SDValue();5404 5405  bool UseLASX;5406  unsigned Opc = ISD::DELETED_NODE;5407  EVT CmpVT = Src.getOperand(0).getValueType();5408  EVT EltVT = CmpVT.getVectorElementType();5409 5410  if (Subtarget.hasExtLSX() && CmpVT.getSizeInBits() == 128)5411    UseLASX = false;5412  else if (Subtarget.has32S() && Subtarget.hasExtLASX() &&5413           CmpVT.getSizeInBits() == 256)5414    UseLASX = true;5415  else5416    return SDValue();5417 5418  SDValue SrcN1 = Src.getOperand(1);5419  switch (cast<CondCodeSDNode>(Src.getOperand(2))->get()) {5420  default:5421    break;5422  case ISD::SETEQ:5423    // x == 0 => not (vmsknez.b x)5424    if (ISD::isBuildVectorAllZeros(SrcN1.getNode()) && EltVT == MVT::i8)5425      Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ;5426    break;5427  case ISD::SETGT:5428    // x > -1 => vmskgez.b x5429    if (ISD::isBuildVectorAllOnes(SrcN1.getNode()) && EltVT == MVT::i8)5430      Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;5431    break;5432  case ISD::SETGE:5433    // x >= 0 => vmskgez.b x5434    if (ISD::isBuildVectorAllZeros(SrcN1.getNode()) && EltVT == MVT::i8)5435      Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ;5436    break;5437  case ISD::SETLT:5438    // x < 0 => vmskltz.{b,h,w,d} x5439    if (ISD::isBuildVectorAllZeros(SrcN1.getNode()) &&5440        (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||5441         EltVT == MVT::i64))5442      Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;5443    break;5444  case ISD::SETLE:5445    // x <= -1 => vmskltz.{b,h,w,d} x5446    if (ISD::isBuildVectorAllOnes(SrcN1.getNode()) &&5447        (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||5448         EltVT == MVT::i64))5449      Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;5450    break;5451  case ISD::SETNE:5452    // x != 0 => vmsknez.b x5453    if (ISD::isBuildVectorAllZeros(SrcN1.getNode()) && EltVT == MVT::i8)5454      Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ;5455    break;5456  }5457 5458  if (Opc == ISD::DELETED_NODE)5459    return SDValue();5460 5461  SDValue V = DAG.getNode(Opc, DL, Subtarget.getGRLenVT(), Src.getOperand(0));5462  EVT T = EVT::getIntegerVT(*DAG.getContext(), SrcVT.getVectorNumElements());5463  V = DAG.getZExtOrTrunc(V, DL, T);5464  return DAG.getBitcast(VT, V);5465}5466 5467static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG,5468                                     TargetLowering::DAGCombinerInfo &DCI,5469                                     const LoongArchSubtarget &Subtarget) {5470  SDLoc DL(N);5471  EVT VT = N->getValueType(0);5472  SDValue Src = N->getOperand(0);5473  EVT SrcVT = Src.getValueType();5474  MVT GRLenVT = Subtarget.getGRLenVT();5475 5476  if (!DCI.isBeforeLegalizeOps())5477    return SDValue();5478 5479  if (!SrcVT.isSimple() || SrcVT.getScalarType() != MVT::i1)5480    return SDValue();5481 5482  // Combine SETCC and BITCAST into [X]VMSK{LT,GE,NE} when possible5483  SDValue Res = performSETCC_BITCASTCombine(N, DAG, DCI, Subtarget);5484  if (Res)5485    return Res;5486 5487  // Generate vXi1 using [X]VMSKLTZ5488  MVT SExtVT;5489  unsigned Opc;5490  bool UseLASX = false;5491  bool PropagateSExt = false;5492 5493  if (Src.getOpcode() == ISD::SETCC && Src.hasOneUse()) {5494    EVT CmpVT = Src.getOperand(0).getValueType();5495    if (CmpVT.getSizeInBits() > 256)5496      return SDValue();5497  }5498 5499  switch (SrcVT.getSimpleVT().SimpleTy) {5500  default:5501    return SDValue();5502  case MVT::v2i1:5503    SExtVT = MVT::v2i64;5504    break;5505  case MVT::v4i1:5506    SExtVT = MVT::v4i32;5507    if (Subtarget.hasExtLASX() && checkBitcastSrcVectorSize(Src, 256, 0)) {5508      SExtVT = MVT::v4i64;5509      UseLASX = true;5510      PropagateSExt = true;5511    }5512    break;5513  case MVT::v8i1:5514    SExtVT = MVT::v8i16;5515    if (Subtarget.hasExtLASX() && checkBitcastSrcVectorSize(Src, 256, 0)) {5516      SExtVT = MVT::v8i32;5517      UseLASX = true;5518      PropagateSExt = true;5519    }5520    break;5521  case MVT::v16i1:5522    SExtVT = MVT::v16i8;5523    if (Subtarget.hasExtLASX() && checkBitcastSrcVectorSize(Src, 256, 0)) {5524      SExtVT = MVT::v16i16;5525      UseLASX = true;5526      PropagateSExt = true;5527    }5528    break;5529  case MVT::v32i1:5530    SExtVT = MVT::v32i8;5531    UseLASX = true;5532    break;5533  };5534  Src = PropagateSExt ? signExtendBitcastSrcVector(DAG, SExtVT, Src, DL)5535                      : DAG.getNode(ISD::SIGN_EXTEND, DL, SExtVT, Src);5536 5537  SDValue V;5538  if (!Subtarget.has32S() || !Subtarget.hasExtLASX()) {5539    if (Src.getSimpleValueType() == MVT::v32i8) {5540      SDValue Lo, Hi;5541      std::tie(Lo, Hi) = DAG.SplitVector(Src, DL);5542      Lo = DAG.getNode(LoongArchISD::VMSKLTZ, DL, GRLenVT, Lo);5543      Hi = DAG.getNode(LoongArchISD::VMSKLTZ, DL, GRLenVT, Hi);5544      Hi = DAG.getNode(ISD::SHL, DL, GRLenVT, Hi,5545                       DAG.getConstant(16, DL, MVT::i8));5546      V = DAG.getNode(ISD::OR, DL, GRLenVT, Lo, Hi);5547    } else if (UseLASX) {5548      return SDValue();5549    }5550  }5551 5552  if (!V) {5553    Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ;5554    V = DAG.getNode(Opc, DL, GRLenVT, Src);5555  }5556 5557  EVT T = EVT::getIntegerVT(*DAG.getContext(), SrcVT.getVectorNumElements());5558  V = DAG.getZExtOrTrunc(V, DL, T);5559  return DAG.getBitcast(VT, V);5560}5561 5562static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,5563                                TargetLowering::DAGCombinerInfo &DCI,5564                                const LoongArchSubtarget &Subtarget) {5565  MVT GRLenVT = Subtarget.getGRLenVT();5566  EVT ValTy = N->getValueType(0);5567  SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);5568  ConstantSDNode *CN0, *CN1;5569  SDLoc DL(N);5570  unsigned ValBits = ValTy.getSizeInBits();5571  unsigned MaskIdx0, MaskLen0, MaskIdx1, MaskLen1;5572  unsigned Shamt;5573  bool SwapAndRetried = false;5574 5575  // BSTRPICK requires the 32S feature.5576  if (!Subtarget.has32S())5577    return SDValue();5578 5579  if (DCI.isBeforeLegalizeOps())5580    return SDValue();5581 5582  if (ValBits != 32 && ValBits != 64)5583    return SDValue();5584 5585Retry:5586  // 1st pattern to match BSTRINS:5587  //  R = or (and X, mask0), (and (shl Y, lsb), mask1)5588  //  where mask1 = (2**size - 1) << lsb, mask0 = ~mask15589  //  =>5590  //  R = BSTRINS X, Y, msb, lsb (where msb = lsb + size - 1)5591  if (N0.getOpcode() == ISD::AND &&5592      (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) &&5593      isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) &&5594      N1.getOpcode() == ISD::AND && N1.getOperand(0).getOpcode() == ISD::SHL &&5595      (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&5596      isShiftedMask_64(CN1->getZExtValue(), MaskIdx1, MaskLen1) &&5597      MaskIdx0 == MaskIdx1 && MaskLen0 == MaskLen1 &&5598      (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&5599      (Shamt = CN1->getZExtValue()) == MaskIdx0 &&5600      (MaskIdx0 + MaskLen0 <= ValBits)) {5601    LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 1\n");5602    return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0),5603                       N1.getOperand(0).getOperand(0),5604                       DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT),5605                       DAG.getConstant(MaskIdx0, DL, GRLenVT));5606  }5607 5608  // 2nd pattern to match BSTRINS:5609  //  R = or (and X, mask0), (shl (and Y, mask1), lsb)5610  //  where mask1 = (2**size - 1), mask0 = ~(mask1 << lsb)5611  //  =>5612  //  R = BSTRINS X, Y, msb, lsb (where msb = lsb + size - 1)5613  if (N0.getOpcode() == ISD::AND &&5614      (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) &&5615      isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) &&5616      N1.getOpcode() == ISD::SHL && N1.getOperand(0).getOpcode() == ISD::AND &&5617      (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&5618      (Shamt = CN1->getZExtValue()) == MaskIdx0 &&5619      (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&5620      isShiftedMask_64(CN1->getZExtValue(), MaskIdx1, MaskLen1) &&5621      MaskLen0 == MaskLen1 && MaskIdx1 == 0 &&5622      (MaskIdx0 + MaskLen0 <= ValBits)) {5623    LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 2\n");5624    return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0),5625                       N1.getOperand(0).getOperand(0),5626                       DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT),5627                       DAG.getConstant(MaskIdx0, DL, GRLenVT));5628  }5629 5630  // 3rd pattern to match BSTRINS:5631  //  R = or (and X, mask0), (and Y, mask1)5632  //  where ~mask0 = (2**size - 1) << lsb, mask0 & mask1 = 05633  //  =>5634  //  R = BSTRINS X, (shr (and Y, mask1), lsb), msb, lsb5635  //  where msb = lsb + size - 15636  if (N0.getOpcode() == ISD::AND && N1.getOpcode() == ISD::AND &&5637      (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) &&5638      isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) &&5639      (MaskIdx0 + MaskLen0 <= 64) &&5640      (CN1 = dyn_cast<ConstantSDNode>(N1->getOperand(1))) &&5641      (CN1->getSExtValue() & CN0->getSExtValue()) == 0) {5642    LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 3\n");5643    return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0),5644                       DAG.getNode(ISD::SRL, DL, N1->getValueType(0), N1,5645                                   DAG.getConstant(MaskIdx0, DL, GRLenVT)),5646                       DAG.getConstant(ValBits == 325647                                           ? (MaskIdx0 + (MaskLen0 & 31) - 1)5648                                           : (MaskIdx0 + MaskLen0 - 1),5649                                       DL, GRLenVT),5650                       DAG.getConstant(MaskIdx0, DL, GRLenVT));5651  }5652 5653  // 4th pattern to match BSTRINS:5654  //  R = or (and X, mask), (shl Y, shamt)5655  //  where mask = (2**shamt - 1)5656  //  =>5657  //  R = BSTRINS X, Y, ValBits - 1, shamt5658  //  where ValBits = 32 or 645659  if (N0.getOpcode() == ISD::AND && N1.getOpcode() == ISD::SHL &&5660      (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) &&5661      isShiftedMask_64(CN0->getZExtValue(), MaskIdx0, MaskLen0) &&5662      MaskIdx0 == 0 && (CN1 = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&5663      (Shamt = CN1->getZExtValue()) == MaskLen0 &&5664      (MaskIdx0 + MaskLen0 <= ValBits)) {5665    LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 4\n");5666    return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0),5667                       N1.getOperand(0),5668                       DAG.getConstant((ValBits - 1), DL, GRLenVT),5669                       DAG.getConstant(Shamt, DL, GRLenVT));5670  }5671 5672  // 5th pattern to match BSTRINS:5673  //  R = or (and X, mask), const5674  //  where ~mask = (2**size - 1) << lsb, mask & const = 05675  //  =>5676  //  R = BSTRINS X, (const >> lsb), msb, lsb5677  //  where msb = lsb + size - 15678  if (N0.getOpcode() == ISD::AND &&5679      (CN0 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) &&5680      isShiftedMask_64(~CN0->getSExtValue(), MaskIdx0, MaskLen0) &&5681      (CN1 = dyn_cast<ConstantSDNode>(N1)) &&5682      (CN1->getSExtValue() & CN0->getSExtValue()) == 0) {5683    LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 5\n");5684    return DAG.getNode(5685        LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0),5686        DAG.getSignedConstant(CN1->getSExtValue() >> MaskIdx0, DL, ValTy),5687        DAG.getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1)5688                                      : (MaskIdx0 + MaskLen0 - 1),5689                        DL, GRLenVT),5690        DAG.getConstant(MaskIdx0, DL, GRLenVT));5691  }5692 5693  // 6th pattern.5694  // a = b | ((c & mask) << shamt), where all positions in b to be overwritten5695  // by the incoming bits are known to be zero.5696  // =>5697  // a = BSTRINS b, c, shamt + MaskLen - 1, shamt5698  //5699  // Note that the 1st pattern is a special situation of the 6th, i.e. the 6th5700  // pattern is more common than the 1st. So we put the 1st before the 6th in5701  // order to match as many nodes as possible.5702  ConstantSDNode *CNMask, *CNShamt;5703  unsigned MaskIdx, MaskLen;5704  if (N1.getOpcode() == ISD::SHL && N1.getOperand(0).getOpcode() == ISD::AND &&5705      (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&5706      isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen) &&5707      MaskIdx == 0 && (CNShamt = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&5708      CNShamt->getZExtValue() + MaskLen <= ValBits) {5709    Shamt = CNShamt->getZExtValue();5710    APInt ShMask(ValBits, CNMask->getZExtValue() << Shamt);5711    if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) {5712      LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 6\n");5713      return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0,5714                         N1.getOperand(0).getOperand(0),5715                         DAG.getConstant(Shamt + MaskLen - 1, DL, GRLenVT),5716                         DAG.getConstant(Shamt, DL, GRLenVT));5717    }5718  }5719 5720  // 7th pattern.5721  // a = b | ((c << shamt) & shifted_mask), where all positions in b to be5722  // overwritten by the incoming bits are known to be zero.5723  // =>5724  // a = BSTRINS b, c, MaskIdx + MaskLen - 1, MaskIdx5725  //5726  // Similarly, the 7th pattern is more common than the 2nd. So we put the 2nd5727  // before the 7th in order to match as many nodes as possible.5728  if (N1.getOpcode() == ISD::AND &&5729      (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&5730      isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen) &&5731      N1.getOperand(0).getOpcode() == ISD::SHL &&5732      (CNShamt = dyn_cast<ConstantSDNode>(N1.getOperand(0).getOperand(1))) &&5733      CNShamt->getZExtValue() == MaskIdx) {5734    APInt ShMask(ValBits, CNMask->getZExtValue());5735    if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) {5736      LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 7\n");5737      return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0,5738                         N1.getOperand(0).getOperand(0),5739                         DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT),5740                         DAG.getConstant(MaskIdx, DL, GRLenVT));5741    }5742  }5743 5744  // (or a, b) and (or b, a) are equivalent, so swap the operands and retry.5745  if (!SwapAndRetried) {5746    std::swap(N0, N1);5747    SwapAndRetried = true;5748    goto Retry;5749  }5750 5751  SwapAndRetried = false;5752Retry2:5753  // 8th pattern.5754  // a = b | (c & shifted_mask), where all positions in b to be overwritten by5755  // the incoming bits are known to be zero.5756  // =>5757  // a = BSTRINS b, c >> MaskIdx, MaskIdx + MaskLen - 1, MaskIdx5758  //5759  // Similarly, the 8th pattern is more common than the 4th and 5th patterns. So5760  // we put it here in order to match as many nodes as possible or generate less5761  // instructions.5762  if (N1.getOpcode() == ISD::AND &&5763      (CNMask = dyn_cast<ConstantSDNode>(N1.getOperand(1))) &&5764      isShiftedMask_64(CNMask->getZExtValue(), MaskIdx, MaskLen)) {5765    APInt ShMask(ValBits, CNMask->getZExtValue());5766    if (ShMask.isSubsetOf(DAG.computeKnownBits(N0).Zero)) {5767      LLVM_DEBUG(dbgs() << "Perform OR combine: match pattern 8\n");5768      return DAG.getNode(LoongArchISD::BSTRINS, DL, ValTy, N0,5769                         DAG.getNode(ISD::SRL, DL, N1->getValueType(0),5770                                     N1->getOperand(0),5771                                     DAG.getConstant(MaskIdx, DL, GRLenVT)),5772                         DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT),5773                         DAG.getConstant(MaskIdx, DL, GRLenVT));5774    }5775  }5776  // Swap N0/N1 and retry.5777  if (!SwapAndRetried) {5778    std::swap(N0, N1);5779    SwapAndRetried = true;5780    goto Retry2;5781  }5782 5783  return SDValue();5784}5785 5786static bool checkValueWidth(SDValue V, ISD::LoadExtType &ExtType) {5787  ExtType = ISD::NON_EXTLOAD;5788 5789  switch (V.getNode()->getOpcode()) {5790  case ISD::LOAD: {5791    LoadSDNode *LoadNode = cast<LoadSDNode>(V.getNode());5792    if ((LoadNode->getMemoryVT() == MVT::i8) ||5793        (LoadNode->getMemoryVT() == MVT::i16)) {5794      ExtType = LoadNode->getExtensionType();5795      return true;5796    }5797    return false;5798  }5799  case ISD::AssertSext: {5800    VTSDNode *TypeNode = cast<VTSDNode>(V.getNode()->getOperand(1));5801    if ((TypeNode->getVT() == MVT::i8) || (TypeNode->getVT() == MVT::i16)) {5802      ExtType = ISD::SEXTLOAD;5803      return true;5804    }5805    return false;5806  }5807  case ISD::AssertZext: {5808    VTSDNode *TypeNode = cast<VTSDNode>(V.getNode()->getOperand(1));5809    if ((TypeNode->getVT() == MVT::i8) || (TypeNode->getVT() == MVT::i16)) {5810      ExtType = ISD::ZEXTLOAD;5811      return true;5812    }5813    return false;5814  }5815  default:5816    return false;5817  }5818 5819  return false;5820}5821 5822// Eliminate redundant truncation and zero-extension nodes.5823// * Case 1:5824//  +------------+ +------------+ +------------+5825//  |   Input1   | |   Input2   | |     CC     |5826//  +------------+ +------------+ +------------+5827//         |              |              |5828//         V              V              +----+5829//  +------------+ +------------+             |5830//  |  TRUNCATE  | |  TRUNCATE  |             |5831//  +------------+ +------------+             |5832//         |              |                   |5833//         V              V                   |5834//  +------------+ +------------+             |5835//  |  ZERO_EXT  | |  ZERO_EXT  |             |5836//  +------------+ +------------+             |5837//         |              |                   |5838//         |              +-------------+     |5839//         V              V             |     |5840//        +----------------+            |     |5841//        |      AND       |            |     |5842//        +----------------+            |     |5843//                |                     |     |5844//                +---------------+     |     |5845//                                |     |     |5846//                                V     V     V5847//                               +-------------+5848//                               |     CMP     |5849//                               +-------------+5850// * Case 2:5851//  +------------+ +------------+ +-------------+ +------------+ +------------+5852//  |   Input1   | |   Input2   | | Constant -1 | | Constant 0 | |     CC     |5853//  +------------+ +------------+ +-------------+ +------------+ +------------+5854//         |              |             |               |               |5855//         V              |             |               |               |5856//  +------------+        |             |               |               |5857//  |     XOR    |<---------------------+               |               |5858//  +------------+        |                             |               |5859//         |              |                             |               |5860//         V              V             +---------------+               |5861//  +------------+ +------------+       |                               |5862//  |  TRUNCATE  | |  TRUNCATE  |       |     +-------------------------+5863//  +------------+ +------------+       |     |5864//         |              |             |     |5865//         V              V             |     |5866//  +------------+ +------------+       |     |5867//  |  ZERO_EXT  | |  ZERO_EXT  |       |     |5868//  +------------+ +------------+       |     |5869//         |              |             |     |5870//         V              V             |     |5871//        +----------------+            |     |5872//        |      AND       |            |     |5873//        +----------------+            |     |5874//                |                     |     |5875//                +---------------+     |     |5876//                                |     |     |5877//                                V     V     V5878//                               +-------------+5879//                               |     CMP     |5880//                               +-------------+5881static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG,5882                                   TargetLowering::DAGCombinerInfo &DCI,5883                                   const LoongArchSubtarget &Subtarget) {5884  ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();5885 5886  SDNode *AndNode = N->getOperand(0).getNode();5887  if (AndNode->getOpcode() != ISD::AND)5888    return SDValue();5889 5890  SDValue AndInputValue2 = AndNode->getOperand(1);5891  if (AndInputValue2.getOpcode() != ISD::ZERO_EXTEND)5892    return SDValue();5893 5894  SDValue CmpInputValue = N->getOperand(1);5895  SDValue AndInputValue1 = AndNode->getOperand(0);5896  if (AndInputValue1.getOpcode() == ISD::XOR) {5897    if (CC != ISD::SETEQ && CC != ISD::SETNE)5898      return SDValue();5899    ConstantSDNode *CN = dyn_cast<ConstantSDNode>(AndInputValue1.getOperand(1));5900    if (!CN || CN->getSExtValue() != -1)5901      return SDValue();5902    CN = dyn_cast<ConstantSDNode>(CmpInputValue);5903    if (!CN || CN->getSExtValue() != 0)5904      return SDValue();5905    AndInputValue1 = AndInputValue1.getOperand(0);5906    if (AndInputValue1.getOpcode() != ISD::ZERO_EXTEND)5907      return SDValue();5908  } else if (AndInputValue1.getOpcode() == ISD::ZERO_EXTEND) {5909    if (AndInputValue2 != CmpInputValue)5910      return SDValue();5911  } else {5912    return SDValue();5913  }5914 5915  SDValue TruncValue1 = AndInputValue1.getNode()->getOperand(0);5916  if (TruncValue1.getOpcode() != ISD::TRUNCATE)5917    return SDValue();5918 5919  SDValue TruncValue2 = AndInputValue2.getNode()->getOperand(0);5920  if (TruncValue2.getOpcode() != ISD::TRUNCATE)5921    return SDValue();5922 5923  SDValue TruncInputValue1 = TruncValue1.getNode()->getOperand(0);5924  SDValue TruncInputValue2 = TruncValue2.getNode()->getOperand(0);5925  ISD::LoadExtType ExtType1;5926  ISD::LoadExtType ExtType2;5927 5928  if (!checkValueWidth(TruncInputValue1, ExtType1) ||5929      !checkValueWidth(TruncInputValue2, ExtType2))5930    return SDValue();5931 5932  if (TruncInputValue1->getValueType(0) != TruncInputValue2->getValueType(0) ||5933      AndNode->getValueType(0) != TruncInputValue1->getValueType(0))5934    return SDValue();5935 5936  if ((ExtType2 != ISD::ZEXTLOAD) &&5937      ((ExtType2 != ISD::SEXTLOAD) && (ExtType1 != ISD::SEXTLOAD)))5938    return SDValue();5939 5940  // These truncation and zero-extension nodes are not necessary, remove them.5941  SDValue NewAnd = DAG.getNode(ISD::AND, SDLoc(N), AndNode->getValueType(0),5942                               TruncInputValue1, TruncInputValue2);5943  SDValue NewSetCC =5944      DAG.getSetCC(SDLoc(N), N->getValueType(0), NewAnd, TruncInputValue2, CC);5945  DAG.ReplaceAllUsesWith(N, NewSetCC.getNode());5946  return SDValue(N, 0);5947}5948 5949// Combine (loongarch_bitrev_w (loongarch_revb_2w X)) to loongarch_bitrev_4b.5950static SDValue performBITREV_WCombine(SDNode *N, SelectionDAG &DAG,5951                                      TargetLowering::DAGCombinerInfo &DCI,5952                                      const LoongArchSubtarget &Subtarget) {5953  if (DCI.isBeforeLegalizeOps())5954    return SDValue();5955 5956  SDValue Src = N->getOperand(0);5957  if (Src.getOpcode() != LoongArchISD::REVB_2W)5958    return SDValue();5959 5960  return DAG.getNode(LoongArchISD::BITREV_4B, SDLoc(N), N->getValueType(0),5961                     Src.getOperand(0));5962}5963 5964// Perform common combines for BR_CC and SELECT_CC conditions.5965static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL,5966                       SelectionDAG &DAG, const LoongArchSubtarget &Subtarget) {5967  ISD::CondCode CCVal = cast<CondCodeSDNode>(CC)->get();5968 5969  // As far as arithmetic right shift always saves the sign,5970  // shift can be omitted.5971  // Fold setlt (sra X, N), 0 -> setlt X, 0 and5972  // setge (sra X, N), 0 -> setge X, 05973  if (isNullConstant(RHS) && (CCVal == ISD::SETGE || CCVal == ISD::SETLT) &&5974      LHS.getOpcode() == ISD::SRA) {5975    LHS = LHS.getOperand(0);5976    return true;5977  }5978 5979  if (!ISD::isIntEqualitySetCC(CCVal))5980    return false;5981 5982  // Fold ((setlt X, Y), 0, ne) -> (X, Y, lt)5983  // Sometimes the setcc is introduced after br_cc/select_cc has been formed.5984  if (LHS.getOpcode() == ISD::SETCC && isNullConstant(RHS) &&5985      LHS.getOperand(0).getValueType() == Subtarget.getGRLenVT()) {5986    // If we're looking for eq 0 instead of ne 0, we need to invert the5987    // condition.5988    bool Invert = CCVal == ISD::SETEQ;5989    CCVal = cast<CondCodeSDNode>(LHS.getOperand(2))->get();5990    if (Invert)5991      CCVal = ISD::getSetCCInverse(CCVal, LHS.getValueType());5992 5993    RHS = LHS.getOperand(1);5994    LHS = LHS.getOperand(0);5995    translateSetCCForBranch(DL, LHS, RHS, CCVal, DAG);5996 5997    CC = DAG.getCondCode(CCVal);5998    return true;5999  }6000 6001  // Fold ((srl (and X, 1<<C), C), 0, eq/ne) -> ((shl X, GRLen-1-C), 0, ge/lt)6002  if (isNullConstant(RHS) && LHS.getOpcode() == ISD::SRL && LHS.hasOneUse() &&6003      LHS.getOperand(1).getOpcode() == ISD::Constant) {6004    SDValue LHS0 = LHS.getOperand(0);6005    if (LHS0.getOpcode() == ISD::AND &&6006        LHS0.getOperand(1).getOpcode() == ISD::Constant) {6007      uint64_t Mask = LHS0.getConstantOperandVal(1);6008      uint64_t ShAmt = LHS.getConstantOperandVal(1);6009      if (isPowerOf2_64(Mask) && Log2_64(Mask) == ShAmt) {6010        CCVal = CCVal == ISD::SETEQ ? ISD::SETGE : ISD::SETLT;6011        CC = DAG.getCondCode(CCVal);6012 6013        ShAmt = LHS.getValueSizeInBits() - 1 - ShAmt;6014        LHS = LHS0.getOperand(0);6015        if (ShAmt != 0)6016          LHS =6017              DAG.getNode(ISD::SHL, DL, LHS.getValueType(), LHS0.getOperand(0),6018                          DAG.getConstant(ShAmt, DL, LHS.getValueType()));6019        return true;6020      }6021    }6022  }6023 6024  // (X, 1, setne) -> (X, 0, seteq) if we can prove X is 0/1.6025  // This can occur when legalizing some floating point comparisons.6026  APInt Mask = APInt::getBitsSetFrom(LHS.getValueSizeInBits(), 1);6027  if (isOneConstant(RHS) && DAG.MaskedValueIsZero(LHS, Mask)) {6028    CCVal = ISD::getSetCCInverse(CCVal, LHS.getValueType());6029    CC = DAG.getCondCode(CCVal);6030    RHS = DAG.getConstant(0, DL, LHS.getValueType());6031    return true;6032  }6033 6034  return false;6035}6036 6037static SDValue performBR_CCCombine(SDNode *N, SelectionDAG &DAG,6038                                   TargetLowering::DAGCombinerInfo &DCI,6039                                   const LoongArchSubtarget &Subtarget) {6040  SDValue LHS = N->getOperand(1);6041  SDValue RHS = N->getOperand(2);6042  SDValue CC = N->getOperand(3);6043  SDLoc DL(N);6044 6045  if (combine_CC(LHS, RHS, CC, DL, DAG, Subtarget))6046    return DAG.getNode(LoongArchISD::BR_CC, DL, N->getValueType(0),6047                       N->getOperand(0), LHS, RHS, CC, N->getOperand(4));6048 6049  return SDValue();6050}6051 6052static SDValue performSELECT_CCCombine(SDNode *N, SelectionDAG &DAG,6053                                       TargetLowering::DAGCombinerInfo &DCI,6054                                       const LoongArchSubtarget &Subtarget) {6055  // Transform6056  SDValue LHS = N->getOperand(0);6057  SDValue RHS = N->getOperand(1);6058  SDValue CC = N->getOperand(2);6059  ISD::CondCode CCVal = cast<CondCodeSDNode>(CC)->get();6060  SDValue TrueV = N->getOperand(3);6061  SDValue FalseV = N->getOperand(4);6062  SDLoc DL(N);6063  EVT VT = N->getValueType(0);6064 6065  // If the True and False values are the same, we don't need a select_cc.6066  if (TrueV == FalseV)6067    return TrueV;6068 6069  // (select (x < 0), y, z)  -> x >> (GRLEN - 1) & (y - z) + z6070  // (select (x >= 0), y, z) -> x >> (GRLEN - 1) & (z - y) + y6071  if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&6072      isNullConstant(RHS) &&6073      (CCVal == ISD::CondCode::SETLT || CCVal == ISD::CondCode::SETGE)) {6074    if (CCVal == ISD::CondCode::SETGE)6075      std::swap(TrueV, FalseV);6076 6077    int64_t TrueSImm = cast<ConstantSDNode>(TrueV)->getSExtValue();6078    int64_t FalseSImm = cast<ConstantSDNode>(FalseV)->getSExtValue();6079    // Only handle simm12, if it is not in this range, it can be considered as6080    // register.6081    if (isInt<12>(TrueSImm) && isInt<12>(FalseSImm) &&6082        isInt<12>(TrueSImm - FalseSImm)) {6083      SDValue SRA =6084          DAG.getNode(ISD::SRA, DL, VT, LHS,6085                      DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT));6086      SDValue AND =6087          DAG.getNode(ISD::AND, DL, VT, SRA,6088                      DAG.getSignedConstant(TrueSImm - FalseSImm, DL, VT));6089      return DAG.getNode(ISD::ADD, DL, VT, AND, FalseV);6090    }6091 6092    if (CCVal == ISD::CondCode::SETGE)6093      std::swap(TrueV, FalseV);6094  }6095 6096  if (combine_CC(LHS, RHS, CC, DL, DAG, Subtarget))6097    return DAG.getNode(LoongArchISD::SELECT_CC, DL, N->getValueType(0),6098                       {LHS, RHS, CC, TrueV, FalseV});6099 6100  return SDValue();6101}6102 6103template <unsigned N>6104static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp,6105                                       SelectionDAG &DAG,6106                                       const LoongArchSubtarget &Subtarget,6107                                       bool IsSigned = false) {6108  SDLoc DL(Node);6109  auto *CImm = cast<ConstantSDNode>(Node->getOperand(ImmOp));6110  // Check the ImmArg.6111  if ((IsSigned && !isInt<N>(CImm->getSExtValue())) ||6112      (!IsSigned && !isUInt<N>(CImm->getZExtValue()))) {6113    DAG.getContext()->emitError(Node->getOperationName(0) +6114                                ": argument out of range.");6115    return DAG.getNode(ISD::UNDEF, DL, Subtarget.getGRLenVT());6116  }6117  return DAG.getConstant(CImm->getZExtValue(), DL, Subtarget.getGRLenVT());6118}6119 6120template <unsigned N>6121static SDValue lowerVectorSplatImm(SDNode *Node, unsigned ImmOp,6122                                   SelectionDAG &DAG, bool IsSigned = false) {6123  SDLoc DL(Node);6124  EVT ResTy = Node->getValueType(0);6125  auto *CImm = cast<ConstantSDNode>(Node->getOperand(ImmOp));6126 6127  // Check the ImmArg.6128  if ((IsSigned && !isInt<N>(CImm->getSExtValue())) ||6129      (!IsSigned && !isUInt<N>(CImm->getZExtValue()))) {6130    DAG.getContext()->emitError(Node->getOperationName(0) +6131                                ": argument out of range.");6132    return DAG.getNode(ISD::UNDEF, DL, ResTy);6133  }6134  return DAG.getConstant(6135      APInt(ResTy.getScalarType().getSizeInBits(),6136            IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),6137      DL, ResTy);6138}6139 6140static SDValue truncateVecElts(SDNode *Node, SelectionDAG &DAG) {6141  SDLoc DL(Node);6142  EVT ResTy = Node->getValueType(0);6143  SDValue Vec = Node->getOperand(2);6144  SDValue Mask = DAG.getConstant(Vec.getScalarValueSizeInBits() - 1, DL, ResTy);6145  return DAG.getNode(ISD::AND, DL, ResTy, Vec, Mask);6146}6147 6148static SDValue lowerVectorBitClear(SDNode *Node, SelectionDAG &DAG) {6149  SDLoc DL(Node);6150  EVT ResTy = Node->getValueType(0);6151  SDValue One = DAG.getConstant(1, DL, ResTy);6152  SDValue Bit =6153      DAG.getNode(ISD::SHL, DL, ResTy, One, truncateVecElts(Node, DAG));6154 6155  return DAG.getNode(ISD::AND, DL, ResTy, Node->getOperand(1),6156                     DAG.getNOT(DL, Bit, ResTy));6157}6158 6159template <unsigned N>6160static SDValue lowerVectorBitClearImm(SDNode *Node, SelectionDAG &DAG) {6161  SDLoc DL(Node);6162  EVT ResTy = Node->getValueType(0);6163  auto *CImm = cast<ConstantSDNode>(Node->getOperand(2));6164  // Check the unsigned ImmArg.6165  if (!isUInt<N>(CImm->getZExtValue())) {6166    DAG.getContext()->emitError(Node->getOperationName(0) +6167                                ": argument out of range.");6168    return DAG.getNode(ISD::UNDEF, DL, ResTy);6169  }6170 6171  APInt BitImm = APInt(ResTy.getScalarSizeInBits(), 1) << CImm->getAPIntValue();6172  SDValue Mask = DAG.getConstant(~BitImm, DL, ResTy);6173 6174  return DAG.getNode(ISD::AND, DL, ResTy, Node->getOperand(1), Mask);6175}6176 6177template <unsigned N>6178static SDValue lowerVectorBitSetImm(SDNode *Node, SelectionDAG &DAG) {6179  SDLoc DL(Node);6180  EVT ResTy = Node->getValueType(0);6181  auto *CImm = cast<ConstantSDNode>(Node->getOperand(2));6182  // Check the unsigned ImmArg.6183  if (!isUInt<N>(CImm->getZExtValue())) {6184    DAG.getContext()->emitError(Node->getOperationName(0) +6185                                ": argument out of range.");6186    return DAG.getNode(ISD::UNDEF, DL, ResTy);6187  }6188 6189  APInt Imm = APInt(ResTy.getScalarSizeInBits(), 1) << CImm->getAPIntValue();6190  SDValue BitImm = DAG.getConstant(Imm, DL, ResTy);6191  return DAG.getNode(ISD::OR, DL, ResTy, Node->getOperand(1), BitImm);6192}6193 6194template <unsigned N>6195static SDValue lowerVectorBitRevImm(SDNode *Node, SelectionDAG &DAG) {6196  SDLoc DL(Node);6197  EVT ResTy = Node->getValueType(0);6198  auto *CImm = cast<ConstantSDNode>(Node->getOperand(2));6199  // Check the unsigned ImmArg.6200  if (!isUInt<N>(CImm->getZExtValue())) {6201    DAG.getContext()->emitError(Node->getOperationName(0) +6202                                ": argument out of range.");6203    return DAG.getNode(ISD::UNDEF, DL, ResTy);6204  }6205 6206  APInt Imm = APInt(ResTy.getScalarSizeInBits(), 1) << CImm->getAPIntValue();6207  SDValue BitImm = DAG.getConstant(Imm, DL, ResTy);6208  return DAG.getNode(ISD::XOR, DL, ResTy, Node->getOperand(1), BitImm);6209}6210 6211template <unsigned W>6212static SDValue lowerVectorPickVE2GR(SDNode *N, SelectionDAG &DAG,6213                                    unsigned ResOp) {6214  unsigned Imm = N->getConstantOperandVal(2);6215  if (!isUInt<W>(Imm)) {6216    const StringRef ErrorMsg = "argument out of range";6217    DAG.getContext()->emitError(N->getOperationName(0) + ": " + ErrorMsg + ".");6218    return DAG.getUNDEF(N->getValueType(0));6219  }6220  SDLoc DL(N);6221  SDValue Vec = N->getOperand(1);6222  SDValue Idx = DAG.getConstant(Imm, DL, MVT::i32);6223  SDValue EltVT = DAG.getValueType(Vec.getValueType().getVectorElementType());6224  return DAG.getNode(ResOp, DL, N->getValueType(0), Vec, Idx, EltVT);6225}6226 6227static SDValue6228performINTRINSIC_WO_CHAINCombine(SDNode *N, SelectionDAG &DAG,6229                                 TargetLowering::DAGCombinerInfo &DCI,6230                                 const LoongArchSubtarget &Subtarget) {6231  SDLoc DL(N);6232  switch (N->getConstantOperandVal(0)) {6233  default:6234    break;6235  case Intrinsic::loongarch_lsx_vadd_b:6236  case Intrinsic::loongarch_lsx_vadd_h:6237  case Intrinsic::loongarch_lsx_vadd_w:6238  case Intrinsic::loongarch_lsx_vadd_d:6239  case Intrinsic::loongarch_lasx_xvadd_b:6240  case Intrinsic::loongarch_lasx_xvadd_h:6241  case Intrinsic::loongarch_lasx_xvadd_w:6242  case Intrinsic::loongarch_lasx_xvadd_d:6243    return DAG.getNode(ISD::ADD, DL, N->getValueType(0), N->getOperand(1),6244                       N->getOperand(2));6245  case Intrinsic::loongarch_lsx_vaddi_bu:6246  case Intrinsic::loongarch_lsx_vaddi_hu:6247  case Intrinsic::loongarch_lsx_vaddi_wu:6248  case Intrinsic::loongarch_lsx_vaddi_du:6249  case Intrinsic::loongarch_lasx_xvaddi_bu:6250  case Intrinsic::loongarch_lasx_xvaddi_hu:6251  case Intrinsic::loongarch_lasx_xvaddi_wu:6252  case Intrinsic::loongarch_lasx_xvaddi_du:6253    return DAG.getNode(ISD::ADD, DL, N->getValueType(0), N->getOperand(1),6254                       lowerVectorSplatImm<5>(N, 2, DAG));6255  case Intrinsic::loongarch_lsx_vsub_b:6256  case Intrinsic::loongarch_lsx_vsub_h:6257  case Intrinsic::loongarch_lsx_vsub_w:6258  case Intrinsic::loongarch_lsx_vsub_d:6259  case Intrinsic::loongarch_lasx_xvsub_b:6260  case Intrinsic::loongarch_lasx_xvsub_h:6261  case Intrinsic::loongarch_lasx_xvsub_w:6262  case Intrinsic::loongarch_lasx_xvsub_d:6263    return DAG.getNode(ISD::SUB, DL, N->getValueType(0), N->getOperand(1),6264                       N->getOperand(2));6265  case Intrinsic::loongarch_lsx_vsubi_bu:6266  case Intrinsic::loongarch_lsx_vsubi_hu:6267  case Intrinsic::loongarch_lsx_vsubi_wu:6268  case Intrinsic::loongarch_lsx_vsubi_du:6269  case Intrinsic::loongarch_lasx_xvsubi_bu:6270  case Intrinsic::loongarch_lasx_xvsubi_hu:6271  case Intrinsic::loongarch_lasx_xvsubi_wu:6272  case Intrinsic::loongarch_lasx_xvsubi_du:6273    return DAG.getNode(ISD::SUB, DL, N->getValueType(0), N->getOperand(1),6274                       lowerVectorSplatImm<5>(N, 2, DAG));6275  case Intrinsic::loongarch_lsx_vneg_b:6276  case Intrinsic::loongarch_lsx_vneg_h:6277  case Intrinsic::loongarch_lsx_vneg_w:6278  case Intrinsic::loongarch_lsx_vneg_d:6279  case Intrinsic::loongarch_lasx_xvneg_b:6280  case Intrinsic::loongarch_lasx_xvneg_h:6281  case Intrinsic::loongarch_lasx_xvneg_w:6282  case Intrinsic::loongarch_lasx_xvneg_d:6283    return DAG.getNode(6284        ISD::SUB, DL, N->getValueType(0),6285        DAG.getConstant(6286            APInt(N->getValueType(0).getScalarType().getSizeInBits(), 0,6287                  /*isSigned=*/true),6288            SDLoc(N), N->getValueType(0)),6289        N->getOperand(1));6290  case Intrinsic::loongarch_lsx_vmax_b:6291  case Intrinsic::loongarch_lsx_vmax_h:6292  case Intrinsic::loongarch_lsx_vmax_w:6293  case Intrinsic::loongarch_lsx_vmax_d:6294  case Intrinsic::loongarch_lasx_xvmax_b:6295  case Intrinsic::loongarch_lasx_xvmax_h:6296  case Intrinsic::loongarch_lasx_xvmax_w:6297  case Intrinsic::loongarch_lasx_xvmax_d:6298    return DAG.getNode(ISD::SMAX, DL, N->getValueType(0), N->getOperand(1),6299                       N->getOperand(2));6300  case Intrinsic::loongarch_lsx_vmax_bu:6301  case Intrinsic::loongarch_lsx_vmax_hu:6302  case Intrinsic::loongarch_lsx_vmax_wu:6303  case Intrinsic::loongarch_lsx_vmax_du:6304  case Intrinsic::loongarch_lasx_xvmax_bu:6305  case Intrinsic::loongarch_lasx_xvmax_hu:6306  case Intrinsic::loongarch_lasx_xvmax_wu:6307  case Intrinsic::loongarch_lasx_xvmax_du:6308    return DAG.getNode(ISD::UMAX, DL, N->getValueType(0), N->getOperand(1),6309                       N->getOperand(2));6310  case Intrinsic::loongarch_lsx_vmaxi_b:6311  case Intrinsic::loongarch_lsx_vmaxi_h:6312  case Intrinsic::loongarch_lsx_vmaxi_w:6313  case Intrinsic::loongarch_lsx_vmaxi_d:6314  case Intrinsic::loongarch_lasx_xvmaxi_b:6315  case Intrinsic::loongarch_lasx_xvmaxi_h:6316  case Intrinsic::loongarch_lasx_xvmaxi_w:6317  case Intrinsic::loongarch_lasx_xvmaxi_d:6318    return DAG.getNode(ISD::SMAX, DL, N->getValueType(0), N->getOperand(1),6319                       lowerVectorSplatImm<5>(N, 2, DAG, /*IsSigned=*/true));6320  case Intrinsic::loongarch_lsx_vmaxi_bu:6321  case Intrinsic::loongarch_lsx_vmaxi_hu:6322  case Intrinsic::loongarch_lsx_vmaxi_wu:6323  case Intrinsic::loongarch_lsx_vmaxi_du:6324  case Intrinsic::loongarch_lasx_xvmaxi_bu:6325  case Intrinsic::loongarch_lasx_xvmaxi_hu:6326  case Intrinsic::loongarch_lasx_xvmaxi_wu:6327  case Intrinsic::loongarch_lasx_xvmaxi_du:6328    return DAG.getNode(ISD::UMAX, DL, N->getValueType(0), N->getOperand(1),6329                       lowerVectorSplatImm<5>(N, 2, DAG));6330  case Intrinsic::loongarch_lsx_vmin_b:6331  case Intrinsic::loongarch_lsx_vmin_h:6332  case Intrinsic::loongarch_lsx_vmin_w:6333  case Intrinsic::loongarch_lsx_vmin_d:6334  case Intrinsic::loongarch_lasx_xvmin_b:6335  case Intrinsic::loongarch_lasx_xvmin_h:6336  case Intrinsic::loongarch_lasx_xvmin_w:6337  case Intrinsic::loongarch_lasx_xvmin_d:6338    return DAG.getNode(ISD::SMIN, DL, N->getValueType(0), N->getOperand(1),6339                       N->getOperand(2));6340  case Intrinsic::loongarch_lsx_vmin_bu:6341  case Intrinsic::loongarch_lsx_vmin_hu:6342  case Intrinsic::loongarch_lsx_vmin_wu:6343  case Intrinsic::loongarch_lsx_vmin_du:6344  case Intrinsic::loongarch_lasx_xvmin_bu:6345  case Intrinsic::loongarch_lasx_xvmin_hu:6346  case Intrinsic::loongarch_lasx_xvmin_wu:6347  case Intrinsic::loongarch_lasx_xvmin_du:6348    return DAG.getNode(ISD::UMIN, DL, N->getValueType(0), N->getOperand(1),6349                       N->getOperand(2));6350  case Intrinsic::loongarch_lsx_vmini_b:6351  case Intrinsic::loongarch_lsx_vmini_h:6352  case Intrinsic::loongarch_lsx_vmini_w:6353  case Intrinsic::loongarch_lsx_vmini_d:6354  case Intrinsic::loongarch_lasx_xvmini_b:6355  case Intrinsic::loongarch_lasx_xvmini_h:6356  case Intrinsic::loongarch_lasx_xvmini_w:6357  case Intrinsic::loongarch_lasx_xvmini_d:6358    return DAG.getNode(ISD::SMIN, DL, N->getValueType(0), N->getOperand(1),6359                       lowerVectorSplatImm<5>(N, 2, DAG, /*IsSigned=*/true));6360  case Intrinsic::loongarch_lsx_vmini_bu:6361  case Intrinsic::loongarch_lsx_vmini_hu:6362  case Intrinsic::loongarch_lsx_vmini_wu:6363  case Intrinsic::loongarch_lsx_vmini_du:6364  case Intrinsic::loongarch_lasx_xvmini_bu:6365  case Intrinsic::loongarch_lasx_xvmini_hu:6366  case Intrinsic::loongarch_lasx_xvmini_wu:6367  case Intrinsic::loongarch_lasx_xvmini_du:6368    return DAG.getNode(ISD::UMIN, DL, N->getValueType(0), N->getOperand(1),6369                       lowerVectorSplatImm<5>(N, 2, DAG));6370  case Intrinsic::loongarch_lsx_vmul_b:6371  case Intrinsic::loongarch_lsx_vmul_h:6372  case Intrinsic::loongarch_lsx_vmul_w:6373  case Intrinsic::loongarch_lsx_vmul_d:6374  case Intrinsic::loongarch_lasx_xvmul_b:6375  case Intrinsic::loongarch_lasx_xvmul_h:6376  case Intrinsic::loongarch_lasx_xvmul_w:6377  case Intrinsic::loongarch_lasx_xvmul_d:6378    return DAG.getNode(ISD::MUL, DL, N->getValueType(0), N->getOperand(1),6379                       N->getOperand(2));6380  case Intrinsic::loongarch_lsx_vmadd_b:6381  case Intrinsic::loongarch_lsx_vmadd_h:6382  case Intrinsic::loongarch_lsx_vmadd_w:6383  case Intrinsic::loongarch_lsx_vmadd_d:6384  case Intrinsic::loongarch_lasx_xvmadd_b:6385  case Intrinsic::loongarch_lasx_xvmadd_h:6386  case Intrinsic::loongarch_lasx_xvmadd_w:6387  case Intrinsic::loongarch_lasx_xvmadd_d: {6388    EVT ResTy = N->getValueType(0);6389    return DAG.getNode(ISD::ADD, SDLoc(N), ResTy, N->getOperand(1),6390                       DAG.getNode(ISD::MUL, SDLoc(N), ResTy, N->getOperand(2),6391                                   N->getOperand(3)));6392  }6393  case Intrinsic::loongarch_lsx_vmsub_b:6394  case Intrinsic::loongarch_lsx_vmsub_h:6395  case Intrinsic::loongarch_lsx_vmsub_w:6396  case Intrinsic::loongarch_lsx_vmsub_d:6397  case Intrinsic::loongarch_lasx_xvmsub_b:6398  case Intrinsic::loongarch_lasx_xvmsub_h:6399  case Intrinsic::loongarch_lasx_xvmsub_w:6400  case Intrinsic::loongarch_lasx_xvmsub_d: {6401    EVT ResTy = N->getValueType(0);6402    return DAG.getNode(ISD::SUB, SDLoc(N), ResTy, N->getOperand(1),6403                       DAG.getNode(ISD::MUL, SDLoc(N), ResTy, N->getOperand(2),6404                                   N->getOperand(3)));6405  }6406  case Intrinsic::loongarch_lsx_vdiv_b:6407  case Intrinsic::loongarch_lsx_vdiv_h:6408  case Intrinsic::loongarch_lsx_vdiv_w:6409  case Intrinsic::loongarch_lsx_vdiv_d:6410  case Intrinsic::loongarch_lasx_xvdiv_b:6411  case Intrinsic::loongarch_lasx_xvdiv_h:6412  case Intrinsic::loongarch_lasx_xvdiv_w:6413  case Intrinsic::loongarch_lasx_xvdiv_d:6414    return DAG.getNode(ISD::SDIV, DL, N->getValueType(0), N->getOperand(1),6415                       N->getOperand(2));6416  case Intrinsic::loongarch_lsx_vdiv_bu:6417  case Intrinsic::loongarch_lsx_vdiv_hu:6418  case Intrinsic::loongarch_lsx_vdiv_wu:6419  case Intrinsic::loongarch_lsx_vdiv_du:6420  case Intrinsic::loongarch_lasx_xvdiv_bu:6421  case Intrinsic::loongarch_lasx_xvdiv_hu:6422  case Intrinsic::loongarch_lasx_xvdiv_wu:6423  case Intrinsic::loongarch_lasx_xvdiv_du:6424    return DAG.getNode(ISD::UDIV, DL, N->getValueType(0), N->getOperand(1),6425                       N->getOperand(2));6426  case Intrinsic::loongarch_lsx_vmod_b:6427  case Intrinsic::loongarch_lsx_vmod_h:6428  case Intrinsic::loongarch_lsx_vmod_w:6429  case Intrinsic::loongarch_lsx_vmod_d:6430  case Intrinsic::loongarch_lasx_xvmod_b:6431  case Intrinsic::loongarch_lasx_xvmod_h:6432  case Intrinsic::loongarch_lasx_xvmod_w:6433  case Intrinsic::loongarch_lasx_xvmod_d:6434    return DAG.getNode(ISD::SREM, DL, N->getValueType(0), N->getOperand(1),6435                       N->getOperand(2));6436  case Intrinsic::loongarch_lsx_vmod_bu:6437  case Intrinsic::loongarch_lsx_vmod_hu:6438  case Intrinsic::loongarch_lsx_vmod_wu:6439  case Intrinsic::loongarch_lsx_vmod_du:6440  case Intrinsic::loongarch_lasx_xvmod_bu:6441  case Intrinsic::loongarch_lasx_xvmod_hu:6442  case Intrinsic::loongarch_lasx_xvmod_wu:6443  case Intrinsic::loongarch_lasx_xvmod_du:6444    return DAG.getNode(ISD::UREM, DL, N->getValueType(0), N->getOperand(1),6445                       N->getOperand(2));6446  case Intrinsic::loongarch_lsx_vand_v:6447  case Intrinsic::loongarch_lasx_xvand_v:6448    return DAG.getNode(ISD::AND, DL, N->getValueType(0), N->getOperand(1),6449                       N->getOperand(2));6450  case Intrinsic::loongarch_lsx_vor_v:6451  case Intrinsic::loongarch_lasx_xvor_v:6452    return DAG.getNode(ISD::OR, DL, N->getValueType(0), N->getOperand(1),6453                       N->getOperand(2));6454  case Intrinsic::loongarch_lsx_vxor_v:6455  case Intrinsic::loongarch_lasx_xvxor_v:6456    return DAG.getNode(ISD::XOR, DL, N->getValueType(0), N->getOperand(1),6457                       N->getOperand(2));6458  case Intrinsic::loongarch_lsx_vnor_v:6459  case Intrinsic::loongarch_lasx_xvnor_v: {6460    SDValue Res = DAG.getNode(ISD::OR, DL, N->getValueType(0), N->getOperand(1),6461                              N->getOperand(2));6462    return DAG.getNOT(DL, Res, Res->getValueType(0));6463  }6464  case Intrinsic::loongarch_lsx_vandi_b:6465  case Intrinsic::loongarch_lasx_xvandi_b:6466    return DAG.getNode(ISD::AND, DL, N->getValueType(0), N->getOperand(1),6467                       lowerVectorSplatImm<8>(N, 2, DAG));6468  case Intrinsic::loongarch_lsx_vori_b:6469  case Intrinsic::loongarch_lasx_xvori_b:6470    return DAG.getNode(ISD::OR, DL, N->getValueType(0), N->getOperand(1),6471                       lowerVectorSplatImm<8>(N, 2, DAG));6472  case Intrinsic::loongarch_lsx_vxori_b:6473  case Intrinsic::loongarch_lasx_xvxori_b:6474    return DAG.getNode(ISD::XOR, DL, N->getValueType(0), N->getOperand(1),6475                       lowerVectorSplatImm<8>(N, 2, DAG));6476  case Intrinsic::loongarch_lsx_vsll_b:6477  case Intrinsic::loongarch_lsx_vsll_h:6478  case Intrinsic::loongarch_lsx_vsll_w:6479  case Intrinsic::loongarch_lsx_vsll_d:6480  case Intrinsic::loongarch_lasx_xvsll_b:6481  case Intrinsic::loongarch_lasx_xvsll_h:6482  case Intrinsic::loongarch_lasx_xvsll_w:6483  case Intrinsic::loongarch_lasx_xvsll_d:6484    return DAG.getNode(ISD::SHL, DL, N->getValueType(0), N->getOperand(1),6485                       truncateVecElts(N, DAG));6486  case Intrinsic::loongarch_lsx_vslli_b:6487  case Intrinsic::loongarch_lasx_xvslli_b:6488    return DAG.getNode(ISD::SHL, DL, N->getValueType(0), N->getOperand(1),6489                       lowerVectorSplatImm<3>(N, 2, DAG));6490  case Intrinsic::loongarch_lsx_vslli_h:6491  case Intrinsic::loongarch_lasx_xvslli_h:6492    return DAG.getNode(ISD::SHL, DL, N->getValueType(0), N->getOperand(1),6493                       lowerVectorSplatImm<4>(N, 2, DAG));6494  case Intrinsic::loongarch_lsx_vslli_w:6495  case Intrinsic::loongarch_lasx_xvslli_w:6496    return DAG.getNode(ISD::SHL, DL, N->getValueType(0), N->getOperand(1),6497                       lowerVectorSplatImm<5>(N, 2, DAG));6498  case Intrinsic::loongarch_lsx_vslli_d:6499  case Intrinsic::loongarch_lasx_xvslli_d:6500    return DAG.getNode(ISD::SHL, DL, N->getValueType(0), N->getOperand(1),6501                       lowerVectorSplatImm<6>(N, 2, DAG));6502  case Intrinsic::loongarch_lsx_vsrl_b:6503  case Intrinsic::loongarch_lsx_vsrl_h:6504  case Intrinsic::loongarch_lsx_vsrl_w:6505  case Intrinsic::loongarch_lsx_vsrl_d:6506  case Intrinsic::loongarch_lasx_xvsrl_b:6507  case Intrinsic::loongarch_lasx_xvsrl_h:6508  case Intrinsic::loongarch_lasx_xvsrl_w:6509  case Intrinsic::loongarch_lasx_xvsrl_d:6510    return DAG.getNode(ISD::SRL, DL, N->getValueType(0), N->getOperand(1),6511                       truncateVecElts(N, DAG));6512  case Intrinsic::loongarch_lsx_vsrli_b:6513  case Intrinsic::loongarch_lasx_xvsrli_b:6514    return DAG.getNode(ISD::SRL, DL, N->getValueType(0), N->getOperand(1),6515                       lowerVectorSplatImm<3>(N, 2, DAG));6516  case Intrinsic::loongarch_lsx_vsrli_h:6517  case Intrinsic::loongarch_lasx_xvsrli_h:6518    return DAG.getNode(ISD::SRL, DL, N->getValueType(0), N->getOperand(1),6519                       lowerVectorSplatImm<4>(N, 2, DAG));6520  case Intrinsic::loongarch_lsx_vsrli_w:6521  case Intrinsic::loongarch_lasx_xvsrli_w:6522    return DAG.getNode(ISD::SRL, DL, N->getValueType(0), N->getOperand(1),6523                       lowerVectorSplatImm<5>(N, 2, DAG));6524  case Intrinsic::loongarch_lsx_vsrli_d:6525  case Intrinsic::loongarch_lasx_xvsrli_d:6526    return DAG.getNode(ISD::SRL, DL, N->getValueType(0), N->getOperand(1),6527                       lowerVectorSplatImm<6>(N, 2, DAG));6528  case Intrinsic::loongarch_lsx_vsra_b:6529  case Intrinsic::loongarch_lsx_vsra_h:6530  case Intrinsic::loongarch_lsx_vsra_w:6531  case Intrinsic::loongarch_lsx_vsra_d:6532  case Intrinsic::loongarch_lasx_xvsra_b:6533  case Intrinsic::loongarch_lasx_xvsra_h:6534  case Intrinsic::loongarch_lasx_xvsra_w:6535  case Intrinsic::loongarch_lasx_xvsra_d:6536    return DAG.getNode(ISD::SRA, DL, N->getValueType(0), N->getOperand(1),6537                       truncateVecElts(N, DAG));6538  case Intrinsic::loongarch_lsx_vsrai_b:6539  case Intrinsic::loongarch_lasx_xvsrai_b:6540    return DAG.getNode(ISD::SRA, DL, N->getValueType(0), N->getOperand(1),6541                       lowerVectorSplatImm<3>(N, 2, DAG));6542  case Intrinsic::loongarch_lsx_vsrai_h:6543  case Intrinsic::loongarch_lasx_xvsrai_h:6544    return DAG.getNode(ISD::SRA, DL, N->getValueType(0), N->getOperand(1),6545                       lowerVectorSplatImm<4>(N, 2, DAG));6546  case Intrinsic::loongarch_lsx_vsrai_w:6547  case Intrinsic::loongarch_lasx_xvsrai_w:6548    return DAG.getNode(ISD::SRA, DL, N->getValueType(0), N->getOperand(1),6549                       lowerVectorSplatImm<5>(N, 2, DAG));6550  case Intrinsic::loongarch_lsx_vsrai_d:6551  case Intrinsic::loongarch_lasx_xvsrai_d:6552    return DAG.getNode(ISD::SRA, DL, N->getValueType(0), N->getOperand(1),6553                       lowerVectorSplatImm<6>(N, 2, DAG));6554  case Intrinsic::loongarch_lsx_vclz_b:6555  case Intrinsic::loongarch_lsx_vclz_h:6556  case Intrinsic::loongarch_lsx_vclz_w:6557  case Intrinsic::loongarch_lsx_vclz_d:6558  case Intrinsic::loongarch_lasx_xvclz_b:6559  case Intrinsic::loongarch_lasx_xvclz_h:6560  case Intrinsic::loongarch_lasx_xvclz_w:6561  case Intrinsic::loongarch_lasx_xvclz_d:6562    return DAG.getNode(ISD::CTLZ, DL, N->getValueType(0), N->getOperand(1));6563  case Intrinsic::loongarch_lsx_vpcnt_b:6564  case Intrinsic::loongarch_lsx_vpcnt_h:6565  case Intrinsic::loongarch_lsx_vpcnt_w:6566  case Intrinsic::loongarch_lsx_vpcnt_d:6567  case Intrinsic::loongarch_lasx_xvpcnt_b:6568  case Intrinsic::loongarch_lasx_xvpcnt_h:6569  case Intrinsic::loongarch_lasx_xvpcnt_w:6570  case Intrinsic::loongarch_lasx_xvpcnt_d:6571    return DAG.getNode(ISD::CTPOP, DL, N->getValueType(0), N->getOperand(1));6572  case Intrinsic::loongarch_lsx_vbitclr_b:6573  case Intrinsic::loongarch_lsx_vbitclr_h:6574  case Intrinsic::loongarch_lsx_vbitclr_w:6575  case Intrinsic::loongarch_lsx_vbitclr_d:6576  case Intrinsic::loongarch_lasx_xvbitclr_b:6577  case Intrinsic::loongarch_lasx_xvbitclr_h:6578  case Intrinsic::loongarch_lasx_xvbitclr_w:6579  case Intrinsic::loongarch_lasx_xvbitclr_d:6580    return lowerVectorBitClear(N, DAG);6581  case Intrinsic::loongarch_lsx_vbitclri_b:6582  case Intrinsic::loongarch_lasx_xvbitclri_b:6583    return lowerVectorBitClearImm<3>(N, DAG);6584  case Intrinsic::loongarch_lsx_vbitclri_h:6585  case Intrinsic::loongarch_lasx_xvbitclri_h:6586    return lowerVectorBitClearImm<4>(N, DAG);6587  case Intrinsic::loongarch_lsx_vbitclri_w:6588  case Intrinsic::loongarch_lasx_xvbitclri_w:6589    return lowerVectorBitClearImm<5>(N, DAG);6590  case Intrinsic::loongarch_lsx_vbitclri_d:6591  case Intrinsic::loongarch_lasx_xvbitclri_d:6592    return lowerVectorBitClearImm<6>(N, DAG);6593  case Intrinsic::loongarch_lsx_vbitset_b:6594  case Intrinsic::loongarch_lsx_vbitset_h:6595  case Intrinsic::loongarch_lsx_vbitset_w:6596  case Intrinsic::loongarch_lsx_vbitset_d:6597  case Intrinsic::loongarch_lasx_xvbitset_b:6598  case Intrinsic::loongarch_lasx_xvbitset_h:6599  case Intrinsic::loongarch_lasx_xvbitset_w:6600  case Intrinsic::loongarch_lasx_xvbitset_d: {6601    EVT VecTy = N->getValueType(0);6602    SDValue One = DAG.getConstant(1, DL, VecTy);6603    return DAG.getNode(6604        ISD::OR, DL, VecTy, N->getOperand(1),6605        DAG.getNode(ISD::SHL, DL, VecTy, One, truncateVecElts(N, DAG)));6606  }6607  case Intrinsic::loongarch_lsx_vbitseti_b:6608  case Intrinsic::loongarch_lasx_xvbitseti_b:6609    return lowerVectorBitSetImm<3>(N, DAG);6610  case Intrinsic::loongarch_lsx_vbitseti_h:6611  case Intrinsic::loongarch_lasx_xvbitseti_h:6612    return lowerVectorBitSetImm<4>(N, DAG);6613  case Intrinsic::loongarch_lsx_vbitseti_w:6614  case Intrinsic::loongarch_lasx_xvbitseti_w:6615    return lowerVectorBitSetImm<5>(N, DAG);6616  case Intrinsic::loongarch_lsx_vbitseti_d:6617  case Intrinsic::loongarch_lasx_xvbitseti_d:6618    return lowerVectorBitSetImm<6>(N, DAG);6619  case Intrinsic::loongarch_lsx_vbitrev_b:6620  case Intrinsic::loongarch_lsx_vbitrev_h:6621  case Intrinsic::loongarch_lsx_vbitrev_w:6622  case Intrinsic::loongarch_lsx_vbitrev_d:6623  case Intrinsic::loongarch_lasx_xvbitrev_b:6624  case Intrinsic::loongarch_lasx_xvbitrev_h:6625  case Intrinsic::loongarch_lasx_xvbitrev_w:6626  case Intrinsic::loongarch_lasx_xvbitrev_d: {6627    EVT VecTy = N->getValueType(0);6628    SDValue One = DAG.getConstant(1, DL, VecTy);6629    return DAG.getNode(6630        ISD::XOR, DL, VecTy, N->getOperand(1),6631        DAG.getNode(ISD::SHL, DL, VecTy, One, truncateVecElts(N, DAG)));6632  }6633  case Intrinsic::loongarch_lsx_vbitrevi_b:6634  case Intrinsic::loongarch_lasx_xvbitrevi_b:6635    return lowerVectorBitRevImm<3>(N, DAG);6636  case Intrinsic::loongarch_lsx_vbitrevi_h:6637  case Intrinsic::loongarch_lasx_xvbitrevi_h:6638    return lowerVectorBitRevImm<4>(N, DAG);6639  case Intrinsic::loongarch_lsx_vbitrevi_w:6640  case Intrinsic::loongarch_lasx_xvbitrevi_w:6641    return lowerVectorBitRevImm<5>(N, DAG);6642  case Intrinsic::loongarch_lsx_vbitrevi_d:6643  case Intrinsic::loongarch_lasx_xvbitrevi_d:6644    return lowerVectorBitRevImm<6>(N, DAG);6645  case Intrinsic::loongarch_lsx_vfadd_s:6646  case Intrinsic::loongarch_lsx_vfadd_d:6647  case Intrinsic::loongarch_lasx_xvfadd_s:6648  case Intrinsic::loongarch_lasx_xvfadd_d:6649    return DAG.getNode(ISD::FADD, DL, N->getValueType(0), N->getOperand(1),6650                       N->getOperand(2));6651  case Intrinsic::loongarch_lsx_vfsub_s:6652  case Intrinsic::loongarch_lsx_vfsub_d:6653  case Intrinsic::loongarch_lasx_xvfsub_s:6654  case Intrinsic::loongarch_lasx_xvfsub_d:6655    return DAG.getNode(ISD::FSUB, DL, N->getValueType(0), N->getOperand(1),6656                       N->getOperand(2));6657  case Intrinsic::loongarch_lsx_vfmul_s:6658  case Intrinsic::loongarch_lsx_vfmul_d:6659  case Intrinsic::loongarch_lasx_xvfmul_s:6660  case Intrinsic::loongarch_lasx_xvfmul_d:6661    return DAG.getNode(ISD::FMUL, DL, N->getValueType(0), N->getOperand(1),6662                       N->getOperand(2));6663  case Intrinsic::loongarch_lsx_vfdiv_s:6664  case Intrinsic::loongarch_lsx_vfdiv_d:6665  case Intrinsic::loongarch_lasx_xvfdiv_s:6666  case Intrinsic::loongarch_lasx_xvfdiv_d:6667    return DAG.getNode(ISD::FDIV, DL, N->getValueType(0), N->getOperand(1),6668                       N->getOperand(2));6669  case Intrinsic::loongarch_lsx_vfmadd_s:6670  case Intrinsic::loongarch_lsx_vfmadd_d:6671  case Intrinsic::loongarch_lasx_xvfmadd_s:6672  case Intrinsic::loongarch_lasx_xvfmadd_d:6673    return DAG.getNode(ISD::FMA, DL, N->getValueType(0), N->getOperand(1),6674                       N->getOperand(2), N->getOperand(3));6675  case Intrinsic::loongarch_lsx_vinsgr2vr_b:6676    return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N), N->getValueType(0),6677                       N->getOperand(1), N->getOperand(2),6678                       legalizeIntrinsicImmArg<4>(N, 3, DAG, Subtarget));6679  case Intrinsic::loongarch_lsx_vinsgr2vr_h:6680  case Intrinsic::loongarch_lasx_xvinsgr2vr_w:6681    return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N), N->getValueType(0),6682                       N->getOperand(1), N->getOperand(2),6683                       legalizeIntrinsicImmArg<3>(N, 3, DAG, Subtarget));6684  case Intrinsic::loongarch_lsx_vinsgr2vr_w:6685  case Intrinsic::loongarch_lasx_xvinsgr2vr_d:6686    return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N), N->getValueType(0),6687                       N->getOperand(1), N->getOperand(2),6688                       legalizeIntrinsicImmArg<2>(N, 3, DAG, Subtarget));6689  case Intrinsic::loongarch_lsx_vinsgr2vr_d:6690    return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N), N->getValueType(0),6691                       N->getOperand(1), N->getOperand(2),6692                       legalizeIntrinsicImmArg<1>(N, 3, DAG, Subtarget));6693  case Intrinsic::loongarch_lsx_vreplgr2vr_b:6694  case Intrinsic::loongarch_lsx_vreplgr2vr_h:6695  case Intrinsic::loongarch_lsx_vreplgr2vr_w:6696  case Intrinsic::loongarch_lsx_vreplgr2vr_d:6697  case Intrinsic::loongarch_lasx_xvreplgr2vr_b:6698  case Intrinsic::loongarch_lasx_xvreplgr2vr_h:6699  case Intrinsic::loongarch_lasx_xvreplgr2vr_w:6700  case Intrinsic::loongarch_lasx_xvreplgr2vr_d:6701    return DAG.getNode(LoongArchISD::VREPLGR2VR, DL, N->getValueType(0),6702                       DAG.getNode(ISD::ANY_EXTEND, DL, Subtarget.getGRLenVT(),6703                                   N->getOperand(1)));6704  case Intrinsic::loongarch_lsx_vreplve_b:6705  case Intrinsic::loongarch_lsx_vreplve_h:6706  case Intrinsic::loongarch_lsx_vreplve_w:6707  case Intrinsic::loongarch_lsx_vreplve_d:6708  case Intrinsic::loongarch_lasx_xvreplve_b:6709  case Intrinsic::loongarch_lasx_xvreplve_h:6710  case Intrinsic::loongarch_lasx_xvreplve_w:6711  case Intrinsic::loongarch_lasx_xvreplve_d:6712    return DAG.getNode(LoongArchISD::VREPLVE, DL, N->getValueType(0),6713                       N->getOperand(1),6714                       DAG.getNode(ISD::ANY_EXTEND, DL, Subtarget.getGRLenVT(),6715                                   N->getOperand(2)));6716  case Intrinsic::loongarch_lsx_vpickve2gr_b:6717    if (!Subtarget.is64Bit())6718      return lowerVectorPickVE2GR<4>(N, DAG, LoongArchISD::VPICK_SEXT_ELT);6719    break;6720  case Intrinsic::loongarch_lsx_vpickve2gr_h:6721  case Intrinsic::loongarch_lasx_xvpickve2gr_w:6722    if (!Subtarget.is64Bit())6723      return lowerVectorPickVE2GR<3>(N, DAG, LoongArchISD::VPICK_SEXT_ELT);6724    break;6725  case Intrinsic::loongarch_lsx_vpickve2gr_w:6726    if (!Subtarget.is64Bit())6727      return lowerVectorPickVE2GR<2>(N, DAG, LoongArchISD::VPICK_SEXT_ELT);6728    break;6729  case Intrinsic::loongarch_lsx_vpickve2gr_bu:6730    if (!Subtarget.is64Bit())6731      return lowerVectorPickVE2GR<4>(N, DAG, LoongArchISD::VPICK_ZEXT_ELT);6732    break;6733  case Intrinsic::loongarch_lsx_vpickve2gr_hu:6734  case Intrinsic::loongarch_lasx_xvpickve2gr_wu:6735    if (!Subtarget.is64Bit())6736      return lowerVectorPickVE2GR<3>(N, DAG, LoongArchISD::VPICK_ZEXT_ELT);6737    break;6738  case Intrinsic::loongarch_lsx_vpickve2gr_wu:6739    if (!Subtarget.is64Bit())6740      return lowerVectorPickVE2GR<2>(N, DAG, LoongArchISD::VPICK_ZEXT_ELT);6741    break;6742  case Intrinsic::loongarch_lsx_bz_b:6743  case Intrinsic::loongarch_lsx_bz_h:6744  case Intrinsic::loongarch_lsx_bz_w:6745  case Intrinsic::loongarch_lsx_bz_d:6746  case Intrinsic::loongarch_lasx_xbz_b:6747  case Intrinsic::loongarch_lasx_xbz_h:6748  case Intrinsic::loongarch_lasx_xbz_w:6749  case Intrinsic::loongarch_lasx_xbz_d:6750    if (!Subtarget.is64Bit())6751      return DAG.getNode(LoongArchISD::VALL_ZERO, DL, N->getValueType(0),6752                         N->getOperand(1));6753    break;6754  case Intrinsic::loongarch_lsx_bz_v:6755  case Intrinsic::loongarch_lasx_xbz_v:6756    if (!Subtarget.is64Bit())6757      return DAG.getNode(LoongArchISD::VANY_ZERO, DL, N->getValueType(0),6758                         N->getOperand(1));6759    break;6760  case Intrinsic::loongarch_lsx_bnz_b:6761  case Intrinsic::loongarch_lsx_bnz_h:6762  case Intrinsic::loongarch_lsx_bnz_w:6763  case Intrinsic::loongarch_lsx_bnz_d:6764  case Intrinsic::loongarch_lasx_xbnz_b:6765  case Intrinsic::loongarch_lasx_xbnz_h:6766  case Intrinsic::loongarch_lasx_xbnz_w:6767  case Intrinsic::loongarch_lasx_xbnz_d:6768    if (!Subtarget.is64Bit())6769      return DAG.getNode(LoongArchISD::VALL_NONZERO, DL, N->getValueType(0),6770                         N->getOperand(1));6771    break;6772  case Intrinsic::loongarch_lsx_bnz_v:6773  case Intrinsic::loongarch_lasx_xbnz_v:6774    if (!Subtarget.is64Bit())6775      return DAG.getNode(LoongArchISD::VANY_NONZERO, DL, N->getValueType(0),6776                         N->getOperand(1));6777    break;6778  case Intrinsic::loongarch_lasx_concat_128_s:6779  case Intrinsic::loongarch_lasx_concat_128_d:6780  case Intrinsic::loongarch_lasx_concat_128:6781    return DAG.getNode(ISD::CONCAT_VECTORS, DL, N->getValueType(0),6782                       N->getOperand(1), N->getOperand(2));6783  }6784  return SDValue();6785}6786 6787static SDValue performMOVGR2FR_WCombine(SDNode *N, SelectionDAG &DAG,6788                                        TargetLowering::DAGCombinerInfo &DCI,6789                                        const LoongArchSubtarget &Subtarget) {6790  // If the input to MOVGR2FR_W_LA64 is just MOVFR2GR_S_LA64 the the6791  // conversion is unnecessary and can be replaced with the6792  // MOVFR2GR_S_LA64 operand.6793  SDValue Op0 = N->getOperand(0);6794  if (Op0.getOpcode() == LoongArchISD::MOVFR2GR_S_LA64)6795    return Op0.getOperand(0);6796  return SDValue();6797}6798 6799static SDValue performMOVFR2GR_SCombine(SDNode *N, SelectionDAG &DAG,6800                                        TargetLowering::DAGCombinerInfo &DCI,6801                                        const LoongArchSubtarget &Subtarget) {6802  // If the input to MOVFR2GR_S_LA64 is just MOVGR2FR_W_LA64 then the6803  // conversion is unnecessary and can be replaced with the MOVGR2FR_W_LA646804  // operand.6805  SDValue Op0 = N->getOperand(0);6806  if (Op0->getOpcode() == LoongArchISD::MOVGR2FR_W_LA64) {6807    assert(Op0.getOperand(0).getValueType() == N->getSimpleValueType(0) &&6808           "Unexpected value type!");6809    return Op0.getOperand(0);6810  }6811  return SDValue();6812}6813 6814static SDValue performVMSKLTZCombine(SDNode *N, SelectionDAG &DAG,6815                                     TargetLowering::DAGCombinerInfo &DCI,6816                                     const LoongArchSubtarget &Subtarget) {6817  MVT VT = N->getSimpleValueType(0);6818  unsigned NumBits = VT.getScalarSizeInBits();6819 6820  // Simplify the inputs.6821  const TargetLowering &TLI = DAG.getTargetLoweringInfo();6822  APInt DemandedMask(APInt::getAllOnes(NumBits));6823  if (TLI.SimplifyDemandedBits(SDValue(N, 0), DemandedMask, DCI))6824    return SDValue(N, 0);6825 6826  return SDValue();6827}6828 6829static SDValue6830performSPLIT_PAIR_F64Combine(SDNode *N, SelectionDAG &DAG,6831                             TargetLowering::DAGCombinerInfo &DCI,6832                             const LoongArchSubtarget &Subtarget) {6833  SDValue Op0 = N->getOperand(0);6834  SDLoc DL(N);6835 6836  // If the input to SplitPairF64 is just BuildPairF64 then the operation is6837  // redundant. Instead, use BuildPairF64's operands directly.6838  if (Op0->getOpcode() == LoongArchISD::BUILD_PAIR_F64)6839    return DCI.CombineTo(N, Op0.getOperand(0), Op0.getOperand(1));6840 6841  if (Op0->isUndef()) {6842    SDValue Lo = DAG.getUNDEF(MVT::i32);6843    SDValue Hi = DAG.getUNDEF(MVT::i32);6844    return DCI.CombineTo(N, Lo, Hi);6845  }6846 6847  // It's cheaper to materialise two 32-bit integers than to load a double6848  // from the constant pool and transfer it to integer registers through the6849  // stack.6850  if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Op0)) {6851    APInt V = C->getValueAPF().bitcastToAPInt();6852    SDValue Lo = DAG.getConstant(V.trunc(32), DL, MVT::i32);6853    SDValue Hi = DAG.getConstant(V.lshr(32).trunc(32), DL, MVT::i32);6854    return DCI.CombineTo(N, Lo, Hi);6855  }6856 6857  return SDValue();6858}6859 6860static SDValue6861performEXTRACT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG,6862                                 TargetLowering::DAGCombinerInfo &DCI,6863                                 const LoongArchSubtarget &Subtarget) {6864  if (!DCI.isBeforeLegalize())6865    return SDValue();6866 6867  MVT EltVT = N->getSimpleValueType(0);6868  SDValue Vec = N->getOperand(0);6869  EVT VecTy = Vec->getValueType(0);6870  SDValue Idx = N->getOperand(1);6871  unsigned IdxOp = Idx.getOpcode();6872  SDLoc DL(N);6873 6874  if (!VecTy.is256BitVector() || isa<ConstantSDNode>(Idx))6875    return SDValue();6876 6877  // Combine:6878  //   t2 = truncate t16879  //   t3 = {zero/sign/any}_extend t26880  //   t4 = extract_vector_elt t0, t36881  // to:6882  //   t4 = extract_vector_elt t0, t16883  if (IdxOp == ISD::ZERO_EXTEND || IdxOp == ISD::SIGN_EXTEND ||6884      IdxOp == ISD::ANY_EXTEND) {6885    SDValue IdxOrig = Idx.getOperand(0);6886    if (!(IdxOrig.getOpcode() == ISD::TRUNCATE))6887      return SDValue();6888 6889    return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, Vec,6890                       IdxOrig.getOperand(0));6891  }6892 6893  return SDValue();6894}6895 6896/// Do target-specific dag combines on LoongArchISD::VANDN nodes.6897static SDValue performVANDNCombine(SDNode *N, SelectionDAG &DAG,6898                                   TargetLowering::DAGCombinerInfo &DCI,6899                                   const LoongArchSubtarget &Subtarget) {6900  SDValue N0 = N->getOperand(0);6901  SDValue N1 = N->getOperand(1);6902  MVT VT = N->getSimpleValueType(0);6903  SDLoc DL(N);6904 6905  // VANDN(undef, x) -> 06906  // VANDN(x, undef) -> 06907  if (N0.isUndef() || N1.isUndef())6908    return DAG.getConstant(0, DL, VT);6909 6910  // VANDN(0, x) -> x6911  if (ISD::isBuildVectorAllZeros(N0.getNode()))6912    return N1;6913 6914  // VANDN(x, 0) -> 06915  if (ISD::isBuildVectorAllZeros(N1.getNode()))6916    return DAG.getConstant(0, DL, VT);6917 6918  // VANDN(x, -1) -> NOT(x) -> XOR(x, -1)6919  if (ISD::isBuildVectorAllOnes(N1.getNode()))6920    return DAG.getNOT(DL, N0, VT);6921 6922  // Turn VANDN back to AND if input is inverted.6923  if (SDValue Not = isNOT(N0, DAG))6924    return DAG.getNode(ISD::AND, DL, VT, DAG.getBitcast(VT, Not), N1);6925 6926  // Folds for better commutativity:6927  if (N1->hasOneUse()) {6928    // VANDN(x,NOT(y)) -> AND(NOT(x),NOT(y)) -> NOT(OR(X,Y)).6929    if (SDValue Not = isNOT(N1, DAG))6930      return DAG.getNOT(6931          DL, DAG.getNode(ISD::OR, DL, VT, N0, DAG.getBitcast(VT, Not)), VT);6932 6933    // VANDN(x, SplatVector(Imm)) -> AND(NOT(x), NOT(SplatVector(~Imm)))6934    // -> NOT(OR(x, SplatVector(-Imm))6935    // Combination is performed only when VT is v16i8/v32i8, using `vnori.b` to6936    // gain benefits.6937    if (!DCI.isBeforeLegalizeOps() && (VT == MVT::v16i8 || VT == MVT::v32i8) &&6938        N1.getOpcode() == ISD::BUILD_VECTOR) {6939      if (SDValue SplatValue =6940              cast<BuildVectorSDNode>(N1.getNode())->getSplatValue()) {6941        if (!N1->isOnlyUserOf(SplatValue.getNode()))6942          return SDValue();6943 6944        if (auto *C = dyn_cast<ConstantSDNode>(SplatValue)) {6945          uint8_t NCVal = static_cast<uint8_t>(~(C->getSExtValue()));6946          SDValue Not =6947              DAG.getSplat(VT, DL, DAG.getTargetConstant(NCVal, DL, MVT::i8));6948          return DAG.getNOT(6949              DL, DAG.getNode(ISD::OR, DL, VT, N0, DAG.getBitcast(VT, Not)),6950              VT);6951        }6952      }6953    }6954  }6955 6956  return SDValue();6957}6958 6959SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N,6960                                                   DAGCombinerInfo &DCI) const {6961  SelectionDAG &DAG = DCI.DAG;6962  switch (N->getOpcode()) {6963  default:6964    break;6965  case ISD::AND:6966    return performANDCombine(N, DAG, DCI, Subtarget);6967  case ISD::OR:6968    return performORCombine(N, DAG, DCI, Subtarget);6969  case ISD::SETCC:6970    return performSETCCCombine(N, DAG, DCI, Subtarget);6971  case ISD::SRL:6972    return performSRLCombine(N, DAG, DCI, Subtarget);6973  case ISD::BITCAST:6974    return performBITCASTCombine(N, DAG, DCI, Subtarget);6975  case LoongArchISD::BITREV_W:6976    return performBITREV_WCombine(N, DAG, DCI, Subtarget);6977  case LoongArchISD::BR_CC:6978    return performBR_CCCombine(N, DAG, DCI, Subtarget);6979  case LoongArchISD::SELECT_CC:6980    return performSELECT_CCCombine(N, DAG, DCI, Subtarget);6981  case ISD::INTRINSIC_WO_CHAIN:6982    return performINTRINSIC_WO_CHAINCombine(N, DAG, DCI, Subtarget);6983  case LoongArchISD::MOVGR2FR_W_LA64:6984    return performMOVGR2FR_WCombine(N, DAG, DCI, Subtarget);6985  case LoongArchISD::MOVFR2GR_S_LA64:6986    return performMOVFR2GR_SCombine(N, DAG, DCI, Subtarget);6987  case LoongArchISD::VMSKLTZ:6988  case LoongArchISD::XVMSKLTZ:6989    return performVMSKLTZCombine(N, DAG, DCI, Subtarget);6990  case LoongArchISD::SPLIT_PAIR_F64:6991    return performSPLIT_PAIR_F64Combine(N, DAG, DCI, Subtarget);6992  case ISD::EXTRACT_VECTOR_ELT:6993    return performEXTRACT_VECTOR_ELTCombine(N, DAG, DCI, Subtarget);6994  case LoongArchISD::VANDN:6995    return performVANDNCombine(N, DAG, DCI, Subtarget);6996  }6997  return SDValue();6998}6999 7000static MachineBasicBlock *insertDivByZeroTrap(MachineInstr &MI,7001                                              MachineBasicBlock *MBB) {7002  if (!ZeroDivCheck)7003    return MBB;7004 7005  // Build instructions:7006  // MBB:7007  //   div(or mod)   $dst, $dividend, $divisor7008  //   bne           $divisor, $zero, SinkMBB7009  // BreakMBB:7010  //   break         7 // BRK_DIVZERO7011  // SinkMBB:7012  //   fallthrough7013  const BasicBlock *LLVM_BB = MBB->getBasicBlock();7014  MachineFunction::iterator It = ++MBB->getIterator();7015  MachineFunction *MF = MBB->getParent();7016  auto BreakMBB = MF->CreateMachineBasicBlock(LLVM_BB);7017  auto SinkMBB = MF->CreateMachineBasicBlock(LLVM_BB);7018  MF->insert(It, BreakMBB);7019  MF->insert(It, SinkMBB);7020 7021  // Transfer the remainder of MBB and its successor edges to SinkMBB.7022  SinkMBB->splice(SinkMBB->end(), MBB, std::next(MI.getIterator()), MBB->end());7023  SinkMBB->transferSuccessorsAndUpdatePHIs(MBB);7024 7025  const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();7026  DebugLoc DL = MI.getDebugLoc();7027  MachineOperand &Divisor = MI.getOperand(2);7028  Register DivisorReg = Divisor.getReg();7029 7030  // MBB:7031  BuildMI(MBB, DL, TII.get(LoongArch::BNE))7032      .addReg(DivisorReg, getKillRegState(Divisor.isKill()))7033      .addReg(LoongArch::R0)7034      .addMBB(SinkMBB);7035  MBB->addSuccessor(BreakMBB);7036  MBB->addSuccessor(SinkMBB);7037 7038  // BreakMBB:7039  // See linux header file arch/loongarch/include/uapi/asm/break.h for the7040  // definition of BRK_DIVZERO.7041  BuildMI(BreakMBB, DL, TII.get(LoongArch::BREAK)).addImm(7 /*BRK_DIVZERO*/);7042  BreakMBB->addSuccessor(SinkMBB);7043 7044  // Clear Divisor's kill flag.7045  Divisor.setIsKill(false);7046 7047  return SinkMBB;7048}7049 7050static MachineBasicBlock *7051emitVecCondBranchPseudo(MachineInstr &MI, MachineBasicBlock *BB,7052                        const LoongArchSubtarget &Subtarget) {7053  unsigned CondOpc;7054  switch (MI.getOpcode()) {7055  default:7056    llvm_unreachable("Unexpected opcode");7057  case LoongArch::PseudoVBZ:7058    CondOpc = LoongArch::VSETEQZ_V;7059    break;7060  case LoongArch::PseudoVBZ_B:7061    CondOpc = LoongArch::VSETANYEQZ_B;7062    break;7063  case LoongArch::PseudoVBZ_H:7064    CondOpc = LoongArch::VSETANYEQZ_H;7065    break;7066  case LoongArch::PseudoVBZ_W:7067    CondOpc = LoongArch::VSETANYEQZ_W;7068    break;7069  case LoongArch::PseudoVBZ_D:7070    CondOpc = LoongArch::VSETANYEQZ_D;7071    break;7072  case LoongArch::PseudoVBNZ:7073    CondOpc = LoongArch::VSETNEZ_V;7074    break;7075  case LoongArch::PseudoVBNZ_B:7076    CondOpc = LoongArch::VSETALLNEZ_B;7077    break;7078  case LoongArch::PseudoVBNZ_H:7079    CondOpc = LoongArch::VSETALLNEZ_H;7080    break;7081  case LoongArch::PseudoVBNZ_W:7082    CondOpc = LoongArch::VSETALLNEZ_W;7083    break;7084  case LoongArch::PseudoVBNZ_D:7085    CondOpc = LoongArch::VSETALLNEZ_D;7086    break;7087  case LoongArch::PseudoXVBZ:7088    CondOpc = LoongArch::XVSETEQZ_V;7089    break;7090  case LoongArch::PseudoXVBZ_B:7091    CondOpc = LoongArch::XVSETANYEQZ_B;7092    break;7093  case LoongArch::PseudoXVBZ_H:7094    CondOpc = LoongArch::XVSETANYEQZ_H;7095    break;7096  case LoongArch::PseudoXVBZ_W:7097    CondOpc = LoongArch::XVSETANYEQZ_W;7098    break;7099  case LoongArch::PseudoXVBZ_D:7100    CondOpc = LoongArch::XVSETANYEQZ_D;7101    break;7102  case LoongArch::PseudoXVBNZ:7103    CondOpc = LoongArch::XVSETNEZ_V;7104    break;7105  case LoongArch::PseudoXVBNZ_B:7106    CondOpc = LoongArch::XVSETALLNEZ_B;7107    break;7108  case LoongArch::PseudoXVBNZ_H:7109    CondOpc = LoongArch::XVSETALLNEZ_H;7110    break;7111  case LoongArch::PseudoXVBNZ_W:7112    CondOpc = LoongArch::XVSETALLNEZ_W;7113    break;7114  case LoongArch::PseudoXVBNZ_D:7115    CondOpc = LoongArch::XVSETALLNEZ_D;7116    break;7117  }7118 7119  const TargetInstrInfo *TII = Subtarget.getInstrInfo();7120  const BasicBlock *LLVM_BB = BB->getBasicBlock();7121  DebugLoc DL = MI.getDebugLoc();7122  MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();7123  MachineFunction::iterator It = ++BB->getIterator();7124 7125  MachineFunction *F = BB->getParent();7126  MachineBasicBlock *FalseBB = F->CreateMachineBasicBlock(LLVM_BB);7127  MachineBasicBlock *TrueBB = F->CreateMachineBasicBlock(LLVM_BB);7128  MachineBasicBlock *SinkBB = F->CreateMachineBasicBlock(LLVM_BB);7129 7130  F->insert(It, FalseBB);7131  F->insert(It, TrueBB);7132  F->insert(It, SinkBB);7133 7134  // Transfer the remainder of MBB and its successor edges to Sink.7135  SinkBB->splice(SinkBB->end(), BB, std::next(MI.getIterator()), BB->end());7136  SinkBB->transferSuccessorsAndUpdatePHIs(BB);7137 7138  // Insert the real instruction to BB.7139  Register FCC = MRI.createVirtualRegister(&LoongArch::CFRRegClass);7140  BuildMI(BB, DL, TII->get(CondOpc), FCC).addReg(MI.getOperand(1).getReg());7141 7142  // Insert branch.7143  BuildMI(BB, DL, TII->get(LoongArch::BCNEZ)).addReg(FCC).addMBB(TrueBB);7144  BB->addSuccessor(FalseBB);7145  BB->addSuccessor(TrueBB);7146 7147  // FalseBB.7148  Register RD1 = MRI.createVirtualRegister(&LoongArch::GPRRegClass);7149  BuildMI(FalseBB, DL, TII->get(LoongArch::ADDI_W), RD1)7150      .addReg(LoongArch::R0)7151      .addImm(0);7152  BuildMI(FalseBB, DL, TII->get(LoongArch::PseudoBR)).addMBB(SinkBB);7153  FalseBB->addSuccessor(SinkBB);7154 7155  // TrueBB.7156  Register RD2 = MRI.createVirtualRegister(&LoongArch::GPRRegClass);7157  BuildMI(TrueBB, DL, TII->get(LoongArch::ADDI_W), RD2)7158      .addReg(LoongArch::R0)7159      .addImm(1);7160  TrueBB->addSuccessor(SinkBB);7161 7162  // SinkBB: merge the results.7163  BuildMI(*SinkBB, SinkBB->begin(), DL, TII->get(LoongArch::PHI),7164          MI.getOperand(0).getReg())7165      .addReg(RD1)7166      .addMBB(FalseBB)7167      .addReg(RD2)7168      .addMBB(TrueBB);7169 7170  // The pseudo instruction is gone now.7171  MI.eraseFromParent();7172  return SinkBB;7173}7174 7175static MachineBasicBlock *7176emitPseudoXVINSGR2VR(MachineInstr &MI, MachineBasicBlock *BB,7177                     const LoongArchSubtarget &Subtarget) {7178  unsigned InsOp;7179  unsigned BroadcastOp;7180  unsigned HalfSize;7181  switch (MI.getOpcode()) {7182  default:7183    llvm_unreachable("Unexpected opcode");7184  case LoongArch::PseudoXVINSGR2VR_B:7185    HalfSize = 16;7186    BroadcastOp = LoongArch::XVREPLGR2VR_B;7187    InsOp = LoongArch::XVEXTRINS_B;7188    break;7189  case LoongArch::PseudoXVINSGR2VR_H:7190    HalfSize = 8;7191    BroadcastOp = LoongArch::XVREPLGR2VR_H;7192    InsOp = LoongArch::XVEXTRINS_H;7193    break;7194  }7195  const TargetInstrInfo *TII = Subtarget.getInstrInfo();7196  const TargetRegisterClass *RC = &LoongArch::LASX256RegClass;7197  const TargetRegisterClass *SubRC = &LoongArch::LSX128RegClass;7198  DebugLoc DL = MI.getDebugLoc();7199  MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();7200  // XDst = vector_insert XSrc, Elt, Idx7201  Register XDst = MI.getOperand(0).getReg();7202  Register XSrc = MI.getOperand(1).getReg();7203  Register Elt = MI.getOperand(2).getReg();7204  unsigned Idx = MI.getOperand(3).getImm();7205 7206  if (XSrc.isVirtual() && MRI.getVRegDef(XSrc)->isImplicitDef() &&7207      Idx < HalfSize) {7208    Register ScratchSubReg1 = MRI.createVirtualRegister(SubRC);7209    Register ScratchSubReg2 = MRI.createVirtualRegister(SubRC);7210 7211    BuildMI(*BB, MI, DL, TII->get(LoongArch::COPY), ScratchSubReg1)7212        .addReg(XSrc, 0, LoongArch::sub_128);7213    BuildMI(*BB, MI, DL,7214            TII->get(HalfSize == 8 ? LoongArch::VINSGR2VR_H7215                                   : LoongArch::VINSGR2VR_B),7216            ScratchSubReg2)7217        .addReg(ScratchSubReg1)7218        .addReg(Elt)7219        .addImm(Idx);7220 7221    BuildMI(*BB, MI, DL, TII->get(LoongArch::SUBREG_TO_REG), XDst)7222        .addImm(0)7223        .addReg(ScratchSubReg2)7224        .addImm(LoongArch::sub_128);7225  } else {7226    Register ScratchReg1 = MRI.createVirtualRegister(RC);7227    Register ScratchReg2 = MRI.createVirtualRegister(RC);7228 7229    BuildMI(*BB, MI, DL, TII->get(BroadcastOp), ScratchReg1).addReg(Elt);7230 7231    BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPERMI_Q), ScratchReg2)7232        .addReg(ScratchReg1)7233        .addReg(XSrc)7234        .addImm(Idx >= HalfSize ? 48 : 18);7235 7236    BuildMI(*BB, MI, DL, TII->get(InsOp), XDst)7237        .addReg(XSrc)7238        .addReg(ScratchReg2)7239        .addImm((Idx >= HalfSize ? Idx - HalfSize : Idx) * 17);7240  }7241 7242  MI.eraseFromParent();7243  return BB;7244}7245 7246static MachineBasicBlock *emitPseudoCTPOP(MachineInstr &MI,7247                                          MachineBasicBlock *BB,7248                                          const LoongArchSubtarget &Subtarget) {7249  assert(Subtarget.hasExtLSX());7250  const TargetInstrInfo *TII = Subtarget.getInstrInfo();7251  const TargetRegisterClass *RC = &LoongArch::LSX128RegClass;7252  DebugLoc DL = MI.getDebugLoc();7253  MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();7254  Register Dst = MI.getOperand(0).getReg();7255  Register Src = MI.getOperand(1).getReg();7256  Register ScratchReg1 = MRI.createVirtualRegister(RC);7257  Register ScratchReg2 = MRI.createVirtualRegister(RC);7258  Register ScratchReg3 = MRI.createVirtualRegister(RC);7259 7260  BuildMI(*BB, MI, DL, TII->get(LoongArch::VLDI), ScratchReg1).addImm(0);7261  BuildMI(*BB, MI, DL,7262          TII->get(Subtarget.is64Bit() ? LoongArch::VINSGR2VR_D7263                                       : LoongArch::VINSGR2VR_W),7264          ScratchReg2)7265      .addReg(ScratchReg1)7266      .addReg(Src)7267      .addImm(0);7268  BuildMI(7269      *BB, MI, DL,7270      TII->get(Subtarget.is64Bit() ? LoongArch::VPCNT_D : LoongArch::VPCNT_W),7271      ScratchReg3)7272      .addReg(ScratchReg2);7273  BuildMI(*BB, MI, DL,7274          TII->get(Subtarget.is64Bit() ? LoongArch::VPICKVE2GR_D7275                                       : LoongArch::VPICKVE2GR_W),7276          Dst)7277      .addReg(ScratchReg3)7278      .addImm(0);7279 7280  MI.eraseFromParent();7281  return BB;7282}7283 7284static MachineBasicBlock *7285emitPseudoVMSKCOND(MachineInstr &MI, MachineBasicBlock *BB,7286                   const LoongArchSubtarget &Subtarget) {7287  const TargetInstrInfo *TII = Subtarget.getInstrInfo();7288  const TargetRegisterClass *RC = &LoongArch::LSX128RegClass;7289  const LoongArchRegisterInfo *TRI = Subtarget.getRegisterInfo();7290  MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();7291  Register Dst = MI.getOperand(0).getReg();7292  Register Src = MI.getOperand(1).getReg();7293  DebugLoc DL = MI.getDebugLoc();7294  unsigned EleBits = 8;7295  unsigned NotOpc = 0;7296  unsigned MskOpc;7297 7298  switch (MI.getOpcode()) {7299  default:7300    llvm_unreachable("Unexpected opcode");7301  case LoongArch::PseudoVMSKLTZ_B:7302    MskOpc = LoongArch::VMSKLTZ_B;7303    break;7304  case LoongArch::PseudoVMSKLTZ_H:7305    MskOpc = LoongArch::VMSKLTZ_H;7306    EleBits = 16;7307    break;7308  case LoongArch::PseudoVMSKLTZ_W:7309    MskOpc = LoongArch::VMSKLTZ_W;7310    EleBits = 32;7311    break;7312  case LoongArch::PseudoVMSKLTZ_D:7313    MskOpc = LoongArch::VMSKLTZ_D;7314    EleBits = 64;7315    break;7316  case LoongArch::PseudoVMSKGEZ_B:7317    MskOpc = LoongArch::VMSKGEZ_B;7318    break;7319  case LoongArch::PseudoVMSKEQZ_B:7320    MskOpc = LoongArch::VMSKNZ_B;7321    NotOpc = LoongArch::VNOR_V;7322    break;7323  case LoongArch::PseudoVMSKNEZ_B:7324    MskOpc = LoongArch::VMSKNZ_B;7325    break;7326  case LoongArch::PseudoXVMSKLTZ_B:7327    MskOpc = LoongArch::XVMSKLTZ_B;7328    RC = &LoongArch::LASX256RegClass;7329    break;7330  case LoongArch::PseudoXVMSKLTZ_H:7331    MskOpc = LoongArch::XVMSKLTZ_H;7332    RC = &LoongArch::LASX256RegClass;7333    EleBits = 16;7334    break;7335  case LoongArch::PseudoXVMSKLTZ_W:7336    MskOpc = LoongArch::XVMSKLTZ_W;7337    RC = &LoongArch::LASX256RegClass;7338    EleBits = 32;7339    break;7340  case LoongArch::PseudoXVMSKLTZ_D:7341    MskOpc = LoongArch::XVMSKLTZ_D;7342    RC = &LoongArch::LASX256RegClass;7343    EleBits = 64;7344    break;7345  case LoongArch::PseudoXVMSKGEZ_B:7346    MskOpc = LoongArch::XVMSKGEZ_B;7347    RC = &LoongArch::LASX256RegClass;7348    break;7349  case LoongArch::PseudoXVMSKEQZ_B:7350    MskOpc = LoongArch::XVMSKNZ_B;7351    NotOpc = LoongArch::XVNOR_V;7352    RC = &LoongArch::LASX256RegClass;7353    break;7354  case LoongArch::PseudoXVMSKNEZ_B:7355    MskOpc = LoongArch::XVMSKNZ_B;7356    RC = &LoongArch::LASX256RegClass;7357    break;7358  }7359 7360  Register Msk = MRI.createVirtualRegister(RC);7361  if (NotOpc) {7362    Register Tmp = MRI.createVirtualRegister(RC);7363    BuildMI(*BB, MI, DL, TII->get(MskOpc), Tmp).addReg(Src);7364    BuildMI(*BB, MI, DL, TII->get(NotOpc), Msk)7365        .addReg(Tmp, RegState::Kill)7366        .addReg(Tmp, RegState::Kill);7367  } else {7368    BuildMI(*BB, MI, DL, TII->get(MskOpc), Msk).addReg(Src);7369  }7370 7371  if (TRI->getRegSizeInBits(*RC) > 128) {7372    Register Lo = MRI.createVirtualRegister(&LoongArch::GPRRegClass);7373    Register Hi = MRI.createVirtualRegister(&LoongArch::GPRRegClass);7374    BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPICKVE2GR_WU), Lo)7375        .addReg(Msk)7376        .addImm(0);7377    BuildMI(*BB, MI, DL, TII->get(LoongArch::XVPICKVE2GR_WU), Hi)7378        .addReg(Msk, RegState::Kill)7379        .addImm(4);7380    BuildMI(*BB, MI, DL,7381            TII->get(Subtarget.is64Bit() ? LoongArch::BSTRINS_D7382                                         : LoongArch::BSTRINS_W),7383            Dst)7384        .addReg(Lo, RegState::Kill)7385        .addReg(Hi, RegState::Kill)7386        .addImm(256 / EleBits - 1)7387        .addImm(128 / EleBits);7388  } else {7389    BuildMI(*BB, MI, DL, TII->get(LoongArch::VPICKVE2GR_HU), Dst)7390        .addReg(Msk, RegState::Kill)7391        .addImm(0);7392  }7393 7394  MI.eraseFromParent();7395  return BB;7396}7397 7398static MachineBasicBlock *7399emitSplitPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB,7400                       const LoongArchSubtarget &Subtarget) {7401  assert(MI.getOpcode() == LoongArch::SplitPairF64Pseudo &&7402         "Unexpected instruction");7403 7404  MachineFunction &MF = *BB->getParent();7405  DebugLoc DL = MI.getDebugLoc();7406  const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();7407  Register LoReg = MI.getOperand(0).getReg();7408  Register HiReg = MI.getOperand(1).getReg();7409  Register SrcReg = MI.getOperand(2).getReg();7410 7411  BuildMI(*BB, MI, DL, TII.get(LoongArch::MOVFR2GR_S_64), LoReg).addReg(SrcReg);7412  BuildMI(*BB, MI, DL, TII.get(LoongArch::MOVFRH2GR_S), HiReg)7413      .addReg(SrcReg, getKillRegState(MI.getOperand(2).isKill()));7414  MI.eraseFromParent(); // The pseudo instruction is gone now.7415  return BB;7416}7417 7418static MachineBasicBlock *7419emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB,7420                       const LoongArchSubtarget &Subtarget) {7421  assert(MI.getOpcode() == LoongArch::BuildPairF64Pseudo &&7422         "Unexpected instruction");7423 7424  MachineFunction &MF = *BB->getParent();7425  DebugLoc DL = MI.getDebugLoc();7426  const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();7427  MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();7428  Register TmpReg = MRI.createVirtualRegister(&LoongArch::FPR64RegClass);7429  Register DstReg = MI.getOperand(0).getReg();7430  Register LoReg = MI.getOperand(1).getReg();7431  Register HiReg = MI.getOperand(2).getReg();7432 7433  BuildMI(*BB, MI, DL, TII.get(LoongArch::MOVGR2FR_W_64), TmpReg)7434      .addReg(LoReg, getKillRegState(MI.getOperand(1).isKill()));7435  BuildMI(*BB, MI, DL, TII.get(LoongArch::MOVGR2FRH_W), DstReg)7436      .addReg(TmpReg, RegState::Kill)7437      .addReg(HiReg, getKillRegState(MI.getOperand(2).isKill()));7438  MI.eraseFromParent(); // The pseudo instruction is gone now.7439  return BB;7440}7441 7442static bool isSelectPseudo(MachineInstr &MI) {7443  switch (MI.getOpcode()) {7444  default:7445    return false;7446  case LoongArch::Select_GPR_Using_CC_GPR:7447    return true;7448  }7449}7450 7451static MachineBasicBlock *7452emitSelectPseudo(MachineInstr &MI, MachineBasicBlock *BB,7453                 const LoongArchSubtarget &Subtarget) {7454  // To "insert" Select_* instructions, we actually have to insert the triangle7455  // control-flow pattern.  The incoming instructions know the destination vreg7456  // to set, the condition code register to branch on, the true/false values to7457  // select between, and the condcode to use to select the appropriate branch.7458  //7459  // We produce the following control flow:7460  //     HeadMBB7461  //     |  \7462  //     |  IfFalseMBB7463  //     | /7464  //    TailMBB7465  //7466  // When we find a sequence of selects we attempt to optimize their emission7467  // by sharing the control flow. Currently we only handle cases where we have7468  // multiple selects with the exact same condition (same LHS, RHS and CC).7469  // The selects may be interleaved with other instructions if the other7470  // instructions meet some requirements we deem safe:7471  // - They are not pseudo instructions.7472  // - They are debug instructions. Otherwise,7473  // - They do not have side-effects, do not access memory and their inputs do7474  //   not depend on the results of the select pseudo-instructions.7475  // The TrueV/FalseV operands of the selects cannot depend on the result of7476  // previous selects in the sequence.7477  // These conditions could be further relaxed. See the X86 target for a7478  // related approach and more information.7479 7480  Register LHS = MI.getOperand(1).getReg();7481  Register RHS;7482  if (MI.getOperand(2).isReg())7483    RHS = MI.getOperand(2).getReg();7484  auto CC = static_cast<unsigned>(MI.getOperand(3).getImm());7485 7486  SmallVector<MachineInstr *, 4> SelectDebugValues;7487  SmallSet<Register, 4> SelectDests;7488  SelectDests.insert(MI.getOperand(0).getReg());7489 7490  MachineInstr *LastSelectPseudo = &MI;7491  for (auto E = BB->end(), SequenceMBBI = MachineBasicBlock::iterator(MI);7492       SequenceMBBI != E; ++SequenceMBBI) {7493    if (SequenceMBBI->isDebugInstr())7494      continue;7495    if (isSelectPseudo(*SequenceMBBI)) {7496      if (SequenceMBBI->getOperand(1).getReg() != LHS ||7497          !SequenceMBBI->getOperand(2).isReg() ||7498          SequenceMBBI->getOperand(2).getReg() != RHS ||7499          SequenceMBBI->getOperand(3).getImm() != CC ||7500          SelectDests.count(SequenceMBBI->getOperand(4).getReg()) ||7501          SelectDests.count(SequenceMBBI->getOperand(5).getReg()))7502        break;7503      LastSelectPseudo = &*SequenceMBBI;7504      SequenceMBBI->collectDebugValues(SelectDebugValues);7505      SelectDests.insert(SequenceMBBI->getOperand(0).getReg());7506      continue;7507    }7508    if (SequenceMBBI->hasUnmodeledSideEffects() ||7509        SequenceMBBI->mayLoadOrStore() ||7510        SequenceMBBI->usesCustomInsertionHook())7511      break;7512    if (llvm::any_of(SequenceMBBI->operands(), [&](MachineOperand &MO) {7513          return MO.isReg() && MO.isUse() && SelectDests.count(MO.getReg());7514        }))7515      break;7516  }7517 7518  const LoongArchInstrInfo &TII = *Subtarget.getInstrInfo();7519  const BasicBlock *LLVM_BB = BB->getBasicBlock();7520  DebugLoc DL = MI.getDebugLoc();7521  MachineFunction::iterator I = ++BB->getIterator();7522 7523  MachineBasicBlock *HeadMBB = BB;7524  MachineFunction *F = BB->getParent();7525  MachineBasicBlock *TailMBB = F->CreateMachineBasicBlock(LLVM_BB);7526  MachineBasicBlock *IfFalseMBB = F->CreateMachineBasicBlock(LLVM_BB);7527 7528  F->insert(I, IfFalseMBB);7529  F->insert(I, TailMBB);7530 7531  // Set the call frame size on entry to the new basic blocks.7532  unsigned CallFrameSize = TII.getCallFrameSizeAt(*LastSelectPseudo);7533  IfFalseMBB->setCallFrameSize(CallFrameSize);7534  TailMBB->setCallFrameSize(CallFrameSize);7535 7536  // Transfer debug instructions associated with the selects to TailMBB.7537  for (MachineInstr *DebugInstr : SelectDebugValues) {7538    TailMBB->push_back(DebugInstr->removeFromParent());7539  }7540 7541  // Move all instructions after the sequence to TailMBB.7542  TailMBB->splice(TailMBB->end(), HeadMBB,7543                  std::next(LastSelectPseudo->getIterator()), HeadMBB->end());7544  // Update machine-CFG edges by transferring all successors of the current7545  // block to the new block which will contain the Phi nodes for the selects.7546  TailMBB->transferSuccessorsAndUpdatePHIs(HeadMBB);7547  // Set the successors for HeadMBB.7548  HeadMBB->addSuccessor(IfFalseMBB);7549  HeadMBB->addSuccessor(TailMBB);7550 7551  // Insert appropriate branch.7552  if (MI.getOperand(2).isImm())7553    BuildMI(HeadMBB, DL, TII.get(CC))7554        .addReg(LHS)7555        .addImm(MI.getOperand(2).getImm())7556        .addMBB(TailMBB);7557  else7558    BuildMI(HeadMBB, DL, TII.get(CC)).addReg(LHS).addReg(RHS).addMBB(TailMBB);7559 7560  // IfFalseMBB just falls through to TailMBB.7561  IfFalseMBB->addSuccessor(TailMBB);7562 7563  // Create PHIs for all of the select pseudo-instructions.7564  auto SelectMBBI = MI.getIterator();7565  auto SelectEnd = std::next(LastSelectPseudo->getIterator());7566  auto InsertionPoint = TailMBB->begin();7567  while (SelectMBBI != SelectEnd) {7568    auto Next = std::next(SelectMBBI);7569    if (isSelectPseudo(*SelectMBBI)) {7570      // %Result = phi [ %TrueValue, HeadMBB ], [ %FalseValue, IfFalseMBB ]7571      BuildMI(*TailMBB, InsertionPoint, SelectMBBI->getDebugLoc(),7572              TII.get(LoongArch::PHI), SelectMBBI->getOperand(0).getReg())7573          .addReg(SelectMBBI->getOperand(4).getReg())7574          .addMBB(HeadMBB)7575          .addReg(SelectMBBI->getOperand(5).getReg())7576          .addMBB(IfFalseMBB);7577      SelectMBBI->eraseFromParent();7578    }7579    SelectMBBI = Next;7580  }7581 7582  F->getProperties().resetNoPHIs();7583  return TailMBB;7584}7585 7586MachineBasicBlock *LoongArchTargetLowering::EmitInstrWithCustomInserter(7587    MachineInstr &MI, MachineBasicBlock *BB) const {7588  const TargetInstrInfo *TII = Subtarget.getInstrInfo();7589  DebugLoc DL = MI.getDebugLoc();7590 7591  switch (MI.getOpcode()) {7592  default:7593    llvm_unreachable("Unexpected instr type to insert");7594  case LoongArch::DIV_W:7595  case LoongArch::DIV_WU:7596  case LoongArch::MOD_W:7597  case LoongArch::MOD_WU:7598  case LoongArch::DIV_D:7599  case LoongArch::DIV_DU:7600  case LoongArch::MOD_D:7601  case LoongArch::MOD_DU:7602    return insertDivByZeroTrap(MI, BB);7603    break;7604  case LoongArch::WRFCSR: {7605    BuildMI(*BB, MI, DL, TII->get(LoongArch::MOVGR2FCSR),7606            LoongArch::FCSR0 + MI.getOperand(0).getImm())7607        .addReg(MI.getOperand(1).getReg());7608    MI.eraseFromParent();7609    return BB;7610  }7611  case LoongArch::RDFCSR: {7612    MachineInstr *ReadFCSR =7613        BuildMI(*BB, MI, DL, TII->get(LoongArch::MOVFCSR2GR),7614                MI.getOperand(0).getReg())7615            .addReg(LoongArch::FCSR0 + MI.getOperand(1).getImm());7616    ReadFCSR->getOperand(1).setIsUndef();7617    MI.eraseFromParent();7618    return BB;7619  }7620  case LoongArch::Select_GPR_Using_CC_GPR:7621    return emitSelectPseudo(MI, BB, Subtarget);7622  case LoongArch::BuildPairF64Pseudo:7623    return emitBuildPairF64Pseudo(MI, BB, Subtarget);7624  case LoongArch::SplitPairF64Pseudo:7625    return emitSplitPairF64Pseudo(MI, BB, Subtarget);7626  case LoongArch::PseudoVBZ:7627  case LoongArch::PseudoVBZ_B:7628  case LoongArch::PseudoVBZ_H:7629  case LoongArch::PseudoVBZ_W:7630  case LoongArch::PseudoVBZ_D:7631  case LoongArch::PseudoVBNZ:7632  case LoongArch::PseudoVBNZ_B:7633  case LoongArch::PseudoVBNZ_H:7634  case LoongArch::PseudoVBNZ_W:7635  case LoongArch::PseudoVBNZ_D:7636  case LoongArch::PseudoXVBZ:7637  case LoongArch::PseudoXVBZ_B:7638  case LoongArch::PseudoXVBZ_H:7639  case LoongArch::PseudoXVBZ_W:7640  case LoongArch::PseudoXVBZ_D:7641  case LoongArch::PseudoXVBNZ:7642  case LoongArch::PseudoXVBNZ_B:7643  case LoongArch::PseudoXVBNZ_H:7644  case LoongArch::PseudoXVBNZ_W:7645  case LoongArch::PseudoXVBNZ_D:7646    return emitVecCondBranchPseudo(MI, BB, Subtarget);7647  case LoongArch::PseudoXVINSGR2VR_B:7648  case LoongArch::PseudoXVINSGR2VR_H:7649    return emitPseudoXVINSGR2VR(MI, BB, Subtarget);7650  case LoongArch::PseudoCTPOP:7651    return emitPseudoCTPOP(MI, BB, Subtarget);7652  case LoongArch::PseudoVMSKLTZ_B:7653  case LoongArch::PseudoVMSKLTZ_H:7654  case LoongArch::PseudoVMSKLTZ_W:7655  case LoongArch::PseudoVMSKLTZ_D:7656  case LoongArch::PseudoVMSKGEZ_B:7657  case LoongArch::PseudoVMSKEQZ_B:7658  case LoongArch::PseudoVMSKNEZ_B:7659  case LoongArch::PseudoXVMSKLTZ_B:7660  case LoongArch::PseudoXVMSKLTZ_H:7661  case LoongArch::PseudoXVMSKLTZ_W:7662  case LoongArch::PseudoXVMSKLTZ_D:7663  case LoongArch::PseudoXVMSKGEZ_B:7664  case LoongArch::PseudoXVMSKEQZ_B:7665  case LoongArch::PseudoXVMSKNEZ_B:7666    return emitPseudoVMSKCOND(MI, BB, Subtarget);7667  case TargetOpcode::STATEPOINT:7668    // STATEPOINT is a pseudo instruction which has no implicit defs/uses7669    // while bl call instruction (where statepoint will be lowered at the7670    // end) has implicit def. This def is early-clobber as it will be set at7671    // the moment of the call and earlier than any use is read.7672    // Add this implicit dead def here as a workaround.7673    MI.addOperand(*MI.getMF(),7674                  MachineOperand::CreateReg(7675                      LoongArch::R1, /*isDef*/ true,7676                      /*isImp*/ true, /*isKill*/ false, /*isDead*/ true,7677                      /*isUndef*/ false, /*isEarlyClobber*/ true));7678    if (!Subtarget.is64Bit())7679      report_fatal_error("STATEPOINT is only supported on 64-bit targets");7680    return emitPatchPoint(MI, BB);7681  }7682}7683 7684bool LoongArchTargetLowering::allowsMisalignedMemoryAccesses(7685    EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,7686    unsigned *Fast) const {7687  if (!Subtarget.hasUAL())7688    return false;7689 7690  // TODO: set reasonable speed number.7691  if (Fast)7692    *Fast = 1;7693  return true;7694}7695 7696//===----------------------------------------------------------------------===//7697//                     Calling Convention Implementation7698//===----------------------------------------------------------------------===//7699 7700// Eight general-purpose registers a0-a7 used for passing integer arguments,7701// with a0-a1 reused to return values. Generally, the GPRs are used to pass7702// fixed-point arguments, and floating-point arguments when no FPR is available7703// or with soft float ABI.7704const MCPhysReg ArgGPRs[] = {LoongArch::R4,  LoongArch::R5, LoongArch::R6,7705                             LoongArch::R7,  LoongArch::R8, LoongArch::R9,7706                             LoongArch::R10, LoongArch::R11};7707// Eight floating-point registers fa0-fa7 used for passing floating-point7708// arguments, and fa0-fa1 are also used to return values.7709const MCPhysReg ArgFPR32s[] = {LoongArch::F0, LoongArch::F1, LoongArch::F2,7710                               LoongArch::F3, LoongArch::F4, LoongArch::F5,7711                               LoongArch::F6, LoongArch::F7};7712// FPR32 and FPR64 alias each other.7713const MCPhysReg ArgFPR64s[] = {7714    LoongArch::F0_64, LoongArch::F1_64, LoongArch::F2_64, LoongArch::F3_64,7715    LoongArch::F4_64, LoongArch::F5_64, LoongArch::F6_64, LoongArch::F7_64};7716 7717const MCPhysReg ArgVRs[] = {LoongArch::VR0, LoongArch::VR1, LoongArch::VR2,7718                            LoongArch::VR3, LoongArch::VR4, LoongArch::VR5,7719                            LoongArch::VR6, LoongArch::VR7};7720 7721const MCPhysReg ArgXRs[] = {LoongArch::XR0, LoongArch::XR1, LoongArch::XR2,7722                            LoongArch::XR3, LoongArch::XR4, LoongArch::XR5,7723                            LoongArch::XR6, LoongArch::XR7};7724 7725// Pass a 2*GRLen argument that has been split into two GRLen values through7726// registers or the stack as necessary.7727static bool CC_LoongArchAssign2GRLen(unsigned GRLen, CCState &State,7728                                     CCValAssign VA1, ISD::ArgFlagsTy ArgFlags1,7729                                     unsigned ValNo2, MVT ValVT2, MVT LocVT2,7730                                     ISD::ArgFlagsTy ArgFlags2) {7731  unsigned GRLenInBytes = GRLen / 8;7732  if (Register Reg = State.AllocateReg(ArgGPRs)) {7733    // At least one half can be passed via register.7734    State.addLoc(CCValAssign::getReg(VA1.getValNo(), VA1.getValVT(), Reg,7735                                     VA1.getLocVT(), CCValAssign::Full));7736  } else {7737    // Both halves must be passed on the stack, with proper alignment.7738    Align StackAlign =7739        std::max(Align(GRLenInBytes), ArgFlags1.getNonZeroOrigAlign());7740    State.addLoc(7741        CCValAssign::getMem(VA1.getValNo(), VA1.getValVT(),7742                            State.AllocateStack(GRLenInBytes, StackAlign),7743                            VA1.getLocVT(), CCValAssign::Full));7744    State.addLoc(CCValAssign::getMem(7745        ValNo2, ValVT2, State.AllocateStack(GRLenInBytes, Align(GRLenInBytes)),7746        LocVT2, CCValAssign::Full));7747    return false;7748  }7749  if (Register Reg = State.AllocateReg(ArgGPRs)) {7750    // The second half can also be passed via register.7751    State.addLoc(7752        CCValAssign::getReg(ValNo2, ValVT2, Reg, LocVT2, CCValAssign::Full));7753  } else {7754    // The second half is passed via the stack, without additional alignment.7755    State.addLoc(CCValAssign::getMem(7756        ValNo2, ValVT2, State.AllocateStack(GRLenInBytes, Align(GRLenInBytes)),7757        LocVT2, CCValAssign::Full));7758  }7759  return false;7760}7761 7762// Implements the LoongArch calling convention. Returns true upon failure.7763static bool CC_LoongArch(const DataLayout &DL, LoongArchABI::ABI ABI,7764                         unsigned ValNo, MVT ValVT,7765                         CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,7766                         CCState &State, bool IsRet, Type *OrigTy) {7767  unsigned GRLen = DL.getLargestLegalIntTypeSizeInBits();7768  assert((GRLen == 32 || GRLen == 64) && "Unspport GRLen");7769  MVT GRLenVT = GRLen == 32 ? MVT::i32 : MVT::i64;7770  MVT LocVT = ValVT;7771 7772  // Any return value split into more than two values can't be returned7773  // directly.7774  if (IsRet && ValNo > 1)7775    return true;7776 7777  // If passing a variadic argument, or if no FPR is available.7778  bool UseGPRForFloat = true;7779 7780  switch (ABI) {7781  default:7782    llvm_unreachable("Unexpected ABI");7783    break;7784  case LoongArchABI::ABI_ILP32F:7785  case LoongArchABI::ABI_LP64F:7786  case LoongArchABI::ABI_ILP32D:7787  case LoongArchABI::ABI_LP64D:7788    UseGPRForFloat = ArgFlags.isVarArg();7789    break;7790  case LoongArchABI::ABI_ILP32S:7791  case LoongArchABI::ABI_LP64S:7792    break;7793  }7794 7795  // If this is a variadic argument, the LoongArch calling convention requires7796  // that it is assigned an 'even' or 'aligned' register if it has (2*GRLen)/87797  // byte alignment. An aligned register should be used regardless of whether7798  // the original argument was split during legalisation or not. The argument7799  // will not be passed by registers if the original type is larger than7800  // 2*GRLen, so the register alignment rule does not apply.7801  unsigned TwoGRLenInBytes = (2 * GRLen) / 8;7802  if (ArgFlags.isVarArg() &&7803      ArgFlags.getNonZeroOrigAlign() == TwoGRLenInBytes &&7804      DL.getTypeAllocSize(OrigTy) == TwoGRLenInBytes) {7805    unsigned RegIdx = State.getFirstUnallocated(ArgGPRs);7806    // Skip 'odd' register if necessary.7807    if (RegIdx != std::size(ArgGPRs) && RegIdx % 2 == 1)7808      State.AllocateReg(ArgGPRs);7809  }7810 7811  SmallVectorImpl<CCValAssign> &PendingLocs = State.getPendingLocs();7812  SmallVectorImpl<ISD::ArgFlagsTy> &PendingArgFlags =7813      State.getPendingArgFlags();7814 7815  assert(PendingLocs.size() == PendingArgFlags.size() &&7816         "PendingLocs and PendingArgFlags out of sync");7817 7818  // FPR32 and FPR64 alias each other.7819  if (State.getFirstUnallocated(ArgFPR32s) == std::size(ArgFPR32s))7820    UseGPRForFloat = true;7821 7822  if (UseGPRForFloat && ValVT == MVT::f32) {7823    LocVT = GRLenVT;7824    LocInfo = CCValAssign::BCvt;7825  } else if (UseGPRForFloat && GRLen == 64 && ValVT == MVT::f64) {7826    LocVT = MVT::i64;7827    LocInfo = CCValAssign::BCvt;7828  } else if (UseGPRForFloat && GRLen == 32 && ValVT == MVT::f64) {7829    // Handle passing f64 on LA32D with a soft float ABI or when floating point7830    // registers are exhausted.7831    assert(PendingLocs.empty() && "Can't lower f64 if it is split");7832    // Depending on available argument GPRS, f64 may be passed in a pair of7833    // GPRs, split between a GPR and the stack, or passed completely on the7834    // stack. LowerCall/LowerFormalArguments/LowerReturn must recognise these7835    // cases.7836    MCRegister Reg = State.AllocateReg(ArgGPRs);7837    if (!Reg) {7838      int64_t StackOffset = State.AllocateStack(8, Align(8));7839      State.addLoc(7840          CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));7841      return false;7842    }7843    LocVT = MVT::i32;7844    State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));7845    MCRegister HiReg = State.AllocateReg(ArgGPRs);7846    if (HiReg) {7847      State.addLoc(7848          CCValAssign::getCustomReg(ValNo, ValVT, HiReg, LocVT, LocInfo));7849    } else {7850      int64_t StackOffset = State.AllocateStack(4, Align(4));7851      State.addLoc(7852          CCValAssign::getCustomMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));7853    }7854    return false;7855  }7856 7857  // Split arguments might be passed indirectly, so keep track of the pending7858  // values.7859  if (ValVT.isScalarInteger() && (ArgFlags.isSplit() || !PendingLocs.empty())) {7860    LocVT = GRLenVT;7861    LocInfo = CCValAssign::Indirect;7862    PendingLocs.push_back(7863        CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo));7864    PendingArgFlags.push_back(ArgFlags);7865    if (!ArgFlags.isSplitEnd()) {7866      return false;7867    }7868  }7869 7870  // If the split argument only had two elements, it should be passed directly7871  // in registers or on the stack.7872  if (ValVT.isScalarInteger() && ArgFlags.isSplitEnd() &&7873      PendingLocs.size() <= 2) {7874    assert(PendingLocs.size() == 2 && "Unexpected PendingLocs.size()");7875    // Apply the normal calling convention rules to the first half of the7876    // split argument.7877    CCValAssign VA = PendingLocs[0];7878    ISD::ArgFlagsTy AF = PendingArgFlags[0];7879    PendingLocs.clear();7880    PendingArgFlags.clear();7881    return CC_LoongArchAssign2GRLen(GRLen, State, VA, AF, ValNo, ValVT, LocVT,7882                                    ArgFlags);7883  }7884 7885  // Allocate to a register if possible, or else a stack slot.7886  Register Reg;7887  unsigned StoreSizeBytes = GRLen / 8;7888  Align StackAlign = Align(GRLen / 8);7889 7890  if (ValVT == MVT::f32 && !UseGPRForFloat) {7891    Reg = State.AllocateReg(ArgFPR32s);7892  } else if (ValVT == MVT::f64 && !UseGPRForFloat) {7893    Reg = State.AllocateReg(ArgFPR64s);7894  } else if (ValVT.is128BitVector()) {7895    Reg = State.AllocateReg(ArgVRs);7896    UseGPRForFloat = false;7897    StoreSizeBytes = 16;7898    StackAlign = Align(16);7899  } else if (ValVT.is256BitVector()) {7900    Reg = State.AllocateReg(ArgXRs);7901    UseGPRForFloat = false;7902    StoreSizeBytes = 32;7903    StackAlign = Align(32);7904  } else {7905    Reg = State.AllocateReg(ArgGPRs);7906  }7907 7908  unsigned StackOffset =7909      Reg ? 0 : State.AllocateStack(StoreSizeBytes, StackAlign);7910 7911  // If we reach this point and PendingLocs is non-empty, we must be at the7912  // end of a split argument that must be passed indirectly.7913  if (!PendingLocs.empty()) {7914    assert(ArgFlags.isSplitEnd() && "Expected ArgFlags.isSplitEnd()");7915    assert(PendingLocs.size() > 2 && "Unexpected PendingLocs.size()");7916    for (auto &It : PendingLocs) {7917      if (Reg)7918        It.convertToReg(Reg);7919      else7920        It.convertToMem(StackOffset);7921      State.addLoc(It);7922    }7923    PendingLocs.clear();7924    PendingArgFlags.clear();7925    return false;7926  }7927  assert((!UseGPRForFloat || LocVT == GRLenVT) &&7928         "Expected an GRLenVT at this stage");7929 7930  if (Reg) {7931    State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));7932    return false;7933  }7934 7935  // When a floating-point value is passed on the stack, no bit-cast is needed.7936  if (ValVT.isFloatingPoint()) {7937    LocVT = ValVT;7938    LocInfo = CCValAssign::Full;7939  }7940 7941  State.addLoc(CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));7942  return false;7943}7944 7945void LoongArchTargetLowering::analyzeInputArgs(7946    MachineFunction &MF, CCState &CCInfo,7947    const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet,7948    LoongArchCCAssignFn Fn) const {7949  FunctionType *FType = MF.getFunction().getFunctionType();7950  for (unsigned i = 0, e = Ins.size(); i != e; ++i) {7951    MVT ArgVT = Ins[i].VT;7952    Type *ArgTy = nullptr;7953    if (IsRet)7954      ArgTy = FType->getReturnType();7955    else if (Ins[i].isOrigArg())7956      ArgTy = FType->getParamType(Ins[i].getOrigArgIndex());7957    LoongArchABI::ABI ABI =7958        MF.getSubtarget<LoongArchSubtarget>().getTargetABI();7959    if (Fn(MF.getDataLayout(), ABI, i, ArgVT, CCValAssign::Full, Ins[i].Flags,7960           CCInfo, IsRet, ArgTy)) {7961      LLVM_DEBUG(dbgs() << "InputArg #" << i << " has unhandled type " << ArgVT7962                        << '\n');7963      llvm_unreachable("");7964    }7965  }7966}7967 7968void LoongArchTargetLowering::analyzeOutputArgs(7969    MachineFunction &MF, CCState &CCInfo,7970    const SmallVectorImpl<ISD::OutputArg> &Outs, bool IsRet,7971    CallLoweringInfo *CLI, LoongArchCCAssignFn Fn) const {7972  for (unsigned i = 0, e = Outs.size(); i != e; ++i) {7973    MVT ArgVT = Outs[i].VT;7974    Type *OrigTy = CLI ? CLI->getArgs()[Outs[i].OrigArgIndex].Ty : nullptr;7975    LoongArchABI::ABI ABI =7976        MF.getSubtarget<LoongArchSubtarget>().getTargetABI();7977    if (Fn(MF.getDataLayout(), ABI, i, ArgVT, CCValAssign::Full, Outs[i].Flags,7978           CCInfo, IsRet, OrigTy)) {7979      LLVM_DEBUG(dbgs() << "OutputArg #" << i << " has unhandled type " << ArgVT7980                        << "\n");7981      llvm_unreachable("");7982    }7983  }7984}7985 7986// Convert Val to a ValVT. Should not be called for CCValAssign::Indirect7987// values.7988static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val,7989                                   const CCValAssign &VA, const SDLoc &DL) {7990  switch (VA.getLocInfo()) {7991  default:7992    llvm_unreachable("Unexpected CCValAssign::LocInfo");7993  case CCValAssign::Full:7994  case CCValAssign::Indirect:7995    break;7996  case CCValAssign::BCvt:7997    if (VA.getLocVT() == MVT::i64 && VA.getValVT() == MVT::f32)7998      Val = DAG.getNode(LoongArchISD::MOVGR2FR_W_LA64, DL, MVT::f32, Val);7999    else8000      Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);8001    break;8002  }8003  return Val;8004}8005 8006static SDValue unpackFromRegLoc(SelectionDAG &DAG, SDValue Chain,8007                                const CCValAssign &VA, const SDLoc &DL,8008                                const ISD::InputArg &In,8009                                const LoongArchTargetLowering &TLI) {8010  MachineFunction &MF = DAG.getMachineFunction();8011  MachineRegisterInfo &RegInfo = MF.getRegInfo();8012  EVT LocVT = VA.getLocVT();8013  SDValue Val;8014  const TargetRegisterClass *RC = TLI.getRegClassFor(LocVT.getSimpleVT());8015  Register VReg = RegInfo.createVirtualRegister(RC);8016  RegInfo.addLiveIn(VA.getLocReg(), VReg);8017  Val = DAG.getCopyFromReg(Chain, DL, VReg, LocVT);8018 8019  // If input is sign extended from 32 bits, note it for the OptW pass.8020  if (In.isOrigArg()) {8021    Argument *OrigArg = MF.getFunction().getArg(In.getOrigArgIndex());8022    if (OrigArg->getType()->isIntegerTy()) {8023      unsigned BitWidth = OrigArg->getType()->getIntegerBitWidth();8024      // An input zero extended from i31 can also be considered sign extended.8025      if ((BitWidth <= 32 && In.Flags.isSExt()) ||8026          (BitWidth < 32 && In.Flags.isZExt())) {8027        LoongArchMachineFunctionInfo *LAFI =8028            MF.getInfo<LoongArchMachineFunctionInfo>();8029        LAFI->addSExt32Register(VReg);8030      }8031    }8032  }8033 8034  return convertLocVTToValVT(DAG, Val, VA, DL);8035}8036 8037// The caller is responsible for loading the full value if the argument is8038// passed with CCValAssign::Indirect.8039static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain,8040                                const CCValAssign &VA, const SDLoc &DL) {8041  MachineFunction &MF = DAG.getMachineFunction();8042  MachineFrameInfo &MFI = MF.getFrameInfo();8043  EVT ValVT = VA.getValVT();8044  int FI = MFI.CreateFixedObject(ValVT.getStoreSize(), VA.getLocMemOffset(),8045                                 /*IsImmutable=*/true);8046  SDValue FIN = DAG.getFrameIndex(8047      FI, MVT::getIntegerVT(DAG.getDataLayout().getPointerSizeInBits(0)));8048 8049  ISD::LoadExtType ExtType;8050  switch (VA.getLocInfo()) {8051  default:8052    llvm_unreachable("Unexpected CCValAssign::LocInfo");8053  case CCValAssign::Full:8054  case CCValAssign::Indirect:8055  case CCValAssign::BCvt:8056    ExtType = ISD::NON_EXTLOAD;8057    break;8058  }8059  return DAG.getExtLoad(8060      ExtType, DL, VA.getLocVT(), Chain, FIN,8061      MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), ValVT);8062}8063 8064static SDValue unpackF64OnLA32DSoftABI(SelectionDAG &DAG, SDValue Chain,8065                                       const CCValAssign &VA,8066                                       const CCValAssign &HiVA,8067                                       const SDLoc &DL) {8068  assert(VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64 &&8069         "Unexpected VA");8070  MachineFunction &MF = DAG.getMachineFunction();8071  MachineFrameInfo &MFI = MF.getFrameInfo();8072  MachineRegisterInfo &RegInfo = MF.getRegInfo();8073 8074  assert(VA.isRegLoc() && "Expected register VA assignment");8075 8076  Register LoVReg = RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);8077  RegInfo.addLiveIn(VA.getLocReg(), LoVReg);8078  SDValue Lo = DAG.getCopyFromReg(Chain, DL, LoVReg, MVT::i32);8079  SDValue Hi;8080  if (HiVA.isMemLoc()) {8081    // Second half of f64 is passed on the stack.8082    int FI = MFI.CreateFixedObject(4, HiVA.getLocMemOffset(),8083                                   /*IsImmutable=*/true);8084    SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);8085    Hi = DAG.getLoad(MVT::i32, DL, Chain, FIN,8086                     MachinePointerInfo::getFixedStack(MF, FI));8087  } else {8088    // Second half of f64 is passed in another GPR.8089    Register HiVReg = RegInfo.createVirtualRegister(&LoongArch::GPRRegClass);8090    RegInfo.addLiveIn(HiVA.getLocReg(), HiVReg);8091    Hi = DAG.getCopyFromReg(Chain, DL, HiVReg, MVT::i32);8092  }8093  return DAG.getNode(LoongArchISD::BUILD_PAIR_F64, DL, MVT::f64, Lo, Hi);8094}8095 8096static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val,8097                                   const CCValAssign &VA, const SDLoc &DL) {8098  EVT LocVT = VA.getLocVT();8099 8100  switch (VA.getLocInfo()) {8101  default:8102    llvm_unreachable("Unexpected CCValAssign::LocInfo");8103  case CCValAssign::Full:8104    break;8105  case CCValAssign::BCvt:8106    if (VA.getLocVT() == MVT::i64 && VA.getValVT() == MVT::f32)8107      Val = DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Val);8108    else8109      Val = DAG.getNode(ISD::BITCAST, DL, LocVT, Val);8110    break;8111  }8112  return Val;8113}8114 8115static bool CC_LoongArch_GHC(unsigned ValNo, MVT ValVT, MVT LocVT,8116                             CCValAssign::LocInfo LocInfo,8117                             ISD::ArgFlagsTy ArgFlags, Type *OrigTy,8118                             CCState &State) {8119  if (LocVT == MVT::i32 || LocVT == MVT::i64) {8120    // Pass in STG registers: Base, Sp, Hp, R1, R2, R3, R4, R5, SpLim8121    //                        s0    s1  s2  s3  s4  s5  s6  s7  s88122    static const MCPhysReg GPRList[] = {8123        LoongArch::R23, LoongArch::R24, LoongArch::R25,8124        LoongArch::R26, LoongArch::R27, LoongArch::R28,8125        LoongArch::R29, LoongArch::R30, LoongArch::R31};8126    if (MCRegister Reg = State.AllocateReg(GPRList)) {8127      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));8128      return false;8129    }8130  }8131 8132  if (LocVT == MVT::f32) {8133    // Pass in STG registers: F1, F2, F3, F48134    //                        fs0,fs1,fs2,fs38135    static const MCPhysReg FPR32List[] = {LoongArch::F24, LoongArch::F25,8136                                          LoongArch::F26, LoongArch::F27};8137    if (MCRegister Reg = State.AllocateReg(FPR32List)) {8138      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));8139      return false;8140    }8141  }8142 8143  if (LocVT == MVT::f64) {8144    // Pass in STG registers: D1, D2, D3, D48145    //                        fs4,fs5,fs6,fs78146    static const MCPhysReg FPR64List[] = {LoongArch::F28_64, LoongArch::F29_64,8147                                          LoongArch::F30_64, LoongArch::F31_64};8148    if (MCRegister Reg = State.AllocateReg(FPR64List)) {8149      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));8150      return false;8151    }8152  }8153 8154  report_fatal_error("No registers left in GHC calling convention");8155  return true;8156}8157 8158// Transform physical registers into virtual registers.8159SDValue LoongArchTargetLowering::LowerFormalArguments(8160    SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,8161    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,8162    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {8163 8164  MachineFunction &MF = DAG.getMachineFunction();8165 8166  switch (CallConv) {8167  default:8168    llvm_unreachable("Unsupported calling convention");8169  case CallingConv::C:8170  case CallingConv::Fast:8171  case CallingConv::PreserveMost:8172    break;8173  case CallingConv::GHC:8174    if (!MF.getSubtarget().hasFeature(LoongArch::FeatureBasicF) ||8175        !MF.getSubtarget().hasFeature(LoongArch::FeatureBasicD))8176      report_fatal_error(8177          "GHC calling convention requires the F and D extensions");8178  }8179 8180  EVT PtrVT = getPointerTy(DAG.getDataLayout());8181  MVT GRLenVT = Subtarget.getGRLenVT();8182  unsigned GRLenInBytes = Subtarget.getGRLen() / 8;8183  // Used with varargs to acumulate store chains.8184  std::vector<SDValue> OutChains;8185 8186  // Assign locations to all of the incoming arguments.8187  SmallVector<CCValAssign> ArgLocs;8188  CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());8189 8190  if (CallConv == CallingConv::GHC)8191    CCInfo.AnalyzeFormalArguments(Ins, CC_LoongArch_GHC);8192  else8193    analyzeInputArgs(MF, CCInfo, Ins, /*IsRet=*/false, CC_LoongArch);8194 8195  for (unsigned i = 0, e = ArgLocs.size(), InsIdx = 0; i != e; ++i, ++InsIdx) {8196    CCValAssign &VA = ArgLocs[i];8197    SDValue ArgValue;8198    // Passing f64 on LA32D with a soft float ABI must be handled as a special8199    // case.8200    if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {8201      assert(VA.needsCustom());8202      ArgValue = unpackF64OnLA32DSoftABI(DAG, Chain, VA, ArgLocs[++i], DL);8203    } else if (VA.isRegLoc())8204      ArgValue = unpackFromRegLoc(DAG, Chain, VA, DL, Ins[InsIdx], *this);8205    else8206      ArgValue = unpackFromMemLoc(DAG, Chain, VA, DL);8207    if (VA.getLocInfo() == CCValAssign::Indirect) {8208      // If the original argument was split and passed by reference, we need to8209      // load all parts of it here (using the same address).8210      InVals.push_back(DAG.getLoad(VA.getValVT(), DL, Chain, ArgValue,8211                                   MachinePointerInfo()));8212      unsigned ArgIndex = Ins[InsIdx].OrigArgIndex;8213      unsigned ArgPartOffset = Ins[InsIdx].PartOffset;8214      assert(ArgPartOffset == 0);8215      while (i + 1 != e && Ins[InsIdx + 1].OrigArgIndex == ArgIndex) {8216        CCValAssign &PartVA = ArgLocs[i + 1];8217        unsigned PartOffset = Ins[InsIdx + 1].PartOffset - ArgPartOffset;8218        SDValue Offset = DAG.getIntPtrConstant(PartOffset, DL);8219        SDValue Address = DAG.getNode(ISD::ADD, DL, PtrVT, ArgValue, Offset);8220        InVals.push_back(DAG.getLoad(PartVA.getValVT(), DL, Chain, Address,8221                                     MachinePointerInfo()));8222        ++i;8223        ++InsIdx;8224      }8225      continue;8226    }8227    InVals.push_back(ArgValue);8228  }8229 8230  if (IsVarArg) {8231    ArrayRef<MCPhysReg> ArgRegs = ArrayRef(ArgGPRs);8232    unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs);8233    const TargetRegisterClass *RC = &LoongArch::GPRRegClass;8234    MachineFrameInfo &MFI = MF.getFrameInfo();8235    MachineRegisterInfo &RegInfo = MF.getRegInfo();8236    auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>();8237 8238    // Offset of the first variable argument from stack pointer, and size of8239    // the vararg save area. For now, the varargs save area is either zero or8240    // large enough to hold a0-a7.8241    int VaArgOffset, VarArgsSaveSize;8242 8243    // If all registers are allocated, then all varargs must be passed on the8244    // stack and we don't need to save any argregs.8245    if (ArgRegs.size() == Idx) {8246      VaArgOffset = CCInfo.getStackSize();8247      VarArgsSaveSize = 0;8248    } else {8249      VarArgsSaveSize = GRLenInBytes * (ArgRegs.size() - Idx);8250      VaArgOffset = -VarArgsSaveSize;8251    }8252 8253    // Record the frame index of the first variable argument8254    // which is a value necessary to VASTART.8255    int FI = MFI.CreateFixedObject(GRLenInBytes, VaArgOffset, true);8256    LoongArchFI->setVarArgsFrameIndex(FI);8257 8258    // If saving an odd number of registers then create an extra stack slot to8259    // ensure that the frame pointer is 2*GRLen-aligned, which in turn ensures8260    // offsets to even-numbered registered remain 2*GRLen-aligned.8261    if (Idx % 2) {8262      MFI.CreateFixedObject(GRLenInBytes, VaArgOffset - (int)GRLenInBytes,8263                            true);8264      VarArgsSaveSize += GRLenInBytes;8265    }8266 8267    // Copy the integer registers that may have been used for passing varargs8268    // to the vararg save area.8269    for (unsigned I = Idx; I < ArgRegs.size();8270         ++I, VaArgOffset += GRLenInBytes) {8271      const Register Reg = RegInfo.createVirtualRegister(RC);8272      RegInfo.addLiveIn(ArgRegs[I], Reg);8273      SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, GRLenVT);8274      FI = MFI.CreateFixedObject(GRLenInBytes, VaArgOffset, true);8275      SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));8276      SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff,8277                                   MachinePointerInfo::getFixedStack(MF, FI));8278      cast<StoreSDNode>(Store.getNode())8279          ->getMemOperand()8280          ->setValue((Value *)nullptr);8281      OutChains.push_back(Store);8282    }8283    LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize);8284  }8285 8286  // All stores are grouped in one node to allow the matching between8287  // the size of Ins and InVals. This only happens for vararg functions.8288  if (!OutChains.empty()) {8289    OutChains.push_back(Chain);8290    Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);8291  }8292 8293  return Chain;8294}8295 8296bool LoongArchTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {8297  return CI->isTailCall();8298}8299 8300// Check if the return value is used as only a return value, as otherwise8301// we can't perform a tail-call.8302bool LoongArchTargetLowering::isUsedByReturnOnly(SDNode *N,8303                                                 SDValue &Chain) const {8304  if (N->getNumValues() != 1)8305    return false;8306  if (!N->hasNUsesOfValue(1, 0))8307    return false;8308 8309  SDNode *Copy = *N->user_begin();8310  if (Copy->getOpcode() != ISD::CopyToReg)8311    return false;8312 8313  // If the ISD::CopyToReg has a glue operand, we conservatively assume it8314  // isn't safe to perform a tail call.8315  if (Copy->getGluedNode())8316    return false;8317 8318  // The copy must be used by a LoongArchISD::RET, and nothing else.8319  bool HasRet = false;8320  for (SDNode *Node : Copy->users()) {8321    if (Node->getOpcode() != LoongArchISD::RET)8322      return false;8323    HasRet = true;8324  }8325 8326  if (!HasRet)8327    return false;8328 8329  Chain = Copy->getOperand(0);8330  return true;8331}8332 8333// Check whether the call is eligible for tail call optimization.8334bool LoongArchTargetLowering::isEligibleForTailCallOptimization(8335    CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF,8336    const SmallVectorImpl<CCValAssign> &ArgLocs) const {8337 8338  auto CalleeCC = CLI.CallConv;8339  auto &Outs = CLI.Outs;8340  auto &Caller = MF.getFunction();8341  auto CallerCC = Caller.getCallingConv();8342 8343  // Do not tail call opt if the stack is used to pass parameters.8344  if (CCInfo.getStackSize() != 0)8345    return false;8346 8347  // Do not tail call opt if any parameters need to be passed indirectly.8348  for (auto &VA : ArgLocs)8349    if (VA.getLocInfo() == CCValAssign::Indirect)8350      return false;8351 8352  // Do not tail call opt if either caller or callee uses struct return8353  // semantics.8354  auto IsCallerStructRet = Caller.hasStructRetAttr();8355  auto IsCalleeStructRet = Outs.empty() ? false : Outs[0].Flags.isSRet();8356  if (IsCallerStructRet || IsCalleeStructRet)8357    return false;8358 8359  // Do not tail call opt if either the callee or caller has a byval argument.8360  for (auto &Arg : Outs)8361    if (Arg.Flags.isByVal())8362      return false;8363 8364  // The callee has to preserve all registers the caller needs to preserve.8365  const LoongArchRegisterInfo *TRI = Subtarget.getRegisterInfo();8366  const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC);8367  if (CalleeCC != CallerCC) {8368    const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC);8369    if (!TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))8370      return false;8371  }8372  return true;8373}8374 8375static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG) {8376  return DAG.getDataLayout().getPrefTypeAlign(8377      VT.getTypeForEVT(*DAG.getContext()));8378}8379 8380// Lower a call to a callseq_start + CALL + callseq_end chain, and add input8381// and output parameter nodes.8382SDValue8383LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,8384                                   SmallVectorImpl<SDValue> &InVals) const {8385  SelectionDAG &DAG = CLI.DAG;8386  SDLoc &DL = CLI.DL;8387  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;8388  SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;8389  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;8390  SDValue Chain = CLI.Chain;8391  SDValue Callee = CLI.Callee;8392  CallingConv::ID CallConv = CLI.CallConv;8393  bool IsVarArg = CLI.IsVarArg;8394  EVT PtrVT = getPointerTy(DAG.getDataLayout());8395  MVT GRLenVT = Subtarget.getGRLenVT();8396  bool &IsTailCall = CLI.IsTailCall;8397 8398  MachineFunction &MF = DAG.getMachineFunction();8399 8400  // Analyze the operands of the call, assigning locations to each operand.8401  SmallVector<CCValAssign> ArgLocs;8402  CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());8403 8404  if (CallConv == CallingConv::GHC)8405    ArgCCInfo.AnalyzeCallOperands(Outs, CC_LoongArch_GHC);8406  else8407    analyzeOutputArgs(MF, ArgCCInfo, Outs, /*IsRet=*/false, &CLI, CC_LoongArch);8408 8409  // Check if it's really possible to do a tail call.8410  if (IsTailCall)8411    IsTailCall = isEligibleForTailCallOptimization(ArgCCInfo, CLI, MF, ArgLocs);8412 8413  if (IsTailCall)8414    ++NumTailCalls;8415  else if (CLI.CB && CLI.CB->isMustTailCall())8416    report_fatal_error("failed to perform tail call elimination on a call "8417                       "site marked musttail");8418 8419  // Get a count of how many bytes are to be pushed on the stack.8420  unsigned NumBytes = ArgCCInfo.getStackSize();8421 8422  // Create local copies for byval args.8423  SmallVector<SDValue> ByValArgs;8424  for (unsigned i = 0, e = Outs.size(); i != e; ++i) {8425    ISD::ArgFlagsTy Flags = Outs[i].Flags;8426    if (!Flags.isByVal())8427      continue;8428 8429    SDValue Arg = OutVals[i];8430    unsigned Size = Flags.getByValSize();8431    Align Alignment = Flags.getNonZeroByValAlign();8432 8433    int FI =8434        MF.getFrameInfo().CreateStackObject(Size, Alignment, /*isSS=*/false);8435    SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));8436    SDValue SizeNode = DAG.getConstant(Size, DL, GRLenVT);8437 8438    Chain = DAG.getMemcpy(Chain, DL, FIPtr, Arg, SizeNode, Alignment,8439                          /*IsVolatile=*/false,8440                          /*AlwaysInline=*/false, /*CI=*/nullptr, std::nullopt,8441                          MachinePointerInfo(), MachinePointerInfo());8442    ByValArgs.push_back(FIPtr);8443  }8444 8445  if (!IsTailCall)8446    Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);8447 8448  // Copy argument values to their designated locations.8449  SmallVector<std::pair<Register, SDValue>> RegsToPass;8450  SmallVector<SDValue> MemOpChains;8451  SDValue StackPtr;8452  for (unsigned i = 0, j = 0, e = ArgLocs.size(), OutIdx = 0; i != e;8453       ++i, ++OutIdx) {8454    CCValAssign &VA = ArgLocs[i];8455    SDValue ArgValue = OutVals[OutIdx];8456    ISD::ArgFlagsTy Flags = Outs[OutIdx].Flags;8457 8458    // Handle passing f64 on LA32D with a soft float ABI as a special case.8459    if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {8460      assert(VA.isRegLoc() && "Expected register VA assignment");8461      assert(VA.needsCustom());8462      SDValue SplitF64 =8463          DAG.getNode(LoongArchISD::SPLIT_PAIR_F64, DL,8464                      DAG.getVTList(MVT::i32, MVT::i32), ArgValue);8465      SDValue Lo = SplitF64.getValue(0);8466      SDValue Hi = SplitF64.getValue(1);8467 8468      Register RegLo = VA.getLocReg();8469      RegsToPass.push_back(std::make_pair(RegLo, Lo));8470 8471      // Get the CCValAssign for the Hi part.8472      CCValAssign &HiVA = ArgLocs[++i];8473 8474      if (HiVA.isMemLoc()) {8475        // Second half of f64 is passed on the stack.8476        if (!StackPtr.getNode())8477          StackPtr = DAG.getCopyFromReg(Chain, DL, LoongArch::R3, PtrVT);8478        SDValue Address =8479            DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr,8480                        DAG.getIntPtrConstant(HiVA.getLocMemOffset(), DL));8481        // Emit the store.8482        MemOpChains.push_back(DAG.getStore(8483            Chain, DL, Hi, Address,8484            MachinePointerInfo::getStack(MF, HiVA.getLocMemOffset())));8485      } else {8486        // Second half of f64 is passed in another GPR.8487        Register RegHigh = HiVA.getLocReg();8488        RegsToPass.push_back(std::make_pair(RegHigh, Hi));8489      }8490      continue;8491    }8492 8493    // Promote the value if needed.8494    // For now, only handle fully promoted and indirect arguments.8495    if (VA.getLocInfo() == CCValAssign::Indirect) {8496      // Store the argument in a stack slot and pass its address.8497      Align StackAlign =8498          std::max(getPrefTypeAlign(Outs[OutIdx].ArgVT, DAG),8499                   getPrefTypeAlign(ArgValue.getValueType(), DAG));8500      TypeSize StoredSize = ArgValue.getValueType().getStoreSize();8501      // If the original argument was split and passed by reference, we need to8502      // store the required parts of it here (and pass just one address).8503      unsigned ArgIndex = Outs[OutIdx].OrigArgIndex;8504      unsigned ArgPartOffset = Outs[OutIdx].PartOffset;8505      assert(ArgPartOffset == 0);8506      // Calculate the total size to store. We don't have access to what we're8507      // actually storing other than performing the loop and collecting the8508      // info.8509      SmallVector<std::pair<SDValue, SDValue>> Parts;8510      while (i + 1 != e && Outs[OutIdx + 1].OrigArgIndex == ArgIndex) {8511        SDValue PartValue = OutVals[OutIdx + 1];8512        unsigned PartOffset = Outs[OutIdx + 1].PartOffset - ArgPartOffset;8513        SDValue Offset = DAG.getIntPtrConstant(PartOffset, DL);8514        EVT PartVT = PartValue.getValueType();8515 8516        StoredSize += PartVT.getStoreSize();8517        StackAlign = std::max(StackAlign, getPrefTypeAlign(PartVT, DAG));8518        Parts.push_back(std::make_pair(PartValue, Offset));8519        ++i;8520        ++OutIdx;8521      }8522      SDValue SpillSlot = DAG.CreateStackTemporary(StoredSize, StackAlign);8523      int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();8524      MemOpChains.push_back(8525          DAG.getStore(Chain, DL, ArgValue, SpillSlot,8526                       MachinePointerInfo::getFixedStack(MF, FI)));8527      for (const auto &Part : Parts) {8528        SDValue PartValue = Part.first;8529        SDValue PartOffset = Part.second;8530        SDValue Address =8531            DAG.getNode(ISD::ADD, DL, PtrVT, SpillSlot, PartOffset);8532        MemOpChains.push_back(8533            DAG.getStore(Chain, DL, PartValue, Address,8534                         MachinePointerInfo::getFixedStack(MF, FI)));8535      }8536      ArgValue = SpillSlot;8537    } else {8538      ArgValue = convertValVTToLocVT(DAG, ArgValue, VA, DL);8539    }8540 8541    // Use local copy if it is a byval arg.8542    if (Flags.isByVal())8543      ArgValue = ByValArgs[j++];8544 8545    if (VA.isRegLoc()) {8546      // Queue up the argument copies and emit them at the end.8547      RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue));8548    } else {8549      assert(VA.isMemLoc() && "Argument not register or memory");8550      assert(!IsTailCall && "Tail call not allowed if stack is used "8551                            "for passing parameters");8552 8553      // Work out the address of the stack slot.8554      if (!StackPtr.getNode())8555        StackPtr = DAG.getCopyFromReg(Chain, DL, LoongArch::R3, PtrVT);8556      SDValue Address =8557          DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr,8558                      DAG.getIntPtrConstant(VA.getLocMemOffset(), DL));8559 8560      // Emit the store.8561      MemOpChains.push_back(8562          DAG.getStore(Chain, DL, ArgValue, Address, MachinePointerInfo()));8563    }8564  }8565 8566  // Join the stores, which are independent of one another.8567  if (!MemOpChains.empty())8568    Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);8569 8570  SDValue Glue;8571 8572  // Build a sequence of copy-to-reg nodes, chained and glued together.8573  for (auto &Reg : RegsToPass) {8574    Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue);8575    Glue = Chain.getValue(1);8576  }8577 8578  // If the callee is a GlobalAddress/ExternalSymbol node, turn it into a8579  // TargetGlobalAddress/TargetExternalSymbol node so that legalize won't8580  // split it and then direct call can be matched by PseudoCALL.8581  if (GlobalAddressSDNode *S = dyn_cast<GlobalAddressSDNode>(Callee)) {8582    const GlobalValue *GV = S->getGlobal();8583    unsigned OpFlags = getTargetMachine().shouldAssumeDSOLocal(GV)8584                           ? LoongArchII::MO_CALL8585                           : LoongArchII::MO_CALL_PLT;8586    Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT, 0, OpFlags);8587  } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {8588    unsigned OpFlags = getTargetMachine().shouldAssumeDSOLocal(nullptr)8589                           ? LoongArchII::MO_CALL8590                           : LoongArchII::MO_CALL_PLT;8591    Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, OpFlags);8592  }8593 8594  // The first call operand is the chain and the second is the target address.8595  SmallVector<SDValue> Ops;8596  Ops.push_back(Chain);8597  Ops.push_back(Callee);8598 8599  // Add argument registers to the end of the list so that they are8600  // known live into the call.8601  for (auto &Reg : RegsToPass)8602    Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));8603 8604  if (!IsTailCall) {8605    // Add a register mask operand representing the call-preserved registers.8606    const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();8607    const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);8608    assert(Mask && "Missing call preserved mask for calling convention");8609    Ops.push_back(DAG.getRegisterMask(Mask));8610  }8611 8612  // Glue the call to the argument copies, if any.8613  if (Glue.getNode())8614    Ops.push_back(Glue);8615 8616  // Emit the call.8617  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);8618  unsigned Op;8619  switch (DAG.getTarget().getCodeModel()) {8620  default:8621    report_fatal_error("Unsupported code model");8622  case CodeModel::Small:8623    Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;8624    break;8625  case CodeModel::Medium:8626    assert(Subtarget.is64Bit() && "Medium code model requires LA64");8627    Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;8628    break;8629  case CodeModel::Large:8630    assert(Subtarget.is64Bit() && "Large code model requires LA64");8631    Op = IsTailCall ? LoongArchISD::TAIL_LARGE : LoongArchISD::CALL_LARGE;8632    break;8633  }8634 8635  if (IsTailCall) {8636    MF.getFrameInfo().setHasTailCall();8637    SDValue Ret = DAG.getNode(Op, DL, NodeTys, Ops);8638    DAG.addNoMergeSiteInfo(Ret.getNode(), CLI.NoMerge);8639    return Ret;8640  }8641 8642  Chain = DAG.getNode(Op, DL, NodeTys, Ops);8643  DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);8644  Glue = Chain.getValue(1);8645 8646  // Mark the end of the call, which is glued to the call itself.8647  Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, DL);8648  Glue = Chain.getValue(1);8649 8650  // Assign locations to each value returned by this call.8651  SmallVector<CCValAssign> RVLocs;8652  CCState RetCCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext());8653  analyzeInputArgs(MF, RetCCInfo, Ins, /*IsRet=*/true, CC_LoongArch);8654 8655  // Copy all of the result registers out of their specified physreg.8656  for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {8657    auto &VA = RVLocs[i];8658    // Copy the value out.8659    SDValue RetValue =8660        DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue);8661    // Glue the RetValue to the end of the call sequence.8662    Chain = RetValue.getValue(1);8663    Glue = RetValue.getValue(2);8664 8665    if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {8666      assert(VA.needsCustom());8667      SDValue RetValue2 = DAG.getCopyFromReg(Chain, DL, RVLocs[++i].getLocReg(),8668                                             MVT::i32, Glue);8669      Chain = RetValue2.getValue(1);8670      Glue = RetValue2.getValue(2);8671      RetValue = DAG.getNode(LoongArchISD::BUILD_PAIR_F64, DL, MVT::f64,8672                             RetValue, RetValue2);8673    } else8674      RetValue = convertLocVTToValVT(DAG, RetValue, VA, DL);8675 8676    InVals.push_back(RetValue);8677  }8678 8679  return Chain;8680}8681 8682bool LoongArchTargetLowering::CanLowerReturn(8683    CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,8684    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,8685    const Type *RetTy) const {8686  SmallVector<CCValAssign> RVLocs;8687  CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);8688 8689  for (unsigned i = 0, e = Outs.size(); i != e; ++i) {8690    LoongArchABI::ABI ABI =8691        MF.getSubtarget<LoongArchSubtarget>().getTargetABI();8692    if (CC_LoongArch(MF.getDataLayout(), ABI, i, Outs[i].VT, CCValAssign::Full,8693                     Outs[i].Flags, CCInfo, /*IsRet=*/true, nullptr))8694      return false;8695  }8696  return true;8697}8698 8699SDValue LoongArchTargetLowering::LowerReturn(8700    SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,8701    const SmallVectorImpl<ISD::OutputArg> &Outs,8702    const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,8703    SelectionDAG &DAG) const {8704  // Stores the assignment of the return value to a location.8705  SmallVector<CCValAssign> RVLocs;8706 8707  // Info about the registers and stack slot.8708  CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,8709                 *DAG.getContext());8710 8711  analyzeOutputArgs(DAG.getMachineFunction(), CCInfo, Outs, /*IsRet=*/true,8712                    nullptr, CC_LoongArch);8713  if (CallConv == CallingConv::GHC && !RVLocs.empty())8714    report_fatal_error("GHC functions return void only");8715  SDValue Glue;8716  SmallVector<SDValue, 4> RetOps(1, Chain);8717 8718  // Copy the result values into the output registers.8719  for (unsigned i = 0, e = RVLocs.size(), OutIdx = 0; i < e; ++i, ++OutIdx) {8720    SDValue Val = OutVals[OutIdx];8721    CCValAssign &VA = RVLocs[i];8722    assert(VA.isRegLoc() && "Can only return in registers!");8723 8724    if (VA.getLocVT() == MVT::i32 && VA.getValVT() == MVT::f64) {8725      // Handle returning f64 on LA32D with a soft float ABI.8726      assert(VA.isRegLoc() && "Expected return via registers");8727      assert(VA.needsCustom());8728      SDValue SplitF64 = DAG.getNode(LoongArchISD::SPLIT_PAIR_F64, DL,8729                                     DAG.getVTList(MVT::i32, MVT::i32), Val);8730      SDValue Lo = SplitF64.getValue(0);8731      SDValue Hi = SplitF64.getValue(1);8732      Register RegLo = VA.getLocReg();8733      Register RegHi = RVLocs[++i].getLocReg();8734 8735      Chain = DAG.getCopyToReg(Chain, DL, RegLo, Lo, Glue);8736      Glue = Chain.getValue(1);8737      RetOps.push_back(DAG.getRegister(RegLo, MVT::i32));8738      Chain = DAG.getCopyToReg(Chain, DL, RegHi, Hi, Glue);8739      Glue = Chain.getValue(1);8740      RetOps.push_back(DAG.getRegister(RegHi, MVT::i32));8741    } else {8742      // Handle a 'normal' return.8743      Val = convertValVTToLocVT(DAG, Val, VA, DL);8744      Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Glue);8745 8746      // Guarantee that all emitted copies are stuck together.8747      Glue = Chain.getValue(1);8748      RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));8749    }8750  }8751 8752  RetOps[0] = Chain; // Update chain.8753 8754  // Add the glue node if we have it.8755  if (Glue.getNode())8756    RetOps.push_back(Glue);8757 8758  return DAG.getNode(LoongArchISD::RET, DL, MVT::Other, RetOps);8759}8760 8761// Check if a constant splat can be generated using [x]vldi, where imm[12] == 1.8762// Note: The following prefixes are excluded:8763//   imm[11:8] == 4'b0000, 4'b0100, 4'b10008764// as they can be represented using [x]vrepli.[whb]8765std::pair<bool, uint64_t> LoongArchTargetLowering::isImmVLDILegalForMode1(8766    const APInt &SplatValue, const unsigned SplatBitSize) const {8767  uint64_t RequiredImm = 0;8768  uint64_t V = SplatValue.getZExtValue();8769  if (SplatBitSize == 16 && !(V & 0x00FF)) {8770    // 4'b01018771    RequiredImm = (0b10101 << 8) | (V >> 8);8772    return {true, RequiredImm};8773  } else if (SplatBitSize == 32) {8774    // 4'b00018775    if (!(V & 0xFFFF00FF)) {8776      RequiredImm = (0b10001 << 8) | (V >> 8);8777      return {true, RequiredImm};8778    }8779    // 4'b00108780    if (!(V & 0xFF00FFFF)) {8781      RequiredImm = (0b10010 << 8) | (V >> 16);8782      return {true, RequiredImm};8783    }8784    // 4'b00118785    if (!(V & 0x00FFFFFF)) {8786      RequiredImm = (0b10011 << 8) | (V >> 24);8787      return {true, RequiredImm};8788    }8789    // 4'b01108790    if ((V & 0xFFFF00FF) == 0xFF) {8791      RequiredImm = (0b10110 << 8) | (V >> 8);8792      return {true, RequiredImm};8793    }8794    // 4'b01118795    if ((V & 0xFF00FFFF) == 0xFFFF) {8796      RequiredImm = (0b10111 << 8) | (V >> 16);8797      return {true, RequiredImm};8798    }8799    // 4'b10108800    if ((V & 0x7E07FFFF) == 0x3E000000 || (V & 0x7E07FFFF) == 0x40000000) {8801      RequiredImm =8802          (0b11010 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);8803      return {true, RequiredImm};8804    }8805  } else if (SplatBitSize == 64) {8806    // 4'b10118807    if ((V & 0xFFFFFFFF7E07FFFFULL) == 0x3E000000ULL ||8808        (V & 0xFFFFFFFF7E07FFFFULL) == 0x40000000ULL) {8809      RequiredImm =8810          (0b11011 << 8) | (((V >> 24) & 0xC0) ^ 0x40) | ((V >> 19) & 0x3F);8811      return {true, RequiredImm};8812    }8813    // 4'b11008814    if ((V & 0x7FC0FFFFFFFFFFFFULL) == 0x4000000000000000ULL ||8815        (V & 0x7FC0FFFFFFFFFFFFULL) == 0x3FC0000000000000ULL) {8816      RequiredImm =8817          (0b11100 << 8) | (((V >> 56) & 0xC0) ^ 0x40) | ((V >> 48) & 0x3F);8818      return {true, RequiredImm};8819    }8820    // 4'b10018821    auto sameBitsPreByte = [](uint64_t x) -> std::pair<bool, uint8_t> {8822      uint8_t res = 0;8823      for (int i = 0; i < 8; ++i) {8824        uint8_t byte = x & 0xFF;8825        if (byte == 0 || byte == 0xFF)8826          res |= ((byte & 1) << i);8827        else8828          return {false, 0};8829        x >>= 8;8830      }8831      return {true, res};8832    };8833    auto [IsSame, Suffix] = sameBitsPreByte(V);8834    if (IsSame) {8835      RequiredImm = (0b11001 << 8) | Suffix;8836      return {true, RequiredImm};8837    }8838  }8839  return {false, RequiredImm};8840}8841 8842bool LoongArchTargetLowering::isFPImmVLDILegal(const APFloat &Imm,8843                                               EVT VT) const {8844  if (!Subtarget.hasExtLSX())8845    return false;8846 8847  if (VT == MVT::f32) {8848    uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;8849    return (masked == 0x3e000000 || masked == 0x40000000);8850  }8851 8852  if (VT == MVT::f64) {8853    uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;8854    return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);8855  }8856 8857  return false;8858}8859 8860bool LoongArchTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,8861                                           bool ForCodeSize) const {8862  // TODO: Maybe need more checks here after vector extension is supported.8863  if (VT == MVT::f32 && !Subtarget.hasBasicF())8864    return false;8865  if (VT == MVT::f64 && !Subtarget.hasBasicD())8866    return false;8867  return (Imm.isZero() || Imm.isExactlyValue(1.0) || isFPImmVLDILegal(Imm, VT));8868}8869 8870bool LoongArchTargetLowering::isCheapToSpeculateCttz(Type *) const {8871  return true;8872}8873 8874bool LoongArchTargetLowering::isCheapToSpeculateCtlz(Type *) const {8875  return true;8876}8877 8878bool LoongArchTargetLowering::shouldInsertFencesForAtomic(8879    const Instruction *I) const {8880  if (!Subtarget.is64Bit())8881    return isa<LoadInst>(I) || isa<StoreInst>(I);8882 8883  if (isa<LoadInst>(I))8884    return true;8885 8886  // On LA64, atomic store operations with IntegerBitWidth of 32 and 64 do not8887  // require fences beacuse we can use amswap_db.[w/d].8888  Type *Ty = I->getOperand(0)->getType();8889  if (isa<StoreInst>(I) && Ty->isIntegerTy()) {8890    unsigned Size = Ty->getIntegerBitWidth();8891    return (Size == 8 || Size == 16);8892  }8893 8894  return false;8895}8896 8897EVT LoongArchTargetLowering::getSetCCResultType(const DataLayout &DL,8898                                                LLVMContext &Context,8899                                                EVT VT) const {8900  if (!VT.isVector())8901    return getPointerTy(DL);8902  return VT.changeVectorElementTypeToInteger();8903}8904 8905bool LoongArchTargetLowering::hasAndNot(SDValue Y) const {8906  EVT VT = Y.getValueType();8907 8908  if (VT.isVector())8909    return Subtarget.hasExtLSX() && VT.isInteger();8910 8911  return VT.isScalarInteger() && !isa<ConstantSDNode>(Y);8912}8913 8914bool LoongArchTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,8915                                                 const CallInst &I,8916                                                 MachineFunction &MF,8917                                                 unsigned Intrinsic) const {8918  switch (Intrinsic) {8919  default:8920    return false;8921  case Intrinsic::loongarch_masked_atomicrmw_xchg_i32:8922  case Intrinsic::loongarch_masked_atomicrmw_add_i32:8923  case Intrinsic::loongarch_masked_atomicrmw_sub_i32:8924  case Intrinsic::loongarch_masked_atomicrmw_nand_i32:8925    Info.opc = ISD::INTRINSIC_W_CHAIN;8926    Info.memVT = MVT::i32;8927    Info.ptrVal = I.getArgOperand(0);8928    Info.offset = 0;8929    Info.align = Align(4);8930    Info.flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore |8931                 MachineMemOperand::MOVolatile;8932    return true;8933    // TODO: Add more Intrinsics later.8934  }8935}8936 8937// When -mlamcas is enabled, MinCmpXchgSizeInBits will be set to 8,8938// atomicrmw and/or/xor operations with operands less than 32 bits cannot be8939// expanded to am{and/or/xor}[_db].w through AtomicExpandPass. To prevent8940// regression, we need to implement it manually.8941void LoongArchTargetLowering::emitExpandAtomicRMW(AtomicRMWInst *AI) const {8942  AtomicRMWInst::BinOp Op = AI->getOperation();8943 8944  assert((Op == AtomicRMWInst::Or || Op == AtomicRMWInst::Xor ||8945          Op == AtomicRMWInst::And) &&8946         "Unable to expand");8947  unsigned MinWordSize = 4;8948 8949  IRBuilder<> Builder(AI);8950  LLVMContext &Ctx = Builder.getContext();8951  const DataLayout &DL = AI->getDataLayout();8952  Type *ValueType = AI->getType();8953  Type *WordType = Type::getIntNTy(Ctx, MinWordSize * 8);8954 8955  Value *Addr = AI->getPointerOperand();8956  PointerType *PtrTy = cast<PointerType>(Addr->getType());8957  IntegerType *IntTy = DL.getIndexType(Ctx, PtrTy->getAddressSpace());8958 8959  Value *AlignedAddr = Builder.CreateIntrinsic(8960      Intrinsic::ptrmask, {PtrTy, IntTy},8961      {Addr, ConstantInt::get(IntTy, ~(uint64_t)(MinWordSize - 1))}, nullptr,8962      "AlignedAddr");8963 8964  Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);8965  Value *PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1, "PtrLSB");8966  Value *ShiftAmt = Builder.CreateShl(PtrLSB, 3);8967  ShiftAmt = Builder.CreateTrunc(ShiftAmt, WordType, "ShiftAmt");8968  Value *Mask = Builder.CreateShl(8969      ConstantInt::get(WordType,8970                       (1 << (DL.getTypeStoreSize(ValueType) * 8)) - 1),8971      ShiftAmt, "Mask");8972  Value *Inv_Mask = Builder.CreateNot(Mask, "Inv_Mask");8973  Value *ValOperand_Shifted =8974      Builder.CreateShl(Builder.CreateZExt(AI->getValOperand(), WordType),8975                        ShiftAmt, "ValOperand_Shifted");8976  Value *NewOperand;8977  if (Op == AtomicRMWInst::And)8978    NewOperand = Builder.CreateOr(ValOperand_Shifted, Inv_Mask, "AndOperand");8979  else8980    NewOperand = ValOperand_Shifted;8981 8982  AtomicRMWInst *NewAI =8983      Builder.CreateAtomicRMW(Op, AlignedAddr, NewOperand, Align(MinWordSize),8984                              AI->getOrdering(), AI->getSyncScopeID());8985 8986  Value *Shift = Builder.CreateLShr(NewAI, ShiftAmt, "shifted");8987  Value *Trunc = Builder.CreateTrunc(Shift, ValueType, "extracted");8988  Value *FinalOldResult = Builder.CreateBitCast(Trunc, ValueType);8989  AI->replaceAllUsesWith(FinalOldResult);8990  AI->eraseFromParent();8991}8992 8993TargetLowering::AtomicExpansionKind8994LoongArchTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {8995  // TODO: Add more AtomicRMWInst that needs to be extended.8996 8997  // Since floating-point operation requires a non-trivial set of data8998  // operations, use CmpXChg to expand.8999  if (AI->isFloatingPointOperation() ||9000      AI->getOperation() == AtomicRMWInst::UIncWrap ||9001      AI->getOperation() == AtomicRMWInst::UDecWrap ||9002      AI->getOperation() == AtomicRMWInst::USubCond ||9003      AI->getOperation() == AtomicRMWInst::USubSat)9004    return AtomicExpansionKind::CmpXChg;9005 9006  if (Subtarget.hasLAM_BH() && Subtarget.is64Bit() &&9007      (AI->getOperation() == AtomicRMWInst::Xchg ||9008       AI->getOperation() == AtomicRMWInst::Add ||9009       AI->getOperation() == AtomicRMWInst::Sub)) {9010    return AtomicExpansionKind::None;9011  }9012 9013  unsigned Size = AI->getType()->getPrimitiveSizeInBits();9014  if (Subtarget.hasLAMCAS()) {9015    if (Size < 32 && (AI->getOperation() == AtomicRMWInst::And ||9016                      AI->getOperation() == AtomicRMWInst::Or ||9017                      AI->getOperation() == AtomicRMWInst::Xor))9018      return AtomicExpansionKind::CustomExpand;9019    if (AI->getOperation() == AtomicRMWInst::Nand || Size < 32)9020      return AtomicExpansionKind::CmpXChg;9021  }9022 9023  if (Size == 8 || Size == 16)9024    return AtomicExpansionKind::MaskedIntrinsic;9025  return AtomicExpansionKind::None;9026}9027 9028static Intrinsic::ID9029getIntrinsicForMaskedAtomicRMWBinOp(unsigned GRLen,9030                                    AtomicRMWInst::BinOp BinOp) {9031  if (GRLen == 64) {9032    switch (BinOp) {9033    default:9034      llvm_unreachable("Unexpected AtomicRMW BinOp");9035    case AtomicRMWInst::Xchg:9036      return Intrinsic::loongarch_masked_atomicrmw_xchg_i64;9037    case AtomicRMWInst::Add:9038      return Intrinsic::loongarch_masked_atomicrmw_add_i64;9039    case AtomicRMWInst::Sub:9040      return Intrinsic::loongarch_masked_atomicrmw_sub_i64;9041    case AtomicRMWInst::Nand:9042      return Intrinsic::loongarch_masked_atomicrmw_nand_i64;9043    case AtomicRMWInst::UMax:9044      return Intrinsic::loongarch_masked_atomicrmw_umax_i64;9045    case AtomicRMWInst::UMin:9046      return Intrinsic::loongarch_masked_atomicrmw_umin_i64;9047    case AtomicRMWInst::Max:9048      return Intrinsic::loongarch_masked_atomicrmw_max_i64;9049    case AtomicRMWInst::Min:9050      return Intrinsic::loongarch_masked_atomicrmw_min_i64;9051      // TODO: support other AtomicRMWInst.9052    }9053  }9054 9055  if (GRLen == 32) {9056    switch (BinOp) {9057    default:9058      llvm_unreachable("Unexpected AtomicRMW BinOp");9059    case AtomicRMWInst::Xchg:9060      return Intrinsic::loongarch_masked_atomicrmw_xchg_i32;9061    case AtomicRMWInst::Add:9062      return Intrinsic::loongarch_masked_atomicrmw_add_i32;9063    case AtomicRMWInst::Sub:9064      return Intrinsic::loongarch_masked_atomicrmw_sub_i32;9065    case AtomicRMWInst::Nand:9066      return Intrinsic::loongarch_masked_atomicrmw_nand_i32;9067    case AtomicRMWInst::UMax:9068      return Intrinsic::loongarch_masked_atomicrmw_umax_i32;9069    case AtomicRMWInst::UMin:9070      return Intrinsic::loongarch_masked_atomicrmw_umin_i32;9071    case AtomicRMWInst::Max:9072      return Intrinsic::loongarch_masked_atomicrmw_max_i32;9073    case AtomicRMWInst::Min:9074      return Intrinsic::loongarch_masked_atomicrmw_min_i32;9075      // TODO: support other AtomicRMWInst.9076    }9077  }9078 9079  llvm_unreachable("Unexpected GRLen\n");9080}9081 9082TargetLowering::AtomicExpansionKind9083LoongArchTargetLowering::shouldExpandAtomicCmpXchgInIR(9084    AtomicCmpXchgInst *CI) const {9085 9086  if (Subtarget.hasLAMCAS())9087    return AtomicExpansionKind::None;9088 9089  unsigned Size = CI->getCompareOperand()->getType()->getPrimitiveSizeInBits();9090  if (Size == 8 || Size == 16)9091    return AtomicExpansionKind::MaskedIntrinsic;9092  return AtomicExpansionKind::None;9093}9094 9095Value *LoongArchTargetLowering::emitMaskedAtomicCmpXchgIntrinsic(9096    IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr,9097    Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const {9098  unsigned GRLen = Subtarget.getGRLen();9099  AtomicOrdering FailOrd = CI->getFailureOrdering();9100  Value *FailureOrdering =9101      Builder.getIntN(Subtarget.getGRLen(), static_cast<uint64_t>(FailOrd));9102  Intrinsic::ID CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i32;9103  if (GRLen == 64) {9104    CmpXchgIntrID = Intrinsic::loongarch_masked_cmpxchg_i64;9105    CmpVal = Builder.CreateSExt(CmpVal, Builder.getInt64Ty());9106    NewVal = Builder.CreateSExt(NewVal, Builder.getInt64Ty());9107    Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());9108  }9109  Type *Tys[] = {AlignedAddr->getType()};9110  Value *Result = Builder.CreateIntrinsic(9111      CmpXchgIntrID, Tys, {AlignedAddr, CmpVal, NewVal, Mask, FailureOrdering});9112  if (GRLen == 64)9113    Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());9114  return Result;9115}9116 9117Value *LoongArchTargetLowering::emitMaskedAtomicRMWIntrinsic(9118    IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr,9119    Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const {9120  // In the case of an atomicrmw xchg with a constant 0/-1 operand, replace9121  // the atomic instruction with an AtomicRMWInst::And/Or with appropriate9122  // mask, as this produces better code than the LL/SC loop emitted by9123  // int_loongarch_masked_atomicrmw_xchg.9124  if (AI->getOperation() == AtomicRMWInst::Xchg &&9125      isa<ConstantInt>(AI->getValOperand())) {9126    ConstantInt *CVal = cast<ConstantInt>(AI->getValOperand());9127    if (CVal->isZero())9128      return Builder.CreateAtomicRMW(AtomicRMWInst::And, AlignedAddr,9129                                     Builder.CreateNot(Mask, "Inv_Mask"),9130                                     AI->getAlign(), Ord);9131    if (CVal->isMinusOne())9132      return Builder.CreateAtomicRMW(AtomicRMWInst::Or, AlignedAddr, Mask,9133                                     AI->getAlign(), Ord);9134  }9135 9136  unsigned GRLen = Subtarget.getGRLen();9137  Value *Ordering =9138      Builder.getIntN(GRLen, static_cast<uint64_t>(AI->getOrdering()));9139  Type *Tys[] = {AlignedAddr->getType()};9140  Function *LlwOpScwLoop = Intrinsic::getOrInsertDeclaration(9141      AI->getModule(),9142      getIntrinsicForMaskedAtomicRMWBinOp(GRLen, AI->getOperation()), Tys);9143 9144  if (GRLen == 64) {9145    Incr = Builder.CreateSExt(Incr, Builder.getInt64Ty());9146    Mask = Builder.CreateSExt(Mask, Builder.getInt64Ty());9147    ShiftAmt = Builder.CreateSExt(ShiftAmt, Builder.getInt64Ty());9148  }9149 9150  Value *Result;9151 9152  // Must pass the shift amount needed to sign extend the loaded value prior9153  // to performing a signed comparison for min/max. ShiftAmt is the number of9154  // bits to shift the value into position. Pass GRLen-ShiftAmt-ValWidth, which9155  // is the number of bits to left+right shift the value in order to9156  // sign-extend.9157  if (AI->getOperation() == AtomicRMWInst::Min ||9158      AI->getOperation() == AtomicRMWInst::Max) {9159    const DataLayout &DL = AI->getDataLayout();9160    unsigned ValWidth =9161        DL.getTypeStoreSizeInBits(AI->getValOperand()->getType());9162    Value *SextShamt =9163        Builder.CreateSub(Builder.getIntN(GRLen, GRLen - ValWidth), ShiftAmt);9164    Result = Builder.CreateCall(LlwOpScwLoop,9165                                {AlignedAddr, Incr, Mask, SextShamt, Ordering});9166  } else {9167    Result =9168        Builder.CreateCall(LlwOpScwLoop, {AlignedAddr, Incr, Mask, Ordering});9169  }9170 9171  if (GRLen == 64)9172    Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());9173  return Result;9174}9175 9176bool LoongArchTargetLowering::isFMAFasterThanFMulAndFAdd(9177    const MachineFunction &MF, EVT VT) const {9178  VT = VT.getScalarType();9179 9180  if (!VT.isSimple())9181    return false;9182 9183  switch (VT.getSimpleVT().SimpleTy) {9184  case MVT::f32:9185  case MVT::f64:9186    return true;9187  default:9188    break;9189  }9190 9191  return false;9192}9193 9194Register LoongArchTargetLowering::getExceptionPointerRegister(9195    const Constant *PersonalityFn) const {9196  return LoongArch::R4;9197}9198 9199Register LoongArchTargetLowering::getExceptionSelectorRegister(9200    const Constant *PersonalityFn) const {9201  return LoongArch::R5;9202}9203 9204//===----------------------------------------------------------------------===//9205// Target Optimization Hooks9206//===----------------------------------------------------------------------===//9207 9208static int getEstimateRefinementSteps(EVT VT,9209                                      const LoongArchSubtarget &Subtarget) {9210  // Feature FRECIPE instrucions relative accuracy is 2^-14.9211  // IEEE float has 23 digits and double has 52 digits.9212  int RefinementSteps = VT.getScalarType() == MVT::f64 ? 2 : 1;9213  return RefinementSteps;9214}9215 9216SDValue LoongArchTargetLowering::getSqrtEstimate(SDValue Operand,9217                                                 SelectionDAG &DAG, int Enabled,9218                                                 int &RefinementSteps,9219                                                 bool &UseOneConstNR,9220                                                 bool Reciprocal) const {9221  if (Subtarget.hasFrecipe()) {9222    SDLoc DL(Operand);9223    EVT VT = Operand.getValueType();9224 9225    if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||9226        (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||9227        (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||9228        (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||9229        (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {9230 9231      if (RefinementSteps == ReciprocalEstimate::Unspecified)9232        RefinementSteps = getEstimateRefinementSteps(VT, Subtarget);9233 9234      SDValue Estimate = DAG.getNode(LoongArchISD::FRSQRTE, DL, VT, Operand);9235      if (Reciprocal)9236        Estimate = DAG.getNode(ISD::FMUL, DL, VT, Operand, Estimate);9237 9238      return Estimate;9239    }9240  }9241 9242  return SDValue();9243}9244 9245SDValue LoongArchTargetLowering::getRecipEstimate(SDValue Operand,9246                                                  SelectionDAG &DAG,9247                                                  int Enabled,9248                                                  int &RefinementSteps) const {9249  if (Subtarget.hasFrecipe()) {9250    SDLoc DL(Operand);9251    EVT VT = Operand.getValueType();9252 9253    if (VT == MVT::f32 || (VT == MVT::f64 && Subtarget.hasBasicD()) ||9254        (VT == MVT::v4f32 && Subtarget.hasExtLSX()) ||9255        (VT == MVT::v2f64 && Subtarget.hasExtLSX()) ||9256        (VT == MVT::v8f32 && Subtarget.hasExtLASX()) ||9257        (VT == MVT::v4f64 && Subtarget.hasExtLASX())) {9258 9259      if (RefinementSteps == ReciprocalEstimate::Unspecified)9260        RefinementSteps = getEstimateRefinementSteps(VT, Subtarget);9261 9262      return DAG.getNode(LoongArchISD::FRECIPE, DL, VT, Operand);9263    }9264  }9265 9266  return SDValue();9267}9268 9269//===----------------------------------------------------------------------===//9270//                           LoongArch Inline Assembly Support9271//===----------------------------------------------------------------------===//9272 9273LoongArchTargetLowering::ConstraintType9274LoongArchTargetLowering::getConstraintType(StringRef Constraint) const {9275  // LoongArch specific constraints in GCC: config/loongarch/constraints.md9276  //9277  // 'f':  A floating-point register (if available).9278  // 'k':  A memory operand whose address is formed by a base register and9279  //       (optionally scaled) index register.9280  // 'l':  A signed 16-bit constant.9281  // 'm':  A memory operand whose address is formed by a base register and9282  //       offset that is suitable for use in instructions with the same9283  //       addressing mode as st.w and ld.w.9284  // 'q':  A general-purpose register except for $r0 and $r1 (for the csrxchg9285  //       instruction)9286  // 'I':  A signed 12-bit constant (for arithmetic instructions).9287  // 'J':  Integer zero.9288  // 'K':  An unsigned 12-bit constant (for logic instructions).9289  // "ZB": An address that is held in a general-purpose register. The offset is9290  //       zero.9291  // "ZC": A memory operand whose address is formed by a base register and9292  //       offset that is suitable for use in instructions with the same9293  //       addressing mode as ll.w and sc.w.9294  if (Constraint.size() == 1) {9295    switch (Constraint[0]) {9296    default:9297      break;9298    case 'f':9299    case 'q':9300      return C_RegisterClass;9301    case 'l':9302    case 'I':9303    case 'J':9304    case 'K':9305      return C_Immediate;9306    case 'k':9307      return C_Memory;9308    }9309  }9310 9311  if (Constraint == "ZC" || Constraint == "ZB")9312    return C_Memory;9313 9314  // 'm' is handled here.9315  return TargetLowering::getConstraintType(Constraint);9316}9317 9318InlineAsm::ConstraintCode LoongArchTargetLowering::getInlineAsmMemConstraint(9319    StringRef ConstraintCode) const {9320  return StringSwitch<InlineAsm::ConstraintCode>(ConstraintCode)9321      .Case("k", InlineAsm::ConstraintCode::k)9322      .Case("ZB", InlineAsm::ConstraintCode::ZB)9323      .Case("ZC", InlineAsm::ConstraintCode::ZC)9324      .Default(TargetLowering::getInlineAsmMemConstraint(ConstraintCode));9325}9326 9327std::pair<unsigned, const TargetRegisterClass *>9328LoongArchTargetLowering::getRegForInlineAsmConstraint(9329    const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {9330  // First, see if this is a constraint that directly corresponds to a LoongArch9331  // register class.9332  if (Constraint.size() == 1) {9333    switch (Constraint[0]) {9334    case 'r':9335      // TODO: Support fixed vectors up to GRLen?9336      if (VT.isVector())9337        break;9338      return std::make_pair(0U, &LoongArch::GPRRegClass);9339    case 'q':9340      return std::make_pair(0U, &LoongArch::GPRNoR0R1RegClass);9341    case 'f':9342      if (Subtarget.hasBasicF() && VT == MVT::f32)9343        return std::make_pair(0U, &LoongArch::FPR32RegClass);9344      if (Subtarget.hasBasicD() && VT == MVT::f64)9345        return std::make_pair(0U, &LoongArch::FPR64RegClass);9346      if (Subtarget.hasExtLSX() &&9347          TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))9348        return std::make_pair(0U, &LoongArch::LSX128RegClass);9349      if (Subtarget.hasExtLASX() &&9350          TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))9351        return std::make_pair(0U, &LoongArch::LASX256RegClass);9352      break;9353    default:9354      break;9355    }9356  }9357 9358  // TargetLowering::getRegForInlineAsmConstraint uses the name of the TableGen9359  // record (e.g. the "R0" in `def R0`) to choose registers for InlineAsm9360  // constraints while the official register name is prefixed with a '$'. So we9361  // clip the '$' from the original constraint string (e.g. {$r0} to {r0}.)9362  // before it being parsed. And TargetLowering::getRegForInlineAsmConstraint is9363  // case insensitive, so no need to convert the constraint to upper case here.9364  //9365  // For now, no need to support ABI names (e.g. `$a0`) as clang will correctly9366  // decode the usage of register name aliases into their official names. And9367  // AFAIK, the not yet upstreamed `rustc` for LoongArch will always use9368  // official register names.9369  if (Constraint.starts_with("{$r") || Constraint.starts_with("{$f") ||9370      Constraint.starts_with("{$vr") || Constraint.starts_with("{$xr")) {9371    bool IsFP = Constraint[2] == 'f';9372    std::pair<StringRef, StringRef> Temp = Constraint.split('$');9373    std::pair<unsigned, const TargetRegisterClass *> R;9374    R = TargetLowering::getRegForInlineAsmConstraint(9375        TRI, join_items("", Temp.first, Temp.second), VT);9376    // Match those names to the widest floating point register type available.9377    if (IsFP) {9378      unsigned RegNo = R.first;9379      if (LoongArch::F0 <= RegNo && RegNo <= LoongArch::F31) {9380        if (Subtarget.hasBasicD() && (VT == MVT::f64 || VT == MVT::Other)) {9381          unsigned DReg = RegNo - LoongArch::F0 + LoongArch::F0_64;9382          return std::make_pair(DReg, &LoongArch::FPR64RegClass);9383        }9384      }9385    }9386    return R;9387  }9388 9389  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);9390}9391 9392void LoongArchTargetLowering::LowerAsmOperandForConstraint(9393    SDValue Op, StringRef Constraint, std::vector<SDValue> &Ops,9394    SelectionDAG &DAG) const {9395  // Currently only support length 1 constraints.9396  if (Constraint.size() == 1) {9397    switch (Constraint[0]) {9398    case 'l':9399      // Validate & create a 16-bit signed immediate operand.9400      if (auto *C = dyn_cast<ConstantSDNode>(Op)) {9401        uint64_t CVal = C->getSExtValue();9402        if (isInt<16>(CVal))9403          Ops.push_back(DAG.getSignedTargetConstant(CVal, SDLoc(Op),9404                                                    Subtarget.getGRLenVT()));9405      }9406      return;9407    case 'I':9408      // Validate & create a 12-bit signed immediate operand.9409      if (auto *C = dyn_cast<ConstantSDNode>(Op)) {9410        uint64_t CVal = C->getSExtValue();9411        if (isInt<12>(CVal))9412          Ops.push_back(DAG.getSignedTargetConstant(CVal, SDLoc(Op),9413                                                    Subtarget.getGRLenVT()));9414      }9415      return;9416    case 'J':9417      // Validate & create an integer zero operand.9418      if (auto *C = dyn_cast<ConstantSDNode>(Op))9419        if (C->getZExtValue() == 0)9420          Ops.push_back(9421              DAG.getTargetConstant(0, SDLoc(Op), Subtarget.getGRLenVT()));9422      return;9423    case 'K':9424      // Validate & create a 12-bit unsigned immediate operand.9425      if (auto *C = dyn_cast<ConstantSDNode>(Op)) {9426        uint64_t CVal = C->getZExtValue();9427        if (isUInt<12>(CVal))9428          Ops.push_back(9429              DAG.getTargetConstant(CVal, SDLoc(Op), Subtarget.getGRLenVT()));9430      }9431      return;9432    default:9433      break;9434    }9435  }9436  TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);9437}9438 9439#define GET_REGISTER_MATCHER9440#include "LoongArchGenAsmMatcher.inc"9441 9442Register9443LoongArchTargetLowering::getRegisterByName(const char *RegName, LLT VT,9444                                           const MachineFunction &MF) const {9445  std::pair<StringRef, StringRef> Name = StringRef(RegName).split('$');9446  std::string NewRegName = Name.second.str();9447  Register Reg = MatchRegisterAltName(NewRegName);9448  if (!Reg)9449    Reg = MatchRegisterName(NewRegName);9450  if (!Reg)9451    return Reg;9452  BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);9453  if (!ReservedRegs.test(Reg))9454    report_fatal_error(Twine("Trying to obtain non-reserved register \"" +9455                             StringRef(RegName) + "\"."));9456  return Reg;9457}9458 9459bool LoongArchTargetLowering::decomposeMulByConstant(LLVMContext &Context,9460                                                     EVT VT, SDValue C) const {9461  // TODO: Support vectors.9462  if (!VT.isScalarInteger())9463    return false;9464 9465  // Omit the optimization if the data size exceeds GRLen.9466  if (VT.getSizeInBits() > Subtarget.getGRLen())9467    return false;9468 9469  if (auto *ConstNode = dyn_cast<ConstantSDNode>(C.getNode())) {9470    const APInt &Imm = ConstNode->getAPIntValue();9471    // Break MUL into (SLLI + ADD/SUB) or ALSL.9472    if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||9473        (1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())9474      return true;9475    // Break MUL into (ALSL x, (SLLI x, imm0), imm1).9476    if (ConstNode->hasOneUse() &&9477        ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() ||9478         (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2()))9479      return true;9480    // Break (MUL x, imm) into (ADD (SLLI x, s0), (SLLI x, s1)),9481    // in which the immediate has two set bits. Or Break (MUL x, imm)9482    // into (SUB (SLLI x, s0), (SLLI x, s1)), in which the immediate9483    // equals to (1 << s0) - (1 << s1).9484    if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) {9485      unsigned Shifts = Imm.countr_zero();9486      // Reject immediates which can be composed via a single LUI.9487      if (Shifts >= 12)9488        return false;9489      // Reject multiplications can be optimized to9490      // (SLLI (ALSL x, x, 1/2/3/4), s).9491      APInt ImmPop = Imm.ashr(Shifts);9492      if (ImmPop == 3 || ImmPop == 5 || ImmPop == 9 || ImmPop == 17)9493        return false;9494      // We do not consider the case `(-Imm - ImmSmall).isPowerOf2()`,9495      // since it needs one more instruction than other 3 cases.9496      APInt ImmSmall = APInt(Imm.getBitWidth(), 1ULL << Shifts, true);9497      if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() ||9498          (ImmSmall - Imm).isPowerOf2())9499        return true;9500    }9501  }9502 9503  return false;9504}9505 9506bool LoongArchTargetLowering::isLegalAddressingMode(const DataLayout &DL,9507                                                    const AddrMode &AM,9508                                                    Type *Ty, unsigned AS,9509                                                    Instruction *I) const {9510  // LoongArch has four basic addressing modes:9511  //  1. reg9512  //  2. reg + 12-bit signed offset9513  //  3. reg + 14-bit signed offset left-shifted by 29514  //  4. reg1 + reg29515  // TODO: Add more checks after support vector extension.9516 9517  // No global is ever allowed as a base.9518  if (AM.BaseGV)9519    return false;9520 9521  // Require a 12-bit signed offset or 14-bit signed offset left-shifted by 29522  // with `UAL` feature.9523  if (!isInt<12>(AM.BaseOffs) &&9524      !(isShiftedInt<14, 2>(AM.BaseOffs) && Subtarget.hasUAL()))9525    return false;9526 9527  switch (AM.Scale) {9528  case 0:9529    // "r+i" or just "i", depending on HasBaseReg.9530    break;9531  case 1:9532    // "r+r+i" is not allowed.9533    if (AM.HasBaseReg && AM.BaseOffs)9534      return false;9535    // Otherwise we have "r+r" or "r+i".9536    break;9537  case 2:9538    // "2*r+r" or "2*r+i" is not allowed.9539    if (AM.HasBaseReg || AM.BaseOffs)9540      return false;9541    // Allow "2*r" as "r+r".9542    break;9543  default:9544    return false;9545  }9546 9547  return true;9548}9549 9550bool LoongArchTargetLowering::isLegalICmpImmediate(int64_t Imm) const {9551  return isInt<12>(Imm);9552}9553 9554bool LoongArchTargetLowering::isLegalAddImmediate(int64_t Imm) const {9555  return isInt<12>(Imm);9556}9557 9558bool LoongArchTargetLowering::isZExtFree(SDValue Val, EVT VT2) const {9559  // Zexts are free if they can be combined with a load.9560  // Don't advertise i32->i64 zextload as being free for LA64. It interacts9561  // poorly with type legalization of compares preferring sext.9562  if (auto *LD = dyn_cast<LoadSDNode>(Val)) {9563    EVT MemVT = LD->getMemoryVT();9564    if ((MemVT == MVT::i8 || MemVT == MVT::i16) &&9565        (LD->getExtensionType() == ISD::NON_EXTLOAD ||9566         LD->getExtensionType() == ISD::ZEXTLOAD))9567      return true;9568  }9569 9570  return TargetLowering::isZExtFree(Val, VT2);9571}9572 9573bool LoongArchTargetLowering::isSExtCheaperThanZExt(EVT SrcVT,9574                                                    EVT DstVT) const {9575  return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;9576}9577 9578bool LoongArchTargetLowering::signExtendConstant(const ConstantInt *CI) const {9579  return Subtarget.is64Bit() && CI->getType()->isIntegerTy(32);9580}9581 9582bool LoongArchTargetLowering::hasAndNotCompare(SDValue Y) const {9583  // TODO: Support vectors.9584  if (Y.getValueType().isVector())9585    return false;9586 9587  return !isa<ConstantSDNode>(Y);9588}9589 9590ISD::NodeType LoongArchTargetLowering::getExtendForAtomicCmpSwapArg() const {9591  // LAMCAS will use amcas[_DB].{b/h/w/d} which does not require extension.9592  return Subtarget.hasLAMCAS() ? ISD::ANY_EXTEND : ISD::SIGN_EXTEND;9593}9594 9595bool LoongArchTargetLowering::shouldSignExtendTypeInLibCall(9596    Type *Ty, bool IsSigned) const {9597  if (Subtarget.is64Bit() && Ty->isIntegerTy(32))9598    return true;9599 9600  return IsSigned;9601}9602 9603bool LoongArchTargetLowering::shouldExtendTypeInLibCall(EVT Type) const {9604  // Return false to suppress the unnecessary extensions if the LibCall9605  // arguments or return value is a float narrower than GRLEN on a soft FP ABI.9606  if (Subtarget.isSoftFPABI() && (Type.isFloatingPoint() && !Type.isVector() &&9607                                  Type.getSizeInBits() < Subtarget.getGRLen()))9608    return false;9609  return true;9610}9611 9612// memcpy, and other memory intrinsics, typically tries to use wider load/store9613// if the source/dest is aligned and the copy size is large enough. We therefore9614// want to align such objects passed to memory intrinsics.9615bool LoongArchTargetLowering::shouldAlignPointerArgs(CallInst *CI,9616                                                     unsigned &MinSize,9617                                                     Align &PrefAlign) const {9618  if (!isa<MemIntrinsic>(CI))9619    return false;9620 9621  if (Subtarget.is64Bit()) {9622    MinSize = 8;9623    PrefAlign = Align(8);9624  } else {9625    MinSize = 4;9626    PrefAlign = Align(4);9627  }9628 9629  return true;9630}9631 9632TargetLoweringBase::LegalizeTypeAction9633LoongArchTargetLowering::getPreferredVectorAction(MVT VT) const {9634  if (!VT.isScalableVector() && VT.getVectorNumElements() != 1 &&9635      VT.getVectorElementType() != MVT::i1)9636    return TypeWidenVector;9637 9638  return TargetLoweringBase::getPreferredVectorAction(VT);9639}9640 9641bool LoongArchTargetLowering::splitValueIntoRegisterParts(9642    SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts,9643    unsigned NumParts, MVT PartVT, std::optional<CallingConv::ID> CC) const {9644  bool IsABIRegCopy = CC.has_value();9645  EVT ValueVT = Val.getValueType();9646 9647  if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&9648      PartVT == MVT::f32) {9649    // Cast the [b]f16 to i16, extend to i32, pad with ones to make a float9650    // nan, and cast to f32.9651    Val = DAG.getNode(ISD::BITCAST, DL, MVT::i16, Val);9652    Val = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Val);9653    Val = DAG.getNode(ISD::OR, DL, MVT::i32, Val,9654                      DAG.getConstant(0xFFFF0000, DL, MVT::i32));9655    Val = DAG.getNode(ISD::BITCAST, DL, MVT::f32, Val);9656    Parts[0] = Val;9657    return true;9658  }9659 9660  return false;9661}9662 9663SDValue LoongArchTargetLowering::joinRegisterPartsIntoValue(9664    SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, unsigned NumParts,9665    MVT PartVT, EVT ValueVT, std::optional<CallingConv::ID> CC) const {9666  bool IsABIRegCopy = CC.has_value();9667 9668  if (IsABIRegCopy && (ValueVT == MVT::f16 || ValueVT == MVT::bf16) &&9669      PartVT == MVT::f32) {9670    SDValue Val = Parts[0];9671 9672    // Cast the f32 to i32, truncate to i16, and cast back to [b]f16.9673    Val = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Val);9674    Val = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Val);9675    Val = DAG.getNode(ISD::BITCAST, DL, ValueVT, Val);9676    return Val;9677  }9678 9679  return SDValue();9680}9681 9682MVT LoongArchTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context,9683                                                           CallingConv::ID CC,9684                                                           EVT VT) const {9685  // Use f32 to pass f16.9686  if (VT == MVT::f16 && Subtarget.hasBasicF())9687    return MVT::f32;9688 9689  return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);9690}9691 9692unsigned LoongArchTargetLowering::getNumRegistersForCallingConv(9693    LLVMContext &Context, CallingConv::ID CC, EVT VT) const {9694  // Use f32 to pass f16.9695  if (VT == MVT::f16 && Subtarget.hasBasicF())9696    return 1;9697 9698  return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT);9699}9700 9701bool LoongArchTargetLowering::SimplifyDemandedBitsForTargetNode(9702    SDValue Op, const APInt &OriginalDemandedBits,9703    const APInt &OriginalDemandedElts, KnownBits &Known, TargetLoweringOpt &TLO,9704    unsigned Depth) const {9705  EVT VT = Op.getValueType();9706  unsigned BitWidth = OriginalDemandedBits.getBitWidth();9707  unsigned Opc = Op.getOpcode();9708  switch (Opc) {9709  default:9710    break;9711  case LoongArchISD::VMSKLTZ:9712  case LoongArchISD::XVMSKLTZ: {9713    SDValue Src = Op.getOperand(0);9714    MVT SrcVT = Src.getSimpleValueType();9715    unsigned SrcBits = SrcVT.getScalarSizeInBits();9716    unsigned NumElts = SrcVT.getVectorNumElements();9717 9718    // If we don't need the sign bits at all just return zero.9719    if (OriginalDemandedBits.countr_zero() >= NumElts)9720      return TLO.CombineTo(Op, TLO.DAG.getConstant(0, SDLoc(Op), VT));9721 9722    // Only demand the vector elements of the sign bits we need.9723    APInt KnownUndef, KnownZero;9724    APInt DemandedElts = OriginalDemandedBits.zextOrTrunc(NumElts);9725    if (SimplifyDemandedVectorElts(Src, DemandedElts, KnownUndef, KnownZero,9726                                   TLO, Depth + 1))9727      return true;9728 9729    Known.Zero = KnownZero.zext(BitWidth);9730    Known.Zero.setHighBits(BitWidth - NumElts);9731 9732    // [X]VMSKLTZ only uses the MSB from each vector element.9733    KnownBits KnownSrc;9734    APInt DemandedSrcBits = APInt::getSignMask(SrcBits);9735    if (SimplifyDemandedBits(Src, DemandedSrcBits, DemandedElts, KnownSrc, TLO,9736                             Depth + 1))9737      return true;9738 9739    if (KnownSrc.One[SrcBits - 1])9740      Known.One.setLowBits(NumElts);9741    else if (KnownSrc.Zero[SrcBits - 1])9742      Known.Zero.setLowBits(NumElts);9743 9744    // Attempt to avoid multi-use ops if we don't need anything from it.9745    if (SDValue NewSrc = SimplifyMultipleUseDemandedBits(9746            Src, DemandedSrcBits, DemandedElts, TLO.DAG, Depth + 1))9747      return TLO.CombineTo(Op, TLO.DAG.getNode(Opc, SDLoc(Op), VT, NewSrc));9748    return false;9749  }9750  }9751 9752  return TargetLowering::SimplifyDemandedBitsForTargetNode(9753      Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO, Depth);9754}9755 9756bool LoongArchTargetLowering::shouldScalarizeBinop(SDValue VecOp) const {9757  unsigned Opc = VecOp.getOpcode();9758 9759  // Assume target opcodes can't be scalarized.9760  // TODO - do we have any exceptions?9761  if (Opc >= ISD::BUILTIN_OP_END || !isBinOp(Opc))9762    return false;9763 9764  // If the vector op is not supported, try to convert to scalar.9765  EVT VecVT = VecOp.getValueType();9766  if (!isOperationLegalOrCustomOrPromote(Opc, VecVT))9767    return true;9768 9769  // If the vector op is supported, but the scalar op is not, the transform may9770  // not be worthwhile.9771  EVT ScalarVT = VecVT.getScalarType();9772  return isOperationLegalOrCustomOrPromote(Opc, ScalarVT);9773}9774 9775bool LoongArchTargetLowering::isExtractSubvectorCheap(EVT ResVT, EVT SrcVT,9776                                                      unsigned Index) const {9777  if (!isOperationLegalOrCustom(ISD::EXTRACT_SUBVECTOR, ResVT))9778    return false;9779 9780  // Extract a 128-bit subvector from index 0 of a 256-bit vector is free.9781  return Index == 0;9782}9783 9784bool LoongArchTargetLowering::isExtractVecEltCheap(EVT VT,9785                                                   unsigned Index) const {9786  EVT EltVT = VT.getScalarType();9787 9788  // Extract a scalar FP value from index 0 of a vector is free.9789  return (EltVT == MVT::f32 || EltVT == MVT::f64) && Index == 0;9790}9791