blob: deb65bc44047cbb32209272c5ecbc15174aa488d [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/MachineValueType.h"
32#include "llvm/CodeGen/SelectionDAG.h"
33#include "llvm/CodeGen/SelectionDAGNodes.h"
David Blaikie3f833ed2017-11-08 01:01:31 +000034#include "llvm/CodeGen/TargetInstrInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000035#include "llvm/CodeGen/TargetSubtargetInfo.h"
Eugene Zelenko79220eae2017-08-03 22:12:30 +000036#include "llvm/CodeGen/ValueTypes.h"
37#include "llvm/IR/DebugLoc.h"
Akira Hatanakaa6bbde52013-04-13 02:13:30 +000038#include "llvm/IR/Intrinsics.h"
Eugene Zelenko79220eae2017-08-03 22:12:30 +000039#include "llvm/Support/Casting.h"
Akira Hatanaka96ca1822013-03-13 00:54:29 +000040#include "llvm/Support/CommandLine.h"
Daniel Sanders62aeab82013-10-30 13:31:27 +000041#include "llvm/Support/Debug.h"
Simon Dardis548a53f2017-01-10 16:40:57 +000042#include "llvm/Support/ErrorHandling.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
Petar Jovanoviccd729ea2017-11-15 15:24:04 +0000708static SDValue genConstMult(SDValue X, APInt C, const SDLoc &DL, EVT VT,
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000709 EVT ShiftTy, SelectionDAG &DAG) {
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000710 // Return 0.
711 if (C == 0)
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000712 return DAG.getConstant(0, DL, VT);
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000713
714 // Return x.
715 if (C == 1)
716 return X;
717
718 // If c is power of 2, return (shl x, log2(c)).
Petar Jovanoviccd729ea2017-11-15 15:24:04 +0000719 if (C.isPowerOf2())
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000720 return DAG.getNode(ISD::SHL, DL, VT, X,
Petar Jovanoviccd729ea2017-11-15 15:24:04 +0000721 DAG.getConstant(C.logBase2(), DL, ShiftTy));
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000722
Petar Jovanoviccd729ea2017-11-15 15:24:04 +0000723 unsigned BitWidth = C.getBitWidth();
724 APInt Floor = APInt(BitWidth, 1) << C.logBase2();
725 APInt Ceil = C.isNegative() ? APInt(BitWidth, 0) :
726 APInt(BitWidth, 1) << C.ceilLogBase2();
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000727
728 // If |c - floor_c| <= |c - ceil_c|,
729 // where floor_c = pow(2, floor(log2(c))) and ceil_c = pow(2, ceil(log2(c))),
730 // return (add constMult(x, floor_c), constMult(x, c - floor_c)).
Petar Jovanoviccd729ea2017-11-15 15:24:04 +0000731 if ((C - Floor).ule(Ceil - C)) {
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000732 SDValue Op0 = genConstMult(X, Floor, DL, VT, ShiftTy, DAG);
733 SDValue Op1 = genConstMult(X, C - Floor, DL, VT, ShiftTy, DAG);
734 return DAG.getNode(ISD::ADD, DL, VT, Op0, Op1);
735 }
736
737 // If |c - floor_c| > |c - ceil_c|,
738 // return (sub constMult(x, ceil_c), constMult(x, ceil_c - c)).
739 SDValue Op0 = genConstMult(X, Ceil, DL, VT, ShiftTy, DAG);
740 SDValue Op1 = genConstMult(X, Ceil - C, DL, VT, ShiftTy, DAG);
741 return DAG.getNode(ISD::SUB, DL, VT, Op0, Op1);
742}
743
744static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG,
745 const TargetLowering::DAGCombinerInfo &DCI,
746 const MipsSETargetLowering *TL) {
747 EVT VT = N->getValueType(0);
748
749 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1)))
750 if (!VT.isVector())
Petar Jovanoviccd729ea2017-11-15 15:24:04 +0000751 return genConstMult(N->getOperand(0), C->getAPIntValue(), SDLoc(N), VT,
Mehdi Aminieaabc512015-07-09 15:12:23 +0000752 TL->getScalarShiftAmountTy(DAG.getDataLayout(), VT),
753 DAG);
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000754
755 return SDValue(N, 0);
756}
757
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000758static SDValue performDSPShiftCombine(unsigned Opc, SDNode *N, EVT Ty,
759 SelectionDAG &DAG,
Eric Christopher1c29a652014-07-18 22:55:25 +0000760 const MipsSubtarget &Subtarget) {
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000761 // See if this is a vector splat immediate node.
762 APInt SplatValue, SplatUndef;
763 unsigned SplatBitSize;
764 bool HasAnyUndefs;
Sanjay Patel1ed771f2016-09-14 16:37:15 +0000765 unsigned EltSize = Ty.getScalarSizeInBits();
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000766 BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N->getOperand(1));
767
Eric Christopher1c29a652014-07-18 22:55:25 +0000768 if (!Subtarget.hasDSP())
Daniel Sanders6e664bc2013-11-21 11:40:14 +0000769 return SDValue();
770
Akira Hatanaka0d6964c2013-04-22 19:58:23 +0000771 if (!BV ||
Akira Hatanakad8fb0322013-04-22 20:13:37 +0000772 !BV->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
Eric Christopher1c29a652014-07-18 22:55:25 +0000773 EltSize, !Subtarget.isLittle()) ||
Akira Hatanaka0d6964c2013-04-22 19:58:23 +0000774 (SplatBitSize != EltSize) ||
Akira Hatanakae9d0b312013-04-23 18:09:42 +0000775 (SplatValue.getZExtValue() >= EltSize))
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000776 return SDValue();
777
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000778 SDLoc DL(N);
779 return DAG.getNode(Opc, DL, Ty, N->getOperand(0),
780 DAG.getConstant(SplatValue.getZExtValue(), DL, MVT::i32));
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000781}
782
783static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
784 TargetLowering::DAGCombinerInfo &DCI,
Eric Christopher1c29a652014-07-18 22:55:25 +0000785 const MipsSubtarget &Subtarget) {
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000786 EVT Ty = N->getValueType(0);
787
788 if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8))
789 return SDValue();
790
791 return performDSPShiftCombine(MipsISD::SHLL_DSP, N, Ty, DAG, Subtarget);
792}
793
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000794// Fold sign-extensions into MipsISD::VEXTRACT_[SZ]EXT_ELT for MSA and fold
795// constant splats into MipsISD::SHRA_DSP for DSPr2.
796//
797// Performs the following transformations:
798// - Changes MipsISD::VEXTRACT_[SZ]EXT_ELT to sign extension if its
799// sign/zero-extension is completely overwritten by the new one performed by
800// the ISD::SRA and ISD::SHL nodes.
801// - Removes redundant sign extensions performed by an ISD::SRA and ISD::SHL
802// sequence.
803//
804// See performDSPShiftCombine for more information about the transformation
805// used for DSPr2.
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000806static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG,
807 TargetLowering::DAGCombinerInfo &DCI,
Eric Christopher1c29a652014-07-18 22:55:25 +0000808 const MipsSubtarget &Subtarget) {
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000809 EVT Ty = N->getValueType(0);
810
Eric Christopher1c29a652014-07-18 22:55:25 +0000811 if (Subtarget.hasMSA()) {
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000812 SDValue Op0 = N->getOperand(0);
813 SDValue Op1 = N->getOperand(1);
814
815 // (sra (shl (MipsVExtract[SZ]Ext $a, $b, $c), imm:$d), imm:$d)
816 // where $d + sizeof($c) == 32
817 // or $d + sizeof($c) <= 32 and SExt
818 // -> (MipsVExtractSExt $a, $b, $c)
819 if (Op0->getOpcode() == ISD::SHL && Op1 == Op0->getOperand(1)) {
820 SDValue Op0Op0 = Op0->getOperand(0);
821 ConstantSDNode *ShAmount = dyn_cast<ConstantSDNode>(Op1);
822
823 if (!ShAmount)
824 return SDValue();
825
Daniel Sandersf4f1a872013-09-27 09:25:29 +0000826 if (Op0Op0->getOpcode() != MipsISD::VEXTRACT_SEXT_ELT &&
827 Op0Op0->getOpcode() != MipsISD::VEXTRACT_ZEXT_ELT)
828 return SDValue();
829
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000830 EVT ExtendTy = cast<VTSDNode>(Op0Op0->getOperand(2))->getVT();
831 unsigned TotalBits = ShAmount->getZExtValue() + ExtendTy.getSizeInBits();
832
833 if (TotalBits == 32 ||
834 (Op0Op0->getOpcode() == MipsISD::VEXTRACT_SEXT_ELT &&
835 TotalBits <= 32)) {
836 SDValue Ops[] = { Op0Op0->getOperand(0), Op0Op0->getOperand(1),
837 Op0Op0->getOperand(2) };
Chandler Carruth356665a2014-08-01 22:09:43 +0000838 return DAG.getNode(MipsISD::VEXTRACT_SEXT_ELT, SDLoc(Op0Op0),
839 Op0Op0->getVTList(),
840 makeArrayRef(Ops, Op0Op0->getNumOperands()));
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000841 }
842 }
843 }
844
Eric Christopher1c29a652014-07-18 22:55:25 +0000845 if ((Ty != MVT::v2i16) && ((Ty != MVT::v4i8) || !Subtarget.hasDSPR2()))
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000846 return SDValue();
847
848 return performDSPShiftCombine(MipsISD::SHRA_DSP, N, Ty, DAG, Subtarget);
849}
850
851
852static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG,
853 TargetLowering::DAGCombinerInfo &DCI,
Eric Christopher1c29a652014-07-18 22:55:25 +0000854 const MipsSubtarget &Subtarget) {
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000855 EVT Ty = N->getValueType(0);
856
Eric Christopher1c29a652014-07-18 22:55:25 +0000857 if (((Ty != MVT::v2i16) || !Subtarget.hasDSPR2()) && (Ty != MVT::v4i8))
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000858 return SDValue();
859
860 return performDSPShiftCombine(MipsISD::SHRL_DSP, N, Ty, DAG, Subtarget);
861}
862
Akira Hatanaka68741cc2013-04-30 22:37:26 +0000863static bool isLegalDSPCondCode(EVT Ty, ISD::CondCode CC) {
864 bool IsV216 = (Ty == MVT::v2i16);
865
866 switch (CC) {
867 case ISD::SETEQ:
868 case ISD::SETNE: return true;
869 case ISD::SETLT:
870 case ISD::SETLE:
871 case ISD::SETGT:
872 case ISD::SETGE: return IsV216;
873 case ISD::SETULT:
874 case ISD::SETULE:
875 case ISD::SETUGT:
876 case ISD::SETUGE: return !IsV216;
877 default: return false;
878 }
879}
880
881static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG) {
882 EVT Ty = N->getValueType(0);
883
884 if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8))
885 return SDValue();
886
887 if (!isLegalDSPCondCode(Ty, cast<CondCodeSDNode>(N->getOperand(2))->get()))
888 return SDValue();
889
Andrew Trickef9de2a2013-05-25 02:42:55 +0000890 return DAG.getNode(MipsISD::SETCC_DSP, SDLoc(N), Ty, N->getOperand(0),
Akira Hatanaka68741cc2013-04-30 22:37:26 +0000891 N->getOperand(1), N->getOperand(2));
892}
893
894static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) {
895 EVT Ty = N->getValueType(0);
896
Simon Pilgrim386b8dd2018-02-17 21:29:45 +0000897 if (Ty == MVT::v2i16 || Ty == MVT::v4i8) {
Daniel Sanders3ce56622013-09-24 12:18:31 +0000898 SDValue SetCC = N->getOperand(0);
899
900 if (SetCC.getOpcode() != MipsISD::SETCC_DSP)
901 return SDValue();
902
903 return DAG.getNode(MipsISD::SELECT_CC_DSP, SDLoc(N), Ty,
904 SetCC.getOperand(0), SetCC.getOperand(1),
905 N->getOperand(1), N->getOperand(2), SetCC.getOperand(2));
906 }
907
908 return SDValue();
Akira Hatanaka68741cc2013-04-30 22:37:26 +0000909}
910
Daniel Sandersf7456c72013-09-23 13:22:24 +0000911static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG,
Eric Christopher1c29a652014-07-18 22:55:25 +0000912 const MipsSubtarget &Subtarget) {
Daniel Sandersf7456c72013-09-23 13:22:24 +0000913 EVT Ty = N->getValueType(0);
914
Eric Christopher1c29a652014-07-18 22:55:25 +0000915 if (Subtarget.hasMSA() && Ty.is128BitVector() && Ty.isInteger()) {
Daniel Sandersf7456c72013-09-23 13:22:24 +0000916 // Try the following combines:
917 // (xor (or $a, $b), (build_vector allones))
918 // (xor (or $a, $b), (bitcast (build_vector allones)))
919 SDValue Op0 = N->getOperand(0);
920 SDValue Op1 = N->getOperand(1);
921 SDValue NotOp;
Daniel Sandersf7456c72013-09-23 13:22:24 +0000922
923 if (ISD::isBuildVectorAllOnes(Op0.getNode()))
924 NotOp = Op1;
925 else if (ISD::isBuildVectorAllOnes(Op1.getNode()))
926 NotOp = Op0;
Daniel Sandersf7456c72013-09-23 13:22:24 +0000927 else
928 return SDValue();
929
930 if (NotOp->getOpcode() == ISD::OR)
931 return DAG.getNode(MipsISD::VNOR, SDLoc(N), Ty, NotOp->getOperand(0),
932 NotOp->getOperand(1));
933 }
934
935 return SDValue();
936}
937
Akira Hatanaka9efcd762013-03-30 01:42:24 +0000938SDValue
939MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
940 SelectionDAG &DAG = DCI.DAG;
Akira Hatanaka68741cc2013-04-30 22:37:26 +0000941 SDValue Val;
Akira Hatanaka9efcd762013-03-30 01:42:24 +0000942
943 switch (N->getOpcode()) {
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +0000944 case ISD::AND:
945 Val = performANDCombine(N, DAG, DCI, Subtarget);
946 break;
Daniel Sanders53fe6c42013-10-30 13:51:01 +0000947 case ISD::OR:
948 Val = performORCombine(N, DAG, DCI, Subtarget);
949 break;
Akira Hatanaka5832fc62013-06-26 18:48:17 +0000950 case ISD::MUL:
951 return performMULCombine(N, DAG, DCI, this);
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000952 case ISD::SHL:
Petar Jovanovicb71386a2017-03-15 13:10:08 +0000953 Val = performSHLCombine(N, DAG, DCI, Subtarget);
954 break;
Akira Hatanaka1ebb2a12013-04-19 23:21:32 +0000955 case ISD::SRA:
956 return performSRACombine(N, DAG, DCI, Subtarget);
957 case ISD::SRL:
958 return performSRLCombine(N, DAG, DCI, Subtarget);
Akira Hatanaka68741cc2013-04-30 22:37:26 +0000959 case ISD::VSELECT:
960 return performVSELECTCombine(N, DAG);
Daniel Sandersf7456c72013-09-23 13:22:24 +0000961 case ISD::XOR:
962 Val = performXORCombine(N, DAG, Subtarget);
963 break;
964 case ISD::SETCC:
Akira Hatanaka68741cc2013-04-30 22:37:26 +0000965 Val = performSETCCCombine(N, DAG);
966 break;
Akira Hatanaka9efcd762013-03-30 01:42:24 +0000967 }
Akira Hatanaka68741cc2013-04-30 22:37:26 +0000968
Daniel Sanders62aeab82013-10-30 13:31:27 +0000969 if (Val.getNode()) {
970 DEBUG(dbgs() << "\nMipsSE DAG Combine:\n";
971 N->printrWithDepth(dbgs(), &DAG);
972 dbgs() << "\n=> \n";
973 Val.getNode()->printrWithDepth(dbgs(), &DAG);
974 dbgs() << "\n");
Akira Hatanaka68741cc2013-04-30 22:37:26 +0000975 return Val;
Daniel Sanders62aeab82013-10-30 13:31:27 +0000976 }
Akira Hatanaka68741cc2013-04-30 22:37:26 +0000977
978 return MipsTargetLowering::PerformDAGCombine(N, DCI);
Akira Hatanaka9efcd762013-03-30 01:42:24 +0000979}
980
Akira Hatanaka96ca1822013-03-13 00:54:29 +0000981MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +0000982MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
Akira Hatanaka96ca1822013-03-13 00:54:29 +0000983 MachineBasicBlock *BB) const {
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +0000984 switch (MI.getOpcode()) {
Akira Hatanaka96ca1822013-03-13 00:54:29 +0000985 default:
986 return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB);
987 case Mips::BPOSGE32_PSEUDO:
988 return emitBPOSGE32(MI, BB);
Daniel Sandersce09d072013-08-28 12:14:50 +0000989 case Mips::SNZ_B_PSEUDO:
990 return emitMSACBranchPseudo(MI, BB, Mips::BNZ_B);
991 case Mips::SNZ_H_PSEUDO:
992 return emitMSACBranchPseudo(MI, BB, Mips::BNZ_H);
993 case Mips::SNZ_W_PSEUDO:
994 return emitMSACBranchPseudo(MI, BB, Mips::BNZ_W);
995 case Mips::SNZ_D_PSEUDO:
996 return emitMSACBranchPseudo(MI, BB, Mips::BNZ_D);
997 case Mips::SNZ_V_PSEUDO:
998 return emitMSACBranchPseudo(MI, BB, Mips::BNZ_V);
999 case Mips::SZ_B_PSEUDO:
1000 return emitMSACBranchPseudo(MI, BB, Mips::BZ_B);
1001 case Mips::SZ_H_PSEUDO:
1002 return emitMSACBranchPseudo(MI, BB, Mips::BZ_H);
1003 case Mips::SZ_W_PSEUDO:
1004 return emitMSACBranchPseudo(MI, BB, Mips::BZ_W);
1005 case Mips::SZ_D_PSEUDO:
1006 return emitMSACBranchPseudo(MI, BB, Mips::BZ_D);
1007 case Mips::SZ_V_PSEUDO:
1008 return emitMSACBranchPseudo(MI, BB, Mips::BZ_V);
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00001009 case Mips::COPY_FW_PSEUDO:
1010 return emitCOPY_FW(MI, BB);
1011 case Mips::COPY_FD_PSEUDO:
1012 return emitCOPY_FD(MI, BB);
Daniel Sandersa5150702013-09-27 12:31:32 +00001013 case Mips::INSERT_FW_PSEUDO:
1014 return emitINSERT_FW(MI, BB);
1015 case Mips::INSERT_FD_PSEUDO:
1016 return emitINSERT_FD(MI, BB);
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001017 case Mips::INSERT_B_VIDX_PSEUDO:
Daniel Sanderseda60d22015-05-05 10:32:24 +00001018 case Mips::INSERT_B_VIDX64_PSEUDO:
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001019 return emitINSERT_DF_VIDX(MI, BB, 1, false);
1020 case Mips::INSERT_H_VIDX_PSEUDO:
Daniel Sanderseda60d22015-05-05 10:32:24 +00001021 case Mips::INSERT_H_VIDX64_PSEUDO:
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001022 return emitINSERT_DF_VIDX(MI, BB, 2, false);
1023 case Mips::INSERT_W_VIDX_PSEUDO:
Daniel Sanderseda60d22015-05-05 10:32:24 +00001024 case Mips::INSERT_W_VIDX64_PSEUDO:
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001025 return emitINSERT_DF_VIDX(MI, BB, 4, false);
1026 case Mips::INSERT_D_VIDX_PSEUDO:
Daniel Sanderseda60d22015-05-05 10:32:24 +00001027 case Mips::INSERT_D_VIDX64_PSEUDO:
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001028 return emitINSERT_DF_VIDX(MI, BB, 8, false);
1029 case Mips::INSERT_FW_VIDX_PSEUDO:
Daniel Sanderseda60d22015-05-05 10:32:24 +00001030 case Mips::INSERT_FW_VIDX64_PSEUDO:
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001031 return emitINSERT_DF_VIDX(MI, BB, 4, true);
1032 case Mips::INSERT_FD_VIDX_PSEUDO:
Daniel Sanderseda60d22015-05-05 10:32:24 +00001033 case Mips::INSERT_FD_VIDX64_PSEUDO:
Daniel Sanderse296a0f2014-04-30 12:09:32 +00001034 return emitINSERT_DF_VIDX(MI, BB, 8, true);
Daniel Sanders1dfddc72013-10-15 13:14:41 +00001035 case Mips::FILL_FW_PSEUDO:
1036 return emitFILL_FW(MI, BB);
1037 case Mips::FILL_FD_PSEUDO:
1038 return emitFILL_FD(MI, BB);
Daniel Sandersa9521602013-10-23 10:36:52 +00001039 case Mips::FEXP2_W_1_PSEUDO:
1040 return emitFEXP2_W_1(MI, BB);
1041 case Mips::FEXP2_D_1_PSEUDO:
1042 return emitFEXP2_D_1(MI, BB);
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00001043 case Mips::ST_F16:
1044 return emitST_F16_PSEUDO(MI, BB);
1045 case Mips::LD_F16:
1046 return emitLD_F16_PSEUDO(MI, BB);
1047 case Mips::MSA_FP_EXTEND_W_PSEUDO:
1048 return emitFPEXTEND_PSEUDO(MI, BB, false);
1049 case Mips::MSA_FP_ROUND_W_PSEUDO:
1050 return emitFPROUND_PSEUDO(MI, BB, false);
1051 case Mips::MSA_FP_EXTEND_D_PSEUDO:
1052 return emitFPEXTEND_PSEUDO(MI, BB, true);
1053 case Mips::MSA_FP_ROUND_D_PSEUDO:
1054 return emitFPROUND_PSEUDO(MI, BB, true);
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001055 }
1056}
1057
Daniel Sanders23e98772014-11-02 16:09:29 +00001058bool MipsSETargetLowering::isEligibleForTailCallOptimization(
1059 const CCState &CCInfo, unsigned NextStackOffset,
1060 const MipsFunctionInfo &FI) const {
Simon Dardis57f4ae42016-08-04 09:17:07 +00001061 if (!UseMipsTailCalls)
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001062 return false;
1063
Vasileios Kalintiris43dff0c2015-10-26 12:38:43 +00001064 // Exception has to be cleared with eret.
1065 if (FI.isISR())
1066 return false;
1067
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001068 // Return false if either the callee or caller has a byval argument.
Daniel Sanders23e98772014-11-02 16:09:29 +00001069 if (CCInfo.getInRegsParamsCount() > 0 || FI.hasByvalArg())
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001070 return false;
1071
1072 // Return true if the callee's argument area is no larger than the
1073 // caller's.
1074 return NextStackOffset <= FI.getIncomingArgSize();
1075}
1076
1077void MipsSETargetLowering::
1078getOpndList(SmallVectorImpl<SDValue> &Ops,
Eugene Zelenko79220eae2017-08-03 22:12:30 +00001079 std::deque<std::pair<unsigned, SDValue>> &RegsToPass,
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001080 bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
Sasa Stankovic7072a792014-10-01 08:22:21 +00001081 bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee,
1082 SDValue Chain) const {
Akira Hatanaka168d4e52013-11-27 23:38:42 +00001083 Ops.push_back(Callee);
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001084 MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal,
Sasa Stankovic7072a792014-10-01 08:22:21 +00001085 InternalLinkage, IsCallReloc, CLI, Callee,
1086 Chain);
Akira Hatanaka96ca1822013-03-13 00:54:29 +00001087}
1088
Akira Hatanaka63791212013-09-07 00:52:30 +00001089SDValue MipsSETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const {
1090 LoadSDNode &Nd = *cast<LoadSDNode>(Op);
1091
1092 if (Nd.getMemoryVT() != MVT::f64 || !NoDPLoadStore)
1093 return MipsTargetLowering::lowerLOAD(Op, DAG);
1094
1095 // Replace a double precision load with two i32 loads and a buildpair64.
1096 SDLoc DL(Op);
1097 SDValue Ptr = Nd.getBasePtr(), Chain = Nd.getChain();
1098 EVT PtrVT = Ptr.getValueType();
1099
1100 // i32 load from lower address.
Justin Lebar9c375812016-07-15 18:27:10 +00001101 SDValue Lo = DAG.getLoad(MVT::i32, DL, Chain, Ptr, MachinePointerInfo(),
1102 Nd.getAlignment(), Nd.getMemOperand()->getFlags());
Akira Hatanaka63791212013-09-07 00:52:30 +00001103
1104 // i32 load from higher address.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001105 Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, DL, PtrVT));
Justin Lebar9c375812016-07-15 18:27:10 +00001106 SDValue Hi = DAG.getLoad(
1107 MVT::i32, DL, Lo.getValue(1), Ptr, MachinePointerInfo(),
1108 std::min(Nd.getAlignment(), 4U), Nd.getMemOperand()->getFlags());
Akira Hatanaka63791212013-09-07 00:52:30 +00001109
Eric Christopher1c29a652014-07-18 22:55:25 +00001110 if (!Subtarget.isLittle())
Akira Hatanaka63791212013-09-07 00:52:30 +00001111 std::swap(Lo, Hi);
1112
1113 SDValue BP = DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, Lo, Hi);
1114 SDValue Ops[2] = {BP, Hi.getValue(1)};
Craig Topper64941d92014-04-27 19:20:57 +00001115 return DAG.getMergeValues(Ops, DL);
Akira Hatanaka63791212013-09-07 00:52:30 +00001116}
1117
1118SDValue MipsSETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
1119 StoreSDNode &Nd = *cast<StoreSDNode>(Op);
1120
1121 if (Nd.getMemoryVT() != MVT::f64 || !NoDPLoadStore)
1122 return MipsTargetLowering::lowerSTORE(Op, DAG);
1123
1124 // Replace a double precision store with two extractelement64s and i32 stores.
1125 SDLoc DL(Op);
1126 SDValue Val = Nd.getValue(), Ptr = Nd.getBasePtr(), Chain = Nd.getChain();
1127 EVT PtrVT = Ptr.getValueType();
1128 SDValue Lo = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001129 Val, DAG.getConstant(0, DL, MVT::i32));
Akira Hatanaka63791212013-09-07 00:52:30 +00001130 SDValue Hi = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001131 Val, DAG.getConstant(1, DL, MVT::i32));
Akira Hatanaka63791212013-09-07 00:52:30 +00001132
Eric Christopher1c29a652014-07-18 22:55:25 +00001133 if (!Subtarget.isLittle())
Akira Hatanaka63791212013-09-07 00:52:30 +00001134 std::swap(Lo, Hi);
1135
1136 // i32 store to lower address.
Justin Lebar9c375812016-07-15 18:27:10 +00001137 Chain =
1138 DAG.getStore(Chain, DL, Lo, Ptr, MachinePointerInfo(), Nd.getAlignment(),
1139 Nd.getMemOperand()->getFlags(), Nd.getAAInfo());
Akira Hatanaka63791212013-09-07 00:52:30 +00001140
1141 // i32 store to higher address.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001142 Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, DL, PtrVT));
Akira Hatanaka63791212013-09-07 00:52:30 +00001143 return DAG.getStore(Chain, DL, Hi, Ptr, MachinePointerInfo(),
Justin Lebar9c375812016-07-15 18:27:10 +00001144 std::min(Nd.getAlignment(), 4U),
1145 Nd.getMemOperand()->getFlags(), Nd.getAAInfo());
Akira Hatanaka63791212013-09-07 00:52:30 +00001146}
1147
Akira Hatanakabe8612f2013-03-30 01:36:35 +00001148SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc,
1149 bool HasLo, bool HasHi,
1150 SelectionDAG &DAG) const {
Daniel Sanders308181e2014-06-12 10:44:10 +00001151 // MIPS32r6/MIPS64r6 removed accumulator based multiplies.
Eric Christopher1c29a652014-07-18 22:55:25 +00001152 assert(!Subtarget.hasMips32r6());
Daniel Sanders308181e2014-06-12 10:44:10 +00001153
Akira Hatanakabe8612f2013-03-30 01:36:35 +00001154 EVT Ty = Op.getOperand(0).getValueType();
Andrew Trickef9de2a2013-05-25 02:42:55 +00001155 SDLoc DL(Op);
Akira Hatanakabe8612f2013-03-30 01:36:35 +00001156 SDValue Mult = DAG.getNode(NewOpc, DL, MVT::Untyped,
1157 Op.getOperand(0), Op.getOperand(1));
1158 SDValue Lo, Hi;
1159
1160 if (HasLo)
Akira Hatanakad98c99f2013-10-15 01:12:50 +00001161 Lo = DAG.getNode(MipsISD::MFLO, DL, Ty, Mult);
Akira Hatanakabe8612f2013-03-30 01:36:35 +00001162 if (HasHi)
Akira Hatanakad98c99f2013-10-15 01:12:50 +00001163 Hi = DAG.getNode(MipsISD::MFHI, DL, Ty, Mult);
Akira Hatanakabe8612f2013-03-30 01:36:35 +00001164
1165 if (!HasLo || !HasHi)
1166 return HasLo ? Lo : Hi;
1167
1168 SDValue Vals[] = { Lo, Hi };
Craig Topper64941d92014-04-27 19:20:57 +00001169 return DAG.getMergeValues(Vals, DL);
Akira Hatanakabe8612f2013-03-30 01:36:35 +00001170}
1171
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001172static SDValue initAccumulator(SDValue In, const SDLoc &DL, SelectionDAG &DAG) {
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001173 SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001174 DAG.getConstant(0, DL, MVT::i32));
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001175 SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001176 DAG.getConstant(1, DL, MVT::i32));
Akira Hatanakad98c99f2013-10-15 01:12:50 +00001177 return DAG.getNode(MipsISD::MTLOHI, DL, MVT::Untyped, InLo, InHi);
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001178}
1179
Benjamin Kramerbdc49562016-06-12 15:39:02 +00001180static SDValue extractLOHI(SDValue Op, const SDLoc &DL, SelectionDAG &DAG) {
Akira Hatanakad98c99f2013-10-15 01:12:50 +00001181 SDValue Lo = DAG.getNode(MipsISD::MFLO, DL, MVT::i32, Op);
1182 SDValue Hi = DAG.getNode(MipsISD::MFHI, DL, MVT::i32, Op);
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001183 return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi);
1184}
1185
1186// This function expands mips intrinsic nodes which have 64-bit input operands
1187// or output values.
1188//
1189// out64 = intrinsic-node in64
1190// =>
1191// lo = copy (extract-element (in64, 0))
1192// hi = copy (extract-element (in64, 1))
1193// mips-specific-node
1194// v0 = copy lo
1195// v1 = copy hi
1196// out64 = merge-values (v0, v1)
1197//
1198static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
Andrew Trickef9de2a2013-05-25 02:42:55 +00001199 SDLoc DL(Op);
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001200 bool HasChainIn = Op->getOperand(0).getValueType() == MVT::Other;
1201 SmallVector<SDValue, 3> Ops;
1202 unsigned OpNo = 0;
1203
1204 // See if Op has a chain input.
1205 if (HasChainIn)
1206 Ops.push_back(Op->getOperand(OpNo++));
1207
1208 // The next operand is the intrinsic opcode.
1209 assert(Op->getOperand(OpNo).getOpcode() == ISD::TargetConstant);
1210
1211 // See if the next operand has type i64.
1212 SDValue Opnd = Op->getOperand(++OpNo), In64;
1213
1214 if (Opnd.getValueType() == MVT::i64)
1215 In64 = initAccumulator(Opnd, DL, DAG);
1216 else
1217 Ops.push_back(Opnd);
1218
1219 // Push the remaining operands.
1220 for (++OpNo ; OpNo < Op->getNumOperands(); ++OpNo)
1221 Ops.push_back(Op->getOperand(OpNo));
1222
1223 // Add In64 to the end of the list.
1224 if (In64.getNode())
1225 Ops.push_back(In64);
1226
1227 // Scan output.
1228 SmallVector<EVT, 2> ResTys;
1229
1230 for (SDNode::value_iterator I = Op->value_begin(), E = Op->value_end();
1231 I != E; ++I)
1232 ResTys.push_back((*I == MVT::i64) ? MVT::Untyped : *I);
1233
1234 // Create node.
Craig Topper48d114b2014-04-26 18:35:24 +00001235 SDValue Val = DAG.getNode(Opc, DL, ResTys, Ops);
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001236 SDValue Out = (ResTys[0] == MVT::Untyped) ? extractLOHI(Val, DL, DAG) : Val;
1237
1238 if (!HasChainIn)
1239 return Out;
1240
1241 assert(Val->getValueType(1) == MVT::Other);
1242 SDValue Vals[] = { Out, SDValue(Val.getNode(), 1) };
Craig Topper64941d92014-04-27 19:20:57 +00001243 return DAG.getMergeValues(Vals, DL);
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001244}
1245
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +00001246// Lower an MSA copy intrinsic into the specified SelectionDAG node
1247static SDValue lowerMSACopyIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
1248 SDLoc DL(Op);
1249 SDValue Vec = Op->getOperand(1);
1250 SDValue Idx = Op->getOperand(2);
1251 EVT ResTy = Op->getValueType(0);
1252 EVT EltTy = Vec->getValueType(0).getVectorElementType();
1253
1254 SDValue Result = DAG.getNode(Opc, DL, ResTy, Vec, Idx,
1255 DAG.getValueType(EltTy));
1256
1257 return Result;
1258}
1259
Daniel Sanders50b80412013-11-15 12:56:49 +00001260static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) {
1261 EVT ResVecTy = Op->getValueType(0);
1262 EVT ViaVecTy = ResVecTy;
Stefan Maksimovicb794c0a2017-06-23 09:09:31 +00001263 bool BigEndian = !DAG.getSubtarget().getTargetTriple().isLittleEndian();
Daniel Sanders50b80412013-11-15 12:56:49 +00001264 SDLoc DL(Op);
Daniel Sanders86d0c8d2013-09-23 14:29:55 +00001265
Daniel Sanders50b80412013-11-15 12:56:49 +00001266 // When ResVecTy == MVT::v2i64, LaneA is the upper 32 bits of the lane and
1267 // LaneB is the lower 32-bits. Otherwise LaneA and LaneB are alternating
1268 // lanes.
Stefan Maksimovicb794c0a2017-06-23 09:09:31 +00001269 SDValue LaneA = Op->getOperand(OpNr);
1270 SDValue LaneB;
Daniel Sanders50b80412013-11-15 12:56:49 +00001271
1272 if (ResVecTy == MVT::v2i64) {
Stefan Maksimovicb794c0a2017-06-23 09:09:31 +00001273 LaneB = DAG.getConstant(0, DL, MVT::i32);
Daniel Sandersf49dd822013-09-24 13:33:07 +00001274 ViaVecTy = MVT::v4i32;
Stefan Maksimovicb794c0a2017-06-23 09:09:31 +00001275 if(BigEndian)
1276 std::swap(LaneA, LaneB);
Daniel Sanders50b80412013-11-15 12:56:49 +00001277 } else
Stefan Maksimovicb794c0a2017-06-23 09:09:31 +00001278 LaneB = LaneA;
Daniel Sanders86d0c8d2013-09-23 14:29:55 +00001279
Daniel Sanders50b80412013-11-15 12:56:49 +00001280 SDValue Ops[16] = { LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB,
1281 LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB };
Daniel Sandersf49dd822013-09-24 13:33:07 +00001282
Ahmed Bougacha128f8732016-04-26 21:15:30 +00001283 SDValue Result = DAG.getBuildVector(
1284 ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements()));
Daniel Sanders50b80412013-11-15 12:56:49 +00001285
Stefan Maksimovicb794c0a2017-06-23 09:09:31 +00001286 if (ViaVecTy != ResVecTy) {
1287 SDValue One = DAG.getConstant(1, DL, ViaVecTy);
1288 Result = DAG.getNode(ISD::BITCAST, DL, ResVecTy,
1289 DAG.getNode(ISD::AND, DL, ViaVecTy, Result, One));
1290 }
Daniel Sandersf49dd822013-09-24 13:33:07 +00001291
1292 return Result;
1293}
1294
Simon Dardis548a53f2017-01-10 16:40:57 +00001295static SDValue lowerMSASplatImm(SDValue Op, unsigned ImmOp, SelectionDAG &DAG,
1296 bool IsSigned = false) {
1297 return DAG.getConstant(
1298 APInt(Op->getValueType(0).getScalarType().getSizeInBits(),
1299 Op->getConstantOperandVal(ImmOp), IsSigned),
1300 SDLoc(Op), Op->getValueType(0));
Daniel Sanders50b80412013-11-15 12:56:49 +00001301}
1302
1303static SDValue getBuildVectorSplat(EVT VecTy, SDValue SplatValue,
1304 bool BigEndian, SelectionDAG &DAG) {
1305 EVT ViaVecTy = VecTy;
1306 SDValue SplatValueA = SplatValue;
1307 SDValue SplatValueB = SplatValue;
1308 SDLoc DL(SplatValue);
1309
1310 if (VecTy == MVT::v2i64) {
1311 // v2i64 BUILD_VECTOR must be performed via v4i32 so split into i32's.
1312 ViaVecTy = MVT::v4i32;
1313
1314 SplatValueA = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValue);
1315 SplatValueB = DAG.getNode(ISD::SRL, DL, MVT::i64, SplatValue,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001316 DAG.getConstant(32, DL, MVT::i32));
Daniel Sanders50b80412013-11-15 12:56:49 +00001317 SplatValueB = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValueB);
1318 }
1319
1320 // We currently hold the parts in little endian order. Swap them if
1321 // necessary.
1322 if (BigEndian)
1323 std::swap(SplatValueA, SplatValueB);
1324
1325 SDValue Ops[16] = { SplatValueA, SplatValueB, SplatValueA, SplatValueB,
1326 SplatValueA, SplatValueB, SplatValueA, SplatValueB,
1327 SplatValueA, SplatValueB, SplatValueA, SplatValueB,
1328 SplatValueA, SplatValueB, SplatValueA, SplatValueB };
1329
Ahmed Bougacha128f8732016-04-26 21:15:30 +00001330 SDValue Result = DAG.getBuildVector(
1331 ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements()));
Daniel Sanders50b80412013-11-15 12:56:49 +00001332
1333 if (VecTy != ViaVecTy)
1334 Result = DAG.getNode(ISD::BITCAST, DL, VecTy, Result);
1335
1336 return Result;
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001337}
1338
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001339static SDValue lowerMSABinaryBitImmIntr(SDValue Op, SelectionDAG &DAG,
1340 unsigned Opc, SDValue Imm,
1341 bool BigEndian) {
1342 EVT VecTy = Op->getValueType(0);
1343 SDValue Exp2Imm;
1344 SDLoc DL(Op);
1345
Daniel Sanders50b80412013-11-15 12:56:49 +00001346 // The DAG Combiner can't constant fold bitcasted vectors yet so we must do it
1347 // here for now.
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001348 if (VecTy == MVT::v2i64) {
1349 if (ConstantSDNode *CImm = dyn_cast<ConstantSDNode>(Imm)) {
1350 APInt BitImm = APInt(64, 1) << CImm->getAPIntValue();
1351
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001352 SDValue BitImmHiOp = DAG.getConstant(BitImm.lshr(32).trunc(32), DL,
1353 MVT::i32);
1354 SDValue BitImmLoOp = DAG.getConstant(BitImm.trunc(32), DL, MVT::i32);
Daniel Sanders50b80412013-11-15 12:56:49 +00001355
1356 if (BigEndian)
1357 std::swap(BitImmLoOp, BitImmHiOp);
1358
Ahmed Bougacha128f8732016-04-26 21:15:30 +00001359 Exp2Imm = DAG.getNode(
1360 ISD::BITCAST, DL, MVT::v2i64,
1361 DAG.getBuildVector(MVT::v4i32, DL,
1362 {BitImmLoOp, BitImmHiOp, BitImmLoOp, BitImmHiOp}));
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001363 }
1364 }
1365
Craig Topper062a2ba2014-04-25 05:30:21 +00001366 if (!Exp2Imm.getNode()) {
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001367 // We couldnt constant fold, do a vector shift instead
Daniel Sanders50b80412013-11-15 12:56:49 +00001368
1369 // Extend i32 to i64 if necessary. Sign or zero extend doesn't matter since
1370 // only values 0-63 are valid.
1371 if (VecTy == MVT::v2i64)
1372 Imm = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Imm);
1373
1374 Exp2Imm = getBuildVectorSplat(VecTy, Imm, BigEndian, DAG);
1375
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001376 Exp2Imm = DAG.getNode(ISD::SHL, DL, VecTy, DAG.getConstant(1, DL, VecTy),
1377 Exp2Imm);
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001378 }
1379
1380 return DAG.getNode(Opc, DL, VecTy, Op->getOperand(1), Exp2Imm);
1381}
1382
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00001383static SDValue truncateVecElts(SDValue Op, SelectionDAG &DAG) {
1384 SDLoc DL(Op);
1385 EVT ResTy = Op->getValueType(0);
1386 SDValue Vec = Op->getOperand(2);
1387 bool BigEndian = !DAG.getSubtarget().getTargetTriple().isLittleEndian();
1388 MVT ResEltTy = ResTy == MVT::v2i64 ? MVT::i64 : MVT::i32;
1389 SDValue ConstValue = DAG.getConstant(Vec.getScalarValueSizeInBits() - 1,
1390 DL, ResEltTy);
1391 SDValue SplatVec = getBuildVectorSplat(ResTy, ConstValue, BigEndian, DAG);
1392
1393 return DAG.getNode(ISD::AND, DL, ResTy, Vec, SplatVec);
1394}
1395
Daniel Sanders3f6eb542013-11-12 10:45:18 +00001396static SDValue lowerMSABitClear(SDValue Op, SelectionDAG &DAG) {
1397 EVT ResTy = Op->getValueType(0);
Daniel Sanders3f6eb542013-11-12 10:45:18 +00001398 SDLoc DL(Op);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001399 SDValue One = DAG.getConstant(1, DL, ResTy);
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00001400 SDValue Bit = DAG.getNode(ISD::SHL, DL, ResTy, One, truncateVecElts(Op, DAG));
Daniel Sanders3f6eb542013-11-12 10:45:18 +00001401
Daniel Sanders71ce0ca2013-11-15 16:02:04 +00001402 return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1),
1403 DAG.getNOT(DL, Bit, ResTy));
Daniel Sanders3f6eb542013-11-12 10:45:18 +00001404}
1405
1406static SDValue lowerMSABitClearImm(SDValue Op, SelectionDAG &DAG) {
1407 SDLoc DL(Op);
1408 EVT ResTy = Op->getValueType(0);
Sanjay Patel1ed771f2016-09-14 16:37:15 +00001409 APInt BitImm = APInt(ResTy.getScalarSizeInBits(), 1)
Daniel Sanders50b80412013-11-15 12:56:49 +00001410 << cast<ConstantSDNode>(Op->getOperand(2))->getAPIntValue();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001411 SDValue BitMask = DAG.getConstant(~BitImm, DL, ResTy);
Daniel Sanders3f6eb542013-11-12 10:45:18 +00001412
1413 return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1), BitMask);
1414}
1415
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001416SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
1417 SelectionDAG &DAG) const {
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001418 SDLoc DL(Op);
Simon Dardis548a53f2017-01-10 16:40:57 +00001419 unsigned Intrinsic = cast<ConstantSDNode>(Op->getOperand(0))->getZExtValue();
1420 switch (Intrinsic) {
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00001421 default:
1422 return SDValue();
1423 case Intrinsic::mips_shilo:
1424 return lowerDSPIntr(Op, DAG, MipsISD::SHILO);
1425 case Intrinsic::mips_dpau_h_qbl:
1426 return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBL);
1427 case Intrinsic::mips_dpau_h_qbr:
1428 return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBR);
1429 case Intrinsic::mips_dpsu_h_qbl:
1430 return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBL);
1431 case Intrinsic::mips_dpsu_h_qbr:
1432 return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBR);
1433 case Intrinsic::mips_dpa_w_ph:
1434 return lowerDSPIntr(Op, DAG, MipsISD::DPA_W_PH);
1435 case Intrinsic::mips_dps_w_ph:
1436 return lowerDSPIntr(Op, DAG, MipsISD::DPS_W_PH);
1437 case Intrinsic::mips_dpax_w_ph:
1438 return lowerDSPIntr(Op, DAG, MipsISD::DPAX_W_PH);
1439 case Intrinsic::mips_dpsx_w_ph:
1440 return lowerDSPIntr(Op, DAG, MipsISD::DPSX_W_PH);
1441 case Intrinsic::mips_mulsa_w_ph:
1442 return lowerDSPIntr(Op, DAG, MipsISD::MULSA_W_PH);
1443 case Intrinsic::mips_mult:
1444 return lowerDSPIntr(Op, DAG, MipsISD::Mult);
1445 case Intrinsic::mips_multu:
1446 return lowerDSPIntr(Op, DAG, MipsISD::Multu);
1447 case Intrinsic::mips_madd:
1448 return lowerDSPIntr(Op, DAG, MipsISD::MAdd);
1449 case Intrinsic::mips_maddu:
1450 return lowerDSPIntr(Op, DAG, MipsISD::MAddu);
1451 case Intrinsic::mips_msub:
1452 return lowerDSPIntr(Op, DAG, MipsISD::MSub);
1453 case Intrinsic::mips_msubu:
1454 return lowerDSPIntr(Op, DAG, MipsISD::MSubu);
Daniel Sandersfa5ab1c2013-09-11 10:28:16 +00001455 case Intrinsic::mips_addv_b:
1456 case Intrinsic::mips_addv_h:
1457 case Intrinsic::mips_addv_w:
1458 case Intrinsic::mips_addv_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001459 return DAG.getNode(ISD::ADD, DL, Op->getValueType(0), Op->getOperand(1),
1460 Op->getOperand(2));
Daniel Sanders86d0c8d2013-09-23 14:29:55 +00001461 case Intrinsic::mips_addvi_b:
1462 case Intrinsic::mips_addvi_h:
1463 case Intrinsic::mips_addvi_w:
1464 case Intrinsic::mips_addvi_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001465 return DAG.getNode(ISD::ADD, DL, Op->getValueType(0), Op->getOperand(1),
1466 lowerMSASplatImm(Op, 2, DAG));
Daniel Sanders8ca81e42013-09-23 12:57:42 +00001467 case Intrinsic::mips_and_v:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001468 return DAG.getNode(ISD::AND, DL, Op->getValueType(0), Op->getOperand(1),
1469 Op->getOperand(2));
Daniel Sandersbfc39ce2013-09-24 12:32:47 +00001470 case Intrinsic::mips_andi_b:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001471 return DAG.getNode(ISD::AND, DL, Op->getValueType(0), Op->getOperand(1),
1472 lowerMSASplatImm(Op, 2, DAG));
Daniel Sanders3f6eb542013-11-12 10:45:18 +00001473 case Intrinsic::mips_bclr_b:
1474 case Intrinsic::mips_bclr_h:
1475 case Intrinsic::mips_bclr_w:
1476 case Intrinsic::mips_bclr_d:
1477 return lowerMSABitClear(Op, DAG);
1478 case Intrinsic::mips_bclri_b:
1479 case Intrinsic::mips_bclri_h:
1480 case Intrinsic::mips_bclri_w:
1481 case Intrinsic::mips_bclri_d:
1482 return lowerMSABitClearImm(Op, DAG);
Daniel Sandersd74b1302013-10-30 14:45:14 +00001483 case Intrinsic::mips_binsli_b:
1484 case Intrinsic::mips_binsli_h:
1485 case Intrinsic::mips_binsli_w:
1486 case Intrinsic::mips_binsli_d: {
Daniel Sandersdf2215452014-03-12 11:54:00 +00001487 // binsli_x(IfClear, IfSet, nbits) -> (vselect LBitsMask, IfSet, IfClear)
Daniel Sandersd74b1302013-10-30 14:45:14 +00001488 EVT VecTy = Op->getValueType(0);
1489 EVT EltTy = VecTy.getVectorElementType();
Simon Dardis548a53f2017-01-10 16:40:57 +00001490 if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits())
1491 report_fatal_error("Immediate out of range");
Daniel Sandersd74b1302013-10-30 14:45:14 +00001492 APInt Mask = APInt::getHighBitsSet(EltTy.getSizeInBits(),
Petar Jovanovicbc54eb82017-04-07 13:31:36 +00001493 Op->getConstantOperandVal(3) + 1);
Daniel Sandersd74b1302013-10-30 14:45:14 +00001494 return DAG.getNode(ISD::VSELECT, DL, VecTy,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001495 DAG.getConstant(Mask, DL, VecTy, true),
1496 Op->getOperand(2), Op->getOperand(1));
Daniel Sandersd74b1302013-10-30 14:45:14 +00001497 }
1498 case Intrinsic::mips_binsri_b:
1499 case Intrinsic::mips_binsri_h:
1500 case Intrinsic::mips_binsri_w:
1501 case Intrinsic::mips_binsri_d: {
Daniel Sandersdf2215452014-03-12 11:54:00 +00001502 // binsri_x(IfClear, IfSet, nbits) -> (vselect RBitsMask, IfSet, IfClear)
Daniel Sandersd74b1302013-10-30 14:45:14 +00001503 EVT VecTy = Op->getValueType(0);
1504 EVT EltTy = VecTy.getVectorElementType();
Simon Dardis548a53f2017-01-10 16:40:57 +00001505 if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits())
1506 report_fatal_error("Immediate out of range");
Daniel Sandersd74b1302013-10-30 14:45:14 +00001507 APInt Mask = APInt::getLowBitsSet(EltTy.getSizeInBits(),
Petar Jovanovicbc54eb82017-04-07 13:31:36 +00001508 Op->getConstantOperandVal(3) + 1);
Daniel Sandersd74b1302013-10-30 14:45:14 +00001509 return DAG.getNode(ISD::VSELECT, DL, VecTy,
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001510 DAG.getConstant(Mask, DL, VecTy, true),
1511 Op->getOperand(2), Op->getOperand(1));
Daniel Sandersd74b1302013-10-30 14:45:14 +00001512 }
Daniel Sandersab94b532013-10-30 15:20:38 +00001513 case Intrinsic::mips_bmnz_v:
1514 return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), Op->getOperand(3),
1515 Op->getOperand(2), Op->getOperand(1));
1516 case Intrinsic::mips_bmnzi_b:
1517 return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0),
1518 lowerMSASplatImm(Op, 3, DAG), Op->getOperand(2),
1519 Op->getOperand(1));
1520 case Intrinsic::mips_bmz_v:
1521 return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), Op->getOperand(3),
1522 Op->getOperand(1), Op->getOperand(2));
1523 case Intrinsic::mips_bmzi_b:
1524 return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0),
1525 lowerMSASplatImm(Op, 3, DAG), Op->getOperand(1),
1526 Op->getOperand(2));
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001527 case Intrinsic::mips_bneg_b:
1528 case Intrinsic::mips_bneg_h:
1529 case Intrinsic::mips_bneg_w:
1530 case Intrinsic::mips_bneg_d: {
1531 EVT VecTy = Op->getValueType(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001532 SDValue One = DAG.getConstant(1, DL, VecTy);
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001533
1534 return DAG.getNode(ISD::XOR, DL, VecTy, Op->getOperand(1),
1535 DAG.getNode(ISD::SHL, DL, VecTy, One,
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00001536 truncateVecElts(Op, DAG)));
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001537 }
1538 case Intrinsic::mips_bnegi_b:
1539 case Intrinsic::mips_bnegi_h:
1540 case Intrinsic::mips_bnegi_w:
1541 case Intrinsic::mips_bnegi_d:
1542 return lowerMSABinaryBitImmIntr(Op, DAG, ISD::XOR, Op->getOperand(2),
Eric Christopher1c29a652014-07-18 22:55:25 +00001543 !Subtarget.isLittle());
Daniel Sandersce09d072013-08-28 12:14:50 +00001544 case Intrinsic::mips_bnz_b:
1545 case Intrinsic::mips_bnz_h:
1546 case Intrinsic::mips_bnz_w:
1547 case Intrinsic::mips_bnz_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001548 return DAG.getNode(MipsISD::VALL_NONZERO, DL, Op->getValueType(0),
1549 Op->getOperand(1));
Daniel Sandersce09d072013-08-28 12:14:50 +00001550 case Intrinsic::mips_bnz_v:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001551 return DAG.getNode(MipsISD::VANY_NONZERO, DL, Op->getValueType(0),
1552 Op->getOperand(1));
Daniel Sanderse1d24352013-09-24 12:04:44 +00001553 case Intrinsic::mips_bsel_v:
Daniel Sandersdf2215452014-03-12 11:54:00 +00001554 // bsel_v(Mask, IfClear, IfSet) -> (vselect Mask, IfSet, IfClear)
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001555 return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0),
Daniel Sandersdf2215452014-03-12 11:54:00 +00001556 Op->getOperand(1), Op->getOperand(3),
1557 Op->getOperand(2));
Daniel Sanderse1d24352013-09-24 12:04:44 +00001558 case Intrinsic::mips_bseli_b:
Daniel Sandersdf2215452014-03-12 11:54:00 +00001559 // bseli_v(Mask, IfClear, IfSet) -> (vselect Mask, IfSet, IfClear)
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001560 return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0),
Daniel Sandersdf2215452014-03-12 11:54:00 +00001561 Op->getOperand(1), lowerMSASplatImm(Op, 3, DAG),
1562 Op->getOperand(2));
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001563 case Intrinsic::mips_bset_b:
1564 case Intrinsic::mips_bset_h:
1565 case Intrinsic::mips_bset_w:
1566 case Intrinsic::mips_bset_d: {
1567 EVT VecTy = Op->getValueType(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001568 SDValue One = DAG.getConstant(1, DL, VecTy);
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001569
1570 return DAG.getNode(ISD::OR, DL, VecTy, Op->getOperand(1),
1571 DAG.getNode(ISD::SHL, DL, VecTy, One,
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00001572 truncateVecElts(Op, DAG)));
Daniel Sandersa5bc99f2013-11-12 10:31:49 +00001573 }
1574 case Intrinsic::mips_bseti_b:
1575 case Intrinsic::mips_bseti_h:
1576 case Intrinsic::mips_bseti_w:
1577 case Intrinsic::mips_bseti_d:
1578 return lowerMSABinaryBitImmIntr(Op, DAG, ISD::OR, Op->getOperand(2),
Eric Christopher1c29a652014-07-18 22:55:25 +00001579 !Subtarget.isLittle());
Daniel Sandersce09d072013-08-28 12:14:50 +00001580 case Intrinsic::mips_bz_b:
1581 case Intrinsic::mips_bz_h:
1582 case Intrinsic::mips_bz_w:
1583 case Intrinsic::mips_bz_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001584 return DAG.getNode(MipsISD::VALL_ZERO, DL, Op->getValueType(0),
1585 Op->getOperand(1));
Daniel Sandersce09d072013-08-28 12:14:50 +00001586 case Intrinsic::mips_bz_v:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001587 return DAG.getNode(MipsISD::VANY_ZERO, DL, Op->getValueType(0),
1588 Op->getOperand(1));
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001589 case Intrinsic::mips_ceq_b:
1590 case Intrinsic::mips_ceq_h:
1591 case Intrinsic::mips_ceq_w:
1592 case Intrinsic::mips_ceq_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001593 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001594 Op->getOperand(2), ISD::SETEQ);
1595 case Intrinsic::mips_ceqi_b:
1596 case Intrinsic::mips_ceqi_h:
1597 case Intrinsic::mips_ceqi_w:
1598 case Intrinsic::mips_ceqi_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001599 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Simon Dardis548a53f2017-01-10 16:40:57 +00001600 lowerMSASplatImm(Op, 2, DAG, true), ISD::SETEQ);
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001601 case Intrinsic::mips_cle_s_b:
1602 case Intrinsic::mips_cle_s_h:
1603 case Intrinsic::mips_cle_s_w:
1604 case Intrinsic::mips_cle_s_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001605 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001606 Op->getOperand(2), ISD::SETLE);
1607 case Intrinsic::mips_clei_s_b:
1608 case Intrinsic::mips_clei_s_h:
1609 case Intrinsic::mips_clei_s_w:
1610 case Intrinsic::mips_clei_s_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001611 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Simon Dardis548a53f2017-01-10 16:40:57 +00001612 lowerMSASplatImm(Op, 2, DAG, true), ISD::SETLE);
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001613 case Intrinsic::mips_cle_u_b:
1614 case Intrinsic::mips_cle_u_h:
1615 case Intrinsic::mips_cle_u_w:
1616 case Intrinsic::mips_cle_u_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001617 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001618 Op->getOperand(2), ISD::SETULE);
1619 case Intrinsic::mips_clei_u_b:
1620 case Intrinsic::mips_clei_u_h:
1621 case Intrinsic::mips_clei_u_w:
1622 case Intrinsic::mips_clei_u_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001623 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001624 lowerMSASplatImm(Op, 2, DAG), ISD::SETULE);
1625 case Intrinsic::mips_clt_s_b:
1626 case Intrinsic::mips_clt_s_h:
1627 case Intrinsic::mips_clt_s_w:
1628 case Intrinsic::mips_clt_s_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001629 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001630 Op->getOperand(2), ISD::SETLT);
1631 case Intrinsic::mips_clti_s_b:
1632 case Intrinsic::mips_clti_s_h:
1633 case Intrinsic::mips_clti_s_w:
1634 case Intrinsic::mips_clti_s_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001635 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Simon Dardis548a53f2017-01-10 16:40:57 +00001636 lowerMSASplatImm(Op, 2, DAG, true), ISD::SETLT);
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001637 case Intrinsic::mips_clt_u_b:
1638 case Intrinsic::mips_clt_u_h:
1639 case Intrinsic::mips_clt_u_w:
1640 case Intrinsic::mips_clt_u_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001641 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001642 Op->getOperand(2), ISD::SETULT);
1643 case Intrinsic::mips_clti_u_b:
1644 case Intrinsic::mips_clti_u_h:
1645 case Intrinsic::mips_clti_u_w:
1646 case Intrinsic::mips_clti_u_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001647 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001648 lowerMSASplatImm(Op, 2, DAG), ISD::SETULT);
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +00001649 case Intrinsic::mips_copy_s_b:
1650 case Intrinsic::mips_copy_s_h:
1651 case Intrinsic::mips_copy_s_w:
1652 return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_SEXT_ELT);
Daniel Sanders7f3d9462013-09-27 13:04:21 +00001653 case Intrinsic::mips_copy_s_d:
Eric Christopher1c29a652014-07-18 22:55:25 +00001654 if (Subtarget.hasMips64())
Matheus Almeida74070322014-01-29 14:05:28 +00001655 // Lower directly into VEXTRACT_SEXT_ELT since i64 is legal on Mips64.
1656 return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_SEXT_ELT);
1657 else {
1658 // Lower into the generic EXTRACT_VECTOR_ELT node and let the type
1659 // legalizer and EXTRACT_VECTOR_ELT lowering sort it out.
1660 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(Op),
1661 Op->getValueType(0), Op->getOperand(1),
1662 Op->getOperand(2));
1663 }
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +00001664 case Intrinsic::mips_copy_u_b:
1665 case Intrinsic::mips_copy_u_h:
1666 case Intrinsic::mips_copy_u_w:
1667 return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_ZEXT_ELT);
Daniel Sanders7f3d9462013-09-27 13:04:21 +00001668 case Intrinsic::mips_copy_u_d:
Eric Christopher1c29a652014-07-18 22:55:25 +00001669 if (Subtarget.hasMips64())
Matheus Almeida74070322014-01-29 14:05:28 +00001670 // Lower directly into VEXTRACT_ZEXT_ELT since i64 is legal on Mips64.
1671 return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_ZEXT_ELT);
1672 else {
1673 // Lower into the generic EXTRACT_VECTOR_ELT node and let the type
1674 // legalizer and EXTRACT_VECTOR_ELT lowering sort it out.
1675 // Note: When i64 is illegal, this results in copy_s.w instructions
1676 // instead of copy_u.w instructions. This makes no difference to the
1677 // behaviour since i64 is only illegal when the register file is 32-bit.
1678 return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(Op),
1679 Op->getValueType(0), Op->getOperand(1),
1680 Op->getOperand(2));
1681 }
Daniel Sanders607952b2013-09-11 10:38:58 +00001682 case Intrinsic::mips_div_s_b:
1683 case Intrinsic::mips_div_s_h:
1684 case Intrinsic::mips_div_s_w:
1685 case Intrinsic::mips_div_s_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001686 return DAG.getNode(ISD::SDIV, DL, Op->getValueType(0), Op->getOperand(1),
1687 Op->getOperand(2));
Daniel Sanders607952b2013-09-11 10:38:58 +00001688 case Intrinsic::mips_div_u_b:
1689 case Intrinsic::mips_div_u_h:
1690 case Intrinsic::mips_div_u_w:
1691 case Intrinsic::mips_div_u_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001692 return DAG.getNode(ISD::UDIV, DL, Op->getValueType(0), Op->getOperand(1),
1693 Op->getOperand(2));
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001694 case Intrinsic::mips_fadd_w:
Eugene Zelenko79220eae2017-08-03 22:12:30 +00001695 case Intrinsic::mips_fadd_d:
Sanjay Patela2607012015-09-16 16:31:21 +00001696 // TODO: If intrinsics have fast-math-flags, propagate them.
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001697 return DAG.getNode(ISD::FADD, DL, Op->getValueType(0), Op->getOperand(1),
1698 Op->getOperand(2));
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001699 // Don't lower mips_fcaf_[wd] since LLVM folds SETFALSE condcodes away
1700 case Intrinsic::mips_fceq_w:
1701 case Intrinsic::mips_fceq_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001702 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001703 Op->getOperand(2), ISD::SETOEQ);
1704 case Intrinsic::mips_fcle_w:
1705 case Intrinsic::mips_fcle_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001706 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001707 Op->getOperand(2), ISD::SETOLE);
1708 case Intrinsic::mips_fclt_w:
1709 case Intrinsic::mips_fclt_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001710 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001711 Op->getOperand(2), ISD::SETOLT);
1712 case Intrinsic::mips_fcne_w:
1713 case Intrinsic::mips_fcne_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001714 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001715 Op->getOperand(2), ISD::SETONE);
1716 case Intrinsic::mips_fcor_w:
1717 case Intrinsic::mips_fcor_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001718 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001719 Op->getOperand(2), ISD::SETO);
1720 case Intrinsic::mips_fcueq_w:
1721 case Intrinsic::mips_fcueq_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001722 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001723 Op->getOperand(2), ISD::SETUEQ);
1724 case Intrinsic::mips_fcule_w:
1725 case Intrinsic::mips_fcule_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001726 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001727 Op->getOperand(2), ISD::SETULE);
1728 case Intrinsic::mips_fcult_w:
1729 case Intrinsic::mips_fcult_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001730 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001731 Op->getOperand(2), ISD::SETULT);
1732 case Intrinsic::mips_fcun_w:
1733 case Intrinsic::mips_fcun_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001734 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001735 Op->getOperand(2), ISD::SETUO);
1736 case Intrinsic::mips_fcune_w:
1737 case Intrinsic::mips_fcune_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001738 return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1),
Daniel Sandersfd538dc2013-09-24 10:46:19 +00001739 Op->getOperand(2), ISD::SETUNE);
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001740 case Intrinsic::mips_fdiv_w:
Eugene Zelenko79220eae2017-08-03 22:12:30 +00001741 case Intrinsic::mips_fdiv_d:
Sanjay Patela2607012015-09-16 16:31:21 +00001742 // TODO: If intrinsics have fast-math-flags, propagate them.
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001743 return DAG.getNode(ISD::FDIV, DL, Op->getValueType(0), Op->getOperand(1),
1744 Op->getOperand(2));
Daniel Sanders015972b2013-10-11 10:00:06 +00001745 case Intrinsic::mips_ffint_u_w:
1746 case Intrinsic::mips_ffint_u_d:
1747 return DAG.getNode(ISD::UINT_TO_FP, DL, Op->getValueType(0),
1748 Op->getOperand(1));
1749 case Intrinsic::mips_ffint_s_w:
1750 case Intrinsic::mips_ffint_s_d:
1751 return DAG.getNode(ISD::SINT_TO_FP, DL, Op->getValueType(0),
1752 Op->getOperand(1));
Daniel Sanders7a289d02013-09-23 12:02:46 +00001753 case Intrinsic::mips_fill_b:
1754 case Intrinsic::mips_fill_h:
Daniel Sandersc72593e2013-09-27 13:20:41 +00001755 case Intrinsic::mips_fill_w:
1756 case Intrinsic::mips_fill_d: {
Daniel Sandersf49dd822013-09-24 13:33:07 +00001757 EVT ResTy = Op->getValueType(0);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001758 SmallVector<SDValue, 16> Ops(ResTy.getVectorNumElements(),
1759 Op->getOperand(1));
Daniel Sandersf49dd822013-09-24 13:33:07 +00001760
Daniel Sandersc72593e2013-09-27 13:20:41 +00001761 // If ResTy is v2i64 then the type legalizer will break this node down into
1762 // an equivalent v4i32.
Ahmed Bougacha128f8732016-04-26 21:15:30 +00001763 return DAG.getBuildVector(ResTy, DL, Ops);
Daniel Sandersf49dd822013-09-24 13:33:07 +00001764 }
Daniel Sandersa9521602013-10-23 10:36:52 +00001765 case Intrinsic::mips_fexp2_w:
1766 case Intrinsic::mips_fexp2_d: {
Sanjay Patela2607012015-09-16 16:31:21 +00001767 // TODO: If intrinsics have fast-math-flags, propagate them.
Daniel Sandersa9521602013-10-23 10:36:52 +00001768 EVT ResTy = Op->getValueType(0);
1769 return DAG.getNode(
1770 ISD::FMUL, SDLoc(Op), ResTy, Op->getOperand(1),
1771 DAG.getNode(ISD::FEXP2, SDLoc(Op), ResTy, Op->getOperand(2)));
1772 }
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001773 case Intrinsic::mips_flog2_w:
1774 case Intrinsic::mips_flog2_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001775 return DAG.getNode(ISD::FLOG2, DL, Op->getValueType(0), Op->getOperand(1));
Daniel Sandersd7103f32013-10-11 10:14:25 +00001776 case Intrinsic::mips_fmadd_w:
1777 case Intrinsic::mips_fmadd_d:
1778 return DAG.getNode(ISD::FMA, SDLoc(Op), Op->getValueType(0),
1779 Op->getOperand(1), Op->getOperand(2), Op->getOperand(3));
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001780 case Intrinsic::mips_fmul_w:
Eugene Zelenko79220eae2017-08-03 22:12:30 +00001781 case Intrinsic::mips_fmul_d:
Sanjay Patela2607012015-09-16 16:31:21 +00001782 // TODO: If intrinsics have fast-math-flags, propagate them.
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001783 return DAG.getNode(ISD::FMUL, DL, Op->getValueType(0), Op->getOperand(1),
1784 Op->getOperand(2));
Daniel Sanderse67bd872013-10-11 10:27:32 +00001785 case Intrinsic::mips_fmsub_w:
1786 case Intrinsic::mips_fmsub_d: {
Sanjay Patela2607012015-09-16 16:31:21 +00001787 // TODO: If intrinsics have fast-math-flags, propagate them.
Daniel Sanderse67bd872013-10-11 10:27:32 +00001788 EVT ResTy = Op->getValueType(0);
1789 return DAG.getNode(ISD::FSUB, SDLoc(Op), ResTy, Op->getOperand(1),
1790 DAG.getNode(ISD::FMUL, SDLoc(Op), ResTy,
1791 Op->getOperand(2), Op->getOperand(3)));
1792 }
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001793 case Intrinsic::mips_frint_w:
1794 case Intrinsic::mips_frint_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001795 return DAG.getNode(ISD::FRINT, DL, Op->getValueType(0), Op->getOperand(1));
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001796 case Intrinsic::mips_fsqrt_w:
1797 case Intrinsic::mips_fsqrt_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001798 return DAG.getNode(ISD::FSQRT, DL, Op->getValueType(0), Op->getOperand(1));
Daniel Sandersf5bd9372013-09-11 10:51:30 +00001799 case Intrinsic::mips_fsub_w:
Eugene Zelenko79220eae2017-08-03 22:12:30 +00001800 case Intrinsic::mips_fsub_d:
Sanjay Patela2607012015-09-16 16:31:21 +00001801 // TODO: If intrinsics have fast-math-flags, propagate them.
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001802 return DAG.getNode(ISD::FSUB, DL, Op->getValueType(0), Op->getOperand(1),
1803 Op->getOperand(2));
Daniel Sanders015972b2013-10-11 10:00:06 +00001804 case Intrinsic::mips_ftrunc_u_w:
1805 case Intrinsic::mips_ftrunc_u_d:
1806 return DAG.getNode(ISD::FP_TO_UINT, DL, Op->getValueType(0),
1807 Op->getOperand(1));
1808 case Intrinsic::mips_ftrunc_s_w:
1809 case Intrinsic::mips_ftrunc_s_d:
1810 return DAG.getNode(ISD::FP_TO_SINT, DL, Op->getValueType(0),
1811 Op->getOperand(1));
Daniel Sanders2ed228b2013-09-24 14:36:12 +00001812 case Intrinsic::mips_ilvev_b:
1813 case Intrinsic::mips_ilvev_h:
1814 case Intrinsic::mips_ilvev_w:
1815 case Intrinsic::mips_ilvev_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001816 return DAG.getNode(MipsISD::ILVEV, DL, Op->getValueType(0),
Daniel Sanders2ed228b2013-09-24 14:36:12 +00001817 Op->getOperand(1), Op->getOperand(2));
1818 case Intrinsic::mips_ilvl_b:
1819 case Intrinsic::mips_ilvl_h:
1820 case Intrinsic::mips_ilvl_w:
1821 case Intrinsic::mips_ilvl_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001822 return DAG.getNode(MipsISD::ILVL, DL, Op->getValueType(0),
Daniel Sanders2ed228b2013-09-24 14:36:12 +00001823 Op->getOperand(1), Op->getOperand(2));
1824 case Intrinsic::mips_ilvod_b:
1825 case Intrinsic::mips_ilvod_h:
1826 case Intrinsic::mips_ilvod_w:
1827 case Intrinsic::mips_ilvod_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001828 return DAG.getNode(MipsISD::ILVOD, DL, Op->getValueType(0),
Daniel Sanders2ed228b2013-09-24 14:36:12 +00001829 Op->getOperand(1), Op->getOperand(2));
1830 case Intrinsic::mips_ilvr_b:
1831 case Intrinsic::mips_ilvr_h:
1832 case Intrinsic::mips_ilvr_w:
1833 case Intrinsic::mips_ilvr_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001834 return DAG.getNode(MipsISD::ILVR, DL, Op->getValueType(0),
Daniel Sanders2ed228b2013-09-24 14:36:12 +00001835 Op->getOperand(1), Op->getOperand(2));
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +00001836 case Intrinsic::mips_insert_b:
1837 case Intrinsic::mips_insert_h:
1838 case Intrinsic::mips_insert_w:
Daniel Sanders6098b332013-09-27 13:36:54 +00001839 case Intrinsic::mips_insert_d:
1840 return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(Op), Op->getValueType(0),
1841 Op->getOperand(1), Op->getOperand(3), Op->getOperand(2));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001842 case Intrinsic::mips_insve_b:
1843 case Intrinsic::mips_insve_h:
1844 case Intrinsic::mips_insve_w:
Simon Dardis548a53f2017-01-10 16:40:57 +00001845 case Intrinsic::mips_insve_d: {
1846 // Report an error for out of range values.
1847 int64_t Max;
1848 switch (Intrinsic) {
1849 case Intrinsic::mips_insve_b: Max = 15; break;
1850 case Intrinsic::mips_insve_h: Max = 7; break;
1851 case Intrinsic::mips_insve_w: Max = 3; break;
1852 case Intrinsic::mips_insve_d: Max = 1; break;
1853 default: llvm_unreachable("Unmatched intrinsic");
1854 }
1855 int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
1856 if (Value < 0 || Value > Max)
1857 report_fatal_error("Immediate out of range");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001858 return DAG.getNode(MipsISD::INSVE, DL, Op->getValueType(0),
1859 Op->getOperand(1), Op->getOperand(2), Op->getOperand(3),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001860 DAG.getConstant(0, DL, MVT::i32));
Simon Dardis548a53f2017-01-10 16:40:57 +00001861 }
Daniel Sanders7a289d02013-09-23 12:02:46 +00001862 case Intrinsic::mips_ldi_b:
1863 case Intrinsic::mips_ldi_h:
1864 case Intrinsic::mips_ldi_w:
1865 case Intrinsic::mips_ldi_d:
Simon Dardis548a53f2017-01-10 16:40:57 +00001866 return lowerMSASplatImm(Op, 1, DAG, true);
Matheus Almeida4b27eb52014-02-10 12:05:17 +00001867 case Intrinsic::mips_lsa:
1868 case Intrinsic::mips_dlsa: {
Daniel Sandersa4eaf592013-10-17 13:38:20 +00001869 EVT ResTy = Op->getValueType(0);
1870 return DAG.getNode(ISD::ADD, SDLoc(Op), ResTy, Op->getOperand(1),
1871 DAG.getNode(ISD::SHL, SDLoc(Op), ResTy,
1872 Op->getOperand(2), Op->getOperand(3)));
1873 }
Daniel Sanders50e5ed32013-10-11 10:50:42 +00001874 case Intrinsic::mips_maddv_b:
1875 case Intrinsic::mips_maddv_h:
1876 case Intrinsic::mips_maddv_w:
1877 case Intrinsic::mips_maddv_d: {
1878 EVT ResTy = Op->getValueType(0);
1879 return DAG.getNode(ISD::ADD, SDLoc(Op), ResTy, Op->getOperand(1),
1880 DAG.getNode(ISD::MUL, SDLoc(Op), ResTy,
1881 Op->getOperand(2), Op->getOperand(3)));
1882 }
Daniel Sanders3ce56622013-09-24 12:18:31 +00001883 case Intrinsic::mips_max_s_b:
1884 case Intrinsic::mips_max_s_h:
1885 case Intrinsic::mips_max_s_w:
1886 case Intrinsic::mips_max_s_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001887 return DAG.getNode(ISD::SMAX, DL, Op->getValueType(0),
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001888 Op->getOperand(1), Op->getOperand(2));
Daniel Sanders3ce56622013-09-24 12:18:31 +00001889 case Intrinsic::mips_max_u_b:
1890 case Intrinsic::mips_max_u_h:
1891 case Intrinsic::mips_max_u_w:
1892 case Intrinsic::mips_max_u_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001893 return DAG.getNode(ISD::UMAX, DL, Op->getValueType(0),
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001894 Op->getOperand(1), Op->getOperand(2));
Daniel Sanders3ce56622013-09-24 12:18:31 +00001895 case Intrinsic::mips_maxi_s_b:
1896 case Intrinsic::mips_maxi_s_h:
1897 case Intrinsic::mips_maxi_s_w:
1898 case Intrinsic::mips_maxi_s_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001899 return DAG.getNode(ISD::SMAX, DL, Op->getValueType(0),
Simon Dardis548a53f2017-01-10 16:40:57 +00001900 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG, true));
Daniel Sanders3ce56622013-09-24 12:18:31 +00001901 case Intrinsic::mips_maxi_u_b:
1902 case Intrinsic::mips_maxi_u_h:
1903 case Intrinsic::mips_maxi_u_w:
1904 case Intrinsic::mips_maxi_u_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001905 return DAG.getNode(ISD::UMAX, DL, Op->getValueType(0),
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001906 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Daniel Sanders3ce56622013-09-24 12:18:31 +00001907 case Intrinsic::mips_min_s_b:
1908 case Intrinsic::mips_min_s_h:
1909 case Intrinsic::mips_min_s_w:
1910 case Intrinsic::mips_min_s_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001911 return DAG.getNode(ISD::SMIN, DL, Op->getValueType(0),
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001912 Op->getOperand(1), Op->getOperand(2));
Daniel Sanders3ce56622013-09-24 12:18:31 +00001913 case Intrinsic::mips_min_u_b:
1914 case Intrinsic::mips_min_u_h:
1915 case Intrinsic::mips_min_u_w:
1916 case Intrinsic::mips_min_u_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001917 return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0),
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001918 Op->getOperand(1), Op->getOperand(2));
Daniel Sanders3ce56622013-09-24 12:18:31 +00001919 case Intrinsic::mips_mini_s_b:
1920 case Intrinsic::mips_mini_s_h:
1921 case Intrinsic::mips_mini_s_w:
1922 case Intrinsic::mips_mini_s_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001923 return DAG.getNode(ISD::SMIN, DL, Op->getValueType(0),
Simon Dardis548a53f2017-01-10 16:40:57 +00001924 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG, true));
Daniel Sanders3ce56622013-09-24 12:18:31 +00001925 case Intrinsic::mips_mini_u_b:
1926 case Intrinsic::mips_mini_u_h:
1927 case Intrinsic::mips_mini_u_w:
1928 case Intrinsic::mips_mini_u_d:
Simon Pilgrim386b8dd2018-02-17 21:29:45 +00001929 return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0),
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001930 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Daniel Sanders0210dd42013-10-01 10:22:35 +00001931 case Intrinsic::mips_mod_s_b:
1932 case Intrinsic::mips_mod_s_h:
1933 case Intrinsic::mips_mod_s_w:
1934 case Intrinsic::mips_mod_s_d:
1935 return DAG.getNode(ISD::SREM, DL, Op->getValueType(0), Op->getOperand(1),
1936 Op->getOperand(2));
1937 case Intrinsic::mips_mod_u_b:
1938 case Intrinsic::mips_mod_u_h:
1939 case Intrinsic::mips_mod_u_w:
1940 case Intrinsic::mips_mod_u_d:
1941 return DAG.getNode(ISD::UREM, DL, Op->getValueType(0), Op->getOperand(1),
1942 Op->getOperand(2));
Daniel Sandersfbcb5822013-09-11 11:58:30 +00001943 case Intrinsic::mips_mulv_b:
1944 case Intrinsic::mips_mulv_h:
1945 case Intrinsic::mips_mulv_w:
1946 case Intrinsic::mips_mulv_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001947 return DAG.getNode(ISD::MUL, DL, Op->getValueType(0), Op->getOperand(1),
1948 Op->getOperand(2));
Daniel Sanders50e5ed32013-10-11 10:50:42 +00001949 case Intrinsic::mips_msubv_b:
1950 case Intrinsic::mips_msubv_h:
1951 case Intrinsic::mips_msubv_w:
1952 case Intrinsic::mips_msubv_d: {
1953 EVT ResTy = Op->getValueType(0);
1954 return DAG.getNode(ISD::SUB, SDLoc(Op), ResTy, Op->getOperand(1),
1955 DAG.getNode(ISD::MUL, SDLoc(Op), ResTy,
1956 Op->getOperand(2), Op->getOperand(3)));
1957 }
Daniel Sandersfbcb5822013-09-11 11:58:30 +00001958 case Intrinsic::mips_nlzc_b:
1959 case Intrinsic::mips_nlzc_h:
1960 case Intrinsic::mips_nlzc_w:
1961 case Intrinsic::mips_nlzc_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001962 return DAG.getNode(ISD::CTLZ, DL, Op->getValueType(0), Op->getOperand(1));
Daniel Sandersf7456c72013-09-23 13:22:24 +00001963 case Intrinsic::mips_nor_v: {
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001964 SDValue Res = DAG.getNode(ISD::OR, DL, Op->getValueType(0),
1965 Op->getOperand(1), Op->getOperand(2));
1966 return DAG.getNOT(DL, Res, Res->getValueType(0));
Daniel Sandersf7456c72013-09-23 13:22:24 +00001967 }
Daniel Sandersbfc39ce2013-09-24 12:32:47 +00001968 case Intrinsic::mips_nori_b: {
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001969 SDValue Res = DAG.getNode(ISD::OR, DL, Op->getValueType(0),
1970 Op->getOperand(1),
1971 lowerMSASplatImm(Op, 2, DAG));
1972 return DAG.getNOT(DL, Res, Res->getValueType(0));
Daniel Sandersbfc39ce2013-09-24 12:32:47 +00001973 }
Daniel Sanders8ca81e42013-09-23 12:57:42 +00001974 case Intrinsic::mips_or_v:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001975 return DAG.getNode(ISD::OR, DL, Op->getValueType(0), Op->getOperand(1),
1976 Op->getOperand(2));
Daniel Sandersbfc39ce2013-09-24 12:32:47 +00001977 case Intrinsic::mips_ori_b:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001978 return DAG.getNode(ISD::OR, DL, Op->getValueType(0),
1979 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00001980 case Intrinsic::mips_pckev_b:
1981 case Intrinsic::mips_pckev_h:
1982 case Intrinsic::mips_pckev_w:
1983 case Intrinsic::mips_pckev_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001984 return DAG.getNode(MipsISD::PCKEV, DL, Op->getValueType(0),
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00001985 Op->getOperand(1), Op->getOperand(2));
1986 case Intrinsic::mips_pckod_b:
1987 case Intrinsic::mips_pckod_h:
1988 case Intrinsic::mips_pckod_w:
1989 case Intrinsic::mips_pckod_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001990 return DAG.getNode(MipsISD::PCKOD, DL, Op->getValueType(0),
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00001991 Op->getOperand(1), Op->getOperand(2));
Daniel Sanders766cb692013-09-23 13:40:21 +00001992 case Intrinsic::mips_pcnt_b:
1993 case Intrinsic::mips_pcnt_h:
1994 case Intrinsic::mips_pcnt_w:
1995 case Intrinsic::mips_pcnt_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00001996 return DAG.getNode(ISD::CTPOP, DL, Op->getValueType(0), Op->getOperand(1));
Simon Dardis548a53f2017-01-10 16:40:57 +00001997 case Intrinsic::mips_sat_s_b:
1998 case Intrinsic::mips_sat_s_h:
1999 case Intrinsic::mips_sat_s_w:
2000 case Intrinsic::mips_sat_s_d:
2001 case Intrinsic::mips_sat_u_b:
2002 case Intrinsic::mips_sat_u_h:
2003 case Intrinsic::mips_sat_u_w:
2004 case Intrinsic::mips_sat_u_d: {
2005 // Report an error for out of range values.
2006 int64_t Max;
2007 switch (Intrinsic) {
2008 case Intrinsic::mips_sat_s_b:
2009 case Intrinsic::mips_sat_u_b: Max = 7; break;
2010 case Intrinsic::mips_sat_s_h:
2011 case Intrinsic::mips_sat_u_h: Max = 15; break;
2012 case Intrinsic::mips_sat_s_w:
2013 case Intrinsic::mips_sat_u_w: Max = 31; break;
2014 case Intrinsic::mips_sat_s_d:
2015 case Intrinsic::mips_sat_u_d: Max = 63; break;
2016 default: llvm_unreachable("Unmatched intrinsic");
2017 }
2018 int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
2019 if (Value < 0 || Value > Max)
2020 report_fatal_error("Immediate out of range");
2021 return SDValue();
2022 }
Daniel Sanders26307182013-09-24 14:20:00 +00002023 case Intrinsic::mips_shf_b:
2024 case Intrinsic::mips_shf_h:
Simon Dardis548a53f2017-01-10 16:40:57 +00002025 case Intrinsic::mips_shf_w: {
2026 int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
2027 if (Value < 0 || Value > 255)
2028 report_fatal_error("Immediate out of range");
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002029 return DAG.getNode(MipsISD::SHF, DL, Op->getValueType(0),
Daniel Sanders26307182013-09-24 14:20:00 +00002030 Op->getOperand(2), Op->getOperand(1));
Simon Dardis548a53f2017-01-10 16:40:57 +00002031 }
2032 case Intrinsic::mips_sldi_b:
2033 case Intrinsic::mips_sldi_h:
2034 case Intrinsic::mips_sldi_w:
2035 case Intrinsic::mips_sldi_d: {
2036 // Report an error for out of range values.
2037 int64_t Max;
2038 switch (Intrinsic) {
2039 case Intrinsic::mips_sldi_b: Max = 15; break;
2040 case Intrinsic::mips_sldi_h: Max = 7; break;
2041 case Intrinsic::mips_sldi_w: Max = 3; break;
2042 case Intrinsic::mips_sldi_d: Max = 1; break;
2043 default: llvm_unreachable("Unmatched intrinsic");
2044 }
2045 int64_t Value = cast<ConstantSDNode>(Op->getOperand(3))->getSExtValue();
2046 if (Value < 0 || Value > Max)
2047 report_fatal_error("Immediate out of range");
2048 return SDValue();
2049 }
Daniel Sandersfbcb5822013-09-11 11:58:30 +00002050 case Intrinsic::mips_sll_b:
2051 case Intrinsic::mips_sll_h:
2052 case Intrinsic::mips_sll_w:
2053 case Intrinsic::mips_sll_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002054 return DAG.getNode(ISD::SHL, DL, Op->getValueType(0), Op->getOperand(1),
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00002055 truncateVecElts(Op, DAG));
Daniel Sanderscba19222013-09-24 10:28:18 +00002056 case Intrinsic::mips_slli_b:
2057 case Intrinsic::mips_slli_h:
2058 case Intrinsic::mips_slli_w:
2059 case Intrinsic::mips_slli_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002060 return DAG.getNode(ISD::SHL, DL, Op->getValueType(0),
2061 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Daniel Sanderse7ef0c82013-10-30 13:07:44 +00002062 case Intrinsic::mips_splat_b:
2063 case Intrinsic::mips_splat_h:
2064 case Intrinsic::mips_splat_w:
2065 case Intrinsic::mips_splat_d:
2066 // We can't lower via VECTOR_SHUFFLE because it requires constant shuffle
2067 // masks, nor can we lower via BUILD_VECTOR & EXTRACT_VECTOR_ELT because
2068 // EXTRACT_VECTOR_ELT can't extract i64's on MIPS32.
2069 // Instead we lower to MipsISD::VSHF and match from there.
2070 return DAG.getNode(MipsISD::VSHF, DL, Op->getValueType(0),
Daniel Sanders50b80412013-11-15 12:56:49 +00002071 lowerMSASplatZExt(Op, 2, DAG), Op->getOperand(1),
Daniel Sanderse7ef0c82013-10-30 13:07:44 +00002072 Op->getOperand(1));
Daniel Sanders7e51fe12013-09-27 11:48:57 +00002073 case Intrinsic::mips_splati_b:
2074 case Intrinsic::mips_splati_h:
2075 case Intrinsic::mips_splati_w:
2076 case Intrinsic::mips_splati_d:
2077 return DAG.getNode(MipsISD::VSHF, DL, Op->getValueType(0),
2078 lowerMSASplatImm(Op, 2, DAG), Op->getOperand(1),
2079 Op->getOperand(1));
Daniel Sandersfbcb5822013-09-11 11:58:30 +00002080 case Intrinsic::mips_sra_b:
2081 case Intrinsic::mips_sra_h:
2082 case Intrinsic::mips_sra_w:
2083 case Intrinsic::mips_sra_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002084 return DAG.getNode(ISD::SRA, DL, Op->getValueType(0), Op->getOperand(1),
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00002085 truncateVecElts(Op, DAG));
Daniel Sanderscba19222013-09-24 10:28:18 +00002086 case Intrinsic::mips_srai_b:
2087 case Intrinsic::mips_srai_h:
2088 case Intrinsic::mips_srai_w:
2089 case Intrinsic::mips_srai_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002090 return DAG.getNode(ISD::SRA, DL, Op->getValueType(0),
2091 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Simon Dardis548a53f2017-01-10 16:40:57 +00002092 case Intrinsic::mips_srari_b:
2093 case Intrinsic::mips_srari_h:
2094 case Intrinsic::mips_srari_w:
2095 case Intrinsic::mips_srari_d: {
2096 // Report an error for out of range values.
2097 int64_t Max;
2098 switch (Intrinsic) {
2099 case Intrinsic::mips_srari_b: Max = 7; break;
2100 case Intrinsic::mips_srari_h: Max = 15; break;
2101 case Intrinsic::mips_srari_w: Max = 31; break;
2102 case Intrinsic::mips_srari_d: Max = 63; break;
2103 default: llvm_unreachable("Unmatched intrinsic");
2104 }
2105 int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
2106 if (Value < 0 || Value > Max)
2107 report_fatal_error("Immediate out of range");
2108 return SDValue();
2109 }
Daniel Sandersfbcb5822013-09-11 11:58:30 +00002110 case Intrinsic::mips_srl_b:
2111 case Intrinsic::mips_srl_h:
2112 case Intrinsic::mips_srl_w:
2113 case Intrinsic::mips_srl_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002114 return DAG.getNode(ISD::SRL, DL, Op->getValueType(0), Op->getOperand(1),
Petar Jovanovic2b6fe3f2017-04-20 13:26:46 +00002115 truncateVecElts(Op, DAG));
Daniel Sanderscba19222013-09-24 10:28:18 +00002116 case Intrinsic::mips_srli_b:
2117 case Intrinsic::mips_srli_h:
2118 case Intrinsic::mips_srli_w:
2119 case Intrinsic::mips_srli_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002120 return DAG.getNode(ISD::SRL, DL, Op->getValueType(0),
2121 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Simon Dardis548a53f2017-01-10 16:40:57 +00002122 case Intrinsic::mips_srlri_b:
2123 case Intrinsic::mips_srlri_h:
2124 case Intrinsic::mips_srlri_w:
2125 case Intrinsic::mips_srlri_d: {
2126 // Report an error for out of range values.
2127 int64_t Max;
2128 switch (Intrinsic) {
2129 case Intrinsic::mips_srlri_b: Max = 7; break;
2130 case Intrinsic::mips_srlri_h: Max = 15; break;
2131 case Intrinsic::mips_srlri_w: Max = 31; break;
2132 case Intrinsic::mips_srlri_d: Max = 63; break;
2133 default: llvm_unreachable("Unmatched intrinsic");
2134 }
2135 int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue();
2136 if (Value < 0 || Value > Max)
2137 report_fatal_error("Immediate out of range");
2138 return SDValue();
2139 }
Daniel Sandersfbcb5822013-09-11 11:58:30 +00002140 case Intrinsic::mips_subv_b:
2141 case Intrinsic::mips_subv_h:
2142 case Intrinsic::mips_subv_w:
2143 case Intrinsic::mips_subv_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002144 return DAG.getNode(ISD::SUB, DL, Op->getValueType(0), Op->getOperand(1),
2145 Op->getOperand(2));
Daniel Sanders86d0c8d2013-09-23 14:29:55 +00002146 case Intrinsic::mips_subvi_b:
2147 case Intrinsic::mips_subvi_h:
2148 case Intrinsic::mips_subvi_w:
2149 case Intrinsic::mips_subvi_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002150 return DAG.getNode(ISD::SUB, DL, Op->getValueType(0),
2151 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Daniel Sanderse5087042013-09-24 14:02:15 +00002152 case Intrinsic::mips_vshf_b:
2153 case Intrinsic::mips_vshf_h:
2154 case Intrinsic::mips_vshf_w:
2155 case Intrinsic::mips_vshf_d:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002156 return DAG.getNode(MipsISD::VSHF, DL, Op->getValueType(0),
Daniel Sanderse5087042013-09-24 14:02:15 +00002157 Op->getOperand(1), Op->getOperand(2), Op->getOperand(3));
Daniel Sanders8ca81e42013-09-23 12:57:42 +00002158 case Intrinsic::mips_xor_v:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002159 return DAG.getNode(ISD::XOR, DL, Op->getValueType(0), Op->getOperand(1),
2160 Op->getOperand(2));
Daniel Sandersbfc39ce2013-09-24 12:32:47 +00002161 case Intrinsic::mips_xori_b:
Daniel Sanders84e7caf2013-09-27 10:25:41 +00002162 return DAG.getNode(ISD::XOR, DL, Op->getValueType(0),
2163 Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
Marcin Koscielnicki7efdca52016-04-27 17:21:49 +00002164 case Intrinsic::thread_pointer: {
2165 EVT PtrVT = getPointerTy(DAG.getDataLayout());
2166 return DAG.getNode(MipsISD::ThreadPointer, DL, PtrVT);
2167 }
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00002168 }
2169}
2170
Simon Dardis548a53f2017-01-10 16:40:57 +00002171static SDValue lowerMSALoadIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr,
2172 const MipsSubtarget &Subtarget) {
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002173 SDLoc DL(Op);
2174 SDValue ChainIn = Op->getOperand(0);
2175 SDValue Address = Op->getOperand(2);
2176 SDValue Offset = Op->getOperand(3);
2177 EVT ResTy = Op->getValueType(0);
2178 EVT PtrTy = Address->getValueType(0);
2179
Simon Dardis548a53f2017-01-10 16:40:57 +00002180 // For N64 addresses have the underlying type MVT::i64. This intrinsic
2181 // however takes an i32 signed constant offset. The actual type of the
2182 // intrinsic is a scaled signed i10.
2183 if (Subtarget.isABI_N64())
2184 Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset);
2185
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002186 Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset);
Justin Lebar9c375812016-07-15 18:27:10 +00002187 return DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(),
2188 /* Alignment = */ 16);
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002189}
2190
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00002191SDValue MipsSETargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,
2192 SelectionDAG &DAG) const {
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002193 unsigned Intr = cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue();
2194 switch (Intr) {
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00002195 default:
2196 return SDValue();
2197 case Intrinsic::mips_extp:
2198 return lowerDSPIntr(Op, DAG, MipsISD::EXTP);
2199 case Intrinsic::mips_extpdp:
2200 return lowerDSPIntr(Op, DAG, MipsISD::EXTPDP);
2201 case Intrinsic::mips_extr_w:
2202 return lowerDSPIntr(Op, DAG, MipsISD::EXTR_W);
2203 case Intrinsic::mips_extr_r_w:
2204 return lowerDSPIntr(Op, DAG, MipsISD::EXTR_R_W);
2205 case Intrinsic::mips_extr_rs_w:
2206 return lowerDSPIntr(Op, DAG, MipsISD::EXTR_RS_W);
2207 case Intrinsic::mips_extr_s_h:
2208 return lowerDSPIntr(Op, DAG, MipsISD::EXTR_S_H);
2209 case Intrinsic::mips_mthlip:
2210 return lowerDSPIntr(Op, DAG, MipsISD::MTHLIP);
2211 case Intrinsic::mips_mulsaq_s_w_ph:
2212 return lowerDSPIntr(Op, DAG, MipsISD::MULSAQ_S_W_PH);
2213 case Intrinsic::mips_maq_s_w_phl:
2214 return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHL);
2215 case Intrinsic::mips_maq_s_w_phr:
2216 return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHR);
2217 case Intrinsic::mips_maq_sa_w_phl:
2218 return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHL);
2219 case Intrinsic::mips_maq_sa_w_phr:
2220 return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHR);
2221 case Intrinsic::mips_dpaq_s_w_ph:
2222 return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_S_W_PH);
2223 case Intrinsic::mips_dpsq_s_w_ph:
2224 return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_S_W_PH);
2225 case Intrinsic::mips_dpaq_sa_l_w:
2226 return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_SA_L_W);
2227 case Intrinsic::mips_dpsq_sa_l_w:
2228 return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_SA_L_W);
2229 case Intrinsic::mips_dpaqx_s_w_ph:
2230 return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_S_W_PH);
2231 case Intrinsic::mips_dpaqx_sa_w_ph:
2232 return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_SA_W_PH);
2233 case Intrinsic::mips_dpsqx_s_w_ph:
2234 return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_S_W_PH);
2235 case Intrinsic::mips_dpsqx_sa_w_ph:
2236 return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_SA_W_PH);
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002237 case Intrinsic::mips_ld_b:
2238 case Intrinsic::mips_ld_h:
2239 case Intrinsic::mips_ld_w:
2240 case Intrinsic::mips_ld_d:
Simon Dardis548a53f2017-01-10 16:40:57 +00002241 return lowerMSALoadIntr(Op, DAG, Intr, Subtarget);
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002242 }
2243}
2244
Simon Dardis548a53f2017-01-10 16:40:57 +00002245static SDValue lowerMSAStoreIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr,
2246 const MipsSubtarget &Subtarget) {
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002247 SDLoc DL(Op);
2248 SDValue ChainIn = Op->getOperand(0);
2249 SDValue Value = Op->getOperand(2);
2250 SDValue Address = Op->getOperand(3);
2251 SDValue Offset = Op->getOperand(4);
2252 EVT PtrTy = Address->getValueType(0);
2253
Simon Dardis548a53f2017-01-10 16:40:57 +00002254 // For N64 addresses have the underlying type MVT::i64. This intrinsic
2255 // however takes an i32 signed constant offset. The actual type of the
2256 // intrinsic is a scaled signed i10.
2257 if (Subtarget.isABI_N64())
2258 Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset);
2259
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002260 Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset);
2261
Justin Lebar9c375812016-07-15 18:27:10 +00002262 return DAG.getStore(ChainIn, DL, Value, Address, MachinePointerInfo(),
2263 /* Alignment = */ 16);
Daniel Sanderse6ed5b72013-08-28 12:04:29 +00002264}
2265
2266SDValue MipsSETargetLowering::lowerINTRINSIC_VOID(SDValue Op,
2267 SelectionDAG &DAG) const {
2268 unsigned Intr = cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue();
2269 switch (Intr) {
2270 default:
2271 return SDValue();
2272 case Intrinsic::mips_st_b:
2273 case Intrinsic::mips_st_h:
2274 case Intrinsic::mips_st_w:
2275 case Intrinsic::mips_st_d:
Simon Dardis548a53f2017-01-10 16:40:57 +00002276 return lowerMSAStoreIntr(Op, DAG, Intr, Subtarget);
Akira Hatanakaa6bbde52013-04-13 02:13:30 +00002277 }
2278}
2279
Daniel Sanders7a289d02013-09-23 12:02:46 +00002280/// \brief Check if the given BuildVectorSDNode is a splat.
2281/// This method currently relies on DAG nodes being reused when equivalent,
2282/// so it's possible for this to return false even when isConstantSplat returns
2283/// true.
2284static bool isSplatVector(const BuildVectorSDNode *N) {
Daniel Sanders7a289d02013-09-23 12:02:46 +00002285 unsigned int nOps = N->getNumOperands();
Daniel Sandersab94b532013-10-30 15:20:38 +00002286 assert(nOps > 1 && "isSplatVector has 0 or 1 sized build vector");
Daniel Sanders7a289d02013-09-23 12:02:46 +00002287
2288 SDValue Operand0 = N->getOperand(0);
2289
2290 for (unsigned int i = 1; i < nOps; ++i) {
2291 if (N->getOperand(i) != Operand0)
2292 return false;
2293 }
2294
2295 return true;
2296}
2297
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +00002298// Lower ISD::EXTRACT_VECTOR_ELT into MipsISD::VEXTRACT_SEXT_ELT.
2299//
2300// The non-value bits resulting from ISD::EXTRACT_VECTOR_ELT are undefined. We
2301// choose to sign-extend but we could have equally chosen zero-extend. The
2302// DAGCombiner will fold any sign/zero extension of the ISD::EXTRACT_VECTOR_ELT
2303// result into this node later (possibly changing it to a zero-extend in the
2304// process).
2305SDValue MipsSETargetLowering::
2306lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const {
2307 SDLoc DL(Op);
2308 EVT ResTy = Op->getValueType(0);
2309 SDValue Op0 = Op->getOperand(0);
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00002310 EVT VecTy = Op0->getValueType(0);
2311
2312 if (!VecTy.is128BitVector())
2313 return SDValue();
2314
2315 if (ResTy.isInteger()) {
2316 SDValue Op1 = Op->getOperand(1);
2317 EVT EltTy = VecTy.getVectorElementType();
2318 return DAG.getNode(MipsISD::VEXTRACT_SEXT_ELT, DL, ResTy, Op0, Op1,
2319 DAG.getValueType(EltTy));
2320 }
2321
2322 return Op;
Daniel Sandersa4c8f3a2013-09-23 14:03:12 +00002323}
2324
Daniel Sandersf49dd822013-09-24 13:33:07 +00002325static bool isConstantOrUndef(const SDValue Op) {
Sanjay Patel57195842016-03-14 17:28:46 +00002326 if (Op->isUndef())
Daniel Sandersf49dd822013-09-24 13:33:07 +00002327 return true;
Vasileios Kalintiris46963f62015-02-13 19:12:16 +00002328 if (isa<ConstantSDNode>(Op))
Daniel Sandersf49dd822013-09-24 13:33:07 +00002329 return true;
Vasileios Kalintiris46963f62015-02-13 19:12:16 +00002330 if (isa<ConstantFPSDNode>(Op))
Daniel Sandersf49dd822013-09-24 13:33:07 +00002331 return true;
2332 return false;
2333}
2334
2335static bool isConstantOrUndefBUILD_VECTOR(const BuildVectorSDNode *Op) {
2336 for (unsigned i = 0; i < Op->getNumOperands(); ++i)
2337 if (isConstantOrUndef(Op->getOperand(i)))
2338 return true;
2339 return false;
2340}
2341
Daniel Sanders7a289d02013-09-23 12:02:46 +00002342// Lowers ISD::BUILD_VECTOR into appropriate SelectionDAG nodes for the
2343// backend.
2344//
2345// Lowers according to the following rules:
Daniel Sandersf49dd822013-09-24 13:33:07 +00002346// - Constant splats are legal as-is as long as the SplatBitSize is a power of
2347// 2 less than or equal to 64 and the value fits into a signed 10-bit
2348// immediate
2349// - Constant splats are lowered to bitconverted BUILD_VECTORs if SplatBitSize
2350// is a power of 2 less than or equal to 64 and the value does not fit into a
2351// signed 10-bit immediate
2352// - Non-constant splats are legal as-is.
2353// - Non-constant non-splats are lowered to sequences of INSERT_VECTOR_ELT.
2354// - All others are illegal and must be expanded.
Daniel Sanders7a289d02013-09-23 12:02:46 +00002355SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op,
2356 SelectionDAG &DAG) const {
2357 BuildVectorSDNode *Node = cast<BuildVectorSDNode>(Op);
2358 EVT ResTy = Op->getValueType(0);
2359 SDLoc DL(Op);
2360 APInt SplatValue, SplatUndef;
2361 unsigned SplatBitSize;
2362 bool HasAnyUndefs;
2363
Eric Christopher1c29a652014-07-18 22:55:25 +00002364 if (!Subtarget.hasMSA() || !ResTy.is128BitVector())
Daniel Sanders7a289d02013-09-23 12:02:46 +00002365 return SDValue();
2366
2367 if (Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
2368 HasAnyUndefs, 8,
Eric Christopher1c29a652014-07-18 22:55:25 +00002369 !Subtarget.isLittle()) && SplatBitSize <= 64) {
Daniel Sandersf49dd822013-09-24 13:33:07 +00002370 // We can only cope with 8, 16, 32, or 64-bit elements
2371 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
2372 SplatBitSize != 64)
2373 return SDValue();
2374
Simon Dardis7090d142017-03-10 13:27:14 +00002375 // If the value isn't an integer type we will have to bitcast
2376 // from an integer type first. Also, if there are any undefs, we must
2377 // lower them to defined values first.
2378 if (ResTy.isInteger() && !HasAnyUndefs)
Daniel Sandersf49dd822013-09-24 13:33:07 +00002379 return Op;
2380
2381 EVT ViaVecTy;
Daniel Sanders7a289d02013-09-23 12:02:46 +00002382
2383 switch (SplatBitSize) {
2384 default:
2385 return SDValue();
Daniel Sandersf49dd822013-09-24 13:33:07 +00002386 case 8:
2387 ViaVecTy = MVT::v16i8;
Daniel Sanders7a289d02013-09-23 12:02:46 +00002388 break;
2389 case 16:
Daniel Sandersf49dd822013-09-24 13:33:07 +00002390 ViaVecTy = MVT::v8i16;
Daniel Sanders7a289d02013-09-23 12:02:46 +00002391 break;
Daniel Sandersf49dd822013-09-24 13:33:07 +00002392 case 32:
2393 ViaVecTy = MVT::v4i32;
Daniel Sanders7a289d02013-09-23 12:02:46 +00002394 break;
Daniel Sandersf49dd822013-09-24 13:33:07 +00002395 case 64:
2396 // There's no fill.d to fall back on for 64-bit values
2397 return SDValue();
Daniel Sanders7a289d02013-09-23 12:02:46 +00002398 }
2399
Daniel Sanders50b80412013-11-15 12:56:49 +00002400 // SelectionDAG::getConstant will promote SplatValue appropriately.
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002401 SDValue Result = DAG.getConstant(SplatValue, DL, ViaVecTy);
Daniel Sandersf49dd822013-09-24 13:33:07 +00002402
Daniel Sanders50b80412013-11-15 12:56:49 +00002403 // Bitcast to the type we originally wanted
Daniel Sandersf49dd822013-09-24 13:33:07 +00002404 if (ViaVecTy != ResTy)
2405 Result = DAG.getNode(ISD::BITCAST, SDLoc(Node), ResTy, Result);
Daniel Sanders7a289d02013-09-23 12:02:46 +00002406
2407 return Result;
Daniel Sandersf49dd822013-09-24 13:33:07 +00002408 } else if (isSplatVector(Node))
2409 return Op;
2410 else if (!isConstantOrUndefBUILD_VECTOR(Node)) {
Daniel Sandersf86622b2013-09-24 13:16:15 +00002411 // Use INSERT_VECTOR_ELT operations rather than expand to stores.
2412 // The resulting code is the same length as the expansion, but it doesn't
2413 // use memory operations
2414 EVT ResTy = Node->getValueType(0);
2415
2416 assert(ResTy.isVector());
2417
2418 unsigned NumElts = ResTy.getVectorNumElements();
2419 SDValue Vector = DAG.getUNDEF(ResTy);
2420 for (unsigned i = 0; i < NumElts; ++i) {
2421 Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, ResTy, Vector,
2422 Node->getOperand(i),
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002423 DAG.getConstant(i, DL, MVT::i32));
Daniel Sandersf86622b2013-09-24 13:16:15 +00002424 }
2425 return Vector;
2426 }
Daniel Sanders7a289d02013-09-23 12:02:46 +00002427
2428 return SDValue();
2429}
2430
Daniel Sanders26307182013-09-24 14:20:00 +00002431// Lower VECTOR_SHUFFLE into SHF (if possible).
2432//
2433// SHF splits the vector into blocks of four elements, then shuffles these
2434// elements according to a <4 x i2> constant (encoded as an integer immediate).
2435//
2436// It is therefore possible to lower into SHF when the mask takes the form:
2437// <a, b, c, d, a+4, b+4, c+4, d+4, a+8, b+8, c+8, d+8, ...>
2438// When undef's appear they are treated as if they were whatever value is
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002439// necessary in order to fit the above forms.
Daniel Sanders26307182013-09-24 14:20:00 +00002440//
2441// For example:
2442// %2 = shufflevector <8 x i16> %0, <8 x i16> undef,
2443// <8 x i32> <i32 3, i32 2, i32 1, i32 0,
2444// i32 7, i32 6, i32 5, i32 4>
2445// is lowered to:
2446// (SHF_H $w0, $w1, 27)
2447// where the 27 comes from:
2448// 3 + (2 << 2) + (1 << 4) + (0 << 6)
2449static SDValue lowerVECTOR_SHUFFLE_SHF(SDValue Op, EVT ResTy,
2450 SmallVector<int, 16> Indices,
2451 SelectionDAG &DAG) {
2452 int SHFIndices[4] = { -1, -1, -1, -1 };
2453
2454 if (Indices.size() < 4)
2455 return SDValue();
2456
2457 for (unsigned i = 0; i < 4; ++i) {
2458 for (unsigned j = i; j < Indices.size(); j += 4) {
2459 int Idx = Indices[j];
2460
2461 // Convert from vector index to 4-element subvector index
2462 // If an index refers to an element outside of the subvector then give up
2463 if (Idx != -1) {
2464 Idx -= 4 * (j / 4);
2465 if (Idx < 0 || Idx >= 4)
2466 return SDValue();
2467 }
2468
2469 // If the mask has an undef, replace it with the current index.
2470 // Note that it might still be undef if the current index is also undef
2471 if (SHFIndices[i] == -1)
2472 SHFIndices[i] = Idx;
2473
2474 // Check that non-undef values are the same as in the mask. If they
2475 // aren't then give up
2476 if (!(Idx == -1 || Idx == SHFIndices[i]))
2477 return SDValue();
2478 }
2479 }
2480
2481 // Calculate the immediate. Replace any remaining undefs with zero
2482 APInt Imm(32, 0);
2483 for (int i = 3; i >= 0; --i) {
2484 int Idx = SHFIndices[i];
2485
2486 if (Idx == -1)
2487 Idx = 0;
2488
2489 Imm <<= 2;
2490 Imm |= Idx & 0x3;
2491 }
2492
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002493 SDLoc DL(Op);
2494 return DAG.getNode(MipsISD::SHF, DL, ResTy,
2495 DAG.getConstant(Imm, DL, MVT::i32), Op->getOperand(0));
Daniel Sanders26307182013-09-24 14:20:00 +00002496}
2497
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002498/// Determine whether a range fits a regular pattern of values.
2499/// This function accounts for the possibility of jumping over the End iterator.
2500template <typename ValType>
2501static bool
2502fitsRegularPattern(typename SmallVectorImpl<ValType>::const_iterator Begin,
2503 unsigned CheckStride,
2504 typename SmallVectorImpl<ValType>::const_iterator End,
2505 ValType ExpectedIndex, unsigned ExpectedIndexStride) {
2506 auto &I = Begin;
2507
2508 while (I != End) {
2509 if (*I != -1 && *I != ExpectedIndex)
2510 return false;
2511 ExpectedIndex += ExpectedIndexStride;
2512
2513 // Incrementing past End is undefined behaviour so we must increment one
2514 // step at a time and check for End at each step.
2515 for (unsigned n = 0; n < CheckStride && I != End; ++n, ++I)
2516 ; // Empty loop body.
2517 }
2518 return true;
2519}
2520
2521// Determine whether VECTOR_SHUFFLE is a SPLATI.
2522//
2523// It is a SPLATI when the mask is:
2524// <x, x, x, ...>
2525// where x is any valid index.
2526//
2527// When undef's appear in the mask they are treated as if they were whatever
2528// value is necessary in order to fit the above form.
2529static bool isVECTOR_SHUFFLE_SPLATI(SDValue Op, EVT ResTy,
2530 SmallVector<int, 16> Indices,
2531 SelectionDAG &DAG) {
2532 assert((Indices.size() % 2) == 0);
2533
2534 int SplatIndex = -1;
2535 for (const auto &V : Indices) {
2536 if (V != -1) {
2537 SplatIndex = V;
2538 break;
2539 }
2540 }
2541
2542 return fitsRegularPattern<int>(Indices.begin(), 1, Indices.end(), SplatIndex,
2543 0);
2544}
2545
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002546// Lower VECTOR_SHUFFLE into ILVEV (if possible).
2547//
2548// ILVEV interleaves the even elements from each vector.
2549//
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002550// It is possible to lower into ILVEV when the mask consists of two of the
2551// following forms interleaved:
2552// <0, 2, 4, ...>
2553// <n, n+2, n+4, ...>
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002554// where n is the number of elements in the vector.
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002555// For example:
2556// <0, 0, 2, 2, 4, 4, ...>
2557// <0, n, 2, n+2, 4, n+4, ...>
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002558//
2559// When undef's appear in the mask they are treated as if they were whatever
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002560// value is necessary in order to fit the above forms.
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002561static SDValue lowerVECTOR_SHUFFLE_ILVEV(SDValue Op, EVT ResTy,
2562 SmallVector<int, 16> Indices,
2563 SelectionDAG &DAG) {
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002564 assert((Indices.size() % 2) == 0);
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002565
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002566 SDValue Wt;
2567 SDValue Ws;
2568 const auto &Begin = Indices.begin();
2569 const auto &End = Indices.end();
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002570
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002571 // Check even elements are taken from the even elements of one half or the
2572 // other and pick an operand accordingly.
2573 if (fitsRegularPattern<int>(Begin, 2, End, 0, 2))
2574 Wt = Op->getOperand(0);
2575 else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size(), 2))
2576 Wt = Op->getOperand(1);
2577 else
2578 return SDValue();
2579
2580 // Check odd elements are taken from the even elements of one half or the
2581 // other and pick an operand accordingly.
2582 if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 2))
2583 Ws = Op->getOperand(0);
2584 else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size(), 2))
2585 Ws = Op->getOperand(1);
2586 else
2587 return SDValue();
2588
2589 return DAG.getNode(MipsISD::ILVEV, SDLoc(Op), ResTy, Ws, Wt);
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002590}
2591
2592// Lower VECTOR_SHUFFLE into ILVOD (if possible).
2593//
2594// ILVOD interleaves the odd elements from each vector.
2595//
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002596// It is possible to lower into ILVOD when the mask consists of two of the
2597// following forms interleaved:
2598// <1, 3, 5, ...>
2599// <n+1, n+3, n+5, ...>
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002600// where n is the number of elements in the vector.
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002601// For example:
2602// <1, 1, 3, 3, 5, 5, ...>
2603// <1, n+1, 3, n+3, 5, n+5, ...>
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002604//
2605// When undef's appear in the mask they are treated as if they were whatever
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002606// value is necessary in order to fit the above forms.
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002607static SDValue lowerVECTOR_SHUFFLE_ILVOD(SDValue Op, EVT ResTy,
2608 SmallVector<int, 16> Indices,
2609 SelectionDAG &DAG) {
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002610 assert((Indices.size() % 2) == 0);
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002611
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002612 SDValue Wt;
2613 SDValue Ws;
2614 const auto &Begin = Indices.begin();
2615 const auto &End = Indices.end();
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002616
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002617 // Check even elements are taken from the odd elements of one half or the
2618 // other and pick an operand accordingly.
2619 if (fitsRegularPattern<int>(Begin, 2, End, 1, 2))
2620 Wt = Op->getOperand(0);
2621 else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size() + 1, 2))
2622 Wt = Op->getOperand(1);
2623 else
2624 return SDValue();
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002625
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002626 // Check odd elements are taken from the odd elements of one half or the
2627 // other and pick an operand accordingly.
2628 if (fitsRegularPattern<int>(Begin + 1, 2, End, 1, 2))
2629 Ws = Op->getOperand(0);
2630 else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size() + 1, 2))
2631 Ws = Op->getOperand(1);
2632 else
2633 return SDValue();
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002634
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002635 return DAG.getNode(MipsISD::ILVOD, SDLoc(Op), ResTy, Wt, Ws);
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002636}
2637
2638// Lower VECTOR_SHUFFLE into ILVR (if possible).
2639//
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002640// ILVR interleaves consecutive elements from the right (lowest-indexed) half of
2641// each vector.
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002642//
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002643// It is possible to lower into ILVR when the mask consists of two of the
2644// following forms interleaved:
2645// <0, 1, 2, ...>
2646// <n, n+1, n+2, ...>
2647// where n is the number of elements in the vector.
2648// For example:
2649// <0, 0, 1, 1, 2, 2, ...>
2650// <0, n, 1, n+1, 2, n+2, ...>
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002651//
2652// When undef's appear in the mask they are treated as if they were whatever
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002653// value is necessary in order to fit the above forms.
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002654static SDValue lowerVECTOR_SHUFFLE_ILVR(SDValue Op, EVT ResTy,
2655 SmallVector<int, 16> Indices,
2656 SelectionDAG &DAG) {
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002657 assert((Indices.size() % 2) == 0);
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002658
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002659 SDValue Wt;
2660 SDValue Ws;
2661 const auto &Begin = Indices.begin();
2662 const auto &End = Indices.end();
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002663
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002664 // Check even elements are taken from the right (lowest-indexed) elements of
2665 // one half or the other and pick an operand accordingly.
2666 if (fitsRegularPattern<int>(Begin, 2, End, 0, 1))
2667 Wt = Op->getOperand(0);
2668 else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size(), 1))
2669 Wt = Op->getOperand(1);
2670 else
2671 return SDValue();
2672
2673 // Check odd elements are taken from the right (lowest-indexed) elements of
2674 // one half or the other and pick an operand accordingly.
2675 if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 1))
2676 Ws = Op->getOperand(0);
2677 else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size(), 1))
2678 Ws = Op->getOperand(1);
2679 else
2680 return SDValue();
2681
2682 return DAG.getNode(MipsISD::ILVR, SDLoc(Op), ResTy, Ws, Wt);
2683}
2684
2685// Lower VECTOR_SHUFFLE into ILVL (if possible).
2686//
2687// ILVL interleaves consecutive elements from the left (highest-indexed) half
2688// of each vector.
2689//
2690// It is possible to lower into ILVL when the mask consists of two of the
2691// following forms interleaved:
2692// <x, x+1, x+2, ...>
2693// <n+x, n+x+1, n+x+2, ...>
2694// where n is the number of elements in the vector and x is half n.
2695// For example:
2696// <x, x, x+1, x+1, x+2, x+2, ...>
2697// <x, n+x, x+1, n+x+1, x+2, n+x+2, ...>
2698//
2699// When undef's appear in the mask they are treated as if they were whatever
2700// value is necessary in order to fit the above forms.
2701static SDValue lowerVECTOR_SHUFFLE_ILVL(SDValue Op, EVT ResTy,
2702 SmallVector<int, 16> Indices,
2703 SelectionDAG &DAG) {
2704 assert((Indices.size() % 2) == 0);
2705
2706 unsigned HalfSize = Indices.size() / 2;
2707 SDValue Wt;
2708 SDValue Ws;
2709 const auto &Begin = Indices.begin();
2710 const auto &End = Indices.end();
2711
2712 // Check even elements are taken from the left (highest-indexed) elements of
2713 // one half or the other and pick an operand accordingly.
2714 if (fitsRegularPattern<int>(Begin, 2, End, HalfSize, 1))
2715 Wt = Op->getOperand(0);
2716 else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size() + HalfSize, 1))
2717 Wt = Op->getOperand(1);
2718 else
2719 return SDValue();
2720
2721 // Check odd elements are taken from the left (highest-indexed) elements of
2722 // one half or the other and pick an operand accordingly.
2723 if (fitsRegularPattern<int>(Begin + 1, 2, End, HalfSize, 1))
2724 Ws = Op->getOperand(0);
2725 else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size() + HalfSize,
2726 1))
2727 Ws = Op->getOperand(1);
2728 else
2729 return SDValue();
2730
2731 return DAG.getNode(MipsISD::ILVL, SDLoc(Op), ResTy, Ws, Wt);
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002732}
2733
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002734// Lower VECTOR_SHUFFLE into PCKEV (if possible).
2735//
2736// PCKEV copies the even elements of each vector into the result vector.
2737//
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002738// It is possible to lower into PCKEV when the mask consists of two of the
2739// following forms concatenated:
2740// <0, 2, 4, ...>
2741// <n, n+2, n+4, ...>
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002742// where n is the number of elements in the vector.
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002743// For example:
2744// <0, 2, 4, ..., 0, 2, 4, ...>
2745// <0, 2, 4, ..., n, n+2, n+4, ...>
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002746//
2747// When undef's appear in the mask they are treated as if they were whatever
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002748// value is necessary in order to fit the above forms.
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002749static SDValue lowerVECTOR_SHUFFLE_PCKEV(SDValue Op, EVT ResTy,
2750 SmallVector<int, 16> Indices,
2751 SelectionDAG &DAG) {
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002752 assert((Indices.size() % 2) == 0);
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002753
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002754 SDValue Wt;
2755 SDValue Ws;
2756 const auto &Begin = Indices.begin();
2757 const auto &Mid = Indices.begin() + Indices.size() / 2;
2758 const auto &End = Indices.end();
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002759
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002760 if (fitsRegularPattern<int>(Begin, 1, Mid, 0, 2))
2761 Wt = Op->getOperand(0);
2762 else if (fitsRegularPattern<int>(Begin, 1, Mid, Indices.size(), 2))
2763 Wt = Op->getOperand(1);
2764 else
2765 return SDValue();
2766
2767 if (fitsRegularPattern<int>(Mid, 1, End, 0, 2))
2768 Ws = Op->getOperand(0);
2769 else if (fitsRegularPattern<int>(Mid, 1, End, Indices.size(), 2))
2770 Ws = Op->getOperand(1);
2771 else
2772 return SDValue();
2773
2774 return DAG.getNode(MipsISD::PCKEV, SDLoc(Op), ResTy, Ws, Wt);
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002775}
2776
2777// Lower VECTOR_SHUFFLE into PCKOD (if possible).
2778//
2779// PCKOD copies the odd elements of each vector into the result vector.
2780//
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002781// It is possible to lower into PCKOD when the mask consists of two of the
2782// following forms concatenated:
2783// <1, 3, 5, ...>
2784// <n+1, n+3, n+5, ...>
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002785// where n is the number of elements in the vector.
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002786// For example:
2787// <1, 3, 5, ..., 1, 3, 5, ...>
2788// <1, 3, 5, ..., n+1, n+3, n+5, ...>
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002789//
2790// When undef's appear in the mask they are treated as if they were whatever
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002791// value is necessary in order to fit the above forms.
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002792static SDValue lowerVECTOR_SHUFFLE_PCKOD(SDValue Op, EVT ResTy,
2793 SmallVector<int, 16> Indices,
2794 SelectionDAG &DAG) {
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002795 assert((Indices.size() % 2) == 0);
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002796
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002797 SDValue Wt;
2798 SDValue Ws;
2799 const auto &Begin = Indices.begin();
2800 const auto &Mid = Indices.begin() + Indices.size() / 2;
2801 const auto &End = Indices.end();
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002802
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002803 if (fitsRegularPattern<int>(Begin, 1, Mid, 1, 2))
2804 Wt = Op->getOperand(0);
2805 else if (fitsRegularPattern<int>(Begin, 1, Mid, Indices.size() + 1, 2))
2806 Wt = Op->getOperand(1);
2807 else
2808 return SDValue();
2809
2810 if (fitsRegularPattern<int>(Mid, 1, End, 1, 2))
2811 Ws = Op->getOperand(0);
2812 else if (fitsRegularPattern<int>(Mid, 1, End, Indices.size() + 1, 2))
2813 Ws = Op->getOperand(1);
2814 else
2815 return SDValue();
2816
2817 return DAG.getNode(MipsISD::PCKOD, SDLoc(Op), ResTy, Ws, Wt);
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002818}
2819
Daniel Sanderse5087042013-09-24 14:02:15 +00002820// Lower VECTOR_SHUFFLE into VSHF.
2821//
2822// This mostly consists of converting the shuffle indices in Indices into a
2823// BUILD_VECTOR and adding it as an operand to the resulting VSHF. There is
2824// also code to eliminate unused operands of the VECTOR_SHUFFLE. For example,
2825// if the type is v8i16 and all the indices are less than 8 then the second
2826// operand is unused and can be replaced with anything. We choose to replace it
2827// with the used operand since this reduces the number of instructions overall.
2828static SDValue lowerVECTOR_SHUFFLE_VSHF(SDValue Op, EVT ResTy,
2829 SmallVector<int, 16> Indices,
2830 SelectionDAG &DAG) {
2831 SmallVector<SDValue, 16> Ops;
2832 SDValue Op0;
2833 SDValue Op1;
2834 EVT MaskVecTy = ResTy.changeVectorElementTypeToInteger();
2835 EVT MaskEltTy = MaskVecTy.getVectorElementType();
2836 bool Using1stVec = false;
2837 bool Using2ndVec = false;
2838 SDLoc DL(Op);
2839 int ResTyNumElts = ResTy.getVectorNumElements();
2840
2841 for (int i = 0; i < ResTyNumElts; ++i) {
2842 // Idx == -1 means UNDEF
2843 int Idx = Indices[i];
2844
2845 if (0 <= Idx && Idx < ResTyNumElts)
2846 Using1stVec = true;
2847 if (ResTyNumElts <= Idx && Idx < ResTyNumElts * 2)
2848 Using2ndVec = true;
2849 }
2850
2851 for (SmallVector<int, 16>::iterator I = Indices.begin(); I != Indices.end();
2852 ++I)
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00002853 Ops.push_back(DAG.getTargetConstant(*I, DL, MaskEltTy));
Daniel Sanderse5087042013-09-24 14:02:15 +00002854
Ahmed Bougacha128f8732016-04-26 21:15:30 +00002855 SDValue MaskVec = DAG.getBuildVector(MaskVecTy, DL, Ops);
Daniel Sanderse5087042013-09-24 14:02:15 +00002856
2857 if (Using1stVec && Using2ndVec) {
2858 Op0 = Op->getOperand(0);
2859 Op1 = Op->getOperand(1);
2860 } else if (Using1stVec)
2861 Op0 = Op1 = Op->getOperand(0);
2862 else if (Using2ndVec)
2863 Op0 = Op1 = Op->getOperand(1);
2864 else
2865 llvm_unreachable("shuffle vector mask references neither vector operand?");
2866
Daniel Sandersf88a29e2014-03-21 16:56:51 +00002867 // VECTOR_SHUFFLE concatenates the vectors in an vectorwise fashion.
2868 // <0b00, 0b01> + <0b10, 0b11> -> <0b00, 0b01, 0b10, 0b11>
2869 // VSHF concatenates the vectors in a bitwise fashion:
2870 // <0b00, 0b01> + <0b10, 0b11> ->
2871 // 0b0100 + 0b1110 -> 0b01001110
2872 // <0b10, 0b11, 0b00, 0b01>
2873 // We must therefore swap the operands to get the correct result.
2874 return DAG.getNode(MipsISD::VSHF, DL, ResTy, MaskVec, Op1, Op0);
Daniel Sanderse5087042013-09-24 14:02:15 +00002875}
2876
2877// Lower VECTOR_SHUFFLE into one of a number of instructions depending on the
2878// indices in the shuffle.
2879SDValue MipsSETargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
2880 SelectionDAG &DAG) const {
2881 ShuffleVectorSDNode *Node = cast<ShuffleVectorSDNode>(Op);
2882 EVT ResTy = Op->getValueType(0);
2883
2884 if (!ResTy.is128BitVector())
2885 return SDValue();
2886
2887 int ResTyNumElts = ResTy.getVectorNumElements();
2888 SmallVector<int, 16> Indices;
2889
2890 for (int i = 0; i < ResTyNumElts; ++i)
2891 Indices.push_back(Node->getMaskElt(i));
2892
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002893 // splati.[bhwd] is preferable to the others but is matched from
2894 // MipsISD::VSHF.
2895 if (isVECTOR_SHUFFLE_SPLATI(Op, ResTy, Indices, DAG))
2896 return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG);
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002897 SDValue Result;
2898 if ((Result = lowerVECTOR_SHUFFLE_ILVEV(Op, ResTy, Indices, DAG)))
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002899 return Result;
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002900 if ((Result = lowerVECTOR_SHUFFLE_ILVOD(Op, ResTy, Indices, DAG)))
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002901 return Result;
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002902 if ((Result = lowerVECTOR_SHUFFLE_ILVL(Op, ResTy, Indices, DAG)))
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002903 return Result;
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002904 if ((Result = lowerVECTOR_SHUFFLE_ILVR(Op, ResTy, Indices, DAG)))
Daniel Sanders2ed228b2013-09-24 14:36:12 +00002905 return Result;
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002906 if ((Result = lowerVECTOR_SHUFFLE_PCKEV(Op, ResTy, Indices, DAG)))
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002907 return Result;
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002908 if ((Result = lowerVECTOR_SHUFFLE_PCKOD(Op, ResTy, Indices, DAG)))
Daniel Sandersfae5f2a2013-09-24 14:53:25 +00002909 return Result;
Ahmed Bougachaf8dfb472016-02-09 22:54:12 +00002910 if ((Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG)))
Daniel Sandersc8cd58f2015-05-19 12:24:52 +00002911 return Result;
Daniel Sanderse5087042013-09-24 14:02:15 +00002912 return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG);
2913}
2914
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00002915MachineBasicBlock *
2916MipsSETargetLowering::emitBPOSGE32(MachineInstr &MI,
2917 MachineBasicBlock *BB) const {
Akira Hatanaka96ca1822013-03-13 00:54:29 +00002918 // $bb:
2919 // bposge32_pseudo $vr0
2920 // =>
2921 // $bb:
2922 // bposge32 $tbb
2923 // $fbb:
2924 // li $vr2, 0
2925 // b $sink
2926 // $tbb:
2927 // li $vr1, 1
2928 // $sink:
2929 // $vr0 = phi($vr2, $fbb, $vr1, $tbb)
2930
2931 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Eric Christopher96e72c62015-01-29 23:27:36 +00002932 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00002933 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00002934 DebugLoc DL = MI.getDebugLoc();
Akira Hatanaka96ca1822013-03-13 00:54:29 +00002935 const BasicBlock *LLVM_BB = BB->getBasicBlock();
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00002936 MachineFunction::iterator It = std::next(MachineFunction::iterator(BB));
Akira Hatanaka96ca1822013-03-13 00:54:29 +00002937 MachineFunction *F = BB->getParent();
2938 MachineBasicBlock *FBB = F->CreateMachineBasicBlock(LLVM_BB);
2939 MachineBasicBlock *TBB = F->CreateMachineBasicBlock(LLVM_BB);
2940 MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB);
2941 F->insert(It, FBB);
2942 F->insert(It, TBB);
2943 F->insert(It, Sink);
2944
2945 // Transfer the remainder of BB and its successor edges to Sink.
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00002946 Sink->splice(Sink->begin(), BB, std::next(MachineBasicBlock::iterator(MI)),
Akira Hatanaka96ca1822013-03-13 00:54:29 +00002947 BB->end());
2948 Sink->transferSuccessorsAndUpdatePHIs(BB);
2949
2950 // Add successors.
2951 BB->addSuccessor(FBB);
2952 BB->addSuccessor(TBB);
2953 FBB->addSuccessor(Sink);
2954 TBB->addSuccessor(Sink);
2955
2956 // Insert the real bposge32 instruction to $BB.
2957 BuildMI(BB, DL, TII->get(Mips::BPOSGE32)).addMBB(TBB);
Hrvoje Varga6f09cdf2016-05-13 11:32:53 +00002958 // Insert the real bposge32c instruction to $BB.
2959 BuildMI(BB, DL, TII->get(Mips::BPOSGE32C_MMR3)).addMBB(TBB);
Akira Hatanaka96ca1822013-03-13 00:54:29 +00002960
2961 // Fill $FBB.
2962 unsigned VR2 = RegInfo.createVirtualRegister(RC);
2963 BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::ADDiu), VR2)
2964 .addReg(Mips::ZERO).addImm(0);
2965 BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::B)).addMBB(Sink);
2966
2967 // Fill $TBB.
2968 unsigned VR1 = RegInfo.createVirtualRegister(RC);
2969 BuildMI(*TBB, TBB->end(), DL, TII->get(Mips::ADDiu), VR1)
2970 .addReg(Mips::ZERO).addImm(1);
2971
2972 // Insert phi function to $Sink.
2973 BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI),
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00002974 MI.getOperand(0).getReg())
2975 .addReg(VR2)
2976 .addMBB(FBB)
2977 .addReg(VR1)
2978 .addMBB(TBB);
Akira Hatanaka96ca1822013-03-13 00:54:29 +00002979
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00002980 MI.eraseFromParent(); // The pseudo instruction is gone now.
Akira Hatanaka96ca1822013-03-13 00:54:29 +00002981 return Sink;
2982}
Daniel Sandersce09d072013-08-28 12:14:50 +00002983
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00002984MachineBasicBlock *MipsSETargetLowering::emitMSACBranchPseudo(
2985 MachineInstr &MI, MachineBasicBlock *BB, unsigned BranchOp) const {
Daniel Sandersce09d072013-08-28 12:14:50 +00002986 // $bb:
2987 // vany_nonzero $rd, $ws
2988 // =>
2989 // $bb:
2990 // bnz.b $ws, $tbb
2991 // b $fbb
2992 // $fbb:
2993 // li $rd1, 0
2994 // b $sink
2995 // $tbb:
2996 // li $rd2, 1
2997 // $sink:
2998 // $rd = phi($rd1, $fbb, $rd2, $tbb)
2999
3000 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Eric Christopher96e72c62015-01-29 23:27:36 +00003001 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sandersce09d072013-08-28 12:14:50 +00003002 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003003 DebugLoc DL = MI.getDebugLoc();
Daniel Sandersce09d072013-08-28 12:14:50 +00003004 const BasicBlock *LLVM_BB = BB->getBasicBlock();
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00003005 MachineFunction::iterator It = std::next(MachineFunction::iterator(BB));
Daniel Sandersce09d072013-08-28 12:14:50 +00003006 MachineFunction *F = BB->getParent();
3007 MachineBasicBlock *FBB = F->CreateMachineBasicBlock(LLVM_BB);
3008 MachineBasicBlock *TBB = F->CreateMachineBasicBlock(LLVM_BB);
3009 MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB);
3010 F->insert(It, FBB);
3011 F->insert(It, TBB);
3012 F->insert(It, Sink);
3013
3014 // Transfer the remainder of BB and its successor edges to Sink.
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00003015 Sink->splice(Sink->begin(), BB, std::next(MachineBasicBlock::iterator(MI)),
Daniel Sandersce09d072013-08-28 12:14:50 +00003016 BB->end());
3017 Sink->transferSuccessorsAndUpdatePHIs(BB);
3018
3019 // Add successors.
3020 BB->addSuccessor(FBB);
3021 BB->addSuccessor(TBB);
3022 FBB->addSuccessor(Sink);
3023 TBB->addSuccessor(Sink);
3024
3025 // Insert the real bnz.b instruction to $BB.
3026 BuildMI(BB, DL, TII->get(BranchOp))
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003027 .addReg(MI.getOperand(1).getReg())
3028 .addMBB(TBB);
Daniel Sandersce09d072013-08-28 12:14:50 +00003029
3030 // Fill $FBB.
3031 unsigned RD1 = RegInfo.createVirtualRegister(RC);
3032 BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::ADDiu), RD1)
3033 .addReg(Mips::ZERO).addImm(0);
3034 BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::B)).addMBB(Sink);
3035
3036 // Fill $TBB.
3037 unsigned RD2 = RegInfo.createVirtualRegister(RC);
3038 BuildMI(*TBB, TBB->end(), DL, TII->get(Mips::ADDiu), RD2)
3039 .addReg(Mips::ZERO).addImm(1);
3040
3041 // Insert phi function to $Sink.
3042 BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI),
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003043 MI.getOperand(0).getReg())
3044 .addReg(RD1)
3045 .addMBB(FBB)
3046 .addReg(RD2)
3047 .addMBB(TBB);
Daniel Sandersce09d072013-08-28 12:14:50 +00003048
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003049 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sandersce09d072013-08-28 12:14:50 +00003050 return Sink;
3051}
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003052
3053// Emit the COPY_FW pseudo instruction.
3054//
3055// copy_fw_pseudo $fd, $ws, n
3056// =>
3057// copy_u_w $rt, $ws, $n
3058// mtc1 $rt, $fd
3059//
3060// When n is zero, the equivalent operation can be performed with (potentially)
3061// zero instructions due to register overlaps. This optimization is never valid
3062// 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 +00003063MachineBasicBlock *
3064MipsSETargetLowering::emitCOPY_FW(MachineInstr &MI,
3065 MachineBasicBlock *BB) const {
Eric Christopher96e72c62015-01-29 23:27:36 +00003066 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003067 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003068 DebugLoc DL = MI.getDebugLoc();
3069 unsigned Fd = MI.getOperand(0).getReg();
3070 unsigned Ws = MI.getOperand(1).getReg();
3071 unsigned Lane = MI.getOperand(2).getImm();
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003072
Daniel Sandersafe27c72015-02-23 17:22:16 +00003073 if (Lane == 0) {
3074 unsigned Wt = Ws;
3075 if (!Subtarget.useOddSPReg()) {
3076 // We must copy to an even-numbered MSA register so that the
3077 // single-precision sub-register is also guaranteed to be even-numbered.
3078 Wt = RegInfo.createVirtualRegister(&Mips::MSA128WEvensRegClass);
3079
3080 BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Wt).addReg(Ws);
3081 }
3082
3083 BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_lo);
3084 } else {
3085 unsigned Wt = RegInfo.createVirtualRegister(
3086 Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass :
3087 &Mips::MSA128WEvensRegClass);
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003088
Daniel Sandersd9207702014-03-04 13:54:30 +00003089 BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_W), Wt).addReg(Ws).addImm(Lane);
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003090 BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_lo);
3091 }
3092
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003093 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003094 return BB;
3095}
3096
3097// Emit the COPY_FD pseudo instruction.
3098//
3099// copy_fd_pseudo $fd, $ws, n
3100// =>
3101// splati.d $wt, $ws, $n
3102// copy $fd, $wt:sub_64
3103//
3104// When n is zero, the equivalent operation can be performed with (potentially)
3105// zero instructions due to register overlaps. This optimization is always
3106// valid because FR=1 mode which is the only supported mode in MSA.
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003107MachineBasicBlock *
3108MipsSETargetLowering::emitCOPY_FD(MachineInstr &MI,
3109 MachineBasicBlock *BB) const {
Eric Christopher1c29a652014-07-18 22:55:25 +00003110 assert(Subtarget.isFP64bit());
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003111
Eric Christopher96e72c62015-01-29 23:27:36 +00003112 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003113 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003114 unsigned Fd = MI.getOperand(0).getReg();
3115 unsigned Ws = MI.getOperand(1).getReg();
3116 unsigned Lane = MI.getOperand(2).getImm() * 2;
3117 DebugLoc DL = MI.getDebugLoc();
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003118
3119 if (Lane == 0)
3120 BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Ws, 0, Mips::sub_64);
3121 else {
3122 unsigned Wt = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
3123
3124 BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_D), Wt).addReg(Ws).addImm(1);
3125 BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_64);
3126 }
3127
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003128 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sanders39bb8ba2013-09-27 12:17:32 +00003129 return BB;
3130}
Daniel Sandersa5150702013-09-27 12:31:32 +00003131
3132// Emit the INSERT_FW pseudo instruction.
3133//
3134// insert_fw_pseudo $wd, $wd_in, $n, $fs
3135// =>
3136// subreg_to_reg $wt:sub_lo, $fs
3137// insve_w $wd[$n], $wd_in, $wt[0]
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003138MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003139MipsSETargetLowering::emitINSERT_FW(MachineInstr &MI,
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003140 MachineBasicBlock *BB) const {
Eric Christopher96e72c62015-01-29 23:27:36 +00003141 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sandersa5150702013-09-27 12:31:32 +00003142 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003143 DebugLoc DL = MI.getDebugLoc();
3144 unsigned Wd = MI.getOperand(0).getReg();
3145 unsigned Wd_in = MI.getOperand(1).getReg();
3146 unsigned Lane = MI.getOperand(2).getImm();
3147 unsigned Fs = MI.getOperand(3).getReg();
Daniel Sandersafe27c72015-02-23 17:22:16 +00003148 unsigned Wt = RegInfo.createVirtualRegister(
3149 Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass :
3150 &Mips::MSA128WEvensRegClass);
Daniel Sandersa5150702013-09-27 12:31:32 +00003151
3152 BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt)
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003153 .addImm(0)
3154 .addReg(Fs)
3155 .addImm(Mips::sub_lo);
Daniel Sandersa5150702013-09-27 12:31:32 +00003156 BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_W), Wd)
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003157 .addReg(Wd_in)
3158 .addImm(Lane)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003159 .addReg(Wt)
3160 .addImm(0);
Daniel Sandersa5150702013-09-27 12:31:32 +00003161
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003162 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sandersa5150702013-09-27 12:31:32 +00003163 return BB;
3164}
3165
3166// Emit the INSERT_FD pseudo instruction.
3167//
3168// insert_fd_pseudo $wd, $fs, n
3169// =>
3170// subreg_to_reg $wt:sub_64, $fs
3171// insve_d $wd[$n], $wd_in, $wt[0]
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003172MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003173MipsSETargetLowering::emitINSERT_FD(MachineInstr &MI,
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003174 MachineBasicBlock *BB) const {
Eric Christopher1c29a652014-07-18 22:55:25 +00003175 assert(Subtarget.isFP64bit());
Daniel Sandersa5150702013-09-27 12:31:32 +00003176
Eric Christopher96e72c62015-01-29 23:27:36 +00003177 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sandersa5150702013-09-27 12:31:32 +00003178 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003179 DebugLoc DL = MI.getDebugLoc();
3180 unsigned Wd = MI.getOperand(0).getReg();
3181 unsigned Wd_in = MI.getOperand(1).getReg();
3182 unsigned Lane = MI.getOperand(2).getImm();
3183 unsigned Fs = MI.getOperand(3).getReg();
Daniel Sandersa5150702013-09-27 12:31:32 +00003184 unsigned Wt = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
3185
3186 BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt)
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003187 .addImm(0)
3188 .addReg(Fs)
3189 .addImm(Mips::sub_64);
Daniel Sandersa5150702013-09-27 12:31:32 +00003190 BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_D), Wd)
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003191 .addReg(Wd_in)
3192 .addImm(Lane)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003193 .addReg(Wt)
3194 .addImm(0);
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003195
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003196 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003197 return BB;
3198}
3199
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003200// Emit the INSERT_([BHWD]|F[WD])_VIDX pseudo instruction.
3201//
3202// For integer:
3203// (INSERT_([BHWD]|F[WD])_PSEUDO $wd, $wd_in, $n, $rs)
3204// =>
3205// (SLL $lanetmp1, $lane, <log2size)
3206// (SLD_B $wdtmp1, $wd_in, $wd_in, $lanetmp1)
3207// (INSERT_[BHWD], $wdtmp2, $wdtmp1, 0, $rs)
3208// (NEG $lanetmp2, $lanetmp1)
3209// (SLD_B $wd, $wdtmp2, $wdtmp2, $lanetmp2)
3210//
3211// For floating point:
3212// (INSERT_([BHWD]|F[WD])_PSEUDO $wd, $wd_in, $n, $fs)
3213// =>
3214// (SUBREG_TO_REG $wt, $fs, <subreg>)
3215// (SLL $lanetmp1, $lane, <log2size)
3216// (SLD_B $wdtmp1, $wd_in, $wd_in, $lanetmp1)
3217// (INSVE_[WD], $wdtmp2, 0, $wdtmp1, 0)
3218// (NEG $lanetmp2, $lanetmp1)
3219// (SLD_B $wd, $wdtmp2, $wdtmp2, $lanetmp2)
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003220MachineBasicBlock *MipsSETargetLowering::emitINSERT_DF_VIDX(
3221 MachineInstr &MI, MachineBasicBlock *BB, unsigned EltSizeInBytes,
3222 bool IsFP) const {
Eric Christopher96e72c62015-01-29 23:27:36 +00003223 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003224 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003225 DebugLoc DL = MI.getDebugLoc();
3226 unsigned Wd = MI.getOperand(0).getReg();
3227 unsigned SrcVecReg = MI.getOperand(1).getReg();
3228 unsigned LaneReg = MI.getOperand(2).getReg();
3229 unsigned SrcValReg = MI.getOperand(3).getReg();
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003230
3231 const TargetRegisterClass *VecRC = nullptr;
Daniel Sandersd3bb2082016-06-15 08:43:23 +00003232 // FIXME: This should be true for N32 too.
Eric Christopherbf33a3c2014-07-02 23:18:40 +00003233 const TargetRegisterClass *GPRRC =
Daniel Sanders4160c802015-05-05 08:48:35 +00003234 Subtarget.isABI_N64() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
Daniel Sandersd3bb2082016-06-15 08:43:23 +00003235 unsigned SubRegIdx = Subtarget.isABI_N64() ? Mips::sub_32 : 0;
3236 unsigned ShiftOp = Subtarget.isABI_N64() ? Mips::DSLL : Mips::SLL;
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003237 unsigned EltLog2Size;
3238 unsigned InsertOp = 0;
3239 unsigned InsveOp = 0;
3240 switch (EltSizeInBytes) {
3241 default:
3242 llvm_unreachable("Unexpected size");
3243 case 1:
3244 EltLog2Size = 0;
3245 InsertOp = Mips::INSERT_B;
3246 InsveOp = Mips::INSVE_B;
3247 VecRC = &Mips::MSA128BRegClass;
3248 break;
3249 case 2:
3250 EltLog2Size = 1;
3251 InsertOp = Mips::INSERT_H;
3252 InsveOp = Mips::INSVE_H;
3253 VecRC = &Mips::MSA128HRegClass;
3254 break;
3255 case 4:
3256 EltLog2Size = 2;
3257 InsertOp = Mips::INSERT_W;
3258 InsveOp = Mips::INSVE_W;
3259 VecRC = &Mips::MSA128WRegClass;
3260 break;
3261 case 8:
3262 EltLog2Size = 3;
3263 InsertOp = Mips::INSERT_D;
3264 InsveOp = Mips::INSVE_D;
3265 VecRC = &Mips::MSA128DRegClass;
3266 break;
3267 }
3268
3269 if (IsFP) {
3270 unsigned Wt = RegInfo.createVirtualRegister(VecRC);
3271 BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt)
3272 .addImm(0)
3273 .addReg(SrcValReg)
3274 .addImm(EltSizeInBytes == 8 ? Mips::sub_64 : Mips::sub_lo);
3275 SrcValReg = Wt;
3276 }
3277
3278 // Convert the lane index into a byte index
3279 if (EltSizeInBytes != 1) {
3280 unsigned LaneTmp1 = RegInfo.createVirtualRegister(GPRRC);
Daniel Sandersd3bb2082016-06-15 08:43:23 +00003281 BuildMI(*BB, MI, DL, TII->get(ShiftOp), LaneTmp1)
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003282 .addReg(LaneReg)
3283 .addImm(EltLog2Size);
3284 LaneReg = LaneTmp1;
3285 }
3286
3287 // Rotate bytes around so that the desired lane is element zero
3288 unsigned WdTmp1 = RegInfo.createVirtualRegister(VecRC);
3289 BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), WdTmp1)
3290 .addReg(SrcVecReg)
3291 .addReg(SrcVecReg)
Daniel Sandersd3bb2082016-06-15 08:43:23 +00003292 .addReg(LaneReg, 0, SubRegIdx);
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003293
3294 unsigned WdTmp2 = RegInfo.createVirtualRegister(VecRC);
3295 if (IsFP) {
3296 // Use insve.df to insert to element zero
3297 BuildMI(*BB, MI, DL, TII->get(InsveOp), WdTmp2)
3298 .addReg(WdTmp1)
3299 .addImm(0)
3300 .addReg(SrcValReg)
3301 .addImm(0);
3302 } else {
3303 // Use insert.df to insert to element zero
3304 BuildMI(*BB, MI, DL, TII->get(InsertOp), WdTmp2)
3305 .addReg(WdTmp1)
3306 .addReg(SrcValReg)
3307 .addImm(0);
3308 }
3309
3310 // Rotate elements the rest of the way for a full rotation.
3311 // sld.df inteprets $rt modulo the number of columns so we only need to negate
3312 // the lane index to do this.
3313 unsigned LaneTmp2 = RegInfo.createVirtualRegister(GPRRC);
Daniel Sanders4160c802015-05-05 08:48:35 +00003314 BuildMI(*BB, MI, DL, TII->get(Subtarget.isABI_N64() ? Mips::DSUB : Mips::SUB),
3315 LaneTmp2)
3316 .addReg(Subtarget.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO)
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003317 .addReg(LaneReg);
3318 BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), Wd)
3319 .addReg(WdTmp2)
3320 .addReg(WdTmp2)
Daniel Sandersd3bb2082016-06-15 08:43:23 +00003321 .addReg(LaneTmp2, 0, SubRegIdx);
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003322
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003323 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sanderse296a0f2014-04-30 12:09:32 +00003324 return BB;
3325}
3326
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003327// Emit the FILL_FW pseudo instruction.
3328//
3329// fill_fw_pseudo $wd, $fs
3330// =>
3331// implicit_def $wt1
3332// insert_subreg $wt2:subreg_lo, $wt1, $fs
3333// splati.w $wd, $wt2[0]
3334MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003335MipsSETargetLowering::emitFILL_FW(MachineInstr &MI,
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003336 MachineBasicBlock *BB) const {
Eric Christopher96e72c62015-01-29 23:27:36 +00003337 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003338 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003339 DebugLoc DL = MI.getDebugLoc();
3340 unsigned Wd = MI.getOperand(0).getReg();
3341 unsigned Fs = MI.getOperand(1).getReg();
Simon Dardis0e9e2372017-01-10 15:53:10 +00003342 unsigned Wt1 = RegInfo.createVirtualRegister(
3343 Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass
3344 : &Mips::MSA128WEvensRegClass);
3345 unsigned Wt2 = RegInfo.createVirtualRegister(
3346 Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass
3347 : &Mips::MSA128WEvensRegClass);
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003348
3349 BuildMI(*BB, MI, DL, TII->get(Mips::IMPLICIT_DEF), Wt1);
3350 BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_SUBREG), Wt2)
3351 .addReg(Wt1)
3352 .addReg(Fs)
3353 .addImm(Mips::sub_lo);
3354 BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_W), Wd).addReg(Wt2).addImm(0);
3355
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003356 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003357 return BB;
3358}
3359
3360// Emit the FILL_FD pseudo instruction.
3361//
3362// fill_fd_pseudo $wd, $fs
3363// =>
3364// implicit_def $wt1
3365// insert_subreg $wt2:subreg_64, $wt1, $fs
3366// splati.d $wd, $wt2[0]
3367MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003368MipsSETargetLowering::emitFILL_FD(MachineInstr &MI,
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003369 MachineBasicBlock *BB) const {
Eric Christopher1c29a652014-07-18 22:55:25 +00003370 assert(Subtarget.isFP64bit());
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003371
Eric Christopher96e72c62015-01-29 23:27:36 +00003372 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003373 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003374 DebugLoc DL = MI.getDebugLoc();
3375 unsigned Wd = MI.getOperand(0).getReg();
3376 unsigned Fs = MI.getOperand(1).getReg();
Daniel Sanders1dfddc72013-10-15 13:14:41 +00003377 unsigned Wt1 = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
3378 unsigned Wt2 = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
3379
3380 BuildMI(*BB, MI, DL, TII->get(Mips::IMPLICIT_DEF), Wt1);
3381 BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_SUBREG), Wt2)
3382 .addReg(Wt1)
3383 .addReg(Fs)
3384 .addImm(Mips::sub_64);
3385 BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_D), Wd).addReg(Wt2).addImm(0);
Daniel Sandersa5150702013-09-27 12:31:32 +00003386
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003387 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sandersa5150702013-09-27 12:31:32 +00003388 return BB;
3389}
Daniel Sandersa9521602013-10-23 10:36:52 +00003390
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003391// Emit the ST_F16_PSEDUO instruction to store a f16 value from an MSA
3392// register.
3393//
3394// STF16 MSA128F16:$wd, mem_simm10:$addr
3395// =>
3396// copy_u.h $rtemp,$wd[0]
3397// sh $rtemp, $addr
3398//
3399// Safety: We can't use st.h & co as they would over write the memory after
3400// the destination. It would require half floats be allocated 16 bytes(!) of
3401// space.
3402MachineBasicBlock *
3403MipsSETargetLowering::emitST_F16_PSEUDO(MachineInstr &MI,
3404 MachineBasicBlock *BB) const {
3405
3406 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3407 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3408 DebugLoc DL = MI.getDebugLoc();
3409 unsigned Ws = MI.getOperand(0).getReg();
3410 unsigned Rt = MI.getOperand(1).getReg();
3411 const MachineMemOperand &MMO = **MI.memoperands_begin();
3412 unsigned Imm = MMO.getOffset();
3413
3414 // Caution: A load via the GOT can expand to a GPR32 operand, a load via
3415 // spill and reload can expand as a GPR64 operand. Examine the
3416 // operand in detail and default to ABI.
3417 const TargetRegisterClass *RC =
3418 MI.getOperand(1).isReg() ? RegInfo.getRegClass(MI.getOperand(1).getReg())
3419 : (Subtarget.isABI_O32() ? &Mips::GPR32RegClass
3420 : &Mips::GPR64RegClass);
3421 const bool UsingMips32 = RC == &Mips::GPR32RegClass;
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003422 unsigned Rs = RegInfo.createVirtualRegister(&Mips::GPR32RegClass);
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003423
3424 BuildMI(*BB, MI, DL, TII->get(Mips::COPY_U_H), Rs).addReg(Ws).addImm(0);
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003425 if(!UsingMips32) {
3426 unsigned Tmp = RegInfo.createVirtualRegister(&Mips::GPR64RegClass);
3427 BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Tmp)
3428 .addImm(0)
3429 .addReg(Rs)
3430 .addImm(Mips::sub_32);
3431 Rs = Tmp;
3432 }
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003433 BuildMI(*BB, MI, DL, TII->get(UsingMips32 ? Mips::SH : Mips::SH64))
3434 .addReg(Rs)
3435 .addReg(Rt)
3436 .addImm(Imm)
3437 .addMemOperand(BB->getParent()->getMachineMemOperand(
3438 &MMO, MMO.getOffset(), MMO.getSize()));
3439
3440 MI.eraseFromParent();
3441 return BB;
3442}
3443
3444// Emit the LD_F16_PSEDUO instruction to load a f16 value into an MSA register.
3445//
3446// LD_F16 MSA128F16:$wd, mem_simm10:$addr
3447// =>
3448// lh $rtemp, $addr
3449// fill.h $wd, $rtemp
3450//
3451// Safety: We can't use ld.h & co as they over-read from the source.
3452// Additionally, if the address is not modulo 16, 2 cases can occur:
3453// a) Segmentation fault as the load instruction reads from a memory page
3454// memory it's not supposed to.
3455// b) The load crosses an implementation specific boundary, requiring OS
3456// intervention.
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003457MachineBasicBlock *
3458MipsSETargetLowering::emitLD_F16_PSEUDO(MachineInstr &MI,
3459 MachineBasicBlock *BB) const {
3460
3461 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3462 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3463 DebugLoc DL = MI.getDebugLoc();
3464 unsigned Wd = MI.getOperand(0).getReg();
3465
3466 // Caution: A load via the GOT can expand to a GPR32 operand, a load via
3467 // spill and reload can expand as a GPR64 operand. Examine the
3468 // operand in detail and default to ABI.
3469 const TargetRegisterClass *RC =
3470 MI.getOperand(1).isReg() ? RegInfo.getRegClass(MI.getOperand(1).getReg())
3471 : (Subtarget.isABI_O32() ? &Mips::GPR32RegClass
3472 : &Mips::GPR64RegClass);
3473
3474 const bool UsingMips32 = RC == &Mips::GPR32RegClass;
3475 unsigned Rt = RegInfo.createVirtualRegister(RC);
3476
3477 MachineInstrBuilder MIB =
3478 BuildMI(*BB, MI, DL, TII->get(UsingMips32 ? Mips::LH : Mips::LH64), Rt);
3479 for (unsigned i = 1; i < MI.getNumOperands(); i++)
Diana Picus116bbab2017-01-13 09:58:52 +00003480 MIB.add(MI.getOperand(i));
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003481
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003482 if(!UsingMips32) {
3483 unsigned Tmp = RegInfo.createVirtualRegister(&Mips::GPR32RegClass);
3484 BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Tmp).addReg(Rt, 0, Mips::sub_32);
3485 Rt = Tmp;
3486 }
3487
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003488 BuildMI(*BB, MI, DL, TII->get(Mips::FILL_H), Wd).addReg(Rt);
3489
3490 MI.eraseFromParent();
3491 return BB;
3492}
3493
3494// Emit the FPROUND_PSEUDO instruction.
3495//
3496// Round an FGR64Opnd, FGR32Opnd to an f16.
3497//
3498// Safety: Cycle the operand through the GPRs so the result always ends up
3499// the correct MSA register.
3500//
3501// FIXME: This copying is strictly unnecessary. If we could tie FGR32Opnd:$Fs
3502// / FGR64Opnd:$Fs and MSA128F16:$Wd to the same physical register
3503// (which they can be, as the MSA registers are defined to alias the
3504// FPU's 64 bit and 32 bit registers) the result can be accessed using
3505// the correct register class. That requires operands be tie-able across
3506// register classes which have a sub/super register class relationship.
3507//
3508// For FPG32Opnd:
3509//
3510// FPROUND MSA128F16:$wd, FGR32Opnd:$fs
3511// =>
3512// mfc1 $rtemp, $fs
3513// fill.w $rtemp, $wtemp
3514// fexdo.w $wd, $wtemp, $wtemp
3515//
3516// For FPG64Opnd on mips32r2+:
3517//
3518// FPROUND MSA128F16:$wd, FGR64Opnd:$fs
3519// =>
3520// mfc1 $rtemp, $fs
3521// fill.w $rtemp, $wtemp
3522// mfhc1 $rtemp2, $fs
3523// insert.w $wtemp[1], $rtemp2
3524// insert.w $wtemp[3], $rtemp2
3525// fexdo.w $wtemp2, $wtemp, $wtemp
3526// fexdo.h $wd, $temp2, $temp2
3527//
3528// For FGR64Opnd on mips64r2+:
3529//
3530// FPROUND MSA128F16:$wd, FGR64Opnd:$fs
3531// =>
3532// dmfc1 $rtemp, $fs
3533// fill.d $rtemp, $wtemp
3534// fexdo.w $wtemp2, $wtemp, $wtemp
3535// fexdo.h $wd, $wtemp2, $wtemp2
3536//
3537// Safety note: As $wtemp is UNDEF, we may provoke a spurious exception if the
3538// undef bits are "just right" and the exception enable bits are
3539// set. By using fill.w to replicate $fs into all elements over
3540// insert.w for one element, we avoid that potiential case. If
3541// fexdo.[hw] causes an exception in, the exception is valid and it
3542// occurs for all elements.
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003543MachineBasicBlock *
3544MipsSETargetLowering::emitFPROUND_PSEUDO(MachineInstr &MI,
3545 MachineBasicBlock *BB,
3546 bool IsFGR64) const {
3547
3548 // Strictly speaking, we need MIPS32R5 to support MSA. We'll be generous
3549 // here. It's technically doable to support MIPS32 here, but the ISA forbids
3550 // it.
3551 assert(Subtarget.hasMSA() && Subtarget.hasMips32r2());
3552
3553 bool IsFGR64onMips64 = Subtarget.hasMips64() && IsFGR64;
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003554 bool IsFGR64onMips32 = !Subtarget.hasMips64() && IsFGR64;
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003555
3556 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3557 DebugLoc DL = MI.getDebugLoc();
3558 unsigned Wd = MI.getOperand(0).getReg();
3559 unsigned Fs = MI.getOperand(1).getReg();
3560
3561 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3562 unsigned Wtemp = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
3563 const TargetRegisterClass *GPRRC =
3564 IsFGR64onMips64 ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003565 unsigned MFC1Opc = IsFGR64onMips64
3566 ? Mips::DMFC1
3567 : (IsFGR64onMips32 ? Mips::MFC1_D64 : Mips::MFC1);
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003568 unsigned FILLOpc = IsFGR64onMips64 ? Mips::FILL_D : Mips::FILL_W;
3569
3570 // Perform the register class copy as mentioned above.
3571 unsigned Rtemp = RegInfo.createVirtualRegister(GPRRC);
3572 BuildMI(*BB, MI, DL, TII->get(MFC1Opc), Rtemp).addReg(Fs);
3573 BuildMI(*BB, MI, DL, TII->get(FILLOpc), Wtemp).addReg(Rtemp);
3574 unsigned WPHI = Wtemp;
3575
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003576 if (IsFGR64onMips32) {
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003577 unsigned Rtemp2 = RegInfo.createVirtualRegister(GPRRC);
3578 BuildMI(*BB, MI, DL, TII->get(Mips::MFHC1_D64), Rtemp2).addReg(Fs);
3579 unsigned Wtemp2 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
3580 unsigned Wtemp3 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
3581 BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_W), Wtemp2)
3582 .addReg(Wtemp)
3583 .addReg(Rtemp2)
3584 .addImm(1);
3585 BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_W), Wtemp3)
3586 .addReg(Wtemp2)
3587 .addReg(Rtemp2)
3588 .addImm(3);
3589 WPHI = Wtemp3;
3590 }
3591
3592 if (IsFGR64) {
3593 unsigned Wtemp2 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
3594 BuildMI(*BB, MI, DL, TII->get(Mips::FEXDO_W), Wtemp2)
3595 .addReg(WPHI)
3596 .addReg(WPHI);
3597 WPHI = Wtemp2;
3598 }
3599
3600 BuildMI(*BB, MI, DL, TII->get(Mips::FEXDO_H), Wd).addReg(WPHI).addReg(WPHI);
3601
3602 MI.eraseFromParent();
3603 return BB;
3604}
3605
3606// Emit the FPEXTEND_PSEUDO instruction.
3607//
3608// Expand an f16 to either a FGR32Opnd or FGR64Opnd.
3609//
3610// Safety: Cycle the result through the GPRs so the result always ends up
3611// the correct floating point register.
3612//
3613// FIXME: This copying is strictly unnecessary. If we could tie FGR32Opnd:$Fd
3614// / FGR64Opnd:$Fd and MSA128F16:$Ws to the same physical register
3615// (which they can be, as the MSA registers are defined to alias the
3616// FPU's 64 bit and 32 bit registers) the result can be accessed using
3617// the correct register class. That requires operands be tie-able across
3618// register classes which have a sub/super register class relationship. I
3619// haven't checked.
3620//
3621// For FGR32Opnd:
3622//
3623// FPEXTEND FGR32Opnd:$fd, MSA128F16:$ws
3624// =>
3625// fexupr.w $wtemp, $ws
3626// copy_s.w $rtemp, $ws[0]
3627// mtc1 $rtemp, $fd
3628//
3629// For FGR64Opnd on Mips64:
3630//
3631// FPEXTEND FGR64Opnd:$fd, MSA128F16:$ws
3632// =>
3633// fexupr.w $wtemp, $ws
3634// fexupr.d $wtemp2, $wtemp
3635// copy_s.d $rtemp, $wtemp2s[0]
3636// dmtc1 $rtemp, $fd
3637//
3638// For FGR64Opnd on Mips32:
3639//
3640// FPEXTEND FGR64Opnd:$fd, MSA128F16:$ws
3641// =>
3642// fexupr.w $wtemp, $ws
3643// fexupr.d $wtemp2, $wtemp
3644// copy_s.w $rtemp, $wtemp2[0]
3645// mtc1 $rtemp, $ftemp
3646// copy_s.w $rtemp2, $wtemp2[1]
3647// $fd = mthc1 $rtemp2, $ftemp
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003648MachineBasicBlock *
3649MipsSETargetLowering::emitFPEXTEND_PSEUDO(MachineInstr &MI,
3650 MachineBasicBlock *BB,
3651 bool IsFGR64) const {
3652
3653 // Strictly speaking, we need MIPS32R5 to support MSA. We'll be generous
3654 // here. It's technically doable to support MIPS32 here, but the ISA forbids
3655 // it.
3656 assert(Subtarget.hasMSA() && Subtarget.hasMips32r2());
3657
3658 bool IsFGR64onMips64 = Subtarget.hasMips64() && IsFGR64;
3659 bool IsFGR64onMips32 = !Subtarget.hasMips64() && IsFGR64;
3660
3661 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3662 DebugLoc DL = MI.getDebugLoc();
3663 unsigned Fd = MI.getOperand(0).getReg();
3664 unsigned Ws = MI.getOperand(1).getReg();
3665
3666 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3667 const TargetRegisterClass *GPRRC =
3668 IsFGR64onMips64 ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
Stefan Maksimovic58f225b2017-07-18 12:05:35 +00003669 unsigned MTC1Opc = IsFGR64onMips64
3670 ? Mips::DMTC1
3671 : (IsFGR64onMips32 ? Mips::MTC1_D64 : Mips::MTC1);
Simon Dardis0e2ee3b2016-11-18 16:17:44 +00003672 unsigned COPYOpc = IsFGR64onMips64 ? Mips::COPY_S_D : Mips::COPY_S_W;
3673
3674 unsigned Wtemp = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
3675 unsigned WPHI = Wtemp;
3676
3677 BuildMI(*BB, MI, DL, TII->get(Mips::FEXUPR_W), Wtemp).addReg(Ws);
3678 if (IsFGR64) {
3679 WPHI = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
3680 BuildMI(*BB, MI, DL, TII->get(Mips::FEXUPR_D), WPHI).addReg(Wtemp);
3681 }
3682
3683 // Perform the safety regclass copy mentioned above.
3684 unsigned Rtemp = RegInfo.createVirtualRegister(GPRRC);
3685 unsigned FPRPHI = IsFGR64onMips32
3686 ? RegInfo.createVirtualRegister(&Mips::FGR64RegClass)
3687 : Fd;
3688 BuildMI(*BB, MI, DL, TII->get(COPYOpc), Rtemp).addReg(WPHI).addImm(0);
3689 BuildMI(*BB, MI, DL, TII->get(MTC1Opc), FPRPHI).addReg(Rtemp);
3690
3691 if (IsFGR64onMips32) {
3692 unsigned Rtemp2 = RegInfo.createVirtualRegister(GPRRC);
3693 BuildMI(*BB, MI, DL, TII->get(Mips::COPY_S_W), Rtemp2)
3694 .addReg(WPHI)
3695 .addImm(1);
3696 BuildMI(*BB, MI, DL, TII->get(Mips::MTHC1_D64), Fd)
3697 .addReg(FPRPHI)
3698 .addReg(Rtemp2);
3699 }
3700
3701 MI.eraseFromParent();
3702 return BB;
3703}
3704
Daniel Sandersa9521602013-10-23 10:36:52 +00003705// Emit the FEXP2_W_1 pseudo instructions.
3706//
3707// fexp2_w_1_pseudo $wd, $wt
3708// =>
3709// ldi.w $ws, 1
3710// fexp2.w $wd, $ws, $wt
3711MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003712MipsSETargetLowering::emitFEXP2_W_1(MachineInstr &MI,
Daniel Sandersa9521602013-10-23 10:36:52 +00003713 MachineBasicBlock *BB) const {
Eric Christopher96e72c62015-01-29 23:27:36 +00003714 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sandersa9521602013-10-23 10:36:52 +00003715 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3716 const TargetRegisterClass *RC = &Mips::MSA128WRegClass;
3717 unsigned Ws1 = RegInfo.createVirtualRegister(RC);
3718 unsigned Ws2 = RegInfo.createVirtualRegister(RC);
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003719 DebugLoc DL = MI.getDebugLoc();
Daniel Sandersa9521602013-10-23 10:36:52 +00003720
3721 // Splat 1.0 into a vector
3722 BuildMI(*BB, MI, DL, TII->get(Mips::LDI_W), Ws1).addImm(1);
3723 BuildMI(*BB, MI, DL, TII->get(Mips::FFINT_U_W), Ws2).addReg(Ws1);
3724
3725 // Emit 1.0 * fexp2(Wt)
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003726 BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_W), MI.getOperand(0).getReg())
Daniel Sandersa9521602013-10-23 10:36:52 +00003727 .addReg(Ws2)
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003728 .addReg(MI.getOperand(1).getReg());
Daniel Sandersa9521602013-10-23 10:36:52 +00003729
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003730 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sandersa9521602013-10-23 10:36:52 +00003731 return BB;
3732}
3733
3734// Emit the FEXP2_D_1 pseudo instructions.
3735//
3736// fexp2_d_1_pseudo $wd, $wt
3737// =>
3738// ldi.d $ws, 1
3739// fexp2.d $wd, $ws, $wt
3740MachineBasicBlock *
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003741MipsSETargetLowering::emitFEXP2_D_1(MachineInstr &MI,
Daniel Sandersa9521602013-10-23 10:36:52 +00003742 MachineBasicBlock *BB) const {
Eric Christopher96e72c62015-01-29 23:27:36 +00003743 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
Daniel Sandersa9521602013-10-23 10:36:52 +00003744 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3745 const TargetRegisterClass *RC = &Mips::MSA128DRegClass;
3746 unsigned Ws1 = RegInfo.createVirtualRegister(RC);
3747 unsigned Ws2 = RegInfo.createVirtualRegister(RC);
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003748 DebugLoc DL = MI.getDebugLoc();
Daniel Sandersa9521602013-10-23 10:36:52 +00003749
3750 // Splat 1.0 into a vector
3751 BuildMI(*BB, MI, DL, TII->get(Mips::LDI_D), Ws1).addImm(1);
3752 BuildMI(*BB, MI, DL, TII->get(Mips::FFINT_U_D), Ws2).addReg(Ws1);
3753
3754 // Emit 1.0 * fexp2(Wt)
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003755 BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_D), MI.getOperand(0).getReg())
Daniel Sandersa9521602013-10-23 10:36:52 +00003756 .addReg(Ws2)
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003757 .addReg(MI.getOperand(1).getReg());
Daniel Sandersa9521602013-10-23 10:36:52 +00003758
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00003759 MI.eraseFromParent(); // The pseudo instruction is gone now.
Daniel Sandersa9521602013-10-23 10:36:52 +00003760 return BB;
3761}