blob: a62ae07c12b65e38b1e6618f3748f5d1f6d9f195 [file] [log] [blame]
Eugene Zelenko79220eae2017-08-03 22:12:30 +00001//===- MipsSEISelLowering.cpp - MipsSE DAG Lowering Interface -------------===//
Akira Hatanaka96ca1822013-03-13 00:54:29 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Subclass of MipsTargetLowering specialized for mips32/64.
11//
12//===----------------------------------------------------------------------===//
Eugene Zelenko79220eae2017-08-03 22:12:30 +000013
Akira Hatanaka96ca1822013-03-13 00:54:29 +000014#include "MipsSEISelLowering.h"
Eric Christopher79cc1e32014-09-02 22:28:02 +000015#include "MipsMachineFunction.h"
Akira Hatanaka96ca1822013-03-13 00:54:29 +000016#include "MipsRegisterInfo.h"
Eugene Zelenko79220eae2017-08-03 22:12:30 +000017#include "MipsSubtarget.h"
Simon Dardis548a53f2017-01-10 16:40:57 +000018#include "llvm/ADT/APInt.h"
Eugene Zelenko79220eae2017-08-03 22:12:30 +000019#include "llvm/ADT/ArrayRef.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/Triple.h"
23#include "llvm/CodeGen/CallingConvLower.h"
24#include "llvm/CodeGen/ISDOpcodes.h"
25#include "llvm/CodeGen/MachineBasicBlock.h"
26#include "llvm/CodeGen/MachineFunction.h"
27#include "llvm/CodeGen/MachineInstr.h"
Akira Hatanaka96ca1822013-03-13 00:54:29 +000028#include "llvm/CodeGen/MachineInstrBuilder.h"
Eugene Zelenko79220eae2017-08-03 22:12:30 +000029#include "llvm/CodeGen/MachineMemOperand.h"
Akira Hatanaka96ca1822013-03-13 00:54:29 +000030#include "llvm/CodeGen/MachineRegisterInfo.h"
Eugene Zelenko79220eae2017-08-03 22:12:30 +000031#include "llvm/CodeGen/SelectionDAG.h"
32#include "llvm/CodeGen/SelectionDAGNodes.h"
David Blaikie3f833ed2017-11-08 01:01:31 +000033#include "llvm/CodeGen/TargetInstrInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000034#include "llvm/CodeGen/TargetSubtargetInfo.h"
Craig Topper2fa14362018-03-29 17:21:10 +000035#include "llvm/CodeGen/ValueTypes.h"
Eugene Zelenko79220eae2017-08-03 22:12:30 +000036#include "llvm/IR/DebugLoc.h"
Akira Hatanakaa6bbde52013-04-13 02:13:30 +000037#include "llvm/IR/Intrinsics.h"
Eugene Zelenko79220eae2017-08-03 22:12:30 +000038#include "llvm/Support/Casting.h"
Akira Hatanaka96ca1822013-03-13 00:54:29 +000039#include "llvm/Support/CommandLine.h"
Daniel Sanders62aeab82013-10-30 13:31:27 +000040#include "llvm/Support/Debug.h"
Simon Dardis548a53f2017-01-10 16:40:57 +000041#include "llvm/Support/ErrorHandling.h"
David Blaikie13e77db2018-03-23 23:58:25 +000042#include "llvm/Support/MachineValueType.h"
Eugene Zelenko79220eae2017-08-03 22:12:30 +000043#include "llvm/Support/MathExtras.h"
Hans Wennborg3e9b1c12013-10-30 16:10:10 +000044#include "llvm/Support/raw_ostream.h"
Eugene Zelenko79220eae2017-08-03 22:12:30 +000045#include <algorithm>
46#include <cassert>
47#include <cstdint>
48#include <iterator>
49#include <utility>
Akira Hatanaka96ca1822013-03-13 00:54:29 +000050
51using namespace llvm;
52
Chandler Carruth84e68b22014-04-22 02:41:26 +000053#define DEBUG_TYPE "mips-isel"
54
Akira Hatanaka96ca1822013-03-13 00:54:29 +000055static cl::opt<bool>
Simon Dardis57f4ae42016-08-04 09:17:07 +000056UseMipsTailCalls("mips-tail-calls", cl::Hidden,
Simon Dardisd2ed8ab2016-09-27 13:15:54 +000057 cl::desc("MIPS: permit tail calls."), cl::init(false));
Akira Hatanaka96ca1822013-03-13 00:54:29 +000058
Akira Hatanaka63791212013-09-07 00:52:30 +000059static cl::opt<bool> NoDPLoadStore("mno-ldc1-sdc1", cl::init(false),
60 cl::desc("Expand double precision loads and "
61 "stores to their single precision "
62 "counterparts"));
63
Eric Christopherb1526602014-09-19 23:30:42 +000064MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM,
Eric Christopher8924d272014-07-18 23:25:04 +000065 const MipsSubtarget &STI)
66 : MipsTargetLowering(TM, STI) {
Akira Hatanaka96ca1822013-03-13 00:54:29 +000067 // Set up the register classes
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +000068 addRegisterClass(MVT::i32, &Mips::GPR32RegClass);
Akira Hatanaka96ca1822013-03-13 00:54:29 +000069
Eric Christopher1c29a652014-07-18 22:55:25 +000070 if (Subtarget.isGP64bit())
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +000071 addRegisterClass(MVT::i64, &Mips::GPR64RegClass);
Akira Hatanaka96ca1822013-03-13 00:54:29 +000072
Eric Christopher1c29a652014-07-18 22:55:25 +000073 if (Subtarget.hasDSP() || Subtarget.hasMSA()) {
Daniel Sanders36c671e2013-09-27 09:44:59 +000074 // Expand all truncating stores and extending loads.
Ahmed Bougacha67dd2d22015-01-07 21:27:10 +000075 for (MVT VT0 : MVT::vector_valuetypes()) {
Ahmed Bougacha2b6917b2015-01-08 00:51:32 +000076 for (MVT VT1 : MVT::vector_valuetypes()) {
Ahmed Bougacha67dd2d22015-01-07 21:27:10 +000077 setTruncStoreAction(VT0, VT1, Expand);
Ahmed Bougacha2b6917b2015-01-08 00:51:32 +000078 setLoadExtAction(ISD::SEXTLOAD, VT0, VT1, Expand);
79 setLoadExtAction(ISD::ZEXTLOAD, VT0, VT1, Expand);
80 setLoadExtAction(ISD::EXTLOAD, VT0, VT1, Expand);
81 }
Daniel Sanders36c671e2013-09-27 09:44:59 +000082 }
83 }
84
Eric Christopher1c29a652014-07-18 22:55:25 +000085 if (Subtarget.hasDSP()) {
Akira Hatanaka96ca1822013-03-13 00:54:29 +000086 MVT::SimpleValueType VecTys[2] = {MVT::v2i16, MVT::v4i8};
87
88 for (unsigned i = 0; i < array_lengthof(VecTys); ++i) {
Akira Hatanaka654655f2013-08-14 00:53:38 +000089 addRegisterClass(VecTys[i], &Mips::DSPRRegClass);
Akira Hatanaka96ca1822013-03-13 00:54:29 +000090
91 // Expand all builtin opcodes.
92 for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
93 setOperationAction(Opc, VecTys[i], Expand);
94
Akira Hatanaka2f088222013-04-13 00:55:41 +000095 setOperationAction(ISD::ADD, VecTys[i], Legal);
96 setOperationAction(ISD::SUB, VecTys[i], Legal);
Akira Hatanaka96ca1822013-03-13 00:54:29 +000097 setOperationAction(ISD::LOAD, VecTys[i], Legal);
98 setOperationAction(ISD::STORE, VecTys[i], Legal);
99 setOperationAction(ISD::BITCAST, VecTys[i], Legal);
100 }
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000101
102 setTargetDAGCombine(ISD::SHL);
103 setTargetDAGCombine(ISD::SRA);
104 setTargetDAGCombine(ISD::SRL);
Akira Hatanaka68741cc2013-04-30 22:37:26 +0000105 setTargetDAGCombine(ISD::SETCC);
106 setTargetDAGCombine(ISD::VSELECT);
Akira Hatanaka96ca1822013-03-13 00:54:29 +0000107 }
108
Eric Christopher1c29a652014-07-18 22:55:25 +0000109 if (Subtarget.hasDSPR2())
Akira Hatanaka2f088222013-04-13 00:55:41 +0000110 setOperationAction(ISD::MUL, MVT::v2i16, Legal);
111
Eric Christopher1c29a652014-07-18 22:55:25 +0000112 if (Subtarget.hasMSA()) {
Daniel Sandersc65f58a2013-09-11 10:15:48 +0000113 addMSAIntType(MVT::v16i8, &Mips::MSA128BRegClass);
114 addMSAIntType(MVT::v8i16, &Mips::MSA128HRegClass);
115 addMSAIntType(MVT::v4i32, &Mips::MSA128WRegClass);
116 addMSAIntType(MVT::v2i64, &Mips::MSA128DRegClass);
117 addMSAFloatType(MVT::v8f16, &Mips::MSA128HRegClass);
118 addMSAFloatType(MVT::v4f32, &Mips::MSA128WRegClass);
119 addMSAFloatType(MVT::v2f64, &Mips::MSA128DRegClass);
Daniel Sandersf7456c72013-09-23 13:22:24 +0000120
Simon Dardis0e2ee3b2016-11-18 16:17:44 +0000121 // f16 is a storage-only type, always promote it to f32.
122 addRegisterClass(MVT::f16, &Mips::MSA128HRegClass);
123 setOperationAction(ISD::SETCC, MVT::f16, Promote);
124 setOperationAction(ISD::BR_CC, MVT::f16, Promote);
125 setOperationAction(ISD::SELECT_CC, MVT::f16, Promote);
126 setOperationAction(ISD::SELECT, MVT::f16, Promote);
127 setOperationAction(ISD::FADD, MVT::f16, Promote);
128 setOperationAction(ISD::FSUB, MVT::f16, Promote);
129 setOperationAction(ISD::FMUL, MVT::f16, Promote);
130 setOperationAction(ISD::FDIV, MVT::f16, Promote);
131 setOperationAction(ISD::FREM, MVT::f16, Promote);
132 setOperationAction(ISD::FMA, MVT::f16, Promote);
133 setOperationAction(ISD::FNEG, MVT::f16, Promote);
134 setOperationAction(ISD::FABS, MVT::f16, Promote);
135 setOperationAction(ISD::FCEIL, MVT::f16, Promote);
136 setOperationAction(ISD::FCOPYSIGN, MVT::f16, Promote);
137 setOperationAction(ISD::FCOS, MVT::f16, Promote);
138 setOperationAction(ISD::FP_EXTEND, MVT::f16, Promote);
139 setOperationAction(ISD::FFLOOR, MVT::f16, Promote);
140 setOperationAction(ISD::FNEARBYINT, MVT::f16, Promote);
141 setOperationAction(ISD::FPOW, MVT::f16, Promote);
142 setOperationAction(ISD::FPOWI, MVT::f16, Promote);
143 setOperationAction(ISD::FRINT, MVT::f16, Promote);
144 setOperationAction(ISD::FSIN, MVT::f16, Promote);
145 setOperationAction(ISD::FSINCOS, MVT::f16, Promote);
146 setOperationAction(ISD::FSQRT, MVT::f16, Promote);
147 setOperationAction(ISD::FEXP, MVT::f16, Promote);
148 setOperationAction(ISD::FEXP2, MVT::f16, Promote);
149 setOperationAction(ISD::FLOG, MVT::f16, Promote);
150 setOperationAction(ISD::FLOG2, MVT::f16, Promote);
151 setOperationAction(ISD::FLOG10, MVT::f16, Promote);
152 setOperationAction(ISD::FROUND, MVT::f16, Promote);
153 setOperationAction(ISD::FTRUNC, MVT::f16, Promote);
154 setOperationAction(ISD::FMINNUM, MVT::f16, Promote);
155 setOperationAction(ISD::FMAXNUM, MVT::f16, Promote);
156 setOperationAction(ISD::FMINNAN, MVT::f16, Promote);
157 setOperationAction(ISD::FMAXNAN, MVT::f16, Promote);
158
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000159 setTargetDAGCombine(ISD::AND);
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000160 setTargetDAGCombine(ISD::OR);
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000161 setTargetDAGCombine(ISD::SRA);
Daniel Sanderse1d24352013-09-24 12:04:44 +0000162 setTargetDAGCombine(ISD::VSELECT);
Daniel Sandersf7456c72013-09-23 13:22:24 +0000163 setTargetDAGCombine(ISD::XOR);
Jack Carter3a2c2d42013-08-13 20:54:07 +0000164 }
165
Eric Christophere8ae3e32015-05-07 23:10:21 +0000166 if (!Subtarget.useSoftFloat()) {
Akira Hatanaka96ca1822013-03-13 00:54:29 +0000167 addRegisterClass(MVT::f32, &Mips::FGR32RegClass);
168
169 // When dealing with single precision only, use libcalls
Eric Christopher1c29a652014-07-18 22:55:25 +0000170 if (!Subtarget.isSingleFloat()) {
171 if (Subtarget.isFP64bit())
Akira Hatanaka96ca1822013-03-13 00:54:29 +0000172 addRegisterClass(MVT::f64, &Mips::FGR64RegClass);
173 else
174 addRegisterClass(MVT::f64, &Mips::AFGR64RegClass);
175 }
176 }
177
Akira Hatanakabe8612f2013-03-30 01:36:35 +0000178 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
179 setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
180 setOperationAction(ISD::MULHS, MVT::i32, Custom);
181 setOperationAction(ISD::MULHU, MVT::i32, Custom);
182
Eric Christopher1c29a652014-07-18 22:55:25 +0000183 if (Subtarget.hasCnMips())
Kai Nacke93fe5e82014-03-20 11:51:58 +0000184 setOperationAction(ISD::MUL, MVT::i64, Legal);
Eric Christopher1c29a652014-07-18 22:55:25 +0000185 else if (Subtarget.isGP64bit())
Kai Nacke93fe5e82014-03-20 11:51:58 +0000186 setOperationAction(ISD::MUL, MVT::i64, Custom);
187
Eric Christopher1c29a652014-07-18 22:55:25 +0000188 if (Subtarget.isGP64bit()) {
Vasileios Kalintirisef96a8e2015-01-26 12:33:22 +0000189 setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom);
190 setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom);
Akira Hatanaka4f1130e2013-04-11 19:29:26 +0000191 setOperationAction(ISD::MULHS, MVT::i64, Custom);
192 setOperationAction(ISD::MULHU, MVT::i64, Custom);
Jan Vesely54468a5a2014-10-17 14:45:28 +0000193 setOperationAction(ISD::SDIVREM, MVT::i64, Custom);
194 setOperationAction(ISD::UDIVREM, MVT::i64, Custom);
Akira Hatanaka4f1130e2013-04-11 19:29:26 +0000195 }
Akira Hatanakabe8612f2013-03-30 01:36:35 +0000196
Akira Hatanakaa6bbde52013-04-13 02:13:30 +0000197 setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom);
198 setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom);
199
Akira Hatanakabe8612f2013-03-30 01:36:35 +0000200 setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
201 setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
Akira Hatanaka96ca1822013-03-13 00:54:29 +0000202 setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
203 setOperationAction(ISD::LOAD, MVT::i32, Custom);
204 setOperationAction(ISD::STORE, MVT::i32, Custom);
205
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000206 setTargetDAGCombine(ISD::MUL);
Akira Hatanaka9efcd762013-03-30 01:42:24 +0000207
Daniel Sandersce09d072013-08-28 12:14:50 +0000208 setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
Daniel Sanderse6ed5b72013-08-28 12:04:29 +0000209 setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);
210 setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
211
Akira Hatanaka63791212013-09-07 00:52:30 +0000212 if (NoDPLoadStore) {
213 setOperationAction(ISD::LOAD, MVT::f64, Custom);
214 setOperationAction(ISD::STORE, MVT::f64, Custom);
215 }
216
Eric Christopher1c29a652014-07-18 22:55:25 +0000217 if (Subtarget.hasMips32r6()) {
Daniel Sanders308181e2014-06-12 10:44:10 +0000218 // MIPS32r6 replaces the accumulator-based multiplies with a three register
219 // instruction
Daniel Sanders826f8b32014-06-12 10:54:16 +0000220 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
221 setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
Daniel Sanders308181e2014-06-12 10:44:10 +0000222 setOperationAction(ISD::MUL, MVT::i32, Legal);
223 setOperationAction(ISD::MULHS, MVT::i32, Legal);
224 setOperationAction(ISD::MULHU, MVT::i32, Legal);
225
226 // MIPS32r6 replaces the accumulator-based division/remainder with separate
227 // three register division and remainder instructions.
228 setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
229 setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
230 setOperationAction(ISD::SDIV, MVT::i32, Legal);
231 setOperationAction(ISD::UDIV, MVT::i32, Legal);
232 setOperationAction(ISD::SREM, MVT::i32, Legal);
233 setOperationAction(ISD::UREM, MVT::i32, Legal);
Daniel Sanders0fa60412014-06-12 13:39:06 +0000234
235 // MIPS32r6 replaces conditional moves with an equivalent that removes the
236 // need for three GPR read ports.
237 setOperationAction(ISD::SETCC, MVT::i32, Legal);
238 setOperationAction(ISD::SELECT, MVT::i32, Legal);
239 setOperationAction(ISD::SELECT_CC, MVT::i32, Expand);
240
241 setOperationAction(ISD::SETCC, MVT::f32, Legal);
242 setOperationAction(ISD::SELECT, MVT::f32, Legal);
243 setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
244
Eric Christopher1c29a652014-07-18 22:55:25 +0000245 assert(Subtarget.isFP64bit() && "FR=1 is required for MIPS32r6");
Daniel Sanders0fa60412014-06-12 13:39:06 +0000246 setOperationAction(ISD::SETCC, MVT::f64, Legal);
Stefan Maksimovicbe0bc712017-07-20 13:08:18 +0000247 setOperationAction(ISD::SELECT, MVT::f64, Custom);
Daniel Sanders0fa60412014-06-12 13:39:06 +0000248 setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
249
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000250 setOperationAction(ISD::BRCOND, MVT::Other, Legal);
251
Daniel Sanders0fa60412014-06-12 13:39:06 +0000252 // Floating point > and >= are supported via < and <=
253 setCondCodeAction(ISD::SETOGE, MVT::f32, Expand);
254 setCondCodeAction(ISD::SETOGT, MVT::f32, Expand);
255 setCondCodeAction(ISD::SETUGE, MVT::f32, Expand);
256 setCondCodeAction(ISD::SETUGT, MVT::f32, Expand);
257
258 setCondCodeAction(ISD::SETOGE, MVT::f64, Expand);
259 setCondCodeAction(ISD::SETOGT, MVT::f64, Expand);
260 setCondCodeAction(ISD::SETUGE, MVT::f64, Expand);
261 setCondCodeAction(ISD::SETUGT, MVT::f64, Expand);
Daniel Sanders308181e2014-06-12 10:44:10 +0000262 }
263
Eric Christopher1c29a652014-07-18 22:55:25 +0000264 if (Subtarget.hasMips64r6()) {
Daniel Sanders308181e2014-06-12 10:44:10 +0000265 // MIPS64r6 replaces the accumulator-based multiplies with a three register
266 // instruction
Vasileios Kalintirisef96a8e2015-01-26 12:33:22 +0000267 setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
268 setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
Daniel Sanders308181e2014-06-12 10:44:10 +0000269 setOperationAction(ISD::MUL, MVT::i64, Legal);
270 setOperationAction(ISD::MULHS, MVT::i64, Legal);
271 setOperationAction(ISD::MULHU, MVT::i64, Legal);
272
273 // MIPS32r6 replaces the accumulator-based division/remainder with separate
274 // three register division and remainder instructions.
275 setOperationAction(ISD::SDIVREM, MVT::i64, Expand);
276 setOperationAction(ISD::UDIVREM, MVT::i64, Expand);
277 setOperationAction(ISD::SDIV, MVT::i64, Legal);
278 setOperationAction(ISD::UDIV, MVT::i64, Legal);
279 setOperationAction(ISD::SREM, MVT::i64, Legal);
280 setOperationAction(ISD::UREM, MVT::i64, Legal);
Daniel Sanders0fa60412014-06-12 13:39:06 +0000281
282 // MIPS64r6 replaces conditional moves with an equivalent that removes the
283 // need for three GPR read ports.
284 setOperationAction(ISD::SETCC, MVT::i64, Legal);
285 setOperationAction(ISD::SELECT, MVT::i64, Legal);
286 setOperationAction(ISD::SELECT_CC, MVT::i64, Expand);
Daniel Sanders308181e2014-06-12 10:44:10 +0000287 }
288
Eric Christopher23a3a7c2015-02-26 00:00:24 +0000289 computeRegisterProperties(Subtarget.getRegisterInfo());
Akira Hatanaka96ca1822013-03-13 00:54:29 +0000290}
291
292const MipsTargetLowering *
Eric Christopherb1526602014-09-19 23:30:42 +0000293llvm::createMipsSETargetLowering(const MipsTargetMachine &TM,
Eric Christopher8924d272014-07-18 23:25:04 +0000294 const MipsSubtarget &STI) {
295 return new MipsSETargetLowering(TM, STI);
Akira Hatanaka96ca1822013-03-13 00:54:29 +0000296}
297
Eric Christopherbf33a3c2014-07-02 23:18:40 +0000298const TargetRegisterClass *
299MipsSETargetLowering::getRepRegClassFor(MVT VT) const {
300 if (VT == MVT::Untyped)
Eric Christopher1c29a652014-07-18 22:55:25 +0000301 return Subtarget.hasDSP() ? &Mips::ACC64DSPRegClass : &Mips::ACC64RegClass;
Eric Christopherbf33a3c2014-07-02 23:18:40 +0000302
303 return TargetLowering::getRepRegClassFor(VT);
304}
305
Daniel Sanders7a289d02013-09-23 12:02:46 +0000306// Enable MSA support for the given integer type and Register class.
Daniel Sanders3c9a0ad2013-08-23 10:10:13 +0000307void MipsSETargetLowering::
Daniel Sandersc65f58a2013-09-11 10:15:48 +0000308addMSAIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) {
309 addRegisterClass(Ty, RC);
310
311 // Expand all builtin opcodes.
312 for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
313 setOperationAction(Opc, Ty, Expand);
314
315 setOperationAction(ISD::BITCAST, Ty, Legal);
316 setOperationAction(ISD::LOAD, Ty, Legal);
317 setOperationAction(ISD::STORE, Ty, Legal);
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000318 setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Custom);
319 setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Legal);
Daniel Sanders7a289d02013-09-23 12:02:46 +0000320 setOperationAction(ISD::BUILD_VECTOR, Ty, Custom);
Daniel Sandersc65f58a2013-09-11 10:15:48 +0000321
Daniel Sandersfa5ab1c2013-09-11 10:28:16 +0000322 setOperationAction(ISD::ADD, Ty, Legal);
Daniel Sanders8ca81e42013-09-23 12:57:42 +0000323 setOperationAction(ISD::AND, Ty, Legal);
Daniel Sandersfbcb5822013-09-11 11:58:30 +0000324 setOperationAction(ISD::CTLZ, Ty, Legal);
Daniel Sanders766cb692013-09-23 13:40:21 +0000325 setOperationAction(ISD::CTPOP, Ty, Legal);
Daniel Sandersfbcb5822013-09-11 11:58:30 +0000326 setOperationAction(ISD::MUL, Ty, Legal);
Daniel Sanders8ca81e42013-09-23 12:57:42 +0000327 setOperationAction(ISD::OR, Ty, Legal);
Daniel Sanders607952b2013-09-11 10:38:58 +0000328 setOperationAction(ISD::SDIV, Ty, Legal);
Daniel Sanders0210dd42013-10-01 10:22:35 +0000329 setOperationAction(ISD::SREM, Ty, Legal);
Daniel Sandersfbcb5822013-09-11 11:58:30 +0000330 setOperationAction(ISD::SHL, Ty, Legal);
331 setOperationAction(ISD::SRA, Ty, Legal);
332 setOperationAction(ISD::SRL, Ty, Legal);
333 setOperationAction(ISD::SUB, Ty, Legal);
Simon Pilgrim386b8dd2018-02-17 21:29:45 +0000334 setOperationAction(ISD::SMAX, Ty, Legal);
335 setOperationAction(ISD::SMIN, Ty, Legal);
Daniel Sanders607952b2013-09-11 10:38:58 +0000336 setOperationAction(ISD::UDIV, Ty, Legal);
Daniel Sanders0210dd42013-10-01 10:22:35 +0000337 setOperationAction(ISD::UREM, Ty, Legal);
Simon Pilgrim386b8dd2018-02-17 21:29:45 +0000338 setOperationAction(ISD::UMAX, Ty, Legal);
339 setOperationAction(ISD::UMIN, Ty, Legal);
Daniel Sanderse5087042013-09-24 14:02:15 +0000340 setOperationAction(ISD::VECTOR_SHUFFLE, Ty, Custom);
Daniel Sanderse1d24352013-09-24 12:04:44 +0000341 setOperationAction(ISD::VSELECT, Ty, Legal);
Daniel Sanders8ca81e42013-09-23 12:57:42 +0000342 setOperationAction(ISD::XOR, Ty, Legal);
Daniel Sandersfd538dc2013-09-24 10:46:19 +0000343
Daniel Sanders015972b2013-10-11 10:00:06 +0000344 if (Ty == MVT::v4i32 || Ty == MVT::v2i64) {
345 setOperationAction(ISD::FP_TO_SINT, Ty, Legal);
346 setOperationAction(ISD::FP_TO_UINT, Ty, Legal);
347 setOperationAction(ISD::SINT_TO_FP, Ty, Legal);
348 setOperationAction(ISD::UINT_TO_FP, Ty, Legal);
349 }
350
Daniel Sandersfd538dc2013-09-24 10:46:19 +0000351 setOperationAction(ISD::SETCC, Ty, Legal);
352 setCondCodeAction(ISD::SETNE, Ty, Expand);
353 setCondCodeAction(ISD::SETGE, Ty, Expand);
354 setCondCodeAction(ISD::SETGT, Ty, Expand);
355 setCondCodeAction(ISD::SETUGE, Ty, Expand);
356 setCondCodeAction(ISD::SETUGT, Ty, Expand);
Daniel Sandersc65f58a2013-09-11 10:15:48 +0000357}
358
Daniel Sanders7a289d02013-09-23 12:02:46 +0000359// Enable MSA support for the given floating-point type and Register class.
Daniel Sandersc65f58a2013-09-11 10:15:48 +0000360void MipsSETargetLowering::
361addMSAFloatType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) {
Daniel Sanders3c9a0ad2013-08-23 10:10:13 +0000362 addRegisterClass(Ty, RC);
Jack Carterbabdcc82013-08-15 12:24:57 +0000363
364 // Expand all builtin opcodes.
365 for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
366 setOperationAction(Opc, Ty, Expand);
367
368 setOperationAction(ISD::LOAD, Ty, Legal);
369 setOperationAction(ISD::STORE, Ty, Legal);
370 setOperationAction(ISD::BITCAST, Ty, Legal);
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000371 setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Legal);
Daniel Sandersa5150702013-09-27 12:31:32 +0000372 setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Legal);
Daniel Sanders1dfddc72013-10-15 13:14:41 +0000373 setOperationAction(ISD::BUILD_VECTOR, Ty, Custom);
Daniel Sandersf5bd9372013-09-11 10:51:30 +0000374
375 if (Ty != MVT::v8f16) {
Daniel Sanders4f3ff1b2013-09-24 13:02:08 +0000376 setOperationAction(ISD::FABS, Ty, Legal);
Daniel Sandersf5bd9372013-09-11 10:51:30 +0000377 setOperationAction(ISD::FADD, Ty, Legal);
378 setOperationAction(ISD::FDIV, Ty, Legal);
Daniel Sandersa9521602013-10-23 10:36:52 +0000379 setOperationAction(ISD::FEXP2, Ty, Legal);
Daniel Sandersf5bd9372013-09-11 10:51:30 +0000380 setOperationAction(ISD::FLOG2, Ty, Legal);
Daniel Sandersd7103f32013-10-11 10:14:25 +0000381 setOperationAction(ISD::FMA, Ty, Legal);
Daniel Sandersf5bd9372013-09-11 10:51:30 +0000382 setOperationAction(ISD::FMUL, Ty, Legal);
383 setOperationAction(ISD::FRINT, Ty, Legal);
384 setOperationAction(ISD::FSQRT, Ty, Legal);
385 setOperationAction(ISD::FSUB, Ty, Legal);
Daniel Sanderse1d24352013-09-24 12:04:44 +0000386 setOperationAction(ISD::VSELECT, Ty, Legal);
Daniel Sandersfd538dc2013-09-24 10:46:19 +0000387
388 setOperationAction(ISD::SETCC, Ty, Legal);
389 setCondCodeAction(ISD::SETOGE, Ty, Expand);
390 setCondCodeAction(ISD::SETOGT, Ty, Expand);
391 setCondCodeAction(ISD::SETUGE, Ty, Expand);
392 setCondCodeAction(ISD::SETUGT, Ty, Expand);
393 setCondCodeAction(ISD::SETGE, Ty, Expand);
394 setCondCodeAction(ISD::SETGT, Ty, Expand);
Daniel Sandersf5bd9372013-09-11 10:51:30 +0000395 }
Jack Carterbabdcc82013-08-15 12:24:57 +0000396}
Akira Hatanaka96ca1822013-03-13 00:54:29 +0000397
Stefan Maksimovicbe0bc712017-07-20 13:08:18 +0000398SDValue MipsSETargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
Stefan Maksimovicbe0bc712017-07-20 13:08:18 +0000399 if(!Subtarget.hasMips32r6())
400 return MipsTargetLowering::LowerOperation(Op, DAG);
401
402 EVT ResTy = Op->getValueType(0);
403 SDLoc DL(Op);
404
405 // Although MTC1_D64 takes an i32 and writes an f64, the upper 32 bits of the
406 // floating point register are undefined. Not really an issue as sel.d, which
407 // is produced from an FSELECT node, only looks at bit 0.
408 SDValue Tmp = DAG.getNode(MipsISD::MTC1_D64, DL, MVT::f64, Op->getOperand(0));
409 return DAG.getNode(MipsISD::FSELECT, DL, ResTy, Tmp, Op->getOperand(1),
410 Op->getOperand(2));
411}
412
Akira Hatanaka96ca1822013-03-13 00:54:29 +0000413bool
Matt Arsenault6f2a5262014-07-27 17:46:40 +0000414MipsSETargetLowering::allowsMisalignedMemoryAccesses(EVT VT,
415 unsigned,
416 unsigned,
417 bool *Fast) const {
Akira Hatanaka96ca1822013-03-13 00:54:29 +0000418 MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy;
419
Eric Christopher1c29a652014-07-18 22:55:25 +0000420 if (Subtarget.systemSupportsUnalignedAccess()) {
Daniel Sandersac272632014-05-23 13:18:02 +0000421 // MIPS32r6/MIPS64r6 is required to support unaligned access. It's
422 // implementation defined whether this is handled by hardware, software, or
423 // a hybrid of the two but it's expected that most implementations will
424 // handle the majority of cases in hardware.
425 if (Fast)
426 *Fast = true;
427 return true;
428 }
429
Akira Hatanaka96ca1822013-03-13 00:54:29 +0000430 switch (SVT) {
431 case MVT::i64:
432 case MVT::i32:
433 if (Fast)
434 *Fast = true;
435 return true;
436 default:
437 return false;
438 }
439}
440
Akira Hatanakabe8612f2013-03-30 01:36:35 +0000441SDValue MipsSETargetLowering::LowerOperation(SDValue Op,
442 SelectionDAG &DAG) const {
443 switch(Op.getOpcode()) {
Akira Hatanaka63791212013-09-07 00:52:30 +0000444 case ISD::LOAD: return lowerLOAD(Op, DAG);
445 case ISD::STORE: return lowerSTORE(Op, DAG);
Akira Hatanakabe8612f2013-03-30 01:36:35 +0000446 case ISD::SMUL_LOHI: return lowerMulDiv(Op, MipsISD::Mult, true, true, DAG);
447 case ISD::UMUL_LOHI: return lowerMulDiv(Op, MipsISD::Multu, true, true, DAG);
448 case ISD::MULHS: return lowerMulDiv(Op, MipsISD::Mult, false, true, DAG);
449 case ISD::MULHU: return lowerMulDiv(Op, MipsISD::Multu, false, true, DAG);
450 case ISD::MUL: return lowerMulDiv(Op, MipsISD::Mult, true, false, DAG);
451 case ISD::SDIVREM: return lowerMulDiv(Op, MipsISD::DivRem, true, true, DAG);
Akira Hatanakad8fb0322013-04-22 20:13:37 +0000452 case ISD::UDIVREM: return lowerMulDiv(Op, MipsISD::DivRemU, true, true,
453 DAG);
Akira Hatanakaa6bbde52013-04-13 02:13:30 +0000454 case ISD::INTRINSIC_WO_CHAIN: return lowerINTRINSIC_WO_CHAIN(Op, DAG);
455 case ISD::INTRINSIC_W_CHAIN: return lowerINTRINSIC_W_CHAIN(Op, DAG);
Daniel Sanderse6ed5b72013-08-28 12:04:29 +0000456 case ISD::INTRINSIC_VOID: return lowerINTRINSIC_VOID(Op, DAG);
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000457 case ISD::EXTRACT_VECTOR_ELT: return lowerEXTRACT_VECTOR_ELT(Op, DAG);
Daniel Sanders7a289d02013-09-23 12:02:46 +0000458 case ISD::BUILD_VECTOR: return lowerBUILD_VECTOR(Op, DAG);
Daniel Sanderse5087042013-09-24 14:02:15 +0000459 case ISD::VECTOR_SHUFFLE: return lowerVECTOR_SHUFFLE(Op, DAG);
Stefan Maksimovicbe0bc712017-07-20 13:08:18 +0000460 case ISD::SELECT: return lowerSELECT(Op, DAG);
Akira Hatanakabe8612f2013-03-30 01:36:35 +0000461 }
462
463 return MipsTargetLowering::LowerOperation(Op, DAG);
464}
465
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000466// Fold zero extensions into MipsISD::VEXTRACT_[SZ]EXT_ELT
467//
468// Performs the following transformations:
469// - Changes MipsISD::VEXTRACT_[SZ]EXT_ELT to zero extension if its
470// sign/zero-extension is completely overwritten by the new one performed by
471// the ISD::AND.
472// - Removes redundant zero extensions performed by an ISD::AND.
473static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
474 TargetLowering::DAGCombinerInfo &DCI,
Eric Christopher1c29a652014-07-18 22:55:25 +0000475 const MipsSubtarget &Subtarget) {
476 if (!Subtarget.hasMSA())
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000477 return SDValue();
478
479 SDValue Op0 = N->getOperand(0);
480 SDValue Op1 = N->getOperand(1);
481 unsigned Op0Opcode = Op0->getOpcode();
482
483 // (and (MipsVExtract[SZ]Ext $a, $b, $c), imm:$d)
484 // where $d + 1 == 2^n and n == 32
485 // or $d + 1 == 2^n and n <= 32 and ZExt
486 // -> (MipsVExtractZExt $a, $b, $c)
487 if (Op0Opcode == MipsISD::VEXTRACT_SEXT_ELT ||
488 Op0Opcode == MipsISD::VEXTRACT_ZEXT_ELT) {
489 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(Op1);
490
491 if (!Mask)
492 return SDValue();
493
494 int32_t Log2IfPositive = (Mask->getAPIntValue() + 1).exactLogBase2();
495
496 if (Log2IfPositive <= 0)
497 return SDValue(); // Mask+1 is not a power of 2
498
499 SDValue Op0Op2 = Op0->getOperand(2);
500 EVT ExtendTy = cast<VTSDNode>(Op0Op2)->getVT();
501 unsigned ExtendTySize = ExtendTy.getSizeInBits();
502 unsigned Log2 = Log2IfPositive;
503
504 if ((Op0Opcode == MipsISD::VEXTRACT_ZEXT_ELT && Log2 >= ExtendTySize) ||
505 Log2 == ExtendTySize) {
506 SDValue Ops[] = { Op0->getOperand(0), Op0->getOperand(1), Op0Op2 };
Chandler Carruth356665a2014-08-01 22:09:43 +0000507 return DAG.getNode(MipsISD::VEXTRACT_ZEXT_ELT, SDLoc(Op0),
508 Op0->getVTList(),
509 makeArrayRef(Ops, Op0->getNumOperands()));
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000510 }
511 }
512
513 return SDValue();
514}
515
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000516// Determine if the specified node is a constant vector splat.
517//
518// Returns true and sets Imm if:
519// * N is a ISD::BUILD_VECTOR representing a constant splat
520//
521// This function is quite similar to MipsSEDAGToDAGISel::selectVSplat. The
522// differences are that it assumes the MSA has already been checked and the
523// arbitrary requirement for a maximum of 32-bit integers isn't applied (and
524// must not be in order for binsri.d to be selectable).
525static bool isVSplat(SDValue N, APInt &Imm, bool IsLittleEndian) {
526 BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N.getNode());
527
Craig Topper062a2ba2014-04-25 05:30:21 +0000528 if (!Node)
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000529 return false;
530
531 APInt SplatValue, SplatUndef;
532 unsigned SplatBitSize;
533 bool HasAnyUndefs;
534
535 if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
536 8, !IsLittleEndian))
537 return false;
538
539 Imm = SplatValue;
540
541 return true;
542}
543
Daniel Sandersab94b532013-10-30 15:20:38 +0000544// Test whether the given node is an all-ones build_vector.
545static bool isVectorAllOnes(SDValue N) {
546 // Look through bitcasts. Endianness doesn't matter because we are looking
547 // for an all-ones value.
548 if (N->getOpcode() == ISD::BITCAST)
549 N = N->getOperand(0);
550
551 BuildVectorSDNode *BVN = dyn_cast<BuildVectorSDNode>(N);
552
553 if (!BVN)
554 return false;
555
556 APInt SplatValue, SplatUndef;
557 unsigned SplatBitSize;
558 bool HasAnyUndefs;
559
560 // Endianness doesn't matter in this context because we are looking for
561 // an all-ones value.
562 if (BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs))
563 return SplatValue.isAllOnesValue();
564
565 return false;
566}
567
568// Test whether N is the bitwise inverse of OfNode.
569static bool isBitwiseInverse(SDValue N, SDValue OfNode) {
570 if (N->getOpcode() != ISD::XOR)
571 return false;
572
573 if (isVectorAllOnes(N->getOperand(0)))
574 return N->getOperand(1) == OfNode;
575
576 if (isVectorAllOnes(N->getOperand(1)))
577 return N->getOperand(0) == OfNode;
578
579 return false;
580}
581
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000582// Perform combines where ISD::OR is the root node.
583//
584// Performs the following transformations:
585// - (or (and $a, $mask), (and $b, $inv_mask)) => (vselect $mask, $a, $b)
586// where $inv_mask is the bitwise inverse of $mask and the 'or' has a 128-bit
587// vector type.
588static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
589 TargetLowering::DAGCombinerInfo &DCI,
Eric Christopher1c29a652014-07-18 22:55:25 +0000590 const MipsSubtarget &Subtarget) {
591 if (!Subtarget.hasMSA())
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000592 return SDValue();
593
594 EVT Ty = N->getValueType(0);
595
596 if (!Ty.is128BitVector())
597 return SDValue();
598
599 SDValue Op0 = N->getOperand(0);
600 SDValue Op1 = N->getOperand(1);
601
602 if (Op0->getOpcode() == ISD::AND && Op1->getOpcode() == ISD::AND) {
603 SDValue Op0Op0 = Op0->getOperand(0);
604 SDValue Op0Op1 = Op0->getOperand(1);
605 SDValue Op1Op0 = Op1->getOperand(0);
606 SDValue Op1Op1 = Op1->getOperand(1);
Eric Christopher1c29a652014-07-18 22:55:25 +0000607 bool IsLittleEndian = !Subtarget.isLittle();
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000608
609 SDValue IfSet, IfClr, Cond;
Daniel Sandersab94b532013-10-30 15:20:38 +0000610 bool IsConstantMask = false;
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000611 APInt Mask, InvMask;
612
613 // If Op0Op0 is an appropriate mask, try to find it's inverse in either
614 // Op1Op0, or Op1Op1. Keep track of the Cond, IfSet, and IfClr nodes, while
615 // looking.
616 // IfClr will be set if we find a valid match.
617 if (isVSplat(Op0Op0, Mask, IsLittleEndian)) {
618 Cond = Op0Op0;
619 IfSet = Op0Op1;
620
Daniel Sandersc8c50fb2013-11-21 16:11:31 +0000621 if (isVSplat(Op1Op0, InvMask, IsLittleEndian) &&
622 Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask)
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000623 IfClr = Op1Op1;
Daniel Sandersc8c50fb2013-11-21 16:11:31 +0000624 else if (isVSplat(Op1Op1, InvMask, IsLittleEndian) &&
625 Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask)
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000626 IfClr = Op1Op0;
Daniel Sandersab94b532013-10-30 15:20:38 +0000627
628 IsConstantMask = true;
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000629 }
630
631 // If IfClr is not yet set, and Op0Op1 is an appropriate mask, try the same
632 // thing again using this mask.
633 // IfClr will be set if we find a valid match.
634 if (!IfClr.getNode() && isVSplat(Op0Op1, Mask, IsLittleEndian)) {
635 Cond = Op0Op1;
636 IfSet = Op0Op0;
637
Daniel Sandersc8c50fb2013-11-21 16:11:31 +0000638 if (isVSplat(Op1Op0, InvMask, IsLittleEndian) &&
639 Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask)
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000640 IfClr = Op1Op1;
Daniel Sandersc8c50fb2013-11-21 16:11:31 +0000641 else if (isVSplat(Op1Op1, InvMask, IsLittleEndian) &&
642 Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask)
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000643 IfClr = Op1Op0;
Daniel Sandersab94b532013-10-30 15:20:38 +0000644
645 IsConstantMask = true;
646 }
647
648 // If IfClr is not yet set, try looking for a non-constant match.
649 // IfClr will be set if we find a valid match amongst the eight
650 // possibilities.
651 if (!IfClr.getNode()) {
652 if (isBitwiseInverse(Op0Op0, Op1Op0)) {
653 Cond = Op1Op0;
654 IfSet = Op1Op1;
655 IfClr = Op0Op1;
656 } else if (isBitwiseInverse(Op0Op1, Op1Op0)) {
657 Cond = Op1Op0;
658 IfSet = Op1Op1;
659 IfClr = Op0Op0;
660 } else if (isBitwiseInverse(Op0Op0, Op1Op1)) {
661 Cond = Op1Op1;
662 IfSet = Op1Op0;
663 IfClr = Op0Op1;
664 } else if (isBitwiseInverse(Op0Op1, Op1Op1)) {
665 Cond = Op1Op1;
666 IfSet = Op1Op0;
667 IfClr = Op0Op0;
668 } else if (isBitwiseInverse(Op1Op0, Op0Op0)) {
669 Cond = Op0Op0;
670 IfSet = Op0Op1;
671 IfClr = Op1Op1;
672 } else if (isBitwiseInverse(Op1Op1, Op0Op0)) {
673 Cond = Op0Op0;
674 IfSet = Op0Op1;
675 IfClr = Op1Op0;
676 } else if (isBitwiseInverse(Op1Op0, Op0Op1)) {
677 Cond = Op0Op1;
678 IfSet = Op0Op0;
679 IfClr = Op1Op1;
680 } else if (isBitwiseInverse(Op1Op1, Op0Op1)) {
681 Cond = Op0Op1;
682 IfSet = Op0Op0;
683 IfClr = Op1Op0;
684 }
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000685 }
686
687 // At this point, IfClr will be set if we have a valid match.
688 if (!IfClr.getNode())
689 return SDValue();
690
691 assert(Cond.getNode() && IfSet.getNode());
692
693 // Fold degenerate cases.
Daniel Sandersab94b532013-10-30 15:20:38 +0000694 if (IsConstantMask) {
695 if (Mask.isAllOnesValue())
696 return IfSet;
697 else if (Mask == 0)
698 return IfClr;
699 }
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000700
701 // Transform the DAG into an equivalent VSELECT.
Daniel Sandersdf2215452014-03-12 11:54:00 +0000702 return DAG.getNode(ISD::VSELECT, SDLoc(N), Ty, Cond, IfSet, IfClr);
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000703 }
704
705 return SDValue();
706}
707
Simon Dardis9ec9f442018-04-13 16:09:07 +0000708static bool shouldTransformMulToShiftsAddsSubs(APInt C, EVT VT,
709 SelectionDAG &DAG,
710 const MipsSubtarget &Subtarget) {
711 // Estimate the number of operations the below transform will turn a
712 // constant multiply into. The number is approximately how many powers
713 // of two summed together that the constant can be broken down into.
714
715 SmallVector<APInt, 16> WorkStack(1, C);
716 unsigned Steps = 0;
717 unsigned BitWidth = C.getBitWidth();
718
719 while (!WorkStack.empty()) {
720 APInt Val = WorkStack.pop_back_val();
721
722 if (Val == 0 || Val == 1)
723 continue;
724
725 if (Val.isPowerOf2()) {
726 ++Steps;
727 continue;
728 }
729
730 APInt Floor = APInt(BitWidth, 1) << Val.logBase2();
731 APInt Ceil = Val.isNegative() ? APInt(BitWidth, 0)
732 : APInt(BitWidth, 1) << C.ceilLogBase2();
733
734 if ((Val - Floor).ule(Ceil - Val)) {
735 WorkStack.push_back(Floor);
736 WorkStack.push_back(Val - Floor);
737 ++Steps;
738 continue;
739 }
740
741 WorkStack.push_back(Ceil);
742 WorkStack.push_back(Ceil - Val);
743 ++Steps;
744
745 // If we have taken more than 12[1] / 8[2] steps to attempt the
746 // optimization for a native sized value, it is more than likely that this
747 // optimization will make things worse.
748 //
749 // [1] MIPS64 requires 6 instructions at most to materialize any constant,
750 // multiplication requires at least 4 cycles, but another cycle (or two)
751 // to retrieve the result from the HI/LO registers.
752 //
753 // [2] For MIPS32, more than 8 steps is expensive as the constant could be
754 // materialized in 2 instructions, multiplication requires at least 4
755 // cycles, but another cycle (or two) to retrieve the result from the
756 // HI/LO registers.
757
758 if (Steps > 12 && (Subtarget.isABI_N32() || Subtarget.isABI_N64()))
759 return false;
760
761 if (Steps > 8 && Subtarget.isABI_O32())
762 return false;
763 }
764
765 // If the value being multiplied is not supported natively, we have to pay
766 // an additional legalization cost, conservatively assume an increase in the
767 // cost of 3 instructions per step. This values for this heuristic were
768 // determined experimentally.
769 unsigned RegisterSize = DAG.getTargetLoweringInfo()
770 .getRegisterType(*DAG.getContext(), VT)
771 .getSizeInBits();
772 Steps *= (VT.getSizeInBits() != RegisterSize) * 3;
773 if (Steps > 27)
774 return false;
775
776 return true;
777}
778
Petar Jovanoviccd729ea2017-11-15 15:24:04 +0000779static SDValue genConstMult(SDValue X, APInt C, const SDLoc &DL, EVT VT,
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000780 EVT ShiftTy, SelectionDAG &DAG) {
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000781 // Return 0.
782 if (C == 0)
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000783 return DAG.getConstant(0, DL, VT);
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000784
785 // Return x.
786 if (C == 1)
787 return X;
788
789 // If c is power of 2, return (shl x, log2(c)).
Petar Jovanoviccd729ea2017-11-15 15:24:04 +0000790 if (C.isPowerOf2())
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000791 return DAG.getNode(ISD::SHL, DL, VT, X,
Petar Jovanoviccd729ea2017-11-15 15:24:04 +0000792 DAG.getConstant(C.logBase2(), DL, ShiftTy));
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000793
Petar Jovanoviccd729ea2017-11-15 15:24:04 +0000794 unsigned BitWidth = C.getBitWidth();
795 APInt Floor = APInt(BitWidth, 1) << C.logBase2();
796 APInt Ceil = C.isNegative() ? APInt(BitWidth, 0) :
797 APInt(BitWidth, 1) << C.ceilLogBase2();
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000798
799 // If |c - floor_c| <= |c - ceil_c|,
800 // where floor_c = pow(2, floor(log2(c))) and ceil_c = pow(2, ceil(log2(c))),
801 // return (add constMult(x, floor_c), constMult(x, c - floor_c)).
Petar Jovanoviccd729ea2017-11-15 15:24:04 +0000802 if ((C - Floor).ule(Ceil - C)) {
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000803 SDValue Op0 = genConstMult(X, Floor, DL, VT, ShiftTy, DAG);
804 SDValue Op1 = genConstMult(X, C - Floor, DL, VT, ShiftTy, DAG);
805 return DAG.getNode(ISD::ADD, DL, VT, Op0, Op1);
806 }
807
808 // If |c - floor_c| > |c - ceil_c|,
809 // return (sub constMult(x, ceil_c), constMult(x, ceil_c - c)).
810 SDValue Op0 = genConstMult(X, Ceil, DL, VT, ShiftTy, DAG);
811 SDValue Op1 = genConstMult(X, Ceil - C, DL, VT, ShiftTy, DAG);
812 return DAG.getNode(ISD::SUB, DL, VT, Op0, Op1);
813}
814
815static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG,
816 const TargetLowering::DAGCombinerInfo &DCI,
Simon Dardis9ec9f442018-04-13 16:09:07 +0000817 const MipsSETargetLowering *TL,
818 const MipsSubtarget &Subtarget) {
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000819 EVT VT = N->getValueType(0);
820
821 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1)))
Simon Dardis9ec9f442018-04-13 16:09:07 +0000822 if (!VT.isVector() && shouldTransformMulToShiftsAddsSubs(
823 C->getAPIntValue(), VT, DAG, Subtarget))
Petar Jovanoviccd729ea2017-11-15 15:24:04 +0000824 return genConstMult(N->getOperand(0), C->getAPIntValue(), SDLoc(N), VT,
Mehdi Aminieaabc512015-07-09 15:12:23 +0000825 TL->getScalarShiftAmountTy(DAG.getDataLayout(), VT),
826 DAG);
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000827
828 return SDValue(N, 0);
829}
830
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000831static SDValue performDSPShiftCombine(unsigned Opc, SDNode *N, EVT Ty,
832 SelectionDAG &DAG,
Eric Christopher1c29a652014-07-18 22:55:25 +0000833 const MipsSubtarget &Subtarget) {
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000834 // See if this is a vector splat immediate node.
835 APInt SplatValue, SplatUndef;
836 unsigned SplatBitSize;
837 bool HasAnyUndefs;
Sanjay Patel1ed771f2016-09-14 16:37:15 +0000838 unsigned EltSize = Ty.getScalarSizeInBits();
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000839 BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N->getOperand(1));
840
Eric Christopher1c29a652014-07-18 22:55:25 +0000841 if (!Subtarget.hasDSP())
Daniel Sanders6e664bc2013-11-21 11:40:14 +0000842 return SDValue();
843
Akira Hatanaka0d6964c2013-04-22 19:58:23 +0000844 if (!BV ||
Akira Hatanakad8fb0322013-04-22 20:13:37 +0000845 !BV->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
Eric Christopher1c29a652014-07-18 22:55:25 +0000846 EltSize, !Subtarget.isLittle()) ||
Akira Hatanaka0d6964c2013-04-22 19:58:23 +0000847 (SplatBitSize != EltSize) ||
Akira Hatanakae9d0b312013-04-23 18:09:42 +0000848 (SplatValue.getZExtValue() >= EltSize))
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000849 return SDValue();
850
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000851 SDLoc DL(N);
852 return DAG.getNode(Opc, DL, Ty, N->getOperand(0),
853 DAG.getConstant(SplatValue.getZExtValue(), DL, MVT::i32));
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000854}
855
856static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
857 TargetLowering::DAGCombinerInfo &DCI,
Eric Christopher1c29a652014-07-18 22:55:25 +0000858 const MipsSubtarget &Subtarget) {
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000859 EVT Ty = N->getValueType(0);
860
861 if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8))
862 return SDValue();
863
864 return performDSPShiftCombine(MipsISD::SHLL_DSP, N, Ty, DAG, Subtarget);
865}
866
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000867// Fold sign-extensions into MipsISD::VEXTRACT_[SZ]EXT_ELT for MSA and fold
868// constant splats into MipsISD::SHRA_DSP for DSPr2.
869//
870// Performs the following transformations:
871// - Changes MipsISD::VEXTRACT_[SZ]EXT_ELT to sign extension if its
872// sign/zero-extension is completely overwritten by the new one performed by
873// the ISD::SRA and ISD::SHL nodes.
874// - Removes redundant sign extensions performed by an ISD::SRA and ISD::SHL
875// sequence.
876//
877// See performDSPShiftCombine for more information about the transformation
878// used for DSPr2.
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000879static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG,
880 TargetLowering::DAGCombinerInfo &DCI,
Eric Christopher1c29a652014-07-18 22:55:25 +0000881 const MipsSubtarget &Subtarget) {
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000882 EVT Ty = N->getValueType(0);
883
Eric Christopher1c29a652014-07-18 22:55:25 +0000884 if (Subtarget.hasMSA()) {
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000885 SDValue Op0 = N->getOperand(0);
886 SDValue Op1 = N->getOperand(1);
887
888 // (sra (shl (MipsVExtract[SZ]Ext $a, $b, $c), imm:$d), imm:$d)
889 // where $d + sizeof($c) == 32
890 // or $d + sizeof($c) <= 32 and SExt
891 // -> (MipsVExtractSExt $a, $b, $c)
892 if (Op0->getOpcode() == ISD::SHL && Op1 == Op0->getOperand(1)) {
893 SDValue Op0Op0 = Op0->getOperand(0);
894 ConstantSDNode *ShAmount = dyn_cast<ConstantSDNode>(Op1);
895
896 if (!ShAmount)
897 return SDValue();
898
Daniel Sandersf4f1a872013-09-27 09:25:29 +0000899 if (Op0Op0->getOpcode() != MipsISD::VEXTRACT_SEXT_ELT &&
900 Op0Op0->getOpcode() != MipsISD::VEXTRACT_ZEXT_ELT)
901 return SDValue();
902
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000903 EVT ExtendTy = cast<VTSDNode>(Op0Op0->getOperand(2))->getVT();
904 unsigned TotalBits = ShAmount->getZExtValue() + ExtendTy.getSizeInBits();
905
906 if (TotalBits == 32 ||
907 (Op0Op0->getOpcode() == MipsISD::VEXTRACT_SEXT_ELT &&
908 TotalBits <= 32)) {
909 SDValue Ops[] = { Op0Op0->getOperand(0), Op0Op0->getOperand(1),
910 Op0Op0->getOperand(2) };
Chandler Carruth356665a2014-08-01 22:09:43 +0000911 return DAG.getNode(MipsISD::VEXTRACT_SEXT_ELT, SDLoc(Op0Op0),
912 Op0Op0->getVTList(),
913 makeArrayRef(Ops, Op0Op0->getNumOperands()));
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000914 }
915 }
916 }
917
Eric Christopher1c29a652014-07-18 22:55:25 +0000918 if ((Ty != MVT::v2i16) && ((Ty != MVT::v4i8) || !Subtarget.hasDSPR2()))
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000919 return SDValue();
920
921 return performDSPShiftCombine(MipsISD::SHRA_DSP, N, Ty, DAG, Subtarget);
922}
923
924
925static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG,
926 TargetLowering::DAGCombinerInfo &DCI,
Eric Christopher1c29a652014-07-18 22:55:25 +0000927 const MipsSubtarget &Subtarget) {
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000928 EVT Ty = N->getValueType(0);
929
Eric Christopher1c29a652014-07-18 22:55:25 +0000930 if (((Ty != MVT::v2i16) || !Subtarget.hasDSPR2()) && (Ty != MVT::v4i8))
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000931 return SDValue();
932
933 return performDSPShiftCombine(MipsISD::SHRL_DSP, N, Ty, DAG, Subtarget);
934}
935
Akira Hatanaka68741cc2013-04-30 22:37:26 +0000936static bool isLegalDSPCondCode(EVT Ty, ISD::CondCode CC) {
937 bool IsV216 = (Ty == MVT::v2i16);
938
939 switch (CC) {
940 case ISD::SETEQ:
941 case ISD::SETNE: return true;
942 case ISD::SETLT:
943 case ISD::SETLE:
944 case ISD::SETGT:
945 case ISD::SETGE: return IsV216;
946 case ISD::SETULT:
947 case ISD::SETULE:
948 case ISD::SETUGT:
949 case ISD::SETUGE: return !IsV216;
950 default: return false;
951 }
952}
953
954static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG) {
955 EVT Ty = N->getValueType(0);
956
957 if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8))
958 return SDValue();
959
960 if (!isLegalDSPCondCode(Ty, cast<CondCodeSDNode>(N->getOperand(2))->get()))
961 return SDValue();
962
Andrew Trickef9de2a2013-05-25 02:42:55 +0000963 return DAG.getNode(MipsISD::SETCC_DSP, SDLoc(N), Ty, N->getOperand(0),
Akira Hatanaka68741cc2013-04-30 22:37:26 +0000964 N->getOperand(1), N->getOperand(2));
965}
966
967static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) {
968 EVT Ty = N->getValueType(0);
969
Simon Pilgrim386b8dd2018-02-17 21:29:45 +0000970 if (Ty == MVT::v2i16 || Ty == MVT::v4i8) {
Daniel Sanders3ce56622013-09-24 12:18:31 +0000971 SDValue SetCC = N->getOperand(0);
972
973 if (SetCC.getOpcode() != MipsISD::SETCC_DSP)
974 return SDValue();
975
976 return DAG.getNode(MipsISD::SELECT_CC_DSP, SDLoc(N), Ty,
977 SetCC.getOperand(0), SetCC.getOperand(1),
978 N->getOperand(1), N->getOperand(2), SetCC.getOperand(2));
979 }
980
981 return SDValue();
Akira Hatanaka68741cc2013-04-30 22:37:26 +0000982}
983
Daniel Sandersf7456c72013-09-23 13:22:24 +0000984static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG,
Eric Christopher1c29a652014-07-18 22:55:25 +0000985 const MipsSubtarget &Subtarget) {
Daniel Sandersf7456c72013-09-23 13:22:24 +0000986 EVT Ty = N->getValueType(0);
987
Eric Christopher1c29a652014-07-18 22:55:25 +0000988 if (Subtarget.hasMSA() && Ty.is128BitVector() && Ty.isInteger()) {
Daniel Sandersf7456c72013-09-23 13:22:24 +0000989 // Try the following combines:
990 // (xor (or $a, $b), (build_vector allones))
991 // (xor (or $a, $b), (bitcast (build_vector allones)))
992 SDValue Op0 = N->getOperand(0);
993 SDValue Op1 = N->getOperand(1);
994 SDValue NotOp;
Daniel Sandersf7456c72013-09-23 13:22:24 +0000995
996 if (ISD::isBuildVectorAllOnes(Op0.getNode()))
997 NotOp = Op1;
998 else if (ISD::isBuildVectorAllOnes(Op1.getNode()))
999 NotOp = Op0;
Daniel Sandersf7456c72013-09-23 13:22:24 +00001000 else
1001 return SDValue();
1002
1003 if (NotOp->getOpcode() == ISD::OR)
1004 return DAG.getNode(MipsISD::VNOR, SDLoc(N), Ty, NotOp->getOperand(0),
1005 NotOp->getOperand(1));
1006 }
1007
1008 return SDValue();
1009}
1010
Akira Hatanaka9efcd762013-03-30 01:42:24 +00001011SDValue
1012MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
1013 SelectionDAG &DAG = DCI.DAG;
Akira Hatanaka68741cc2013-04-30 22:37:26 +00001014 SDValue Val;
Akira Hatanaka9efcd762013-03-30 01:42:24 +00001015
1016 switch (N->getOpcode()) {
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +00001017 case ISD::AND:
1018 Val = performANDCombine(N, DAG, DCI, Subtarget);
1019 break;
Daniel Sanders53fe6c42013-10-30 13:51:01 +00001020 case ISD::OR:
1021 Val = performORCombine(N, DAG, DCI, Subtarget);
1022 break;
Akira Hatanaka5832fc62013-06-26 18:48:17 +00001023 case ISD::MUL:
Simon Dardis9ec9f442018-04-13 16:09:07 +00001024 return performMULCombine(N, DAG, DCI, this, Subtarget);
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +00001025 case ISD::SHL:
Petar Jovanovicb71386a2017-03-15 13:10:08 +00001026 Val = performSHLCombine(N, DAG, DCI, Subtarget);
1027 break;
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +00001028 case ISD::SRA:
1029 return performSRACombine(N, DAG, DCI, Subtarget);
1030 case ISD::SRL:
1031 return performSRLCombine(N, DAG, DCI, Subtarget);
Akira Hatanaka68741cc2013-04-30 22:37:26 +00001032 case ISD::VSELECT:
1033 return performVSELECTCombine(N, DAG);
Daniel Sandersf7456c72013-09-23 13:22:24 +00001034 case ISD::XOR:
1035 Val = performXORCombine(N, DAG, Subtarget);
1036 break;
1037 case ISD::SETCC:
Akira Hatanaka68741cc2013-04-30 22:37:26 +00001038 Val = performSETCCCombine(N, DAG);
1039 break;
Akira Hatanaka9efcd762013-03-30 01:42:24 +00001040 }
Akira Hatanaka68741cc2013-04-30 22:37:26 +00001041
Daniel Sanders62aeab82013-10-30 13:31:27 +00001042 if (Val.getNode()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001043 LLVM_DEBUG(dbgs() << "\nMipsSE DAG Combine:\n";
1044 N->printrWithDepth(dbgs(), &DAG); dbgs() << "\n=> \n";
1045 Val.getNode()->printrWithDepth(dbgs(), &DAG); dbgs() << "\n");
Akira Hatanaka68741cc2013-04-30 22:37:26 +00001046 return Val;
Daniel Sanders62aeab82013-10-30 13:31:27 +00001047 }
Akira Hatanaka68741cc2013-04-30 22:37:26 +00001048
1049 return MipsTargetLowering::PerformDAGCombine(N, DCI);
Akira Hatanaka9efcd762013-03-30 01:42:24 +00001050}
1051
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001052MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00001053MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001054 MachineBasicBlock *BB) const {
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00001055 switch (MI.getOpcode()) {
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001056 default:
1057 return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB);
1058 case Mips::BPOSGE32_PSEUDO:
1059 return emitBPOSGE32(MI, BB);
Daniel Sandersce09d072013-08-28 12:14:50 +00001060 case Mips::SNZ_B_PSEUDO:
1061 return emitMSACBranchPseudo(MI, BB, Mips::BNZ_B);
1062 case Mips::SNZ_H_PSEUDO:
1063 return emitMSACBranchPseudo(MI, BB, Mips::BNZ_H);
1064 case Mips::SNZ_W_PSEUDO:
1065 return emitMSACBranchPseudo(MI, BB, Mips::BNZ_W);
1066 case Mips::SNZ_D_PSEUDO:
1067 return emitMSACBranchPseudo(MI, BB, Mips::BNZ_D);
1068 case Mips::SNZ_V_PSEUDO:
1069 return emitMSACBranchPseudo(MI, BB, Mips::BNZ_V);
1070 case Mips::SZ_B_PSEUDO:
1071 return emitMSACBranchPseudo(MI, BB, Mips::BZ_B);
1072 case Mips::SZ_H_PSEUDO:
1073 return emitMSACBranchPseudo(MI, BB, Mips::BZ_H);
1074 case Mips::SZ_W_PSEUDO:
1075 return emitMSACBranchPseudo(MI, BB, Mips::BZ_W);
1076 case Mips::SZ_D_PSEUDO:
1077 return emitMSACBranchPseudo(MI, BB, Mips::BZ_D);
1078 case Mips::SZ_V_PSEUDO:
1079 return emitMSACBranchPseudo(MI, BB, Mips::BZ_V);
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00001080 case Mips::COPY_FW_PSEUDO:
1081 return emitCOPY_FW(MI, BB);
1082 case Mips::COPY_FD_PSEUDO:
1083 return emitCOPY_FD(MI, BB);
Daniel Sandersa5150702013-09-27 12:31:32 +00001084 case Mips::INSERT_FW_PSEUDO:
1085 return emitINSERT_FW(MI, BB);
1086 case Mips::INSERT_FD_PSEUDO:
1087 return emitINSERT_FD(MI, BB);
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001088 case Mips::INSERT_B_VIDX_PSEUDO:
Daniel Sanderseda60d22015-05-05 10:32:24 +00001089 case Mips::INSERT_B_VIDX64_PSEUDO:
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001090 return emitINSERT_DF_VIDX(MI, BB, 1, false);
1091 case Mips::INSERT_H_VIDX_PSEUDO:
Daniel Sanderseda60d22015-05-05 10:32:24 +00001092 case Mips::INSERT_H_VIDX64_PSEUDO:
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001093 return emitINSERT_DF_VIDX(MI, BB, 2, false);
1094 case Mips::INSERT_W_VIDX_PSEUDO:
Daniel Sanderseda60d22015-05-05 10:32:24 +00001095 case Mips::INSERT_W_VIDX64_PSEUDO:
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001096 return emitINSERT_DF_VIDX(MI, BB, 4, false);
1097 case Mips::INSERT_D_VIDX_PSEUDO:
Daniel Sanderseda60d22015-05-05 10:32:24 +00001098 case Mips::INSERT_D_VIDX64_PSEUDO:
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001099 return emitINSERT_DF_VIDX(MI, BB, 8, false);
1100 case Mips::INSERT_FW_VIDX_PSEUDO:
Daniel Sanderseda60d22015-05-05 10:32:24 +00001101 case Mips::INSERT_FW_VIDX64_PSEUDO:
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001102 return emitINSERT_DF_VIDX(MI, BB, 4, true);
1103 case Mips::INSERT_FD_VIDX_PSEUDO:
Daniel Sanderseda60d22015-05-05 10:32:24 +00001104 case Mips::INSERT_FD_VIDX64_PSEUDO:
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001105 return emitINSERT_DF_VIDX(MI, BB, 8, true);
Daniel Sanders1dfddc72013-10-15 13:14:41 +00001106 case Mips::FILL_FW_PSEUDO:
1107 return emitFILL_FW(MI, BB);
1108 case Mips::FILL_FD_PSEUDO:
1109 return emitFILL_FD(MI, BB);
Daniel Sandersa9521602013-10-23 10:36:52 +00001110 case Mips::FEXP2_W_1_PSEUDO:
1111 return emitFEXP2_W_1(MI, BB);
1112 case Mips::FEXP2_D_1_PSEUDO:
1113 return emitFEXP2_D_1(MI, BB);
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00001114 case Mips::ST_F16:
1115 return emitST_F16_PSEUDO(MI, BB);
1116 case Mips::LD_F16:
1117 return emitLD_F16_PSEUDO(MI, BB);
1118 case Mips::MSA_FP_EXTEND_W_PSEUDO:
1119 return emitFPEXTEND_PSEUDO(MI, BB, false);
1120 case Mips::MSA_FP_ROUND_W_PSEUDO:
1121 return emitFPROUND_PSEUDO(MI, BB, false);
1122 case Mips::MSA_FP_EXTEND_D_PSEUDO:
1123 return emitFPEXTEND_PSEUDO(MI, BB, true);
1124 case Mips::MSA_FP_ROUND_D_PSEUDO:
1125 return emitFPROUND_PSEUDO(MI, BB, true);
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001126 }
1127}
1128
Daniel Sanders23e98772014-11-02 16:09:29 +00001129bool MipsSETargetLowering::isEligibleForTailCallOptimization(
1130 const CCState &CCInfo, unsigned NextStackOffset,
1131 const MipsFunctionInfo &FI) const {
Simon Dardis57f4ae42016-08-04 09:17:07 +00001132 if (!UseMipsTailCalls)
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001133 return false;
1134
Vasileios Kalintiris43dff0c2015-10-26 12:38:43 +00001135 // Exception has to be cleared with eret.
1136 if (FI.isISR())
1137 return false;
1138
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001139 // Return false if either the callee or caller has a byval argument.
Daniel Sanders23e98772014-11-02 16:09:29 +00001140 if (CCInfo.getInRegsParamsCount() > 0 || FI.hasByvalArg())
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001141 return false;
1142
1143 // Return true if the callee's argument area is no larger than the
1144 // caller's.
1145 return NextStackOffset <= FI.getIncomingArgSize();
1146}
1147
1148void MipsSETargetLowering::
1149getOpndList(SmallVectorImpl<SDValue> &Ops,
Eugene Zelenko79220eae2017-08-03 22:12:30 +00001150 std::deque<std::pair<unsigned, SDValue>> &RegsToPass,
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001151 bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
Sasa Stankovic7072a792014-10-01 08:22:21 +00001152 bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee,
1153 SDValue Chain) const {
Akira Hatanaka168d4e52013-11-27 23:38:42 +00001154 Ops.push_back(Callee);
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001155 MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal,
Sasa Stankovic7072a792014-10-01 08:22:21 +00001156 InternalLinkage, IsCallReloc, CLI, Callee,
1157 Chain);
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001158}
1159
Akira Hatanaka63791212013-09-07 00:52:30 +00001160SDValue MipsSETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const {
1161 LoadSDNode &Nd = *cast<LoadSDNode>(Op);
1162
1163 if (Nd.getMemoryVT() != MVT::f64 || !NoDPLoadStore)
1164 return MipsTargetLowering::lowerLOAD(Op, DAG);
1165
1166 // Replace a double precision load with two i32 loads and a buildpair64.
1167 SDLoc DL(Op);
1168 SDValue Ptr = Nd.getBasePtr(), Chain = Nd.getChain();
1169 EVT PtrVT = Ptr.getValueType();
1170
1171 // i32 load from lower address.
Justin Lebar9c375812016-07-15 18:27:10 +00001172 SDValue Lo = DAG.getLoad(MVT::i32, DL, Chain, Ptr, MachinePointerInfo(),
1173 Nd.getAlignment(), Nd.getMemOperand()->getFlags());
Akira Hatanaka63791212013-09-07 00:52:30 +00001174
1175 // i32 load from higher address.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001176 Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, DL, PtrVT));
Justin Lebar9c375812016-07-15 18:27:10 +00001177 SDValue Hi = DAG.getLoad(
1178 MVT::i32, DL, Lo.getValue(1), Ptr, MachinePointerInfo(),
1179 std::min(Nd.getAlignment(), 4U), Nd.getMemOperand()->getFlags());
Akira Hatanaka63791212013-09-07 00:52:30 +00001180
Eric Christopher1c29a652014-07-18 22:55:25 +00001181 if (!Subtarget.isLittle())
Akira Hatanaka63791212013-09-07 00:52:30 +00001182 std::swap(Lo, Hi);
1183
1184 SDValue BP = DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, Lo, Hi);
1185 SDValue Ops[2] = {BP, Hi.getValue(1)};
Craig Topper64941d92014-04-27 19:20:57 +00001186 return DAG.getMergeValues(Ops, DL);
Akira Hatanaka63791212013-09-07 00:52:30 +00001187}
1188
1189SDValue MipsSETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
1190 StoreSDNode &Nd = *cast<StoreSDNode>(Op);
1191
1192 if (Nd.getMemoryVT() != MVT::f64 || !NoDPLoadStore)
1193 return MipsTargetLowering::lowerSTORE(Op, DAG);
1194
1195 // Replace a double precision store with two extractelement64s and i32 stores.
1196 SDLoc DL(Op);
1197 SDValue Val = Nd.getValue(), Ptr = Nd.getBasePtr(), Chain = Nd.getChain();
1198 EVT PtrVT = Ptr.getValueType();
1199 SDValue Lo = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001200 Val, DAG.getConstant(0, DL, MVT::i32));
Akira Hatanaka63791212013-09-07 00:52:30 +00001201 SDValue Hi = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001202 Val, DAG.getConstant(1, DL, MVT::i32));
Akira Hatanaka63791212013-09-07 00:52:30 +00001203
Eric Christopher1c29a652014-07-18 22:55:25 +00001204 if (!Subtarget.isLittle())
Akira Hatanaka63791212013-09-07 00:52:30 +00001205 std::swap(Lo, Hi);
1206
1207 // i32 store to lower address.
Justin Lebar9c375812016-07-15 18:27:10 +00001208 Chain =
1209 DAG.getStore(Chain, DL, Lo, Ptr, MachinePointerInfo(), Nd.getAlignment(),
1210 Nd.getMemOperand()->getFlags(), Nd.getAAInfo());
Akira Hatanaka63791212013-09-07 00:52:30 +00001211
1212 // i32 store to higher address.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001213 Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, DL, PtrVT));
Akira Hatanaka63791212013-09-07 00:52:30 +00001214 return DAG.getStore(Chain, DL, Hi, Ptr, MachinePointerInfo(),
Justin Lebar9c375812016-07-15 18:27:10 +00001215 std::min(Nd.getAlignment(), 4U),
1216 Nd.getMemOperand()->getFlags(), Nd.getAAInfo());
Akira Hatanaka63791212013-09-07 00:52:30 +00001217}
1218
Akira Hatanakabe8612f2013-03-30 01:36:35 +00001219SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc,
1220 bool HasLo, bool HasHi,
1221 SelectionDAG &DAG) const {
Daniel Sanders308181e2014-06-12 10:44:10 +00001222 // MIPS32r6/MIPS64r6 removed accumulator based multiplies.
Eric Christopher1c29a652014-07-18 22:55:25 +00001223 assert(!Subtarget.hasMips32r6());
Daniel Sanders308181e2014-06-12 10:44:10 +00001224
Akira Hatanakabe8612f2013-03-30 01:36:35 +00001225 EVT Ty = Op.getOperand(0).getValueType();
Andrew Trickef9de2a2013-05-25 02:42:55 +00001226 SDLoc DL(Op);
Akira Hatanakabe8612f2013-03-30 01:36:35 +00001227 SDValue Mult = DAG.getNode(NewOpc, DL, MVT::Untyped,
1228 Op.getOperand(0), Op.getOperand(1));
1229 SDValue Lo, Hi;
1230
1231 if (HasLo)
Akira Hatanakad98c99f2013-10-15 01:12:50 +00001232 Lo = DAG.getNode(MipsISD::MFLO, DL, Ty, Mult);
Akira Hatanakabe8612f2013-03-30 01:36:35 +00001233 if (HasHi)
Akira Hatanakad98c99f2013-10-15 01:12:50 +00001234 Hi = DAG.getNode(MipsISD::MFHI, DL, Ty, Mult);
Akira Hatanakabe8612f2013-03-30 01:36:35 +00001235
1236 if (!HasLo || !HasHi)
1237 return HasLo ? Lo : Hi;
1238
1239 SDValue Vals[] = { Lo, Hi };
Craig Topper64941d92014-04-27 19:20:57 +00001240 return DAG.getMergeValues(Vals, DL);
Akira Hatanakabe8612f2013-03-30 01:36:35 +00001241}
1242
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001243static SDValue initAccumulator(SDValue In, const SDLoc &DL, SelectionDAG &DAG) {
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001244 SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001245 DAG.getConstant(0, DL, MVT::i32));
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001246 SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001247 DAG.getConstant(1, DL, MVT::i32));
Akira Hatanakad98c99f2013-10-15 01:12:50 +00001248 return DAG.getNode(MipsISD::MTLOHI, DL, MVT::Untyped, InLo, InHi);
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001249}
1250
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001251static SDValue extractLOHI(SDValue Op, const SDLoc &DL, SelectionDAG &DAG) {
Akira Hatanakad98c99f2013-10-15 01:12:50 +00001252 SDValue Lo = DAG.getNode(MipsISD::MFLO, DL, MVT::i32, Op);
1253 SDValue Hi = DAG.getNode(MipsISD::MFHI, DL, MVT::i32, Op);
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001254 return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi);
1255}
1256
1257// This function expands mips intrinsic nodes which have 64-bit input operands
1258// or output values.
1259//
1260// out64 = intrinsic-node in64
1261// =>
1262// lo = copy (extract-element (in64, 0))
1263// hi = copy (extract-element (in64, 1))
1264// mips-specific-node
1265// v0 = copy lo
1266// v1 = copy hi
1267// out64 = merge-values (v0, v1)
1268//
1269static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001270 SDLoc DL(Op);
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001271 bool HasChainIn = Op->getOperand(0).getValueType() == MVT::Other;
1272 SmallVector<SDValue, 3> Ops;
1273 unsigned OpNo = 0;
1274
1275 // See if Op has a chain input.
1276 if (HasChainIn)
1277 Ops.push_back(Op->getOperand(OpNo++));
1278
1279 // The next operand is the intrinsic opcode.
1280 assert(Op->getOperand(OpNo).getOpcode() == ISD::TargetConstant);
1281
1282 // See if the next operand has type i64.
1283 SDValue Opnd = Op->getOperand(++OpNo), In64;
1284
1285 if (Opnd.getValueType() == MVT::i64)
1286 In64 = initAccumulator(Opnd, DL, DAG);
1287 else
1288 Ops.push_back(Opnd);
1289
1290 // Push the remaining operands.
1291 for (++OpNo ; OpNo < Op->getNumOperands(); ++OpNo)
1292 Ops.push_back(Op->getOperand(OpNo));
1293
1294 // Add In64 to the end of the list.
1295 if (In64.getNode())
1296 Ops.push_back(In64);
1297
1298 // Scan output.
1299 SmallVector<EVT, 2> ResTys;
1300
1301 for (SDNode::value_iterator I = Op->value_begin(), E = Op->value_end();
1302 I != E; ++I)
1303 ResTys.push_back((*I == MVT::i64) ? MVT::Untyped : *I);
1304
1305 // Create node.
Craig Topper48d114b2014-04-26 18:35:24 +00001306 SDValue Val = DAG.getNode(Opc, DL, ResTys, Ops);
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001307 SDValue Out = (ResTys[0] == MVT::Untyped) ? extractLOHI(Val, DL, DAG) : Val;
1308
1309 if (!HasChainIn)
1310 return Out;
1311
1312 assert(Val->getValueType(1) == MVT::Other);
1313 SDValue Vals[] = { Out, SDValue(Val.getNode(), 1) };
Craig Topper64941d92014-04-27 19:20:57 +00001314 return DAG.getMergeValues(Vals, DL);
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001315}
1316
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +00001317// Lower an MSA copy intrinsic into the specified SelectionDAG node
1318static SDValue lowerMSACopyIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
1319 SDLoc DL(Op);
1320 SDValue Vec = Op->getOperand(1);
1321 SDValue Idx = Op->getOperand(2);
1322 EVT ResTy = Op->getValueType(0);
1323 EVT EltTy = Vec->getValueType(0).getVectorElementType();
1324
1325 SDValue Result = DAG.getNode(Opc, DL, ResTy, Vec, Idx,
1326 DAG.getValueType(EltTy));
1327
1328 return Result;
1329}
1330
Daniel Sanders50b80412013-11-15 12:56:49 +00001331static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) {
1332 EVT ResVecTy = Op->getValueType(0);
1333 EVT ViaVecTy = ResVecTy;
Stefan Maksimovicb794c0a2017-06-23 09:09:31 +00001334 bool BigEndian = !DAG.getSubtarget().getTargetTriple().isLittleEndian();
Daniel Sanders50b80412013-11-15 12:56:49 +00001335 SDLoc DL(Op);
Daniel Sanders86d0c8d2013-09-23 14:29:55 +00001336
Daniel Sanders50b80412013-11-15 12:56:49 +00001337 // When ResVecTy == MVT::v2i64, LaneA is the upper 32 bits of the lane and
1338 // LaneB is the lower 32-bits. Otherwise LaneA and LaneB are alternating
1339 // lanes.
Stefan Maksimovicb794c0a2017-06-23 09:09:31 +00001340 SDValue LaneA = Op->getOperand(OpNr);
1341 SDValue LaneB;
Daniel Sanders50b80412013-11-15 12:56:49 +00001342
1343 if (ResVecTy == MVT::v2i64) {
Stefan Maksimovicc7113cc2018-05-08 15:12:29 +00001344 // In case of the index being passed as an immediate value, set the upper
1345 // lane to 0 so that the splati.d instruction can be matched.
1346 if (isa<ConstantSDNode>(LaneA))
1347 LaneB = DAG.getConstant(0, DL, MVT::i32);
1348 // Having the index passed in a register, set the upper lane to the same
1349 // value as the lower - this results in the BUILD_VECTOR node not being
1350 // expanded through stack. This way we are able to pattern match the set of
1351 // nodes created here to splat.d.
1352 else
1353 LaneB = LaneA;
Daniel Sandersf49dd822013-09-24 13:33:07 +00001354 ViaVecTy = MVT::v4i32;
Stefan Maksimovicb794c0a2017-06-23 09:09:31 +00001355 if(BigEndian)
1356 std::swap(LaneA, LaneB);
Daniel Sanders50b80412013-11-15 12:56:49 +00001357 } else
Stefan Maksimovicb794c0a2017-06-23 09:09:31 +00001358 LaneB = LaneA;
Daniel Sanders86d0c8d2013-09-23 14:29:55 +00001359
Daniel Sanders50b80412013-11-15 12:56:49 +00001360 SDValue Ops[16] = { LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB,
1361 LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB };
Daniel Sandersf49dd822013-09-24 13:33:07 +00001362
Ahmed Bougacha128f8732016-04-26 21:15:30 +00001363 SDValue Result = DAG.getBuildVector(
1364 ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements()));
Daniel Sanders50b80412013-11-15 12:56:49 +00001365
Stefan Maksimovicb794c0a2017-06-23 09:09:31 +00001366 if (ViaVecTy != ResVecTy) {
1367 SDValue One = DAG.getConstant(1, DL, ViaVecTy);
1368 Result = DAG.getNode(ISD::BITCAST, DL, ResVecTy,
1369 DAG.getNode(ISD::AND, DL, ViaVecTy, Result, One));
1370 }
Daniel Sandersf49dd822013-09-24 13:33:07 +00001371
1372 return Result;
1373}
1374
Simon Dardis548a53f2017-01-10 16:40:57 +00001375static SDValue lowerMSASplatImm(SDValue Op, unsigned ImmOp, SelectionDAG &DAG,
1376 bool IsSigned = false) {
1377 return DAG.getConstant(
1378 APInt(Op->getValueType(0).getScalarType().getSizeInBits(),
1379 Op->getConstantOperandVal(ImmOp), IsSigned),
1380 SDLoc(Op), Op->getValueType(0));
Daniel Sanders50b80412013-11-15 12:56:49 +00001381}
1382
1383static SDValue getBuildVectorSplat(EVT VecTy, SDValue SplatValue,
1384 bool BigEndian, SelectionDAG &DAG) {
1385 EVT ViaVecTy = VecTy;
1386 SDValue SplatValueA = SplatValue;
1387 SDValue SplatValueB = SplatValue;
1388 SDLoc DL(SplatValue);
1389
1390 if (VecTy == MVT::v2i64) {
1391 // v2i64 BUILD_VECTOR must be performed via v4i32 so split into i32's.
1392 ViaVecTy = MVT::v4i32;
1393
1394 SplatValueA = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValue);
1395 SplatValueB = DAG.getNode(ISD::SRL, DL, MVT::i64, SplatValue,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001396 DAG.getConstant(32, DL, MVT::i32));
Daniel Sanders50b80412013-11-15 12:56:49 +00001397 SplatValueB = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValueB);
1398 }
1399
1400 // We currently hold the parts in little endian order. Swap them if
1401 // necessary.
1402 if (BigEndian)
1403 std::swap(SplatValueA, SplatValueB);
1404
1405 SDValue Ops[16] = { SplatValueA, SplatValueB, SplatValueA, SplatValueB,
1406 SplatValueA, SplatValueB, SplatValueA, SplatValueB,
1407 SplatValueA, SplatValueB, SplatValueA, SplatValueB,
1408 SplatValueA, SplatValueB, SplatValueA, SplatValueB };
1409
Ahmed Bougacha128f8732016-04-26 21:15:30 +00001410 SDValue Result = DAG.getBuildVector(
1411 ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements()));
Daniel Sanders50b80412013-11-15 12:56:49 +00001412
1413 if (VecTy != ViaVecTy)
1414 Result = DAG.getNode(ISD::BITCAST, DL, VecTy, Result);
1415
1416 return Result;
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001417}
1418
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001419static SDValue lowerMSABinaryBitImmIntr(SDValue Op, SelectionDAG &DAG,
1420 unsigned Opc, SDValue Imm,
1421 bool BigEndian) {
1422 EVT VecTy = Op->getValueType(0);
1423 SDValue Exp2Imm;
1424 SDLoc DL(Op);
1425
Daniel Sanders50b80412013-11-15 12:56:49 +00001426 // The DAG Combiner can't constant fold bitcasted vectors yet so we must do it
1427 // here for now.
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001428 if (VecTy == MVT::v2i64) {
1429 if (ConstantSDNode *CImm = dyn_cast<ConstantSDNode>(Imm)) {
1430 APInt BitImm = APInt(64, 1) << CImm->getAPIntValue();
1431
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001432 SDValue BitImmHiOp = DAG.getConstant(BitImm.lshr(32).trunc(32), DL,
1433 MVT::i32);
1434 SDValue BitImmLoOp = DAG.getConstant(BitImm.trunc(32), DL, MVT::i32);
Daniel Sanders50b80412013-11-15 12:56:49 +00001435
1436 if (BigEndian)
1437 std::swap(BitImmLoOp, BitImmHiOp);
1438
Ahmed Bougacha128f8732016-04-26 21:15:30 +00001439 Exp2Imm = DAG.getNode(
1440 ISD::BITCAST, DL, MVT::v2i64,
1441 DAG.getBuildVector(MVT::v4i32, DL,
1442 {BitImmLoOp, BitImmHiOp, BitImmLoOp, BitImmHiOp}));
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001443 }
1444 }
1445
Craig Topper062a2ba2014-04-25 05:30:21 +00001446 if (!Exp2Imm.getNode()) {
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001447 // We couldnt constant fold, do a vector shift instead
Daniel Sanders50b80412013-11-15 12:56:49 +00001448
1449 // Extend i32 to i64 if necessary. Sign or zero extend doesn't matter since
1450 // only values 0-63 are valid.
1451 if (VecTy == MVT::v2i64)
1452 Imm = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Imm);
1453
1454 Exp2Imm = getBuildVectorSplat(VecTy, Imm, BigEndian, DAG);
1455
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001456 Exp2Imm = DAG.getNode(ISD::SHL, DL, VecTy, DAG.getConstant(1, DL, VecTy),
1457 Exp2Imm);
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001458 }
1459
1460 return DAG.getNode(Opc, DL, VecTy, Op->getOperand(1), Exp2Imm);
1461}
1462
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00001463static SDValue truncateVecElts(SDValue Op, SelectionDAG &DAG) {
1464 SDLoc DL(Op);
1465 EVT ResTy = Op->getValueType(0);
1466 SDValue Vec = Op->getOperand(2);
1467 bool BigEndian = !DAG.getSubtarget().getTargetTriple().isLittleEndian();
1468 MVT ResEltTy = ResTy == MVT::v2i64 ? MVT::i64 : MVT::i32;
1469 SDValue ConstValue = DAG.getConstant(Vec.getScalarValueSizeInBits() - 1,
1470 DL, ResEltTy);
1471 SDValue SplatVec = getBuildVectorSplat(ResTy, ConstValue, BigEndian, DAG);
1472
1473 return DAG.getNode(ISD::AND, DL, ResTy, Vec, SplatVec);
1474}
1475
Daniel Sanders3f6eb542013-11-12 10:45:18 +00001476static SDValue lowerMSABitClear(SDValue Op, SelectionDAG &DAG) {
1477 EVT ResTy = Op->getValueType(0);
Daniel Sanders3f6eb542013-11-12 10:45:18 +00001478 SDLoc DL(Op);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001479 SDValue One = DAG.getConstant(1, DL, ResTy);
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00001480 SDValue Bit = DAG.getNode(ISD::SHL, DL, ResTy, One, truncateVecElts(Op, DAG));
Daniel Sanders3f6eb542013-11-12 10:45:18 +00001481
Daniel Sanders71ce0ca2013-11-15 16:02:04 +00001482 return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1),
1483 DAG.getNOT(DL, Bit, ResTy));
Daniel Sanders3f6eb542013-11-12 10:45:18 +00001484}
1485
1486static SDValue lowerMSABitClearImm(SDValue Op, SelectionDAG &DAG) {
1487 SDLoc DL(Op);
1488 EVT ResTy = Op->getValueType(0);
Sanjay Patel1ed771f2016-09-14 16:37:15 +00001489 APInt BitImm = APInt(ResTy.getScalarSizeInBits(), 1)
Daniel Sanders50b80412013-11-15 12:56:49 +00001490 << cast<ConstantSDNode>(Op->getOperand(2))->getAPIntValue();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001491 SDValue BitMask = DAG.getConstant(~BitImm, DL, ResTy);
Daniel Sanders3f6eb542013-11-12 10:45:18 +00001492
1493 return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1), BitMask);
1494}
1495
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001496SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
1497 SelectionDAG &DAG) const {
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001498 SDLoc DL(Op);
Simon Dardis548a53f2017-01-10 16:40:57 +00001499 unsigned Intrinsic = cast<ConstantSDNode>(Op->getOperand(0))->getZExtValue();
1500 switch (Intrinsic) {
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001501 default:
1502 return SDValue();
1503 case Intrinsic::mips_shilo:
1504 return lowerDSPIntr(Op, DAG, MipsISD::SHILO);
1505 case Intrinsic::mips_dpau_h_qbl:
1506 return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBL);
1507 case Intrinsic::mips_dpau_h_qbr:
1508 return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBR);
1509 case Intrinsic::mips_dpsu_h_qbl:
1510 return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBL);
1511 case Intrinsic::mips_dpsu_h_qbr:
1512 return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBR);
1513 case Intrinsic::mips_dpa_w_ph:
1514 return lowerDSPIntr(Op, DAG, MipsISD::DPA_W_PH);
1515 case Intrinsic::mips_dps_w_ph:
1516 return lowerDSPIntr(Op, DAG, MipsISD::DPS_W_PH);
1517 case Intrinsic::mips_dpax_w_ph:
1518 return lowerDSPIntr(Op, DAG, MipsISD::DPAX_W_PH);
1519 case Intrinsic::mips_dpsx_w_ph:
1520 return lowerDSPIntr(Op, DAG, MipsISD::DPSX_W_PH);
1521 case Intrinsic::mips_mulsa_w_ph:
1522 return lowerDSPIntr(Op, DAG, MipsISD::MULSA_W_PH);
1523 case Intrinsic::mips_mult:
1524 return lowerDSPIntr(Op, DAG, MipsISD::Mult);
1525 case Intrinsic::mips_multu:
1526 return lowerDSPIntr(Op, DAG, MipsISD::Multu);
1527 case Intrinsic::mips_madd:
1528 return lowerDSPIntr(Op, DAG, MipsISD::MAdd);
1529 case Intrinsic::mips_maddu:
1530 return lowerDSPIntr(Op, DAG, MipsISD::MAddu);
1531 case Intrinsic::mips_msub:
1532 return lowerDSPIntr(Op, DAG, MipsISD::MSub);
1533 case Intrinsic::mips_msubu:
1534 return lowerDSPIntr(Op, DAG, MipsISD::MSubu);
Daniel Sandersfa5ab1c2013-09-11 10:28:16 +00001535 case Intrinsic::mips_addv_b:
1536 case Intrinsic::mips_addv_h:
1537 case Intrinsic::mips_addv_w:
1538 case Intrinsic::mips_addv_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001539 return DAG.getNode(ISD::ADD, DL, Op->getValueType(0), Op->getOperand(1),
1540 Op->getOperand(2));
Daniel Sanders86d0c8d2013-09-23 14:29:55 +00001541 case Intrinsic::mips_addvi_b:
1542 case Intrinsic::mips_addvi_h:
1543 case Intrinsic::mips_addvi_w:
1544 case Intrinsic::mips_addvi_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001545 return DAG.getNode(ISD::ADD, DL, Op->getValueType(0), Op->getOperand(1),
1546 lowerMSASplatImm(Op, 2, DAG));
Daniel Sanders8ca81e42013-09-23 12:57:42 +00001547 case Intrinsic::mips_and_v:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001548 return DAG.getNode(ISD::AND, DL, Op->getValueType(0), Op->getOperand(1),
1549 Op->getOperand(2));
Daniel Sandersbfc39ce2013-09-24 12:32:47 +00001550 case Intrinsic::mips_andi_b:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001551 return DAG.getNode(ISD::AND, DL, Op->getValueType(0), Op->getOperand(1),
1552 lowerMSASplatImm(Op, 2, DAG));
Daniel Sanders3f6eb542013-11-12 10:45:18 +00001553 case Intrinsic::mips_bclr_b:
1554 case Intrinsic::mips_bclr_h:
1555 case Intrinsic::mips_bclr_w:
1556 case Intrinsic::mips_bclr_d:
1557 return lowerMSABitClear(Op, DAG);
1558 case Intrinsic::mips_bclri_b:
1559 case Intrinsic::mips_bclri_h:
1560 case Intrinsic::mips_bclri_w:
1561 case Intrinsic::mips_bclri_d:
1562 return lowerMSABitClearImm(Op, DAG);
Daniel Sandersd74b1302013-10-30 14:45:14 +00001563 case Intrinsic::mips_binsli_b:
1564 case Intrinsic::mips_binsli_h:
1565 case Intrinsic::mips_binsli_w:
1566 case Intrinsic::mips_binsli_d: {
Daniel Sandersdf2215452014-03-12 11:54:00 +00001567 // binsli_x(IfClear, IfSet, nbits) -> (vselect LBitsMask, IfSet, IfClear)
Daniel Sandersd74b1302013-10-30 14:45:14 +00001568 EVT VecTy = Op->getValueType(0);
1569 EVT EltTy = VecTy.getVectorElementType();
Simon Dardis548a53f2017-01-10 16:40:57 +00001570 if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits())
1571 report_fatal_error("Immediate out of range");
Daniel Sandersd74b1302013-10-30 14:45:14 +00001572 APInt Mask = APInt::getHighBitsSet(EltTy.getSizeInBits(),
Petar Jovanovicbc54eb82017-04-07 13:31:36 +00001573 Op->getConstantOperandVal(3) + 1);
Daniel Sandersd74b1302013-10-30 14:45:14 +00001574 return DAG.getNode(ISD::VSELECT, DL, VecTy,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001575 DAG.getConstant(Mask, DL, VecTy, true),
1576 Op->getOperand(2), Op->getOperand(1));
Daniel Sandersd74b1302013-10-30 14:45:14 +00001577 }
1578 case Intrinsic::mips_binsri_b:
1579 case Intrinsic::mips_binsri_h:
1580 case Intrinsic::mips_binsri_w:
1581 case Intrinsic::mips_binsri_d: {
Daniel Sandersdf2215452014-03-12 11:54:00 +00001582 // binsri_x(IfClear, IfSet, nbits) -> (vselect RBitsMask, IfSet, IfClear)
Daniel Sandersd74b1302013-10-30 14:45:14 +00001583 EVT VecTy = Op->getValueType(0);
1584 EVT EltTy = VecTy.getVectorElementType();
Simon Dardis548a53f2017-01-10 16:40:57 +00001585 if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits())
1586 report_fatal_error("Immediate out of range");
Daniel Sandersd74b1302013-10-30 14:45:14 +00001587 APInt Mask = APInt::getLowBitsSet(EltTy.getSizeInBits(),
Petar Jovanovicbc54eb82017-04-07 13:31:36 +00001588 Op->getConstantOperandVal(3) + 1);
Daniel Sandersd74b1302013-10-30 14:45:14 +00001589 return DAG.getNode(ISD::VSELECT, DL, VecTy,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001590 DAG.getConstant(Mask, DL, VecTy, true),
1591 Op->getOperand(2), Op->getOperand(1));
Daniel Sandersd74b1302013-10-30 14:45:14 +00001592 }
Daniel Sandersab94b532013-10-30 15:20:38 +00001593 case Intrinsic::mips_bmnz_v:
1594 return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), Op->getOperand(3),
1595 Op->getOperand(2), Op->getOperand(1));
1596 case Intrinsic::mips_bmnzi_b:
1597 return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0),
1598 lowerMSASplatImm(Op, 3, DAG), Op->getOperand(2),
1599 Op->getOperand(1));
1600 case Intrinsic::mips_bmz_v:
1601 return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), Op->getOperand(3),
1602 Op->getOperand(1), Op->getOperand(2));
1603 case Intrinsic::mips_bmzi_b:
1604 return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0),
1605 lowerMSASplatImm(Op, 3, DAG), Op->getOperand(1),
1606 Op->getOperand(2));
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001607 case Intrinsic::mips_bneg_b:
1608 case Intrinsic::mips_bneg_h:
1609 case Intrinsic::mips_bneg_w:
1610 case Intrinsic::mips_bneg_d: {
1611 EVT VecTy = Op->getValueType(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001612 SDValue One = DAG.getConstant(1, DL, VecTy);
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001613
1614 return DAG.getNode(ISD::XOR, DL, VecTy, Op->getOperand(1),
1615 DAG.getNode(ISD::SHL, DL, VecTy, One,
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00001616 truncateVecElts(Op, DAG)));
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001617 }
1618 case Intrinsic::mips_bnegi_b:
1619 case Intrinsic::mips_bnegi_h:
1620 case Intrinsic::mips_bnegi_w:
1621 case Intrinsic::mips_bnegi_d:
1622 return lowerMSABinaryBitImmIntr(Op, DAG, ISD::XOR, Op->getOperand(2),
Eric Christopher1c29a652014-07-18 22:55:25 +00001623 !Subtarget.isLittle());
Daniel Sandersce09d072013-08-28 12:14:50 +00001624 case Intrinsic::mips_bnz_b:
1625 case Intrinsic::mips_bnz_h:
1626 case Intrinsic::mips_bnz_w:
1627 case Intrinsic::mips_bnz_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001628 return DAG.getNode(MipsISD::VALL_NONZERO, DL, Op->getValueType(0),
1629 Op->getOperand(1));
Daniel Sandersce09d072013-08-28 12:14:50 +00001630 case Intrinsic::mips_bnz_v:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001631 return DAG.getNode(MipsISD::VANY_NONZERO, DL, Op->getValueType(0),
1632 Op->getOperand(1));
Daniel Sanderse1d24352013-09-24 12:04:44 +00001633 case Intrinsic::mips_bsel_v:
Daniel Sandersdf2215452014-03-12 11:54:00 +00001634 // bsel_v(Mask, IfClear, IfSet) -> (vselect Mask, IfSet, IfClear)
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001635 return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0),
Daniel Sandersdf2215452014-03-12 11:54:00 +00001636 Op->getOperand(1), Op->getOperand(3),
1637 Op->getOperand(2));
Daniel Sanderse1d24352013-09-24 12:04:44 +00001638 case Intrinsic::mips_bseli_b:
Daniel Sandersdf2215452014-03-12 11:54:00 +00001639 // bseli_v(Mask, IfClear, IfSet) -> (vselect Mask, IfSet, IfClear)
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001640 return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0),
Daniel Sandersdf2215452014-03-12 11:54:00 +00001641 Op->getOperand(1), lowerMSASplatImm(Op, 3, DAG),
1642 Op->getOperand(2));
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001643 case Intrinsic::mips_bset_b:
1644 case Intrinsic::mips_bset_h:
1645 case Intrinsic::mips_bset_w:
1646 case Intrinsic::mips_bset_d: {
1647 EVT VecTy = Op->getValueType(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001648 SDValue One = DAG.getConstant(1, DL, VecTy);
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001649
1650 return DAG.getNode(ISD::OR, DL, VecTy, Op->getOperand(1),
1651 DAG.getNode(ISD::SHL, DL, VecTy, One,
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00001652 truncateVecElts(Op, DAG)));
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001653 }
1654 case Intrinsic::mips_bseti_b:
1655 case Intrinsic::mips_bseti_h:
1656 case Intrinsic::mips_bseti_w:
1657 case Intrinsic::mips_bseti_d:
1658 return lowerMSABinaryBitImmIntr(Op, DAG, ISD::OR, Op->getOperand(2),
Eric Christopher1c29a652014-07-18 22:55:25 +00001659 !Subtarget.isLittle());
Daniel Sandersce09d072013-08-28 12:14:50 +00001660 case Intrinsic::mips_bz_b:
1661 case Intrinsic::mips_bz_h:
1662 case Intrinsic::mips_bz_w:
1663 case Intrinsic::mips_bz_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001664 return DAG.getNode(MipsISD::VALL_ZERO, DL, Op->getValueType(0),
1665 Op->getOperand(1));
Daniel Sandersce09d072013-08-28 12:14:50 +00001666 case Intrinsic::mips_bz_v:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001667 return DAG.getNode(MipsISD::VANY_ZERO, DL, Op->getValueType(0),
1668 Op->getOperand(1));
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001669 case Intrinsic::mips_ceq_b:
1670 case Intrinsic::mips_ceq_h:
1671 case Intrinsic::mips_ceq_w:
1672 case Intrinsic::mips_ceq_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001673 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001674 Op->getOperand(2), ISD::SETEQ);
1675 case Intrinsic::mips_ceqi_b:
1676 case Intrinsic::mips_ceqi_h:
1677 case Intrinsic::mips_ceqi_w:
1678 case Intrinsic::mips_ceqi_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001679 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Simon Dardis548a53f2017-01-10 16:40:57 +00001680 lowerMSASplatImm(Op, 2, DAG, true), ISD::SETEQ);
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001681 case Intrinsic::mips_cle_s_b:
1682 case Intrinsic::mips_cle_s_h:
1683 case Intrinsic::mips_cle_s_w:
1684 case Intrinsic::mips_cle_s_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001685 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001686 Op->getOperand(2), ISD::SETLE);
1687 case Intrinsic::mips_clei_s_b:
1688 case Intrinsic::mips_clei_s_h:
1689 case Intrinsic::mips_clei_s_w:
1690 case Intrinsic::mips_clei_s_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001691 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Simon Dardis548a53f2017-01-10 16:40:57 +00001692 lowerMSASplatImm(Op, 2, DAG, true), ISD::SETLE);
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001693 case Intrinsic::mips_cle_u_b:
1694 case Intrinsic::mips_cle_u_h:
1695 case Intrinsic::mips_cle_u_w:
1696 case Intrinsic::mips_cle_u_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001697 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001698 Op->getOperand(2), ISD::SETULE);
1699 case Intrinsic::mips_clei_u_b:
1700 case Intrinsic::mips_clei_u_h:
1701 case Intrinsic::mips_clei_u_w:
1702 case Intrinsic::mips_clei_u_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001703 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001704 lowerMSASplatImm(Op, 2, DAG), ISD::SETULE);
1705 case Intrinsic::mips_clt_s_b:
1706 case Intrinsic::mips_clt_s_h:
1707 case Intrinsic::mips_clt_s_w:
1708 case Intrinsic::mips_clt_s_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001709 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001710 Op->getOperand(2), ISD::SETLT);
1711 case Intrinsic::mips_clti_s_b:
1712 case Intrinsic::mips_clti_s_h:
1713 case Intrinsic::mips_clti_s_w:
1714 case Intrinsic::mips_clti_s_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001715 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Simon Dardis548a53f2017-01-10 16:40:57 +00001716 lowerMSASplatImm(Op, 2, DAG, true), ISD::SETLT);
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001717 case Intrinsic::mips_clt_u_b:
1718 case Intrinsic::mips_clt_u_h:
1719 case Intrinsic::mips_clt_u_w:
1720 case Intrinsic::mips_clt_u_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001721 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001722 Op->getOperand(2), ISD::SETULT);
1723 case Intrinsic::mips_clti_u_b:
1724 case Intrinsic::mips_clti_u_h:
1725 case Intrinsic::mips_clti_u_w:
1726 case Intrinsic::mips_clti_u_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001727 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001728 lowerMSASplatImm(Op, 2, DAG), ISD::SETULT);
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +00001729 case Intrinsic::mips_copy_s_b:
1730 case Intrinsic::mips_copy_s_h:
1731 case Intrinsic::mips_copy_s_w:
1732 return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_SEXT_ELT);
Daniel Sanders7f3d9462013-09-27 13:04:21 +00001733 case Intrinsic::mips_copy_s_d:
Eric Christopher1c29a652014-07-18 22:55:25 +00001734 if (Subtarget.hasMips64())
Matheus Almeida74070322014-01-29 14:05:28 +00001735 // Lower directly into VEXTRACT_SEXT_ELT since i64 is legal on Mips64.
1736 return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_SEXT_ELT);
1737 else {
1738 // Lower into the generic EXTRACT_VECTOR_ELT node and let the type
1739 // legalizer and EXTRACT_VECTOR_ELT lowering sort it out.
1740 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(Op),
1741 Op->getValueType(0), Op->getOperand(1),
1742 Op->getOperand(2));
1743 }
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +00001744 case Intrinsic::mips_copy_u_b:
1745 case Intrinsic::mips_copy_u_h:
1746 case Intrinsic::mips_copy_u_w:
1747 return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_ZEXT_ELT);
Daniel Sanders7f3d9462013-09-27 13:04:21 +00001748 case Intrinsic::mips_copy_u_d:
Eric Christopher1c29a652014-07-18 22:55:25 +00001749 if (Subtarget.hasMips64())
Matheus Almeida74070322014-01-29 14:05:28 +00001750 // Lower directly into VEXTRACT_ZEXT_ELT since i64 is legal on Mips64.
1751 return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_ZEXT_ELT);
1752 else {
1753 // Lower into the generic EXTRACT_VECTOR_ELT node and let the type
1754 // legalizer and EXTRACT_VECTOR_ELT lowering sort it out.
1755 // Note: When i64 is illegal, this results in copy_s.w instructions
1756 // instead of copy_u.w instructions. This makes no difference to the
1757 // behaviour since i64 is only illegal when the register file is 32-bit.
1758 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(Op),
1759 Op->getValueType(0), Op->getOperand(1),
1760 Op->getOperand(2));
1761 }
Daniel Sanders607952b2013-09-11 10:38:58 +00001762 case Intrinsic::mips_div_s_b:
1763 case Intrinsic::mips_div_s_h:
1764 case Intrinsic::mips_div_s_w:
1765 case Intrinsic::mips_div_s_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001766 return DAG.getNode(ISD::SDIV, DL, Op->getValueType(0), Op->getOperand(1),
1767 Op->getOperand(2));
Daniel Sanders607952b2013-09-11 10:38:58 +00001768 case Intrinsic::mips_div_u_b:
1769 case Intrinsic::mips_div_u_h:
1770 case Intrinsic::mips_div_u_w:
1771 case Intrinsic::mips_div_u_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001772 return DAG.getNode(ISD::UDIV, DL, Op->getValueType(0), Op->getOperand(1),
1773 Op->getOperand(2));
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001774 case Intrinsic::mips_fadd_w:
Eugene Zelenko79220eae2017-08-03 22:12:30 +00001775 case Intrinsic::mips_fadd_d:
Sanjay Patela2607012015-09-16 16:31:21 +00001776 // TODO: If intrinsics have fast-math-flags, propagate them.
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001777 return DAG.getNode(ISD::FADD, DL, Op->getValueType(0), Op->getOperand(1),
1778 Op->getOperand(2));
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001779 // Don't lower mips_fcaf_[wd] since LLVM folds SETFALSE condcodes away
1780 case Intrinsic::mips_fceq_w:
1781 case Intrinsic::mips_fceq_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001782 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001783 Op->getOperand(2), ISD::SETOEQ);
1784 case Intrinsic::mips_fcle_w:
1785 case Intrinsic::mips_fcle_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001786 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001787 Op->getOperand(2), ISD::SETOLE);
1788 case Intrinsic::mips_fclt_w:
1789 case Intrinsic::mips_fclt_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001790 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001791 Op->getOperand(2), ISD::SETOLT);
1792 case Intrinsic::mips_fcne_w:
1793 case Intrinsic::mips_fcne_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001794 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001795 Op->getOperand(2), ISD::SETONE);
1796 case Intrinsic::mips_fcor_w:
1797 case Intrinsic::mips_fcor_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001798 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001799 Op->getOperand(2), ISD::SETO);
1800 case Intrinsic::mips_fcueq_w:
1801 case Intrinsic::mips_fcueq_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001802 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001803 Op->getOperand(2), ISD::SETUEQ);
1804 case Intrinsic::mips_fcule_w:
1805 case Intrinsic::mips_fcule_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001806 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001807 Op->getOperand(2), ISD::SETULE);
1808 case Intrinsic::mips_fcult_w:
1809 case Intrinsic::mips_fcult_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001810 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001811 Op->getOperand(2), ISD::SETULT);
1812 case Intrinsic::mips_fcun_w:
1813 case Intrinsic::mips_fcun_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001814 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001815 Op->getOperand(2), ISD::SETUO);
1816 case Intrinsic::mips_fcune_w:
1817 case Intrinsic::mips_fcune_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001818 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001819 Op->getOperand(2), ISD::SETUNE);
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001820 case Intrinsic::mips_fdiv_w:
Eugene Zelenko79220eae2017-08-03 22:12:30 +00001821 case Intrinsic::mips_fdiv_d:
Sanjay Patela2607012015-09-16 16:31:21 +00001822 // TODO: If intrinsics have fast-math-flags, propagate them.
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001823 return DAG.getNode(ISD::FDIV, DL, Op->getValueType(0), Op->getOperand(1),
1824 Op->getOperand(2));
Daniel Sanders015972b2013-10-11 10:00:06 +00001825 case Intrinsic::mips_ffint_u_w:
1826 case Intrinsic::mips_ffint_u_d:
1827 return DAG.getNode(ISD::UINT_TO_FP, DL, Op->getValueType(0),
1828 Op->getOperand(1));
1829 case Intrinsic::mips_ffint_s_w:
1830 case Intrinsic::mips_ffint_s_d:
1831 return DAG.getNode(ISD::SINT_TO_FP, DL, Op->getValueType(0),
1832 Op->getOperand(1));
Daniel Sanders7a289d02013-09-23 12:02:46 +00001833 case Intrinsic::mips_fill_b:
1834 case Intrinsic::mips_fill_h:
Daniel Sandersc72593e2013-09-27 13:20:41 +00001835 case Intrinsic::mips_fill_w:
1836 case Intrinsic::mips_fill_d: {
Daniel Sandersf49dd822013-09-24 13:33:07 +00001837 EVT ResTy = Op->getValueType(0);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001838 SmallVector<SDValue, 16> Ops(ResTy.getVectorNumElements(),
1839 Op->getOperand(1));
Daniel Sandersf49dd822013-09-24 13:33:07 +00001840
Daniel Sandersc72593e2013-09-27 13:20:41 +00001841 // If ResTy is v2i64 then the type legalizer will break this node down into
1842 // an equivalent v4i32.
Ahmed Bougacha128f8732016-04-26 21:15:30 +00001843 return DAG.getBuildVector(ResTy, DL, Ops);
Daniel Sandersf49dd822013-09-24 13:33:07 +00001844 }
Daniel Sandersa9521602013-10-23 10:36:52 +00001845 case Intrinsic::mips_fexp2_w:
1846 case Intrinsic::mips_fexp2_d: {
Sanjay Patela2607012015-09-16 16:31:21 +00001847 // TODO: If intrinsics have fast-math-flags, propagate them.
Daniel Sandersa9521602013-10-23 10:36:52 +00001848 EVT ResTy = Op->getValueType(0);
1849 return DAG.getNode(
1850 ISD::FMUL, SDLoc(Op), ResTy, Op->getOperand(1),
1851 DAG.getNode(ISD::FEXP2, SDLoc(Op), ResTy, Op->getOperand(2)));
1852 }
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001853 case Intrinsic::mips_flog2_w:
1854 case Intrinsic::mips_flog2_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001855 return DAG.getNode(ISD::FLOG2, DL, Op->getValueType(0), Op->getOperand(1));
Daniel Sandersd7103f32013-10-11 10:14:25 +00001856 case Intrinsic::mips_fmadd_w:
1857 case Intrinsic::mips_fmadd_d:
1858 return DAG.getNode(ISD::FMA, SDLoc(Op), Op->getValueType(0),
1859 Op->getOperand(1), Op->getOperand(2), Op->getOperand(3));
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001860 case Intrinsic::mips_fmul_w:
Eugene Zelenko79220eae2017-08-03 22:12:30 +00001861 case Intrinsic::mips_fmul_d:
Sanjay Patela2607012015-09-16 16:31:21 +00001862 // TODO: If intrinsics have fast-math-flags, propagate them.
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001863 return DAG.getNode(ISD::FMUL, DL, Op->getValueType(0), Op->getOperand(1),
1864 Op->getOperand(2));
Daniel Sanderse67bd872013-10-11 10:27:32 +00001865 case Intrinsic::mips_fmsub_w:
1866 case Intrinsic::mips_fmsub_d: {
Sanjay Patela2607012015-09-16 16:31:21 +00001867 // TODO: If intrinsics have fast-math-flags, propagate them.
Aleksandar Beserminji3546c162018-04-27 13:30:27 +00001868 return DAG.getNode(MipsISD::FMS, SDLoc(Op), Op->getValueType(0),
1869 Op->getOperand(1), Op->getOperand(2), Op->getOperand(3));
Daniel Sanderse67bd872013-10-11 10:27:32 +00001870 }
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001871 case Intrinsic::mips_frint_w:
1872 case Intrinsic::mips_frint_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001873 return DAG.getNode(ISD::FRINT, DL, Op->getValueType(0), Op->getOperand(1));
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001874 case Intrinsic::mips_fsqrt_w:
1875 case Intrinsic::mips_fsqrt_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001876 return DAG.getNode(ISD::FSQRT, DL, Op->getValueType(0), Op->getOperand(1));
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001877 case Intrinsic::mips_fsub_w:
Eugene Zelenko79220eae2017-08-03 22:12:30 +00001878 case Intrinsic::mips_fsub_d:
Sanjay Patela2607012015-09-16 16:31:21 +00001879 // TODO: If intrinsics have fast-math-flags, propagate them.
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001880 return DAG.getNode(ISD::FSUB, DL, Op->getValueType(0), Op->getOperand(1),
1881 Op->getOperand(2));
Daniel Sanders015972b2013-10-11 10:00:06 +00001882 case Intrinsic::mips_ftrunc_u_w:
1883 case Intrinsic::mips_ftrunc_u_d:
1884 return DAG.getNode(ISD::FP_TO_UINT, DL, Op->getValueType(0),
1885 Op->getOperand(1));
1886 case Intrinsic::mips_ftrunc_s_w:
1887 case Intrinsic::mips_ftrunc_s_d:
1888 return DAG.getNode(ISD::FP_TO_SINT, DL, Op->getValueType(0),
1889 Op->getOperand(1));
Daniel Sanders2ed228b2013-09-24 14:36:12 +00001890 case Intrinsic::mips_ilvev_b:
1891 case Intrinsic::mips_ilvev_h:
1892 case Intrinsic::mips_ilvev_w:
1893 case Intrinsic::mips_ilvev_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001894 return DAG.getNode(MipsISD::ILVEV, DL, Op->getValueType(0),
Daniel Sanders2ed228b2013-09-24 14:36:12 +00001895 Op->getOperand(1), Op->getOperand(2));
1896 case Intrinsic::mips_ilvl_b:
1897 case Intrinsic::mips_ilvl_h:
1898 case Intrinsic::mips_ilvl_w:
1899 case Intrinsic::mips_ilvl_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001900 return DAG.getNode(MipsISD::ILVL, DL, Op->getValueType(0),
Daniel Sanders2ed228b2013-09-24 14:36:12 +00001901 Op->getOperand(1), Op->getOperand(2));
1902 case Intrinsic::mips_ilvod_b:
1903 case Intrinsic::mips_ilvod_h:
1904 case Intrinsic::mips_ilvod_w:
1905 case Intrinsic::mips_ilvod_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001906 return DAG.getNode(MipsISD::ILVOD, DL, Op->getValueType(0),
Daniel Sanders2ed228b2013-09-24 14:36:12 +00001907 Op->getOperand(1), Op->getOperand(2));
1908 case Intrinsic::mips_ilvr_b:
1909 case Intrinsic::mips_ilvr_h:
1910 case Intrinsic::mips_ilvr_w:
1911 case Intrinsic::mips_ilvr_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001912 return DAG.getNode(MipsISD::ILVR, DL, Op->getValueType(0),
Daniel Sanders2ed228b2013-09-24 14:36:12 +00001913 Op->getOperand(1), Op->getOperand(2));
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +00001914 case Intrinsic::mips_insert_b:
1915 case Intrinsic::mips_insert_h:
1916 case Intrinsic::mips_insert_w:
Daniel Sanders6098b332013-09-27 13:36:54 +00001917 case Intrinsic::mips_insert_d:
1918 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(Op), Op->getValueType(0),
1919 Op->getOperand(1), Op->getOperand(3), Op->getOperand(2));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001920 case Intrinsic::mips_insve_b:
1921 case Intrinsic::mips_insve_h:
1922 case Intrinsic::mips_insve_w:
Simon Dardis548a53f2017-01-10 16:40:57 +00001923 case Intrinsic::mips_insve_d: {
1924 // Report an error for out of range values.
1925 int64_t Max;
1926 switch (Intrinsic) {
1927 case Intrinsic::mips_insve_b: Max = 15; break;
1928 case Intrinsic::mips_insve_h: Max = 7; break;
1929 case Intrinsic::mips_insve_w: Max = 3; break;
1930 case Intrinsic::mips_insve_d: Max = 1; break;
1931 default: llvm_unreachable("Unmatched intrinsic");
1932 }
1933 int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
1934 if (Value < 0 || Value > Max)
1935 report_fatal_error("Immediate out of range");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001936 return DAG.getNode(MipsISD::INSVE, DL, Op->getValueType(0),
1937 Op->getOperand(1), Op->getOperand(2), Op->getOperand(3),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001938 DAG.getConstant(0, DL, MVT::i32));
Simon Dardis548a53f2017-01-10 16:40:57 +00001939 }
Daniel Sanders7a289d02013-09-23 12:02:46 +00001940 case Intrinsic::mips_ldi_b:
1941 case Intrinsic::mips_ldi_h:
1942 case Intrinsic::mips_ldi_w:
1943 case Intrinsic::mips_ldi_d:
Simon Dardis548a53f2017-01-10 16:40:57 +00001944 return lowerMSASplatImm(Op, 1, DAG, true);
Matheus Almeida4b27eb52014-02-10 12:05:17 +00001945 case Intrinsic::mips_lsa:
1946 case Intrinsic::mips_dlsa: {
Daniel Sandersa4eaf592013-10-17 13:38:20 +00001947 EVT ResTy = Op->getValueType(0);
1948 return DAG.getNode(ISD::ADD, SDLoc(Op), ResTy, Op->getOperand(1),
1949 DAG.getNode(ISD::SHL, SDLoc(Op), ResTy,
1950 Op->getOperand(2), Op->getOperand(3)));
1951 }
Daniel Sanders50e5ed32013-10-11 10:50:42 +00001952 case Intrinsic::mips_maddv_b:
1953 case Intrinsic::mips_maddv_h:
1954 case Intrinsic::mips_maddv_w:
1955 case Intrinsic::mips_maddv_d: {
1956 EVT ResTy = Op->getValueType(0);
1957 return DAG.getNode(ISD::ADD, SDLoc(Op), ResTy, Op->getOperand(1),
1958 DAG.getNode(ISD::MUL, SDLoc(Op), ResTy,
1959 Op->getOperand(2), Op->getOperand(3)));
1960 }
Daniel Sanders3ce56622013-09-24 12:18:31 +00001961 case Intrinsic::mips_max_s_b:
1962 case Intrinsic::mips_max_s_h:
1963 case Intrinsic::mips_max_s_w:
1964 case Intrinsic::mips_max_s_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001965 return DAG.getNode(ISD::SMAX, DL, Op->getValueType(0),
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001966 Op->getOperand(1), Op->getOperand(2));
Daniel Sanders3ce56622013-09-24 12:18:31 +00001967 case Intrinsic::mips_max_u_b:
1968 case Intrinsic::mips_max_u_h:
1969 case Intrinsic::mips_max_u_w:
1970 case Intrinsic::mips_max_u_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001971 return DAG.getNode(ISD::UMAX, DL, Op->getValueType(0),
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001972 Op->getOperand(1), Op->getOperand(2));
Daniel Sanders3ce56622013-09-24 12:18:31 +00001973 case Intrinsic::mips_maxi_s_b:
1974 case Intrinsic::mips_maxi_s_h:
1975 case Intrinsic::mips_maxi_s_w:
1976 case Intrinsic::mips_maxi_s_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001977 return DAG.getNode(ISD::SMAX, DL, Op->getValueType(0),
Simon Dardis548a53f2017-01-10 16:40:57 +00001978 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG, true));
Daniel Sanders3ce56622013-09-24 12:18:31 +00001979 case Intrinsic::mips_maxi_u_b:
1980 case Intrinsic::mips_maxi_u_h:
1981 case Intrinsic::mips_maxi_u_w:
1982 case Intrinsic::mips_maxi_u_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001983 return DAG.getNode(ISD::UMAX, DL, Op->getValueType(0),
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001984 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Daniel Sanders3ce56622013-09-24 12:18:31 +00001985 case Intrinsic::mips_min_s_b:
1986 case Intrinsic::mips_min_s_h:
1987 case Intrinsic::mips_min_s_w:
1988 case Intrinsic::mips_min_s_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001989 return DAG.getNode(ISD::SMIN, DL, Op->getValueType(0),
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001990 Op->getOperand(1), Op->getOperand(2));
Daniel Sanders3ce56622013-09-24 12:18:31 +00001991 case Intrinsic::mips_min_u_b:
1992 case Intrinsic::mips_min_u_h:
1993 case Intrinsic::mips_min_u_w:
1994 case Intrinsic::mips_min_u_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001995 return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0),
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001996 Op->getOperand(1), Op->getOperand(2));
Daniel Sanders3ce56622013-09-24 12:18:31 +00001997 case Intrinsic::mips_mini_s_b:
1998 case Intrinsic::mips_mini_s_h:
1999 case Intrinsic::mips_mini_s_w:
2000 case Intrinsic::mips_mini_s_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00002001 return DAG.getNode(ISD::SMIN, DL, Op->getValueType(0),
Simon Dardis548a53f2017-01-10 16:40:57 +00002002 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG, true));
Daniel Sanders3ce56622013-09-24 12:18:31 +00002003 case Intrinsic::mips_mini_u_b:
2004 case Intrinsic::mips_mini_u_h:
2005 case Intrinsic::mips_mini_u_w:
2006 case Intrinsic::mips_mini_u_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00002007 return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0),
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002008 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Daniel Sanders0210dd42013-10-01 10:22:35 +00002009 case Intrinsic::mips_mod_s_b:
2010 case Intrinsic::mips_mod_s_h:
2011 case Intrinsic::mips_mod_s_w:
2012 case Intrinsic::mips_mod_s_d:
2013 return DAG.getNode(ISD::SREM, DL, Op->getValueType(0), Op->getOperand(1),
2014 Op->getOperand(2));
2015 case Intrinsic::mips_mod_u_b:
2016 case Intrinsic::mips_mod_u_h:
2017 case Intrinsic::mips_mod_u_w:
2018 case Intrinsic::mips_mod_u_d:
2019 return DAG.getNode(ISD::UREM, DL, Op->getValueType(0), Op->getOperand(1),
2020 Op->getOperand(2));
Daniel Sandersfbcb5822013-09-11 11:58:30 +00002021 case Intrinsic::mips_mulv_b:
2022 case Intrinsic::mips_mulv_h:
2023 case Intrinsic::mips_mulv_w:
2024 case Intrinsic::mips_mulv_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002025 return DAG.getNode(ISD::MUL, DL, Op->getValueType(0), Op->getOperand(1),
2026 Op->getOperand(2));
Daniel Sanders50e5ed32013-10-11 10:50:42 +00002027 case Intrinsic::mips_msubv_b:
2028 case Intrinsic::mips_msubv_h:
2029 case Intrinsic::mips_msubv_w:
2030 case Intrinsic::mips_msubv_d: {
2031 EVT ResTy = Op->getValueType(0);
2032 return DAG.getNode(ISD::SUB, SDLoc(Op), ResTy, Op->getOperand(1),
2033 DAG.getNode(ISD::MUL, SDLoc(Op), ResTy,
2034 Op->getOperand(2), Op->getOperand(3)));
2035 }
Daniel Sandersfbcb5822013-09-11 11:58:30 +00002036 case Intrinsic::mips_nlzc_b:
2037 case Intrinsic::mips_nlzc_h:
2038 case Intrinsic::mips_nlzc_w:
2039 case Intrinsic::mips_nlzc_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002040 return DAG.getNode(ISD::CTLZ, DL, Op->getValueType(0), Op->getOperand(1));
Daniel Sandersf7456c72013-09-23 13:22:24 +00002041 case Intrinsic::mips_nor_v: {
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002042 SDValue Res = DAG.getNode(ISD::OR, DL, Op->getValueType(0),
2043 Op->getOperand(1), Op->getOperand(2));
2044 return DAG.getNOT(DL, Res, Res->getValueType(0));
Daniel Sandersf7456c72013-09-23 13:22:24 +00002045 }
Daniel Sandersbfc39ce2013-09-24 12:32:47 +00002046 case Intrinsic::mips_nori_b: {
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002047 SDValue Res = DAG.getNode(ISD::OR, DL, Op->getValueType(0),
2048 Op->getOperand(1),
2049 lowerMSASplatImm(Op, 2, DAG));
2050 return DAG.getNOT(DL, Res, Res->getValueType(0));
Daniel Sandersbfc39ce2013-09-24 12:32:47 +00002051 }
Daniel Sanders8ca81e42013-09-23 12:57:42 +00002052 case Intrinsic::mips_or_v:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002053 return DAG.getNode(ISD::OR, DL, Op->getValueType(0), Op->getOperand(1),
2054 Op->getOperand(2));
Daniel Sandersbfc39ce2013-09-24 12:32:47 +00002055 case Intrinsic::mips_ori_b:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002056 return DAG.getNode(ISD::OR, DL, Op->getValueType(0),
2057 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002058 case Intrinsic::mips_pckev_b:
2059 case Intrinsic::mips_pckev_h:
2060 case Intrinsic::mips_pckev_w:
2061 case Intrinsic::mips_pckev_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002062 return DAG.getNode(MipsISD::PCKEV, DL, Op->getValueType(0),
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002063 Op->getOperand(1), Op->getOperand(2));
2064 case Intrinsic::mips_pckod_b:
2065 case Intrinsic::mips_pckod_h:
2066 case Intrinsic::mips_pckod_w:
2067 case Intrinsic::mips_pckod_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002068 return DAG.getNode(MipsISD::PCKOD, DL, Op->getValueType(0),
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002069 Op->getOperand(1), Op->getOperand(2));
Daniel Sanders766cb692013-09-23 13:40:21 +00002070 case Intrinsic::mips_pcnt_b:
2071 case Intrinsic::mips_pcnt_h:
2072 case Intrinsic::mips_pcnt_w:
2073 case Intrinsic::mips_pcnt_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002074 return DAG.getNode(ISD::CTPOP, DL, Op->getValueType(0), Op->getOperand(1));
Simon Dardis548a53f2017-01-10 16:40:57 +00002075 case Intrinsic::mips_sat_s_b:
2076 case Intrinsic::mips_sat_s_h:
2077 case Intrinsic::mips_sat_s_w:
2078 case Intrinsic::mips_sat_s_d:
2079 case Intrinsic::mips_sat_u_b:
2080 case Intrinsic::mips_sat_u_h:
2081 case Intrinsic::mips_sat_u_w:
2082 case Intrinsic::mips_sat_u_d: {
2083 // Report an error for out of range values.
2084 int64_t Max;
2085 switch (Intrinsic) {
2086 case Intrinsic::mips_sat_s_b:
2087 case Intrinsic::mips_sat_u_b: Max = 7; break;
2088 case Intrinsic::mips_sat_s_h:
2089 case Intrinsic::mips_sat_u_h: Max = 15; break;
2090 case Intrinsic::mips_sat_s_w:
2091 case Intrinsic::mips_sat_u_w: Max = 31; break;
2092 case Intrinsic::mips_sat_s_d:
2093 case Intrinsic::mips_sat_u_d: Max = 63; break;
2094 default: llvm_unreachable("Unmatched intrinsic");
2095 }
2096 int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
2097 if (Value < 0 || Value > Max)
2098 report_fatal_error("Immediate out of range");
2099 return SDValue();
2100 }
Daniel Sanders26307182013-09-24 14:20:00 +00002101 case Intrinsic::mips_shf_b:
2102 case Intrinsic::mips_shf_h:
Simon Dardis548a53f2017-01-10 16:40:57 +00002103 case Intrinsic::mips_shf_w: {
2104 int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
2105 if (Value < 0 || Value > 255)
2106 report_fatal_error("Immediate out of range");
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002107 return DAG.getNode(MipsISD::SHF, DL, Op->getValueType(0),
Daniel Sanders26307182013-09-24 14:20:00 +00002108 Op->getOperand(2), Op->getOperand(1));
Simon Dardis548a53f2017-01-10 16:40:57 +00002109 }
2110 case Intrinsic::mips_sldi_b:
2111 case Intrinsic::mips_sldi_h:
2112 case Intrinsic::mips_sldi_w:
2113 case Intrinsic::mips_sldi_d: {
2114 // Report an error for out of range values.
2115 int64_t Max;
2116 switch (Intrinsic) {
2117 case Intrinsic::mips_sldi_b: Max = 15; break;
2118 case Intrinsic::mips_sldi_h: Max = 7; break;
2119 case Intrinsic::mips_sldi_w: Max = 3; break;
2120 case Intrinsic::mips_sldi_d: Max = 1; break;
2121 default: llvm_unreachable("Unmatched intrinsic");
2122 }
2123 int64_t Value = cast<ConstantSDNode>(Op->getOperand(3))->getSExtValue();
2124 if (Value < 0 || Value > Max)
2125 report_fatal_error("Immediate out of range");
2126 return SDValue();
2127 }
Daniel Sandersfbcb5822013-09-11 11:58:30 +00002128 case Intrinsic::mips_sll_b:
2129 case Intrinsic::mips_sll_h:
2130 case Intrinsic::mips_sll_w:
2131 case Intrinsic::mips_sll_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002132 return DAG.getNode(ISD::SHL, DL, Op->getValueType(0), Op->getOperand(1),
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00002133 truncateVecElts(Op, DAG));
Daniel Sanderscba19222013-09-24 10:28:18 +00002134 case Intrinsic::mips_slli_b:
2135 case Intrinsic::mips_slli_h:
2136 case Intrinsic::mips_slli_w:
2137 case Intrinsic::mips_slli_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002138 return DAG.getNode(ISD::SHL, DL, Op->getValueType(0),
2139 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Daniel Sanderse7ef0c82013-10-30 13:07:44 +00002140 case Intrinsic::mips_splat_b:
2141 case Intrinsic::mips_splat_h:
2142 case Intrinsic::mips_splat_w:
2143 case Intrinsic::mips_splat_d:
2144 // We can't lower via VECTOR_SHUFFLE because it requires constant shuffle
2145 // masks, nor can we lower via BUILD_VECTOR & EXTRACT_VECTOR_ELT because
2146 // EXTRACT_VECTOR_ELT can't extract i64's on MIPS32.
2147 // Instead we lower to MipsISD::VSHF and match from there.
2148 return DAG.getNode(MipsISD::VSHF, DL, Op->getValueType(0),
Daniel Sanders50b80412013-11-15 12:56:49 +00002149 lowerMSASplatZExt(Op, 2, DAG), Op->getOperand(1),
Daniel Sanderse7ef0c82013-10-30 13:07:44 +00002150 Op->getOperand(1));
Daniel Sanders7e51fe12013-09-27 11:48:57 +00002151 case Intrinsic::mips_splati_b:
2152 case Intrinsic::mips_splati_h:
2153 case Intrinsic::mips_splati_w:
2154 case Intrinsic::mips_splati_d:
2155 return DAG.getNode(MipsISD::VSHF, DL, Op->getValueType(0),
2156 lowerMSASplatImm(Op, 2, DAG), Op->getOperand(1),
2157 Op->getOperand(1));
Daniel Sandersfbcb5822013-09-11 11:58:30 +00002158 case Intrinsic::mips_sra_b:
2159 case Intrinsic::mips_sra_h:
2160 case Intrinsic::mips_sra_w:
2161 case Intrinsic::mips_sra_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002162 return DAG.getNode(ISD::SRA, DL, Op->getValueType(0), Op->getOperand(1),
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00002163 truncateVecElts(Op, DAG));
Daniel Sanderscba19222013-09-24 10:28:18 +00002164 case Intrinsic::mips_srai_b:
2165 case Intrinsic::mips_srai_h:
2166 case Intrinsic::mips_srai_w:
2167 case Intrinsic::mips_srai_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002168 return DAG.getNode(ISD::SRA, DL, Op->getValueType(0),
2169 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Simon Dardis548a53f2017-01-10 16:40:57 +00002170 case Intrinsic::mips_srari_b:
2171 case Intrinsic::mips_srari_h:
2172 case Intrinsic::mips_srari_w:
2173 case Intrinsic::mips_srari_d: {
2174 // Report an error for out of range values.
2175 int64_t Max;
2176 switch (Intrinsic) {
2177 case Intrinsic::mips_srari_b: Max = 7; break;
2178 case Intrinsic::mips_srari_h: Max = 15; break;
2179 case Intrinsic::mips_srari_w: Max = 31; break;
2180 case Intrinsic::mips_srari_d: Max = 63; break;
2181 default: llvm_unreachable("Unmatched intrinsic");
2182 }
2183 int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
2184 if (Value < 0 || Value > Max)
2185 report_fatal_error("Immediate out of range");
2186 return SDValue();
2187 }
Daniel Sandersfbcb5822013-09-11 11:58:30 +00002188 case Intrinsic::mips_srl_b:
2189 case Intrinsic::mips_srl_h:
2190 case Intrinsic::mips_srl_w:
2191 case Intrinsic::mips_srl_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002192 return DAG.getNode(ISD::SRL, DL, Op->getValueType(0), Op->getOperand(1),
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00002193 truncateVecElts(Op, DAG));
Daniel Sanderscba19222013-09-24 10:28:18 +00002194 case Intrinsic::mips_srli_b:
2195 case Intrinsic::mips_srli_h:
2196 case Intrinsic::mips_srli_w:
2197 case Intrinsic::mips_srli_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002198 return DAG.getNode(ISD::SRL, DL, Op->getValueType(0),
2199 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Simon Dardis548a53f2017-01-10 16:40:57 +00002200 case Intrinsic::mips_srlri_b:
2201 case Intrinsic::mips_srlri_h:
2202 case Intrinsic::mips_srlri_w:
2203 case Intrinsic::mips_srlri_d: {
2204 // Report an error for out of range values.
2205 int64_t Max;
2206 switch (Intrinsic) {
2207 case Intrinsic::mips_srlri_b: Max = 7; break;
2208 case Intrinsic::mips_srlri_h: Max = 15; break;
2209 case Intrinsic::mips_srlri_w: Max = 31; break;
2210 case Intrinsic::mips_srlri_d: Max = 63; break;
2211 default: llvm_unreachable("Unmatched intrinsic");
2212 }
2213 int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
2214 if (Value < 0 || Value > Max)
2215 report_fatal_error("Immediate out of range");
2216 return SDValue();
2217 }
Daniel Sandersfbcb5822013-09-11 11:58:30 +00002218 case Intrinsic::mips_subv_b:
2219 case Intrinsic::mips_subv_h:
2220 case Intrinsic::mips_subv_w:
2221 case Intrinsic::mips_subv_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002222 return DAG.getNode(ISD::SUB, DL, Op->getValueType(0), Op->getOperand(1),
2223 Op->getOperand(2));
Daniel Sanders86d0c8d2013-09-23 14:29:55 +00002224 case Intrinsic::mips_subvi_b:
2225 case Intrinsic::mips_subvi_h:
2226 case Intrinsic::mips_subvi_w:
2227 case Intrinsic::mips_subvi_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002228 return DAG.getNode(ISD::SUB, DL, Op->getValueType(0),
2229 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Daniel Sanderse5087042013-09-24 14:02:15 +00002230 case Intrinsic::mips_vshf_b:
2231 case Intrinsic::mips_vshf_h:
2232 case Intrinsic::mips_vshf_w:
2233 case Intrinsic::mips_vshf_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002234 return DAG.getNode(MipsISD::VSHF, DL, Op->getValueType(0),
Daniel Sanderse5087042013-09-24 14:02:15 +00002235 Op->getOperand(1), Op->getOperand(2), Op->getOperand(3));
Daniel Sanders8ca81e42013-09-23 12:57:42 +00002236 case Intrinsic::mips_xor_v:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002237 return DAG.getNode(ISD::XOR, DL, Op->getValueType(0), Op->getOperand(1),
2238 Op->getOperand(2));
Daniel Sandersbfc39ce2013-09-24 12:32:47 +00002239 case Intrinsic::mips_xori_b:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002240 return DAG.getNode(ISD::XOR, DL, Op->getValueType(0),
2241 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Marcin Koscielnicki7efdca52016-04-27 17:21:49 +00002242 case Intrinsic::thread_pointer: {
2243 EVT PtrVT = getPointerTy(DAG.getDataLayout());
2244 return DAG.getNode(MipsISD::ThreadPointer, DL, PtrVT);
2245 }
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00002246 }
2247}
2248
Simon Dardis548a53f2017-01-10 16:40:57 +00002249static SDValue lowerMSALoadIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr,
2250 const MipsSubtarget &Subtarget) {
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002251 SDLoc DL(Op);
2252 SDValue ChainIn = Op->getOperand(0);
2253 SDValue Address = Op->getOperand(2);
2254 SDValue Offset = Op->getOperand(3);
2255 EVT ResTy = Op->getValueType(0);
2256 EVT PtrTy = Address->getValueType(0);
2257
Simon Dardis548a53f2017-01-10 16:40:57 +00002258 // For N64 addresses have the underlying type MVT::i64. This intrinsic
2259 // however takes an i32 signed constant offset. The actual type of the
2260 // intrinsic is a scaled signed i10.
2261 if (Subtarget.isABI_N64())
2262 Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset);
2263
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002264 Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset);
Justin Lebar9c375812016-07-15 18:27:10 +00002265 return DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(),
2266 /* Alignment = */ 16);
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002267}
2268
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00002269SDValue MipsSETargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,
2270 SelectionDAG &DAG) const {
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002271 unsigned Intr = cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue();
2272 switch (Intr) {
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00002273 default:
2274 return SDValue();
2275 case Intrinsic::mips_extp:
2276 return lowerDSPIntr(Op, DAG, MipsISD::EXTP);
2277 case Intrinsic::mips_extpdp:
2278 return lowerDSPIntr(Op, DAG, MipsISD::EXTPDP);
2279 case Intrinsic::mips_extr_w:
2280 return lowerDSPIntr(Op, DAG, MipsISD::EXTR_W);
2281 case Intrinsic::mips_extr_r_w:
2282 return lowerDSPIntr(Op, DAG, MipsISD::EXTR_R_W);
2283 case Intrinsic::mips_extr_rs_w:
2284 return lowerDSPIntr(Op, DAG, MipsISD::EXTR_RS_W);
2285 case Intrinsic::mips_extr_s_h:
2286 return lowerDSPIntr(Op, DAG, MipsISD::EXTR_S_H);
2287 case Intrinsic::mips_mthlip:
2288 return lowerDSPIntr(Op, DAG, MipsISD::MTHLIP);
2289 case Intrinsic::mips_mulsaq_s_w_ph:
2290 return lowerDSPIntr(Op, DAG, MipsISD::MULSAQ_S_W_PH);
2291 case Intrinsic::mips_maq_s_w_phl:
2292 return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHL);
2293 case Intrinsic::mips_maq_s_w_phr:
2294 return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHR);
2295 case Intrinsic::mips_maq_sa_w_phl:
2296 return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHL);
2297 case Intrinsic::mips_maq_sa_w_phr:
2298 return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHR);
2299 case Intrinsic::mips_dpaq_s_w_ph:
2300 return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_S_W_PH);
2301 case Intrinsic::mips_dpsq_s_w_ph:
2302 return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_S_W_PH);
2303 case Intrinsic::mips_dpaq_sa_l_w:
2304 return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_SA_L_W);
2305 case Intrinsic::mips_dpsq_sa_l_w:
2306 return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_SA_L_W);
2307 case Intrinsic::mips_dpaqx_s_w_ph:
2308 return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_S_W_PH);
2309 case Intrinsic::mips_dpaqx_sa_w_ph:
2310 return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_SA_W_PH);
2311 case Intrinsic::mips_dpsqx_s_w_ph:
2312 return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_S_W_PH);
2313 case Intrinsic::mips_dpsqx_sa_w_ph:
2314 return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_SA_W_PH);
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002315 case Intrinsic::mips_ld_b:
2316 case Intrinsic::mips_ld_h:
2317 case Intrinsic::mips_ld_w:
2318 case Intrinsic::mips_ld_d:
Simon Dardis548a53f2017-01-10 16:40:57 +00002319 return lowerMSALoadIntr(Op, DAG, Intr, Subtarget);
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002320 }
2321}
2322
Simon Dardis548a53f2017-01-10 16:40:57 +00002323static SDValue lowerMSAStoreIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr,
2324 const MipsSubtarget &Subtarget) {
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002325 SDLoc DL(Op);
2326 SDValue ChainIn = Op->getOperand(0);
2327 SDValue Value = Op->getOperand(2);
2328 SDValue Address = Op->getOperand(3);
2329 SDValue Offset = Op->getOperand(4);
2330 EVT PtrTy = Address->getValueType(0);
2331
Simon Dardis548a53f2017-01-10 16:40:57 +00002332 // For N64 addresses have the underlying type MVT::i64. This intrinsic
2333 // however takes an i32 signed constant offset. The actual type of the
2334 // intrinsic is a scaled signed i10.
2335 if (Subtarget.isABI_N64())
2336 Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset);
2337
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002338 Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset);
2339
Justin Lebar9c375812016-07-15 18:27:10 +00002340 return DAG.getStore(ChainIn, DL, Value, Address, MachinePointerInfo(),
2341 /* Alignment = */ 16);
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002342}
2343
2344SDValue MipsSETargetLowering::lowerINTRINSIC_VOID(SDValue Op,
2345 SelectionDAG &DAG) const {
2346 unsigned Intr = cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue();
2347 switch (Intr) {
2348 default:
2349 return SDValue();
2350 case Intrinsic::mips_st_b:
2351 case Intrinsic::mips_st_h:
2352 case Intrinsic::mips_st_w:
2353 case Intrinsic::mips_st_d:
Simon Dardis548a53f2017-01-10 16:40:57 +00002354 return lowerMSAStoreIntr(Op, DAG, Intr, Subtarget);
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00002355 }
2356}
2357
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00002358/// Check if the given BuildVectorSDNode is a splat.
Daniel Sanders7a289d02013-09-23 12:02:46 +00002359/// This method currently relies on DAG nodes being reused when equivalent,
2360/// so it's possible for this to return false even when isConstantSplat returns
2361/// true.
2362static bool isSplatVector(const BuildVectorSDNode *N) {
Daniel Sanders7a289d02013-09-23 12:02:46 +00002363 unsigned int nOps = N->getNumOperands();
Daniel Sandersab94b532013-10-30 15:20:38 +00002364 assert(nOps > 1 && "isSplatVector has 0 or 1 sized build vector");
Daniel Sanders7a289d02013-09-23 12:02:46 +00002365
2366 SDValue Operand0 = N->getOperand(0);
2367
2368 for (unsigned int i = 1; i < nOps; ++i) {
2369 if (N->getOperand(i) != Operand0)
2370 return false;
2371 }
2372
2373 return true;
2374}
2375
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +00002376// Lower ISD::EXTRACT_VECTOR_ELT into MipsISD::VEXTRACT_SEXT_ELT.
2377//
2378// The non-value bits resulting from ISD::EXTRACT_VECTOR_ELT are undefined. We
2379// choose to sign-extend but we could have equally chosen zero-extend. The
2380// DAGCombiner will fold any sign/zero extension of the ISD::EXTRACT_VECTOR_ELT
2381// result into this node later (possibly changing it to a zero-extend in the
2382// process).
2383SDValue MipsSETargetLowering::
2384lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const {
2385 SDLoc DL(Op);
2386 EVT ResTy = Op->getValueType(0);
2387 SDValue Op0 = Op->getOperand(0);
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00002388 EVT VecTy = Op0->getValueType(0);
2389
2390 if (!VecTy.is128BitVector())
2391 return SDValue();
2392
2393 if (ResTy.isInteger()) {
2394 SDValue Op1 = Op->getOperand(1);
2395 EVT EltTy = VecTy.getVectorElementType();
2396 return DAG.getNode(MipsISD::VEXTRACT_SEXT_ELT, DL, ResTy, Op0, Op1,
2397 DAG.getValueType(EltTy));
2398 }
2399
2400 return Op;
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +00002401}
2402
Daniel Sandersf49dd822013-09-24 13:33:07 +00002403static bool isConstantOrUndef(const SDValue Op) {
Sanjay Patel57195842016-03-14 17:28:46 +00002404 if (Op->isUndef())
Daniel Sandersf49dd822013-09-24 13:33:07 +00002405 return true;
Vasileios Kalintiris46963f62015-02-13 19:12:16 +00002406 if (isa<ConstantSDNode>(Op))
Daniel Sandersf49dd822013-09-24 13:33:07 +00002407 return true;
Vasileios Kalintiris46963f62015-02-13 19:12:16 +00002408 if (isa<ConstantFPSDNode>(Op))
Daniel Sandersf49dd822013-09-24 13:33:07 +00002409 return true;
2410 return false;
2411}
2412
2413static bool isConstantOrUndefBUILD_VECTOR(const BuildVectorSDNode *Op) {
2414 for (unsigned i = 0; i < Op->getNumOperands(); ++i)
2415 if (isConstantOrUndef(Op->getOperand(i)))
2416 return true;
2417 return false;
2418}
2419
Daniel Sanders7a289d02013-09-23 12:02:46 +00002420// Lowers ISD::BUILD_VECTOR into appropriate SelectionDAG nodes for the
2421// backend.
2422//
2423// Lowers according to the following rules:
Daniel Sandersf49dd822013-09-24 13:33:07 +00002424// - Constant splats are legal as-is as long as the SplatBitSize is a power of
2425// 2 less than or equal to 64 and the value fits into a signed 10-bit
2426// immediate
2427// - Constant splats are lowered to bitconverted BUILD_VECTORs if SplatBitSize
2428// is a power of 2 less than or equal to 64 and the value does not fit into a
2429// signed 10-bit immediate
2430// - Non-constant splats are legal as-is.
2431// - Non-constant non-splats are lowered to sequences of INSERT_VECTOR_ELT.
2432// - All others are illegal and must be expanded.
Daniel Sanders7a289d02013-09-23 12:02:46 +00002433SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op,
2434 SelectionDAG &DAG) const {
2435 BuildVectorSDNode *Node = cast<BuildVectorSDNode>(Op);
2436 EVT ResTy = Op->getValueType(0);
2437 SDLoc DL(Op);
2438 APInt SplatValue, SplatUndef;
2439 unsigned SplatBitSize;
2440 bool HasAnyUndefs;
2441
Eric Christopher1c29a652014-07-18 22:55:25 +00002442 if (!Subtarget.hasMSA() || !ResTy.is128BitVector())
Daniel Sanders7a289d02013-09-23 12:02:46 +00002443 return SDValue();
2444
2445 if (Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
2446 HasAnyUndefs, 8,
Eric Christopher1c29a652014-07-18 22:55:25 +00002447 !Subtarget.isLittle()) && SplatBitSize <= 64) {
Daniel Sandersf49dd822013-09-24 13:33:07 +00002448 // We can only cope with 8, 16, 32, or 64-bit elements
2449 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
2450 SplatBitSize != 64)
2451 return SDValue();
2452
Simon Dardis7090d142017-03-10 13:27:14 +00002453 // If the value isn't an integer type we will have to bitcast
2454 // from an integer type first. Also, if there are any undefs, we must
2455 // lower them to defined values first.
2456 if (ResTy.isInteger() && !HasAnyUndefs)
Daniel Sandersf49dd822013-09-24 13:33:07 +00002457 return Op;
2458
2459 EVT ViaVecTy;
Daniel Sanders7a289d02013-09-23 12:02:46 +00002460
2461 switch (SplatBitSize) {
2462 default:
2463 return SDValue();
Daniel Sandersf49dd822013-09-24 13:33:07 +00002464 case 8:
2465 ViaVecTy = MVT::v16i8;
Daniel Sanders7a289d02013-09-23 12:02:46 +00002466 break;
2467 case 16:
Daniel Sandersf49dd822013-09-24 13:33:07 +00002468 ViaVecTy = MVT::v8i16;
Daniel Sanders7a289d02013-09-23 12:02:46 +00002469 break;
Daniel Sandersf49dd822013-09-24 13:33:07 +00002470 case 32:
2471 ViaVecTy = MVT::v4i32;
Daniel Sanders7a289d02013-09-23 12:02:46 +00002472 break;
Daniel Sandersf49dd822013-09-24 13:33:07 +00002473 case 64:
2474 // There's no fill.d to fall back on for 64-bit values
2475 return SDValue();
Daniel Sanders7a289d02013-09-23 12:02:46 +00002476 }
2477
Daniel Sanders50b80412013-11-15 12:56:49 +00002478 // SelectionDAG::getConstant will promote SplatValue appropriately.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002479 SDValue Result = DAG.getConstant(SplatValue, DL, ViaVecTy);
Daniel Sandersf49dd822013-09-24 13:33:07 +00002480
Daniel Sanders50b80412013-11-15 12:56:49 +00002481 // Bitcast to the type we originally wanted
Daniel Sandersf49dd822013-09-24 13:33:07 +00002482 if (ViaVecTy != ResTy)
2483 Result = DAG.getNode(ISD::BITCAST, SDLoc(Node), ResTy, Result);
Daniel Sanders7a289d02013-09-23 12:02:46 +00002484
2485 return Result;
Daniel Sandersf49dd822013-09-24 13:33:07 +00002486 } else if (isSplatVector(Node))
2487 return Op;
2488 else if (!isConstantOrUndefBUILD_VECTOR(Node)) {
Daniel Sandersf86622b2013-09-24 13:16:15 +00002489 // Use INSERT_VECTOR_ELT operations rather than expand to stores.
2490 // The resulting code is the same length as the expansion, but it doesn't
2491 // use memory operations
2492 EVT ResTy = Node->getValueType(0);
2493
2494 assert(ResTy.isVector());
2495
2496 unsigned NumElts = ResTy.getVectorNumElements();
2497 SDValue Vector = DAG.getUNDEF(ResTy);
2498 for (unsigned i = 0; i < NumElts; ++i) {
2499 Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, ResTy, Vector,
2500 Node->getOperand(i),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002501 DAG.getConstant(i, DL, MVT::i32));
Daniel Sandersf86622b2013-09-24 13:16:15 +00002502 }
2503 return Vector;
2504 }
Daniel Sanders7a289d02013-09-23 12:02:46 +00002505
2506 return SDValue();
2507}
2508
Daniel Sanders26307182013-09-24 14:20:00 +00002509// Lower VECTOR_SHUFFLE into SHF (if possible).
2510//
2511// SHF splits the vector into blocks of four elements, then shuffles these
2512// elements according to a <4 x i2> constant (encoded as an integer immediate).
2513//
2514// It is therefore possible to lower into SHF when the mask takes the form:
2515// <a, b, c, d, a+4, b+4, c+4, d+4, a+8, b+8, c+8, d+8, ...>
2516// When undef's appear they are treated as if they were whatever value is
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002517// necessary in order to fit the above forms.
Daniel Sanders26307182013-09-24 14:20:00 +00002518//
2519// For example:
2520// %2 = shufflevector <8 x i16> %0, <8 x i16> undef,
2521// <8 x i32> <i32 3, i32 2, i32 1, i32 0,
2522// i32 7, i32 6, i32 5, i32 4>
2523// is lowered to:
2524// (SHF_H $w0, $w1, 27)
2525// where the 27 comes from:
2526// 3 + (2 << 2) + (1 << 4) + (0 << 6)
2527static SDValue lowerVECTOR_SHUFFLE_SHF(SDValue Op, EVT ResTy,
2528 SmallVector<int, 16> Indices,
2529 SelectionDAG &DAG) {
2530 int SHFIndices[4] = { -1, -1, -1, -1 };
2531
2532 if (Indices.size() < 4)
2533 return SDValue();
2534
2535 for (unsigned i = 0; i < 4; ++i) {
2536 for (unsigned j = i; j < Indices.size(); j += 4) {
2537 int Idx = Indices[j];
2538
2539 // Convert from vector index to 4-element subvector index
2540 // If an index refers to an element outside of the subvector then give up
2541 if (Idx != -1) {
2542 Idx -= 4 * (j / 4);
2543 if (Idx < 0 || Idx >= 4)
2544 return SDValue();
2545 }
2546
2547 // If the mask has an undef, replace it with the current index.
2548 // Note that it might still be undef if the current index is also undef
2549 if (SHFIndices[i] == -1)
2550 SHFIndices[i] = Idx;
2551
2552 // Check that non-undef values are the same as in the mask. If they
2553 // aren't then give up
2554 if (!(Idx == -1 || Idx == SHFIndices[i]))
2555 return SDValue();
2556 }
2557 }
2558
2559 // Calculate the immediate. Replace any remaining undefs with zero
2560 APInt Imm(32, 0);
2561 for (int i = 3; i >= 0; --i) {
2562 int Idx = SHFIndices[i];
2563
2564 if (Idx == -1)
2565 Idx = 0;
2566
2567 Imm <<= 2;
2568 Imm |= Idx & 0x3;
2569 }
2570
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002571 SDLoc DL(Op);
2572 return DAG.getNode(MipsISD::SHF, DL, ResTy,
2573 DAG.getConstant(Imm, DL, MVT::i32), Op->getOperand(0));
Daniel Sanders26307182013-09-24 14:20:00 +00002574}
2575
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002576/// Determine whether a range fits a regular pattern of values.
2577/// This function accounts for the possibility of jumping over the End iterator.
2578template <typename ValType>
2579static bool
2580fitsRegularPattern(typename SmallVectorImpl<ValType>::const_iterator Begin,
2581 unsigned CheckStride,
2582 typename SmallVectorImpl<ValType>::const_iterator End,
2583 ValType ExpectedIndex, unsigned ExpectedIndexStride) {
2584 auto &I = Begin;
2585
2586 while (I != End) {
2587 if (*I != -1 && *I != ExpectedIndex)
2588 return false;
2589 ExpectedIndex += ExpectedIndexStride;
2590
2591 // Incrementing past End is undefined behaviour so we must increment one
2592 // step at a time and check for End at each step.
2593 for (unsigned n = 0; n < CheckStride && I != End; ++n, ++I)
2594 ; // Empty loop body.
2595 }
2596 return true;
2597}
2598
2599// Determine whether VECTOR_SHUFFLE is a SPLATI.
2600//
2601// It is a SPLATI when the mask is:
2602// <x, x, x, ...>
2603// where x is any valid index.
2604//
2605// When undef's appear in the mask they are treated as if they were whatever
2606// value is necessary in order to fit the above form.
2607static bool isVECTOR_SHUFFLE_SPLATI(SDValue Op, EVT ResTy,
2608 SmallVector<int, 16> Indices,
2609 SelectionDAG &DAG) {
2610 assert((Indices.size() % 2) == 0);
2611
2612 int SplatIndex = -1;
2613 for (const auto &V : Indices) {
2614 if (V != -1) {
2615 SplatIndex = V;
2616 break;
2617 }
2618 }
2619
2620 return fitsRegularPattern<int>(Indices.begin(), 1, Indices.end(), SplatIndex,
2621 0);
2622}
2623
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002624// Lower VECTOR_SHUFFLE into ILVEV (if possible).
2625//
2626// ILVEV interleaves the even elements from each vector.
2627//
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002628// It is possible to lower into ILVEV when the mask consists of two of the
2629// following forms interleaved:
2630// <0, 2, 4, ...>
2631// <n, n+2, n+4, ...>
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002632// where n is the number of elements in the vector.
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002633// For example:
2634// <0, 0, 2, 2, 4, 4, ...>
2635// <0, n, 2, n+2, 4, n+4, ...>
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002636//
2637// When undef's appear in the mask they are treated as if they were whatever
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002638// value is necessary in order to fit the above forms.
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002639static SDValue lowerVECTOR_SHUFFLE_ILVEV(SDValue Op, EVT ResTy,
2640 SmallVector<int, 16> Indices,
2641 SelectionDAG &DAG) {
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002642 assert((Indices.size() % 2) == 0);
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002643
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002644 SDValue Wt;
2645 SDValue Ws;
2646 const auto &Begin = Indices.begin();
2647 const auto &End = Indices.end();
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002648
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002649 // Check even elements are taken from the even elements of one half or the
2650 // other and pick an operand accordingly.
2651 if (fitsRegularPattern<int>(Begin, 2, End, 0, 2))
2652 Wt = Op->getOperand(0);
2653 else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size(), 2))
2654 Wt = Op->getOperand(1);
2655 else
2656 return SDValue();
2657
2658 // Check odd elements are taken from the even elements of one half or the
2659 // other and pick an operand accordingly.
2660 if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 2))
2661 Ws = Op->getOperand(0);
2662 else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size(), 2))
2663 Ws = Op->getOperand(1);
2664 else
2665 return SDValue();
2666
2667 return DAG.getNode(MipsISD::ILVEV, SDLoc(Op), ResTy, Ws, Wt);
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002668}
2669
2670// Lower VECTOR_SHUFFLE into ILVOD (if possible).
2671//
2672// ILVOD interleaves the odd elements from each vector.
2673//
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002674// It is possible to lower into ILVOD when the mask consists of two of the
2675// following forms interleaved:
2676// <1, 3, 5, ...>
2677// <n+1, n+3, n+5, ...>
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002678// where n is the number of elements in the vector.
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002679// For example:
2680// <1, 1, 3, 3, 5, 5, ...>
2681// <1, n+1, 3, n+3, 5, n+5, ...>
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002682//
2683// When undef's appear in the mask they are treated as if they were whatever
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002684// value is necessary in order to fit the above forms.
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002685static SDValue lowerVECTOR_SHUFFLE_ILVOD(SDValue Op, EVT ResTy,
2686 SmallVector<int, 16> Indices,
2687 SelectionDAG &DAG) {
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002688 assert((Indices.size() % 2) == 0);
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002689
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002690 SDValue Wt;
2691 SDValue Ws;
2692 const auto &Begin = Indices.begin();
2693 const auto &End = Indices.end();
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002694
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002695 // Check even elements are taken from the odd elements of one half or the
2696 // other and pick an operand accordingly.
2697 if (fitsRegularPattern<int>(Begin, 2, End, 1, 2))
2698 Wt = Op->getOperand(0);
2699 else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size() + 1, 2))
2700 Wt = Op->getOperand(1);
2701 else
2702 return SDValue();
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002703
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002704 // Check odd elements are taken from the odd elements of one half or the
2705 // other and pick an operand accordingly.
2706 if (fitsRegularPattern<int>(Begin + 1, 2, End, 1, 2))
2707 Ws = Op->getOperand(0);
2708 else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size() + 1, 2))
2709 Ws = Op->getOperand(1);
2710 else
2711 return SDValue();
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002712
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002713 return DAG.getNode(MipsISD::ILVOD, SDLoc(Op), ResTy, Wt, Ws);
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002714}
2715
2716// Lower VECTOR_SHUFFLE into ILVR (if possible).
2717//
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002718// ILVR interleaves consecutive elements from the right (lowest-indexed) half of
2719// each vector.
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002720//
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002721// It is possible to lower into ILVR when the mask consists of two of the
2722// following forms interleaved:
2723// <0, 1, 2, ...>
2724// <n, n+1, n+2, ...>
2725// where n is the number of elements in the vector.
2726// For example:
2727// <0, 0, 1, 1, 2, 2, ...>
2728// <0, n, 1, n+1, 2, n+2, ...>
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002729//
2730// When undef's appear in the mask they are treated as if they were whatever
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002731// value is necessary in order to fit the above forms.
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002732static SDValue lowerVECTOR_SHUFFLE_ILVR(SDValue Op, EVT ResTy,
2733 SmallVector<int, 16> Indices,
2734 SelectionDAG &DAG) {
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002735 assert((Indices.size() % 2) == 0);
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002736
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002737 SDValue Wt;
2738 SDValue Ws;
2739 const auto &Begin = Indices.begin();
2740 const auto &End = Indices.end();
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002741
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002742 // Check even elements are taken from the right (lowest-indexed) elements of
2743 // one half or the other and pick an operand accordingly.
2744 if (fitsRegularPattern<int>(Begin, 2, End, 0, 1))
2745 Wt = Op->getOperand(0);
2746 else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size(), 1))
2747 Wt = Op->getOperand(1);
2748 else
2749 return SDValue();
2750
2751 // Check odd elements are taken from the right (lowest-indexed) elements of
2752 // one half or the other and pick an operand accordingly.
2753 if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 1))
2754 Ws = Op->getOperand(0);
2755 else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size(), 1))
2756 Ws = Op->getOperand(1);
2757 else
2758 return SDValue();
2759
2760 return DAG.getNode(MipsISD::ILVR, SDLoc(Op), ResTy, Ws, Wt);
2761}
2762
2763// Lower VECTOR_SHUFFLE into ILVL (if possible).
2764//
2765// ILVL interleaves consecutive elements from the left (highest-indexed) half
2766// of each vector.
2767//
2768// It is possible to lower into ILVL when the mask consists of two of the
2769// following forms interleaved:
2770// <x, x+1, x+2, ...>
2771// <n+x, n+x+1, n+x+2, ...>
2772// where n is the number of elements in the vector and x is half n.
2773// For example:
2774// <x, x, x+1, x+1, x+2, x+2, ...>
2775// <x, n+x, x+1, n+x+1, x+2, n+x+2, ...>
2776//
2777// When undef's appear in the mask they are treated as if they were whatever
2778// value is necessary in order to fit the above forms.
2779static SDValue lowerVECTOR_SHUFFLE_ILVL(SDValue Op, EVT ResTy,
2780 SmallVector<int, 16> Indices,
2781 SelectionDAG &DAG) {
2782 assert((Indices.size() % 2) == 0);
2783
2784 unsigned HalfSize = Indices.size() / 2;
2785 SDValue Wt;
2786 SDValue Ws;
2787 const auto &Begin = Indices.begin();
2788 const auto &End = Indices.end();
2789
2790 // Check even elements are taken from the left (highest-indexed) elements of
2791 // one half or the other and pick an operand accordingly.
2792 if (fitsRegularPattern<int>(Begin, 2, End, HalfSize, 1))
2793 Wt = Op->getOperand(0);
2794 else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size() + HalfSize, 1))
2795 Wt = Op->getOperand(1);
2796 else
2797 return SDValue();
2798
2799 // Check odd elements are taken from the left (highest-indexed) elements of
2800 // one half or the other and pick an operand accordingly.
2801 if (fitsRegularPattern<int>(Begin + 1, 2, End, HalfSize, 1))
2802 Ws = Op->getOperand(0);
2803 else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size() + HalfSize,
2804 1))
2805 Ws = Op->getOperand(1);
2806 else
2807 return SDValue();
2808
2809 return DAG.getNode(MipsISD::ILVL, SDLoc(Op), ResTy, Ws, Wt);
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002810}
2811
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002812// Lower VECTOR_SHUFFLE into PCKEV (if possible).
2813//
2814// PCKEV copies the even elements of each vector into the result vector.
2815//
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002816// It is possible to lower into PCKEV when the mask consists of two of the
2817// following forms concatenated:
2818// <0, 2, 4, ...>
2819// <n, n+2, n+4, ...>
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002820// where n is the number of elements in the vector.
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002821// For example:
2822// <0, 2, 4, ..., 0, 2, 4, ...>
2823// <0, 2, 4, ..., n, n+2, n+4, ...>
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002824//
2825// When undef's appear in the mask they are treated as if they were whatever
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002826// value is necessary in order to fit the above forms.
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002827static SDValue lowerVECTOR_SHUFFLE_PCKEV(SDValue Op, EVT ResTy,
2828 SmallVector<int, 16> Indices,
2829 SelectionDAG &DAG) {
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002830 assert((Indices.size() % 2) == 0);
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002831
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002832 SDValue Wt;
2833 SDValue Ws;
2834 const auto &Begin = Indices.begin();
2835 const auto &Mid = Indices.begin() + Indices.size() / 2;
2836 const auto &End = Indices.end();
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002837
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002838 if (fitsRegularPattern<int>(Begin, 1, Mid, 0, 2))
2839 Wt = Op->getOperand(0);
2840 else if (fitsRegularPattern<int>(Begin, 1, Mid, Indices.size(), 2))
2841 Wt = Op->getOperand(1);
2842 else
2843 return SDValue();
2844
2845 if (fitsRegularPattern<int>(Mid, 1, End, 0, 2))
2846 Ws = Op->getOperand(0);
2847 else if (fitsRegularPattern<int>(Mid, 1, End, Indices.size(), 2))
2848 Ws = Op->getOperand(1);
2849 else
2850 return SDValue();
2851
2852 return DAG.getNode(MipsISD::PCKEV, SDLoc(Op), ResTy, Ws, Wt);
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002853}
2854
2855// Lower VECTOR_SHUFFLE into PCKOD (if possible).
2856//
2857// PCKOD copies the odd elements of each vector into the result vector.
2858//
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002859// It is possible to lower into PCKOD when the mask consists of two of the
2860// following forms concatenated:
2861// <1, 3, 5, ...>
2862// <n+1, n+3, n+5, ...>
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002863// where n is the number of elements in the vector.
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002864// For example:
2865// <1, 3, 5, ..., 1, 3, 5, ...>
2866// <1, 3, 5, ..., n+1, n+3, n+5, ...>
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002867//
2868// When undef's appear in the mask they are treated as if they were whatever
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002869// value is necessary in order to fit the above forms.
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002870static SDValue lowerVECTOR_SHUFFLE_PCKOD(SDValue Op, EVT ResTy,
2871 SmallVector<int, 16> Indices,
2872 SelectionDAG &DAG) {
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002873 assert((Indices.size() % 2) == 0);
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002874
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002875 SDValue Wt;
2876 SDValue Ws;
2877 const auto &Begin = Indices.begin();
2878 const auto &Mid = Indices.begin() + Indices.size() / 2;
2879 const auto &End = Indices.end();
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002880
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002881 if (fitsRegularPattern<int>(Begin, 1, Mid, 1, 2))
2882 Wt = Op->getOperand(0);
2883 else if (fitsRegularPattern<int>(Begin, 1, Mid, Indices.size() + 1, 2))
2884 Wt = Op->getOperand(1);
2885 else
2886 return SDValue();
2887
2888 if (fitsRegularPattern<int>(Mid, 1, End, 1, 2))
2889 Ws = Op->getOperand(0);
2890 else if (fitsRegularPattern<int>(Mid, 1, End, Indices.size() + 1, 2))
2891 Ws = Op->getOperand(1);
2892 else
2893 return SDValue();
2894
2895 return DAG.getNode(MipsISD::PCKOD, SDLoc(Op), ResTy, Ws, Wt);
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002896}
2897
Daniel Sanderse5087042013-09-24 14:02:15 +00002898// Lower VECTOR_SHUFFLE into VSHF.
2899//
2900// This mostly consists of converting the shuffle indices in Indices into a
2901// BUILD_VECTOR and adding it as an operand to the resulting VSHF. There is
2902// also code to eliminate unused operands of the VECTOR_SHUFFLE. For example,
2903// if the type is v8i16 and all the indices are less than 8 then the second
2904// operand is unused and can be replaced with anything. We choose to replace it
2905// with the used operand since this reduces the number of instructions overall.
2906static SDValue lowerVECTOR_SHUFFLE_VSHF(SDValue Op, EVT ResTy,
2907 SmallVector<int, 16> Indices,
2908 SelectionDAG &DAG) {
2909 SmallVector<SDValue, 16> Ops;
2910 SDValue Op0;
2911 SDValue Op1;
2912 EVT MaskVecTy = ResTy.changeVectorElementTypeToInteger();
2913 EVT MaskEltTy = MaskVecTy.getVectorElementType();
2914 bool Using1stVec = false;
2915 bool Using2ndVec = false;
2916 SDLoc DL(Op);
2917 int ResTyNumElts = ResTy.getVectorNumElements();
2918
2919 for (int i = 0; i < ResTyNumElts; ++i) {
2920 // Idx == -1 means UNDEF
2921 int Idx = Indices[i];
2922
2923 if (0 <= Idx && Idx < ResTyNumElts)
2924 Using1stVec = true;
2925 if (ResTyNumElts <= Idx && Idx < ResTyNumElts * 2)
2926 Using2ndVec = true;
2927 }
2928
2929 for (SmallVector<int, 16>::iterator I = Indices.begin(); I != Indices.end();
2930 ++I)
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002931 Ops.push_back(DAG.getTargetConstant(*I, DL, MaskEltTy));
Daniel Sanderse5087042013-09-24 14:02:15 +00002932
Ahmed Bougacha128f8732016-04-26 21:15:30 +00002933 SDValue MaskVec = DAG.getBuildVector(MaskVecTy, DL, Ops);
Daniel Sanderse5087042013-09-24 14:02:15 +00002934
2935 if (Using1stVec && Using2ndVec) {
2936 Op0 = Op->getOperand(0);
2937 Op1 = Op->getOperand(1);
2938 } else if (Using1stVec)
2939 Op0 = Op1 = Op->getOperand(0);
2940 else if (Using2ndVec)
2941 Op0 = Op1 = Op->getOperand(1);
2942 else
2943 llvm_unreachable("shuffle vector mask references neither vector operand?");
2944
Daniel Sandersf88a29e2014-03-21 16:56:51 +00002945 // VECTOR_SHUFFLE concatenates the vectors in an vectorwise fashion.
2946 // <0b00, 0b01> + <0b10, 0b11> -> <0b00, 0b01, 0b10, 0b11>
2947 // VSHF concatenates the vectors in a bitwise fashion:
2948 // <0b00, 0b01> + <0b10, 0b11> ->
2949 // 0b0100 + 0b1110 -> 0b01001110
2950 // <0b10, 0b11, 0b00, 0b01>
2951 // We must therefore swap the operands to get the correct result.
2952 return DAG.getNode(MipsISD::VSHF, DL, ResTy, MaskVec, Op1, Op0);
Daniel Sanderse5087042013-09-24 14:02:15 +00002953}
2954
2955// Lower VECTOR_SHUFFLE into one of a number of instructions depending on the
2956// indices in the shuffle.
2957SDValue MipsSETargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
2958 SelectionDAG &DAG) const {
2959 ShuffleVectorSDNode *Node = cast<ShuffleVectorSDNode>(Op);
2960 EVT ResTy = Op->getValueType(0);
2961
2962 if (!ResTy.is128BitVector())
2963 return SDValue();
2964
2965 int ResTyNumElts = ResTy.getVectorNumElements();
2966 SmallVector<int, 16> Indices;
2967
2968 for (int i = 0; i < ResTyNumElts; ++i)
2969 Indices.push_back(Node->getMaskElt(i));
2970
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002971 // splati.[bhwd] is preferable to the others but is matched from
2972 // MipsISD::VSHF.
2973 if (isVECTOR_SHUFFLE_SPLATI(Op, ResTy, Indices, DAG))
2974 return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG);
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002975 SDValue Result;
2976 if ((Result = lowerVECTOR_SHUFFLE_ILVEV(Op, ResTy, Indices, DAG)))
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002977 return Result;
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002978 if ((Result = lowerVECTOR_SHUFFLE_ILVOD(Op, ResTy, Indices, DAG)))
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002979 return Result;
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002980 if ((Result = lowerVECTOR_SHUFFLE_ILVL(Op, ResTy, Indices, DAG)))
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002981 return Result;
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002982 if ((Result = lowerVECTOR_SHUFFLE_ILVR(Op, ResTy, Indices, DAG)))
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002983 return Result;
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002984 if ((Result = lowerVECTOR_SHUFFLE_PCKEV(Op, ResTy, Indices, DAG)))
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002985 return Result;
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002986 if ((Result = lowerVECTOR_SHUFFLE_PCKOD(Op, ResTy, Indices, DAG)))
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002987 return Result;
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002988 if ((Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG)))
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002989 return Result;
Daniel Sanderse5087042013-09-24 14:02:15 +00002990 return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG);
2991}
2992
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00002993MachineBasicBlock *
2994MipsSETargetLowering::emitBPOSGE32(MachineInstr &MI,
2995 MachineBasicBlock *BB) const {
Akira Hatanaka96ca1822013-03-13 00:54:29 +00002996 // $bb:
2997 // bposge32_pseudo $vr0
2998 // =>
2999 // $bb:
3000 // bposge32 $tbb
3001 // $fbb:
3002 // li $vr2, 0
3003 // b $sink
3004 // $tbb:
3005 // li $vr1, 1
3006 // $sink:
3007 // $vr0 = phi($vr2, $fbb, $vr1, $tbb)
3008
3009 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Eric Christopher96e72c62015-01-29 23:27:36 +00003010 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00003011 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003012 DebugLoc DL = MI.getDebugLoc();
Akira Hatanaka96ca1822013-03-13 00:54:29 +00003013 const BasicBlock *LLVM_BB = BB->getBasicBlock();
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00003014 MachineFunction::iterator It = std::next(MachineFunction::iterator(BB));
Akira Hatanaka96ca1822013-03-13 00:54:29 +00003015 MachineFunction *F = BB->getParent();
3016 MachineBasicBlock *FBB = F->CreateMachineBasicBlock(LLVM_BB);
3017 MachineBasicBlock *TBB = F->CreateMachineBasicBlock(LLVM_BB);
3018 MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB);
3019 F->insert(It, FBB);
3020 F->insert(It, TBB);
3021 F->insert(It, Sink);
3022
3023 // Transfer the remainder of BB and its successor edges to Sink.
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00003024 Sink->splice(Sink->begin(), BB, std::next(MachineBasicBlock::iterator(MI)),
Akira Hatanaka96ca1822013-03-13 00:54:29 +00003025 BB->end());
3026 Sink->transferSuccessorsAndUpdatePHIs(BB);
3027
3028 // Add successors.
3029 BB->addSuccessor(FBB);
3030 BB->addSuccessor(TBB);
3031 FBB->addSuccessor(Sink);
3032 TBB->addSuccessor(Sink);
3033
3034 // Insert the real bposge32 instruction to $BB.
3035 BuildMI(BB, DL, TII->get(Mips::BPOSGE32)).addMBB(TBB);
Hrvoje Varga6f09cdf2016-05-13 11:32:53 +00003036 // Insert the real bposge32c instruction to $BB.
3037 BuildMI(BB, DL, TII->get(Mips::BPOSGE32C_MMR3)).addMBB(TBB);
Akira Hatanaka96ca1822013-03-13 00:54:29 +00003038
3039 // Fill $FBB.
3040 unsigned VR2 = RegInfo.createVirtualRegister(RC);
3041 BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::ADDiu), VR2)
3042 .addReg(Mips::ZERO).addImm(0);
3043 BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::B)).addMBB(Sink);
3044
3045 // Fill $TBB.
3046 unsigned VR1 = RegInfo.createVirtualRegister(RC);
3047 BuildMI(*TBB, TBB->end(), DL, TII->get(Mips::ADDiu), VR1)
3048 .addReg(Mips::ZERO).addImm(1);
3049
3050 // Insert phi function to $Sink.
3051 BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI),
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003052 MI.getOperand(0).getReg())
3053 .addReg(VR2)
3054 .addMBB(FBB)
3055 .addReg(VR1)
3056 .addMBB(TBB);
Akira Hatanaka96ca1822013-03-13 00:54:29 +00003057
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003058 MI.eraseFromParent(); // The pseudo instruction is gone now.
Akira Hatanaka96ca1822013-03-13 00:54:29 +00003059 return Sink;
3060}
Daniel Sandersce09d072013-08-28 12:14:50 +00003061
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003062MachineBasicBlock *MipsSETargetLowering::emitMSACBranchPseudo(
3063 MachineInstr &MI, MachineBasicBlock *BB, unsigned BranchOp) const {
Daniel Sandersce09d072013-08-28 12:14:50 +00003064 // $bb:
3065 // vany_nonzero $rd, $ws
3066 // =>
3067 // $bb:
3068 // bnz.b $ws, $tbb
3069 // b $fbb
3070 // $fbb:
3071 // li $rd1, 0
3072 // b $sink
3073 // $tbb:
3074 // li $rd2, 1
3075 // $sink:
3076 // $rd = phi($rd1, $fbb, $rd2, $tbb)
3077
3078 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Eric Christopher96e72c62015-01-29 23:27:36 +00003079 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sandersce09d072013-08-28 12:14:50 +00003080 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003081 DebugLoc DL = MI.getDebugLoc();
Daniel Sandersce09d072013-08-28 12:14:50 +00003082 const BasicBlock *LLVM_BB = BB->getBasicBlock();
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00003083 MachineFunction::iterator It = std::next(MachineFunction::iterator(BB));
Daniel Sandersce09d072013-08-28 12:14:50 +00003084 MachineFunction *F = BB->getParent();
3085 MachineBasicBlock *FBB = F->CreateMachineBasicBlock(LLVM_BB);
3086 MachineBasicBlock *TBB = F->CreateMachineBasicBlock(LLVM_BB);
3087 MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB);
3088 F->insert(It, FBB);
3089 F->insert(It, TBB);
3090 F->insert(It, Sink);
3091
3092 // Transfer the remainder of BB and its successor edges to Sink.
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00003093 Sink->splice(Sink->begin(), BB, std::next(MachineBasicBlock::iterator(MI)),
Daniel Sandersce09d072013-08-28 12:14:50 +00003094 BB->end());
3095 Sink->transferSuccessorsAndUpdatePHIs(BB);
3096
3097 // Add successors.
3098 BB->addSuccessor(FBB);
3099 BB->addSuccessor(TBB);
3100 FBB->addSuccessor(Sink);
3101 TBB->addSuccessor(Sink);
3102
3103 // Insert the real bnz.b instruction to $BB.
3104 BuildMI(BB, DL, TII->get(BranchOp))
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003105 .addReg(MI.getOperand(1).getReg())
3106 .addMBB(TBB);
Daniel Sandersce09d072013-08-28 12:14:50 +00003107
3108 // Fill $FBB.
3109 unsigned RD1 = RegInfo.createVirtualRegister(RC);
3110 BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::ADDiu), RD1)
3111 .addReg(Mips::ZERO).addImm(0);
3112 BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::B)).addMBB(Sink);
3113
3114 // Fill $TBB.
3115 unsigned RD2 = RegInfo.createVirtualRegister(RC);
3116 BuildMI(*TBB, TBB->end(), DL, TII->get(Mips::ADDiu), RD2)
3117 .addReg(Mips::ZERO).addImm(1);
3118
3119 // Insert phi function to $Sink.
3120 BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI),
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003121 MI.getOperand(0).getReg())
3122 .addReg(RD1)
3123 .addMBB(FBB)
3124 .addReg(RD2)
3125 .addMBB(TBB);
Daniel Sandersce09d072013-08-28 12:14:50 +00003126
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003127 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sandersce09d072013-08-28 12:14:50 +00003128 return Sink;
3129}
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003130
3131// Emit the COPY_FW pseudo instruction.
3132//
3133// copy_fw_pseudo $fd, $ws, n
3134// =>
3135// copy_u_w $rt, $ws, $n
3136// mtc1 $rt, $fd
3137//
3138// When n is zero, the equivalent operation can be performed with (potentially)
3139// zero instructions due to register overlaps. This optimization is never valid
3140// for lane 1 because it would require FR=0 mode which isn't supported by MSA.
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003141MachineBasicBlock *
3142MipsSETargetLowering::emitCOPY_FW(MachineInstr &MI,
3143 MachineBasicBlock *BB) const {
Eric Christopher96e72c62015-01-29 23:27:36 +00003144 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003145 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003146 DebugLoc DL = MI.getDebugLoc();
3147 unsigned Fd = MI.getOperand(0).getReg();
3148 unsigned Ws = MI.getOperand(1).getReg();
3149 unsigned Lane = MI.getOperand(2).getImm();
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003150
Daniel Sandersafe27c72015-02-23 17:22:16 +00003151 if (Lane == 0) {
3152 unsigned Wt = Ws;
3153 if (!Subtarget.useOddSPReg()) {
3154 // We must copy to an even-numbered MSA register so that the
3155 // single-precision sub-register is also guaranteed to be even-numbered.
3156 Wt = RegInfo.createVirtualRegister(&Mips::MSA128WEvensRegClass);
3157
3158 BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Wt).addReg(Ws);
3159 }
3160
3161 BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_lo);
3162 } else {
3163 unsigned Wt = RegInfo.createVirtualRegister(
3164 Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass :
3165 &Mips::MSA128WEvensRegClass);
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003166
Daniel Sandersd9207702014-03-04 13:54:30 +00003167 BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_W), Wt).addReg(Ws).addImm(Lane);
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003168 BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_lo);
3169 }
3170
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003171 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003172 return BB;
3173}
3174
3175// Emit the COPY_FD pseudo instruction.
3176//
3177// copy_fd_pseudo $fd, $ws, n
3178// =>
3179// splati.d $wt, $ws, $n
3180// copy $fd, $wt:sub_64
3181//
3182// When n is zero, the equivalent operation can be performed with (potentially)
3183// zero instructions due to register overlaps. This optimization is always
3184// valid because FR=1 mode which is the only supported mode in MSA.
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003185MachineBasicBlock *
3186MipsSETargetLowering::emitCOPY_FD(MachineInstr &MI,
3187 MachineBasicBlock *BB) const {
Eric Christopher1c29a652014-07-18 22:55:25 +00003188 assert(Subtarget.isFP64bit());
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003189
Eric Christopher96e72c62015-01-29 23:27:36 +00003190 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003191 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003192 unsigned Fd = MI.getOperand(0).getReg();
3193 unsigned Ws = MI.getOperand(1).getReg();
3194 unsigned Lane = MI.getOperand(2).getImm() * 2;
3195 DebugLoc DL = MI.getDebugLoc();
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003196
3197 if (Lane == 0)
3198 BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Ws, 0, Mips::sub_64);
3199 else {
3200 unsigned Wt = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
3201
3202 BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_D), Wt).addReg(Ws).addImm(1);
3203 BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_64);
3204 }
3205
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003206 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003207 return BB;
3208}
Daniel Sandersa5150702013-09-27 12:31:32 +00003209
3210// Emit the INSERT_FW pseudo instruction.
3211//
3212// insert_fw_pseudo $wd, $wd_in, $n, $fs
3213// =>
3214// subreg_to_reg $wt:sub_lo, $fs
3215// insve_w $wd[$n], $wd_in, $wt[0]
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003216MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003217MipsSETargetLowering::emitINSERT_FW(MachineInstr &MI,
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003218 MachineBasicBlock *BB) const {
Eric Christopher96e72c62015-01-29 23:27:36 +00003219 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sandersa5150702013-09-27 12:31:32 +00003220 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003221 DebugLoc DL = MI.getDebugLoc();
3222 unsigned Wd = MI.getOperand(0).getReg();
3223 unsigned Wd_in = MI.getOperand(1).getReg();
3224 unsigned Lane = MI.getOperand(2).getImm();
3225 unsigned Fs = MI.getOperand(3).getReg();
Daniel Sandersafe27c72015-02-23 17:22:16 +00003226 unsigned Wt = RegInfo.createVirtualRegister(
3227 Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass :
3228 &Mips::MSA128WEvensRegClass);
Daniel Sandersa5150702013-09-27 12:31:32 +00003229
3230 BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt)
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003231 .addImm(0)
3232 .addReg(Fs)
3233 .addImm(Mips::sub_lo);
Daniel Sandersa5150702013-09-27 12:31:32 +00003234 BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_W), Wd)
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003235 .addReg(Wd_in)
3236 .addImm(Lane)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003237 .addReg(Wt)
3238 .addImm(0);
Daniel Sandersa5150702013-09-27 12:31:32 +00003239
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003240 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sandersa5150702013-09-27 12:31:32 +00003241 return BB;
3242}
3243
3244// Emit the INSERT_FD pseudo instruction.
3245//
3246// insert_fd_pseudo $wd, $fs, n
3247// =>
3248// subreg_to_reg $wt:sub_64, $fs
3249// insve_d $wd[$n], $wd_in, $wt[0]
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003250MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003251MipsSETargetLowering::emitINSERT_FD(MachineInstr &MI,
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003252 MachineBasicBlock *BB) const {
Eric Christopher1c29a652014-07-18 22:55:25 +00003253 assert(Subtarget.isFP64bit());
Daniel Sandersa5150702013-09-27 12:31:32 +00003254
Eric Christopher96e72c62015-01-29 23:27:36 +00003255 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sandersa5150702013-09-27 12:31:32 +00003256 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003257 DebugLoc DL = MI.getDebugLoc();
3258 unsigned Wd = MI.getOperand(0).getReg();
3259 unsigned Wd_in = MI.getOperand(1).getReg();
3260 unsigned Lane = MI.getOperand(2).getImm();
3261 unsigned Fs = MI.getOperand(3).getReg();
Daniel Sandersa5150702013-09-27 12:31:32 +00003262 unsigned Wt = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
3263
3264 BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt)
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003265 .addImm(0)
3266 .addReg(Fs)
3267 .addImm(Mips::sub_64);
Daniel Sandersa5150702013-09-27 12:31:32 +00003268 BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_D), Wd)
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003269 .addReg(Wd_in)
3270 .addImm(Lane)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003271 .addReg(Wt)
3272 .addImm(0);
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003273
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003274 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003275 return BB;
3276}
3277
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003278// Emit the INSERT_([BHWD]|F[WD])_VIDX pseudo instruction.
3279//
3280// For integer:
3281// (INSERT_([BHWD]|F[WD])_PSEUDO $wd, $wd_in, $n, $rs)
3282// =>
3283// (SLL $lanetmp1, $lane, <log2size)
3284// (SLD_B $wdtmp1, $wd_in, $wd_in, $lanetmp1)
3285// (INSERT_[BHWD], $wdtmp2, $wdtmp1, 0, $rs)
3286// (NEG $lanetmp2, $lanetmp1)
3287// (SLD_B $wd, $wdtmp2, $wdtmp2, $lanetmp2)
3288//
3289// For floating point:
3290// (INSERT_([BHWD]|F[WD])_PSEUDO $wd, $wd_in, $n, $fs)
3291// =>
3292// (SUBREG_TO_REG $wt, $fs, <subreg>)
3293// (SLL $lanetmp1, $lane, <log2size)
3294// (SLD_B $wdtmp1, $wd_in, $wd_in, $lanetmp1)
3295// (INSVE_[WD], $wdtmp2, 0, $wdtmp1, 0)
3296// (NEG $lanetmp2, $lanetmp1)
3297// (SLD_B $wd, $wdtmp2, $wdtmp2, $lanetmp2)
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003298MachineBasicBlock *MipsSETargetLowering::emitINSERT_DF_VIDX(
3299 MachineInstr &MI, MachineBasicBlock *BB, unsigned EltSizeInBytes,
3300 bool IsFP) const {
Eric Christopher96e72c62015-01-29 23:27:36 +00003301 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003302 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003303 DebugLoc DL = MI.getDebugLoc();
3304 unsigned Wd = MI.getOperand(0).getReg();
3305 unsigned SrcVecReg = MI.getOperand(1).getReg();
3306 unsigned LaneReg = MI.getOperand(2).getReg();
3307 unsigned SrcValReg = MI.getOperand(3).getReg();
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003308
3309 const TargetRegisterClass *VecRC = nullptr;
Daniel Sandersd3bb2082016-06-15 08:43:23 +00003310 // FIXME: This should be true for N32 too.
Eric Christopherbf33a3c2014-07-02 23:18:40 +00003311 const TargetRegisterClass *GPRRC =
Daniel Sanders4160c802015-05-05 08:48:35 +00003312 Subtarget.isABI_N64() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
Daniel Sandersd3bb2082016-06-15 08:43:23 +00003313 unsigned SubRegIdx = Subtarget.isABI_N64() ? Mips::sub_32 : 0;
3314 unsigned ShiftOp = Subtarget.isABI_N64() ? Mips::DSLL : Mips::SLL;
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003315 unsigned EltLog2Size;
3316 unsigned InsertOp = 0;
3317 unsigned InsveOp = 0;
3318 switch (EltSizeInBytes) {
3319 default:
3320 llvm_unreachable("Unexpected size");
3321 case 1:
3322 EltLog2Size = 0;
3323 InsertOp = Mips::INSERT_B;
3324 InsveOp = Mips::INSVE_B;
3325 VecRC = &Mips::MSA128BRegClass;
3326 break;
3327 case 2:
3328 EltLog2Size = 1;
3329 InsertOp = Mips::INSERT_H;
3330 InsveOp = Mips::INSVE_H;
3331 VecRC = &Mips::MSA128HRegClass;
3332 break;
3333 case 4:
3334 EltLog2Size = 2;
3335 InsertOp = Mips::INSERT_W;
3336 InsveOp = Mips::INSVE_W;
3337 VecRC = &Mips::MSA128WRegClass;
3338 break;
3339 case 8:
3340 EltLog2Size = 3;
3341 InsertOp = Mips::INSERT_D;
3342 InsveOp = Mips::INSVE_D;
3343 VecRC = &Mips::MSA128DRegClass;
3344 break;
3345 }
3346
3347 if (IsFP) {
3348 unsigned Wt = RegInfo.createVirtualRegister(VecRC);
3349 BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt)
3350 .addImm(0)
3351 .addReg(SrcValReg)
3352 .addImm(EltSizeInBytes == 8 ? Mips::sub_64 : Mips::sub_lo);
3353 SrcValReg = Wt;
3354 }
3355
3356 // Convert the lane index into a byte index
3357 if (EltSizeInBytes != 1) {
3358 unsigned LaneTmp1 = RegInfo.createVirtualRegister(GPRRC);
Daniel Sandersd3bb2082016-06-15 08:43:23 +00003359 BuildMI(*BB, MI, DL, TII->get(ShiftOp), LaneTmp1)
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003360 .addReg(LaneReg)
3361 .addImm(EltLog2Size);
3362 LaneReg = LaneTmp1;
3363 }
3364
3365 // Rotate bytes around so that the desired lane is element zero
3366 unsigned WdTmp1 = RegInfo.createVirtualRegister(VecRC);
3367 BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), WdTmp1)
3368 .addReg(SrcVecReg)
3369 .addReg(SrcVecReg)
Daniel Sandersd3bb2082016-06-15 08:43:23 +00003370 .addReg(LaneReg, 0, SubRegIdx);
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003371
3372 unsigned WdTmp2 = RegInfo.createVirtualRegister(VecRC);
3373 if (IsFP) {
3374 // Use insve.df to insert to element zero
3375 BuildMI(*BB, MI, DL, TII->get(InsveOp), WdTmp2)
3376 .addReg(WdTmp1)
3377 .addImm(0)
3378 .addReg(SrcValReg)
3379 .addImm(0);
3380 } else {
3381 // Use insert.df to insert to element zero
3382 BuildMI(*BB, MI, DL, TII->get(InsertOp), WdTmp2)
3383 .addReg(WdTmp1)
3384 .addReg(SrcValReg)
3385 .addImm(0);
3386 }
3387
3388 // Rotate elements the rest of the way for a full rotation.
3389 // sld.df inteprets $rt modulo the number of columns so we only need to negate
3390 // the lane index to do this.
3391 unsigned LaneTmp2 = RegInfo.createVirtualRegister(GPRRC);
Daniel Sanders4160c802015-05-05 08:48:35 +00003392 BuildMI(*BB, MI, DL, TII->get(Subtarget.isABI_N64() ? Mips::DSUB : Mips::SUB),
3393 LaneTmp2)
3394 .addReg(Subtarget.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO)
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003395 .addReg(LaneReg);
3396 BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), Wd)
3397 .addReg(WdTmp2)
3398 .addReg(WdTmp2)
Daniel Sandersd3bb2082016-06-15 08:43:23 +00003399 .addReg(LaneTmp2, 0, SubRegIdx);
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003400
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003401 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003402 return BB;
3403}
3404
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003405// Emit the FILL_FW pseudo instruction.
3406//
3407// fill_fw_pseudo $wd, $fs
3408// =>
3409// implicit_def $wt1
3410// insert_subreg $wt2:subreg_lo, $wt1, $fs
3411// splati.w $wd, $wt2[0]
3412MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003413MipsSETargetLowering::emitFILL_FW(MachineInstr &MI,
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003414 MachineBasicBlock *BB) const {
Eric Christopher96e72c62015-01-29 23:27:36 +00003415 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003416 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003417 DebugLoc DL = MI.getDebugLoc();
3418 unsigned Wd = MI.getOperand(0).getReg();
3419 unsigned Fs = MI.getOperand(1).getReg();
Simon Dardis0e9e2372017-01-10 15:53:10 +00003420 unsigned Wt1 = RegInfo.createVirtualRegister(
3421 Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass
3422 : &Mips::MSA128WEvensRegClass);
3423 unsigned Wt2 = RegInfo.createVirtualRegister(
3424 Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass
3425 : &Mips::MSA128WEvensRegClass);
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003426
3427 BuildMI(*BB, MI, DL, TII->get(Mips::IMPLICIT_DEF), Wt1);
3428 BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_SUBREG), Wt2)
3429 .addReg(Wt1)
3430 .addReg(Fs)
3431 .addImm(Mips::sub_lo);
3432 BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_W), Wd).addReg(Wt2).addImm(0);
3433
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003434 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003435 return BB;
3436}
3437
3438// Emit the FILL_FD pseudo instruction.
3439//
3440// fill_fd_pseudo $wd, $fs
3441// =>
3442// implicit_def $wt1
3443// insert_subreg $wt2:subreg_64, $wt1, $fs
3444// splati.d $wd, $wt2[0]
3445MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003446MipsSETargetLowering::emitFILL_FD(MachineInstr &MI,
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003447 MachineBasicBlock *BB) const {
Eric Christopher1c29a652014-07-18 22:55:25 +00003448 assert(Subtarget.isFP64bit());
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003449
Eric Christopher96e72c62015-01-29 23:27:36 +00003450 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003451 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003452 DebugLoc DL = MI.getDebugLoc();
3453 unsigned Wd = MI.getOperand(0).getReg();
3454 unsigned Fs = MI.getOperand(1).getReg();
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003455 unsigned Wt1 = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
3456 unsigned Wt2 = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
3457
3458 BuildMI(*BB, MI, DL, TII->get(Mips::IMPLICIT_DEF), Wt1);
3459 BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_SUBREG), Wt2)
3460 .addReg(Wt1)
3461 .addReg(Fs)
3462 .addImm(Mips::sub_64);
3463 BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_D), Wd).addReg(Wt2).addImm(0);
Daniel Sandersa5150702013-09-27 12:31:32 +00003464
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003465 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sandersa5150702013-09-27 12:31:32 +00003466 return BB;
3467}
Daniel Sandersa9521602013-10-23 10:36:52 +00003468
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003469// Emit the ST_F16_PSEDUO instruction to store a f16 value from an MSA
3470// register.
3471//
3472// STF16 MSA128F16:$wd, mem_simm10:$addr
3473// =>
3474// copy_u.h $rtemp,$wd[0]
3475// sh $rtemp, $addr
3476//
3477// Safety: We can't use st.h & co as they would over write the memory after
3478// the destination. It would require half floats be allocated 16 bytes(!) of
3479// space.
3480MachineBasicBlock *
3481MipsSETargetLowering::emitST_F16_PSEUDO(MachineInstr &MI,
3482 MachineBasicBlock *BB) const {
3483
3484 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3485 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3486 DebugLoc DL = MI.getDebugLoc();
3487 unsigned Ws = MI.getOperand(0).getReg();
3488 unsigned Rt = MI.getOperand(1).getReg();
3489 const MachineMemOperand &MMO = **MI.memoperands_begin();
3490 unsigned Imm = MMO.getOffset();
3491
3492 // Caution: A load via the GOT can expand to a GPR32 operand, a load via
3493 // spill and reload can expand as a GPR64 operand. Examine the
3494 // operand in detail and default to ABI.
3495 const TargetRegisterClass *RC =
3496 MI.getOperand(1).isReg() ? RegInfo.getRegClass(MI.getOperand(1).getReg())
3497 : (Subtarget.isABI_O32() ? &Mips::GPR32RegClass
3498 : &Mips::GPR64RegClass);
3499 const bool UsingMips32 = RC == &Mips::GPR32RegClass;
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003500 unsigned Rs = RegInfo.createVirtualRegister(&Mips::GPR32RegClass);
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003501
3502 BuildMI(*BB, MI, DL, TII->get(Mips::COPY_U_H), Rs).addReg(Ws).addImm(0);
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003503 if(!UsingMips32) {
3504 unsigned Tmp = RegInfo.createVirtualRegister(&Mips::GPR64RegClass);
3505 BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Tmp)
3506 .addImm(0)
3507 .addReg(Rs)
3508 .addImm(Mips::sub_32);
3509 Rs = Tmp;
3510 }
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003511 BuildMI(*BB, MI, DL, TII->get(UsingMips32 ? Mips::SH : Mips::SH64))
3512 .addReg(Rs)
3513 .addReg(Rt)
3514 .addImm(Imm)
3515 .addMemOperand(BB->getParent()->getMachineMemOperand(
3516 &MMO, MMO.getOffset(), MMO.getSize()));
3517
3518 MI.eraseFromParent();
3519 return BB;
3520}
3521
3522// Emit the LD_F16_PSEDUO instruction to load a f16 value into an MSA register.
3523//
3524// LD_F16 MSA128F16:$wd, mem_simm10:$addr
3525// =>
3526// lh $rtemp, $addr
3527// fill.h $wd, $rtemp
3528//
3529// Safety: We can't use ld.h & co as they over-read from the source.
3530// Additionally, if the address is not modulo 16, 2 cases can occur:
3531// a) Segmentation fault as the load instruction reads from a memory page
3532// memory it's not supposed to.
3533// b) The load crosses an implementation specific boundary, requiring OS
3534// intervention.
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003535MachineBasicBlock *
3536MipsSETargetLowering::emitLD_F16_PSEUDO(MachineInstr &MI,
3537 MachineBasicBlock *BB) const {
3538
3539 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3540 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3541 DebugLoc DL = MI.getDebugLoc();
3542 unsigned Wd = MI.getOperand(0).getReg();
3543
3544 // Caution: A load via the GOT can expand to a GPR32 operand, a load via
3545 // spill and reload can expand as a GPR64 operand. Examine the
3546 // operand in detail and default to ABI.
3547 const TargetRegisterClass *RC =
3548 MI.getOperand(1).isReg() ? RegInfo.getRegClass(MI.getOperand(1).getReg())
3549 : (Subtarget.isABI_O32() ? &Mips::GPR32RegClass
3550 : &Mips::GPR64RegClass);
3551
3552 const bool UsingMips32 = RC == &Mips::GPR32RegClass;
3553 unsigned Rt = RegInfo.createVirtualRegister(RC);
3554
3555 MachineInstrBuilder MIB =
3556 BuildMI(*BB, MI, DL, TII->get(UsingMips32 ? Mips::LH : Mips::LH64), Rt);
3557 for (unsigned i = 1; i < MI.getNumOperands(); i++)
Diana Picus116bbab2017-01-13 09:58:52 +00003558 MIB.add(MI.getOperand(i));
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003559
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003560 if(!UsingMips32) {
3561 unsigned Tmp = RegInfo.createVirtualRegister(&Mips::GPR32RegClass);
3562 BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Tmp).addReg(Rt, 0, Mips::sub_32);
3563 Rt = Tmp;
3564 }
3565
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003566 BuildMI(*BB, MI, DL, TII->get(Mips::FILL_H), Wd).addReg(Rt);
3567
3568 MI.eraseFromParent();
3569 return BB;
3570}
3571
3572// Emit the FPROUND_PSEUDO instruction.
3573//
3574// Round an FGR64Opnd, FGR32Opnd to an f16.
3575//
3576// Safety: Cycle the operand through the GPRs so the result always ends up
3577// the correct MSA register.
3578//
3579// FIXME: This copying is strictly unnecessary. If we could tie FGR32Opnd:$Fs
3580// / FGR64Opnd:$Fs and MSA128F16:$Wd to the same physical register
3581// (which they can be, as the MSA registers are defined to alias the
3582// FPU's 64 bit and 32 bit registers) the result can be accessed using
3583// the correct register class. That requires operands be tie-able across
3584// register classes which have a sub/super register class relationship.
3585//
3586// For FPG32Opnd:
3587//
3588// FPROUND MSA128F16:$wd, FGR32Opnd:$fs
3589// =>
3590// mfc1 $rtemp, $fs
3591// fill.w $rtemp, $wtemp
3592// fexdo.w $wd, $wtemp, $wtemp
3593//
3594// For FPG64Opnd on mips32r2+:
3595//
3596// FPROUND MSA128F16:$wd, FGR64Opnd:$fs
3597// =>
3598// mfc1 $rtemp, $fs
3599// fill.w $rtemp, $wtemp
3600// mfhc1 $rtemp2, $fs
3601// insert.w $wtemp[1], $rtemp2
3602// insert.w $wtemp[3], $rtemp2
3603// fexdo.w $wtemp2, $wtemp, $wtemp
3604// fexdo.h $wd, $temp2, $temp2
3605//
3606// For FGR64Opnd on mips64r2+:
3607//
3608// FPROUND MSA128F16:$wd, FGR64Opnd:$fs
3609// =>
3610// dmfc1 $rtemp, $fs
3611// fill.d $rtemp, $wtemp
3612// fexdo.w $wtemp2, $wtemp, $wtemp
3613// fexdo.h $wd, $wtemp2, $wtemp2
3614//
3615// Safety note: As $wtemp is UNDEF, we may provoke a spurious exception if the
3616// undef bits are "just right" and the exception enable bits are
3617// set. By using fill.w to replicate $fs into all elements over
3618// insert.w for one element, we avoid that potiential case. If
3619// fexdo.[hw] causes an exception in, the exception is valid and it
3620// occurs for all elements.
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003621MachineBasicBlock *
3622MipsSETargetLowering::emitFPROUND_PSEUDO(MachineInstr &MI,
3623 MachineBasicBlock *BB,
3624 bool IsFGR64) const {
3625
3626 // Strictly speaking, we need MIPS32R5 to support MSA. We'll be generous
3627 // here. It's technically doable to support MIPS32 here, but the ISA forbids
3628 // it.
3629 assert(Subtarget.hasMSA() && Subtarget.hasMips32r2());
3630
3631 bool IsFGR64onMips64 = Subtarget.hasMips64() && IsFGR64;
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003632 bool IsFGR64onMips32 = !Subtarget.hasMips64() && IsFGR64;
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003633
3634 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3635 DebugLoc DL = MI.getDebugLoc();
3636 unsigned Wd = MI.getOperand(0).getReg();
3637 unsigned Fs = MI.getOperand(1).getReg();
3638
3639 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3640 unsigned Wtemp = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
3641 const TargetRegisterClass *GPRRC =
3642 IsFGR64onMips64 ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003643 unsigned MFC1Opc = IsFGR64onMips64
3644 ? Mips::DMFC1
3645 : (IsFGR64onMips32 ? Mips::MFC1_D64 : Mips::MFC1);
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003646 unsigned FILLOpc = IsFGR64onMips64 ? Mips::FILL_D : Mips::FILL_W;
3647
3648 // Perform the register class copy as mentioned above.
3649 unsigned Rtemp = RegInfo.createVirtualRegister(GPRRC);
3650 BuildMI(*BB, MI, DL, TII->get(MFC1Opc), Rtemp).addReg(Fs);
3651 BuildMI(*BB, MI, DL, TII->get(FILLOpc), Wtemp).addReg(Rtemp);
3652 unsigned WPHI = Wtemp;
3653
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003654 if (IsFGR64onMips32) {
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003655 unsigned Rtemp2 = RegInfo.createVirtualRegister(GPRRC);
3656 BuildMI(*BB, MI, DL, TII->get(Mips::MFHC1_D64), Rtemp2).addReg(Fs);
3657 unsigned Wtemp2 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
3658 unsigned Wtemp3 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
3659 BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_W), Wtemp2)
3660 .addReg(Wtemp)
3661 .addReg(Rtemp2)
3662 .addImm(1);
3663 BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_W), Wtemp3)
3664 .addReg(Wtemp2)
3665 .addReg(Rtemp2)
3666 .addImm(3);
3667 WPHI = Wtemp3;
3668 }
3669
3670 if (IsFGR64) {
3671 unsigned Wtemp2 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
3672 BuildMI(*BB, MI, DL, TII->get(Mips::FEXDO_W), Wtemp2)
3673 .addReg(WPHI)
3674 .addReg(WPHI);
3675 WPHI = Wtemp2;
3676 }
3677
3678 BuildMI(*BB, MI, DL, TII->get(Mips::FEXDO_H), Wd).addReg(WPHI).addReg(WPHI);
3679
3680 MI.eraseFromParent();
3681 return BB;
3682}
3683
3684// Emit the FPEXTEND_PSEUDO instruction.
3685//
3686// Expand an f16 to either a FGR32Opnd or FGR64Opnd.
3687//
3688// Safety: Cycle the result through the GPRs so the result always ends up
3689// the correct floating point register.
3690//
3691// FIXME: This copying is strictly unnecessary. If we could tie FGR32Opnd:$Fd
3692// / FGR64Opnd:$Fd and MSA128F16:$Ws to the same physical register
3693// (which they can be, as the MSA registers are defined to alias the
3694// FPU's 64 bit and 32 bit registers) the result can be accessed using
3695// the correct register class. That requires operands be tie-able across
3696// register classes which have a sub/super register class relationship. I
3697// haven't checked.
3698//
3699// For FGR32Opnd:
3700//
3701// FPEXTEND FGR32Opnd:$fd, MSA128F16:$ws
3702// =>
3703// fexupr.w $wtemp, $ws
3704// copy_s.w $rtemp, $ws[0]
3705// mtc1 $rtemp, $fd
3706//
3707// For FGR64Opnd on Mips64:
3708//
3709// FPEXTEND FGR64Opnd:$fd, MSA128F16:$ws
3710// =>
3711// fexupr.w $wtemp, $ws
3712// fexupr.d $wtemp2, $wtemp
3713// copy_s.d $rtemp, $wtemp2s[0]
3714// dmtc1 $rtemp, $fd
3715//
3716// For FGR64Opnd on Mips32:
3717//
3718// FPEXTEND FGR64Opnd:$fd, MSA128F16:$ws
3719// =>
3720// fexupr.w $wtemp, $ws
3721// fexupr.d $wtemp2, $wtemp
3722// copy_s.w $rtemp, $wtemp2[0]
3723// mtc1 $rtemp, $ftemp
3724// copy_s.w $rtemp2, $wtemp2[1]
3725// $fd = mthc1 $rtemp2, $ftemp
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003726MachineBasicBlock *
3727MipsSETargetLowering::emitFPEXTEND_PSEUDO(MachineInstr &MI,
3728 MachineBasicBlock *BB,
3729 bool IsFGR64) const {
3730
3731 // Strictly speaking, we need MIPS32R5 to support MSA. We'll be generous
3732 // here. It's technically doable to support MIPS32 here, but the ISA forbids
3733 // it.
3734 assert(Subtarget.hasMSA() && Subtarget.hasMips32r2());
3735
3736 bool IsFGR64onMips64 = Subtarget.hasMips64() && IsFGR64;
3737 bool IsFGR64onMips32 = !Subtarget.hasMips64() && IsFGR64;
3738
3739 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3740 DebugLoc DL = MI.getDebugLoc();
3741 unsigned Fd = MI.getOperand(0).getReg();
3742 unsigned Ws = MI.getOperand(1).getReg();
3743
3744 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3745 const TargetRegisterClass *GPRRC =
3746 IsFGR64onMips64 ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003747 unsigned MTC1Opc = IsFGR64onMips64
3748 ? Mips::DMTC1
3749 : (IsFGR64onMips32 ? Mips::MTC1_D64 : Mips::MTC1);
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003750 unsigned COPYOpc = IsFGR64onMips64 ? Mips::COPY_S_D : Mips::COPY_S_W;
3751
3752 unsigned Wtemp = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
3753 unsigned WPHI = Wtemp;
3754
3755 BuildMI(*BB, MI, DL, TII->get(Mips::FEXUPR_W), Wtemp).addReg(Ws);
3756 if (IsFGR64) {
3757 WPHI = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
3758 BuildMI(*BB, MI, DL, TII->get(Mips::FEXUPR_D), WPHI).addReg(Wtemp);
3759 }
3760
3761 // Perform the safety regclass copy mentioned above.
3762 unsigned Rtemp = RegInfo.createVirtualRegister(GPRRC);
3763 unsigned FPRPHI = IsFGR64onMips32
3764 ? RegInfo.createVirtualRegister(&Mips::FGR64RegClass)
3765 : Fd;
3766 BuildMI(*BB, MI, DL, TII->get(COPYOpc), Rtemp).addReg(WPHI).addImm(0);
3767 BuildMI(*BB, MI, DL, TII->get(MTC1Opc), FPRPHI).addReg(Rtemp);
3768
3769 if (IsFGR64onMips32) {
3770 unsigned Rtemp2 = RegInfo.createVirtualRegister(GPRRC);
3771 BuildMI(*BB, MI, DL, TII->get(Mips::COPY_S_W), Rtemp2)
3772 .addReg(WPHI)
3773 .addImm(1);
3774 BuildMI(*BB, MI, DL, TII->get(Mips::MTHC1_D64), Fd)
3775 .addReg(FPRPHI)
3776 .addReg(Rtemp2);
3777 }
3778
3779 MI.eraseFromParent();
3780 return BB;
3781}
3782
Daniel Sandersa9521602013-10-23 10:36:52 +00003783// Emit the FEXP2_W_1 pseudo instructions.
3784//
3785// fexp2_w_1_pseudo $wd, $wt
3786// =>
3787// ldi.w $ws, 1
3788// fexp2.w $wd, $ws, $wt
3789MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003790MipsSETargetLowering::emitFEXP2_W_1(MachineInstr &MI,
Daniel Sandersa9521602013-10-23 10:36:52 +00003791 MachineBasicBlock *BB) const {
Eric Christopher96e72c62015-01-29 23:27:36 +00003792 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sandersa9521602013-10-23 10:36:52 +00003793 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3794 const TargetRegisterClass *RC = &Mips::MSA128WRegClass;
3795 unsigned Ws1 = RegInfo.createVirtualRegister(RC);
3796 unsigned Ws2 = RegInfo.createVirtualRegister(RC);
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003797 DebugLoc DL = MI.getDebugLoc();
Daniel Sandersa9521602013-10-23 10:36:52 +00003798
3799 // Splat 1.0 into a vector
3800 BuildMI(*BB, MI, DL, TII->get(Mips::LDI_W), Ws1).addImm(1);
3801 BuildMI(*BB, MI, DL, TII->get(Mips::FFINT_U_W), Ws2).addReg(Ws1);
3802
3803 // Emit 1.0 * fexp2(Wt)
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003804 BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_W), MI.getOperand(0).getReg())
Daniel Sandersa9521602013-10-23 10:36:52 +00003805 .addReg(Ws2)
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003806 .addReg(MI.getOperand(1).getReg());
Daniel Sandersa9521602013-10-23 10:36:52 +00003807
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003808 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sandersa9521602013-10-23 10:36:52 +00003809 return BB;
3810}
3811
3812// Emit the FEXP2_D_1 pseudo instructions.
3813//
3814// fexp2_d_1_pseudo $wd, $wt
3815// =>
3816// ldi.d $ws, 1
3817// fexp2.d $wd, $ws, $wt
3818MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003819MipsSETargetLowering::emitFEXP2_D_1(MachineInstr &MI,
Daniel Sandersa9521602013-10-23 10:36:52 +00003820 MachineBasicBlock *BB) const {
Eric Christopher96e72c62015-01-29 23:27:36 +00003821 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sandersa9521602013-10-23 10:36:52 +00003822 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3823 const TargetRegisterClass *RC = &Mips::MSA128DRegClass;
3824 unsigned Ws1 = RegInfo.createVirtualRegister(RC);
3825 unsigned Ws2 = RegInfo.createVirtualRegister(RC);
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003826 DebugLoc DL = MI.getDebugLoc();
Daniel Sandersa9521602013-10-23 10:36:52 +00003827
3828 // Splat 1.0 into a vector
3829 BuildMI(*BB, MI, DL, TII->get(Mips::LDI_D), Ws1).addImm(1);
3830 BuildMI(*BB, MI, DL, TII->get(Mips::FFINT_U_D), Ws2).addReg(Ws1);
3831
3832 // Emit 1.0 * fexp2(Wt)
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003833 BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_D), MI.getOperand(0).getReg())
Daniel Sandersa9521602013-10-23 10:36:52 +00003834 .addReg(Ws2)
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003835 .addReg(MI.getOperand(1).getReg());
Daniel Sandersa9521602013-10-23 10:36:52 +00003836
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003837 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sandersa9521602013-10-23 10:36:52 +00003838 return BB;
3839}