10b57cec5SDimitry Andric //===- MipsSEISelLowering.cpp - MipsSE DAG Lowering Interface -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Subclass of MipsTargetLowering specialized for mips32/64.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "MipsSEISelLowering.h"
140b57cec5SDimitry Andric #include "MipsMachineFunction.h"
150b57cec5SDimitry Andric #include "MipsRegisterInfo.h"
160b57cec5SDimitry Andric #include "MipsSubtarget.h"
170b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
180b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
190b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
320b57cec5SDimitry Andric #include "llvm/CodeGen/ValueTypes.h"
33*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h"
340b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h"
350b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
36480093f4SDimitry Andric #include "llvm/IR/IntrinsicsMips.h"
370b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
380b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
390b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
400b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
410b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
420b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
4306c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
440b57cec5SDimitry Andric #include <algorithm>
450b57cec5SDimitry Andric #include <cassert>
460b57cec5SDimitry Andric #include <cstdint>
470b57cec5SDimitry Andric #include <iterator>
480b57cec5SDimitry Andric #include <utility>
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric using namespace llvm;
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric #define DEBUG_TYPE "mips-isel"
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric static cl::opt<bool>
550b57cec5SDimitry Andric UseMipsTailCalls("mips-tail-calls", cl::Hidden,
560b57cec5SDimitry Andric cl::desc("MIPS: permit tail calls."), cl::init(false));
570b57cec5SDimitry Andric
580b57cec5SDimitry Andric static cl::opt<bool> NoDPLoadStore("mno-ldc1-sdc1", cl::init(false),
590b57cec5SDimitry Andric cl::desc("Expand double precision loads and "
600b57cec5SDimitry Andric "stores to their single precision "
610b57cec5SDimitry Andric "counterparts"));
620b57cec5SDimitry Andric
MipsSETargetLowering(const MipsTargetMachine & TM,const MipsSubtarget & STI)630b57cec5SDimitry Andric MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM,
640b57cec5SDimitry Andric const MipsSubtarget &STI)
650b57cec5SDimitry Andric : MipsTargetLowering(TM, STI) {
660b57cec5SDimitry Andric // Set up the register classes
670b57cec5SDimitry Andric addRegisterClass(MVT::i32, &Mips::GPR32RegClass);
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric if (Subtarget.isGP64bit())
700b57cec5SDimitry Andric addRegisterClass(MVT::i64, &Mips::GPR64RegClass);
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric if (Subtarget.hasDSP() || Subtarget.hasMSA()) {
730b57cec5SDimitry Andric // Expand all truncating stores and extending loads.
748bcb0991SDimitry Andric for (MVT VT0 : MVT::fixedlen_vector_valuetypes()) {
758bcb0991SDimitry Andric for (MVT VT1 : MVT::fixedlen_vector_valuetypes()) {
760b57cec5SDimitry Andric setTruncStoreAction(VT0, VT1, Expand);
770b57cec5SDimitry Andric setLoadExtAction(ISD::SEXTLOAD, VT0, VT1, Expand);
780b57cec5SDimitry Andric setLoadExtAction(ISD::ZEXTLOAD, VT0, VT1, Expand);
790b57cec5SDimitry Andric setLoadExtAction(ISD::EXTLOAD, VT0, VT1, Expand);
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric
840b57cec5SDimitry Andric if (Subtarget.hasDSP()) {
850b57cec5SDimitry Andric MVT::SimpleValueType VecTys[2] = {MVT::v2i16, MVT::v4i8};
860b57cec5SDimitry Andric
8704eeddc0SDimitry Andric for (const auto &VecTy : VecTys) {
8804eeddc0SDimitry Andric addRegisterClass(VecTy, &Mips::DSPRRegClass);
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric // Expand all builtin opcodes.
910b57cec5SDimitry Andric for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
9204eeddc0SDimitry Andric setOperationAction(Opc, VecTy, Expand);
930b57cec5SDimitry Andric
9404eeddc0SDimitry Andric setOperationAction(ISD::ADD, VecTy, Legal);
9504eeddc0SDimitry Andric setOperationAction(ISD::SUB, VecTy, Legal);
9604eeddc0SDimitry Andric setOperationAction(ISD::LOAD, VecTy, Legal);
9704eeddc0SDimitry Andric setOperationAction(ISD::STORE, VecTy, Legal);
9804eeddc0SDimitry Andric setOperationAction(ISD::BITCAST, VecTy, Legal);
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric
10181ad6265SDimitry Andric setTargetDAGCombine(
10281ad6265SDimitry Andric {ISD::SHL, ISD::SRA, ISD::SRL, ISD::SETCC, ISD::VSELECT});
1030b57cec5SDimitry Andric
1040b57cec5SDimitry Andric if (Subtarget.hasMips32r2()) {
1050b57cec5SDimitry Andric setOperationAction(ISD::ADDC, MVT::i32, Legal);
1060b57cec5SDimitry Andric setOperationAction(ISD::ADDE, MVT::i32, Legal);
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric if (Subtarget.hasDSPR2())
1110b57cec5SDimitry Andric setOperationAction(ISD::MUL, MVT::v2i16, Legal);
1120b57cec5SDimitry Andric
1130b57cec5SDimitry Andric if (Subtarget.hasMSA()) {
1140b57cec5SDimitry Andric addMSAIntType(MVT::v16i8, &Mips::MSA128BRegClass);
1150b57cec5SDimitry Andric addMSAIntType(MVT::v8i16, &Mips::MSA128HRegClass);
1160b57cec5SDimitry Andric addMSAIntType(MVT::v4i32, &Mips::MSA128WRegClass);
1170b57cec5SDimitry Andric addMSAIntType(MVT::v2i64, &Mips::MSA128DRegClass);
1180b57cec5SDimitry Andric addMSAFloatType(MVT::v8f16, &Mips::MSA128HRegClass);
1190b57cec5SDimitry Andric addMSAFloatType(MVT::v4f32, &Mips::MSA128WRegClass);
1200b57cec5SDimitry Andric addMSAFloatType(MVT::v2f64, &Mips::MSA128DRegClass);
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andric // f16 is a storage-only type, always promote it to f32.
1230b57cec5SDimitry Andric addRegisterClass(MVT::f16, &Mips::MSA128HRegClass);
1240b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::f16, Promote);
1250b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::f16, Promote);
1260b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::f16, Promote);
1270b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::f16, Promote);
1280b57cec5SDimitry Andric setOperationAction(ISD::FADD, MVT::f16, Promote);
1290b57cec5SDimitry Andric setOperationAction(ISD::FSUB, MVT::f16, Promote);
1300b57cec5SDimitry Andric setOperationAction(ISD::FMUL, MVT::f16, Promote);
1310b57cec5SDimitry Andric setOperationAction(ISD::FDIV, MVT::f16, Promote);
1320b57cec5SDimitry Andric setOperationAction(ISD::FREM, MVT::f16, Promote);
1330b57cec5SDimitry Andric setOperationAction(ISD::FMA, MVT::f16, Promote);
1340b57cec5SDimitry Andric setOperationAction(ISD::FNEG, MVT::f16, Promote);
1350b57cec5SDimitry Andric setOperationAction(ISD::FABS, MVT::f16, Promote);
1360b57cec5SDimitry Andric setOperationAction(ISD::FCEIL, MVT::f16, Promote);
1370b57cec5SDimitry Andric setOperationAction(ISD::FCOPYSIGN, MVT::f16, Promote);
1380b57cec5SDimitry Andric setOperationAction(ISD::FCOS, MVT::f16, Promote);
1390b57cec5SDimitry Andric setOperationAction(ISD::FP_EXTEND, MVT::f16, Promote);
1400b57cec5SDimitry Andric setOperationAction(ISD::FFLOOR, MVT::f16, Promote);
1410b57cec5SDimitry Andric setOperationAction(ISD::FNEARBYINT, MVT::f16, Promote);
1420b57cec5SDimitry Andric setOperationAction(ISD::FPOW, MVT::f16, Promote);
1430b57cec5SDimitry Andric setOperationAction(ISD::FPOWI, MVT::f16, Promote);
1440b57cec5SDimitry Andric setOperationAction(ISD::FRINT, MVT::f16, Promote);
1450b57cec5SDimitry Andric setOperationAction(ISD::FSIN, MVT::f16, Promote);
1460b57cec5SDimitry Andric setOperationAction(ISD::FSINCOS, MVT::f16, Promote);
1470b57cec5SDimitry Andric setOperationAction(ISD::FSQRT, MVT::f16, Promote);
1480b57cec5SDimitry Andric setOperationAction(ISD::FEXP, MVT::f16, Promote);
1490b57cec5SDimitry Andric setOperationAction(ISD::FEXP2, MVT::f16, Promote);
1500b57cec5SDimitry Andric setOperationAction(ISD::FLOG, MVT::f16, Promote);
1510b57cec5SDimitry Andric setOperationAction(ISD::FLOG2, MVT::f16, Promote);
1520b57cec5SDimitry Andric setOperationAction(ISD::FLOG10, MVT::f16, Promote);
1530b57cec5SDimitry Andric setOperationAction(ISD::FROUND, MVT::f16, Promote);
1540b57cec5SDimitry Andric setOperationAction(ISD::FTRUNC, MVT::f16, Promote);
1550b57cec5SDimitry Andric setOperationAction(ISD::FMINNUM, MVT::f16, Promote);
1560b57cec5SDimitry Andric setOperationAction(ISD::FMAXNUM, MVT::f16, Promote);
1570b57cec5SDimitry Andric setOperationAction(ISD::FMINIMUM, MVT::f16, Promote);
1580b57cec5SDimitry Andric setOperationAction(ISD::FMAXIMUM, MVT::f16, Promote);
1590b57cec5SDimitry Andric
16081ad6265SDimitry Andric setTargetDAGCombine({ISD::AND, ISD::OR, ISD::SRA, ISD::VSELECT, ISD::XOR});
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric if (!Subtarget.useSoftFloat()) {
1640b57cec5SDimitry Andric addRegisterClass(MVT::f32, &Mips::FGR32RegClass);
1650b57cec5SDimitry Andric
1660b57cec5SDimitry Andric // When dealing with single precision only, use libcalls
1670b57cec5SDimitry Andric if (!Subtarget.isSingleFloat()) {
1680b57cec5SDimitry Andric if (Subtarget.isFP64bit())
1690b57cec5SDimitry Andric addRegisterClass(MVT::f64, &Mips::FGR64RegClass);
1700b57cec5SDimitry Andric else
1710b57cec5SDimitry Andric addRegisterClass(MVT::f64, &Mips::AFGR64RegClass);
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
1760b57cec5SDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
1770b57cec5SDimitry Andric setOperationAction(ISD::MULHS, MVT::i32, Custom);
1780b57cec5SDimitry Andric setOperationAction(ISD::MULHU, MVT::i32, Custom);
1790b57cec5SDimitry Andric
1800b57cec5SDimitry Andric if (Subtarget.hasCnMips())
1810b57cec5SDimitry Andric setOperationAction(ISD::MUL, MVT::i64, Legal);
1820b57cec5SDimitry Andric else if (Subtarget.isGP64bit())
1830b57cec5SDimitry Andric setOperationAction(ISD::MUL, MVT::i64, Custom);
1840b57cec5SDimitry Andric
1850b57cec5SDimitry Andric if (Subtarget.isGP64bit()) {
1860b57cec5SDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom);
1870b57cec5SDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom);
1880b57cec5SDimitry Andric setOperationAction(ISD::MULHS, MVT::i64, Custom);
1890b57cec5SDimitry Andric setOperationAction(ISD::MULHU, MVT::i64, Custom);
1900b57cec5SDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i64, Custom);
1910b57cec5SDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i64, Custom);
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric
1940b57cec5SDimitry Andric setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom);
1950b57cec5SDimitry Andric setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom);
1960b57cec5SDimitry Andric
1970b57cec5SDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
1980b57cec5SDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
1990b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
200*0fca6ea1SDimitry Andric if (Subtarget.hasMips32r6()) {
201*0fca6ea1SDimitry Andric setOperationAction(ISD::LOAD, MVT::i32, Legal);
202*0fca6ea1SDimitry Andric setOperationAction(ISD::STORE, MVT::i32, Legal);
203*0fca6ea1SDimitry Andric } else {
2040b57cec5SDimitry Andric setOperationAction(ISD::LOAD, MVT::i32, Custom);
2050b57cec5SDimitry Andric setOperationAction(ISD::STORE, MVT::i32, Custom);
206*0fca6ea1SDimitry Andric }
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andric setTargetDAGCombine(ISD::MUL);
2090b57cec5SDimitry Andric
2100b57cec5SDimitry Andric setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
2110b57cec5SDimitry Andric setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);
2120b57cec5SDimitry Andric setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
2130b57cec5SDimitry Andric
2140b57cec5SDimitry Andric if (Subtarget.hasMips32r2() && !Subtarget.useSoftFloat() &&
2150b57cec5SDimitry Andric !Subtarget.hasMips64()) {
2160b57cec5SDimitry Andric setOperationAction(ISD::BITCAST, MVT::i64, Custom);
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric
2190b57cec5SDimitry Andric if (NoDPLoadStore) {
2200b57cec5SDimitry Andric setOperationAction(ISD::LOAD, MVT::f64, Custom);
2210b57cec5SDimitry Andric setOperationAction(ISD::STORE, MVT::f64, Custom);
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric if (Subtarget.hasMips32r6()) {
2250b57cec5SDimitry Andric // MIPS32r6 replaces the accumulator-based multiplies with a three register
2260b57cec5SDimitry Andric // instruction
2270b57cec5SDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
2280b57cec5SDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
2290b57cec5SDimitry Andric setOperationAction(ISD::MUL, MVT::i32, Legal);
2300b57cec5SDimitry Andric setOperationAction(ISD::MULHS, MVT::i32, Legal);
2310b57cec5SDimitry Andric setOperationAction(ISD::MULHU, MVT::i32, Legal);
2320b57cec5SDimitry Andric
2330b57cec5SDimitry Andric // MIPS32r6 replaces the accumulator-based division/remainder with separate
2340b57cec5SDimitry Andric // three register division and remainder instructions.
2350b57cec5SDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
2360b57cec5SDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
2370b57cec5SDimitry Andric setOperationAction(ISD::SDIV, MVT::i32, Legal);
2380b57cec5SDimitry Andric setOperationAction(ISD::UDIV, MVT::i32, Legal);
2390b57cec5SDimitry Andric setOperationAction(ISD::SREM, MVT::i32, Legal);
2400b57cec5SDimitry Andric setOperationAction(ISD::UREM, MVT::i32, Legal);
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric // MIPS32r6 replaces conditional moves with an equivalent that removes the
2430b57cec5SDimitry Andric // need for three GPR read ports.
2440b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::i32, Legal);
2450b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::i32, Legal);
2460b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i32, Expand);
2470b57cec5SDimitry Andric
2480b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::f32, Legal);
2490b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::f32, Legal);
2500b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric assert(Subtarget.isFP64bit() && "FR=1 is required for MIPS32r6");
2530b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::f64, Legal);
2540b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::f64, Custom);
2550b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
2560b57cec5SDimitry Andric
2570b57cec5SDimitry Andric setOperationAction(ISD::BRCOND, MVT::Other, Legal);
2580b57cec5SDimitry Andric
2590b57cec5SDimitry Andric // Floating point > and >= are supported via < and <=
2600b57cec5SDimitry Andric setCondCodeAction(ISD::SETOGE, MVT::f32, Expand);
2610b57cec5SDimitry Andric setCondCodeAction(ISD::SETOGT, MVT::f32, Expand);
2620b57cec5SDimitry Andric setCondCodeAction(ISD::SETUGE, MVT::f32, Expand);
2630b57cec5SDimitry Andric setCondCodeAction(ISD::SETUGT, MVT::f32, Expand);
2640b57cec5SDimitry Andric
2650b57cec5SDimitry Andric setCondCodeAction(ISD::SETOGE, MVT::f64, Expand);
2660b57cec5SDimitry Andric setCondCodeAction(ISD::SETOGT, MVT::f64, Expand);
2670b57cec5SDimitry Andric setCondCodeAction(ISD::SETUGE, MVT::f64, Expand);
2680b57cec5SDimitry Andric setCondCodeAction(ISD::SETUGT, MVT::f64, Expand);
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric
2710b57cec5SDimitry Andric if (Subtarget.hasMips64r6()) {
2720b57cec5SDimitry Andric // MIPS64r6 replaces the accumulator-based multiplies with a three register
2730b57cec5SDimitry Andric // instruction
2740b57cec5SDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
2750b57cec5SDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
2760b57cec5SDimitry Andric setOperationAction(ISD::MUL, MVT::i64, Legal);
2770b57cec5SDimitry Andric setOperationAction(ISD::MULHS, MVT::i64, Legal);
2780b57cec5SDimitry Andric setOperationAction(ISD::MULHU, MVT::i64, Legal);
2790b57cec5SDimitry Andric
2800b57cec5SDimitry Andric // MIPS32r6 replaces the accumulator-based division/remainder with separate
2810b57cec5SDimitry Andric // three register division and remainder instructions.
2820b57cec5SDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i64, Expand);
2830b57cec5SDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i64, Expand);
2840b57cec5SDimitry Andric setOperationAction(ISD::SDIV, MVT::i64, Legal);
2850b57cec5SDimitry Andric setOperationAction(ISD::UDIV, MVT::i64, Legal);
2860b57cec5SDimitry Andric setOperationAction(ISD::SREM, MVT::i64, Legal);
2870b57cec5SDimitry Andric setOperationAction(ISD::UREM, MVT::i64, Legal);
2880b57cec5SDimitry Andric
2890b57cec5SDimitry Andric // MIPS64r6 replaces conditional moves with an equivalent that removes the
2900b57cec5SDimitry Andric // need for three GPR read ports.
2910b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::i64, Legal);
2920b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::i64, Legal);
2930b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i64, Expand);
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric
2960b57cec5SDimitry Andric computeRegisterProperties(Subtarget.getRegisterInfo());
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric
2990b57cec5SDimitry Andric const MipsTargetLowering *
createMipsSETargetLowering(const MipsTargetMachine & TM,const MipsSubtarget & STI)3000b57cec5SDimitry Andric llvm::createMipsSETargetLowering(const MipsTargetMachine &TM,
3010b57cec5SDimitry Andric const MipsSubtarget &STI) {
3020b57cec5SDimitry Andric return new MipsSETargetLowering(TM, STI);
3030b57cec5SDimitry Andric }
3040b57cec5SDimitry Andric
3050b57cec5SDimitry Andric const TargetRegisterClass *
getRepRegClassFor(MVT VT) const3060b57cec5SDimitry Andric MipsSETargetLowering::getRepRegClassFor(MVT VT) const {
3070b57cec5SDimitry Andric if (VT == MVT::Untyped)
3080b57cec5SDimitry Andric return Subtarget.hasDSP() ? &Mips::ACC64DSPRegClass : &Mips::ACC64RegClass;
3090b57cec5SDimitry Andric
3100b57cec5SDimitry Andric return TargetLowering::getRepRegClassFor(VT);
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric
3130b57cec5SDimitry Andric // Enable MSA support for the given integer type and Register class.
3140b57cec5SDimitry Andric void MipsSETargetLowering::
addMSAIntType(MVT::SimpleValueType Ty,const TargetRegisterClass * RC)3150b57cec5SDimitry Andric addMSAIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) {
3160b57cec5SDimitry Andric addRegisterClass(Ty, RC);
3170b57cec5SDimitry Andric
3180b57cec5SDimitry Andric // Expand all builtin opcodes.
3190b57cec5SDimitry Andric for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
3200b57cec5SDimitry Andric setOperationAction(Opc, Ty, Expand);
3210b57cec5SDimitry Andric
3220b57cec5SDimitry Andric setOperationAction(ISD::BITCAST, Ty, Legal);
3230b57cec5SDimitry Andric setOperationAction(ISD::LOAD, Ty, Legal);
3240b57cec5SDimitry Andric setOperationAction(ISD::STORE, Ty, Legal);
3250b57cec5SDimitry Andric setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Custom);
3260b57cec5SDimitry Andric setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Legal);
3270b57cec5SDimitry Andric setOperationAction(ISD::BUILD_VECTOR, Ty, Custom);
3288bcb0991SDimitry Andric setOperationAction(ISD::UNDEF, Ty, Legal);
3290b57cec5SDimitry Andric
3300b57cec5SDimitry Andric setOperationAction(ISD::ADD, Ty, Legal);
3310b57cec5SDimitry Andric setOperationAction(ISD::AND, Ty, Legal);
3320b57cec5SDimitry Andric setOperationAction(ISD::CTLZ, Ty, Legal);
3330b57cec5SDimitry Andric setOperationAction(ISD::CTPOP, Ty, Legal);
3340b57cec5SDimitry Andric setOperationAction(ISD::MUL, Ty, Legal);
3350b57cec5SDimitry Andric setOperationAction(ISD::OR, Ty, Legal);
3360b57cec5SDimitry Andric setOperationAction(ISD::SDIV, Ty, Legal);
3370b57cec5SDimitry Andric setOperationAction(ISD::SREM, Ty, Legal);
3380b57cec5SDimitry Andric setOperationAction(ISD::SHL, Ty, Legal);
3390b57cec5SDimitry Andric setOperationAction(ISD::SRA, Ty, Legal);
3400b57cec5SDimitry Andric setOperationAction(ISD::SRL, Ty, Legal);
3410b57cec5SDimitry Andric setOperationAction(ISD::SUB, Ty, Legal);
3420b57cec5SDimitry Andric setOperationAction(ISD::SMAX, Ty, Legal);
3430b57cec5SDimitry Andric setOperationAction(ISD::SMIN, Ty, Legal);
3440b57cec5SDimitry Andric setOperationAction(ISD::UDIV, Ty, Legal);
3450b57cec5SDimitry Andric setOperationAction(ISD::UREM, Ty, Legal);
3460b57cec5SDimitry Andric setOperationAction(ISD::UMAX, Ty, Legal);
3470b57cec5SDimitry Andric setOperationAction(ISD::UMIN, Ty, Legal);
3480b57cec5SDimitry Andric setOperationAction(ISD::VECTOR_SHUFFLE, Ty, Custom);
3490b57cec5SDimitry Andric setOperationAction(ISD::VSELECT, Ty, Legal);
3500b57cec5SDimitry Andric setOperationAction(ISD::XOR, Ty, Legal);
3510b57cec5SDimitry Andric
3520b57cec5SDimitry Andric if (Ty == MVT::v4i32 || Ty == MVT::v2i64) {
3530b57cec5SDimitry Andric setOperationAction(ISD::FP_TO_SINT, Ty, Legal);
3540b57cec5SDimitry Andric setOperationAction(ISD::FP_TO_UINT, Ty, Legal);
3550b57cec5SDimitry Andric setOperationAction(ISD::SINT_TO_FP, Ty, Legal);
3560b57cec5SDimitry Andric setOperationAction(ISD::UINT_TO_FP, Ty, Legal);
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric
3590b57cec5SDimitry Andric setOperationAction(ISD::SETCC, Ty, Legal);
3600b57cec5SDimitry Andric setCondCodeAction(ISD::SETNE, Ty, Expand);
3610b57cec5SDimitry Andric setCondCodeAction(ISD::SETGE, Ty, Expand);
3620b57cec5SDimitry Andric setCondCodeAction(ISD::SETGT, Ty, Expand);
3630b57cec5SDimitry Andric setCondCodeAction(ISD::SETUGE, Ty, Expand);
3640b57cec5SDimitry Andric setCondCodeAction(ISD::SETUGT, Ty, Expand);
3650b57cec5SDimitry Andric }
3660b57cec5SDimitry Andric
3670b57cec5SDimitry Andric // Enable MSA support for the given floating-point type and Register class.
3680b57cec5SDimitry Andric void MipsSETargetLowering::
addMSAFloatType(MVT::SimpleValueType Ty,const TargetRegisterClass * RC)3690b57cec5SDimitry Andric addMSAFloatType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) {
3700b57cec5SDimitry Andric addRegisterClass(Ty, RC);
3710b57cec5SDimitry Andric
3720b57cec5SDimitry Andric // Expand all builtin opcodes.
3730b57cec5SDimitry Andric for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
3740b57cec5SDimitry Andric setOperationAction(Opc, Ty, Expand);
3750b57cec5SDimitry Andric
3760b57cec5SDimitry Andric setOperationAction(ISD::LOAD, Ty, Legal);
3770b57cec5SDimitry Andric setOperationAction(ISD::STORE, Ty, Legal);
3780b57cec5SDimitry Andric setOperationAction(ISD::BITCAST, Ty, Legal);
3790b57cec5SDimitry Andric setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Legal);
3800b57cec5SDimitry Andric setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Legal);
3810b57cec5SDimitry Andric setOperationAction(ISD::BUILD_VECTOR, Ty, Custom);
3820b57cec5SDimitry Andric
3830b57cec5SDimitry Andric if (Ty != MVT::v8f16) {
3840b57cec5SDimitry Andric setOperationAction(ISD::FABS, Ty, Legal);
3850b57cec5SDimitry Andric setOperationAction(ISD::FADD, Ty, Legal);
3860b57cec5SDimitry Andric setOperationAction(ISD::FDIV, Ty, Legal);
3870b57cec5SDimitry Andric setOperationAction(ISD::FEXP2, Ty, Legal);
3880b57cec5SDimitry Andric setOperationAction(ISD::FLOG2, Ty, Legal);
3890b57cec5SDimitry Andric setOperationAction(ISD::FMA, Ty, Legal);
3900b57cec5SDimitry Andric setOperationAction(ISD::FMUL, Ty, Legal);
3910b57cec5SDimitry Andric setOperationAction(ISD::FRINT, Ty, Legal);
3920b57cec5SDimitry Andric setOperationAction(ISD::FSQRT, Ty, Legal);
3930b57cec5SDimitry Andric setOperationAction(ISD::FSUB, Ty, Legal);
3940b57cec5SDimitry Andric setOperationAction(ISD::VSELECT, Ty, Legal);
3950b57cec5SDimitry Andric
3960b57cec5SDimitry Andric setOperationAction(ISD::SETCC, Ty, Legal);
3970b57cec5SDimitry Andric setCondCodeAction(ISD::SETOGE, Ty, Expand);
3980b57cec5SDimitry Andric setCondCodeAction(ISD::SETOGT, Ty, Expand);
3990b57cec5SDimitry Andric setCondCodeAction(ISD::SETUGE, Ty, Expand);
4000b57cec5SDimitry Andric setCondCodeAction(ISD::SETUGT, Ty, Expand);
4010b57cec5SDimitry Andric setCondCodeAction(ISD::SETGE, Ty, Expand);
4020b57cec5SDimitry Andric setCondCodeAction(ISD::SETGT, Ty, Expand);
4030b57cec5SDimitry Andric }
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric
lowerSELECT(SDValue Op,SelectionDAG & DAG) const4060b57cec5SDimitry Andric SDValue MipsSETargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
4070b57cec5SDimitry Andric if(!Subtarget.hasMips32r6())
4080b57cec5SDimitry Andric return MipsTargetLowering::LowerOperation(Op, DAG);
4090b57cec5SDimitry Andric
4100b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
4110b57cec5SDimitry Andric SDLoc DL(Op);
4120b57cec5SDimitry Andric
4130b57cec5SDimitry Andric // Although MTC1_D64 takes an i32 and writes an f64, the upper 32 bits of the
4140b57cec5SDimitry Andric // floating point register are undefined. Not really an issue as sel.d, which
4150b57cec5SDimitry Andric // is produced from an FSELECT node, only looks at bit 0.
4160b57cec5SDimitry Andric SDValue Tmp = DAG.getNode(MipsISD::MTC1_D64, DL, MVT::f64, Op->getOperand(0));
4170b57cec5SDimitry Andric return DAG.getNode(MipsISD::FSELECT, DL, ResTy, Tmp, Op->getOperand(1),
4180b57cec5SDimitry Andric Op->getOperand(2));
4190b57cec5SDimitry Andric }
4200b57cec5SDimitry Andric
allowsMisalignedMemoryAccesses(EVT VT,unsigned,Align,MachineMemOperand::Flags,unsigned * Fast) const4210b57cec5SDimitry Andric bool MipsSETargetLowering::allowsMisalignedMemoryAccesses(
422bdd1243dSDimitry Andric EVT VT, unsigned, Align, MachineMemOperand::Flags, unsigned *Fast) const {
4230b57cec5SDimitry Andric MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy;
4240b57cec5SDimitry Andric
4250b57cec5SDimitry Andric if (Subtarget.systemSupportsUnalignedAccess()) {
4260b57cec5SDimitry Andric // MIPS32r6/MIPS64r6 is required to support unaligned access. It's
4270b57cec5SDimitry Andric // implementation defined whether this is handled by hardware, software, or
4280b57cec5SDimitry Andric // a hybrid of the two but it's expected that most implementations will
4290b57cec5SDimitry Andric // handle the majority of cases in hardware.
4300b57cec5SDimitry Andric if (Fast)
431bdd1243dSDimitry Andric *Fast = 1;
4320b57cec5SDimitry Andric return true;
433*0fca6ea1SDimitry Andric } else if (Subtarget.hasMips32r6()) {
434*0fca6ea1SDimitry Andric return false;
4350b57cec5SDimitry Andric }
4360b57cec5SDimitry Andric
4370b57cec5SDimitry Andric switch (SVT) {
4380b57cec5SDimitry Andric case MVT::i64:
4390b57cec5SDimitry Andric case MVT::i32:
4400b57cec5SDimitry Andric if (Fast)
441bdd1243dSDimitry Andric *Fast = 1;
4420b57cec5SDimitry Andric return true;
4430b57cec5SDimitry Andric default:
4440b57cec5SDimitry Andric return false;
4450b57cec5SDimitry Andric }
4460b57cec5SDimitry Andric }
4470b57cec5SDimitry Andric
LowerOperation(SDValue Op,SelectionDAG & DAG) const4480b57cec5SDimitry Andric SDValue MipsSETargetLowering::LowerOperation(SDValue Op,
4490b57cec5SDimitry Andric SelectionDAG &DAG) const {
4500b57cec5SDimitry Andric switch(Op.getOpcode()) {
4510b57cec5SDimitry Andric case ISD::LOAD: return lowerLOAD(Op, DAG);
4520b57cec5SDimitry Andric case ISD::STORE: return lowerSTORE(Op, DAG);
4530b57cec5SDimitry Andric case ISD::SMUL_LOHI: return lowerMulDiv(Op, MipsISD::Mult, true, true, DAG);
4540b57cec5SDimitry Andric case ISD::UMUL_LOHI: return lowerMulDiv(Op, MipsISD::Multu, true, true, DAG);
4550b57cec5SDimitry Andric case ISD::MULHS: return lowerMulDiv(Op, MipsISD::Mult, false, true, DAG);
4560b57cec5SDimitry Andric case ISD::MULHU: return lowerMulDiv(Op, MipsISD::Multu, false, true, DAG);
4570b57cec5SDimitry Andric case ISD::MUL: return lowerMulDiv(Op, MipsISD::Mult, true, false, DAG);
4580b57cec5SDimitry Andric case ISD::SDIVREM: return lowerMulDiv(Op, MipsISD::DivRem, true, true, DAG);
4590b57cec5SDimitry Andric case ISD::UDIVREM: return lowerMulDiv(Op, MipsISD::DivRemU, true, true,
4600b57cec5SDimitry Andric DAG);
4610b57cec5SDimitry Andric case ISD::INTRINSIC_WO_CHAIN: return lowerINTRINSIC_WO_CHAIN(Op, DAG);
4620b57cec5SDimitry Andric case ISD::INTRINSIC_W_CHAIN: return lowerINTRINSIC_W_CHAIN(Op, DAG);
4630b57cec5SDimitry Andric case ISD::INTRINSIC_VOID: return lowerINTRINSIC_VOID(Op, DAG);
4640b57cec5SDimitry Andric case ISD::EXTRACT_VECTOR_ELT: return lowerEXTRACT_VECTOR_ELT(Op, DAG);
4650b57cec5SDimitry Andric case ISD::BUILD_VECTOR: return lowerBUILD_VECTOR(Op, DAG);
4660b57cec5SDimitry Andric case ISD::VECTOR_SHUFFLE: return lowerVECTOR_SHUFFLE(Op, DAG);
4670b57cec5SDimitry Andric case ISD::SELECT: return lowerSELECT(Op, DAG);
4680b57cec5SDimitry Andric case ISD::BITCAST: return lowerBITCAST(Op, DAG);
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric
4710b57cec5SDimitry Andric return MipsTargetLowering::LowerOperation(Op, DAG);
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric
4740b57cec5SDimitry Andric // Fold zero extensions into MipsISD::VEXTRACT_[SZ]EXT_ELT
4750b57cec5SDimitry Andric //
4760b57cec5SDimitry Andric // Performs the following transformations:
4770b57cec5SDimitry Andric // - Changes MipsISD::VEXTRACT_[SZ]EXT_ELT to zero extension if its
4780b57cec5SDimitry Andric // sign/zero-extension is completely overwritten by the new one performed by
4790b57cec5SDimitry Andric // the ISD::AND.
4800b57cec5SDimitry Andric // - Removes redundant zero extensions performed by an ISD::AND.
performANDCombine(SDNode * N,SelectionDAG & DAG,TargetLowering::DAGCombinerInfo & DCI,const MipsSubtarget & Subtarget)4810b57cec5SDimitry Andric static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
4820b57cec5SDimitry Andric TargetLowering::DAGCombinerInfo &DCI,
4830b57cec5SDimitry Andric const MipsSubtarget &Subtarget) {
4840b57cec5SDimitry Andric if (!Subtarget.hasMSA())
4850b57cec5SDimitry Andric return SDValue();
4860b57cec5SDimitry Andric
4870b57cec5SDimitry Andric SDValue Op0 = N->getOperand(0);
4880b57cec5SDimitry Andric SDValue Op1 = N->getOperand(1);
4890b57cec5SDimitry Andric unsigned Op0Opcode = Op0->getOpcode();
4900b57cec5SDimitry Andric
4910b57cec5SDimitry Andric // (and (MipsVExtract[SZ]Ext $a, $b, $c), imm:$d)
4920b57cec5SDimitry Andric // where $d + 1 == 2^n and n == 32
4930b57cec5SDimitry Andric // or $d + 1 == 2^n and n <= 32 and ZExt
4940b57cec5SDimitry Andric // -> (MipsVExtractZExt $a, $b, $c)
4950b57cec5SDimitry Andric if (Op0Opcode == MipsISD::VEXTRACT_SEXT_ELT ||
4960b57cec5SDimitry Andric Op0Opcode == MipsISD::VEXTRACT_ZEXT_ELT) {
4970b57cec5SDimitry Andric ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(Op1);
4980b57cec5SDimitry Andric
4990b57cec5SDimitry Andric if (!Mask)
5000b57cec5SDimitry Andric return SDValue();
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andric int32_t Log2IfPositive = (Mask->getAPIntValue() + 1).exactLogBase2();
5030b57cec5SDimitry Andric
5040b57cec5SDimitry Andric if (Log2IfPositive <= 0)
5050b57cec5SDimitry Andric return SDValue(); // Mask+1 is not a power of 2
5060b57cec5SDimitry Andric
5070b57cec5SDimitry Andric SDValue Op0Op2 = Op0->getOperand(2);
5080b57cec5SDimitry Andric EVT ExtendTy = cast<VTSDNode>(Op0Op2)->getVT();
5090b57cec5SDimitry Andric unsigned ExtendTySize = ExtendTy.getSizeInBits();
5100b57cec5SDimitry Andric unsigned Log2 = Log2IfPositive;
5110b57cec5SDimitry Andric
5120b57cec5SDimitry Andric if ((Op0Opcode == MipsISD::VEXTRACT_ZEXT_ELT && Log2 >= ExtendTySize) ||
5130b57cec5SDimitry Andric Log2 == ExtendTySize) {
5140b57cec5SDimitry Andric SDValue Ops[] = { Op0->getOperand(0), Op0->getOperand(1), Op0Op2 };
5150b57cec5SDimitry Andric return DAG.getNode(MipsISD::VEXTRACT_ZEXT_ELT, SDLoc(Op0),
5160b57cec5SDimitry Andric Op0->getVTList(),
517bdd1243dSDimitry Andric ArrayRef(Ops, Op0->getNumOperands()));
5180b57cec5SDimitry Andric }
5190b57cec5SDimitry Andric }
5200b57cec5SDimitry Andric
5210b57cec5SDimitry Andric return SDValue();
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric
5240b57cec5SDimitry Andric // Determine if the specified node is a constant vector splat.
5250b57cec5SDimitry Andric //
5260b57cec5SDimitry Andric // Returns true and sets Imm if:
5270b57cec5SDimitry Andric // * N is a ISD::BUILD_VECTOR representing a constant splat
5280b57cec5SDimitry Andric //
5290b57cec5SDimitry Andric // This function is quite similar to MipsSEDAGToDAGISel::selectVSplat. The
5300b57cec5SDimitry Andric // differences are that it assumes the MSA has already been checked and the
5310b57cec5SDimitry Andric // arbitrary requirement for a maximum of 32-bit integers isn't applied (and
5320b57cec5SDimitry Andric // must not be in order for binsri.d to be selectable).
isVSplat(SDValue N,APInt & Imm,bool IsLittleEndian)5330b57cec5SDimitry Andric static bool isVSplat(SDValue N, APInt &Imm, bool IsLittleEndian) {
5340b57cec5SDimitry Andric BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N.getNode());
5350b57cec5SDimitry Andric
5360b57cec5SDimitry Andric if (!Node)
5370b57cec5SDimitry Andric return false;
5380b57cec5SDimitry Andric
5390b57cec5SDimitry Andric APInt SplatValue, SplatUndef;
5400b57cec5SDimitry Andric unsigned SplatBitSize;
5410b57cec5SDimitry Andric bool HasAnyUndefs;
5420b57cec5SDimitry Andric
5430b57cec5SDimitry Andric if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
5440b57cec5SDimitry Andric 8, !IsLittleEndian))
5450b57cec5SDimitry Andric return false;
5460b57cec5SDimitry Andric
5470b57cec5SDimitry Andric Imm = SplatValue;
5480b57cec5SDimitry Andric
5490b57cec5SDimitry Andric return true;
5500b57cec5SDimitry Andric }
5510b57cec5SDimitry Andric
5520b57cec5SDimitry Andric // Test whether the given node is an all-ones build_vector.
isVectorAllOnes(SDValue N)5530b57cec5SDimitry Andric static bool isVectorAllOnes(SDValue N) {
5540b57cec5SDimitry Andric // Look through bitcasts. Endianness doesn't matter because we are looking
5550b57cec5SDimitry Andric // for an all-ones value.
5560b57cec5SDimitry Andric if (N->getOpcode() == ISD::BITCAST)
5570b57cec5SDimitry Andric N = N->getOperand(0);
5580b57cec5SDimitry Andric
5590b57cec5SDimitry Andric BuildVectorSDNode *BVN = dyn_cast<BuildVectorSDNode>(N);
5600b57cec5SDimitry Andric
5610b57cec5SDimitry Andric if (!BVN)
5620b57cec5SDimitry Andric return false;
5630b57cec5SDimitry Andric
5640b57cec5SDimitry Andric APInt SplatValue, SplatUndef;
5650b57cec5SDimitry Andric unsigned SplatBitSize;
5660b57cec5SDimitry Andric bool HasAnyUndefs;
5670b57cec5SDimitry Andric
5680b57cec5SDimitry Andric // Endianness doesn't matter in this context because we are looking for
5690b57cec5SDimitry Andric // an all-ones value.
5700b57cec5SDimitry Andric if (BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs))
571349cc55cSDimitry Andric return SplatValue.isAllOnes();
5720b57cec5SDimitry Andric
5730b57cec5SDimitry Andric return false;
5740b57cec5SDimitry Andric }
5750b57cec5SDimitry Andric
5760b57cec5SDimitry Andric // Test whether N is the bitwise inverse of OfNode.
isBitwiseInverse(SDValue N,SDValue OfNode)5770b57cec5SDimitry Andric static bool isBitwiseInverse(SDValue N, SDValue OfNode) {
5780b57cec5SDimitry Andric if (N->getOpcode() != ISD::XOR)
5790b57cec5SDimitry Andric return false;
5800b57cec5SDimitry Andric
5810b57cec5SDimitry Andric if (isVectorAllOnes(N->getOperand(0)))
5820b57cec5SDimitry Andric return N->getOperand(1) == OfNode;
5830b57cec5SDimitry Andric
5840b57cec5SDimitry Andric if (isVectorAllOnes(N->getOperand(1)))
5850b57cec5SDimitry Andric return N->getOperand(0) == OfNode;
5860b57cec5SDimitry Andric
5870b57cec5SDimitry Andric return false;
5880b57cec5SDimitry Andric }
5890b57cec5SDimitry Andric
5900b57cec5SDimitry Andric // Perform combines where ISD::OR is the root node.
5910b57cec5SDimitry Andric //
5920b57cec5SDimitry Andric // Performs the following transformations:
5930b57cec5SDimitry Andric // - (or (and $a, $mask), (and $b, $inv_mask)) => (vselect $mask, $a, $b)
5940b57cec5SDimitry Andric // where $inv_mask is the bitwise inverse of $mask and the 'or' has a 128-bit
5950b57cec5SDimitry Andric // vector type.
performORCombine(SDNode * N,SelectionDAG & DAG,TargetLowering::DAGCombinerInfo & DCI,const MipsSubtarget & Subtarget)5960b57cec5SDimitry Andric static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
5970b57cec5SDimitry Andric TargetLowering::DAGCombinerInfo &DCI,
5980b57cec5SDimitry Andric const MipsSubtarget &Subtarget) {
5990b57cec5SDimitry Andric if (!Subtarget.hasMSA())
6000b57cec5SDimitry Andric return SDValue();
6010b57cec5SDimitry Andric
6020b57cec5SDimitry Andric EVT Ty = N->getValueType(0);
6030b57cec5SDimitry Andric
6040b57cec5SDimitry Andric if (!Ty.is128BitVector())
6050b57cec5SDimitry Andric return SDValue();
6060b57cec5SDimitry Andric
6070b57cec5SDimitry Andric SDValue Op0 = N->getOperand(0);
6080b57cec5SDimitry Andric SDValue Op1 = N->getOperand(1);
6090b57cec5SDimitry Andric
6100b57cec5SDimitry Andric if (Op0->getOpcode() == ISD::AND && Op1->getOpcode() == ISD::AND) {
6110b57cec5SDimitry Andric SDValue Op0Op0 = Op0->getOperand(0);
6120b57cec5SDimitry Andric SDValue Op0Op1 = Op0->getOperand(1);
6130b57cec5SDimitry Andric SDValue Op1Op0 = Op1->getOperand(0);
6140b57cec5SDimitry Andric SDValue Op1Op1 = Op1->getOperand(1);
6150b57cec5SDimitry Andric bool IsLittleEndian = !Subtarget.isLittle();
6160b57cec5SDimitry Andric
6170b57cec5SDimitry Andric SDValue IfSet, IfClr, Cond;
6180b57cec5SDimitry Andric bool IsConstantMask = false;
6190b57cec5SDimitry Andric APInt Mask, InvMask;
6200b57cec5SDimitry Andric
6210b57cec5SDimitry Andric // If Op0Op0 is an appropriate mask, try to find it's inverse in either
6220b57cec5SDimitry Andric // Op1Op0, or Op1Op1. Keep track of the Cond, IfSet, and IfClr nodes, while
6230b57cec5SDimitry Andric // looking.
6240b57cec5SDimitry Andric // IfClr will be set if we find a valid match.
6250b57cec5SDimitry Andric if (isVSplat(Op0Op0, Mask, IsLittleEndian)) {
6260b57cec5SDimitry Andric Cond = Op0Op0;
6270b57cec5SDimitry Andric IfSet = Op0Op1;
6280b57cec5SDimitry Andric
6290b57cec5SDimitry Andric if (isVSplat(Op1Op0, InvMask, IsLittleEndian) &&
6300b57cec5SDimitry Andric Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask)
6310b57cec5SDimitry Andric IfClr = Op1Op1;
6320b57cec5SDimitry Andric else if (isVSplat(Op1Op1, InvMask, IsLittleEndian) &&
6330b57cec5SDimitry Andric Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask)
6340b57cec5SDimitry Andric IfClr = Op1Op0;
6350b57cec5SDimitry Andric
6360b57cec5SDimitry Andric IsConstantMask = true;
6370b57cec5SDimitry Andric }
6380b57cec5SDimitry Andric
6390b57cec5SDimitry Andric // If IfClr is not yet set, and Op0Op1 is an appropriate mask, try the same
6400b57cec5SDimitry Andric // thing again using this mask.
6410b57cec5SDimitry Andric // IfClr will be set if we find a valid match.
6420b57cec5SDimitry Andric if (!IfClr.getNode() && isVSplat(Op0Op1, Mask, IsLittleEndian)) {
6430b57cec5SDimitry Andric Cond = Op0Op1;
6440b57cec5SDimitry Andric IfSet = Op0Op0;
6450b57cec5SDimitry Andric
6460b57cec5SDimitry Andric if (isVSplat(Op1Op0, InvMask, IsLittleEndian) &&
6470b57cec5SDimitry Andric Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask)
6480b57cec5SDimitry Andric IfClr = Op1Op1;
6490b57cec5SDimitry Andric else if (isVSplat(Op1Op1, InvMask, IsLittleEndian) &&
6500b57cec5SDimitry Andric Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask)
6510b57cec5SDimitry Andric IfClr = Op1Op0;
6520b57cec5SDimitry Andric
6530b57cec5SDimitry Andric IsConstantMask = true;
6540b57cec5SDimitry Andric }
6550b57cec5SDimitry Andric
6560b57cec5SDimitry Andric // If IfClr is not yet set, try looking for a non-constant match.
6570b57cec5SDimitry Andric // IfClr will be set if we find a valid match amongst the eight
6580b57cec5SDimitry Andric // possibilities.
6590b57cec5SDimitry Andric if (!IfClr.getNode()) {
6600b57cec5SDimitry Andric if (isBitwiseInverse(Op0Op0, Op1Op0)) {
6610b57cec5SDimitry Andric Cond = Op1Op0;
6620b57cec5SDimitry Andric IfSet = Op1Op1;
6630b57cec5SDimitry Andric IfClr = Op0Op1;
6640b57cec5SDimitry Andric } else if (isBitwiseInverse(Op0Op1, Op1Op0)) {
6650b57cec5SDimitry Andric Cond = Op1Op0;
6660b57cec5SDimitry Andric IfSet = Op1Op1;
6670b57cec5SDimitry Andric IfClr = Op0Op0;
6680b57cec5SDimitry Andric } else if (isBitwiseInverse(Op0Op0, Op1Op1)) {
6690b57cec5SDimitry Andric Cond = Op1Op1;
6700b57cec5SDimitry Andric IfSet = Op1Op0;
6710b57cec5SDimitry Andric IfClr = Op0Op1;
6720b57cec5SDimitry Andric } else if (isBitwiseInverse(Op0Op1, Op1Op1)) {
6730b57cec5SDimitry Andric Cond = Op1Op1;
6740b57cec5SDimitry Andric IfSet = Op1Op0;
6750b57cec5SDimitry Andric IfClr = Op0Op0;
6760b57cec5SDimitry Andric } else if (isBitwiseInverse(Op1Op0, Op0Op0)) {
6770b57cec5SDimitry Andric Cond = Op0Op0;
6780b57cec5SDimitry Andric IfSet = Op0Op1;
6790b57cec5SDimitry Andric IfClr = Op1Op1;
6800b57cec5SDimitry Andric } else if (isBitwiseInverse(Op1Op1, Op0Op0)) {
6810b57cec5SDimitry Andric Cond = Op0Op0;
6820b57cec5SDimitry Andric IfSet = Op0Op1;
6830b57cec5SDimitry Andric IfClr = Op1Op0;
6840b57cec5SDimitry Andric } else if (isBitwiseInverse(Op1Op0, Op0Op1)) {
6850b57cec5SDimitry Andric Cond = Op0Op1;
6860b57cec5SDimitry Andric IfSet = Op0Op0;
6870b57cec5SDimitry Andric IfClr = Op1Op1;
6880b57cec5SDimitry Andric } else if (isBitwiseInverse(Op1Op1, Op0Op1)) {
6890b57cec5SDimitry Andric Cond = Op0Op1;
6900b57cec5SDimitry Andric IfSet = Op0Op0;
6910b57cec5SDimitry Andric IfClr = Op1Op0;
6920b57cec5SDimitry Andric }
6930b57cec5SDimitry Andric }
6940b57cec5SDimitry Andric
6950b57cec5SDimitry Andric // At this point, IfClr will be set if we have a valid match.
6960b57cec5SDimitry Andric if (!IfClr.getNode())
6970b57cec5SDimitry Andric return SDValue();
6980b57cec5SDimitry Andric
6990b57cec5SDimitry Andric assert(Cond.getNode() && IfSet.getNode());
7000b57cec5SDimitry Andric
7010b57cec5SDimitry Andric // Fold degenerate cases.
7020b57cec5SDimitry Andric if (IsConstantMask) {
703349cc55cSDimitry Andric if (Mask.isAllOnes())
7040b57cec5SDimitry Andric return IfSet;
7050b57cec5SDimitry Andric else if (Mask == 0)
7060b57cec5SDimitry Andric return IfClr;
7070b57cec5SDimitry Andric }
7080b57cec5SDimitry Andric
7090b57cec5SDimitry Andric // Transform the DAG into an equivalent VSELECT.
7100b57cec5SDimitry Andric return DAG.getNode(ISD::VSELECT, SDLoc(N), Ty, Cond, IfSet, IfClr);
7110b57cec5SDimitry Andric }
7120b57cec5SDimitry Andric
7130b57cec5SDimitry Andric return SDValue();
7140b57cec5SDimitry Andric }
7150b57cec5SDimitry Andric
shouldTransformMulToShiftsAddsSubs(APInt C,EVT VT,SelectionDAG & DAG,const MipsSubtarget & Subtarget)7160b57cec5SDimitry Andric static bool shouldTransformMulToShiftsAddsSubs(APInt C, EVT VT,
7170b57cec5SDimitry Andric SelectionDAG &DAG,
7180b57cec5SDimitry Andric const MipsSubtarget &Subtarget) {
7190b57cec5SDimitry Andric // Estimate the number of operations the below transform will turn a
7200b57cec5SDimitry Andric // constant multiply into. The number is approximately equal to the minimal
7210b57cec5SDimitry Andric // number of powers of two that constant can be broken down to by adding
7220b57cec5SDimitry Andric // or subtracting them.
7230b57cec5SDimitry Andric //
7240b57cec5SDimitry Andric // If we have taken more than 12[1] / 8[2] steps to attempt the
7250b57cec5SDimitry Andric // optimization for a native sized value, it is more than likely that this
7260b57cec5SDimitry Andric // optimization will make things worse.
7270b57cec5SDimitry Andric //
7280b57cec5SDimitry Andric // [1] MIPS64 requires 6 instructions at most to materialize any constant,
7290b57cec5SDimitry Andric // multiplication requires at least 4 cycles, but another cycle (or two)
7300b57cec5SDimitry Andric // to retrieve the result from the HI/LO registers.
7310b57cec5SDimitry Andric //
7320b57cec5SDimitry Andric // [2] For MIPS32, more than 8 steps is expensive as the constant could be
7330b57cec5SDimitry Andric // materialized in 2 instructions, multiplication requires at least 4
7340b57cec5SDimitry Andric // cycles, but another cycle (or two) to retrieve the result from the
7350b57cec5SDimitry Andric // HI/LO registers.
7360b57cec5SDimitry Andric //
7370b57cec5SDimitry Andric // TODO:
7380b57cec5SDimitry Andric // - MaxSteps needs to consider the `VT` of the constant for the current
7390b57cec5SDimitry Andric // target.
7400b57cec5SDimitry Andric // - Consider to perform this optimization after type legalization.
7410b57cec5SDimitry Andric // That allows to remove a workaround for types not supported natively.
7420b57cec5SDimitry Andric // - Take in account `-Os, -Oz` flags because this optimization
7430b57cec5SDimitry Andric // increases code size.
7440b57cec5SDimitry Andric unsigned MaxSteps = Subtarget.isABI_O32() ? 8 : 12;
7450b57cec5SDimitry Andric
7460b57cec5SDimitry Andric SmallVector<APInt, 16> WorkStack(1, C);
7470b57cec5SDimitry Andric unsigned Steps = 0;
7480b57cec5SDimitry Andric unsigned BitWidth = C.getBitWidth();
7490b57cec5SDimitry Andric
7500b57cec5SDimitry Andric while (!WorkStack.empty()) {
7510b57cec5SDimitry Andric APInt Val = WorkStack.pop_back_val();
7520b57cec5SDimitry Andric
7530b57cec5SDimitry Andric if (Val == 0 || Val == 1)
7540b57cec5SDimitry Andric continue;
7550b57cec5SDimitry Andric
7560b57cec5SDimitry Andric if (Steps >= MaxSteps)
7570b57cec5SDimitry Andric return false;
7580b57cec5SDimitry Andric
7590b57cec5SDimitry Andric if (Val.isPowerOf2()) {
7600b57cec5SDimitry Andric ++Steps;
7610b57cec5SDimitry Andric continue;
7620b57cec5SDimitry Andric }
7630b57cec5SDimitry Andric
7640b57cec5SDimitry Andric APInt Floor = APInt(BitWidth, 1) << Val.logBase2();
7650b57cec5SDimitry Andric APInt Ceil = Val.isNegative() ? APInt(BitWidth, 0)
7660b57cec5SDimitry Andric : APInt(BitWidth, 1) << C.ceilLogBase2();
7670b57cec5SDimitry Andric if ((Val - Floor).ule(Ceil - Val)) {
7680b57cec5SDimitry Andric WorkStack.push_back(Floor);
7690b57cec5SDimitry Andric WorkStack.push_back(Val - Floor);
7700b57cec5SDimitry Andric } else {
7710b57cec5SDimitry Andric WorkStack.push_back(Ceil);
7720b57cec5SDimitry Andric WorkStack.push_back(Ceil - Val);
7730b57cec5SDimitry Andric }
7740b57cec5SDimitry Andric
7750b57cec5SDimitry Andric ++Steps;
7760b57cec5SDimitry Andric }
7770b57cec5SDimitry Andric
7780b57cec5SDimitry Andric // If the value being multiplied is not supported natively, we have to pay
7790b57cec5SDimitry Andric // an additional legalization cost, conservatively assume an increase in the
7800b57cec5SDimitry Andric // cost of 3 instructions per step. This values for this heuristic were
7810b57cec5SDimitry Andric // determined experimentally.
7820b57cec5SDimitry Andric unsigned RegisterSize = DAG.getTargetLoweringInfo()
7830b57cec5SDimitry Andric .getRegisterType(*DAG.getContext(), VT)
7840b57cec5SDimitry Andric .getSizeInBits();
7850b57cec5SDimitry Andric Steps *= (VT.getSizeInBits() != RegisterSize) * 3;
7860b57cec5SDimitry Andric if (Steps > 27)
7870b57cec5SDimitry Andric return false;
7880b57cec5SDimitry Andric
7890b57cec5SDimitry Andric return true;
7900b57cec5SDimitry Andric }
7910b57cec5SDimitry Andric
genConstMult(SDValue X,APInt C,const SDLoc & DL,EVT VT,EVT ShiftTy,SelectionDAG & DAG)7920b57cec5SDimitry Andric static SDValue genConstMult(SDValue X, APInt C, const SDLoc &DL, EVT VT,
7930b57cec5SDimitry Andric EVT ShiftTy, SelectionDAG &DAG) {
7940b57cec5SDimitry Andric // Return 0.
7950b57cec5SDimitry Andric if (C == 0)
7960b57cec5SDimitry Andric return DAG.getConstant(0, DL, VT);
7970b57cec5SDimitry Andric
7980b57cec5SDimitry Andric // Return x.
7990b57cec5SDimitry Andric if (C == 1)
8000b57cec5SDimitry Andric return X;
8010b57cec5SDimitry Andric
8020b57cec5SDimitry Andric // If c is power of 2, return (shl x, log2(c)).
8030b57cec5SDimitry Andric if (C.isPowerOf2())
8040b57cec5SDimitry Andric return DAG.getNode(ISD::SHL, DL, VT, X,
8050b57cec5SDimitry Andric DAG.getConstant(C.logBase2(), DL, ShiftTy));
8060b57cec5SDimitry Andric
8070b57cec5SDimitry Andric unsigned BitWidth = C.getBitWidth();
8080b57cec5SDimitry Andric APInt Floor = APInt(BitWidth, 1) << C.logBase2();
8090b57cec5SDimitry Andric APInt Ceil = C.isNegative() ? APInt(BitWidth, 0) :
8100b57cec5SDimitry Andric APInt(BitWidth, 1) << C.ceilLogBase2();
8110b57cec5SDimitry Andric
8120b57cec5SDimitry Andric // If |c - floor_c| <= |c - ceil_c|,
8130b57cec5SDimitry Andric // where floor_c = pow(2, floor(log2(c))) and ceil_c = pow(2, ceil(log2(c))),
8140b57cec5SDimitry Andric // return (add constMult(x, floor_c), constMult(x, c - floor_c)).
8150b57cec5SDimitry Andric if ((C - Floor).ule(Ceil - C)) {
8160b57cec5SDimitry Andric SDValue Op0 = genConstMult(X, Floor, DL, VT, ShiftTy, DAG);
8170b57cec5SDimitry Andric SDValue Op1 = genConstMult(X, C - Floor, DL, VT, ShiftTy, DAG);
8180b57cec5SDimitry Andric return DAG.getNode(ISD::ADD, DL, VT, Op0, Op1);
8190b57cec5SDimitry Andric }
8200b57cec5SDimitry Andric
8210b57cec5SDimitry Andric // If |c - floor_c| > |c - ceil_c|,
8220b57cec5SDimitry Andric // return (sub constMult(x, ceil_c), constMult(x, ceil_c - c)).
8230b57cec5SDimitry Andric SDValue Op0 = genConstMult(X, Ceil, DL, VT, ShiftTy, DAG);
8240b57cec5SDimitry Andric SDValue Op1 = genConstMult(X, Ceil - C, DL, VT, ShiftTy, DAG);
8250b57cec5SDimitry Andric return DAG.getNode(ISD::SUB, DL, VT, Op0, Op1);
8260b57cec5SDimitry Andric }
8270b57cec5SDimitry Andric
performMULCombine(SDNode * N,SelectionDAG & DAG,const TargetLowering::DAGCombinerInfo & DCI,const MipsSETargetLowering * TL,const MipsSubtarget & Subtarget)8280b57cec5SDimitry Andric static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG,
8290b57cec5SDimitry Andric const TargetLowering::DAGCombinerInfo &DCI,
8300b57cec5SDimitry Andric const MipsSETargetLowering *TL,
8310b57cec5SDimitry Andric const MipsSubtarget &Subtarget) {
8320b57cec5SDimitry Andric EVT VT = N->getValueType(0);
8330b57cec5SDimitry Andric
8340b57cec5SDimitry Andric if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1)))
8350b57cec5SDimitry Andric if (!VT.isVector() && shouldTransformMulToShiftsAddsSubs(
8360b57cec5SDimitry Andric C->getAPIntValue(), VT, DAG, Subtarget))
8370b57cec5SDimitry Andric return genConstMult(N->getOperand(0), C->getAPIntValue(), SDLoc(N), VT,
8380b57cec5SDimitry Andric TL->getScalarShiftAmountTy(DAG.getDataLayout(), VT),
8390b57cec5SDimitry Andric DAG);
8400b57cec5SDimitry Andric
8410b57cec5SDimitry Andric return SDValue(N, 0);
8420b57cec5SDimitry Andric }
8430b57cec5SDimitry Andric
performDSPShiftCombine(unsigned Opc,SDNode * N,EVT Ty,SelectionDAG & DAG,const MipsSubtarget & Subtarget)8440b57cec5SDimitry Andric static SDValue performDSPShiftCombine(unsigned Opc, SDNode *N, EVT Ty,
8450b57cec5SDimitry Andric SelectionDAG &DAG,
8460b57cec5SDimitry Andric const MipsSubtarget &Subtarget) {
8470b57cec5SDimitry Andric // See if this is a vector splat immediate node.
8480b57cec5SDimitry Andric APInt SplatValue, SplatUndef;
8490b57cec5SDimitry Andric unsigned SplatBitSize;
8500b57cec5SDimitry Andric bool HasAnyUndefs;
8510b57cec5SDimitry Andric unsigned EltSize = Ty.getScalarSizeInBits();
8520b57cec5SDimitry Andric BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N->getOperand(1));
8530b57cec5SDimitry Andric
8540b57cec5SDimitry Andric if (!Subtarget.hasDSP())
8550b57cec5SDimitry Andric return SDValue();
8560b57cec5SDimitry Andric
8570b57cec5SDimitry Andric if (!BV ||
8580b57cec5SDimitry Andric !BV->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
8590b57cec5SDimitry Andric EltSize, !Subtarget.isLittle()) ||
8600b57cec5SDimitry Andric (SplatBitSize != EltSize) ||
8610b57cec5SDimitry Andric (SplatValue.getZExtValue() >= EltSize))
8620b57cec5SDimitry Andric return SDValue();
8630b57cec5SDimitry Andric
8640b57cec5SDimitry Andric SDLoc DL(N);
8650b57cec5SDimitry Andric return DAG.getNode(Opc, DL, Ty, N->getOperand(0),
8660b57cec5SDimitry Andric DAG.getConstant(SplatValue.getZExtValue(), DL, MVT::i32));
8670b57cec5SDimitry Andric }
8680b57cec5SDimitry Andric
performSHLCombine(SDNode * N,SelectionDAG & DAG,TargetLowering::DAGCombinerInfo & DCI,const MipsSubtarget & Subtarget)8690b57cec5SDimitry Andric static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
8700b57cec5SDimitry Andric TargetLowering::DAGCombinerInfo &DCI,
8710b57cec5SDimitry Andric const MipsSubtarget &Subtarget) {
8720b57cec5SDimitry Andric EVT Ty = N->getValueType(0);
8730b57cec5SDimitry Andric
8740b57cec5SDimitry Andric if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8))
8750b57cec5SDimitry Andric return SDValue();
8760b57cec5SDimitry Andric
8770b57cec5SDimitry Andric return performDSPShiftCombine(MipsISD::SHLL_DSP, N, Ty, DAG, Subtarget);
8780b57cec5SDimitry Andric }
8790b57cec5SDimitry Andric
8800b57cec5SDimitry Andric // Fold sign-extensions into MipsISD::VEXTRACT_[SZ]EXT_ELT for MSA and fold
8810b57cec5SDimitry Andric // constant splats into MipsISD::SHRA_DSP for DSPr2.
8820b57cec5SDimitry Andric //
8830b57cec5SDimitry Andric // Performs the following transformations:
8840b57cec5SDimitry Andric // - Changes MipsISD::VEXTRACT_[SZ]EXT_ELT to sign extension if its
8850b57cec5SDimitry Andric // sign/zero-extension is completely overwritten by the new one performed by
8860b57cec5SDimitry Andric // the ISD::SRA and ISD::SHL nodes.
8870b57cec5SDimitry Andric // - Removes redundant sign extensions performed by an ISD::SRA and ISD::SHL
8880b57cec5SDimitry Andric // sequence.
8890b57cec5SDimitry Andric //
8900b57cec5SDimitry Andric // See performDSPShiftCombine for more information about the transformation
8910b57cec5SDimitry Andric // used for DSPr2.
performSRACombine(SDNode * N,SelectionDAG & DAG,TargetLowering::DAGCombinerInfo & DCI,const MipsSubtarget & Subtarget)8920b57cec5SDimitry Andric static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG,
8930b57cec5SDimitry Andric TargetLowering::DAGCombinerInfo &DCI,
8940b57cec5SDimitry Andric const MipsSubtarget &Subtarget) {
8950b57cec5SDimitry Andric EVT Ty = N->getValueType(0);
8960b57cec5SDimitry Andric
8970b57cec5SDimitry Andric if (Subtarget.hasMSA()) {
8980b57cec5SDimitry Andric SDValue Op0 = N->getOperand(0);
8990b57cec5SDimitry Andric SDValue Op1 = N->getOperand(1);
9000b57cec5SDimitry Andric
9010b57cec5SDimitry Andric // (sra (shl (MipsVExtract[SZ]Ext $a, $b, $c), imm:$d), imm:$d)
9020b57cec5SDimitry Andric // where $d + sizeof($c) == 32
9030b57cec5SDimitry Andric // or $d + sizeof($c) <= 32 and SExt
9040b57cec5SDimitry Andric // -> (MipsVExtractSExt $a, $b, $c)
9050b57cec5SDimitry Andric if (Op0->getOpcode() == ISD::SHL && Op1 == Op0->getOperand(1)) {
9060b57cec5SDimitry Andric SDValue Op0Op0 = Op0->getOperand(0);
9070b57cec5SDimitry Andric ConstantSDNode *ShAmount = dyn_cast<ConstantSDNode>(Op1);
9080b57cec5SDimitry Andric
9090b57cec5SDimitry Andric if (!ShAmount)
9100b57cec5SDimitry Andric return SDValue();
9110b57cec5SDimitry Andric
9120b57cec5SDimitry Andric if (Op0Op0->getOpcode() != MipsISD::VEXTRACT_SEXT_ELT &&
9130b57cec5SDimitry Andric Op0Op0->getOpcode() != MipsISD::VEXTRACT_ZEXT_ELT)
9140b57cec5SDimitry Andric return SDValue();
9150b57cec5SDimitry Andric
9160b57cec5SDimitry Andric EVT ExtendTy = cast<VTSDNode>(Op0Op0->getOperand(2))->getVT();
9170b57cec5SDimitry Andric unsigned TotalBits = ShAmount->getZExtValue() + ExtendTy.getSizeInBits();
9180b57cec5SDimitry Andric
9190b57cec5SDimitry Andric if (TotalBits == 32 ||
9200b57cec5SDimitry Andric (Op0Op0->getOpcode() == MipsISD::VEXTRACT_SEXT_ELT &&
9210b57cec5SDimitry Andric TotalBits <= 32)) {
9220b57cec5SDimitry Andric SDValue Ops[] = { Op0Op0->getOperand(0), Op0Op0->getOperand(1),
9230b57cec5SDimitry Andric Op0Op0->getOperand(2) };
9240b57cec5SDimitry Andric return DAG.getNode(MipsISD::VEXTRACT_SEXT_ELT, SDLoc(Op0Op0),
9250b57cec5SDimitry Andric Op0Op0->getVTList(),
926bdd1243dSDimitry Andric ArrayRef(Ops, Op0Op0->getNumOperands()));
9270b57cec5SDimitry Andric }
9280b57cec5SDimitry Andric }
9290b57cec5SDimitry Andric }
9300b57cec5SDimitry Andric
9310b57cec5SDimitry Andric if ((Ty != MVT::v2i16) && ((Ty != MVT::v4i8) || !Subtarget.hasDSPR2()))
9320b57cec5SDimitry Andric return SDValue();
9330b57cec5SDimitry Andric
9340b57cec5SDimitry Andric return performDSPShiftCombine(MipsISD::SHRA_DSP, N, Ty, DAG, Subtarget);
9350b57cec5SDimitry Andric }
9360b57cec5SDimitry Andric
9370b57cec5SDimitry Andric
performSRLCombine(SDNode * N,SelectionDAG & DAG,TargetLowering::DAGCombinerInfo & DCI,const MipsSubtarget & Subtarget)9380b57cec5SDimitry Andric static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG,
9390b57cec5SDimitry Andric TargetLowering::DAGCombinerInfo &DCI,
9400b57cec5SDimitry Andric const MipsSubtarget &Subtarget) {
9410b57cec5SDimitry Andric EVT Ty = N->getValueType(0);
9420b57cec5SDimitry Andric
9430b57cec5SDimitry Andric if (((Ty != MVT::v2i16) || !Subtarget.hasDSPR2()) && (Ty != MVT::v4i8))
9440b57cec5SDimitry Andric return SDValue();
9450b57cec5SDimitry Andric
9460b57cec5SDimitry Andric return performDSPShiftCombine(MipsISD::SHRL_DSP, N, Ty, DAG, Subtarget);
9470b57cec5SDimitry Andric }
9480b57cec5SDimitry Andric
isLegalDSPCondCode(EVT Ty,ISD::CondCode CC)9490b57cec5SDimitry Andric static bool isLegalDSPCondCode(EVT Ty, ISD::CondCode CC) {
9500b57cec5SDimitry Andric bool IsV216 = (Ty == MVT::v2i16);
9510b57cec5SDimitry Andric
9520b57cec5SDimitry Andric switch (CC) {
9530b57cec5SDimitry Andric case ISD::SETEQ:
9540b57cec5SDimitry Andric case ISD::SETNE: return true;
9550b57cec5SDimitry Andric case ISD::SETLT:
9560b57cec5SDimitry Andric case ISD::SETLE:
9570b57cec5SDimitry Andric case ISD::SETGT:
9580b57cec5SDimitry Andric case ISD::SETGE: return IsV216;
9590b57cec5SDimitry Andric case ISD::SETULT:
9600b57cec5SDimitry Andric case ISD::SETULE:
9610b57cec5SDimitry Andric case ISD::SETUGT:
9620b57cec5SDimitry Andric case ISD::SETUGE: return !IsV216;
9630b57cec5SDimitry Andric default: return false;
9640b57cec5SDimitry Andric }
9650b57cec5SDimitry Andric }
9660b57cec5SDimitry Andric
performSETCCCombine(SDNode * N,SelectionDAG & DAG)9670b57cec5SDimitry Andric static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG) {
9680b57cec5SDimitry Andric EVT Ty = N->getValueType(0);
9690b57cec5SDimitry Andric
9700b57cec5SDimitry Andric if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8))
9710b57cec5SDimitry Andric return SDValue();
9720b57cec5SDimitry Andric
9730b57cec5SDimitry Andric if (!isLegalDSPCondCode(Ty, cast<CondCodeSDNode>(N->getOperand(2))->get()))
9740b57cec5SDimitry Andric return SDValue();
9750b57cec5SDimitry Andric
9760b57cec5SDimitry Andric return DAG.getNode(MipsISD::SETCC_DSP, SDLoc(N), Ty, N->getOperand(0),
9770b57cec5SDimitry Andric N->getOperand(1), N->getOperand(2));
9780b57cec5SDimitry Andric }
9790b57cec5SDimitry Andric
performVSELECTCombine(SDNode * N,SelectionDAG & DAG)9800b57cec5SDimitry Andric static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) {
9810b57cec5SDimitry Andric EVT Ty = N->getValueType(0);
9820b57cec5SDimitry Andric
9830b57cec5SDimitry Andric if (Ty == MVT::v2i16 || Ty == MVT::v4i8) {
9840b57cec5SDimitry Andric SDValue SetCC = N->getOperand(0);
9850b57cec5SDimitry Andric
9860b57cec5SDimitry Andric if (SetCC.getOpcode() != MipsISD::SETCC_DSP)
9870b57cec5SDimitry Andric return SDValue();
9880b57cec5SDimitry Andric
9890b57cec5SDimitry Andric return DAG.getNode(MipsISD::SELECT_CC_DSP, SDLoc(N), Ty,
9900b57cec5SDimitry Andric SetCC.getOperand(0), SetCC.getOperand(1),
9910b57cec5SDimitry Andric N->getOperand(1), N->getOperand(2), SetCC.getOperand(2));
9920b57cec5SDimitry Andric }
9930b57cec5SDimitry Andric
9940b57cec5SDimitry Andric return SDValue();
9950b57cec5SDimitry Andric }
9960b57cec5SDimitry Andric
performXORCombine(SDNode * N,SelectionDAG & DAG,const MipsSubtarget & Subtarget)9970b57cec5SDimitry Andric static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG,
9980b57cec5SDimitry Andric const MipsSubtarget &Subtarget) {
9990b57cec5SDimitry Andric EVT Ty = N->getValueType(0);
10000b57cec5SDimitry Andric
10010b57cec5SDimitry Andric if (Subtarget.hasMSA() && Ty.is128BitVector() && Ty.isInteger()) {
10020b57cec5SDimitry Andric // Try the following combines:
10030b57cec5SDimitry Andric // (xor (or $a, $b), (build_vector allones))
10040b57cec5SDimitry Andric // (xor (or $a, $b), (bitcast (build_vector allones)))
10050b57cec5SDimitry Andric SDValue Op0 = N->getOperand(0);
10060b57cec5SDimitry Andric SDValue Op1 = N->getOperand(1);
10070b57cec5SDimitry Andric SDValue NotOp;
10080b57cec5SDimitry Andric
10090b57cec5SDimitry Andric if (ISD::isBuildVectorAllOnes(Op0.getNode()))
10100b57cec5SDimitry Andric NotOp = Op1;
10110b57cec5SDimitry Andric else if (ISD::isBuildVectorAllOnes(Op1.getNode()))
10120b57cec5SDimitry Andric NotOp = Op0;
10130b57cec5SDimitry Andric else
10140b57cec5SDimitry Andric return SDValue();
10150b57cec5SDimitry Andric
10160b57cec5SDimitry Andric if (NotOp->getOpcode() == ISD::OR)
10170b57cec5SDimitry Andric return DAG.getNode(MipsISD::VNOR, SDLoc(N), Ty, NotOp->getOperand(0),
10180b57cec5SDimitry Andric NotOp->getOperand(1));
10190b57cec5SDimitry Andric }
10200b57cec5SDimitry Andric
10210b57cec5SDimitry Andric return SDValue();
10220b57cec5SDimitry Andric }
10230b57cec5SDimitry Andric
10240b57cec5SDimitry Andric SDValue
PerformDAGCombine(SDNode * N,DAGCombinerInfo & DCI) const10250b57cec5SDimitry Andric MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
10260b57cec5SDimitry Andric SelectionDAG &DAG = DCI.DAG;
10270b57cec5SDimitry Andric SDValue Val;
10280b57cec5SDimitry Andric
10290b57cec5SDimitry Andric switch (N->getOpcode()) {
10300b57cec5SDimitry Andric case ISD::AND:
10310b57cec5SDimitry Andric Val = performANDCombine(N, DAG, DCI, Subtarget);
10320b57cec5SDimitry Andric break;
10330b57cec5SDimitry Andric case ISD::OR:
10340b57cec5SDimitry Andric Val = performORCombine(N, DAG, DCI, Subtarget);
10350b57cec5SDimitry Andric break;
10360b57cec5SDimitry Andric case ISD::MUL:
10370b57cec5SDimitry Andric return performMULCombine(N, DAG, DCI, this, Subtarget);
10380b57cec5SDimitry Andric case ISD::SHL:
10390b57cec5SDimitry Andric Val = performSHLCombine(N, DAG, DCI, Subtarget);
10400b57cec5SDimitry Andric break;
10410b57cec5SDimitry Andric case ISD::SRA:
10420b57cec5SDimitry Andric return performSRACombine(N, DAG, DCI, Subtarget);
10430b57cec5SDimitry Andric case ISD::SRL:
10440b57cec5SDimitry Andric return performSRLCombine(N, DAG, DCI, Subtarget);
10450b57cec5SDimitry Andric case ISD::VSELECT:
10460b57cec5SDimitry Andric return performVSELECTCombine(N, DAG);
10470b57cec5SDimitry Andric case ISD::XOR:
10480b57cec5SDimitry Andric Val = performXORCombine(N, DAG, Subtarget);
10490b57cec5SDimitry Andric break;
10500b57cec5SDimitry Andric case ISD::SETCC:
10510b57cec5SDimitry Andric Val = performSETCCCombine(N, DAG);
10520b57cec5SDimitry Andric break;
10530b57cec5SDimitry Andric }
10540b57cec5SDimitry Andric
10550b57cec5SDimitry Andric if (Val.getNode()) {
10560b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nMipsSE DAG Combine:\n";
10570b57cec5SDimitry Andric N->printrWithDepth(dbgs(), &DAG); dbgs() << "\n=> \n";
10580b57cec5SDimitry Andric Val.getNode()->printrWithDepth(dbgs(), &DAG); dbgs() << "\n");
10590b57cec5SDimitry Andric return Val;
10600b57cec5SDimitry Andric }
10610b57cec5SDimitry Andric
10620b57cec5SDimitry Andric return MipsTargetLowering::PerformDAGCombine(N, DCI);
10630b57cec5SDimitry Andric }
10640b57cec5SDimitry Andric
10650b57cec5SDimitry Andric MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr & MI,MachineBasicBlock * BB) const10660b57cec5SDimitry Andric MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
10670b57cec5SDimitry Andric MachineBasicBlock *BB) const {
10680b57cec5SDimitry Andric switch (MI.getOpcode()) {
10690b57cec5SDimitry Andric default:
10700b57cec5SDimitry Andric return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB);
10710b57cec5SDimitry Andric case Mips::BPOSGE32_PSEUDO:
10720b57cec5SDimitry Andric return emitBPOSGE32(MI, BB);
10730b57cec5SDimitry Andric case Mips::SNZ_B_PSEUDO:
10740b57cec5SDimitry Andric return emitMSACBranchPseudo(MI, BB, Mips::BNZ_B);
10750b57cec5SDimitry Andric case Mips::SNZ_H_PSEUDO:
10760b57cec5SDimitry Andric return emitMSACBranchPseudo(MI, BB, Mips::BNZ_H);
10770b57cec5SDimitry Andric case Mips::SNZ_W_PSEUDO:
10780b57cec5SDimitry Andric return emitMSACBranchPseudo(MI, BB, Mips::BNZ_W);
10790b57cec5SDimitry Andric case Mips::SNZ_D_PSEUDO:
10800b57cec5SDimitry Andric return emitMSACBranchPseudo(MI, BB, Mips::BNZ_D);
10810b57cec5SDimitry Andric case Mips::SNZ_V_PSEUDO:
10820b57cec5SDimitry Andric return emitMSACBranchPseudo(MI, BB, Mips::BNZ_V);
10830b57cec5SDimitry Andric case Mips::SZ_B_PSEUDO:
10840b57cec5SDimitry Andric return emitMSACBranchPseudo(MI, BB, Mips::BZ_B);
10850b57cec5SDimitry Andric case Mips::SZ_H_PSEUDO:
10860b57cec5SDimitry Andric return emitMSACBranchPseudo(MI, BB, Mips::BZ_H);
10870b57cec5SDimitry Andric case Mips::SZ_W_PSEUDO:
10880b57cec5SDimitry Andric return emitMSACBranchPseudo(MI, BB, Mips::BZ_W);
10890b57cec5SDimitry Andric case Mips::SZ_D_PSEUDO:
10900b57cec5SDimitry Andric return emitMSACBranchPseudo(MI, BB, Mips::BZ_D);
10910b57cec5SDimitry Andric case Mips::SZ_V_PSEUDO:
10920b57cec5SDimitry Andric return emitMSACBranchPseudo(MI, BB, Mips::BZ_V);
10930b57cec5SDimitry Andric case Mips::COPY_FW_PSEUDO:
10940b57cec5SDimitry Andric return emitCOPY_FW(MI, BB);
10950b57cec5SDimitry Andric case Mips::COPY_FD_PSEUDO:
10960b57cec5SDimitry Andric return emitCOPY_FD(MI, BB);
10970b57cec5SDimitry Andric case Mips::INSERT_FW_PSEUDO:
10980b57cec5SDimitry Andric return emitINSERT_FW(MI, BB);
10990b57cec5SDimitry Andric case Mips::INSERT_FD_PSEUDO:
11000b57cec5SDimitry Andric return emitINSERT_FD(MI, BB);
11010b57cec5SDimitry Andric case Mips::INSERT_B_VIDX_PSEUDO:
11020b57cec5SDimitry Andric case Mips::INSERT_B_VIDX64_PSEUDO:
11030b57cec5SDimitry Andric return emitINSERT_DF_VIDX(MI, BB, 1, false);
11040b57cec5SDimitry Andric case Mips::INSERT_H_VIDX_PSEUDO:
11050b57cec5SDimitry Andric case Mips::INSERT_H_VIDX64_PSEUDO:
11060b57cec5SDimitry Andric return emitINSERT_DF_VIDX(MI, BB, 2, false);
11070b57cec5SDimitry Andric case Mips::INSERT_W_VIDX_PSEUDO:
11080b57cec5SDimitry Andric case Mips::INSERT_W_VIDX64_PSEUDO:
11090b57cec5SDimitry Andric return emitINSERT_DF_VIDX(MI, BB, 4, false);
11100b57cec5SDimitry Andric case Mips::INSERT_D_VIDX_PSEUDO:
11110b57cec5SDimitry Andric case Mips::INSERT_D_VIDX64_PSEUDO:
11120b57cec5SDimitry Andric return emitINSERT_DF_VIDX(MI, BB, 8, false);
11130b57cec5SDimitry Andric case Mips::INSERT_FW_VIDX_PSEUDO:
11140b57cec5SDimitry Andric case Mips::INSERT_FW_VIDX64_PSEUDO:
11150b57cec5SDimitry Andric return emitINSERT_DF_VIDX(MI, BB, 4, true);
11160b57cec5SDimitry Andric case Mips::INSERT_FD_VIDX_PSEUDO:
11170b57cec5SDimitry Andric case Mips::INSERT_FD_VIDX64_PSEUDO:
11180b57cec5SDimitry Andric return emitINSERT_DF_VIDX(MI, BB, 8, true);
11190b57cec5SDimitry Andric case Mips::FILL_FW_PSEUDO:
11200b57cec5SDimitry Andric return emitFILL_FW(MI, BB);
11210b57cec5SDimitry Andric case Mips::FILL_FD_PSEUDO:
11220b57cec5SDimitry Andric return emitFILL_FD(MI, BB);
11230b57cec5SDimitry Andric case Mips::FEXP2_W_1_PSEUDO:
11240b57cec5SDimitry Andric return emitFEXP2_W_1(MI, BB);
11250b57cec5SDimitry Andric case Mips::FEXP2_D_1_PSEUDO:
11260b57cec5SDimitry Andric return emitFEXP2_D_1(MI, BB);
11270b57cec5SDimitry Andric case Mips::ST_F16:
11280b57cec5SDimitry Andric return emitST_F16_PSEUDO(MI, BB);
11290b57cec5SDimitry Andric case Mips::LD_F16:
11300b57cec5SDimitry Andric return emitLD_F16_PSEUDO(MI, BB);
11310b57cec5SDimitry Andric case Mips::MSA_FP_EXTEND_W_PSEUDO:
11320b57cec5SDimitry Andric return emitFPEXTEND_PSEUDO(MI, BB, false);
11330b57cec5SDimitry Andric case Mips::MSA_FP_ROUND_W_PSEUDO:
11340b57cec5SDimitry Andric return emitFPROUND_PSEUDO(MI, BB, false);
11350b57cec5SDimitry Andric case Mips::MSA_FP_EXTEND_D_PSEUDO:
11360b57cec5SDimitry Andric return emitFPEXTEND_PSEUDO(MI, BB, true);
11370b57cec5SDimitry Andric case Mips::MSA_FP_ROUND_D_PSEUDO:
11380b57cec5SDimitry Andric return emitFPROUND_PSEUDO(MI, BB, true);
11390b57cec5SDimitry Andric }
11400b57cec5SDimitry Andric }
11410b57cec5SDimitry Andric
isEligibleForTailCallOptimization(const CCState & CCInfo,unsigned NextStackOffset,const MipsFunctionInfo & FI) const11420b57cec5SDimitry Andric bool MipsSETargetLowering::isEligibleForTailCallOptimization(
11430b57cec5SDimitry Andric const CCState &CCInfo, unsigned NextStackOffset,
11440b57cec5SDimitry Andric const MipsFunctionInfo &FI) const {
11450b57cec5SDimitry Andric if (!UseMipsTailCalls)
11460b57cec5SDimitry Andric return false;
11470b57cec5SDimitry Andric
11480b57cec5SDimitry Andric // Exception has to be cleared with eret.
11490b57cec5SDimitry Andric if (FI.isISR())
11500b57cec5SDimitry Andric return false;
11510b57cec5SDimitry Andric
11520b57cec5SDimitry Andric // Return false if either the callee or caller has a byval argument.
11530b57cec5SDimitry Andric if (CCInfo.getInRegsParamsCount() > 0 || FI.hasByvalArg())
11540b57cec5SDimitry Andric return false;
11550b57cec5SDimitry Andric
11560b57cec5SDimitry Andric // Return true if the callee's argument area is no larger than the
11570b57cec5SDimitry Andric // caller's.
11580b57cec5SDimitry Andric return NextStackOffset <= FI.getIncomingArgSize();
11590b57cec5SDimitry Andric }
11600b57cec5SDimitry Andric
11610b57cec5SDimitry Andric void MipsSETargetLowering::
getOpndList(SmallVectorImpl<SDValue> & Ops,std::deque<std::pair<unsigned,SDValue>> & RegsToPass,bool IsPICCall,bool GlobalOrExternal,bool InternalLinkage,bool IsCallReloc,CallLoweringInfo & CLI,SDValue Callee,SDValue Chain) const11620b57cec5SDimitry Andric getOpndList(SmallVectorImpl<SDValue> &Ops,
11630b57cec5SDimitry Andric std::deque<std::pair<unsigned, SDValue>> &RegsToPass,
11640b57cec5SDimitry Andric bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
11650b57cec5SDimitry Andric bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee,
11660b57cec5SDimitry Andric SDValue Chain) const {
11670b57cec5SDimitry Andric Ops.push_back(Callee);
11680b57cec5SDimitry Andric MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal,
11690b57cec5SDimitry Andric InternalLinkage, IsCallReloc, CLI, Callee,
11700b57cec5SDimitry Andric Chain);
11710b57cec5SDimitry Andric }
11720b57cec5SDimitry Andric
lowerLOAD(SDValue Op,SelectionDAG & DAG) const11730b57cec5SDimitry Andric SDValue MipsSETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const {
11740b57cec5SDimitry Andric LoadSDNode &Nd = *cast<LoadSDNode>(Op);
11750b57cec5SDimitry Andric
11760b57cec5SDimitry Andric if (Nd.getMemoryVT() != MVT::f64 || !NoDPLoadStore)
11770b57cec5SDimitry Andric return MipsTargetLowering::lowerLOAD(Op, DAG);
11780b57cec5SDimitry Andric
11790b57cec5SDimitry Andric // Replace a double precision load with two i32 loads and a buildpair64.
11800b57cec5SDimitry Andric SDLoc DL(Op);
11810b57cec5SDimitry Andric SDValue Ptr = Nd.getBasePtr(), Chain = Nd.getChain();
11820b57cec5SDimitry Andric EVT PtrVT = Ptr.getValueType();
11830b57cec5SDimitry Andric
11840b57cec5SDimitry Andric // i32 load from lower address.
11850b57cec5SDimitry Andric SDValue Lo = DAG.getLoad(MVT::i32, DL, Chain, Ptr, MachinePointerInfo(),
118681ad6265SDimitry Andric Nd.getAlign(), Nd.getMemOperand()->getFlags());
11870b57cec5SDimitry Andric
11880b57cec5SDimitry Andric // i32 load from higher address.
11890b57cec5SDimitry Andric Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, DL, PtrVT));
11900b57cec5SDimitry Andric SDValue Hi = DAG.getLoad(
11910b57cec5SDimitry Andric MVT::i32, DL, Lo.getValue(1), Ptr, MachinePointerInfo(),
119281ad6265SDimitry Andric commonAlignment(Nd.getAlign(), 4), Nd.getMemOperand()->getFlags());
11930b57cec5SDimitry Andric
11940b57cec5SDimitry Andric if (!Subtarget.isLittle())
11950b57cec5SDimitry Andric std::swap(Lo, Hi);
11960b57cec5SDimitry Andric
11970b57cec5SDimitry Andric SDValue BP = DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, Lo, Hi);
11980b57cec5SDimitry Andric SDValue Ops[2] = {BP, Hi.getValue(1)};
11990b57cec5SDimitry Andric return DAG.getMergeValues(Ops, DL);
12000b57cec5SDimitry Andric }
12010b57cec5SDimitry Andric
lowerSTORE(SDValue Op,SelectionDAG & DAG) const12020b57cec5SDimitry Andric SDValue MipsSETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
12030b57cec5SDimitry Andric StoreSDNode &Nd = *cast<StoreSDNode>(Op);
12040b57cec5SDimitry Andric
12050b57cec5SDimitry Andric if (Nd.getMemoryVT() != MVT::f64 || !NoDPLoadStore)
12060b57cec5SDimitry Andric return MipsTargetLowering::lowerSTORE(Op, DAG);
12070b57cec5SDimitry Andric
12080b57cec5SDimitry Andric // Replace a double precision store with two extractelement64s and i32 stores.
12090b57cec5SDimitry Andric SDLoc DL(Op);
12100b57cec5SDimitry Andric SDValue Val = Nd.getValue(), Ptr = Nd.getBasePtr(), Chain = Nd.getChain();
12110b57cec5SDimitry Andric EVT PtrVT = Ptr.getValueType();
12120b57cec5SDimitry Andric SDValue Lo = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
12130b57cec5SDimitry Andric Val, DAG.getConstant(0, DL, MVT::i32));
12140b57cec5SDimitry Andric SDValue Hi = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
12150b57cec5SDimitry Andric Val, DAG.getConstant(1, DL, MVT::i32));
12160b57cec5SDimitry Andric
12170b57cec5SDimitry Andric if (!Subtarget.isLittle())
12180b57cec5SDimitry Andric std::swap(Lo, Hi);
12190b57cec5SDimitry Andric
12200b57cec5SDimitry Andric // i32 store to lower address.
122181ad6265SDimitry Andric Chain = DAG.getStore(Chain, DL, Lo, Ptr, MachinePointerInfo(), Nd.getAlign(),
12220b57cec5SDimitry Andric Nd.getMemOperand()->getFlags(), Nd.getAAInfo());
12230b57cec5SDimitry Andric
12240b57cec5SDimitry Andric // i32 store to higher address.
12250b57cec5SDimitry Andric Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, DL, PtrVT));
12260b57cec5SDimitry Andric return DAG.getStore(Chain, DL, Hi, Ptr, MachinePointerInfo(),
122781ad6265SDimitry Andric commonAlignment(Nd.getAlign(), 4),
12280b57cec5SDimitry Andric Nd.getMemOperand()->getFlags(), Nd.getAAInfo());
12290b57cec5SDimitry Andric }
12300b57cec5SDimitry Andric
lowerBITCAST(SDValue Op,SelectionDAG & DAG) const12310b57cec5SDimitry Andric SDValue MipsSETargetLowering::lowerBITCAST(SDValue Op,
12320b57cec5SDimitry Andric SelectionDAG &DAG) const {
12330b57cec5SDimitry Andric SDLoc DL(Op);
12340b57cec5SDimitry Andric MVT Src = Op.getOperand(0).getValueType().getSimpleVT();
12350b57cec5SDimitry Andric MVT Dest = Op.getValueType().getSimpleVT();
12360b57cec5SDimitry Andric
12370b57cec5SDimitry Andric // Bitcast i64 to double.
12380b57cec5SDimitry Andric if (Src == MVT::i64 && Dest == MVT::f64) {
123906c3fb27SDimitry Andric SDValue Lo, Hi;
124006c3fb27SDimitry Andric std::tie(Lo, Hi) =
124106c3fb27SDimitry Andric DAG.SplitScalar(Op.getOperand(0), DL, MVT::i32, MVT::i32);
12420b57cec5SDimitry Andric return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, Lo, Hi);
12430b57cec5SDimitry Andric }
12440b57cec5SDimitry Andric
12450b57cec5SDimitry Andric // Bitcast double to i64.
12460b57cec5SDimitry Andric if (Src == MVT::f64 && Dest == MVT::i64) {
12470b57cec5SDimitry Andric SDValue Lo =
12480b57cec5SDimitry Andric DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0),
12490b57cec5SDimitry Andric DAG.getConstant(0, DL, MVT::i32));
12500b57cec5SDimitry Andric SDValue Hi =
12510b57cec5SDimitry Andric DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0),
12520b57cec5SDimitry Andric DAG.getConstant(1, DL, MVT::i32));
12530b57cec5SDimitry Andric return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi);
12540b57cec5SDimitry Andric }
12550b57cec5SDimitry Andric
12560b57cec5SDimitry Andric // Skip other cases of bitcast and use default lowering.
12570b57cec5SDimitry Andric return SDValue();
12580b57cec5SDimitry Andric }
12590b57cec5SDimitry Andric
lowerMulDiv(SDValue Op,unsigned NewOpc,bool HasLo,bool HasHi,SelectionDAG & DAG) const12600b57cec5SDimitry Andric SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc,
12610b57cec5SDimitry Andric bool HasLo, bool HasHi,
12620b57cec5SDimitry Andric SelectionDAG &DAG) const {
12630b57cec5SDimitry Andric // MIPS32r6/MIPS64r6 removed accumulator based multiplies.
12640b57cec5SDimitry Andric assert(!Subtarget.hasMips32r6());
12650b57cec5SDimitry Andric
12660b57cec5SDimitry Andric EVT Ty = Op.getOperand(0).getValueType();
12670b57cec5SDimitry Andric SDLoc DL(Op);
12680b57cec5SDimitry Andric SDValue Mult = DAG.getNode(NewOpc, DL, MVT::Untyped,
12690b57cec5SDimitry Andric Op.getOperand(0), Op.getOperand(1));
12700b57cec5SDimitry Andric SDValue Lo, Hi;
12710b57cec5SDimitry Andric
12720b57cec5SDimitry Andric if (HasLo)
12730b57cec5SDimitry Andric Lo = DAG.getNode(MipsISD::MFLO, DL, Ty, Mult);
12740b57cec5SDimitry Andric if (HasHi)
12750b57cec5SDimitry Andric Hi = DAG.getNode(MipsISD::MFHI, DL, Ty, Mult);
12760b57cec5SDimitry Andric
12770b57cec5SDimitry Andric if (!HasLo || !HasHi)
12780b57cec5SDimitry Andric return HasLo ? Lo : Hi;
12790b57cec5SDimitry Andric
12800b57cec5SDimitry Andric SDValue Vals[] = { Lo, Hi };
12810b57cec5SDimitry Andric return DAG.getMergeValues(Vals, DL);
12820b57cec5SDimitry Andric }
12830b57cec5SDimitry Andric
initAccumulator(SDValue In,const SDLoc & DL,SelectionDAG & DAG)12840b57cec5SDimitry Andric static SDValue initAccumulator(SDValue In, const SDLoc &DL, SelectionDAG &DAG) {
128506c3fb27SDimitry Andric SDValue InLo, InHi;
128606c3fb27SDimitry Andric std::tie(InLo, InHi) = DAG.SplitScalar(In, DL, MVT::i32, MVT::i32);
12870b57cec5SDimitry Andric return DAG.getNode(MipsISD::MTLOHI, DL, MVT::Untyped, InLo, InHi);
12880b57cec5SDimitry Andric }
12890b57cec5SDimitry Andric
extractLOHI(SDValue Op,const SDLoc & DL,SelectionDAG & DAG)12900b57cec5SDimitry Andric static SDValue extractLOHI(SDValue Op, const SDLoc &DL, SelectionDAG &DAG) {
12910b57cec5SDimitry Andric SDValue Lo = DAG.getNode(MipsISD::MFLO, DL, MVT::i32, Op);
12920b57cec5SDimitry Andric SDValue Hi = DAG.getNode(MipsISD::MFHI, DL, MVT::i32, Op);
12930b57cec5SDimitry Andric return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi);
12940b57cec5SDimitry Andric }
12950b57cec5SDimitry Andric
12960b57cec5SDimitry Andric // This function expands mips intrinsic nodes which have 64-bit input operands
12970b57cec5SDimitry Andric // or output values.
12980b57cec5SDimitry Andric //
12990b57cec5SDimitry Andric // out64 = intrinsic-node in64
13000b57cec5SDimitry Andric // =>
13010b57cec5SDimitry Andric // lo = copy (extract-element (in64, 0))
13020b57cec5SDimitry Andric // hi = copy (extract-element (in64, 1))
13030b57cec5SDimitry Andric // mips-specific-node
13040b57cec5SDimitry Andric // v0 = copy lo
13050b57cec5SDimitry Andric // v1 = copy hi
13060b57cec5SDimitry Andric // out64 = merge-values (v0, v1)
13070b57cec5SDimitry Andric //
lowerDSPIntr(SDValue Op,SelectionDAG & DAG,unsigned Opc)13080b57cec5SDimitry Andric static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
13090b57cec5SDimitry Andric SDLoc DL(Op);
13100b57cec5SDimitry Andric bool HasChainIn = Op->getOperand(0).getValueType() == MVT::Other;
13110b57cec5SDimitry Andric SmallVector<SDValue, 3> Ops;
13120b57cec5SDimitry Andric unsigned OpNo = 0;
13130b57cec5SDimitry Andric
13140b57cec5SDimitry Andric // See if Op has a chain input.
13150b57cec5SDimitry Andric if (HasChainIn)
13160b57cec5SDimitry Andric Ops.push_back(Op->getOperand(OpNo++));
13170b57cec5SDimitry Andric
13180b57cec5SDimitry Andric // The next operand is the intrinsic opcode.
13190b57cec5SDimitry Andric assert(Op->getOperand(OpNo).getOpcode() == ISD::TargetConstant);
13200b57cec5SDimitry Andric
13210b57cec5SDimitry Andric // See if the next operand has type i64.
13220b57cec5SDimitry Andric SDValue Opnd = Op->getOperand(++OpNo), In64;
13230b57cec5SDimitry Andric
13240b57cec5SDimitry Andric if (Opnd.getValueType() == MVT::i64)
13250b57cec5SDimitry Andric In64 = initAccumulator(Opnd, DL, DAG);
13260b57cec5SDimitry Andric else
13270b57cec5SDimitry Andric Ops.push_back(Opnd);
13280b57cec5SDimitry Andric
13290b57cec5SDimitry Andric // Push the remaining operands.
13300b57cec5SDimitry Andric for (++OpNo ; OpNo < Op->getNumOperands(); ++OpNo)
13310b57cec5SDimitry Andric Ops.push_back(Op->getOperand(OpNo));
13320b57cec5SDimitry Andric
13330b57cec5SDimitry Andric // Add In64 to the end of the list.
13340b57cec5SDimitry Andric if (In64.getNode())
13350b57cec5SDimitry Andric Ops.push_back(In64);
13360b57cec5SDimitry Andric
13370b57cec5SDimitry Andric // Scan output.
13380b57cec5SDimitry Andric SmallVector<EVT, 2> ResTys;
13390b57cec5SDimitry Andric
13405ffd83dbSDimitry Andric for (EVT Ty : Op->values())
13415ffd83dbSDimitry Andric ResTys.push_back((Ty == MVT::i64) ? MVT::Untyped : Ty);
13420b57cec5SDimitry Andric
13430b57cec5SDimitry Andric // Create node.
13440b57cec5SDimitry Andric SDValue Val = DAG.getNode(Opc, DL, ResTys, Ops);
13450b57cec5SDimitry Andric SDValue Out = (ResTys[0] == MVT::Untyped) ? extractLOHI(Val, DL, DAG) : Val;
13460b57cec5SDimitry Andric
13470b57cec5SDimitry Andric if (!HasChainIn)
13480b57cec5SDimitry Andric return Out;
13490b57cec5SDimitry Andric
13500b57cec5SDimitry Andric assert(Val->getValueType(1) == MVT::Other);
13510b57cec5SDimitry Andric SDValue Vals[] = { Out, SDValue(Val.getNode(), 1) };
13520b57cec5SDimitry Andric return DAG.getMergeValues(Vals, DL);
13530b57cec5SDimitry Andric }
13540b57cec5SDimitry Andric
13550b57cec5SDimitry Andric // Lower an MSA copy intrinsic into the specified SelectionDAG node
lowerMSACopyIntr(SDValue Op,SelectionDAG & DAG,unsigned Opc)13560b57cec5SDimitry Andric static SDValue lowerMSACopyIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
13570b57cec5SDimitry Andric SDLoc DL(Op);
13580b57cec5SDimitry Andric SDValue Vec = Op->getOperand(1);
13590b57cec5SDimitry Andric SDValue Idx = Op->getOperand(2);
13600b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
13610b57cec5SDimitry Andric EVT EltTy = Vec->getValueType(0).getVectorElementType();
13620b57cec5SDimitry Andric
13630b57cec5SDimitry Andric SDValue Result = DAG.getNode(Opc, DL, ResTy, Vec, Idx,
13640b57cec5SDimitry Andric DAG.getValueType(EltTy));
13650b57cec5SDimitry Andric
13660b57cec5SDimitry Andric return Result;
13670b57cec5SDimitry Andric }
13680b57cec5SDimitry Andric
lowerMSASplatZExt(SDValue Op,unsigned OpNr,SelectionDAG & DAG)13690b57cec5SDimitry Andric static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) {
13700b57cec5SDimitry Andric EVT ResVecTy = Op->getValueType(0);
13710b57cec5SDimitry Andric EVT ViaVecTy = ResVecTy;
13720b57cec5SDimitry Andric bool BigEndian = !DAG.getSubtarget().getTargetTriple().isLittleEndian();
13730b57cec5SDimitry Andric SDLoc DL(Op);
13740b57cec5SDimitry Andric
13750b57cec5SDimitry Andric // When ResVecTy == MVT::v2i64, LaneA is the upper 32 bits of the lane and
13760b57cec5SDimitry Andric // LaneB is the lower 32-bits. Otherwise LaneA and LaneB are alternating
13770b57cec5SDimitry Andric // lanes.
13780b57cec5SDimitry Andric SDValue LaneA = Op->getOperand(OpNr);
13790b57cec5SDimitry Andric SDValue LaneB;
13800b57cec5SDimitry Andric
13810b57cec5SDimitry Andric if (ResVecTy == MVT::v2i64) {
13820b57cec5SDimitry Andric // In case of the index being passed as an immediate value, set the upper
13830b57cec5SDimitry Andric // lane to 0 so that the splati.d instruction can be matched.
13840b57cec5SDimitry Andric if (isa<ConstantSDNode>(LaneA))
13850b57cec5SDimitry Andric LaneB = DAG.getConstant(0, DL, MVT::i32);
13860b57cec5SDimitry Andric // Having the index passed in a register, set the upper lane to the same
13870b57cec5SDimitry Andric // value as the lower - this results in the BUILD_VECTOR node not being
13880b57cec5SDimitry Andric // expanded through stack. This way we are able to pattern match the set of
13890b57cec5SDimitry Andric // nodes created here to splat.d.
13900b57cec5SDimitry Andric else
13910b57cec5SDimitry Andric LaneB = LaneA;
13920b57cec5SDimitry Andric ViaVecTy = MVT::v4i32;
13930b57cec5SDimitry Andric if(BigEndian)
13940b57cec5SDimitry Andric std::swap(LaneA, LaneB);
13950b57cec5SDimitry Andric } else
13960b57cec5SDimitry Andric LaneB = LaneA;
13970b57cec5SDimitry Andric
13980b57cec5SDimitry Andric SDValue Ops[16] = { LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB,
13990b57cec5SDimitry Andric LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB };
14000b57cec5SDimitry Andric
14010b57cec5SDimitry Andric SDValue Result = DAG.getBuildVector(
1402bdd1243dSDimitry Andric ViaVecTy, DL, ArrayRef(Ops, ViaVecTy.getVectorNumElements()));
14030b57cec5SDimitry Andric
14040b57cec5SDimitry Andric if (ViaVecTy != ResVecTy) {
14050b57cec5SDimitry Andric SDValue One = DAG.getConstant(1, DL, ViaVecTy);
14060b57cec5SDimitry Andric Result = DAG.getNode(ISD::BITCAST, DL, ResVecTy,
14070b57cec5SDimitry Andric DAG.getNode(ISD::AND, DL, ViaVecTy, Result, One));
14080b57cec5SDimitry Andric }
14090b57cec5SDimitry Andric
14100b57cec5SDimitry Andric return Result;
14110b57cec5SDimitry Andric }
14120b57cec5SDimitry Andric
lowerMSASplatImm(SDValue Op,unsigned ImmOp,SelectionDAG & DAG,bool IsSigned=false)14130b57cec5SDimitry Andric static SDValue lowerMSASplatImm(SDValue Op, unsigned ImmOp, SelectionDAG &DAG,
14140b57cec5SDimitry Andric bool IsSigned = false) {
14150b57cec5SDimitry Andric auto *CImm = cast<ConstantSDNode>(Op->getOperand(ImmOp));
14160b57cec5SDimitry Andric return DAG.getConstant(
14170b57cec5SDimitry Andric APInt(Op->getValueType(0).getScalarType().getSizeInBits(),
14180b57cec5SDimitry Andric IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
14190b57cec5SDimitry Andric SDLoc(Op), Op->getValueType(0));
14200b57cec5SDimitry Andric }
14210b57cec5SDimitry Andric
getBuildVectorSplat(EVT VecTy,SDValue SplatValue,bool BigEndian,SelectionDAG & DAG)14220b57cec5SDimitry Andric static SDValue getBuildVectorSplat(EVT VecTy, SDValue SplatValue,
14230b57cec5SDimitry Andric bool BigEndian, SelectionDAG &DAG) {
14240b57cec5SDimitry Andric EVT ViaVecTy = VecTy;
14250b57cec5SDimitry Andric SDValue SplatValueA = SplatValue;
14260b57cec5SDimitry Andric SDValue SplatValueB = SplatValue;
14270b57cec5SDimitry Andric SDLoc DL(SplatValue);
14280b57cec5SDimitry Andric
14290b57cec5SDimitry Andric if (VecTy == MVT::v2i64) {
14300b57cec5SDimitry Andric // v2i64 BUILD_VECTOR must be performed via v4i32 so split into i32's.
14310b57cec5SDimitry Andric ViaVecTy = MVT::v4i32;
14320b57cec5SDimitry Andric
14330b57cec5SDimitry Andric SplatValueA = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValue);
14340b57cec5SDimitry Andric SplatValueB = DAG.getNode(ISD::SRL, DL, MVT::i64, SplatValue,
14350b57cec5SDimitry Andric DAG.getConstant(32, DL, MVT::i32));
14360b57cec5SDimitry Andric SplatValueB = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValueB);
14370b57cec5SDimitry Andric }
14380b57cec5SDimitry Andric
14390b57cec5SDimitry Andric // We currently hold the parts in little endian order. Swap them if
14400b57cec5SDimitry Andric // necessary.
14410b57cec5SDimitry Andric if (BigEndian)
14420b57cec5SDimitry Andric std::swap(SplatValueA, SplatValueB);
14430b57cec5SDimitry Andric
14440b57cec5SDimitry Andric SDValue Ops[16] = { SplatValueA, SplatValueB, SplatValueA, SplatValueB,
14450b57cec5SDimitry Andric SplatValueA, SplatValueB, SplatValueA, SplatValueB,
14460b57cec5SDimitry Andric SplatValueA, SplatValueB, SplatValueA, SplatValueB,
14470b57cec5SDimitry Andric SplatValueA, SplatValueB, SplatValueA, SplatValueB };
14480b57cec5SDimitry Andric
14490b57cec5SDimitry Andric SDValue Result = DAG.getBuildVector(
1450bdd1243dSDimitry Andric ViaVecTy, DL, ArrayRef(Ops, ViaVecTy.getVectorNumElements()));
14510b57cec5SDimitry Andric
14520b57cec5SDimitry Andric if (VecTy != ViaVecTy)
14530b57cec5SDimitry Andric Result = DAG.getNode(ISD::BITCAST, DL, VecTy, Result);
14540b57cec5SDimitry Andric
14550b57cec5SDimitry Andric return Result;
14560b57cec5SDimitry Andric }
14570b57cec5SDimitry Andric
lowerMSABinaryBitImmIntr(SDValue Op,SelectionDAG & DAG,unsigned Opc,SDValue Imm,bool BigEndian)14580b57cec5SDimitry Andric static SDValue lowerMSABinaryBitImmIntr(SDValue Op, SelectionDAG &DAG,
14590b57cec5SDimitry Andric unsigned Opc, SDValue Imm,
14600b57cec5SDimitry Andric bool BigEndian) {
14610b57cec5SDimitry Andric EVT VecTy = Op->getValueType(0);
14620b57cec5SDimitry Andric SDValue Exp2Imm;
14630b57cec5SDimitry Andric SDLoc DL(Op);
14640b57cec5SDimitry Andric
14650b57cec5SDimitry Andric // The DAG Combiner can't constant fold bitcasted vectors yet so we must do it
14660b57cec5SDimitry Andric // here for now.
14670b57cec5SDimitry Andric if (VecTy == MVT::v2i64) {
14680b57cec5SDimitry Andric if (ConstantSDNode *CImm = dyn_cast<ConstantSDNode>(Imm)) {
14690b57cec5SDimitry Andric APInt BitImm = APInt(64, 1) << CImm->getAPIntValue();
14700b57cec5SDimitry Andric
14710b57cec5SDimitry Andric SDValue BitImmHiOp = DAG.getConstant(BitImm.lshr(32).trunc(32), DL,
14720b57cec5SDimitry Andric MVT::i32);
14730b57cec5SDimitry Andric SDValue BitImmLoOp = DAG.getConstant(BitImm.trunc(32), DL, MVT::i32);
14740b57cec5SDimitry Andric
14750b57cec5SDimitry Andric if (BigEndian)
14760b57cec5SDimitry Andric std::swap(BitImmLoOp, BitImmHiOp);
14770b57cec5SDimitry Andric
14780b57cec5SDimitry Andric Exp2Imm = DAG.getNode(
14790b57cec5SDimitry Andric ISD::BITCAST, DL, MVT::v2i64,
14800b57cec5SDimitry Andric DAG.getBuildVector(MVT::v4i32, DL,
14810b57cec5SDimitry Andric {BitImmLoOp, BitImmHiOp, BitImmLoOp, BitImmHiOp}));
14820b57cec5SDimitry Andric }
14830b57cec5SDimitry Andric }
14840b57cec5SDimitry Andric
14850b57cec5SDimitry Andric if (!Exp2Imm.getNode()) {
14860b57cec5SDimitry Andric // We couldnt constant fold, do a vector shift instead
14870b57cec5SDimitry Andric
14880b57cec5SDimitry Andric // Extend i32 to i64 if necessary. Sign or zero extend doesn't matter since
14890b57cec5SDimitry Andric // only values 0-63 are valid.
14900b57cec5SDimitry Andric if (VecTy == MVT::v2i64)
14910b57cec5SDimitry Andric Imm = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Imm);
14920b57cec5SDimitry Andric
14930b57cec5SDimitry Andric Exp2Imm = getBuildVectorSplat(VecTy, Imm, BigEndian, DAG);
14940b57cec5SDimitry Andric
14950b57cec5SDimitry Andric Exp2Imm = DAG.getNode(ISD::SHL, DL, VecTy, DAG.getConstant(1, DL, VecTy),
14960b57cec5SDimitry Andric Exp2Imm);
14970b57cec5SDimitry Andric }
14980b57cec5SDimitry Andric
14990b57cec5SDimitry Andric return DAG.getNode(Opc, DL, VecTy, Op->getOperand(1), Exp2Imm);
15000b57cec5SDimitry Andric }
15010b57cec5SDimitry Andric
truncateVecElts(SDValue Op,SelectionDAG & DAG)15020b57cec5SDimitry Andric static SDValue truncateVecElts(SDValue Op, SelectionDAG &DAG) {
15030b57cec5SDimitry Andric SDLoc DL(Op);
15040b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
15050b57cec5SDimitry Andric SDValue Vec = Op->getOperand(2);
15060b57cec5SDimitry Andric bool BigEndian = !DAG.getSubtarget().getTargetTriple().isLittleEndian();
15070b57cec5SDimitry Andric MVT ResEltTy = ResTy == MVT::v2i64 ? MVT::i64 : MVT::i32;
15080b57cec5SDimitry Andric SDValue ConstValue = DAG.getConstant(Vec.getScalarValueSizeInBits() - 1,
15090b57cec5SDimitry Andric DL, ResEltTy);
15100b57cec5SDimitry Andric SDValue SplatVec = getBuildVectorSplat(ResTy, ConstValue, BigEndian, DAG);
15110b57cec5SDimitry Andric
15120b57cec5SDimitry Andric return DAG.getNode(ISD::AND, DL, ResTy, Vec, SplatVec);
15130b57cec5SDimitry Andric }
15140b57cec5SDimitry Andric
lowerMSABitClear(SDValue Op,SelectionDAG & DAG)15150b57cec5SDimitry Andric static SDValue lowerMSABitClear(SDValue Op, SelectionDAG &DAG) {
15160b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
15170b57cec5SDimitry Andric SDLoc DL(Op);
15180b57cec5SDimitry Andric SDValue One = DAG.getConstant(1, DL, ResTy);
15190b57cec5SDimitry Andric SDValue Bit = DAG.getNode(ISD::SHL, DL, ResTy, One, truncateVecElts(Op, DAG));
15200b57cec5SDimitry Andric
15210b57cec5SDimitry Andric return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1),
15220b57cec5SDimitry Andric DAG.getNOT(DL, Bit, ResTy));
15230b57cec5SDimitry Andric }
15240b57cec5SDimitry Andric
lowerMSABitClearImm(SDValue Op,SelectionDAG & DAG)15250b57cec5SDimitry Andric static SDValue lowerMSABitClearImm(SDValue Op, SelectionDAG &DAG) {
15260b57cec5SDimitry Andric SDLoc DL(Op);
15270b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
15280b57cec5SDimitry Andric APInt BitImm = APInt(ResTy.getScalarSizeInBits(), 1)
1529647cbc5dSDimitry Andric << Op->getConstantOperandAPInt(2);
15300b57cec5SDimitry Andric SDValue BitMask = DAG.getConstant(~BitImm, DL, ResTy);
15310b57cec5SDimitry Andric
15320b57cec5SDimitry Andric return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1), BitMask);
15330b57cec5SDimitry Andric }
15340b57cec5SDimitry Andric
lowerINTRINSIC_WO_CHAIN(SDValue Op,SelectionDAG & DAG) const15350b57cec5SDimitry Andric SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
15360b57cec5SDimitry Andric SelectionDAG &DAG) const {
15370b57cec5SDimitry Andric SDLoc DL(Op);
1538647cbc5dSDimitry Andric unsigned Intrinsic = Op->getConstantOperandVal(0);
15390b57cec5SDimitry Andric switch (Intrinsic) {
15400b57cec5SDimitry Andric default:
15410b57cec5SDimitry Andric return SDValue();
15420b57cec5SDimitry Andric case Intrinsic::mips_shilo:
15430b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::SHILO);
15440b57cec5SDimitry Andric case Intrinsic::mips_dpau_h_qbl:
15450b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBL);
15460b57cec5SDimitry Andric case Intrinsic::mips_dpau_h_qbr:
15470b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBR);
15480b57cec5SDimitry Andric case Intrinsic::mips_dpsu_h_qbl:
15490b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBL);
15500b57cec5SDimitry Andric case Intrinsic::mips_dpsu_h_qbr:
15510b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBR);
15520b57cec5SDimitry Andric case Intrinsic::mips_dpa_w_ph:
15530b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPA_W_PH);
15540b57cec5SDimitry Andric case Intrinsic::mips_dps_w_ph:
15550b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPS_W_PH);
15560b57cec5SDimitry Andric case Intrinsic::mips_dpax_w_ph:
15570b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPAX_W_PH);
15580b57cec5SDimitry Andric case Intrinsic::mips_dpsx_w_ph:
15590b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPSX_W_PH);
15600b57cec5SDimitry Andric case Intrinsic::mips_mulsa_w_ph:
15610b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::MULSA_W_PH);
15620b57cec5SDimitry Andric case Intrinsic::mips_mult:
15630b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::Mult);
15640b57cec5SDimitry Andric case Intrinsic::mips_multu:
15650b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::Multu);
15660b57cec5SDimitry Andric case Intrinsic::mips_madd:
15670b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::MAdd);
15680b57cec5SDimitry Andric case Intrinsic::mips_maddu:
15690b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::MAddu);
15700b57cec5SDimitry Andric case Intrinsic::mips_msub:
15710b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::MSub);
15720b57cec5SDimitry Andric case Intrinsic::mips_msubu:
15730b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::MSubu);
15740b57cec5SDimitry Andric case Intrinsic::mips_addv_b:
15750b57cec5SDimitry Andric case Intrinsic::mips_addv_h:
15760b57cec5SDimitry Andric case Intrinsic::mips_addv_w:
15770b57cec5SDimitry Andric case Intrinsic::mips_addv_d:
15780b57cec5SDimitry Andric return DAG.getNode(ISD::ADD, DL, Op->getValueType(0), Op->getOperand(1),
15790b57cec5SDimitry Andric Op->getOperand(2));
15800b57cec5SDimitry Andric case Intrinsic::mips_addvi_b:
15810b57cec5SDimitry Andric case Intrinsic::mips_addvi_h:
15820b57cec5SDimitry Andric case Intrinsic::mips_addvi_w:
15830b57cec5SDimitry Andric case Intrinsic::mips_addvi_d:
15840b57cec5SDimitry Andric return DAG.getNode(ISD::ADD, DL, Op->getValueType(0), Op->getOperand(1),
15850b57cec5SDimitry Andric lowerMSASplatImm(Op, 2, DAG));
15860b57cec5SDimitry Andric case Intrinsic::mips_and_v:
15870b57cec5SDimitry Andric return DAG.getNode(ISD::AND, DL, Op->getValueType(0), Op->getOperand(1),
15880b57cec5SDimitry Andric Op->getOperand(2));
15890b57cec5SDimitry Andric case Intrinsic::mips_andi_b:
15900b57cec5SDimitry Andric return DAG.getNode(ISD::AND, DL, Op->getValueType(0), Op->getOperand(1),
15910b57cec5SDimitry Andric lowerMSASplatImm(Op, 2, DAG));
15920b57cec5SDimitry Andric case Intrinsic::mips_bclr_b:
15930b57cec5SDimitry Andric case Intrinsic::mips_bclr_h:
15940b57cec5SDimitry Andric case Intrinsic::mips_bclr_w:
15950b57cec5SDimitry Andric case Intrinsic::mips_bclr_d:
15960b57cec5SDimitry Andric return lowerMSABitClear(Op, DAG);
15970b57cec5SDimitry Andric case Intrinsic::mips_bclri_b:
15980b57cec5SDimitry Andric case Intrinsic::mips_bclri_h:
15990b57cec5SDimitry Andric case Intrinsic::mips_bclri_w:
16000b57cec5SDimitry Andric case Intrinsic::mips_bclri_d:
16010b57cec5SDimitry Andric return lowerMSABitClearImm(Op, DAG);
16020b57cec5SDimitry Andric case Intrinsic::mips_binsli_b:
16030b57cec5SDimitry Andric case Intrinsic::mips_binsli_h:
16040b57cec5SDimitry Andric case Intrinsic::mips_binsli_w:
16050b57cec5SDimitry Andric case Intrinsic::mips_binsli_d: {
16060b57cec5SDimitry Andric // binsli_x(IfClear, IfSet, nbits) -> (vselect LBitsMask, IfSet, IfClear)
16070b57cec5SDimitry Andric EVT VecTy = Op->getValueType(0);
16080b57cec5SDimitry Andric EVT EltTy = VecTy.getVectorElementType();
16090b57cec5SDimitry Andric if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits())
16100b57cec5SDimitry Andric report_fatal_error("Immediate out of range");
16110b57cec5SDimitry Andric APInt Mask = APInt::getHighBitsSet(EltTy.getSizeInBits(),
16120b57cec5SDimitry Andric Op->getConstantOperandVal(3) + 1);
16130b57cec5SDimitry Andric return DAG.getNode(ISD::VSELECT, DL, VecTy,
16140b57cec5SDimitry Andric DAG.getConstant(Mask, DL, VecTy, true),
16150b57cec5SDimitry Andric Op->getOperand(2), Op->getOperand(1));
16160b57cec5SDimitry Andric }
16170b57cec5SDimitry Andric case Intrinsic::mips_binsri_b:
16180b57cec5SDimitry Andric case Intrinsic::mips_binsri_h:
16190b57cec5SDimitry Andric case Intrinsic::mips_binsri_w:
16200b57cec5SDimitry Andric case Intrinsic::mips_binsri_d: {
16210b57cec5SDimitry Andric // binsri_x(IfClear, IfSet, nbits) -> (vselect RBitsMask, IfSet, IfClear)
16220b57cec5SDimitry Andric EVT VecTy = Op->getValueType(0);
16230b57cec5SDimitry Andric EVT EltTy = VecTy.getVectorElementType();
16240b57cec5SDimitry Andric if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits())
16250b57cec5SDimitry Andric report_fatal_error("Immediate out of range");
16260b57cec5SDimitry Andric APInt Mask = APInt::getLowBitsSet(EltTy.getSizeInBits(),
16270b57cec5SDimitry Andric Op->getConstantOperandVal(3) + 1);
16280b57cec5SDimitry Andric return DAG.getNode(ISD::VSELECT, DL, VecTy,
16290b57cec5SDimitry Andric DAG.getConstant(Mask, DL, VecTy, true),
16300b57cec5SDimitry Andric Op->getOperand(2), Op->getOperand(1));
16310b57cec5SDimitry Andric }
16320b57cec5SDimitry Andric case Intrinsic::mips_bmnz_v:
16330b57cec5SDimitry Andric return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), Op->getOperand(3),
16340b57cec5SDimitry Andric Op->getOperand(2), Op->getOperand(1));
16350b57cec5SDimitry Andric case Intrinsic::mips_bmnzi_b:
16360b57cec5SDimitry Andric return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0),
16370b57cec5SDimitry Andric lowerMSASplatImm(Op, 3, DAG), Op->getOperand(2),
16380b57cec5SDimitry Andric Op->getOperand(1));
16390b57cec5SDimitry Andric case Intrinsic::mips_bmz_v:
16400b57cec5SDimitry Andric return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), Op->getOperand(3),
16410b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2));
16420b57cec5SDimitry Andric case Intrinsic::mips_bmzi_b:
16430b57cec5SDimitry Andric return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0),
16440b57cec5SDimitry Andric lowerMSASplatImm(Op, 3, DAG), Op->getOperand(1),
16450b57cec5SDimitry Andric Op->getOperand(2));
16460b57cec5SDimitry Andric case Intrinsic::mips_bneg_b:
16470b57cec5SDimitry Andric case Intrinsic::mips_bneg_h:
16480b57cec5SDimitry Andric case Intrinsic::mips_bneg_w:
16490b57cec5SDimitry Andric case Intrinsic::mips_bneg_d: {
16500b57cec5SDimitry Andric EVT VecTy = Op->getValueType(0);
16510b57cec5SDimitry Andric SDValue One = DAG.getConstant(1, DL, VecTy);
16520b57cec5SDimitry Andric
16530b57cec5SDimitry Andric return DAG.getNode(ISD::XOR, DL, VecTy, Op->getOperand(1),
16540b57cec5SDimitry Andric DAG.getNode(ISD::SHL, DL, VecTy, One,
16550b57cec5SDimitry Andric truncateVecElts(Op, DAG)));
16560b57cec5SDimitry Andric }
16570b57cec5SDimitry Andric case Intrinsic::mips_bnegi_b:
16580b57cec5SDimitry Andric case Intrinsic::mips_bnegi_h:
16590b57cec5SDimitry Andric case Intrinsic::mips_bnegi_w:
16600b57cec5SDimitry Andric case Intrinsic::mips_bnegi_d:
16610b57cec5SDimitry Andric return lowerMSABinaryBitImmIntr(Op, DAG, ISD::XOR, Op->getOperand(2),
16620b57cec5SDimitry Andric !Subtarget.isLittle());
16630b57cec5SDimitry Andric case Intrinsic::mips_bnz_b:
16640b57cec5SDimitry Andric case Intrinsic::mips_bnz_h:
16650b57cec5SDimitry Andric case Intrinsic::mips_bnz_w:
16660b57cec5SDimitry Andric case Intrinsic::mips_bnz_d:
16670b57cec5SDimitry Andric return DAG.getNode(MipsISD::VALL_NONZERO, DL, Op->getValueType(0),
16680b57cec5SDimitry Andric Op->getOperand(1));
16690b57cec5SDimitry Andric case Intrinsic::mips_bnz_v:
16700b57cec5SDimitry Andric return DAG.getNode(MipsISD::VANY_NONZERO, DL, Op->getValueType(0),
16710b57cec5SDimitry Andric Op->getOperand(1));
16720b57cec5SDimitry Andric case Intrinsic::mips_bsel_v:
16730b57cec5SDimitry Andric // bsel_v(Mask, IfClear, IfSet) -> (vselect Mask, IfSet, IfClear)
16740b57cec5SDimitry Andric return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0),
16750b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(3),
16760b57cec5SDimitry Andric Op->getOperand(2));
16770b57cec5SDimitry Andric case Intrinsic::mips_bseli_b:
16780b57cec5SDimitry Andric // bseli_v(Mask, IfClear, IfSet) -> (vselect Mask, IfSet, IfClear)
16790b57cec5SDimitry Andric return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0),
16800b57cec5SDimitry Andric Op->getOperand(1), lowerMSASplatImm(Op, 3, DAG),
16810b57cec5SDimitry Andric Op->getOperand(2));
16820b57cec5SDimitry Andric case Intrinsic::mips_bset_b:
16830b57cec5SDimitry Andric case Intrinsic::mips_bset_h:
16840b57cec5SDimitry Andric case Intrinsic::mips_bset_w:
16850b57cec5SDimitry Andric case Intrinsic::mips_bset_d: {
16860b57cec5SDimitry Andric EVT VecTy = Op->getValueType(0);
16870b57cec5SDimitry Andric SDValue One = DAG.getConstant(1, DL, VecTy);
16880b57cec5SDimitry Andric
16890b57cec5SDimitry Andric return DAG.getNode(ISD::OR, DL, VecTy, Op->getOperand(1),
16900b57cec5SDimitry Andric DAG.getNode(ISD::SHL, DL, VecTy, One,
16910b57cec5SDimitry Andric truncateVecElts(Op, DAG)));
16920b57cec5SDimitry Andric }
16930b57cec5SDimitry Andric case Intrinsic::mips_bseti_b:
16940b57cec5SDimitry Andric case Intrinsic::mips_bseti_h:
16950b57cec5SDimitry Andric case Intrinsic::mips_bseti_w:
16960b57cec5SDimitry Andric case Intrinsic::mips_bseti_d:
16970b57cec5SDimitry Andric return lowerMSABinaryBitImmIntr(Op, DAG, ISD::OR, Op->getOperand(2),
16980b57cec5SDimitry Andric !Subtarget.isLittle());
16990b57cec5SDimitry Andric case Intrinsic::mips_bz_b:
17000b57cec5SDimitry Andric case Intrinsic::mips_bz_h:
17010b57cec5SDimitry Andric case Intrinsic::mips_bz_w:
17020b57cec5SDimitry Andric case Intrinsic::mips_bz_d:
17030b57cec5SDimitry Andric return DAG.getNode(MipsISD::VALL_ZERO, DL, Op->getValueType(0),
17040b57cec5SDimitry Andric Op->getOperand(1));
17050b57cec5SDimitry Andric case Intrinsic::mips_bz_v:
17060b57cec5SDimitry Andric return DAG.getNode(MipsISD::VANY_ZERO, DL, Op->getValueType(0),
17070b57cec5SDimitry Andric Op->getOperand(1));
17080b57cec5SDimitry Andric case Intrinsic::mips_ceq_b:
17090b57cec5SDimitry Andric case Intrinsic::mips_ceq_h:
17100b57cec5SDimitry Andric case Intrinsic::mips_ceq_w:
17110b57cec5SDimitry Andric case Intrinsic::mips_ceq_d:
17120b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
17130b57cec5SDimitry Andric Op->getOperand(2), ISD::SETEQ);
17140b57cec5SDimitry Andric case Intrinsic::mips_ceqi_b:
17150b57cec5SDimitry Andric case Intrinsic::mips_ceqi_h:
17160b57cec5SDimitry Andric case Intrinsic::mips_ceqi_w:
17170b57cec5SDimitry Andric case Intrinsic::mips_ceqi_d:
17180b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
17190b57cec5SDimitry Andric lowerMSASplatImm(Op, 2, DAG, true), ISD::SETEQ);
17200b57cec5SDimitry Andric case Intrinsic::mips_cle_s_b:
17210b57cec5SDimitry Andric case Intrinsic::mips_cle_s_h:
17220b57cec5SDimitry Andric case Intrinsic::mips_cle_s_w:
17230b57cec5SDimitry Andric case Intrinsic::mips_cle_s_d:
17240b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
17250b57cec5SDimitry Andric Op->getOperand(2), ISD::SETLE);
17260b57cec5SDimitry Andric case Intrinsic::mips_clei_s_b:
17270b57cec5SDimitry Andric case Intrinsic::mips_clei_s_h:
17280b57cec5SDimitry Andric case Intrinsic::mips_clei_s_w:
17290b57cec5SDimitry Andric case Intrinsic::mips_clei_s_d:
17300b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
17310b57cec5SDimitry Andric lowerMSASplatImm(Op, 2, DAG, true), ISD::SETLE);
17320b57cec5SDimitry Andric case Intrinsic::mips_cle_u_b:
17330b57cec5SDimitry Andric case Intrinsic::mips_cle_u_h:
17340b57cec5SDimitry Andric case Intrinsic::mips_cle_u_w:
17350b57cec5SDimitry Andric case Intrinsic::mips_cle_u_d:
17360b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
17370b57cec5SDimitry Andric Op->getOperand(2), ISD::SETULE);
17380b57cec5SDimitry Andric case Intrinsic::mips_clei_u_b:
17390b57cec5SDimitry Andric case Intrinsic::mips_clei_u_h:
17400b57cec5SDimitry Andric case Intrinsic::mips_clei_u_w:
17410b57cec5SDimitry Andric case Intrinsic::mips_clei_u_d:
17420b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
17430b57cec5SDimitry Andric lowerMSASplatImm(Op, 2, DAG), ISD::SETULE);
17440b57cec5SDimitry Andric case Intrinsic::mips_clt_s_b:
17450b57cec5SDimitry Andric case Intrinsic::mips_clt_s_h:
17460b57cec5SDimitry Andric case Intrinsic::mips_clt_s_w:
17470b57cec5SDimitry Andric case Intrinsic::mips_clt_s_d:
17480b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
17490b57cec5SDimitry Andric Op->getOperand(2), ISD::SETLT);
17500b57cec5SDimitry Andric case Intrinsic::mips_clti_s_b:
17510b57cec5SDimitry Andric case Intrinsic::mips_clti_s_h:
17520b57cec5SDimitry Andric case Intrinsic::mips_clti_s_w:
17530b57cec5SDimitry Andric case Intrinsic::mips_clti_s_d:
17540b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
17550b57cec5SDimitry Andric lowerMSASplatImm(Op, 2, DAG, true), ISD::SETLT);
17560b57cec5SDimitry Andric case Intrinsic::mips_clt_u_b:
17570b57cec5SDimitry Andric case Intrinsic::mips_clt_u_h:
17580b57cec5SDimitry Andric case Intrinsic::mips_clt_u_w:
17590b57cec5SDimitry Andric case Intrinsic::mips_clt_u_d:
17600b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
17610b57cec5SDimitry Andric Op->getOperand(2), ISD::SETULT);
17620b57cec5SDimitry Andric case Intrinsic::mips_clti_u_b:
17630b57cec5SDimitry Andric case Intrinsic::mips_clti_u_h:
17640b57cec5SDimitry Andric case Intrinsic::mips_clti_u_w:
17650b57cec5SDimitry Andric case Intrinsic::mips_clti_u_d:
17660b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
17670b57cec5SDimitry Andric lowerMSASplatImm(Op, 2, DAG), ISD::SETULT);
17680b57cec5SDimitry Andric case Intrinsic::mips_copy_s_b:
17690b57cec5SDimitry Andric case Intrinsic::mips_copy_s_h:
17700b57cec5SDimitry Andric case Intrinsic::mips_copy_s_w:
17710b57cec5SDimitry Andric return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_SEXT_ELT);
17720b57cec5SDimitry Andric case Intrinsic::mips_copy_s_d:
17730b57cec5SDimitry Andric if (Subtarget.hasMips64())
17740b57cec5SDimitry Andric // Lower directly into VEXTRACT_SEXT_ELT since i64 is legal on Mips64.
17750b57cec5SDimitry Andric return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_SEXT_ELT);
17760b57cec5SDimitry Andric else {
17770b57cec5SDimitry Andric // Lower into the generic EXTRACT_VECTOR_ELT node and let the type
17780b57cec5SDimitry Andric // legalizer and EXTRACT_VECTOR_ELT lowering sort it out.
17790b57cec5SDimitry Andric return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(Op),
17800b57cec5SDimitry Andric Op->getValueType(0), Op->getOperand(1),
17810b57cec5SDimitry Andric Op->getOperand(2));
17820b57cec5SDimitry Andric }
17830b57cec5SDimitry Andric case Intrinsic::mips_copy_u_b:
17840b57cec5SDimitry Andric case Intrinsic::mips_copy_u_h:
17850b57cec5SDimitry Andric case Intrinsic::mips_copy_u_w:
17860b57cec5SDimitry Andric return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_ZEXT_ELT);
17870b57cec5SDimitry Andric case Intrinsic::mips_copy_u_d:
17880b57cec5SDimitry Andric if (Subtarget.hasMips64())
17890b57cec5SDimitry Andric // Lower directly into VEXTRACT_ZEXT_ELT since i64 is legal on Mips64.
17900b57cec5SDimitry Andric return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_ZEXT_ELT);
17910b57cec5SDimitry Andric else {
17920b57cec5SDimitry Andric // Lower into the generic EXTRACT_VECTOR_ELT node and let the type
17930b57cec5SDimitry Andric // legalizer and EXTRACT_VECTOR_ELT lowering sort it out.
17940b57cec5SDimitry Andric // Note: When i64 is illegal, this results in copy_s.w instructions
17950b57cec5SDimitry Andric // instead of copy_u.w instructions. This makes no difference to the
17960b57cec5SDimitry Andric // behaviour since i64 is only illegal when the register file is 32-bit.
17970b57cec5SDimitry Andric return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(Op),
17980b57cec5SDimitry Andric Op->getValueType(0), Op->getOperand(1),
17990b57cec5SDimitry Andric Op->getOperand(2));
18000b57cec5SDimitry Andric }
18010b57cec5SDimitry Andric case Intrinsic::mips_div_s_b:
18020b57cec5SDimitry Andric case Intrinsic::mips_div_s_h:
18030b57cec5SDimitry Andric case Intrinsic::mips_div_s_w:
18040b57cec5SDimitry Andric case Intrinsic::mips_div_s_d:
18050b57cec5SDimitry Andric return DAG.getNode(ISD::SDIV, DL, Op->getValueType(0), Op->getOperand(1),
18060b57cec5SDimitry Andric Op->getOperand(2));
18070b57cec5SDimitry Andric case Intrinsic::mips_div_u_b:
18080b57cec5SDimitry Andric case Intrinsic::mips_div_u_h:
18090b57cec5SDimitry Andric case Intrinsic::mips_div_u_w:
18100b57cec5SDimitry Andric case Intrinsic::mips_div_u_d:
18110b57cec5SDimitry Andric return DAG.getNode(ISD::UDIV, DL, Op->getValueType(0), Op->getOperand(1),
18120b57cec5SDimitry Andric Op->getOperand(2));
18130b57cec5SDimitry Andric case Intrinsic::mips_fadd_w:
18140b57cec5SDimitry Andric case Intrinsic::mips_fadd_d:
18150b57cec5SDimitry Andric // TODO: If intrinsics have fast-math-flags, propagate them.
18160b57cec5SDimitry Andric return DAG.getNode(ISD::FADD, DL, Op->getValueType(0), Op->getOperand(1),
18170b57cec5SDimitry Andric Op->getOperand(2));
18180b57cec5SDimitry Andric // Don't lower mips_fcaf_[wd] since LLVM folds SETFALSE condcodes away
18190b57cec5SDimitry Andric case Intrinsic::mips_fceq_w:
18200b57cec5SDimitry Andric case Intrinsic::mips_fceq_d:
18210b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
18220b57cec5SDimitry Andric Op->getOperand(2), ISD::SETOEQ);
18230b57cec5SDimitry Andric case Intrinsic::mips_fcle_w:
18240b57cec5SDimitry Andric case Intrinsic::mips_fcle_d:
18250b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
18260b57cec5SDimitry Andric Op->getOperand(2), ISD::SETOLE);
18270b57cec5SDimitry Andric case Intrinsic::mips_fclt_w:
18280b57cec5SDimitry Andric case Intrinsic::mips_fclt_d:
18290b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
18300b57cec5SDimitry Andric Op->getOperand(2), ISD::SETOLT);
18310b57cec5SDimitry Andric case Intrinsic::mips_fcne_w:
18320b57cec5SDimitry Andric case Intrinsic::mips_fcne_d:
18330b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
18340b57cec5SDimitry Andric Op->getOperand(2), ISD::SETONE);
18350b57cec5SDimitry Andric case Intrinsic::mips_fcor_w:
18360b57cec5SDimitry Andric case Intrinsic::mips_fcor_d:
18370b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
18380b57cec5SDimitry Andric Op->getOperand(2), ISD::SETO);
18390b57cec5SDimitry Andric case Intrinsic::mips_fcueq_w:
18400b57cec5SDimitry Andric case Intrinsic::mips_fcueq_d:
18410b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
18420b57cec5SDimitry Andric Op->getOperand(2), ISD::SETUEQ);
18430b57cec5SDimitry Andric case Intrinsic::mips_fcule_w:
18440b57cec5SDimitry Andric case Intrinsic::mips_fcule_d:
18450b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
18460b57cec5SDimitry Andric Op->getOperand(2), ISD::SETULE);
18470b57cec5SDimitry Andric case Intrinsic::mips_fcult_w:
18480b57cec5SDimitry Andric case Intrinsic::mips_fcult_d:
18490b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
18500b57cec5SDimitry Andric Op->getOperand(2), ISD::SETULT);
18510b57cec5SDimitry Andric case Intrinsic::mips_fcun_w:
18520b57cec5SDimitry Andric case Intrinsic::mips_fcun_d:
18530b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
18540b57cec5SDimitry Andric Op->getOperand(2), ISD::SETUO);
18550b57cec5SDimitry Andric case Intrinsic::mips_fcune_w:
18560b57cec5SDimitry Andric case Intrinsic::mips_fcune_d:
18570b57cec5SDimitry Andric return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
18580b57cec5SDimitry Andric Op->getOperand(2), ISD::SETUNE);
18590b57cec5SDimitry Andric case Intrinsic::mips_fdiv_w:
18600b57cec5SDimitry Andric case Intrinsic::mips_fdiv_d:
18610b57cec5SDimitry Andric // TODO: If intrinsics have fast-math-flags, propagate them.
18620b57cec5SDimitry Andric return DAG.getNode(ISD::FDIV, DL, Op->getValueType(0), Op->getOperand(1),
18630b57cec5SDimitry Andric Op->getOperand(2));
18640b57cec5SDimitry Andric case Intrinsic::mips_ffint_u_w:
18650b57cec5SDimitry Andric case Intrinsic::mips_ffint_u_d:
18660b57cec5SDimitry Andric return DAG.getNode(ISD::UINT_TO_FP, DL, Op->getValueType(0),
18670b57cec5SDimitry Andric Op->getOperand(1));
18680b57cec5SDimitry Andric case Intrinsic::mips_ffint_s_w:
18690b57cec5SDimitry Andric case Intrinsic::mips_ffint_s_d:
18700b57cec5SDimitry Andric return DAG.getNode(ISD::SINT_TO_FP, DL, Op->getValueType(0),
18710b57cec5SDimitry Andric Op->getOperand(1));
18720b57cec5SDimitry Andric case Intrinsic::mips_fill_b:
18730b57cec5SDimitry Andric case Intrinsic::mips_fill_h:
18740b57cec5SDimitry Andric case Intrinsic::mips_fill_w:
18750b57cec5SDimitry Andric case Intrinsic::mips_fill_d: {
18760b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
18770b57cec5SDimitry Andric SmallVector<SDValue, 16> Ops(ResTy.getVectorNumElements(),
18780b57cec5SDimitry Andric Op->getOperand(1));
18790b57cec5SDimitry Andric
18800b57cec5SDimitry Andric // If ResTy is v2i64 then the type legalizer will break this node down into
18810b57cec5SDimitry Andric // an equivalent v4i32.
18820b57cec5SDimitry Andric return DAG.getBuildVector(ResTy, DL, Ops);
18830b57cec5SDimitry Andric }
18840b57cec5SDimitry Andric case Intrinsic::mips_fexp2_w:
18850b57cec5SDimitry Andric case Intrinsic::mips_fexp2_d: {
18860b57cec5SDimitry Andric // TODO: If intrinsics have fast-math-flags, propagate them.
18870b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
18880b57cec5SDimitry Andric return DAG.getNode(
18890b57cec5SDimitry Andric ISD::FMUL, SDLoc(Op), ResTy, Op->getOperand(1),
18900b57cec5SDimitry Andric DAG.getNode(ISD::FEXP2, SDLoc(Op), ResTy, Op->getOperand(2)));
18910b57cec5SDimitry Andric }
18920b57cec5SDimitry Andric case Intrinsic::mips_flog2_w:
18930b57cec5SDimitry Andric case Intrinsic::mips_flog2_d:
18940b57cec5SDimitry Andric return DAG.getNode(ISD::FLOG2, DL, Op->getValueType(0), Op->getOperand(1));
18950b57cec5SDimitry Andric case Intrinsic::mips_fmadd_w:
18960b57cec5SDimitry Andric case Intrinsic::mips_fmadd_d:
18970b57cec5SDimitry Andric return DAG.getNode(ISD::FMA, SDLoc(Op), Op->getValueType(0),
18980b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2), Op->getOperand(3));
18990b57cec5SDimitry Andric case Intrinsic::mips_fmul_w:
19000b57cec5SDimitry Andric case Intrinsic::mips_fmul_d:
19010b57cec5SDimitry Andric // TODO: If intrinsics have fast-math-flags, propagate them.
19020b57cec5SDimitry Andric return DAG.getNode(ISD::FMUL, DL, Op->getValueType(0), Op->getOperand(1),
19030b57cec5SDimitry Andric Op->getOperand(2));
19040b57cec5SDimitry Andric case Intrinsic::mips_fmsub_w:
19050b57cec5SDimitry Andric case Intrinsic::mips_fmsub_d: {
19060b57cec5SDimitry Andric // TODO: If intrinsics have fast-math-flags, propagate them.
19070b57cec5SDimitry Andric return DAG.getNode(MipsISD::FMS, SDLoc(Op), Op->getValueType(0),
19080b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2), Op->getOperand(3));
19090b57cec5SDimitry Andric }
19100b57cec5SDimitry Andric case Intrinsic::mips_frint_w:
19110b57cec5SDimitry Andric case Intrinsic::mips_frint_d:
19120b57cec5SDimitry Andric return DAG.getNode(ISD::FRINT, DL, Op->getValueType(0), Op->getOperand(1));
19130b57cec5SDimitry Andric case Intrinsic::mips_fsqrt_w:
19140b57cec5SDimitry Andric case Intrinsic::mips_fsqrt_d:
19150b57cec5SDimitry Andric return DAG.getNode(ISD::FSQRT, DL, Op->getValueType(0), Op->getOperand(1));
19160b57cec5SDimitry Andric case Intrinsic::mips_fsub_w:
19170b57cec5SDimitry Andric case Intrinsic::mips_fsub_d:
19180b57cec5SDimitry Andric // TODO: If intrinsics have fast-math-flags, propagate them.
19190b57cec5SDimitry Andric return DAG.getNode(ISD::FSUB, DL, Op->getValueType(0), Op->getOperand(1),
19200b57cec5SDimitry Andric Op->getOperand(2));
19210b57cec5SDimitry Andric case Intrinsic::mips_ftrunc_u_w:
19220b57cec5SDimitry Andric case Intrinsic::mips_ftrunc_u_d:
19230b57cec5SDimitry Andric return DAG.getNode(ISD::FP_TO_UINT, DL, Op->getValueType(0),
19240b57cec5SDimitry Andric Op->getOperand(1));
19250b57cec5SDimitry Andric case Intrinsic::mips_ftrunc_s_w:
19260b57cec5SDimitry Andric case Intrinsic::mips_ftrunc_s_d:
19270b57cec5SDimitry Andric return DAG.getNode(ISD::FP_TO_SINT, DL, Op->getValueType(0),
19280b57cec5SDimitry Andric Op->getOperand(1));
19290b57cec5SDimitry Andric case Intrinsic::mips_ilvev_b:
19300b57cec5SDimitry Andric case Intrinsic::mips_ilvev_h:
19310b57cec5SDimitry Andric case Intrinsic::mips_ilvev_w:
19320b57cec5SDimitry Andric case Intrinsic::mips_ilvev_d:
19330b57cec5SDimitry Andric return DAG.getNode(MipsISD::ILVEV, DL, Op->getValueType(0),
19340b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2));
19350b57cec5SDimitry Andric case Intrinsic::mips_ilvl_b:
19360b57cec5SDimitry Andric case Intrinsic::mips_ilvl_h:
19370b57cec5SDimitry Andric case Intrinsic::mips_ilvl_w:
19380b57cec5SDimitry Andric case Intrinsic::mips_ilvl_d:
19390b57cec5SDimitry Andric return DAG.getNode(MipsISD::ILVL, DL, Op->getValueType(0),
19400b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2));
19410b57cec5SDimitry Andric case Intrinsic::mips_ilvod_b:
19420b57cec5SDimitry Andric case Intrinsic::mips_ilvod_h:
19430b57cec5SDimitry Andric case Intrinsic::mips_ilvod_w:
19440b57cec5SDimitry Andric case Intrinsic::mips_ilvod_d:
19450b57cec5SDimitry Andric return DAG.getNode(MipsISD::ILVOD, DL, Op->getValueType(0),
19460b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2));
19470b57cec5SDimitry Andric case Intrinsic::mips_ilvr_b:
19480b57cec5SDimitry Andric case Intrinsic::mips_ilvr_h:
19490b57cec5SDimitry Andric case Intrinsic::mips_ilvr_w:
19500b57cec5SDimitry Andric case Intrinsic::mips_ilvr_d:
19510b57cec5SDimitry Andric return DAG.getNode(MipsISD::ILVR, DL, Op->getValueType(0),
19520b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2));
19530b57cec5SDimitry Andric case Intrinsic::mips_insert_b:
19540b57cec5SDimitry Andric case Intrinsic::mips_insert_h:
19550b57cec5SDimitry Andric case Intrinsic::mips_insert_w:
19560b57cec5SDimitry Andric case Intrinsic::mips_insert_d:
19570b57cec5SDimitry Andric return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(Op), Op->getValueType(0),
19580b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(3), Op->getOperand(2));
19590b57cec5SDimitry Andric case Intrinsic::mips_insve_b:
19600b57cec5SDimitry Andric case Intrinsic::mips_insve_h:
19610b57cec5SDimitry Andric case Intrinsic::mips_insve_w:
19620b57cec5SDimitry Andric case Intrinsic::mips_insve_d: {
19630b57cec5SDimitry Andric // Report an error for out of range values.
19640b57cec5SDimitry Andric int64_t Max;
19650b57cec5SDimitry Andric switch (Intrinsic) {
19660b57cec5SDimitry Andric case Intrinsic::mips_insve_b: Max = 15; break;
19670b57cec5SDimitry Andric case Intrinsic::mips_insve_h: Max = 7; break;
19680b57cec5SDimitry Andric case Intrinsic::mips_insve_w: Max = 3; break;
19690b57cec5SDimitry Andric case Intrinsic::mips_insve_d: Max = 1; break;
19700b57cec5SDimitry Andric default: llvm_unreachable("Unmatched intrinsic");
19710b57cec5SDimitry Andric }
19720b57cec5SDimitry Andric int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
19730b57cec5SDimitry Andric if (Value < 0 || Value > Max)
19740b57cec5SDimitry Andric report_fatal_error("Immediate out of range");
19750b57cec5SDimitry Andric return DAG.getNode(MipsISD::INSVE, DL, Op->getValueType(0),
19760b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2), Op->getOperand(3),
19770b57cec5SDimitry Andric DAG.getConstant(0, DL, MVT::i32));
19780b57cec5SDimitry Andric }
19790b57cec5SDimitry Andric case Intrinsic::mips_ldi_b:
19800b57cec5SDimitry Andric case Intrinsic::mips_ldi_h:
19810b57cec5SDimitry Andric case Intrinsic::mips_ldi_w:
19820b57cec5SDimitry Andric case Intrinsic::mips_ldi_d:
19830b57cec5SDimitry Andric return lowerMSASplatImm(Op, 1, DAG, true);
19840b57cec5SDimitry Andric case Intrinsic::mips_lsa:
19850b57cec5SDimitry Andric case Intrinsic::mips_dlsa: {
19860b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
19870b57cec5SDimitry Andric return DAG.getNode(ISD::ADD, SDLoc(Op), ResTy, Op->getOperand(1),
19880b57cec5SDimitry Andric DAG.getNode(ISD::SHL, SDLoc(Op), ResTy,
19890b57cec5SDimitry Andric Op->getOperand(2), Op->getOperand(3)));
19900b57cec5SDimitry Andric }
19910b57cec5SDimitry Andric case Intrinsic::mips_maddv_b:
19920b57cec5SDimitry Andric case Intrinsic::mips_maddv_h:
19930b57cec5SDimitry Andric case Intrinsic::mips_maddv_w:
19940b57cec5SDimitry Andric case Intrinsic::mips_maddv_d: {
19950b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
19960b57cec5SDimitry Andric return DAG.getNode(ISD::ADD, SDLoc(Op), ResTy, Op->getOperand(1),
19970b57cec5SDimitry Andric DAG.getNode(ISD::MUL, SDLoc(Op), ResTy,
19980b57cec5SDimitry Andric Op->getOperand(2), Op->getOperand(3)));
19990b57cec5SDimitry Andric }
20000b57cec5SDimitry Andric case Intrinsic::mips_max_s_b:
20010b57cec5SDimitry Andric case Intrinsic::mips_max_s_h:
20020b57cec5SDimitry Andric case Intrinsic::mips_max_s_w:
20030b57cec5SDimitry Andric case Intrinsic::mips_max_s_d:
20040b57cec5SDimitry Andric return DAG.getNode(ISD::SMAX, DL, Op->getValueType(0),
20050b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2));
20060b57cec5SDimitry Andric case Intrinsic::mips_max_u_b:
20070b57cec5SDimitry Andric case Intrinsic::mips_max_u_h:
20080b57cec5SDimitry Andric case Intrinsic::mips_max_u_w:
20090b57cec5SDimitry Andric case Intrinsic::mips_max_u_d:
20100b57cec5SDimitry Andric return DAG.getNode(ISD::UMAX, DL, Op->getValueType(0),
20110b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2));
20120b57cec5SDimitry Andric case Intrinsic::mips_maxi_s_b:
20130b57cec5SDimitry Andric case Intrinsic::mips_maxi_s_h:
20140b57cec5SDimitry Andric case Intrinsic::mips_maxi_s_w:
20150b57cec5SDimitry Andric case Intrinsic::mips_maxi_s_d:
20160b57cec5SDimitry Andric return DAG.getNode(ISD::SMAX, DL, Op->getValueType(0),
20170b57cec5SDimitry Andric Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG, true));
20180b57cec5SDimitry Andric case Intrinsic::mips_maxi_u_b:
20190b57cec5SDimitry Andric case Intrinsic::mips_maxi_u_h:
20200b57cec5SDimitry Andric case Intrinsic::mips_maxi_u_w:
20210b57cec5SDimitry Andric case Intrinsic::mips_maxi_u_d:
20220b57cec5SDimitry Andric return DAG.getNode(ISD::UMAX, DL, Op->getValueType(0),
20230b57cec5SDimitry Andric Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
20240b57cec5SDimitry Andric case Intrinsic::mips_min_s_b:
20250b57cec5SDimitry Andric case Intrinsic::mips_min_s_h:
20260b57cec5SDimitry Andric case Intrinsic::mips_min_s_w:
20270b57cec5SDimitry Andric case Intrinsic::mips_min_s_d:
20280b57cec5SDimitry Andric return DAG.getNode(ISD::SMIN, DL, Op->getValueType(0),
20290b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2));
20300b57cec5SDimitry Andric case Intrinsic::mips_min_u_b:
20310b57cec5SDimitry Andric case Intrinsic::mips_min_u_h:
20320b57cec5SDimitry Andric case Intrinsic::mips_min_u_w:
20330b57cec5SDimitry Andric case Intrinsic::mips_min_u_d:
20340b57cec5SDimitry Andric return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0),
20350b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2));
20360b57cec5SDimitry Andric case Intrinsic::mips_mini_s_b:
20370b57cec5SDimitry Andric case Intrinsic::mips_mini_s_h:
20380b57cec5SDimitry Andric case Intrinsic::mips_mini_s_w:
20390b57cec5SDimitry Andric case Intrinsic::mips_mini_s_d:
20400b57cec5SDimitry Andric return DAG.getNode(ISD::SMIN, DL, Op->getValueType(0),
20410b57cec5SDimitry Andric Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG, true));
20420b57cec5SDimitry Andric case Intrinsic::mips_mini_u_b:
20430b57cec5SDimitry Andric case Intrinsic::mips_mini_u_h:
20440b57cec5SDimitry Andric case Intrinsic::mips_mini_u_w:
20450b57cec5SDimitry Andric case Intrinsic::mips_mini_u_d:
20460b57cec5SDimitry Andric return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0),
20470b57cec5SDimitry Andric Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
20480b57cec5SDimitry Andric case Intrinsic::mips_mod_s_b:
20490b57cec5SDimitry Andric case Intrinsic::mips_mod_s_h:
20500b57cec5SDimitry Andric case Intrinsic::mips_mod_s_w:
20510b57cec5SDimitry Andric case Intrinsic::mips_mod_s_d:
20520b57cec5SDimitry Andric return DAG.getNode(ISD::SREM, DL, Op->getValueType(0), Op->getOperand(1),
20530b57cec5SDimitry Andric Op->getOperand(2));
20540b57cec5SDimitry Andric case Intrinsic::mips_mod_u_b:
20550b57cec5SDimitry Andric case Intrinsic::mips_mod_u_h:
20560b57cec5SDimitry Andric case Intrinsic::mips_mod_u_w:
20570b57cec5SDimitry Andric case Intrinsic::mips_mod_u_d:
20580b57cec5SDimitry Andric return DAG.getNode(ISD::UREM, DL, Op->getValueType(0), Op->getOperand(1),
20590b57cec5SDimitry Andric Op->getOperand(2));
20600b57cec5SDimitry Andric case Intrinsic::mips_mulv_b:
20610b57cec5SDimitry Andric case Intrinsic::mips_mulv_h:
20620b57cec5SDimitry Andric case Intrinsic::mips_mulv_w:
20630b57cec5SDimitry Andric case Intrinsic::mips_mulv_d:
20640b57cec5SDimitry Andric return DAG.getNode(ISD::MUL, DL, Op->getValueType(0), Op->getOperand(1),
20650b57cec5SDimitry Andric Op->getOperand(2));
20660b57cec5SDimitry Andric case Intrinsic::mips_msubv_b:
20670b57cec5SDimitry Andric case Intrinsic::mips_msubv_h:
20680b57cec5SDimitry Andric case Intrinsic::mips_msubv_w:
20690b57cec5SDimitry Andric case Intrinsic::mips_msubv_d: {
20700b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
20710b57cec5SDimitry Andric return DAG.getNode(ISD::SUB, SDLoc(Op), ResTy, Op->getOperand(1),
20720b57cec5SDimitry Andric DAG.getNode(ISD::MUL, SDLoc(Op), ResTy,
20730b57cec5SDimitry Andric Op->getOperand(2), Op->getOperand(3)));
20740b57cec5SDimitry Andric }
20750b57cec5SDimitry Andric case Intrinsic::mips_nlzc_b:
20760b57cec5SDimitry Andric case Intrinsic::mips_nlzc_h:
20770b57cec5SDimitry Andric case Intrinsic::mips_nlzc_w:
20780b57cec5SDimitry Andric case Intrinsic::mips_nlzc_d:
20790b57cec5SDimitry Andric return DAG.getNode(ISD::CTLZ, DL, Op->getValueType(0), Op->getOperand(1));
20800b57cec5SDimitry Andric case Intrinsic::mips_nor_v: {
20810b57cec5SDimitry Andric SDValue Res = DAG.getNode(ISD::OR, DL, Op->getValueType(0),
20820b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2));
20830b57cec5SDimitry Andric return DAG.getNOT(DL, Res, Res->getValueType(0));
20840b57cec5SDimitry Andric }
20850b57cec5SDimitry Andric case Intrinsic::mips_nori_b: {
20860b57cec5SDimitry Andric SDValue Res = DAG.getNode(ISD::OR, DL, Op->getValueType(0),
20870b57cec5SDimitry Andric Op->getOperand(1),
20880b57cec5SDimitry Andric lowerMSASplatImm(Op, 2, DAG));
20890b57cec5SDimitry Andric return DAG.getNOT(DL, Res, Res->getValueType(0));
20900b57cec5SDimitry Andric }
20910b57cec5SDimitry Andric case Intrinsic::mips_or_v:
20920b57cec5SDimitry Andric return DAG.getNode(ISD::OR, DL, Op->getValueType(0), Op->getOperand(1),
20930b57cec5SDimitry Andric Op->getOperand(2));
20940b57cec5SDimitry Andric case Intrinsic::mips_ori_b:
20950b57cec5SDimitry Andric return DAG.getNode(ISD::OR, DL, Op->getValueType(0),
20960b57cec5SDimitry Andric Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
20970b57cec5SDimitry Andric case Intrinsic::mips_pckev_b:
20980b57cec5SDimitry Andric case Intrinsic::mips_pckev_h:
20990b57cec5SDimitry Andric case Intrinsic::mips_pckev_w:
21000b57cec5SDimitry Andric case Intrinsic::mips_pckev_d:
21010b57cec5SDimitry Andric return DAG.getNode(MipsISD::PCKEV, DL, Op->getValueType(0),
21020b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2));
21030b57cec5SDimitry Andric case Intrinsic::mips_pckod_b:
21040b57cec5SDimitry Andric case Intrinsic::mips_pckod_h:
21050b57cec5SDimitry Andric case Intrinsic::mips_pckod_w:
21060b57cec5SDimitry Andric case Intrinsic::mips_pckod_d:
21070b57cec5SDimitry Andric return DAG.getNode(MipsISD::PCKOD, DL, Op->getValueType(0),
21080b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2));
21090b57cec5SDimitry Andric case Intrinsic::mips_pcnt_b:
21100b57cec5SDimitry Andric case Intrinsic::mips_pcnt_h:
21110b57cec5SDimitry Andric case Intrinsic::mips_pcnt_w:
21120b57cec5SDimitry Andric case Intrinsic::mips_pcnt_d:
21130b57cec5SDimitry Andric return DAG.getNode(ISD::CTPOP, DL, Op->getValueType(0), Op->getOperand(1));
21140b57cec5SDimitry Andric case Intrinsic::mips_sat_s_b:
21150b57cec5SDimitry Andric case Intrinsic::mips_sat_s_h:
21160b57cec5SDimitry Andric case Intrinsic::mips_sat_s_w:
21170b57cec5SDimitry Andric case Intrinsic::mips_sat_s_d:
21180b57cec5SDimitry Andric case Intrinsic::mips_sat_u_b:
21190b57cec5SDimitry Andric case Intrinsic::mips_sat_u_h:
21200b57cec5SDimitry Andric case Intrinsic::mips_sat_u_w:
21210b57cec5SDimitry Andric case Intrinsic::mips_sat_u_d: {
21220b57cec5SDimitry Andric // Report an error for out of range values.
21230b57cec5SDimitry Andric int64_t Max;
21240b57cec5SDimitry Andric switch (Intrinsic) {
21250b57cec5SDimitry Andric case Intrinsic::mips_sat_s_b:
21260b57cec5SDimitry Andric case Intrinsic::mips_sat_u_b: Max = 7; break;
21270b57cec5SDimitry Andric case Intrinsic::mips_sat_s_h:
21280b57cec5SDimitry Andric case Intrinsic::mips_sat_u_h: Max = 15; break;
21290b57cec5SDimitry Andric case Intrinsic::mips_sat_s_w:
21300b57cec5SDimitry Andric case Intrinsic::mips_sat_u_w: Max = 31; break;
21310b57cec5SDimitry Andric case Intrinsic::mips_sat_s_d:
21320b57cec5SDimitry Andric case Intrinsic::mips_sat_u_d: Max = 63; break;
21330b57cec5SDimitry Andric default: llvm_unreachable("Unmatched intrinsic");
21340b57cec5SDimitry Andric }
21350b57cec5SDimitry Andric int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
21360b57cec5SDimitry Andric if (Value < 0 || Value > Max)
21370b57cec5SDimitry Andric report_fatal_error("Immediate out of range");
21380b57cec5SDimitry Andric return SDValue();
21390b57cec5SDimitry Andric }
21400b57cec5SDimitry Andric case Intrinsic::mips_shf_b:
21410b57cec5SDimitry Andric case Intrinsic::mips_shf_h:
21420b57cec5SDimitry Andric case Intrinsic::mips_shf_w: {
21430b57cec5SDimitry Andric int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
21440b57cec5SDimitry Andric if (Value < 0 || Value > 255)
21450b57cec5SDimitry Andric report_fatal_error("Immediate out of range");
21460b57cec5SDimitry Andric return DAG.getNode(MipsISD::SHF, DL, Op->getValueType(0),
21470b57cec5SDimitry Andric Op->getOperand(2), Op->getOperand(1));
21480b57cec5SDimitry Andric }
21490b57cec5SDimitry Andric case Intrinsic::mips_sldi_b:
21500b57cec5SDimitry Andric case Intrinsic::mips_sldi_h:
21510b57cec5SDimitry Andric case Intrinsic::mips_sldi_w:
21520b57cec5SDimitry Andric case Intrinsic::mips_sldi_d: {
21530b57cec5SDimitry Andric // Report an error for out of range values.
21540b57cec5SDimitry Andric int64_t Max;
21550b57cec5SDimitry Andric switch (Intrinsic) {
21560b57cec5SDimitry Andric case Intrinsic::mips_sldi_b: Max = 15; break;
21570b57cec5SDimitry Andric case Intrinsic::mips_sldi_h: Max = 7; break;
21580b57cec5SDimitry Andric case Intrinsic::mips_sldi_w: Max = 3; break;
21590b57cec5SDimitry Andric case Intrinsic::mips_sldi_d: Max = 1; break;
21600b57cec5SDimitry Andric default: llvm_unreachable("Unmatched intrinsic");
21610b57cec5SDimitry Andric }
21620b57cec5SDimitry Andric int64_t Value = cast<ConstantSDNode>(Op->getOperand(3))->getSExtValue();
21630b57cec5SDimitry Andric if (Value < 0 || Value > Max)
21640b57cec5SDimitry Andric report_fatal_error("Immediate out of range");
21650b57cec5SDimitry Andric return SDValue();
21660b57cec5SDimitry Andric }
21670b57cec5SDimitry Andric case Intrinsic::mips_sll_b:
21680b57cec5SDimitry Andric case Intrinsic::mips_sll_h:
21690b57cec5SDimitry Andric case Intrinsic::mips_sll_w:
21700b57cec5SDimitry Andric case Intrinsic::mips_sll_d:
21710b57cec5SDimitry Andric return DAG.getNode(ISD::SHL, DL, Op->getValueType(0), Op->getOperand(1),
21720b57cec5SDimitry Andric truncateVecElts(Op, DAG));
21730b57cec5SDimitry Andric case Intrinsic::mips_slli_b:
21740b57cec5SDimitry Andric case Intrinsic::mips_slli_h:
21750b57cec5SDimitry Andric case Intrinsic::mips_slli_w:
21760b57cec5SDimitry Andric case Intrinsic::mips_slli_d:
21770b57cec5SDimitry Andric return DAG.getNode(ISD::SHL, DL, Op->getValueType(0),
21780b57cec5SDimitry Andric Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
21790b57cec5SDimitry Andric case Intrinsic::mips_splat_b:
21800b57cec5SDimitry Andric case Intrinsic::mips_splat_h:
21810b57cec5SDimitry Andric case Intrinsic::mips_splat_w:
21820b57cec5SDimitry Andric case Intrinsic::mips_splat_d:
21830b57cec5SDimitry Andric // We can't lower via VECTOR_SHUFFLE because it requires constant shuffle
21840b57cec5SDimitry Andric // masks, nor can we lower via BUILD_VECTOR & EXTRACT_VECTOR_ELT because
21850b57cec5SDimitry Andric // EXTRACT_VECTOR_ELT can't extract i64's on MIPS32.
21860b57cec5SDimitry Andric // Instead we lower to MipsISD::VSHF and match from there.
21870b57cec5SDimitry Andric return DAG.getNode(MipsISD::VSHF, DL, Op->getValueType(0),
21880b57cec5SDimitry Andric lowerMSASplatZExt(Op, 2, DAG), Op->getOperand(1),
21890b57cec5SDimitry Andric Op->getOperand(1));
21900b57cec5SDimitry Andric case Intrinsic::mips_splati_b:
21910b57cec5SDimitry Andric case Intrinsic::mips_splati_h:
21920b57cec5SDimitry Andric case Intrinsic::mips_splati_w:
21930b57cec5SDimitry Andric case Intrinsic::mips_splati_d:
21940b57cec5SDimitry Andric return DAG.getNode(MipsISD::VSHF, DL, Op->getValueType(0),
21950b57cec5SDimitry Andric lowerMSASplatImm(Op, 2, DAG), Op->getOperand(1),
21960b57cec5SDimitry Andric Op->getOperand(1));
21970b57cec5SDimitry Andric case Intrinsic::mips_sra_b:
21980b57cec5SDimitry Andric case Intrinsic::mips_sra_h:
21990b57cec5SDimitry Andric case Intrinsic::mips_sra_w:
22000b57cec5SDimitry Andric case Intrinsic::mips_sra_d:
22010b57cec5SDimitry Andric return DAG.getNode(ISD::SRA, DL, Op->getValueType(0), Op->getOperand(1),
22020b57cec5SDimitry Andric truncateVecElts(Op, DAG));
22030b57cec5SDimitry Andric case Intrinsic::mips_srai_b:
22040b57cec5SDimitry Andric case Intrinsic::mips_srai_h:
22050b57cec5SDimitry Andric case Intrinsic::mips_srai_w:
22060b57cec5SDimitry Andric case Intrinsic::mips_srai_d:
22070b57cec5SDimitry Andric return DAG.getNode(ISD::SRA, DL, Op->getValueType(0),
22080b57cec5SDimitry Andric Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
22090b57cec5SDimitry Andric case Intrinsic::mips_srari_b:
22100b57cec5SDimitry Andric case Intrinsic::mips_srari_h:
22110b57cec5SDimitry Andric case Intrinsic::mips_srari_w:
22120b57cec5SDimitry Andric case Intrinsic::mips_srari_d: {
22130b57cec5SDimitry Andric // Report an error for out of range values.
22140b57cec5SDimitry Andric int64_t Max;
22150b57cec5SDimitry Andric switch (Intrinsic) {
22160b57cec5SDimitry Andric case Intrinsic::mips_srari_b: Max = 7; break;
22170b57cec5SDimitry Andric case Intrinsic::mips_srari_h: Max = 15; break;
22180b57cec5SDimitry Andric case Intrinsic::mips_srari_w: Max = 31; break;
22190b57cec5SDimitry Andric case Intrinsic::mips_srari_d: Max = 63; break;
22200b57cec5SDimitry Andric default: llvm_unreachable("Unmatched intrinsic");
22210b57cec5SDimitry Andric }
22220b57cec5SDimitry Andric int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
22230b57cec5SDimitry Andric if (Value < 0 || Value > Max)
22240b57cec5SDimitry Andric report_fatal_error("Immediate out of range");
22250b57cec5SDimitry Andric return SDValue();
22260b57cec5SDimitry Andric }
22270b57cec5SDimitry Andric case Intrinsic::mips_srl_b:
22280b57cec5SDimitry Andric case Intrinsic::mips_srl_h:
22290b57cec5SDimitry Andric case Intrinsic::mips_srl_w:
22300b57cec5SDimitry Andric case Intrinsic::mips_srl_d:
22310b57cec5SDimitry Andric return DAG.getNode(ISD::SRL, DL, Op->getValueType(0), Op->getOperand(1),
22320b57cec5SDimitry Andric truncateVecElts(Op, DAG));
22330b57cec5SDimitry Andric case Intrinsic::mips_srli_b:
22340b57cec5SDimitry Andric case Intrinsic::mips_srli_h:
22350b57cec5SDimitry Andric case Intrinsic::mips_srli_w:
22360b57cec5SDimitry Andric case Intrinsic::mips_srli_d:
22370b57cec5SDimitry Andric return DAG.getNode(ISD::SRL, DL, Op->getValueType(0),
22380b57cec5SDimitry Andric Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
22390b57cec5SDimitry Andric case Intrinsic::mips_srlri_b:
22400b57cec5SDimitry Andric case Intrinsic::mips_srlri_h:
22410b57cec5SDimitry Andric case Intrinsic::mips_srlri_w:
22420b57cec5SDimitry Andric case Intrinsic::mips_srlri_d: {
22430b57cec5SDimitry Andric // Report an error for out of range values.
22440b57cec5SDimitry Andric int64_t Max;
22450b57cec5SDimitry Andric switch (Intrinsic) {
22460b57cec5SDimitry Andric case Intrinsic::mips_srlri_b: Max = 7; break;
22470b57cec5SDimitry Andric case Intrinsic::mips_srlri_h: Max = 15; break;
22480b57cec5SDimitry Andric case Intrinsic::mips_srlri_w: Max = 31; break;
22490b57cec5SDimitry Andric case Intrinsic::mips_srlri_d: Max = 63; break;
22500b57cec5SDimitry Andric default: llvm_unreachable("Unmatched intrinsic");
22510b57cec5SDimitry Andric }
22520b57cec5SDimitry Andric int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
22530b57cec5SDimitry Andric if (Value < 0 || Value > Max)
22540b57cec5SDimitry Andric report_fatal_error("Immediate out of range");
22550b57cec5SDimitry Andric return SDValue();
22560b57cec5SDimitry Andric }
22570b57cec5SDimitry Andric case Intrinsic::mips_subv_b:
22580b57cec5SDimitry Andric case Intrinsic::mips_subv_h:
22590b57cec5SDimitry Andric case Intrinsic::mips_subv_w:
22600b57cec5SDimitry Andric case Intrinsic::mips_subv_d:
22610b57cec5SDimitry Andric return DAG.getNode(ISD::SUB, DL, Op->getValueType(0), Op->getOperand(1),
22620b57cec5SDimitry Andric Op->getOperand(2));
22630b57cec5SDimitry Andric case Intrinsic::mips_subvi_b:
22640b57cec5SDimitry Andric case Intrinsic::mips_subvi_h:
22650b57cec5SDimitry Andric case Intrinsic::mips_subvi_w:
22660b57cec5SDimitry Andric case Intrinsic::mips_subvi_d:
22670b57cec5SDimitry Andric return DAG.getNode(ISD::SUB, DL, Op->getValueType(0),
22680b57cec5SDimitry Andric Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
22690b57cec5SDimitry Andric case Intrinsic::mips_vshf_b:
22700b57cec5SDimitry Andric case Intrinsic::mips_vshf_h:
22710b57cec5SDimitry Andric case Intrinsic::mips_vshf_w:
22720b57cec5SDimitry Andric case Intrinsic::mips_vshf_d:
22730b57cec5SDimitry Andric return DAG.getNode(MipsISD::VSHF, DL, Op->getValueType(0),
22740b57cec5SDimitry Andric Op->getOperand(1), Op->getOperand(2), Op->getOperand(3));
22750b57cec5SDimitry Andric case Intrinsic::mips_xor_v:
22760b57cec5SDimitry Andric return DAG.getNode(ISD::XOR, DL, Op->getValueType(0), Op->getOperand(1),
22770b57cec5SDimitry Andric Op->getOperand(2));
22780b57cec5SDimitry Andric case Intrinsic::mips_xori_b:
22790b57cec5SDimitry Andric return DAG.getNode(ISD::XOR, DL, Op->getValueType(0),
22800b57cec5SDimitry Andric Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
22810b57cec5SDimitry Andric case Intrinsic::thread_pointer: {
22820b57cec5SDimitry Andric EVT PtrVT = getPointerTy(DAG.getDataLayout());
22830b57cec5SDimitry Andric return DAG.getNode(MipsISD::ThreadPointer, DL, PtrVT);
22840b57cec5SDimitry Andric }
22850b57cec5SDimitry Andric }
22860b57cec5SDimitry Andric }
22870b57cec5SDimitry Andric
lowerMSALoadIntr(SDValue Op,SelectionDAG & DAG,unsigned Intr,const MipsSubtarget & Subtarget)22880b57cec5SDimitry Andric static SDValue lowerMSALoadIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr,
22890b57cec5SDimitry Andric const MipsSubtarget &Subtarget) {
22900b57cec5SDimitry Andric SDLoc DL(Op);
22910b57cec5SDimitry Andric SDValue ChainIn = Op->getOperand(0);
22920b57cec5SDimitry Andric SDValue Address = Op->getOperand(2);
22930b57cec5SDimitry Andric SDValue Offset = Op->getOperand(3);
22940b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
22950b57cec5SDimitry Andric EVT PtrTy = Address->getValueType(0);
22960b57cec5SDimitry Andric
22970b57cec5SDimitry Andric // For N64 addresses have the underlying type MVT::i64. This intrinsic
22980b57cec5SDimitry Andric // however takes an i32 signed constant offset. The actual type of the
22990b57cec5SDimitry Andric // intrinsic is a scaled signed i10.
23000b57cec5SDimitry Andric if (Subtarget.isABI_N64())
23010b57cec5SDimitry Andric Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset);
23020b57cec5SDimitry Andric
23030b57cec5SDimitry Andric Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset);
23040b57cec5SDimitry Andric return DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(),
2305e8d8bef9SDimitry Andric Align(16));
23060b57cec5SDimitry Andric }
23070b57cec5SDimitry Andric
lowerINTRINSIC_W_CHAIN(SDValue Op,SelectionDAG & DAG) const23080b57cec5SDimitry Andric SDValue MipsSETargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,
23090b57cec5SDimitry Andric SelectionDAG &DAG) const {
2310647cbc5dSDimitry Andric unsigned Intr = Op->getConstantOperandVal(1);
23110b57cec5SDimitry Andric switch (Intr) {
23120b57cec5SDimitry Andric default:
23130b57cec5SDimitry Andric return SDValue();
23140b57cec5SDimitry Andric case Intrinsic::mips_extp:
23150b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::EXTP);
23160b57cec5SDimitry Andric case Intrinsic::mips_extpdp:
23170b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::EXTPDP);
23180b57cec5SDimitry Andric case Intrinsic::mips_extr_w:
23190b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::EXTR_W);
23200b57cec5SDimitry Andric case Intrinsic::mips_extr_r_w:
23210b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::EXTR_R_W);
23220b57cec5SDimitry Andric case Intrinsic::mips_extr_rs_w:
23230b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::EXTR_RS_W);
23240b57cec5SDimitry Andric case Intrinsic::mips_extr_s_h:
23250b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::EXTR_S_H);
23260b57cec5SDimitry Andric case Intrinsic::mips_mthlip:
23270b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::MTHLIP);
23280b57cec5SDimitry Andric case Intrinsic::mips_mulsaq_s_w_ph:
23290b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::MULSAQ_S_W_PH);
23300b57cec5SDimitry Andric case Intrinsic::mips_maq_s_w_phl:
23310b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHL);
23320b57cec5SDimitry Andric case Intrinsic::mips_maq_s_w_phr:
23330b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHR);
23340b57cec5SDimitry Andric case Intrinsic::mips_maq_sa_w_phl:
23350b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHL);
23360b57cec5SDimitry Andric case Intrinsic::mips_maq_sa_w_phr:
23370b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHR);
23380b57cec5SDimitry Andric case Intrinsic::mips_dpaq_s_w_ph:
23390b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_S_W_PH);
23400b57cec5SDimitry Andric case Intrinsic::mips_dpsq_s_w_ph:
23410b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_S_W_PH);
23420b57cec5SDimitry Andric case Intrinsic::mips_dpaq_sa_l_w:
23430b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_SA_L_W);
23440b57cec5SDimitry Andric case Intrinsic::mips_dpsq_sa_l_w:
23450b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_SA_L_W);
23460b57cec5SDimitry Andric case Intrinsic::mips_dpaqx_s_w_ph:
23470b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_S_W_PH);
23480b57cec5SDimitry Andric case Intrinsic::mips_dpaqx_sa_w_ph:
23490b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_SA_W_PH);
23500b57cec5SDimitry Andric case Intrinsic::mips_dpsqx_s_w_ph:
23510b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_S_W_PH);
23520b57cec5SDimitry Andric case Intrinsic::mips_dpsqx_sa_w_ph:
23530b57cec5SDimitry Andric return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_SA_W_PH);
23540b57cec5SDimitry Andric case Intrinsic::mips_ld_b:
23550b57cec5SDimitry Andric case Intrinsic::mips_ld_h:
23560b57cec5SDimitry Andric case Intrinsic::mips_ld_w:
23570b57cec5SDimitry Andric case Intrinsic::mips_ld_d:
23580b57cec5SDimitry Andric return lowerMSALoadIntr(Op, DAG, Intr, Subtarget);
23590b57cec5SDimitry Andric }
23600b57cec5SDimitry Andric }
23610b57cec5SDimitry Andric
lowerMSAStoreIntr(SDValue Op,SelectionDAG & DAG,unsigned Intr,const MipsSubtarget & Subtarget)23620b57cec5SDimitry Andric static SDValue lowerMSAStoreIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr,
23630b57cec5SDimitry Andric const MipsSubtarget &Subtarget) {
23640b57cec5SDimitry Andric SDLoc DL(Op);
23650b57cec5SDimitry Andric SDValue ChainIn = Op->getOperand(0);
23660b57cec5SDimitry Andric SDValue Value = Op->getOperand(2);
23670b57cec5SDimitry Andric SDValue Address = Op->getOperand(3);
23680b57cec5SDimitry Andric SDValue Offset = Op->getOperand(4);
23690b57cec5SDimitry Andric EVT PtrTy = Address->getValueType(0);
23700b57cec5SDimitry Andric
23710b57cec5SDimitry Andric // For N64 addresses have the underlying type MVT::i64. This intrinsic
23720b57cec5SDimitry Andric // however takes an i32 signed constant offset. The actual type of the
23730b57cec5SDimitry Andric // intrinsic is a scaled signed i10.
23740b57cec5SDimitry Andric if (Subtarget.isABI_N64())
23750b57cec5SDimitry Andric Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset);
23760b57cec5SDimitry Andric
23770b57cec5SDimitry Andric Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset);
23780b57cec5SDimitry Andric
23790b57cec5SDimitry Andric return DAG.getStore(ChainIn, DL, Value, Address, MachinePointerInfo(),
2380e8d8bef9SDimitry Andric Align(16));
23810b57cec5SDimitry Andric }
23820b57cec5SDimitry Andric
lowerINTRINSIC_VOID(SDValue Op,SelectionDAG & DAG) const23830b57cec5SDimitry Andric SDValue MipsSETargetLowering::lowerINTRINSIC_VOID(SDValue Op,
23840b57cec5SDimitry Andric SelectionDAG &DAG) const {
2385647cbc5dSDimitry Andric unsigned Intr = Op->getConstantOperandVal(1);
23860b57cec5SDimitry Andric switch (Intr) {
23870b57cec5SDimitry Andric default:
23880b57cec5SDimitry Andric return SDValue();
23890b57cec5SDimitry Andric case Intrinsic::mips_st_b:
23900b57cec5SDimitry Andric case Intrinsic::mips_st_h:
23910b57cec5SDimitry Andric case Intrinsic::mips_st_w:
23920b57cec5SDimitry Andric case Intrinsic::mips_st_d:
23930b57cec5SDimitry Andric return lowerMSAStoreIntr(Op, DAG, Intr, Subtarget);
23940b57cec5SDimitry Andric }
23950b57cec5SDimitry Andric }
23960b57cec5SDimitry Andric
23970b57cec5SDimitry Andric // Lower ISD::EXTRACT_VECTOR_ELT into MipsISD::VEXTRACT_SEXT_ELT.
23980b57cec5SDimitry Andric //
23990b57cec5SDimitry Andric // The non-value bits resulting from ISD::EXTRACT_VECTOR_ELT are undefined. We
24000b57cec5SDimitry Andric // choose to sign-extend but we could have equally chosen zero-extend. The
24010b57cec5SDimitry Andric // DAGCombiner will fold any sign/zero extension of the ISD::EXTRACT_VECTOR_ELT
24020b57cec5SDimitry Andric // result into this node later (possibly changing it to a zero-extend in the
24030b57cec5SDimitry Andric // process).
24040b57cec5SDimitry Andric SDValue MipsSETargetLowering::
lowerEXTRACT_VECTOR_ELT(SDValue Op,SelectionDAG & DAG) const24050b57cec5SDimitry Andric lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const {
24060b57cec5SDimitry Andric SDLoc DL(Op);
24070b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
24080b57cec5SDimitry Andric SDValue Op0 = Op->getOperand(0);
24090b57cec5SDimitry Andric EVT VecTy = Op0->getValueType(0);
24100b57cec5SDimitry Andric
24110b57cec5SDimitry Andric if (!VecTy.is128BitVector())
24120b57cec5SDimitry Andric return SDValue();
24130b57cec5SDimitry Andric
24140b57cec5SDimitry Andric if (ResTy.isInteger()) {
24150b57cec5SDimitry Andric SDValue Op1 = Op->getOperand(1);
24160b57cec5SDimitry Andric EVT EltTy = VecTy.getVectorElementType();
24170b57cec5SDimitry Andric return DAG.getNode(MipsISD::VEXTRACT_SEXT_ELT, DL, ResTy, Op0, Op1,
24180b57cec5SDimitry Andric DAG.getValueType(EltTy));
24190b57cec5SDimitry Andric }
24200b57cec5SDimitry Andric
24210b57cec5SDimitry Andric return Op;
24220b57cec5SDimitry Andric }
24230b57cec5SDimitry Andric
isConstantOrUndef(const SDValue Op)24240b57cec5SDimitry Andric static bool isConstantOrUndef(const SDValue Op) {
24250b57cec5SDimitry Andric if (Op->isUndef())
24260b57cec5SDimitry Andric return true;
24270b57cec5SDimitry Andric if (isa<ConstantSDNode>(Op))
24280b57cec5SDimitry Andric return true;
24290b57cec5SDimitry Andric if (isa<ConstantFPSDNode>(Op))
24300b57cec5SDimitry Andric return true;
24310b57cec5SDimitry Andric return false;
24320b57cec5SDimitry Andric }
24330b57cec5SDimitry Andric
isConstantOrUndefBUILD_VECTOR(const BuildVectorSDNode * Op)24340b57cec5SDimitry Andric static bool isConstantOrUndefBUILD_VECTOR(const BuildVectorSDNode *Op) {
24350b57cec5SDimitry Andric for (unsigned i = 0; i < Op->getNumOperands(); ++i)
24360b57cec5SDimitry Andric if (isConstantOrUndef(Op->getOperand(i)))
24370b57cec5SDimitry Andric return true;
24380b57cec5SDimitry Andric return false;
24390b57cec5SDimitry Andric }
24400b57cec5SDimitry Andric
24410b57cec5SDimitry Andric // Lowers ISD::BUILD_VECTOR into appropriate SelectionDAG nodes for the
24420b57cec5SDimitry Andric // backend.
24430b57cec5SDimitry Andric //
24440b57cec5SDimitry Andric // Lowers according to the following rules:
24450b57cec5SDimitry Andric // - Constant splats are legal as-is as long as the SplatBitSize is a power of
24460b57cec5SDimitry Andric // 2 less than or equal to 64 and the value fits into a signed 10-bit
24470b57cec5SDimitry Andric // immediate
24480b57cec5SDimitry Andric // - Constant splats are lowered to bitconverted BUILD_VECTORs if SplatBitSize
24490b57cec5SDimitry Andric // is a power of 2 less than or equal to 64 and the value does not fit into a
24500b57cec5SDimitry Andric // signed 10-bit immediate
24510b57cec5SDimitry Andric // - Non-constant splats are legal as-is.
24520b57cec5SDimitry Andric // - Non-constant non-splats are lowered to sequences of INSERT_VECTOR_ELT.
24530b57cec5SDimitry Andric // - All others are illegal and must be expanded.
lowerBUILD_VECTOR(SDValue Op,SelectionDAG & DAG) const24540b57cec5SDimitry Andric SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op,
24550b57cec5SDimitry Andric SelectionDAG &DAG) const {
24560b57cec5SDimitry Andric BuildVectorSDNode *Node = cast<BuildVectorSDNode>(Op);
24570b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
24580b57cec5SDimitry Andric SDLoc DL(Op);
24590b57cec5SDimitry Andric APInt SplatValue, SplatUndef;
24600b57cec5SDimitry Andric unsigned SplatBitSize;
24610b57cec5SDimitry Andric bool HasAnyUndefs;
24620b57cec5SDimitry Andric
24630b57cec5SDimitry Andric if (!Subtarget.hasMSA() || !ResTy.is128BitVector())
24640b57cec5SDimitry Andric return SDValue();
24650b57cec5SDimitry Andric
24660b57cec5SDimitry Andric if (Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
24670b57cec5SDimitry Andric HasAnyUndefs, 8,
24680b57cec5SDimitry Andric !Subtarget.isLittle()) && SplatBitSize <= 64) {
24690b57cec5SDimitry Andric // We can only cope with 8, 16, 32, or 64-bit elements
24700b57cec5SDimitry Andric if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
24710b57cec5SDimitry Andric SplatBitSize != 64)
24720b57cec5SDimitry Andric return SDValue();
24730b57cec5SDimitry Andric
24740b57cec5SDimitry Andric // If the value isn't an integer type we will have to bitcast
24750b57cec5SDimitry Andric // from an integer type first. Also, if there are any undefs, we must
24760b57cec5SDimitry Andric // lower them to defined values first.
24770b57cec5SDimitry Andric if (ResTy.isInteger() && !HasAnyUndefs)
24780b57cec5SDimitry Andric return Op;
24790b57cec5SDimitry Andric
24800b57cec5SDimitry Andric EVT ViaVecTy;
24810b57cec5SDimitry Andric
24820b57cec5SDimitry Andric switch (SplatBitSize) {
24830b57cec5SDimitry Andric default:
24840b57cec5SDimitry Andric return SDValue();
24850b57cec5SDimitry Andric case 8:
24860b57cec5SDimitry Andric ViaVecTy = MVT::v16i8;
24870b57cec5SDimitry Andric break;
24880b57cec5SDimitry Andric case 16:
24890b57cec5SDimitry Andric ViaVecTy = MVT::v8i16;
24900b57cec5SDimitry Andric break;
24910b57cec5SDimitry Andric case 32:
24920b57cec5SDimitry Andric ViaVecTy = MVT::v4i32;
24930b57cec5SDimitry Andric break;
24940b57cec5SDimitry Andric case 64:
24950b57cec5SDimitry Andric // There's no fill.d to fall back on for 64-bit values
24960b57cec5SDimitry Andric return SDValue();
24970b57cec5SDimitry Andric }
24980b57cec5SDimitry Andric
24990b57cec5SDimitry Andric // SelectionDAG::getConstant will promote SplatValue appropriately.
25000b57cec5SDimitry Andric SDValue Result = DAG.getConstant(SplatValue, DL, ViaVecTy);
25010b57cec5SDimitry Andric
25020b57cec5SDimitry Andric // Bitcast to the type we originally wanted
25030b57cec5SDimitry Andric if (ViaVecTy != ResTy)
25040b57cec5SDimitry Andric Result = DAG.getNode(ISD::BITCAST, SDLoc(Node), ResTy, Result);
25050b57cec5SDimitry Andric
25060b57cec5SDimitry Andric return Result;
25070b57cec5SDimitry Andric } else if (DAG.isSplatValue(Op, /* AllowUndefs */ false))
25080b57cec5SDimitry Andric return Op;
25090b57cec5SDimitry Andric else if (!isConstantOrUndefBUILD_VECTOR(Node)) {
25100b57cec5SDimitry Andric // Use INSERT_VECTOR_ELT operations rather than expand to stores.
25110b57cec5SDimitry Andric // The resulting code is the same length as the expansion, but it doesn't
25120b57cec5SDimitry Andric // use memory operations
25130b57cec5SDimitry Andric EVT ResTy = Node->getValueType(0);
25140b57cec5SDimitry Andric
25150b57cec5SDimitry Andric assert(ResTy.isVector());
25160b57cec5SDimitry Andric
25170b57cec5SDimitry Andric unsigned NumElts = ResTy.getVectorNumElements();
25180b57cec5SDimitry Andric SDValue Vector = DAG.getUNDEF(ResTy);
25190b57cec5SDimitry Andric for (unsigned i = 0; i < NumElts; ++i) {
25200b57cec5SDimitry Andric Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, ResTy, Vector,
25210b57cec5SDimitry Andric Node->getOperand(i),
25220b57cec5SDimitry Andric DAG.getConstant(i, DL, MVT::i32));
25230b57cec5SDimitry Andric }
25240b57cec5SDimitry Andric return Vector;
25250b57cec5SDimitry Andric }
25260b57cec5SDimitry Andric
25270b57cec5SDimitry Andric return SDValue();
25280b57cec5SDimitry Andric }
25290b57cec5SDimitry Andric
25300b57cec5SDimitry Andric // Lower VECTOR_SHUFFLE into SHF (if possible).
25310b57cec5SDimitry Andric //
25320b57cec5SDimitry Andric // SHF splits the vector into blocks of four elements, then shuffles these
25330b57cec5SDimitry Andric // elements according to a <4 x i2> constant (encoded as an integer immediate).
25340b57cec5SDimitry Andric //
25350b57cec5SDimitry Andric // It is therefore possible to lower into SHF when the mask takes the form:
25360b57cec5SDimitry Andric // <a, b, c, d, a+4, b+4, c+4, d+4, a+8, b+8, c+8, d+8, ...>
25370b57cec5SDimitry Andric // When undef's appear they are treated as if they were whatever value is
25380b57cec5SDimitry Andric // necessary in order to fit the above forms.
25390b57cec5SDimitry Andric //
25400b57cec5SDimitry Andric // For example:
25410b57cec5SDimitry Andric // %2 = shufflevector <8 x i16> %0, <8 x i16> undef,
25420b57cec5SDimitry Andric // <8 x i32> <i32 3, i32 2, i32 1, i32 0,
25430b57cec5SDimitry Andric // i32 7, i32 6, i32 5, i32 4>
25440b57cec5SDimitry Andric // is lowered to:
25450b57cec5SDimitry Andric // (SHF_H $w0, $w1, 27)
25460b57cec5SDimitry Andric // where the 27 comes from:
25470b57cec5SDimitry Andric // 3 + (2 << 2) + (1 << 4) + (0 << 6)
lowerVECTOR_SHUFFLE_SHF(SDValue Op,EVT ResTy,SmallVector<int,16> Indices,SelectionDAG & DAG)25480b57cec5SDimitry Andric static SDValue lowerVECTOR_SHUFFLE_SHF(SDValue Op, EVT ResTy,
25490b57cec5SDimitry Andric SmallVector<int, 16> Indices,
25500b57cec5SDimitry Andric SelectionDAG &DAG) {
25510b57cec5SDimitry Andric int SHFIndices[4] = { -1, -1, -1, -1 };
25520b57cec5SDimitry Andric
25530b57cec5SDimitry Andric if (Indices.size() < 4)
25540b57cec5SDimitry Andric return SDValue();
25550b57cec5SDimitry Andric
25560b57cec5SDimitry Andric for (unsigned i = 0; i < 4; ++i) {
25570b57cec5SDimitry Andric for (unsigned j = i; j < Indices.size(); j += 4) {
25580b57cec5SDimitry Andric int Idx = Indices[j];
25590b57cec5SDimitry Andric
25600b57cec5SDimitry Andric // Convert from vector index to 4-element subvector index
25610b57cec5SDimitry Andric // If an index refers to an element outside of the subvector then give up
25620b57cec5SDimitry Andric if (Idx != -1) {
25630b57cec5SDimitry Andric Idx -= 4 * (j / 4);
25640b57cec5SDimitry Andric if (Idx < 0 || Idx >= 4)
25650b57cec5SDimitry Andric return SDValue();
25660b57cec5SDimitry Andric }
25670b57cec5SDimitry Andric
25680b57cec5SDimitry Andric // If the mask has an undef, replace it with the current index.
25690b57cec5SDimitry Andric // Note that it might still be undef if the current index is also undef
25700b57cec5SDimitry Andric if (SHFIndices[i] == -1)
25710b57cec5SDimitry Andric SHFIndices[i] = Idx;
25720b57cec5SDimitry Andric
25730b57cec5SDimitry Andric // Check that non-undef values are the same as in the mask. If they
25740b57cec5SDimitry Andric // aren't then give up
25750b57cec5SDimitry Andric if (!(Idx == -1 || Idx == SHFIndices[i]))
25760b57cec5SDimitry Andric return SDValue();
25770b57cec5SDimitry Andric }
25780b57cec5SDimitry Andric }
25790b57cec5SDimitry Andric
25800b57cec5SDimitry Andric // Calculate the immediate. Replace any remaining undefs with zero
25810b57cec5SDimitry Andric APInt Imm(32, 0);
25820b57cec5SDimitry Andric for (int i = 3; i >= 0; --i) {
25830b57cec5SDimitry Andric int Idx = SHFIndices[i];
25840b57cec5SDimitry Andric
25850b57cec5SDimitry Andric if (Idx == -1)
25860b57cec5SDimitry Andric Idx = 0;
25870b57cec5SDimitry Andric
25880b57cec5SDimitry Andric Imm <<= 2;
25890b57cec5SDimitry Andric Imm |= Idx & 0x3;
25900b57cec5SDimitry Andric }
25910b57cec5SDimitry Andric
25920b57cec5SDimitry Andric SDLoc DL(Op);
25930b57cec5SDimitry Andric return DAG.getNode(MipsISD::SHF, DL, ResTy,
25948bcb0991SDimitry Andric DAG.getTargetConstant(Imm, DL, MVT::i32),
25958bcb0991SDimitry Andric Op->getOperand(0));
25960b57cec5SDimitry Andric }
25970b57cec5SDimitry Andric
25980b57cec5SDimitry Andric /// Determine whether a range fits a regular pattern of values.
25990b57cec5SDimitry Andric /// This function accounts for the possibility of jumping over the End iterator.
26000b57cec5SDimitry Andric template <typename ValType>
26010b57cec5SDimitry Andric static bool
fitsRegularPattern(typename SmallVectorImpl<ValType>::const_iterator Begin,unsigned CheckStride,typename SmallVectorImpl<ValType>::const_iterator End,ValType ExpectedIndex,unsigned ExpectedIndexStride)26020b57cec5SDimitry Andric fitsRegularPattern(typename SmallVectorImpl<ValType>::const_iterator Begin,
26030b57cec5SDimitry Andric unsigned CheckStride,
26040b57cec5SDimitry Andric typename SmallVectorImpl<ValType>::const_iterator End,
26050b57cec5SDimitry Andric ValType ExpectedIndex, unsigned ExpectedIndexStride) {
26060b57cec5SDimitry Andric auto &I = Begin;
26070b57cec5SDimitry Andric
26080b57cec5SDimitry Andric while (I != End) {
26090b57cec5SDimitry Andric if (*I != -1 && *I != ExpectedIndex)
26100b57cec5SDimitry Andric return false;
26110b57cec5SDimitry Andric ExpectedIndex += ExpectedIndexStride;
26120b57cec5SDimitry Andric
26130b57cec5SDimitry Andric // Incrementing past End is undefined behaviour so we must increment one
26140b57cec5SDimitry Andric // step at a time and check for End at each step.
26150b57cec5SDimitry Andric for (unsigned n = 0; n < CheckStride && I != End; ++n, ++I)
26160b57cec5SDimitry Andric ; // Empty loop body.
26170b57cec5SDimitry Andric }
26180b57cec5SDimitry Andric return true;
26190b57cec5SDimitry Andric }
26200b57cec5SDimitry Andric
26210b57cec5SDimitry Andric // Determine whether VECTOR_SHUFFLE is a SPLATI.
26220b57cec5SDimitry Andric //
26230b57cec5SDimitry Andric // It is a SPLATI when the mask is:
26240b57cec5SDimitry Andric // <x, x, x, ...>
26250b57cec5SDimitry Andric // where x is any valid index.
26260b57cec5SDimitry Andric //
26270b57cec5SDimitry Andric // When undef's appear in the mask they are treated as if they were whatever
26280b57cec5SDimitry Andric // value is necessary in order to fit the above form.
isVECTOR_SHUFFLE_SPLATI(SDValue Op,EVT ResTy,SmallVector<int,16> Indices,SelectionDAG & DAG)26290b57cec5SDimitry Andric static bool isVECTOR_SHUFFLE_SPLATI(SDValue Op, EVT ResTy,
26300b57cec5SDimitry Andric SmallVector<int, 16> Indices,
26310b57cec5SDimitry Andric SelectionDAG &DAG) {
26320b57cec5SDimitry Andric assert((Indices.size() % 2) == 0);
26330b57cec5SDimitry Andric
26340b57cec5SDimitry Andric int SplatIndex = -1;
26350b57cec5SDimitry Andric for (const auto &V : Indices) {
26360b57cec5SDimitry Andric if (V != -1) {
26370b57cec5SDimitry Andric SplatIndex = V;
26380b57cec5SDimitry Andric break;
26390b57cec5SDimitry Andric }
26400b57cec5SDimitry Andric }
26410b57cec5SDimitry Andric
26420b57cec5SDimitry Andric return fitsRegularPattern<int>(Indices.begin(), 1, Indices.end(), SplatIndex,
26430b57cec5SDimitry Andric 0);
26440b57cec5SDimitry Andric }
26450b57cec5SDimitry Andric
26460b57cec5SDimitry Andric // Lower VECTOR_SHUFFLE into ILVEV (if possible).
26470b57cec5SDimitry Andric //
26480b57cec5SDimitry Andric // ILVEV interleaves the even elements from each vector.
26490b57cec5SDimitry Andric //
26500b57cec5SDimitry Andric // It is possible to lower into ILVEV when the mask consists of two of the
26510b57cec5SDimitry Andric // following forms interleaved:
26520b57cec5SDimitry Andric // <0, 2, 4, ...>
26530b57cec5SDimitry Andric // <n, n+2, n+4, ...>
26540b57cec5SDimitry Andric // where n is the number of elements in the vector.
26550b57cec5SDimitry Andric // For example:
26560b57cec5SDimitry Andric // <0, 0, 2, 2, 4, 4, ...>
26570b57cec5SDimitry Andric // <0, n, 2, n+2, 4, n+4, ...>
26580b57cec5SDimitry Andric //
26590b57cec5SDimitry Andric // When undef's appear in the mask they are treated as if they were whatever
26600b57cec5SDimitry Andric // value is necessary in order to fit the above forms.
lowerVECTOR_SHUFFLE_ILVEV(SDValue Op,EVT ResTy,SmallVector<int,16> Indices,SelectionDAG & DAG)26610b57cec5SDimitry Andric static SDValue lowerVECTOR_SHUFFLE_ILVEV(SDValue Op, EVT ResTy,
26620b57cec5SDimitry Andric SmallVector<int, 16> Indices,
26630b57cec5SDimitry Andric SelectionDAG &DAG) {
26640b57cec5SDimitry Andric assert((Indices.size() % 2) == 0);
26650b57cec5SDimitry Andric
26660b57cec5SDimitry Andric SDValue Wt;
26670b57cec5SDimitry Andric SDValue Ws;
26680b57cec5SDimitry Andric const auto &Begin = Indices.begin();
26690b57cec5SDimitry Andric const auto &End = Indices.end();
26700b57cec5SDimitry Andric
26710b57cec5SDimitry Andric // Check even elements are taken from the even elements of one half or the
26720b57cec5SDimitry Andric // other and pick an operand accordingly.
26730b57cec5SDimitry Andric if (fitsRegularPattern<int>(Begin, 2, End, 0, 2))
26740b57cec5SDimitry Andric Wt = Op->getOperand(0);
26750b57cec5SDimitry Andric else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size(), 2))
26760b57cec5SDimitry Andric Wt = Op->getOperand(1);
26770b57cec5SDimitry Andric else
26780b57cec5SDimitry Andric return SDValue();
26790b57cec5SDimitry Andric
26800b57cec5SDimitry Andric // Check odd elements are taken from the even elements of one half or the
26810b57cec5SDimitry Andric // other and pick an operand accordingly.
26820b57cec5SDimitry Andric if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 2))
26830b57cec5SDimitry Andric Ws = Op->getOperand(0);
26840b57cec5SDimitry Andric else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size(), 2))
26850b57cec5SDimitry Andric Ws = Op->getOperand(1);
26860b57cec5SDimitry Andric else
26870b57cec5SDimitry Andric return SDValue();
26880b57cec5SDimitry Andric
26890b57cec5SDimitry Andric return DAG.getNode(MipsISD::ILVEV, SDLoc(Op), ResTy, Ws, Wt);
26900b57cec5SDimitry Andric }
26910b57cec5SDimitry Andric
26920b57cec5SDimitry Andric // Lower VECTOR_SHUFFLE into ILVOD (if possible).
26930b57cec5SDimitry Andric //
26940b57cec5SDimitry Andric // ILVOD interleaves the odd elements from each vector.
26950b57cec5SDimitry Andric //
26960b57cec5SDimitry Andric // It is possible to lower into ILVOD when the mask consists of two of the
26970b57cec5SDimitry Andric // following forms interleaved:
26980b57cec5SDimitry Andric // <1, 3, 5, ...>
26990b57cec5SDimitry Andric // <n+1, n+3, n+5, ...>
27000b57cec5SDimitry Andric // where n is the number of elements in the vector.
27010b57cec5SDimitry Andric // For example:
27020b57cec5SDimitry Andric // <1, 1, 3, 3, 5, 5, ...>
27030b57cec5SDimitry Andric // <1, n+1, 3, n+3, 5, n+5, ...>
27040b57cec5SDimitry Andric //
27050b57cec5SDimitry Andric // When undef's appear in the mask they are treated as if they were whatever
27060b57cec5SDimitry Andric // value is necessary in order to fit the above forms.
lowerVECTOR_SHUFFLE_ILVOD(SDValue Op,EVT ResTy,SmallVector<int,16> Indices,SelectionDAG & DAG)27070b57cec5SDimitry Andric static SDValue lowerVECTOR_SHUFFLE_ILVOD(SDValue Op, EVT ResTy,
27080b57cec5SDimitry Andric SmallVector<int, 16> Indices,
27090b57cec5SDimitry Andric SelectionDAG &DAG) {
27100b57cec5SDimitry Andric assert((Indices.size() % 2) == 0);
27110b57cec5SDimitry Andric
27120b57cec5SDimitry Andric SDValue Wt;
27130b57cec5SDimitry Andric SDValue Ws;
27140b57cec5SDimitry Andric const auto &Begin = Indices.begin();
27150b57cec5SDimitry Andric const auto &End = Indices.end();
27160b57cec5SDimitry Andric
27170b57cec5SDimitry Andric // Check even elements are taken from the odd elements of one half or the
27180b57cec5SDimitry Andric // other and pick an operand accordingly.
27190b57cec5SDimitry Andric if (fitsRegularPattern<int>(Begin, 2, End, 1, 2))
27200b57cec5SDimitry Andric Wt = Op->getOperand(0);
27210b57cec5SDimitry Andric else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size() + 1, 2))
27220b57cec5SDimitry Andric Wt = Op->getOperand(1);
27230b57cec5SDimitry Andric else
27240b57cec5SDimitry Andric return SDValue();
27250b57cec5SDimitry Andric
27260b57cec5SDimitry Andric // Check odd elements are taken from the odd elements of one half or the
27270b57cec5SDimitry Andric // other and pick an operand accordingly.
27280b57cec5SDimitry Andric if (fitsRegularPattern<int>(Begin + 1, 2, End, 1, 2))
27290b57cec5SDimitry Andric Ws = Op->getOperand(0);
27300b57cec5SDimitry Andric else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size() + 1, 2))
27310b57cec5SDimitry Andric Ws = Op->getOperand(1);
27320b57cec5SDimitry Andric else
27330b57cec5SDimitry Andric return SDValue();
27340b57cec5SDimitry Andric
27350b57cec5SDimitry Andric return DAG.getNode(MipsISD::ILVOD, SDLoc(Op), ResTy, Wt, Ws);
27360b57cec5SDimitry Andric }
27370b57cec5SDimitry Andric
27380b57cec5SDimitry Andric // Lower VECTOR_SHUFFLE into ILVR (if possible).
27390b57cec5SDimitry Andric //
27400b57cec5SDimitry Andric // ILVR interleaves consecutive elements from the right (lowest-indexed) half of
27410b57cec5SDimitry Andric // each vector.
27420b57cec5SDimitry Andric //
27430b57cec5SDimitry Andric // It is possible to lower into ILVR when the mask consists of two of the
27440b57cec5SDimitry Andric // following forms interleaved:
27450b57cec5SDimitry Andric // <0, 1, 2, ...>
27460b57cec5SDimitry Andric // <n, n+1, n+2, ...>
27470b57cec5SDimitry Andric // where n is the number of elements in the vector.
27480b57cec5SDimitry Andric // For example:
27490b57cec5SDimitry Andric // <0, 0, 1, 1, 2, 2, ...>
27500b57cec5SDimitry Andric // <0, n, 1, n+1, 2, n+2, ...>
27510b57cec5SDimitry Andric //
27520b57cec5SDimitry Andric // When undef's appear in the mask they are treated as if they were whatever
27530b57cec5SDimitry Andric // value is necessary in order to fit the above forms.
lowerVECTOR_SHUFFLE_ILVR(SDValue Op,EVT ResTy,SmallVector<int,16> Indices,SelectionDAG & DAG)27540b57cec5SDimitry Andric static SDValue lowerVECTOR_SHUFFLE_ILVR(SDValue Op, EVT ResTy,
27550b57cec5SDimitry Andric SmallVector<int, 16> Indices,
27560b57cec5SDimitry Andric SelectionDAG &DAG) {
27570b57cec5SDimitry Andric assert((Indices.size() % 2) == 0);
27580b57cec5SDimitry Andric
27590b57cec5SDimitry Andric SDValue Wt;
27600b57cec5SDimitry Andric SDValue Ws;
27610b57cec5SDimitry Andric const auto &Begin = Indices.begin();
27620b57cec5SDimitry Andric const auto &End = Indices.end();
27630b57cec5SDimitry Andric
27640b57cec5SDimitry Andric // Check even elements are taken from the right (lowest-indexed) elements of
27650b57cec5SDimitry Andric // one half or the other and pick an operand accordingly.
27660b57cec5SDimitry Andric if (fitsRegularPattern<int>(Begin, 2, End, 0, 1))
27670b57cec5SDimitry Andric Wt = Op->getOperand(0);
27680b57cec5SDimitry Andric else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size(), 1))
27690b57cec5SDimitry Andric Wt = Op->getOperand(1);
27700b57cec5SDimitry Andric else
27710b57cec5SDimitry Andric return SDValue();
27720b57cec5SDimitry Andric
27730b57cec5SDimitry Andric // Check odd elements are taken from the right (lowest-indexed) elements of
27740b57cec5SDimitry Andric // one half or the other and pick an operand accordingly.
27750b57cec5SDimitry Andric if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 1))
27760b57cec5SDimitry Andric Ws = Op->getOperand(0);
27770b57cec5SDimitry Andric else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size(), 1))
27780b57cec5SDimitry Andric Ws = Op->getOperand(1);
27790b57cec5SDimitry Andric else
27800b57cec5SDimitry Andric return SDValue();
27810b57cec5SDimitry Andric
27820b57cec5SDimitry Andric return DAG.getNode(MipsISD::ILVR, SDLoc(Op), ResTy, Ws, Wt);
27830b57cec5SDimitry Andric }
27840b57cec5SDimitry Andric
27850b57cec5SDimitry Andric // Lower VECTOR_SHUFFLE into ILVL (if possible).
27860b57cec5SDimitry Andric //
27870b57cec5SDimitry Andric // ILVL interleaves consecutive elements from the left (highest-indexed) half
27880b57cec5SDimitry Andric // of each vector.
27890b57cec5SDimitry Andric //
27900b57cec5SDimitry Andric // It is possible to lower into ILVL when the mask consists of two of the
27910b57cec5SDimitry Andric // following forms interleaved:
27920b57cec5SDimitry Andric // <x, x+1, x+2, ...>
27930b57cec5SDimitry Andric // <n+x, n+x+1, n+x+2, ...>
27940b57cec5SDimitry Andric // where n is the number of elements in the vector and x is half n.
27950b57cec5SDimitry Andric // For example:
27960b57cec5SDimitry Andric // <x, x, x+1, x+1, x+2, x+2, ...>
27970b57cec5SDimitry Andric // <x, n+x, x+1, n+x+1, x+2, n+x+2, ...>
27980b57cec5SDimitry Andric //
27990b57cec5SDimitry Andric // When undef's appear in the mask they are treated as if they were whatever
28000b57cec5SDimitry Andric // value is necessary in order to fit the above forms.
lowerVECTOR_SHUFFLE_ILVL(SDValue Op,EVT ResTy,SmallVector<int,16> Indices,SelectionDAG & DAG)28010b57cec5SDimitry Andric static SDValue lowerVECTOR_SHUFFLE_ILVL(SDValue Op, EVT ResTy,
28020b57cec5SDimitry Andric SmallVector<int, 16> Indices,
28030b57cec5SDimitry Andric SelectionDAG &DAG) {
28040b57cec5SDimitry Andric assert((Indices.size() % 2) == 0);
28050b57cec5SDimitry Andric
28060b57cec5SDimitry Andric unsigned HalfSize = Indices.size() / 2;
28070b57cec5SDimitry Andric SDValue Wt;
28080b57cec5SDimitry Andric SDValue Ws;
28090b57cec5SDimitry Andric const auto &Begin = Indices.begin();
28100b57cec5SDimitry Andric const auto &End = Indices.end();
28110b57cec5SDimitry Andric
28120b57cec5SDimitry Andric // Check even elements are taken from the left (highest-indexed) elements of
28130b57cec5SDimitry Andric // one half or the other and pick an operand accordingly.
28140b57cec5SDimitry Andric if (fitsRegularPattern<int>(Begin, 2, End, HalfSize, 1))
28150b57cec5SDimitry Andric Wt = Op->getOperand(0);
28160b57cec5SDimitry Andric else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size() + HalfSize, 1))
28170b57cec5SDimitry Andric Wt = Op->getOperand(1);
28180b57cec5SDimitry Andric else
28190b57cec5SDimitry Andric return SDValue();
28200b57cec5SDimitry Andric
28210b57cec5SDimitry Andric // Check odd elements are taken from the left (highest-indexed) elements of
28220b57cec5SDimitry Andric // one half or the other and pick an operand accordingly.
28230b57cec5SDimitry Andric if (fitsRegularPattern<int>(Begin + 1, 2, End, HalfSize, 1))
28240b57cec5SDimitry Andric Ws = Op->getOperand(0);
28250b57cec5SDimitry Andric else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size() + HalfSize,
28260b57cec5SDimitry Andric 1))
28270b57cec5SDimitry Andric Ws = Op->getOperand(1);
28280b57cec5SDimitry Andric else
28290b57cec5SDimitry Andric return SDValue();
28300b57cec5SDimitry Andric
28310b57cec5SDimitry Andric return DAG.getNode(MipsISD::ILVL, SDLoc(Op), ResTy, Ws, Wt);
28320b57cec5SDimitry Andric }
28330b57cec5SDimitry Andric
28340b57cec5SDimitry Andric // Lower VECTOR_SHUFFLE into PCKEV (if possible).
28350b57cec5SDimitry Andric //
28360b57cec5SDimitry Andric // PCKEV copies the even elements of each vector into the result vector.
28370b57cec5SDimitry Andric //
28380b57cec5SDimitry Andric // It is possible to lower into PCKEV when the mask consists of two of the
28390b57cec5SDimitry Andric // following forms concatenated:
28400b57cec5SDimitry Andric // <0, 2, 4, ...>
28410b57cec5SDimitry Andric // <n, n+2, n+4, ...>
28420b57cec5SDimitry Andric // where n is the number of elements in the vector.
28430b57cec5SDimitry Andric // For example:
28440b57cec5SDimitry Andric // <0, 2, 4, ..., 0, 2, 4, ...>
28450b57cec5SDimitry Andric // <0, 2, 4, ..., n, n+2, n+4, ...>
28460b57cec5SDimitry Andric //
28470b57cec5SDimitry Andric // When undef's appear in the mask they are treated as if they were whatever
28480b57cec5SDimitry Andric // value is necessary in order to fit the above forms.
lowerVECTOR_SHUFFLE_PCKEV(SDValue Op,EVT ResTy,SmallVector<int,16> Indices,SelectionDAG & DAG)28490b57cec5SDimitry Andric static SDValue lowerVECTOR_SHUFFLE_PCKEV(SDValue Op, EVT ResTy,
28500b57cec5SDimitry Andric SmallVector<int, 16> Indices,
28510b57cec5SDimitry Andric SelectionDAG &DAG) {
28520b57cec5SDimitry Andric assert((Indices.size() % 2) == 0);
28530b57cec5SDimitry Andric
28540b57cec5SDimitry Andric SDValue Wt;
28550b57cec5SDimitry Andric SDValue Ws;
28560b57cec5SDimitry Andric const auto &Begin = Indices.begin();
28570b57cec5SDimitry Andric const auto &Mid = Indices.begin() + Indices.size() / 2;
28580b57cec5SDimitry Andric const auto &End = Indices.end();
28590b57cec5SDimitry Andric
28600b57cec5SDimitry Andric if (fitsRegularPattern<int>(Begin, 1, Mid, 0, 2))
28610b57cec5SDimitry Andric Wt = Op->getOperand(0);
28620b57cec5SDimitry Andric else if (fitsRegularPattern<int>(Begin, 1, Mid, Indices.size(), 2))
28630b57cec5SDimitry Andric Wt = Op->getOperand(1);
28640b57cec5SDimitry Andric else
28650b57cec5SDimitry Andric return SDValue();
28660b57cec5SDimitry Andric
28670b57cec5SDimitry Andric if (fitsRegularPattern<int>(Mid, 1, End, 0, 2))
28680b57cec5SDimitry Andric Ws = Op->getOperand(0);
28690b57cec5SDimitry Andric else if (fitsRegularPattern<int>(Mid, 1, End, Indices.size(), 2))
28700b57cec5SDimitry Andric Ws = Op->getOperand(1);
28710b57cec5SDimitry Andric else
28720b57cec5SDimitry Andric return SDValue();
28730b57cec5SDimitry Andric
28740b57cec5SDimitry Andric return DAG.getNode(MipsISD::PCKEV, SDLoc(Op), ResTy, Ws, Wt);
28750b57cec5SDimitry Andric }
28760b57cec5SDimitry Andric
28770b57cec5SDimitry Andric // Lower VECTOR_SHUFFLE into PCKOD (if possible).
28780b57cec5SDimitry Andric //
28790b57cec5SDimitry Andric // PCKOD copies the odd elements of each vector into the result vector.
28800b57cec5SDimitry Andric //
28810b57cec5SDimitry Andric // It is possible to lower into PCKOD when the mask consists of two of the
28820b57cec5SDimitry Andric // following forms concatenated:
28830b57cec5SDimitry Andric // <1, 3, 5, ...>
28840b57cec5SDimitry Andric // <n+1, n+3, n+5, ...>
28850b57cec5SDimitry Andric // where n is the number of elements in the vector.
28860b57cec5SDimitry Andric // For example:
28870b57cec5SDimitry Andric // <1, 3, 5, ..., 1, 3, 5, ...>
28880b57cec5SDimitry Andric // <1, 3, 5, ..., n+1, n+3, n+5, ...>
28890b57cec5SDimitry Andric //
28900b57cec5SDimitry Andric // When undef's appear in the mask they are treated as if they were whatever
28910b57cec5SDimitry Andric // value is necessary in order to fit the above forms.
lowerVECTOR_SHUFFLE_PCKOD(SDValue Op,EVT ResTy,SmallVector<int,16> Indices,SelectionDAG & DAG)28920b57cec5SDimitry Andric static SDValue lowerVECTOR_SHUFFLE_PCKOD(SDValue Op, EVT ResTy,
28930b57cec5SDimitry Andric SmallVector<int, 16> Indices,
28940b57cec5SDimitry Andric SelectionDAG &DAG) {
28950b57cec5SDimitry Andric assert((Indices.size() % 2) == 0);
28960b57cec5SDimitry Andric
28970b57cec5SDimitry Andric SDValue Wt;
28980b57cec5SDimitry Andric SDValue Ws;
28990b57cec5SDimitry Andric const auto &Begin = Indices.begin();
29000b57cec5SDimitry Andric const auto &Mid = Indices.begin() + Indices.size() / 2;
29010b57cec5SDimitry Andric const auto &End = Indices.end();
29020b57cec5SDimitry Andric
29030b57cec5SDimitry Andric if (fitsRegularPattern<int>(Begin, 1, Mid, 1, 2))
29040b57cec5SDimitry Andric Wt = Op->getOperand(0);
29050b57cec5SDimitry Andric else if (fitsRegularPattern<int>(Begin, 1, Mid, Indices.size() + 1, 2))
29060b57cec5SDimitry Andric Wt = Op->getOperand(1);
29070b57cec5SDimitry Andric else
29080b57cec5SDimitry Andric return SDValue();
29090b57cec5SDimitry Andric
29100b57cec5SDimitry Andric if (fitsRegularPattern<int>(Mid, 1, End, 1, 2))
29110b57cec5SDimitry Andric Ws = Op->getOperand(0);
29120b57cec5SDimitry Andric else if (fitsRegularPattern<int>(Mid, 1, End, Indices.size() + 1, 2))
29130b57cec5SDimitry Andric Ws = Op->getOperand(1);
29140b57cec5SDimitry Andric else
29150b57cec5SDimitry Andric return SDValue();
29160b57cec5SDimitry Andric
29170b57cec5SDimitry Andric return DAG.getNode(MipsISD::PCKOD, SDLoc(Op), ResTy, Ws, Wt);
29180b57cec5SDimitry Andric }
29190b57cec5SDimitry Andric
29200b57cec5SDimitry Andric // Lower VECTOR_SHUFFLE into VSHF.
29210b57cec5SDimitry Andric //
29220b57cec5SDimitry Andric // This mostly consists of converting the shuffle indices in Indices into a
29230b57cec5SDimitry Andric // BUILD_VECTOR and adding it as an operand to the resulting VSHF. There is
29240b57cec5SDimitry Andric // also code to eliminate unused operands of the VECTOR_SHUFFLE. For example,
29250b57cec5SDimitry Andric // if the type is v8i16 and all the indices are less than 8 then the second
29260b57cec5SDimitry Andric // operand is unused and can be replaced with anything. We choose to replace it
29270b57cec5SDimitry Andric // with the used operand since this reduces the number of instructions overall.
lowerVECTOR_SHUFFLE_VSHF(SDValue Op,EVT ResTy,const SmallVector<int,16> & Indices,SelectionDAG & DAG)29280b57cec5SDimitry Andric static SDValue lowerVECTOR_SHUFFLE_VSHF(SDValue Op, EVT ResTy,
292904eeddc0SDimitry Andric const SmallVector<int, 16> &Indices,
29300b57cec5SDimitry Andric SelectionDAG &DAG) {
29310b57cec5SDimitry Andric SmallVector<SDValue, 16> Ops;
29320b57cec5SDimitry Andric SDValue Op0;
29330b57cec5SDimitry Andric SDValue Op1;
29340b57cec5SDimitry Andric EVT MaskVecTy = ResTy.changeVectorElementTypeToInteger();
29350b57cec5SDimitry Andric EVT MaskEltTy = MaskVecTy.getVectorElementType();
29360b57cec5SDimitry Andric bool Using1stVec = false;
29370b57cec5SDimitry Andric bool Using2ndVec = false;
29380b57cec5SDimitry Andric SDLoc DL(Op);
29390b57cec5SDimitry Andric int ResTyNumElts = ResTy.getVectorNumElements();
29400b57cec5SDimitry Andric
29410b57cec5SDimitry Andric for (int i = 0; i < ResTyNumElts; ++i) {
29420b57cec5SDimitry Andric // Idx == -1 means UNDEF
29430b57cec5SDimitry Andric int Idx = Indices[i];
29440b57cec5SDimitry Andric
29450b57cec5SDimitry Andric if (0 <= Idx && Idx < ResTyNumElts)
29460b57cec5SDimitry Andric Using1stVec = true;
29470b57cec5SDimitry Andric if (ResTyNumElts <= Idx && Idx < ResTyNumElts * 2)
29480b57cec5SDimitry Andric Using2ndVec = true;
29490b57cec5SDimitry Andric }
29500b57cec5SDimitry Andric
295104eeddc0SDimitry Andric for (int Idx : Indices)
295204eeddc0SDimitry Andric Ops.push_back(DAG.getTargetConstant(Idx, DL, MaskEltTy));
29530b57cec5SDimitry Andric
29540b57cec5SDimitry Andric SDValue MaskVec = DAG.getBuildVector(MaskVecTy, DL, Ops);
29550b57cec5SDimitry Andric
29560b57cec5SDimitry Andric if (Using1stVec && Using2ndVec) {
29570b57cec5SDimitry Andric Op0 = Op->getOperand(0);
29580b57cec5SDimitry Andric Op1 = Op->getOperand(1);
29590b57cec5SDimitry Andric } else if (Using1stVec)
29600b57cec5SDimitry Andric Op0 = Op1 = Op->getOperand(0);
29610b57cec5SDimitry Andric else if (Using2ndVec)
29620b57cec5SDimitry Andric Op0 = Op1 = Op->getOperand(1);
29630b57cec5SDimitry Andric else
29640b57cec5SDimitry Andric llvm_unreachable("shuffle vector mask references neither vector operand?");
29650b57cec5SDimitry Andric
29660b57cec5SDimitry Andric // VECTOR_SHUFFLE concatenates the vectors in an vectorwise fashion.
29670b57cec5SDimitry Andric // <0b00, 0b01> + <0b10, 0b11> -> <0b00, 0b01, 0b10, 0b11>
29680b57cec5SDimitry Andric // VSHF concatenates the vectors in a bitwise fashion:
29690b57cec5SDimitry Andric // <0b00, 0b01> + <0b10, 0b11> ->
29700b57cec5SDimitry Andric // 0b0100 + 0b1110 -> 0b01001110
29710b57cec5SDimitry Andric // <0b10, 0b11, 0b00, 0b01>
29720b57cec5SDimitry Andric // We must therefore swap the operands to get the correct result.
29730b57cec5SDimitry Andric return DAG.getNode(MipsISD::VSHF, DL, ResTy, MaskVec, Op1, Op0);
29740b57cec5SDimitry Andric }
29750b57cec5SDimitry Andric
29760b57cec5SDimitry Andric // Lower VECTOR_SHUFFLE into one of a number of instructions depending on the
29770b57cec5SDimitry Andric // indices in the shuffle.
lowerVECTOR_SHUFFLE(SDValue Op,SelectionDAG & DAG) const29780b57cec5SDimitry Andric SDValue MipsSETargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
29790b57cec5SDimitry Andric SelectionDAG &DAG) const {
29800b57cec5SDimitry Andric ShuffleVectorSDNode *Node = cast<ShuffleVectorSDNode>(Op);
29810b57cec5SDimitry Andric EVT ResTy = Op->getValueType(0);
29820b57cec5SDimitry Andric
29830b57cec5SDimitry Andric if (!ResTy.is128BitVector())
29840b57cec5SDimitry Andric return SDValue();
29850b57cec5SDimitry Andric
29860b57cec5SDimitry Andric int ResTyNumElts = ResTy.getVectorNumElements();
29870b57cec5SDimitry Andric SmallVector<int, 16> Indices;
29880b57cec5SDimitry Andric
29890b57cec5SDimitry Andric for (int i = 0; i < ResTyNumElts; ++i)
29900b57cec5SDimitry Andric Indices.push_back(Node->getMaskElt(i));
29910b57cec5SDimitry Andric
29920b57cec5SDimitry Andric // splati.[bhwd] is preferable to the others but is matched from
29930b57cec5SDimitry Andric // MipsISD::VSHF.
29940b57cec5SDimitry Andric if (isVECTOR_SHUFFLE_SPLATI(Op, ResTy, Indices, DAG))
29950b57cec5SDimitry Andric return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG);
29960b57cec5SDimitry Andric SDValue Result;
29970b57cec5SDimitry Andric if ((Result = lowerVECTOR_SHUFFLE_ILVEV(Op, ResTy, Indices, DAG)))
29980b57cec5SDimitry Andric return Result;
29990b57cec5SDimitry Andric if ((Result = lowerVECTOR_SHUFFLE_ILVOD(Op, ResTy, Indices, DAG)))
30000b57cec5SDimitry Andric return Result;
30010b57cec5SDimitry Andric if ((Result = lowerVECTOR_SHUFFLE_ILVL(Op, ResTy, Indices, DAG)))
30020b57cec5SDimitry Andric return Result;
30030b57cec5SDimitry Andric if ((Result = lowerVECTOR_SHUFFLE_ILVR(Op, ResTy, Indices, DAG)))
30040b57cec5SDimitry Andric return Result;
30050b57cec5SDimitry Andric if ((Result = lowerVECTOR_SHUFFLE_PCKEV(Op, ResTy, Indices, DAG)))
30060b57cec5SDimitry Andric return Result;
30070b57cec5SDimitry Andric if ((Result = lowerVECTOR_SHUFFLE_PCKOD(Op, ResTy, Indices, DAG)))
30080b57cec5SDimitry Andric return Result;
30090b57cec5SDimitry Andric if ((Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG)))
30100b57cec5SDimitry Andric return Result;
30110b57cec5SDimitry Andric return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG);
30120b57cec5SDimitry Andric }
30130b57cec5SDimitry Andric
30140b57cec5SDimitry Andric MachineBasicBlock *
emitBPOSGE32(MachineInstr & MI,MachineBasicBlock * BB) const30150b57cec5SDimitry Andric MipsSETargetLowering::emitBPOSGE32(MachineInstr &MI,
30160b57cec5SDimitry Andric MachineBasicBlock *BB) const {
30170b57cec5SDimitry Andric // $bb:
30180b57cec5SDimitry Andric // bposge32_pseudo $vr0
30190b57cec5SDimitry Andric // =>
30200b57cec5SDimitry Andric // $bb:
30210b57cec5SDimitry Andric // bposge32 $tbb
30220b57cec5SDimitry Andric // $fbb:
30230b57cec5SDimitry Andric // li $vr2, 0
30240b57cec5SDimitry Andric // b $sink
30250b57cec5SDimitry Andric // $tbb:
30260b57cec5SDimitry Andric // li $vr1, 1
30270b57cec5SDimitry Andric // $sink:
30280b57cec5SDimitry Andric // $vr0 = phi($vr2, $fbb, $vr1, $tbb)
30290b57cec5SDimitry Andric
30300b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
30310b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
30320b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::GPR32RegClass;
30330b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
30340b57cec5SDimitry Andric const BasicBlock *LLVM_BB = BB->getBasicBlock();
30350b57cec5SDimitry Andric MachineFunction::iterator It = std::next(MachineFunction::iterator(BB));
30360b57cec5SDimitry Andric MachineFunction *F = BB->getParent();
30370b57cec5SDimitry Andric MachineBasicBlock *FBB = F->CreateMachineBasicBlock(LLVM_BB);
30380b57cec5SDimitry Andric MachineBasicBlock *TBB = F->CreateMachineBasicBlock(LLVM_BB);
30390b57cec5SDimitry Andric MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB);
30400b57cec5SDimitry Andric F->insert(It, FBB);
30410b57cec5SDimitry Andric F->insert(It, TBB);
30420b57cec5SDimitry Andric F->insert(It, Sink);
30430b57cec5SDimitry Andric
30440b57cec5SDimitry Andric // Transfer the remainder of BB and its successor edges to Sink.
30450b57cec5SDimitry Andric Sink->splice(Sink->begin(), BB, std::next(MachineBasicBlock::iterator(MI)),
30460b57cec5SDimitry Andric BB->end());
30470b57cec5SDimitry Andric Sink->transferSuccessorsAndUpdatePHIs(BB);
30480b57cec5SDimitry Andric
30490b57cec5SDimitry Andric // Add successors.
30500b57cec5SDimitry Andric BB->addSuccessor(FBB);
30510b57cec5SDimitry Andric BB->addSuccessor(TBB);
30520b57cec5SDimitry Andric FBB->addSuccessor(Sink);
30530b57cec5SDimitry Andric TBB->addSuccessor(Sink);
30540b57cec5SDimitry Andric
30550b57cec5SDimitry Andric // Insert the real bposge32 instruction to $BB.
30560b57cec5SDimitry Andric BuildMI(BB, DL, TII->get(Mips::BPOSGE32)).addMBB(TBB);
30570b57cec5SDimitry Andric // Insert the real bposge32c instruction to $BB.
30580b57cec5SDimitry Andric BuildMI(BB, DL, TII->get(Mips::BPOSGE32C_MMR3)).addMBB(TBB);
30590b57cec5SDimitry Andric
30600b57cec5SDimitry Andric // Fill $FBB.
30618bcb0991SDimitry Andric Register VR2 = RegInfo.createVirtualRegister(RC);
30620b57cec5SDimitry Andric BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::ADDiu), VR2)
30630b57cec5SDimitry Andric .addReg(Mips::ZERO).addImm(0);
30640b57cec5SDimitry Andric BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::B)).addMBB(Sink);
30650b57cec5SDimitry Andric
30660b57cec5SDimitry Andric // Fill $TBB.
30678bcb0991SDimitry Andric Register VR1 = RegInfo.createVirtualRegister(RC);
30680b57cec5SDimitry Andric BuildMI(*TBB, TBB->end(), DL, TII->get(Mips::ADDiu), VR1)
30690b57cec5SDimitry Andric .addReg(Mips::ZERO).addImm(1);
30700b57cec5SDimitry Andric
30710b57cec5SDimitry Andric // Insert phi function to $Sink.
30720b57cec5SDimitry Andric BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI),
30730b57cec5SDimitry Andric MI.getOperand(0).getReg())
30740b57cec5SDimitry Andric .addReg(VR2)
30750b57cec5SDimitry Andric .addMBB(FBB)
30760b57cec5SDimitry Andric .addReg(VR1)
30770b57cec5SDimitry Andric .addMBB(TBB);
30780b57cec5SDimitry Andric
30790b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now.
30800b57cec5SDimitry Andric return Sink;
30810b57cec5SDimitry Andric }
30820b57cec5SDimitry Andric
emitMSACBranchPseudo(MachineInstr & MI,MachineBasicBlock * BB,unsigned BranchOp) const30830b57cec5SDimitry Andric MachineBasicBlock *MipsSETargetLowering::emitMSACBranchPseudo(
30840b57cec5SDimitry Andric MachineInstr &MI, MachineBasicBlock *BB, unsigned BranchOp) const {
30850b57cec5SDimitry Andric // $bb:
30860b57cec5SDimitry Andric // vany_nonzero $rd, $ws
30870b57cec5SDimitry Andric // =>
30880b57cec5SDimitry Andric // $bb:
30890b57cec5SDimitry Andric // bnz.b $ws, $tbb
30900b57cec5SDimitry Andric // b $fbb
30910b57cec5SDimitry Andric // $fbb:
30920b57cec5SDimitry Andric // li $rd1, 0
30930b57cec5SDimitry Andric // b $sink
30940b57cec5SDimitry Andric // $tbb:
30950b57cec5SDimitry Andric // li $rd2, 1
30960b57cec5SDimitry Andric // $sink:
30970b57cec5SDimitry Andric // $rd = phi($rd1, $fbb, $rd2, $tbb)
30980b57cec5SDimitry Andric
30990b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
31000b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
31010b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::GPR32RegClass;
31020b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
31030b57cec5SDimitry Andric const BasicBlock *LLVM_BB = BB->getBasicBlock();
31040b57cec5SDimitry Andric MachineFunction::iterator It = std::next(MachineFunction::iterator(BB));
31050b57cec5SDimitry Andric MachineFunction *F = BB->getParent();
31060b57cec5SDimitry Andric MachineBasicBlock *FBB = F->CreateMachineBasicBlock(LLVM_BB);
31070b57cec5SDimitry Andric MachineBasicBlock *TBB = F->CreateMachineBasicBlock(LLVM_BB);
31080b57cec5SDimitry Andric MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB);
31090b57cec5SDimitry Andric F->insert(It, FBB);
31100b57cec5SDimitry Andric F->insert(It, TBB);
31110b57cec5SDimitry Andric F->insert(It, Sink);
31120b57cec5SDimitry Andric
31130b57cec5SDimitry Andric // Transfer the remainder of BB and its successor edges to Sink.
31140b57cec5SDimitry Andric Sink->splice(Sink->begin(), BB, std::next(MachineBasicBlock::iterator(MI)),
31150b57cec5SDimitry Andric BB->end());
31160b57cec5SDimitry Andric Sink->transferSuccessorsAndUpdatePHIs(BB);
31170b57cec5SDimitry Andric
31180b57cec5SDimitry Andric // Add successors.
31190b57cec5SDimitry Andric BB->addSuccessor(FBB);
31200b57cec5SDimitry Andric BB->addSuccessor(TBB);
31210b57cec5SDimitry Andric FBB->addSuccessor(Sink);
31220b57cec5SDimitry Andric TBB->addSuccessor(Sink);
31230b57cec5SDimitry Andric
31240b57cec5SDimitry Andric // Insert the real bnz.b instruction to $BB.
31250b57cec5SDimitry Andric BuildMI(BB, DL, TII->get(BranchOp))
31260b57cec5SDimitry Andric .addReg(MI.getOperand(1).getReg())
31270b57cec5SDimitry Andric .addMBB(TBB);
31280b57cec5SDimitry Andric
31290b57cec5SDimitry Andric // Fill $FBB.
31308bcb0991SDimitry Andric Register RD1 = RegInfo.createVirtualRegister(RC);
31310b57cec5SDimitry Andric BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::ADDiu), RD1)
31320b57cec5SDimitry Andric .addReg(Mips::ZERO).addImm(0);
31330b57cec5SDimitry Andric BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::B)).addMBB(Sink);
31340b57cec5SDimitry Andric
31350b57cec5SDimitry Andric // Fill $TBB.
31368bcb0991SDimitry Andric Register RD2 = RegInfo.createVirtualRegister(RC);
31370b57cec5SDimitry Andric BuildMI(*TBB, TBB->end(), DL, TII->get(Mips::ADDiu), RD2)
31380b57cec5SDimitry Andric .addReg(Mips::ZERO).addImm(1);
31390b57cec5SDimitry Andric
31400b57cec5SDimitry Andric // Insert phi function to $Sink.
31410b57cec5SDimitry Andric BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI),
31420b57cec5SDimitry Andric MI.getOperand(0).getReg())
31430b57cec5SDimitry Andric .addReg(RD1)
31440b57cec5SDimitry Andric .addMBB(FBB)
31450b57cec5SDimitry Andric .addReg(RD2)
31460b57cec5SDimitry Andric .addMBB(TBB);
31470b57cec5SDimitry Andric
31480b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now.
31490b57cec5SDimitry Andric return Sink;
31500b57cec5SDimitry Andric }
31510b57cec5SDimitry Andric
31520b57cec5SDimitry Andric // Emit the COPY_FW pseudo instruction.
31530b57cec5SDimitry Andric //
31540b57cec5SDimitry Andric // copy_fw_pseudo $fd, $ws, n
31550b57cec5SDimitry Andric // =>
31560b57cec5SDimitry Andric // copy_u_w $rt, $ws, $n
31570b57cec5SDimitry Andric // mtc1 $rt, $fd
31580b57cec5SDimitry Andric //
31590b57cec5SDimitry Andric // When n is zero, the equivalent operation can be performed with (potentially)
31600b57cec5SDimitry Andric // zero instructions due to register overlaps. This optimization is never valid
31610b57cec5SDimitry Andric // for lane 1 because it would require FR=0 mode which isn't supported by MSA.
31620b57cec5SDimitry Andric MachineBasicBlock *
emitCOPY_FW(MachineInstr & MI,MachineBasicBlock * BB) const31630b57cec5SDimitry Andric MipsSETargetLowering::emitCOPY_FW(MachineInstr &MI,
31640b57cec5SDimitry Andric MachineBasicBlock *BB) const {
31650b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
31660b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
31670b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
31688bcb0991SDimitry Andric Register Fd = MI.getOperand(0).getReg();
31698bcb0991SDimitry Andric Register Ws = MI.getOperand(1).getReg();
31700b57cec5SDimitry Andric unsigned Lane = MI.getOperand(2).getImm();
31710b57cec5SDimitry Andric
31720b57cec5SDimitry Andric if (Lane == 0) {
31730b57cec5SDimitry Andric unsigned Wt = Ws;
31740b57cec5SDimitry Andric if (!Subtarget.useOddSPReg()) {
31750b57cec5SDimitry Andric // We must copy to an even-numbered MSA register so that the
31760b57cec5SDimitry Andric // single-precision sub-register is also guaranteed to be even-numbered.
31770b57cec5SDimitry Andric Wt = RegInfo.createVirtualRegister(&Mips::MSA128WEvensRegClass);
31780b57cec5SDimitry Andric
31790b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Wt).addReg(Ws);
31800b57cec5SDimitry Andric }
31810b57cec5SDimitry Andric
31820b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_lo);
31830b57cec5SDimitry Andric } else {
31848bcb0991SDimitry Andric Register Wt = RegInfo.createVirtualRegister(
31858bcb0991SDimitry Andric Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass
31868bcb0991SDimitry Andric : &Mips::MSA128WEvensRegClass);
31870b57cec5SDimitry Andric
31880b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_W), Wt).addReg(Ws).addImm(Lane);
31890b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_lo);
31900b57cec5SDimitry Andric }
31910b57cec5SDimitry Andric
31920b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now.
31930b57cec5SDimitry Andric return BB;
31940b57cec5SDimitry Andric }
31950b57cec5SDimitry Andric
31960b57cec5SDimitry Andric // Emit the COPY_FD pseudo instruction.
31970b57cec5SDimitry Andric //
31980b57cec5SDimitry Andric // copy_fd_pseudo $fd, $ws, n
31990b57cec5SDimitry Andric // =>
32000b57cec5SDimitry Andric // splati.d $wt, $ws, $n
32010b57cec5SDimitry Andric // copy $fd, $wt:sub_64
32020b57cec5SDimitry Andric //
32030b57cec5SDimitry Andric // When n is zero, the equivalent operation can be performed with (potentially)
32040b57cec5SDimitry Andric // zero instructions due to register overlaps. This optimization is always
32050b57cec5SDimitry Andric // valid because FR=1 mode which is the only supported mode in MSA.
32060b57cec5SDimitry Andric MachineBasicBlock *
emitCOPY_FD(MachineInstr & MI,MachineBasicBlock * BB) const32070b57cec5SDimitry Andric MipsSETargetLowering::emitCOPY_FD(MachineInstr &MI,
32080b57cec5SDimitry Andric MachineBasicBlock *BB) const {
32090b57cec5SDimitry Andric assert(Subtarget.isFP64bit());
32100b57cec5SDimitry Andric
32110b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
32120b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
32138bcb0991SDimitry Andric Register Fd = MI.getOperand(0).getReg();
32148bcb0991SDimitry Andric Register Ws = MI.getOperand(1).getReg();
32150b57cec5SDimitry Andric unsigned Lane = MI.getOperand(2).getImm() * 2;
32160b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
32170b57cec5SDimitry Andric
32180b57cec5SDimitry Andric if (Lane == 0)
32190b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Ws, 0, Mips::sub_64);
32200b57cec5SDimitry Andric else {
32218bcb0991SDimitry Andric Register Wt = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
32220b57cec5SDimitry Andric
32230b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_D), Wt).addReg(Ws).addImm(1);
32240b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_64);
32250b57cec5SDimitry Andric }
32260b57cec5SDimitry Andric
32270b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now.
32280b57cec5SDimitry Andric return BB;
32290b57cec5SDimitry Andric }
32300b57cec5SDimitry Andric
32310b57cec5SDimitry Andric // Emit the INSERT_FW pseudo instruction.
32320b57cec5SDimitry Andric //
32330b57cec5SDimitry Andric // insert_fw_pseudo $wd, $wd_in, $n, $fs
32340b57cec5SDimitry Andric // =>
32350b57cec5SDimitry Andric // subreg_to_reg $wt:sub_lo, $fs
32360b57cec5SDimitry Andric // insve_w $wd[$n], $wd_in, $wt[0]
32370b57cec5SDimitry Andric MachineBasicBlock *
emitINSERT_FW(MachineInstr & MI,MachineBasicBlock * BB) const32380b57cec5SDimitry Andric MipsSETargetLowering::emitINSERT_FW(MachineInstr &MI,
32390b57cec5SDimitry Andric MachineBasicBlock *BB) const {
32400b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
32410b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
32420b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
32438bcb0991SDimitry Andric Register Wd = MI.getOperand(0).getReg();
32448bcb0991SDimitry Andric Register Wd_in = MI.getOperand(1).getReg();
32450b57cec5SDimitry Andric unsigned Lane = MI.getOperand(2).getImm();
32468bcb0991SDimitry Andric Register Fs = MI.getOperand(3).getReg();
32478bcb0991SDimitry Andric Register Wt = RegInfo.createVirtualRegister(
32488bcb0991SDimitry Andric Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass
32498bcb0991SDimitry Andric : &Mips::MSA128WEvensRegClass);
32500b57cec5SDimitry Andric
32510b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt)
32520b57cec5SDimitry Andric .addImm(0)
32530b57cec5SDimitry Andric .addReg(Fs)
32540b57cec5SDimitry Andric .addImm(Mips::sub_lo);
32550b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_W), Wd)
32560b57cec5SDimitry Andric .addReg(Wd_in)
32570b57cec5SDimitry Andric .addImm(Lane)
32580b57cec5SDimitry Andric .addReg(Wt)
32590b57cec5SDimitry Andric .addImm(0);
32600b57cec5SDimitry Andric
32610b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now.
32620b57cec5SDimitry Andric return BB;
32630b57cec5SDimitry Andric }
32640b57cec5SDimitry Andric
32650b57cec5SDimitry Andric // Emit the INSERT_FD pseudo instruction.
32660b57cec5SDimitry Andric //
32670b57cec5SDimitry Andric // insert_fd_pseudo $wd, $fs, n
32680b57cec5SDimitry Andric // =>
32690b57cec5SDimitry Andric // subreg_to_reg $wt:sub_64, $fs
32700b57cec5SDimitry Andric // insve_d $wd[$n], $wd_in, $wt[0]
32710b57cec5SDimitry Andric MachineBasicBlock *
emitINSERT_FD(MachineInstr & MI,MachineBasicBlock * BB) const32720b57cec5SDimitry Andric MipsSETargetLowering::emitINSERT_FD(MachineInstr &MI,
32730b57cec5SDimitry Andric MachineBasicBlock *BB) const {
32740b57cec5SDimitry Andric assert(Subtarget.isFP64bit());
32750b57cec5SDimitry Andric
32760b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
32770b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
32780b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
32798bcb0991SDimitry Andric Register Wd = MI.getOperand(0).getReg();
32808bcb0991SDimitry Andric Register Wd_in = MI.getOperand(1).getReg();
32810b57cec5SDimitry Andric unsigned Lane = MI.getOperand(2).getImm();
32828bcb0991SDimitry Andric Register Fs = MI.getOperand(3).getReg();
32838bcb0991SDimitry Andric Register Wt = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
32840b57cec5SDimitry Andric
32850b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt)
32860b57cec5SDimitry Andric .addImm(0)
32870b57cec5SDimitry Andric .addReg(Fs)
32880b57cec5SDimitry Andric .addImm(Mips::sub_64);
32890b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_D), Wd)
32900b57cec5SDimitry Andric .addReg(Wd_in)
32910b57cec5SDimitry Andric .addImm(Lane)
32920b57cec5SDimitry Andric .addReg(Wt)
32930b57cec5SDimitry Andric .addImm(0);
32940b57cec5SDimitry Andric
32950b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now.
32960b57cec5SDimitry Andric return BB;
32970b57cec5SDimitry Andric }
32980b57cec5SDimitry Andric
32990b57cec5SDimitry Andric // Emit the INSERT_([BHWD]|F[WD])_VIDX pseudo instruction.
33000b57cec5SDimitry Andric //
33010b57cec5SDimitry Andric // For integer:
33020b57cec5SDimitry Andric // (INSERT_([BHWD]|F[WD])_PSEUDO $wd, $wd_in, $n, $rs)
33030b57cec5SDimitry Andric // =>
33040b57cec5SDimitry Andric // (SLL $lanetmp1, $lane, <log2size)
33050b57cec5SDimitry Andric // (SLD_B $wdtmp1, $wd_in, $wd_in, $lanetmp1)
33060b57cec5SDimitry Andric // (INSERT_[BHWD], $wdtmp2, $wdtmp1, 0, $rs)
33070b57cec5SDimitry Andric // (NEG $lanetmp2, $lanetmp1)
33080b57cec5SDimitry Andric // (SLD_B $wd, $wdtmp2, $wdtmp2, $lanetmp2)
33090b57cec5SDimitry Andric //
33100b57cec5SDimitry Andric // For floating point:
33110b57cec5SDimitry Andric // (INSERT_([BHWD]|F[WD])_PSEUDO $wd, $wd_in, $n, $fs)
33120b57cec5SDimitry Andric // =>
33130b57cec5SDimitry Andric // (SUBREG_TO_REG $wt, $fs, <subreg>)
33140b57cec5SDimitry Andric // (SLL $lanetmp1, $lane, <log2size)
33150b57cec5SDimitry Andric // (SLD_B $wdtmp1, $wd_in, $wd_in, $lanetmp1)
33160b57cec5SDimitry Andric // (INSVE_[WD], $wdtmp2, 0, $wdtmp1, 0)
33170b57cec5SDimitry Andric // (NEG $lanetmp2, $lanetmp1)
33180b57cec5SDimitry Andric // (SLD_B $wd, $wdtmp2, $wdtmp2, $lanetmp2)
emitINSERT_DF_VIDX(MachineInstr & MI,MachineBasicBlock * BB,unsigned EltSizeInBytes,bool IsFP) const33190b57cec5SDimitry Andric MachineBasicBlock *MipsSETargetLowering::emitINSERT_DF_VIDX(
33200b57cec5SDimitry Andric MachineInstr &MI, MachineBasicBlock *BB, unsigned EltSizeInBytes,
33210b57cec5SDimitry Andric bool IsFP) const {
33220b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
33230b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
33240b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
33258bcb0991SDimitry Andric Register Wd = MI.getOperand(0).getReg();
33268bcb0991SDimitry Andric Register SrcVecReg = MI.getOperand(1).getReg();
33278bcb0991SDimitry Andric Register LaneReg = MI.getOperand(2).getReg();
33288bcb0991SDimitry Andric Register SrcValReg = MI.getOperand(3).getReg();
33290b57cec5SDimitry Andric
33300b57cec5SDimitry Andric const TargetRegisterClass *VecRC = nullptr;
33310b57cec5SDimitry Andric // FIXME: This should be true for N32 too.
33320b57cec5SDimitry Andric const TargetRegisterClass *GPRRC =
33330b57cec5SDimitry Andric Subtarget.isABI_N64() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
33340b57cec5SDimitry Andric unsigned SubRegIdx = Subtarget.isABI_N64() ? Mips::sub_32 : 0;
33350b57cec5SDimitry Andric unsigned ShiftOp = Subtarget.isABI_N64() ? Mips::DSLL : Mips::SLL;
33360b57cec5SDimitry Andric unsigned EltLog2Size;
33370b57cec5SDimitry Andric unsigned InsertOp = 0;
33380b57cec5SDimitry Andric unsigned InsveOp = 0;
33390b57cec5SDimitry Andric switch (EltSizeInBytes) {
33400b57cec5SDimitry Andric default:
33410b57cec5SDimitry Andric llvm_unreachable("Unexpected size");
33420b57cec5SDimitry Andric case 1:
33430b57cec5SDimitry Andric EltLog2Size = 0;
33440b57cec5SDimitry Andric InsertOp = Mips::INSERT_B;
33450b57cec5SDimitry Andric InsveOp = Mips::INSVE_B;
33460b57cec5SDimitry Andric VecRC = &Mips::MSA128BRegClass;
33470b57cec5SDimitry Andric break;
33480b57cec5SDimitry Andric case 2:
33490b57cec5SDimitry Andric EltLog2Size = 1;
33500b57cec5SDimitry Andric InsertOp = Mips::INSERT_H;
33510b57cec5SDimitry Andric InsveOp = Mips::INSVE_H;
33520b57cec5SDimitry Andric VecRC = &Mips::MSA128HRegClass;
33530b57cec5SDimitry Andric break;
33540b57cec5SDimitry Andric case 4:
33550b57cec5SDimitry Andric EltLog2Size = 2;
33560b57cec5SDimitry Andric InsertOp = Mips::INSERT_W;
33570b57cec5SDimitry Andric InsveOp = Mips::INSVE_W;
33580b57cec5SDimitry Andric VecRC = &Mips::MSA128WRegClass;
33590b57cec5SDimitry Andric break;
33600b57cec5SDimitry Andric case 8:
33610b57cec5SDimitry Andric EltLog2Size = 3;
33620b57cec5SDimitry Andric InsertOp = Mips::INSERT_D;
33630b57cec5SDimitry Andric InsveOp = Mips::INSVE_D;
33640b57cec5SDimitry Andric VecRC = &Mips::MSA128DRegClass;
33650b57cec5SDimitry Andric break;
33660b57cec5SDimitry Andric }
33670b57cec5SDimitry Andric
33680b57cec5SDimitry Andric if (IsFP) {
33698bcb0991SDimitry Andric Register Wt = RegInfo.createVirtualRegister(VecRC);
33700b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt)
33710b57cec5SDimitry Andric .addImm(0)
33720b57cec5SDimitry Andric .addReg(SrcValReg)
33730b57cec5SDimitry Andric .addImm(EltSizeInBytes == 8 ? Mips::sub_64 : Mips::sub_lo);
33740b57cec5SDimitry Andric SrcValReg = Wt;
33750b57cec5SDimitry Andric }
33760b57cec5SDimitry Andric
33770b57cec5SDimitry Andric // Convert the lane index into a byte index
33780b57cec5SDimitry Andric if (EltSizeInBytes != 1) {
33798bcb0991SDimitry Andric Register LaneTmp1 = RegInfo.createVirtualRegister(GPRRC);
33800b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(ShiftOp), LaneTmp1)
33810b57cec5SDimitry Andric .addReg(LaneReg)
33820b57cec5SDimitry Andric .addImm(EltLog2Size);
33830b57cec5SDimitry Andric LaneReg = LaneTmp1;
33840b57cec5SDimitry Andric }
33850b57cec5SDimitry Andric
33860b57cec5SDimitry Andric // Rotate bytes around so that the desired lane is element zero
33878bcb0991SDimitry Andric Register WdTmp1 = RegInfo.createVirtualRegister(VecRC);
33880b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), WdTmp1)
33890b57cec5SDimitry Andric .addReg(SrcVecReg)
33900b57cec5SDimitry Andric .addReg(SrcVecReg)
33910b57cec5SDimitry Andric .addReg(LaneReg, 0, SubRegIdx);
33920b57cec5SDimitry Andric
33938bcb0991SDimitry Andric Register WdTmp2 = RegInfo.createVirtualRegister(VecRC);
33940b57cec5SDimitry Andric if (IsFP) {
33950b57cec5SDimitry Andric // Use insve.df to insert to element zero
33960b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(InsveOp), WdTmp2)
33970b57cec5SDimitry Andric .addReg(WdTmp1)
33980b57cec5SDimitry Andric .addImm(0)
33990b57cec5SDimitry Andric .addReg(SrcValReg)
34000b57cec5SDimitry Andric .addImm(0);
34010b57cec5SDimitry Andric } else {
34020b57cec5SDimitry Andric // Use insert.df to insert to element zero
34030b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(InsertOp), WdTmp2)
34040b57cec5SDimitry Andric .addReg(WdTmp1)
34050b57cec5SDimitry Andric .addReg(SrcValReg)
34060b57cec5SDimitry Andric .addImm(0);
34070b57cec5SDimitry Andric }
34080b57cec5SDimitry Andric
34090b57cec5SDimitry Andric // Rotate elements the rest of the way for a full rotation.
34100b57cec5SDimitry Andric // sld.df inteprets $rt modulo the number of columns so we only need to negate
34110b57cec5SDimitry Andric // the lane index to do this.
34128bcb0991SDimitry Andric Register LaneTmp2 = RegInfo.createVirtualRegister(GPRRC);
34130b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Subtarget.isABI_N64() ? Mips::DSUB : Mips::SUB),
34140b57cec5SDimitry Andric LaneTmp2)
34150b57cec5SDimitry Andric .addReg(Subtarget.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO)
34160b57cec5SDimitry Andric .addReg(LaneReg);
34170b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), Wd)
34180b57cec5SDimitry Andric .addReg(WdTmp2)
34190b57cec5SDimitry Andric .addReg(WdTmp2)
34200b57cec5SDimitry Andric .addReg(LaneTmp2, 0, SubRegIdx);
34210b57cec5SDimitry Andric
34220b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now.
34230b57cec5SDimitry Andric return BB;
34240b57cec5SDimitry Andric }
34250b57cec5SDimitry Andric
34260b57cec5SDimitry Andric // Emit the FILL_FW pseudo instruction.
34270b57cec5SDimitry Andric //
34280b57cec5SDimitry Andric // fill_fw_pseudo $wd, $fs
34290b57cec5SDimitry Andric // =>
34300b57cec5SDimitry Andric // implicit_def $wt1
34310b57cec5SDimitry Andric // insert_subreg $wt2:subreg_lo, $wt1, $fs
34320b57cec5SDimitry Andric // splati.w $wd, $wt2[0]
34330b57cec5SDimitry Andric MachineBasicBlock *
emitFILL_FW(MachineInstr & MI,MachineBasicBlock * BB) const34340b57cec5SDimitry Andric MipsSETargetLowering::emitFILL_FW(MachineInstr &MI,
34350b57cec5SDimitry Andric MachineBasicBlock *BB) const {
34360b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
34370b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
34380b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
34398bcb0991SDimitry Andric Register Wd = MI.getOperand(0).getReg();
34408bcb0991SDimitry Andric Register Fs = MI.getOperand(1).getReg();
34418bcb0991SDimitry Andric Register Wt1 = RegInfo.createVirtualRegister(
34420b57cec5SDimitry Andric Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass
34430b57cec5SDimitry Andric : &Mips::MSA128WEvensRegClass);
34448bcb0991SDimitry Andric Register Wt2 = RegInfo.createVirtualRegister(
34450b57cec5SDimitry Andric Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass
34460b57cec5SDimitry Andric : &Mips::MSA128WEvensRegClass);
34470b57cec5SDimitry Andric
34480b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::IMPLICIT_DEF), Wt1);
34490b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_SUBREG), Wt2)
34500b57cec5SDimitry Andric .addReg(Wt1)
34510b57cec5SDimitry Andric .addReg(Fs)
34520b57cec5SDimitry Andric .addImm(Mips::sub_lo);
34530b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_W), Wd).addReg(Wt2).addImm(0);
34540b57cec5SDimitry Andric
34550b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now.
34560b57cec5SDimitry Andric return BB;
34570b57cec5SDimitry Andric }
34580b57cec5SDimitry Andric
34590b57cec5SDimitry Andric // Emit the FILL_FD pseudo instruction.
34600b57cec5SDimitry Andric //
34610b57cec5SDimitry Andric // fill_fd_pseudo $wd, $fs
34620b57cec5SDimitry Andric // =>
34630b57cec5SDimitry Andric // implicit_def $wt1
34640b57cec5SDimitry Andric // insert_subreg $wt2:subreg_64, $wt1, $fs
34650b57cec5SDimitry Andric // splati.d $wd, $wt2[0]
34660b57cec5SDimitry Andric MachineBasicBlock *
emitFILL_FD(MachineInstr & MI,MachineBasicBlock * BB) const34670b57cec5SDimitry Andric MipsSETargetLowering::emitFILL_FD(MachineInstr &MI,
34680b57cec5SDimitry Andric MachineBasicBlock *BB) const {
34690b57cec5SDimitry Andric assert(Subtarget.isFP64bit());
34700b57cec5SDimitry Andric
34710b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
34720b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
34730b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
34748bcb0991SDimitry Andric Register Wd = MI.getOperand(0).getReg();
34758bcb0991SDimitry Andric Register Fs = MI.getOperand(1).getReg();
34768bcb0991SDimitry Andric Register Wt1 = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
34778bcb0991SDimitry Andric Register Wt2 = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
34780b57cec5SDimitry Andric
34790b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::IMPLICIT_DEF), Wt1);
34800b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_SUBREG), Wt2)
34810b57cec5SDimitry Andric .addReg(Wt1)
34820b57cec5SDimitry Andric .addReg(Fs)
34830b57cec5SDimitry Andric .addImm(Mips::sub_64);
34840b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_D), Wd).addReg(Wt2).addImm(0);
34850b57cec5SDimitry Andric
34860b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now.
34870b57cec5SDimitry Andric return BB;
34880b57cec5SDimitry Andric }
34890b57cec5SDimitry Andric
34900b57cec5SDimitry Andric // Emit the ST_F16_PSEDUO instruction to store a f16 value from an MSA
34910b57cec5SDimitry Andric // register.
34920b57cec5SDimitry Andric //
34930b57cec5SDimitry Andric // STF16 MSA128F16:$wd, mem_simm10:$addr
34940b57cec5SDimitry Andric // =>
34950b57cec5SDimitry Andric // copy_u.h $rtemp,$wd[0]
34960b57cec5SDimitry Andric // sh $rtemp, $addr
34970b57cec5SDimitry Andric //
34980b57cec5SDimitry Andric // Safety: We can't use st.h & co as they would over write the memory after
34990b57cec5SDimitry Andric // the destination. It would require half floats be allocated 16 bytes(!) of
35000b57cec5SDimitry Andric // space.
35010b57cec5SDimitry Andric MachineBasicBlock *
emitST_F16_PSEUDO(MachineInstr & MI,MachineBasicBlock * BB) const35020b57cec5SDimitry Andric MipsSETargetLowering::emitST_F16_PSEUDO(MachineInstr &MI,
35030b57cec5SDimitry Andric MachineBasicBlock *BB) const {
35040b57cec5SDimitry Andric
35050b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
35060b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
35070b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
35088bcb0991SDimitry Andric Register Ws = MI.getOperand(0).getReg();
35098bcb0991SDimitry Andric Register Rt = MI.getOperand(1).getReg();
35100b57cec5SDimitry Andric const MachineMemOperand &MMO = **MI.memoperands_begin();
35110b57cec5SDimitry Andric unsigned Imm = MMO.getOffset();
35120b57cec5SDimitry Andric
35130b57cec5SDimitry Andric // Caution: A load via the GOT can expand to a GPR32 operand, a load via
35140b57cec5SDimitry Andric // spill and reload can expand as a GPR64 operand. Examine the
35150b57cec5SDimitry Andric // operand in detail and default to ABI.
35160b57cec5SDimitry Andric const TargetRegisterClass *RC =
35170b57cec5SDimitry Andric MI.getOperand(1).isReg() ? RegInfo.getRegClass(MI.getOperand(1).getReg())
35180b57cec5SDimitry Andric : (Subtarget.isABI_O32() ? &Mips::GPR32RegClass
35190b57cec5SDimitry Andric : &Mips::GPR64RegClass);
35200b57cec5SDimitry Andric const bool UsingMips32 = RC == &Mips::GPR32RegClass;
35218bcb0991SDimitry Andric Register Rs = RegInfo.createVirtualRegister(&Mips::GPR32RegClass);
35220b57cec5SDimitry Andric
35230b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::COPY_U_H), Rs).addReg(Ws).addImm(0);
35240b57cec5SDimitry Andric if(!UsingMips32) {
35258bcb0991SDimitry Andric Register Tmp = RegInfo.createVirtualRegister(&Mips::GPR64RegClass);
35260b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Tmp)
35270b57cec5SDimitry Andric .addImm(0)
35280b57cec5SDimitry Andric .addReg(Rs)
35290b57cec5SDimitry Andric .addImm(Mips::sub_32);
35300b57cec5SDimitry Andric Rs = Tmp;
35310b57cec5SDimitry Andric }
35320b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(UsingMips32 ? Mips::SH : Mips::SH64))
35330b57cec5SDimitry Andric .addReg(Rs)
35340b57cec5SDimitry Andric .addReg(Rt)
35350b57cec5SDimitry Andric .addImm(Imm)
35360b57cec5SDimitry Andric .addMemOperand(BB->getParent()->getMachineMemOperand(
35370b57cec5SDimitry Andric &MMO, MMO.getOffset(), MMO.getSize()));
35380b57cec5SDimitry Andric
35390b57cec5SDimitry Andric MI.eraseFromParent();
35400b57cec5SDimitry Andric return BB;
35410b57cec5SDimitry Andric }
35420b57cec5SDimitry Andric
35430b57cec5SDimitry Andric // Emit the LD_F16_PSEDUO instruction to load a f16 value into an MSA register.
35440b57cec5SDimitry Andric //
35450b57cec5SDimitry Andric // LD_F16 MSA128F16:$wd, mem_simm10:$addr
35460b57cec5SDimitry Andric // =>
35470b57cec5SDimitry Andric // lh $rtemp, $addr
35480b57cec5SDimitry Andric // fill.h $wd, $rtemp
35490b57cec5SDimitry Andric //
35500b57cec5SDimitry Andric // Safety: We can't use ld.h & co as they over-read from the source.
35510b57cec5SDimitry Andric // Additionally, if the address is not modulo 16, 2 cases can occur:
35520b57cec5SDimitry Andric // a) Segmentation fault as the load instruction reads from a memory page
35530b57cec5SDimitry Andric // memory it's not supposed to.
35540b57cec5SDimitry Andric // b) The load crosses an implementation specific boundary, requiring OS
35550b57cec5SDimitry Andric // intervention.
35560b57cec5SDimitry Andric MachineBasicBlock *
emitLD_F16_PSEUDO(MachineInstr & MI,MachineBasicBlock * BB) const35570b57cec5SDimitry Andric MipsSETargetLowering::emitLD_F16_PSEUDO(MachineInstr &MI,
35580b57cec5SDimitry Andric MachineBasicBlock *BB) const {
35590b57cec5SDimitry Andric
35600b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
35610b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
35620b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
35638bcb0991SDimitry Andric Register Wd = MI.getOperand(0).getReg();
35640b57cec5SDimitry Andric
35650b57cec5SDimitry Andric // Caution: A load via the GOT can expand to a GPR32 operand, a load via
35660b57cec5SDimitry Andric // spill and reload can expand as a GPR64 operand. Examine the
35670b57cec5SDimitry Andric // operand in detail and default to ABI.
35680b57cec5SDimitry Andric const TargetRegisterClass *RC =
35690b57cec5SDimitry Andric MI.getOperand(1).isReg() ? RegInfo.getRegClass(MI.getOperand(1).getReg())
35700b57cec5SDimitry Andric : (Subtarget.isABI_O32() ? &Mips::GPR32RegClass
35710b57cec5SDimitry Andric : &Mips::GPR64RegClass);
35720b57cec5SDimitry Andric
35730b57cec5SDimitry Andric const bool UsingMips32 = RC == &Mips::GPR32RegClass;
35748bcb0991SDimitry Andric Register Rt = RegInfo.createVirtualRegister(RC);
35750b57cec5SDimitry Andric
35760b57cec5SDimitry Andric MachineInstrBuilder MIB =
35770b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(UsingMips32 ? Mips::LH : Mips::LH64), Rt);
35784824e7fdSDimitry Andric for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))
35794824e7fdSDimitry Andric MIB.add(MO);
35800b57cec5SDimitry Andric
35810b57cec5SDimitry Andric if(!UsingMips32) {
35828bcb0991SDimitry Andric Register Tmp = RegInfo.createVirtualRegister(&Mips::GPR32RegClass);
35830b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Tmp).addReg(Rt, 0, Mips::sub_32);
35840b57cec5SDimitry Andric Rt = Tmp;
35850b57cec5SDimitry Andric }
35860b57cec5SDimitry Andric
35870b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::FILL_H), Wd).addReg(Rt);
35880b57cec5SDimitry Andric
35890b57cec5SDimitry Andric MI.eraseFromParent();
35900b57cec5SDimitry Andric return BB;
35910b57cec5SDimitry Andric }
35920b57cec5SDimitry Andric
35930b57cec5SDimitry Andric // Emit the FPROUND_PSEUDO instruction.
35940b57cec5SDimitry Andric //
35950b57cec5SDimitry Andric // Round an FGR64Opnd, FGR32Opnd to an f16.
35960b57cec5SDimitry Andric //
35970b57cec5SDimitry Andric // Safety: Cycle the operand through the GPRs so the result always ends up
35980b57cec5SDimitry Andric // the correct MSA register.
35990b57cec5SDimitry Andric //
36000b57cec5SDimitry Andric // FIXME: This copying is strictly unnecessary. If we could tie FGR32Opnd:$Fs
36010b57cec5SDimitry Andric // / FGR64Opnd:$Fs and MSA128F16:$Wd to the same physical register
36020b57cec5SDimitry Andric // (which they can be, as the MSA registers are defined to alias the
36030b57cec5SDimitry Andric // FPU's 64 bit and 32 bit registers) the result can be accessed using
36040b57cec5SDimitry Andric // the correct register class. That requires operands be tie-able across
36050b57cec5SDimitry Andric // register classes which have a sub/super register class relationship.
36060b57cec5SDimitry Andric //
36070b57cec5SDimitry Andric // For FPG32Opnd:
36080b57cec5SDimitry Andric //
36090b57cec5SDimitry Andric // FPROUND MSA128F16:$wd, FGR32Opnd:$fs
36100b57cec5SDimitry Andric // =>
36110b57cec5SDimitry Andric // mfc1 $rtemp, $fs
36120b57cec5SDimitry Andric // fill.w $rtemp, $wtemp
36130b57cec5SDimitry Andric // fexdo.w $wd, $wtemp, $wtemp
36140b57cec5SDimitry Andric //
36150b57cec5SDimitry Andric // For FPG64Opnd on mips32r2+:
36160b57cec5SDimitry Andric //
36170b57cec5SDimitry Andric // FPROUND MSA128F16:$wd, FGR64Opnd:$fs
36180b57cec5SDimitry Andric // =>
36190b57cec5SDimitry Andric // mfc1 $rtemp, $fs
36200b57cec5SDimitry Andric // fill.w $rtemp, $wtemp
36210b57cec5SDimitry Andric // mfhc1 $rtemp2, $fs
36220b57cec5SDimitry Andric // insert.w $wtemp[1], $rtemp2
36230b57cec5SDimitry Andric // insert.w $wtemp[3], $rtemp2
36240b57cec5SDimitry Andric // fexdo.w $wtemp2, $wtemp, $wtemp
36250b57cec5SDimitry Andric // fexdo.h $wd, $temp2, $temp2
36260b57cec5SDimitry Andric //
36270b57cec5SDimitry Andric // For FGR64Opnd on mips64r2+:
36280b57cec5SDimitry Andric //
36290b57cec5SDimitry Andric // FPROUND MSA128F16:$wd, FGR64Opnd:$fs
36300b57cec5SDimitry Andric // =>
36310b57cec5SDimitry Andric // dmfc1 $rtemp, $fs
36320b57cec5SDimitry Andric // fill.d $rtemp, $wtemp
36330b57cec5SDimitry Andric // fexdo.w $wtemp2, $wtemp, $wtemp
36340b57cec5SDimitry Andric // fexdo.h $wd, $wtemp2, $wtemp2
36350b57cec5SDimitry Andric //
36360b57cec5SDimitry Andric // Safety note: As $wtemp is UNDEF, we may provoke a spurious exception if the
36370b57cec5SDimitry Andric // undef bits are "just right" and the exception enable bits are
36380b57cec5SDimitry Andric // set. By using fill.w to replicate $fs into all elements over
36390b57cec5SDimitry Andric // insert.w for one element, we avoid that potiential case. If
36400b57cec5SDimitry Andric // fexdo.[hw] causes an exception in, the exception is valid and it
36410b57cec5SDimitry Andric // occurs for all elements.
36420b57cec5SDimitry Andric MachineBasicBlock *
emitFPROUND_PSEUDO(MachineInstr & MI,MachineBasicBlock * BB,bool IsFGR64) const36430b57cec5SDimitry Andric MipsSETargetLowering::emitFPROUND_PSEUDO(MachineInstr &MI,
36440b57cec5SDimitry Andric MachineBasicBlock *BB,
36450b57cec5SDimitry Andric bool IsFGR64) const {
36460b57cec5SDimitry Andric
36470b57cec5SDimitry Andric // Strictly speaking, we need MIPS32R5 to support MSA. We'll be generous
36480b57cec5SDimitry Andric // here. It's technically doable to support MIPS32 here, but the ISA forbids
36490b57cec5SDimitry Andric // it.
36500b57cec5SDimitry Andric assert(Subtarget.hasMSA() && Subtarget.hasMips32r2());
36510b57cec5SDimitry Andric
36520b57cec5SDimitry Andric bool IsFGR64onMips64 = Subtarget.hasMips64() && IsFGR64;
36530b57cec5SDimitry Andric bool IsFGR64onMips32 = !Subtarget.hasMips64() && IsFGR64;
36540b57cec5SDimitry Andric
36550b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
36560b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
36578bcb0991SDimitry Andric Register Wd = MI.getOperand(0).getReg();
36588bcb0991SDimitry Andric Register Fs = MI.getOperand(1).getReg();
36590b57cec5SDimitry Andric
36600b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
36618bcb0991SDimitry Andric Register Wtemp = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
36620b57cec5SDimitry Andric const TargetRegisterClass *GPRRC =
36630b57cec5SDimitry Andric IsFGR64onMips64 ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
36640b57cec5SDimitry Andric unsigned MFC1Opc = IsFGR64onMips64
36650b57cec5SDimitry Andric ? Mips::DMFC1
36660b57cec5SDimitry Andric : (IsFGR64onMips32 ? Mips::MFC1_D64 : Mips::MFC1);
36670b57cec5SDimitry Andric unsigned FILLOpc = IsFGR64onMips64 ? Mips::FILL_D : Mips::FILL_W;
36680b57cec5SDimitry Andric
36690b57cec5SDimitry Andric // Perform the register class copy as mentioned above.
36708bcb0991SDimitry Andric Register Rtemp = RegInfo.createVirtualRegister(GPRRC);
36710b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(MFC1Opc), Rtemp).addReg(Fs);
36720b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(FILLOpc), Wtemp).addReg(Rtemp);
36730b57cec5SDimitry Andric unsigned WPHI = Wtemp;
36740b57cec5SDimitry Andric
36750b57cec5SDimitry Andric if (IsFGR64onMips32) {
36768bcb0991SDimitry Andric Register Rtemp2 = RegInfo.createVirtualRegister(GPRRC);
36770b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::MFHC1_D64), Rtemp2).addReg(Fs);
36788bcb0991SDimitry Andric Register Wtemp2 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
36798bcb0991SDimitry Andric Register Wtemp3 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
36800b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_W), Wtemp2)
36810b57cec5SDimitry Andric .addReg(Wtemp)
36820b57cec5SDimitry Andric .addReg(Rtemp2)
36830b57cec5SDimitry Andric .addImm(1);
36840b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_W), Wtemp3)
36850b57cec5SDimitry Andric .addReg(Wtemp2)
36860b57cec5SDimitry Andric .addReg(Rtemp2)
36870b57cec5SDimitry Andric .addImm(3);
36880b57cec5SDimitry Andric WPHI = Wtemp3;
36890b57cec5SDimitry Andric }
36900b57cec5SDimitry Andric
36910b57cec5SDimitry Andric if (IsFGR64) {
36928bcb0991SDimitry Andric Register Wtemp2 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
36930b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::FEXDO_W), Wtemp2)
36940b57cec5SDimitry Andric .addReg(WPHI)
36950b57cec5SDimitry Andric .addReg(WPHI);
36960b57cec5SDimitry Andric WPHI = Wtemp2;
36970b57cec5SDimitry Andric }
36980b57cec5SDimitry Andric
36990b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::FEXDO_H), Wd).addReg(WPHI).addReg(WPHI);
37000b57cec5SDimitry Andric
37010b57cec5SDimitry Andric MI.eraseFromParent();
37020b57cec5SDimitry Andric return BB;
37030b57cec5SDimitry Andric }
37040b57cec5SDimitry Andric
37050b57cec5SDimitry Andric // Emit the FPEXTEND_PSEUDO instruction.
37060b57cec5SDimitry Andric //
37070b57cec5SDimitry Andric // Expand an f16 to either a FGR32Opnd or FGR64Opnd.
37080b57cec5SDimitry Andric //
37090b57cec5SDimitry Andric // Safety: Cycle the result through the GPRs so the result always ends up
37100b57cec5SDimitry Andric // the correct floating point register.
37110b57cec5SDimitry Andric //
37120b57cec5SDimitry Andric // FIXME: This copying is strictly unnecessary. If we could tie FGR32Opnd:$Fd
37130b57cec5SDimitry Andric // / FGR64Opnd:$Fd and MSA128F16:$Ws to the same physical register
37140b57cec5SDimitry Andric // (which they can be, as the MSA registers are defined to alias the
37150b57cec5SDimitry Andric // FPU's 64 bit and 32 bit registers) the result can be accessed using
37160b57cec5SDimitry Andric // the correct register class. That requires operands be tie-able across
37170b57cec5SDimitry Andric // register classes which have a sub/super register class relationship. I
37180b57cec5SDimitry Andric // haven't checked.
37190b57cec5SDimitry Andric //
37200b57cec5SDimitry Andric // For FGR32Opnd:
37210b57cec5SDimitry Andric //
37220b57cec5SDimitry Andric // FPEXTEND FGR32Opnd:$fd, MSA128F16:$ws
37230b57cec5SDimitry Andric // =>
37240b57cec5SDimitry Andric // fexupr.w $wtemp, $ws
37250b57cec5SDimitry Andric // copy_s.w $rtemp, $ws[0]
37260b57cec5SDimitry Andric // mtc1 $rtemp, $fd
37270b57cec5SDimitry Andric //
37280b57cec5SDimitry Andric // For FGR64Opnd on Mips64:
37290b57cec5SDimitry Andric //
37300b57cec5SDimitry Andric // FPEXTEND FGR64Opnd:$fd, MSA128F16:$ws
37310b57cec5SDimitry Andric // =>
37320b57cec5SDimitry Andric // fexupr.w $wtemp, $ws
37330b57cec5SDimitry Andric // fexupr.d $wtemp2, $wtemp
37340b57cec5SDimitry Andric // copy_s.d $rtemp, $wtemp2s[0]
37350b57cec5SDimitry Andric // dmtc1 $rtemp, $fd
37360b57cec5SDimitry Andric //
37370b57cec5SDimitry Andric // For FGR64Opnd on Mips32:
37380b57cec5SDimitry Andric //
37390b57cec5SDimitry Andric // FPEXTEND FGR64Opnd:$fd, MSA128F16:$ws
37400b57cec5SDimitry Andric // =>
37410b57cec5SDimitry Andric // fexupr.w $wtemp, $ws
37420b57cec5SDimitry Andric // fexupr.d $wtemp2, $wtemp
37430b57cec5SDimitry Andric // copy_s.w $rtemp, $wtemp2[0]
37440b57cec5SDimitry Andric // mtc1 $rtemp, $ftemp
37450b57cec5SDimitry Andric // copy_s.w $rtemp2, $wtemp2[1]
37460b57cec5SDimitry Andric // $fd = mthc1 $rtemp2, $ftemp
37470b57cec5SDimitry Andric MachineBasicBlock *
emitFPEXTEND_PSEUDO(MachineInstr & MI,MachineBasicBlock * BB,bool IsFGR64) const37480b57cec5SDimitry Andric MipsSETargetLowering::emitFPEXTEND_PSEUDO(MachineInstr &MI,
37490b57cec5SDimitry Andric MachineBasicBlock *BB,
37500b57cec5SDimitry Andric bool IsFGR64) const {
37510b57cec5SDimitry Andric
37520b57cec5SDimitry Andric // Strictly speaking, we need MIPS32R5 to support MSA. We'll be generous
37530b57cec5SDimitry Andric // here. It's technically doable to support MIPS32 here, but the ISA forbids
37540b57cec5SDimitry Andric // it.
37550b57cec5SDimitry Andric assert(Subtarget.hasMSA() && Subtarget.hasMips32r2());
37560b57cec5SDimitry Andric
37570b57cec5SDimitry Andric bool IsFGR64onMips64 = Subtarget.hasMips64() && IsFGR64;
37580b57cec5SDimitry Andric bool IsFGR64onMips32 = !Subtarget.hasMips64() && IsFGR64;
37590b57cec5SDimitry Andric
37600b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
37610b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
37620b57cec5SDimitry Andric Register Fd = MI.getOperand(0).getReg();
37630b57cec5SDimitry Andric Register Ws = MI.getOperand(1).getReg();
37640b57cec5SDimitry Andric
37650b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
37660b57cec5SDimitry Andric const TargetRegisterClass *GPRRC =
37670b57cec5SDimitry Andric IsFGR64onMips64 ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
37680b57cec5SDimitry Andric unsigned MTC1Opc = IsFGR64onMips64
37690b57cec5SDimitry Andric ? Mips::DMTC1
37700b57cec5SDimitry Andric : (IsFGR64onMips32 ? Mips::MTC1_D64 : Mips::MTC1);
37710b57cec5SDimitry Andric Register COPYOpc = IsFGR64onMips64 ? Mips::COPY_S_D : Mips::COPY_S_W;
37720b57cec5SDimitry Andric
37730b57cec5SDimitry Andric Register Wtemp = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
37740b57cec5SDimitry Andric Register WPHI = Wtemp;
37750b57cec5SDimitry Andric
37760b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::FEXUPR_W), Wtemp).addReg(Ws);
37770b57cec5SDimitry Andric if (IsFGR64) {
37780b57cec5SDimitry Andric WPHI = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
37790b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::FEXUPR_D), WPHI).addReg(Wtemp);
37800b57cec5SDimitry Andric }
37810b57cec5SDimitry Andric
37820b57cec5SDimitry Andric // Perform the safety regclass copy mentioned above.
37830b57cec5SDimitry Andric Register Rtemp = RegInfo.createVirtualRegister(GPRRC);
37840b57cec5SDimitry Andric Register FPRPHI = IsFGR64onMips32
37850b57cec5SDimitry Andric ? RegInfo.createVirtualRegister(&Mips::FGR64RegClass)
37860b57cec5SDimitry Andric : Fd;
37870b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(COPYOpc), Rtemp).addReg(WPHI).addImm(0);
37880b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(MTC1Opc), FPRPHI).addReg(Rtemp);
37890b57cec5SDimitry Andric
37900b57cec5SDimitry Andric if (IsFGR64onMips32) {
37910b57cec5SDimitry Andric Register Rtemp2 = RegInfo.createVirtualRegister(GPRRC);
37920b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::COPY_S_W), Rtemp2)
37930b57cec5SDimitry Andric .addReg(WPHI)
37940b57cec5SDimitry Andric .addImm(1);
37950b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::MTHC1_D64), Fd)
37960b57cec5SDimitry Andric .addReg(FPRPHI)
37970b57cec5SDimitry Andric .addReg(Rtemp2);
37980b57cec5SDimitry Andric }
37990b57cec5SDimitry Andric
38000b57cec5SDimitry Andric MI.eraseFromParent();
38010b57cec5SDimitry Andric return BB;
38020b57cec5SDimitry Andric }
38030b57cec5SDimitry Andric
38040b57cec5SDimitry Andric // Emit the FEXP2_W_1 pseudo instructions.
38050b57cec5SDimitry Andric //
38060b57cec5SDimitry Andric // fexp2_w_1_pseudo $wd, $wt
38070b57cec5SDimitry Andric // =>
38080b57cec5SDimitry Andric // ldi.w $ws, 1
38090b57cec5SDimitry Andric // fexp2.w $wd, $ws, $wt
38100b57cec5SDimitry Andric MachineBasicBlock *
emitFEXP2_W_1(MachineInstr & MI,MachineBasicBlock * BB) const38110b57cec5SDimitry Andric MipsSETargetLowering::emitFEXP2_W_1(MachineInstr &MI,
38120b57cec5SDimitry Andric MachineBasicBlock *BB) const {
38130b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
38140b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
38150b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::MSA128WRegClass;
38168bcb0991SDimitry Andric Register Ws1 = RegInfo.createVirtualRegister(RC);
38178bcb0991SDimitry Andric Register Ws2 = RegInfo.createVirtualRegister(RC);
38180b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
38190b57cec5SDimitry Andric
38200b57cec5SDimitry Andric // Splat 1.0 into a vector
38210b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::LDI_W), Ws1).addImm(1);
38220b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::FFINT_U_W), Ws2).addReg(Ws1);
38230b57cec5SDimitry Andric
38240b57cec5SDimitry Andric // Emit 1.0 * fexp2(Wt)
38250b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_W), MI.getOperand(0).getReg())
38260b57cec5SDimitry Andric .addReg(Ws2)
38270b57cec5SDimitry Andric .addReg(MI.getOperand(1).getReg());
38280b57cec5SDimitry Andric
38290b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now.
38300b57cec5SDimitry Andric return BB;
38310b57cec5SDimitry Andric }
38320b57cec5SDimitry Andric
38330b57cec5SDimitry Andric // Emit the FEXP2_D_1 pseudo instructions.
38340b57cec5SDimitry Andric //
38350b57cec5SDimitry Andric // fexp2_d_1_pseudo $wd, $wt
38360b57cec5SDimitry Andric // =>
38370b57cec5SDimitry Andric // ldi.d $ws, 1
38380b57cec5SDimitry Andric // fexp2.d $wd, $ws, $wt
38390b57cec5SDimitry Andric MachineBasicBlock *
emitFEXP2_D_1(MachineInstr & MI,MachineBasicBlock * BB) const38400b57cec5SDimitry Andric MipsSETargetLowering::emitFEXP2_D_1(MachineInstr &MI,
38410b57cec5SDimitry Andric MachineBasicBlock *BB) const {
38420b57cec5SDimitry Andric const TargetInstrInfo *TII = Subtarget.getInstrInfo();
38430b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
38440b57cec5SDimitry Andric const TargetRegisterClass *RC = &Mips::MSA128DRegClass;
38458bcb0991SDimitry Andric Register Ws1 = RegInfo.createVirtualRegister(RC);
38468bcb0991SDimitry Andric Register Ws2 = RegInfo.createVirtualRegister(RC);
38470b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
38480b57cec5SDimitry Andric
38490b57cec5SDimitry Andric // Splat 1.0 into a vector
38500b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::LDI_D), Ws1).addImm(1);
38510b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::FFINT_U_D), Ws2).addReg(Ws1);
38520b57cec5SDimitry Andric
38530b57cec5SDimitry Andric // Emit 1.0 * fexp2(Wt)
38540b57cec5SDimitry Andric BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_D), MI.getOperand(0).getReg())
38550b57cec5SDimitry Andric .addReg(Ws2)
38560b57cec5SDimitry Andric .addReg(MI.getOperand(1).getReg());
38570b57cec5SDimitry Andric
38580b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now.
38590b57cec5SDimitry Andric return BB;
38600b57cec5SDimitry Andric }
3861