1//===- MipsSEISelLowering.cpp - MipsSE DAG Lowering Interface -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Subclass of MipsTargetLowering specialized for mips32/64.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MipsSEISelLowering.h"
14#include "MipsMachineFunction.h"
15#include "MipsRegisterInfo.h"
16#include "MipsSubtarget.h"
17#include "llvm/ADT/APInt.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/CodeGen/CallingConvLower.h"
21#include "llvm/CodeGen/ISDOpcodes.h"
22#include "llvm/CodeGen/MachineBasicBlock.h"
23#include "llvm/CodeGen/MachineFunction.h"
24#include "llvm/CodeGen/MachineInstr.h"
25#include "llvm/CodeGen/MachineInstrBuilder.h"
26#include "llvm/CodeGen/MachineMemOperand.h"
27#include "llvm/CodeGen/MachineRegisterInfo.h"
28#include "llvm/CodeGen/SelectionDAG.h"
29#include "llvm/CodeGen/SelectionDAGNodes.h"
30#include "llvm/CodeGen/TargetInstrInfo.h"
31#include "llvm/CodeGen/TargetLowering.h"
32#include "llvm/CodeGen/TargetSubtargetInfo.h"
33#include "llvm/CodeGen/ValueTypes.h"
34#include "llvm/CodeGenTypes/MachineValueType.h"
35#include "llvm/IR/DebugLoc.h"
36#include "llvm/IR/Intrinsics.h"
37#include "llvm/IR/IntrinsicsMips.h"
38#include "llvm/Support/Casting.h"
39#include "llvm/Support/CommandLine.h"
40#include "llvm/Support/Debug.h"
41#include "llvm/Support/ErrorHandling.h"
42#include "llvm/Support/raw_ostream.h"
43#include "llvm/TargetParser/Triple.h"
44#include <algorithm>
45#include <cassert>
46#include <cstddef>
47#include <cstdint>
48#include <iterator>
49#include <utility>
50
51using namespace llvm;
52
53#define DEBUG_TYPE "mips-isel"
54
55static cl::opt<bool> NoDPLoadStore("mno-ldc1-sdc1", cl::init(Val: false),
56 cl::desc("Expand double precision loads and "
57 "stores to their single precision "
58 "counterparts"));
59
60// Widen the v2 vectors to the register width, i.e. v2i16 -> v8i16,
61// v2i32 -> v4i32, etc, to ensure the correct rail size is used, i.e.
62// INST.h for v16, INST.w for v32, INST.d for v64.
63TargetLoweringBase::LegalizeTypeAction
64MipsSETargetLowering::getPreferredVectorAction(MVT VT) const {
65 if (this->Subtarget.hasMSA()) {
66 switch (VT.SimpleTy) {
67 // Leave v2i1 vectors to be promoted to larger ones.
68 // Other i1 types will be promoted by default.
69 case MVT::v2i1:
70 return TypePromoteInteger;
71 break;
72 // 16-bit vector types (v2 and longer)
73 case MVT::v2i8:
74 // 32-bit vector types (v2 and longer)
75 case MVT::v2i16:
76 case MVT::v4i8:
77 // 64-bit vector types (v2 and longer)
78 case MVT::v2i32:
79 case MVT::v4i16:
80 case MVT::v8i8:
81 return TypeWidenVector;
82 break;
83 // Only word (.w) and doubleword (.d) are available for floating point
84 // vectors. That means floating point vectors should be either v2f64
85 // or v4f32.
86 // Here we only explicitly widen the f32 types - f16 will be promoted
87 // by default.
88 case MVT::v2f32:
89 case MVT::v3f32:
90 return TypeWidenVector;
91 // v2i64 is already 128-bit wide.
92 default:
93 break;
94 }
95 }
96 return TargetLoweringBase::getPreferredVectorAction(VT);
97}
98
99MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM,
100 const MipsSubtarget &STI)
101 : MipsTargetLowering(TM, STI) {
102 // Set up the register classes
103 addRegisterClass(VT: MVT::i32, RC: &Mips::GPR32RegClass);
104
105 if (Subtarget.isGP64bit())
106 addRegisterClass(VT: MVT::i64, RC: &Mips::GPR64RegClass);
107
108 if (Subtarget.hasDSP() || Subtarget.hasMSA()) {
109 // Expand all truncating stores and extending loads.
110 for (MVT VT0 : MVT::fixedlen_vector_valuetypes()) {
111 for (MVT VT1 : MVT::fixedlen_vector_valuetypes()) {
112 setTruncStoreAction(ValVT: VT0, MemVT: VT1, Action: Expand);
113 setLoadExtAction(ExtType: ISD::SEXTLOAD, ValVT: VT0, MemVT: VT1, Action: Expand);
114 setLoadExtAction(ExtType: ISD::ZEXTLOAD, ValVT: VT0, MemVT: VT1, Action: Expand);
115 setLoadExtAction(ExtType: ISD::EXTLOAD, ValVT: VT0, MemVT: VT1, Action: Expand);
116 }
117 }
118 }
119
120 if (Subtarget.hasDSP()) {
121 MVT::SimpleValueType VecTys[2] = {MVT::v2i16, MVT::v4i8};
122
123 for (const auto &VecTy : VecTys) {
124 addRegisterClass(VT: VecTy, RC: &Mips::DSPRRegClass);
125
126 // Expand all builtin opcodes.
127 for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
128 setOperationAction(Op: Opc, VT: VecTy, Action: Expand);
129
130 setOperationAction(Op: ISD::ADD, VT: VecTy, Action: Legal);
131 setOperationAction(Op: ISD::SUB, VT: VecTy, Action: Legal);
132 setOperationAction(Op: ISD::LOAD, VT: VecTy, Action: Legal);
133 setOperationAction(Op: ISD::STORE, VT: VecTy, Action: Legal);
134 setOperationAction(Op: ISD::BITCAST, VT: VecTy, Action: Legal);
135 }
136
137 setTargetDAGCombine(
138 {ISD::SHL, ISD::SRA, ISD::SRL, ISD::SETCC, ISD::VSELECT});
139
140 if (Subtarget.hasMips32r2()) {
141 setOperationAction(Op: ISD::ADDC, VT: MVT::i32, Action: Legal);
142 setOperationAction(Op: ISD::ADDE, VT: MVT::i32, Action: Legal);
143 }
144 }
145
146 if (Subtarget.hasDSPR2())
147 setOperationAction(Op: ISD::MUL, VT: MVT::v2i16, Action: Legal);
148
149 if (Subtarget.hasMSA()) {
150 addMSAIntType(Ty: MVT::v16i8, RC: &Mips::MSA128BRegClass);
151 addMSAIntType(Ty: MVT::v8i16, RC: &Mips::MSA128HRegClass);
152 addMSAIntType(Ty: MVT::v4i32, RC: &Mips::MSA128WRegClass);
153 addMSAIntType(Ty: MVT::v2i64, RC: &Mips::MSA128DRegClass);
154 addMSAFloatType(Ty: MVT::v8f16, RC: &Mips::MSA128HRegClass);
155 addMSAFloatType(Ty: MVT::v4f32, RC: &Mips::MSA128WRegClass);
156 addMSAFloatType(Ty: MVT::v2f64, RC: &Mips::MSA128DRegClass);
157
158 // We're using soft promotion for f16, but msa has some instructions for
159 // conversion to/from f16. Mark those conversions as custom so we can take
160 // advantage of these instructions.
161 for (MVT VT : {MVT::f32, MVT::f64}) {
162 setOperationAction(Op: ISD::FP16_TO_FP, VT, Action: Custom);
163 setOperationAction(Op: ISD::FP_TO_FP16, VT, Action: Custom);
164 }
165
166 setTargetDAGCombine(
167 {ISD::AND, ISD::OR, ISD::SRA, ISD::VSELECT, ISD::XOR, ISD::FP_TO_UINT});
168 }
169
170 if (!Subtarget.useSoftFloat()) {
171 addRegisterClass(VT: MVT::f32, RC: &Mips::FGR32RegClass);
172
173 // When dealing with single precision only, use libcalls
174 if (!Subtarget.isSingleFloat()) {
175 if (Subtarget.isFP64bit())
176 addRegisterClass(VT: MVT::f64, RC: &Mips::FGR64RegClass);
177 else
178 addRegisterClass(VT: MVT::f64, RC: &Mips::AFGR64RegClass);
179 }
180
181 for (auto Op : {ISD::STRICT_FADD, ISD::STRICT_FSUB, ISD::STRICT_FMUL,
182 ISD::STRICT_FDIV, ISD::STRICT_FSQRT}) {
183 setOperationAction(Op, VT: MVT::f32, Action: Legal);
184 setOperationAction(Op, VT: MVT::f64, Action: Legal);
185 }
186 }
187
188 // Targets with 64bits integer registers, but no 64bit floating point register
189 // do not support conversion between them
190 if (Subtarget.isGP64bit() && Subtarget.isSingleFloat() &&
191 !Subtarget.useSoftFloat()) {
192 setOperationAction(Op: ISD::FP_TO_SINT, VT: MVT::i64, Action: Expand);
193 setOperationAction(Op: ISD::FP_TO_UINT, VT: MVT::i64, Action: Expand);
194 setOperationAction(Op: ISD::SINT_TO_FP, VT: MVT::i64, Action: Expand);
195 setOperationAction(Op: ISD::UINT_TO_FP, VT: MVT::i64, Action: Expand);
196 }
197
198 setOperationAction(Op: ISD::SMUL_LOHI, VT: MVT::i32, Action: Custom);
199 setOperationAction(Op: ISD::UMUL_LOHI, VT: MVT::i32, Action: Custom);
200 setOperationAction(Op: ISD::MULHS, VT: MVT::i32, Action: Custom);
201 setOperationAction(Op: ISD::MULHU, VT: MVT::i32, Action: Custom);
202
203 if (Subtarget.hasCnMips())
204 setOperationAction(Op: ISD::MUL, VT: MVT::i64, Action: Legal);
205 else if (Subtarget.isR5900()) {
206 // R5900 doesn't have DMULT/DMULTU/DDIV/DDIVU - expand to 32-bit ops
207 setOperationAction(Op: ISD::MUL, VT: MVT::i64, Action: Expand);
208 setOperationAction(Op: ISD::SMUL_LOHI, VT: MVT::i64, Action: Expand);
209 setOperationAction(Op: ISD::UMUL_LOHI, VT: MVT::i64, Action: Expand);
210 setOperationAction(Op: ISD::MULHS, VT: MVT::i64, Action: Expand);
211 setOperationAction(Op: ISD::MULHU, VT: MVT::i64, Action: Expand);
212 setOperationAction(Op: ISD::SDIVREM, VT: MVT::i64, Action: Expand);
213 setOperationAction(Op: ISD::UDIVREM, VT: MVT::i64, Action: Expand);
214 } else if (Subtarget.isGP64bit())
215 setOperationAction(Op: ISD::MUL, VT: MVT::i64, Action: Custom);
216
217 if (Subtarget.isGP64bit() && !Subtarget.isR5900()) {
218 setOperationAction(Op: ISD::SMUL_LOHI, VT: MVT::i64, Action: Custom);
219 setOperationAction(Op: ISD::UMUL_LOHI, VT: MVT::i64, Action: Custom);
220 setOperationAction(Op: ISD::MULHS, VT: MVT::i64, Action: Custom);
221 setOperationAction(Op: ISD::MULHU, VT: MVT::i64, Action: Custom);
222 setOperationAction(Op: ISD::SDIVREM, VT: MVT::i64, Action: Custom);
223 setOperationAction(Op: ISD::UDIVREM, VT: MVT::i64, Action: Custom);
224 }
225
226 setOperationAction(Op: ISD::INTRINSIC_WO_CHAIN, VT: MVT::i64, Action: Custom);
227 setOperationAction(Op: ISD::INTRINSIC_W_CHAIN, VT: MVT::i64, Action: Custom);
228
229 setOperationAction(Op: ISD::SDIVREM, VT: MVT::i32, Action: Custom);
230 setOperationAction(Op: ISD::UDIVREM, VT: MVT::i32, Action: Custom);
231 setOperationAction(Op: ISD::ATOMIC_FENCE, VT: MVT::Other, Action: Custom);
232 if (Subtarget.hasMips32r6()) {
233 setOperationAction(Op: ISD::LOAD, VT: MVT::i32, Action: Legal);
234 setOperationAction(Op: ISD::STORE, VT: MVT::i32, Action: Legal);
235 } else {
236 setOperationAction(Op: ISD::LOAD, VT: MVT::i32, Action: Custom);
237 setOperationAction(Op: ISD::STORE, VT: MVT::i32, Action: Custom);
238 }
239
240 setTargetDAGCombine(ISD::MUL);
241
242 setOperationAction(Op: ISD::INTRINSIC_WO_CHAIN, VT: MVT::Other, Action: Custom);
243 setOperationAction(Op: ISD::INTRINSIC_W_CHAIN, VT: MVT::Other, Action: Custom);
244 setOperationAction(Op: ISD::INTRINSIC_VOID, VT: MVT::Other, Action: Custom);
245
246 if (Subtarget.hasMips32r2() && !Subtarget.useSoftFloat() &&
247 !Subtarget.hasMips64()) {
248 setOperationAction(Op: ISD::BITCAST, VT: MVT::i64, Action: Custom);
249 }
250
251 if (NoDPLoadStore) {
252 setOperationAction(Op: ISD::LOAD, VT: MVT::f64, Action: Custom);
253 setOperationAction(Op: ISD::STORE, VT: MVT::f64, Action: Custom);
254 }
255
256 if (Subtarget.hasMips32r6()) {
257 // MIPS32r6 replaces the accumulator-based multiplies with a three register
258 // instruction
259 setOperationAction(Op: ISD::SMUL_LOHI, VT: MVT::i32, Action: Expand);
260 setOperationAction(Op: ISD::UMUL_LOHI, VT: MVT::i32, Action: Expand);
261 setOperationAction(Op: ISD::MUL, VT: MVT::i32, Action: Legal);
262 setOperationAction(Op: ISD::MULHS, VT: MVT::i32, Action: Legal);
263 setOperationAction(Op: ISD::MULHU, VT: MVT::i32, Action: Legal);
264
265 // MIPS32r6 replaces the accumulator-based division/remainder with separate
266 // three register division and remainder instructions.
267 setOperationAction(Op: ISD::SDIVREM, VT: MVT::i32, Action: Expand);
268 setOperationAction(Op: ISD::UDIVREM, VT: MVT::i32, Action: Expand);
269 setOperationAction(Op: ISD::SDIV, VT: MVT::i32, Action: Legal);
270 setOperationAction(Op: ISD::UDIV, VT: MVT::i32, Action: Legal);
271 setOperationAction(Op: ISD::SREM, VT: MVT::i32, Action: Legal);
272 setOperationAction(Op: ISD::UREM, VT: MVT::i32, Action: Legal);
273
274 // MIPS32r6 replaces conditional moves with an equivalent that removes the
275 // need for three GPR read ports.
276 setOperationAction(Op: ISD::SETCC, VT: MVT::i32, Action: Legal);
277 setOperationAction(Op: ISD::SELECT, VT: MVT::i32, Action: Legal);
278 setOperationAction(Op: ISD::SELECT_CC, VT: MVT::i32, Action: Expand);
279
280 setOperationAction(Op: ISD::SETCC, VT: MVT::f32, Action: Legal);
281 setOperationAction(Op: ISD::SELECT, VT: MVT::f32, Action: Legal);
282 setOperationAction(Op: ISD::SELECT_CC, VT: MVT::f32, Action: Expand);
283
284 assert(Subtarget.isFP64bit() && "FR=1 is required for MIPS32r6");
285 setOperationAction(Op: ISD::SETCC, VT: MVT::f64, Action: Legal);
286 setOperationAction(Op: ISD::SELECT, VT: MVT::f64, Action: Legal);
287 setOperationAction(Op: ISD::SELECT_CC, VT: MVT::f64, Action: Expand);
288
289 setOperationAction(Op: ISD::BRCOND, VT: MVT::Other, Action: Legal);
290
291 // Floating point > and >= are supported via < and <=
292 setCondCodeAction(CCs: ISD::SETOGE, VT: MVT::f32, Action: Expand);
293 setCondCodeAction(CCs: ISD::SETOGT, VT: MVT::f32, Action: Expand);
294 setCondCodeAction(CCs: ISD::SETUGE, VT: MVT::f32, Action: Expand);
295 setCondCodeAction(CCs: ISD::SETUGT, VT: MVT::f32, Action: Expand);
296 setCondCodeAction(CCs: ISD::SETONE, VT: MVT::f32, Action: Expand);
297 setCondCodeAction(CCs: ISD::SETO, VT: MVT::f32, Action: Expand);
298 setCondCodeAction(CCs: ISD::SETUNE, VT: MVT::f32, Action: Expand);
299 setCondCodeAction(CCs: ISD::SETNE, VT: MVT::f32, Action: Expand);
300
301 setCondCodeAction(CCs: ISD::SETOGE, VT: MVT::f64, Action: Expand);
302 setCondCodeAction(CCs: ISD::SETOGT, VT: MVT::f64, Action: Expand);
303 setCondCodeAction(CCs: ISD::SETUGE, VT: MVT::f64, Action: Expand);
304 setCondCodeAction(CCs: ISD::SETUGT, VT: MVT::f64, Action: Expand);
305 setCondCodeAction(CCs: ISD::SETONE, VT: MVT::f64, Action: Expand);
306 setCondCodeAction(CCs: ISD::SETO, VT: MVT::f64, Action: Expand);
307 setCondCodeAction(CCs: ISD::SETUNE, VT: MVT::f64, Action: Expand);
308 setCondCodeAction(CCs: ISD::SETNE, VT: MVT::f64, Action: Expand);
309 }
310
311 if (Subtarget.hasMips64r6()) {
312 // MIPS64r6 replaces the accumulator-based multiplies with a three register
313 // instruction
314 setOperationAction(Op: ISD::SMUL_LOHI, VT: MVT::i64, Action: Expand);
315 setOperationAction(Op: ISD::UMUL_LOHI, VT: MVT::i64, Action: Expand);
316 setOperationAction(Op: ISD::MUL, VT: MVT::i64, Action: Legal);
317 setOperationAction(Op: ISD::MULHS, VT: MVT::i64, Action: Legal);
318 setOperationAction(Op: ISD::MULHU, VT: MVT::i64, Action: Legal);
319
320 // MIPS32r6 replaces the accumulator-based division/remainder with separate
321 // three register division and remainder instructions.
322 setOperationAction(Op: ISD::SDIVREM, VT: MVT::i64, Action: Expand);
323 setOperationAction(Op: ISD::UDIVREM, VT: MVT::i64, Action: Expand);
324 setOperationAction(Op: ISD::SDIV, VT: MVT::i64, Action: Legal);
325 setOperationAction(Op: ISD::UDIV, VT: MVT::i64, Action: Legal);
326 setOperationAction(Op: ISD::SREM, VT: MVT::i64, Action: Legal);
327 setOperationAction(Op: ISD::UREM, VT: MVT::i64, Action: Legal);
328
329 // MIPS64r6 replaces conditional moves with an equivalent that removes the
330 // need for three GPR read ports.
331 setOperationAction(Op: ISD::SETCC, VT: MVT::i64, Action: Legal);
332 setOperationAction(Op: ISD::SELECT, VT: MVT::i64, Action: Legal);
333 setOperationAction(Op: ISD::SELECT_CC, VT: MVT::i64, Action: Expand);
334 }
335
336 if (Subtarget.isR5900()) {
337 // R5900 FPU only supports 4 compare conditions: C.F, C.EQ, C.OLT, C.OLE
338 // (and their inversions via bc1t/bc1f). Expand all conditions that would
339 // require C.UN, C.UEQ, C.ULT, or C.ULE instructions (not available on
340 // R5900). The legalizer resolves these via operand swapping, condition
341 // inversion, and decomposition into supported conditions.
342 setCondCodeAction(CCs: ISD::SETOGT, VT: MVT::f32, Action: Expand);
343 setCondCodeAction(CCs: ISD::SETOGE, VT: MVT::f32, Action: Expand);
344 setCondCodeAction(CCs: ISD::SETGT, VT: MVT::f32, Action: Expand);
345 setCondCodeAction(CCs: ISD::SETGE, VT: MVT::f32, Action: Expand);
346 setCondCodeAction(CCs: ISD::SETULT, VT: MVT::f32, Action: Expand);
347 setCondCodeAction(CCs: ISD::SETULE, VT: MVT::f32, Action: Expand);
348 setCondCodeAction(CCs: ISD::SETUO, VT: MVT::f32, Action: Expand);
349 setCondCodeAction(CCs: ISD::SETO, VT: MVT::f32, Action: Expand);
350 setCondCodeAction(CCs: ISD::SETONE, VT: MVT::f32, Action: Expand);
351 setCondCodeAction(CCs: ISD::SETUEQ, VT: MVT::f32, Action: Expand);
352 setCondCodeAction(CCs: ISD::SETNE, VT: MVT::f32, Action: Expand);
353
354 // R5900 FPU does not support IEEE 754 special values (NaN, infinity). Use
355 // custom lowering to decide per-instruction: hardware when nnan+ninf flags
356 // guarantee no NaN or infinity, software libcall otherwise.
357 setOperationAction(Op: ISD::FADD, VT: MVT::f32, Action: Custom);
358 setOperationAction(Op: ISD::FSUB, VT: MVT::f32, Action: Custom);
359 setOperationAction(Op: ISD::FMUL, VT: MVT::f32, Action: Custom);
360 setOperationAction(Op: ISD::FDIV, VT: MVT::f32, Action: Custom);
361 setOperationAction(Op: ISD::FSQRT, VT: MVT::f32, Action: Custom);
362 }
363
364 computeRegisterProperties(TRI: Subtarget.getRegisterInfo());
365}
366
367const MipsTargetLowering *
368llvm::createMipsSETargetLowering(const MipsTargetMachine &TM,
369 const MipsSubtarget &STI) {
370 return new MipsSETargetLowering(TM, STI);
371}
372
373const TargetRegisterClass *
374MipsSETargetLowering::getRepRegClassFor(MVT VT) const {
375 if (VT == MVT::Untyped)
376 return Subtarget.hasDSP() ? &Mips::ACC64DSPRegClass : &Mips::ACC64RegClass;
377
378 return TargetLowering::getRepRegClassFor(VT);
379}
380
381// Enable MSA support for the given integer type and Register class.
382void MipsSETargetLowering::
383addMSAIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) {
384 addRegisterClass(VT: Ty, RC);
385
386 // Expand all builtin opcodes.
387 for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
388 setOperationAction(Op: Opc, VT: Ty, Action: Expand);
389
390 setOperationAction(Op: ISD::BITCAST, VT: Ty, Action: Legal);
391 setOperationAction(Op: ISD::LOAD, VT: Ty, Action: Legal);
392 setOperationAction(Op: ISD::STORE, VT: Ty, Action: Legal);
393 setOperationAction(Op: ISD::EXTRACT_VECTOR_ELT, VT: Ty, Action: Custom);
394 setOperationAction(Op: ISD::INSERT_VECTOR_ELT, VT: Ty, Action: Legal);
395 setOperationAction(Op: ISD::BUILD_VECTOR, VT: Ty, Action: Custom);
396 setOperationAction(Ops: {ISD::UNDEF, ISD::POISON}, VT: Ty, Action: Legal);
397
398 setOperationAction(Op: ISD::ADD, VT: Ty, Action: Legal);
399 setOperationAction(Op: ISD::AND, VT: Ty, Action: Legal);
400 setOperationAction(Op: ISD::CTLZ, VT: Ty, Action: Legal);
401 setOperationAction(Op: ISD::CTPOP, VT: Ty, Action: Legal);
402 setOperationAction(Op: ISD::MUL, VT: Ty, Action: Legal);
403 setOperationAction(Op: ISD::OR, VT: Ty, Action: Legal);
404 setOperationAction(Op: ISD::SDIV, VT: Ty, Action: Legal);
405 setOperationAction(Op: ISD::SREM, VT: Ty, Action: Legal);
406 setOperationAction(Op: ISD::SHL, VT: Ty, Action: Legal);
407 setOperationAction(Op: ISD::SRA, VT: Ty, Action: Legal);
408 setOperationAction(Op: ISD::SRL, VT: Ty, Action: Legal);
409 setOperationAction(Op: ISD::SUB, VT: Ty, Action: Legal);
410 setOperationAction(Op: ISD::SMAX, VT: Ty, Action: Legal);
411 setOperationAction(Op: ISD::SMIN, VT: Ty, Action: Legal);
412 setOperationAction(Op: ISD::UDIV, VT: Ty, Action: Legal);
413 setOperationAction(Op: ISD::UREM, VT: Ty, Action: Legal);
414 setOperationAction(Op: ISD::UMAX, VT: Ty, Action: Legal);
415 setOperationAction(Op: ISD::UMIN, VT: Ty, Action: Legal);
416 setOperationAction(Op: ISD::VECTOR_SHUFFLE, VT: Ty, Action: Custom);
417 setOperationAction(Op: ISD::VSELECT, VT: Ty, Action: Legal);
418 setOperationAction(Op: ISD::XOR, VT: Ty, Action: Legal);
419
420 if (Ty == MVT::v4i32 || Ty == MVT::v2i64) {
421 setOperationAction(Op: ISD::FP_TO_SINT, VT: Ty, Action: Legal);
422 setOperationAction(Op: ISD::FP_TO_UINT, VT: Ty, Action: Legal);
423 setOperationAction(Op: ISD::SINT_TO_FP, VT: Ty, Action: Legal);
424 setOperationAction(Op: ISD::UINT_TO_FP, VT: Ty, Action: Legal);
425 }
426
427 setOperationAction(Op: ISD::SETCC, VT: Ty, Action: Legal);
428 setCondCodeAction(CCs: ISD::SETNE, VT: Ty, Action: Expand);
429 setCondCodeAction(CCs: ISD::SETGE, VT: Ty, Action: Expand);
430 setCondCodeAction(CCs: ISD::SETGT, VT: Ty, Action: Expand);
431 setCondCodeAction(CCs: ISD::SETUGE, VT: Ty, Action: Expand);
432 setCondCodeAction(CCs: ISD::SETUGT, VT: Ty, Action: Expand);
433}
434
435// Enable MSA support for the given floating-point type and Register class.
436void MipsSETargetLowering::
437addMSAFloatType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) {
438 addRegisterClass(VT: Ty, RC);
439
440 // Expand all builtin opcodes.
441 for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
442 setOperationAction(Op: Opc, VT: Ty, Action: Expand);
443
444 setOperationAction(Op: ISD::LOAD, VT: Ty, Action: Legal);
445 setOperationAction(Op: ISD::STORE, VT: Ty, Action: Legal);
446 setOperationAction(Op: ISD::BITCAST, VT: Ty, Action: Legal);
447 setOperationAction(Op: ISD::EXTRACT_VECTOR_ELT, VT: Ty, Action: Legal);
448 setOperationAction(Op: ISD::INSERT_VECTOR_ELT, VT: Ty, Action: Legal);
449 setOperationAction(Op: ISD::BUILD_VECTOR, VT: Ty, Action: Custom);
450 setOperationAction(Op: ISD::UNDEF, VT: Ty, Action: Legal);
451
452 if (Ty != MVT::v8f16) {
453 setOperationAction(Op: ISD::FABS, VT: Ty, Action: Legal);
454 setOperationAction(Op: ISD::FADD, VT: Ty, Action: Legal);
455 setOperationAction(Op: ISD::FDIV, VT: Ty, Action: Legal);
456 setOperationAction(Op: ISD::FEXP2, VT: Ty, Action: Legal);
457 setOperationAction(Op: ISD::FLOG2, VT: Ty, Action: Legal);
458 setOperationAction(Op: ISD::FMA, VT: Ty, Action: Legal);
459 setOperationAction(Op: ISD::FMUL, VT: Ty, Action: Legal);
460 setOperationAction(Op: ISD::FRINT, VT: Ty, Action: Legal);
461 setOperationAction(Op: ISD::FSQRT, VT: Ty, Action: Legal);
462 setOperationAction(Op: ISD::FSUB, VT: Ty, Action: Legal);
463 setOperationAction(Op: ISD::VSELECT, VT: Ty, Action: Legal);
464
465 setOperationAction(Op: ISD::SETCC, VT: Ty, Action: Legal);
466 setCondCodeAction(CCs: ISD::SETOGE, VT: Ty, Action: Expand);
467 setCondCodeAction(CCs: ISD::SETOGT, VT: Ty, Action: Expand);
468 setCondCodeAction(CCs: ISD::SETUGE, VT: Ty, Action: Expand);
469 setCondCodeAction(CCs: ISD::SETUGT, VT: Ty, Action: Expand);
470 setCondCodeAction(CCs: ISD::SETGE, VT: Ty, Action: Expand);
471 setCondCodeAction(CCs: ISD::SETGT, VT: Ty, Action: Expand);
472 }
473}
474
475SDValue MipsSETargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
476 if(!Subtarget.hasMips32r6())
477 return MipsTargetLowering::LowerOperation(Op, DAG);
478
479 EVT ResTy = Op->getValueType(ResNo: 0);
480 SDLoc DL(Op);
481
482 // Although MTC1_D64 takes an i32 and writes an f64, the upper 32 bits of the
483 // floating point register are undefined. Not really an issue as sel.d, which
484 // is produced from an FSELECT node, only looks at bit 0.
485 SDValue Tmp = DAG.getNode(Opcode: MipsISD::MTC1_D64, DL, VT: MVT::f64, Operand: Op->getOperand(Num: 0));
486 return DAG.getNode(Opcode: MipsISD::FSELECT, DL, VT: ResTy, N1: Tmp, N2: Op->getOperand(Num: 1),
487 N3: Op->getOperand(Num: 2));
488}
489
490// Lower FP16_TO_FP (the soft-promote-half representation of an f16 -> f32/f64
491// conversion).
492SDValue MipsSETargetLowering::lowerFP16_TO_FP(SDValue Op,
493 SelectionDAG &DAG) const {
494 SDLoc DL(Op);
495 EVT ResTy = Op.getValueType();
496 assert((ResTy == MVT::f32 || ResTy == MVT::f64) && "Unexpected FP16_TO_FP");
497
498 // The operand type is i32 because i16 isn't actually legal on MIPS.
499 SDValue In = Op.getOperand(i: 0);
500 assert(In.getValueType() == MVT::i32 && "Unexpected FP16_TO_FP operand type");
501
502 // Splat into a v8i16 (the 32-bit In value is truncated to the lower 16 bits).
503 SDValue Splatted = DAG.getSplatBuildVector(VT: MVT::v8i16, DL, Op: In);
504
505 // Bitcast from v8i16 to v8f16.
506 SDValue HVec = DAG.getNode(Opcode: ISD::BITCAST, DL, VT: MVT::v8f16, Operand: Splatted);
507
508 // Convert from v8f16 to v4f32.
509 SDValue F32Vec = DAG.getNode(
510 Opcode: ISD::INTRINSIC_WO_CHAIN, DL, VT: MVT::v4f32,
511 N1: DAG.getConstant(Val: Intrinsic::mips_fexupr_w, DL, VT: MVT::i32), N2: HVec);
512 SDValue Res;
513 if (ResTy == MVT::f32) {
514 // Every lane has the converted value, just read it from lane 0.
515 Res = DAG.getNode(Opcode: ISD::EXTRACT_VECTOR_ELT, DL, VT: MVT::f32, N1: F32Vec,
516 N2: DAG.getVectorIdxConstant(Val: 0, DL));
517 } else {
518 // Convert from v4f32 to v2f64.
519 SDValue F64Vec = DAG.getNode(
520 Opcode: ISD::INTRINSIC_WO_CHAIN, DL, VT: MVT::v2f64,
521 N1: DAG.getConstant(Val: Intrinsic::mips_fexupr_d, DL, VT: MVT::i32), N2: F32Vec);
522 // Every lane has the converted value, just read it from lane 0.
523 Res = DAG.getNode(Opcode: ISD::EXTRACT_VECTOR_ELT, DL, VT: MVT::f64, N1: F64Vec,
524 N2: DAG.getVectorIdxConstant(Val: 0, DL));
525 }
526
527 return Res;
528}
529
530// Lower FP_TO_FP16 (the soft-promote-half representation of an f32/f64 -> f16
531// conversion)
532SDValue MipsSETargetLowering::lowerFP_TO_FP16(SDValue Op,
533 SelectionDAG &DAG) const {
534 SDLoc DL(Op);
535 EVT ResTy = Op.getValueType();
536 SDValue In = Op.getOperand(i: 0);
537 assert((In.getValueType() == MVT::f32 || In.getValueType() == MVT::f64) &&
538 "Unexpected FP_TO_FP16");
539
540 SDValue F32Vec;
541 if (In.getValueType() == MVT::f64) {
542 // Splat f64 to v2f64, then convert to v4f32.
543 SDValue F64Vec = DAG.getSplatBuildVector(VT: MVT::v2f64, DL, Op: In);
544 F32Vec = DAG.getNode(Opcode: ISD::INTRINSIC_WO_CHAIN, DL, VT: MVT::v4f32,
545 N1: DAG.getConstant(Val: Intrinsic::mips_fexdo_w, DL, VT: MVT::i32),
546 N2: F64Vec, N3: F64Vec);
547 } else {
548 // Splat f32 to v4f32.
549 F32Vec = DAG.getSplatBuildVector(VT: MVT::v4f32, DL, Op: In);
550 }
551
552 // Then convert from v4f32 to v8f16.
553 SDValue HVec = DAG.getNode(
554 Opcode: ISD::INTRINSIC_WO_CHAIN, DL, VT: MVT::v8f16,
555 N1: DAG.getConstant(Val: Intrinsic::mips_fexdo_h, DL, VT: MVT::i32), N2: F32Vec, N3: F32Vec);
556
557 // Finally cast to v8i16 (f16 is soft-promoted).
558 SDValue IVec = DAG.getNode(Opcode: ISD::BITCAST, DL, VT: MVT::v8i16, Operand: HVec);
559 SDValue Res = DAG.getNode(Opcode: ISD::EXTRACT_VECTOR_ELT, DL, VT: ResTy, N1: IVec,
560 N2: DAG.getVectorIdxConstant(Val: 0, DL));
561
562 return Res;
563}
564
565bool MipsSETargetLowering::allowsMisalignedMemoryAccesses(
566 EVT VT, unsigned, Align, MachineMemOperand::Flags, unsigned *Fast) const {
567 MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy;
568
569 if (Subtarget.systemSupportsUnalignedAccess()) {
570 // MIPS32r6/MIPS64r6 is required to support unaligned access. It's
571 // implementation defined whether this is handled by hardware, software, or
572 // a hybrid of the two but it's expected that most implementations will
573 // handle the majority of cases in hardware.
574 if (Fast)
575 *Fast = 1;
576 return true;
577 } else if (Subtarget.hasMips32r6()) {
578 return false;
579 }
580
581 switch (SVT) {
582 case MVT::i64:
583 case MVT::i32:
584 if (Fast)
585 *Fast = 1;
586 return true;
587 default:
588 return false;
589 }
590}
591
592SDValue MipsSETargetLowering::LowerOperation(SDValue Op,
593 SelectionDAG &DAG) const {
594 switch(Op.getOpcode()) {
595 case ISD::LOAD: return lowerLOAD(Op, DAG);
596 case ISD::STORE: return lowerSTORE(Op, DAG);
597 case ISD::SMUL_LOHI: return lowerMulDiv(Op, NewOpc: MipsISD::Mult, HasLo: true, HasHi: true, DAG);
598 case ISD::UMUL_LOHI: return lowerMulDiv(Op, NewOpc: MipsISD::Multu, HasLo: true, HasHi: true, DAG);
599 case ISD::MULHS: return lowerMulDiv(Op, NewOpc: MipsISD::Mult, HasLo: false, HasHi: true, DAG);
600 case ISD::MULHU: return lowerMulDiv(Op, NewOpc: MipsISD::Multu, HasLo: false, HasHi: true, DAG);
601 case ISD::MUL: return lowerMulDiv(Op, NewOpc: MipsISD::Mult, HasLo: true, HasHi: false, DAG);
602 case ISD::SDIVREM: return lowerMulDiv(Op, NewOpc: MipsISD::DivRem, HasLo: true, HasHi: true, DAG);
603 case ISD::UDIVREM: return lowerMulDiv(Op, NewOpc: MipsISD::DivRemU, HasLo: true, HasHi: true,
604 DAG);
605 case ISD::INTRINSIC_WO_CHAIN: return lowerINTRINSIC_WO_CHAIN(Op, DAG);
606 case ISD::INTRINSIC_W_CHAIN: return lowerINTRINSIC_W_CHAIN(Op, DAG);
607 case ISD::INTRINSIC_VOID: return lowerINTRINSIC_VOID(Op, DAG);
608 case ISD::EXTRACT_VECTOR_ELT: return lowerEXTRACT_VECTOR_ELT(Op, DAG);
609 case ISD::BUILD_VECTOR: return lowerBUILD_VECTOR(Op, DAG);
610 case ISD::VECTOR_SHUFFLE: return lowerVECTOR_SHUFFLE(Op, DAG);
611 case ISD::SELECT:
612 return lowerSELECT(Op, DAG);
613 case ISD::FP16_TO_FP:
614 case ISD::STRICT_FP16_TO_FP:
615 return lowerFP16_TO_FP(Op, DAG);
616 case ISD::FP_TO_FP16:
617 case ISD::STRICT_FP_TO_FP16:
618 return lowerFP_TO_FP16(Op, DAG);
619 case ISD::BITCAST: return lowerBITCAST(Op, DAG);
620 case ISD::FADD:
621 return lowerR5900FPOp(Op, DAG, LC: RTLIB::ADD_F32);
622 case ISD::FSUB:
623 return lowerR5900FPOp(Op, DAG, LC: RTLIB::SUB_F32);
624 case ISD::FMUL:
625 return lowerR5900FPOp(Op, DAG, LC: RTLIB::MUL_F32);
626 case ISD::FDIV:
627 return lowerR5900FPOp(Op, DAG, LC: RTLIB::DIV_F32);
628 case ISD::FSQRT:
629 return lowerR5900FPOp(Op, DAG, LC: RTLIB::SQRT_F32);
630 }
631
632 return MipsTargetLowering::LowerOperation(Op, DAG);
633}
634
635SDValue MipsSETargetLowering::lowerR5900FPOp(SDValue Op, SelectionDAG &DAG,
636 RTLIB::Libcall LC) const {
637 assert(Subtarget.isR5900());
638 SDNodeFlags Flags = Op->getFlags();
639
640 if (Flags.hasNoNaNs() && Flags.hasNoInfs()) {
641 // Use the hardware FPU instruction if the operation is guaranteed to have
642 // no NaN or infinity inputs/outputs (nnan+ninf flags).
643 return Op;
644 }
645
646 // Fall back to a software libcall for IEEE correctness.
647 SDLoc DL(Op);
648 MVT VT = Op.getSimpleValueType();
649 SmallVector<SDValue, 2> Ops(Op->op_begin(), Op->op_end());
650 TargetLowering::MakeLibCallOptions CallOptions;
651 auto [Result, Chain] = makeLibCall(DAG, LC, RetVT: VT, Ops, CallOptions, dl: DL);
652 return Result;
653}
654
655// Fold zero extensions into MipsISD::VEXTRACT_[SZ]EXT_ELT
656//
657// Performs the following transformations:
658// - Changes MipsISD::VEXTRACT_[SZ]EXT_ELT to zero extension if its
659// sign/zero-extension is completely overwritten by the new one performed by
660// the ISD::AND.
661// - Removes redundant zero extensions performed by an ISD::AND.
662static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
663 TargetLowering::DAGCombinerInfo &DCI,
664 const MipsSubtarget &Subtarget) {
665 if (!Subtarget.hasMSA())
666 return SDValue();
667
668 SDValue Op0 = N->getOperand(Num: 0);
669 SDValue Op1 = N->getOperand(Num: 1);
670 unsigned Op0Opcode = Op0->getOpcode();
671
672 // (and (MipsVExtract[SZ]Ext $a, $b, $c), imm:$d)
673 // where $d + 1 == 2^n and n == 32
674 // or $d + 1 == 2^n and n <= 32 and ZExt
675 // -> (MipsVExtractZExt $a, $b, $c)
676 if (Op0Opcode == MipsISD::VEXTRACT_SEXT_ELT ||
677 Op0Opcode == MipsISD::VEXTRACT_ZEXT_ELT) {
678 ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(Val&: Op1);
679
680 if (!Mask)
681 return SDValue();
682
683 int32_t Log2IfPositive = (Mask->getAPIntValue() + 1).exactLogBase2();
684
685 if (Log2IfPositive <= 0)
686 return SDValue(); // Mask+1 is not a power of 2
687
688 SDValue Op0Op2 = Op0->getOperand(Num: 2);
689 EVT ExtendTy = cast<VTSDNode>(Val&: Op0Op2)->getVT();
690 unsigned ExtendTySize = ExtendTy.getSizeInBits();
691 unsigned Log2 = Log2IfPositive;
692
693 if ((Op0Opcode == MipsISD::VEXTRACT_ZEXT_ELT && Log2 >= ExtendTySize) ||
694 Log2 == ExtendTySize) {
695 SDValue Ops[] = { Op0->getOperand(Num: 0), Op0->getOperand(Num: 1), Op0Op2 };
696 return DAG.getNode(Opcode: MipsISD::VEXTRACT_ZEXT_ELT, DL: SDLoc(Op0),
697 VTList: Op0->getVTList(),
698 Ops: ArrayRef(Ops, Op0->getNumOperands()));
699 }
700 }
701
702 return SDValue();
703}
704
705// Determine if the specified node is a constant vector splat.
706//
707// Returns true and sets Imm if:
708// * N is a ISD::BUILD_VECTOR representing a constant splat
709//
710// This function is quite similar to MipsSEDAGToDAGISel::selectVSplat. The
711// differences are that it assumes the MSA has already been checked and the
712// arbitrary requirement for a maximum of 32-bit integers isn't applied (and
713// must not be in order for binsri.d to be selectable).
714static bool isVSplat(SDValue N, APInt &Imm, bool IsLittleEndian) {
715 BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(Val: N.getNode());
716
717 if (!Node)
718 return false;
719
720 APInt SplatValue, SplatUndef;
721 unsigned SplatBitSize;
722 bool HasAnyUndefs;
723
724 if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
725 MinSplatBits: 8, isBigEndian: !IsLittleEndian))
726 return false;
727
728 Imm = SplatValue;
729
730 return true;
731}
732
733// Test whether the given node is an all-ones build_vector.
734static bool isVectorAllOnes(SDValue N) {
735 // Look through bitcasts. Endianness doesn't matter because we are looking
736 // for an all-ones value.
737 if (N->getOpcode() == ISD::BITCAST)
738 N = N->getOperand(Num: 0);
739
740 BuildVectorSDNode *BVN = dyn_cast<BuildVectorSDNode>(Val&: N);
741
742 if (!BVN)
743 return false;
744
745 APInt SplatValue, SplatUndef;
746 unsigned SplatBitSize;
747 bool HasAnyUndefs;
748
749 // Endianness doesn't matter in this context because we are looking for
750 // an all-ones value.
751 if (BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs))
752 return SplatValue.isAllOnes();
753
754 return false;
755}
756
757// Test whether N is the bitwise inverse of OfNode.
758static bool isBitwiseInverse(SDValue N, SDValue OfNode) {
759 if (N->getOpcode() != ISD::XOR)
760 return false;
761
762 if (isVectorAllOnes(N: N->getOperand(Num: 0)))
763 return N->getOperand(Num: 1) == OfNode;
764
765 if (isVectorAllOnes(N: N->getOperand(Num: 1)))
766 return N->getOperand(Num: 0) == OfNode;
767
768 return false;
769}
770
771// Perform combines where ISD::OR is the root node.
772//
773// Performs the following transformations:
774// - (or (and $a, $mask), (and $b, $inv_mask)) => (vselect $mask, $a, $b)
775// where $inv_mask is the bitwise inverse of $mask and the 'or' has a 128-bit
776// vector type.
777static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
778 TargetLowering::DAGCombinerInfo &DCI,
779 const MipsSubtarget &Subtarget) {
780 if (!Subtarget.hasMSA())
781 return SDValue();
782
783 EVT Ty = N->getValueType(ResNo: 0);
784
785 if (!Ty.is128BitVector())
786 return SDValue();
787
788 SDValue Op0 = N->getOperand(Num: 0);
789 SDValue Op1 = N->getOperand(Num: 1);
790
791 if (Op0->getOpcode() == ISD::AND && Op1->getOpcode() == ISD::AND) {
792 SDValue Op0Op0 = Op0->getOperand(Num: 0);
793 SDValue Op0Op1 = Op0->getOperand(Num: 1);
794 SDValue Op1Op0 = Op1->getOperand(Num: 0);
795 SDValue Op1Op1 = Op1->getOperand(Num: 1);
796 bool IsLittleEndian = !Subtarget.isLittle();
797
798 SDValue IfSet, IfClr, Cond;
799 bool IsConstantMask = false;
800 APInt Mask, InvMask;
801
802 // If Op0Op0 is an appropriate mask, try to find it's inverse in either
803 // Op1Op0, or Op1Op1. Keep track of the Cond, IfSet, and IfClr nodes, while
804 // looking.
805 // IfClr will be set if we find a valid match.
806 if (isVSplat(N: Op0Op0, Imm&: Mask, IsLittleEndian)) {
807 Cond = Op0Op0;
808 IfSet = Op0Op1;
809
810 if (isVSplat(N: Op1Op0, Imm&: InvMask, IsLittleEndian) &&
811 Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask)
812 IfClr = Op1Op1;
813 else if (isVSplat(N: Op1Op1, Imm&: InvMask, IsLittleEndian) &&
814 Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask)
815 IfClr = Op1Op0;
816
817 IsConstantMask = true;
818 }
819
820 // If IfClr is not yet set, and Op0Op1 is an appropriate mask, try the same
821 // thing again using this mask.
822 // IfClr will be set if we find a valid match.
823 if (!IfClr.getNode() && isVSplat(N: Op0Op1, Imm&: Mask, IsLittleEndian)) {
824 Cond = Op0Op1;
825 IfSet = Op0Op0;
826
827 if (isVSplat(N: Op1Op0, Imm&: InvMask, IsLittleEndian) &&
828 Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask)
829 IfClr = Op1Op1;
830 else if (isVSplat(N: Op1Op1, Imm&: InvMask, IsLittleEndian) &&
831 Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask)
832 IfClr = Op1Op0;
833
834 IsConstantMask = true;
835 }
836
837 // If IfClr is not yet set, try looking for a non-constant match.
838 // IfClr will be set if we find a valid match amongst the eight
839 // possibilities.
840 if (!IfClr.getNode()) {
841 if (isBitwiseInverse(N: Op0Op0, OfNode: Op1Op0)) {
842 Cond = Op1Op0;
843 IfSet = Op1Op1;
844 IfClr = Op0Op1;
845 } else if (isBitwiseInverse(N: Op0Op1, OfNode: Op1Op0)) {
846 Cond = Op1Op0;
847 IfSet = Op1Op1;
848 IfClr = Op0Op0;
849 } else if (isBitwiseInverse(N: Op0Op0, OfNode: Op1Op1)) {
850 Cond = Op1Op1;
851 IfSet = Op1Op0;
852 IfClr = Op0Op1;
853 } else if (isBitwiseInverse(N: Op0Op1, OfNode: Op1Op1)) {
854 Cond = Op1Op1;
855 IfSet = Op1Op0;
856 IfClr = Op0Op0;
857 } else if (isBitwiseInverse(N: Op1Op0, OfNode: Op0Op0)) {
858 Cond = Op0Op0;
859 IfSet = Op0Op1;
860 IfClr = Op1Op1;
861 } else if (isBitwiseInverse(N: Op1Op1, OfNode: Op0Op0)) {
862 Cond = Op0Op0;
863 IfSet = Op0Op1;
864 IfClr = Op1Op0;
865 } else if (isBitwiseInverse(N: Op1Op0, OfNode: Op0Op1)) {
866 Cond = Op0Op1;
867 IfSet = Op0Op0;
868 IfClr = Op1Op1;
869 } else if (isBitwiseInverse(N: Op1Op1, OfNode: Op0Op1)) {
870 Cond = Op0Op1;
871 IfSet = Op0Op0;
872 IfClr = Op1Op0;
873 }
874 }
875
876 // At this point, IfClr will be set if we have a valid match.
877 if (!IfClr.getNode())
878 return SDValue();
879
880 assert(Cond.getNode() && IfSet.getNode());
881
882 // Fold degenerate cases.
883 if (IsConstantMask) {
884 if (Mask.isAllOnes())
885 return IfSet;
886 else if (Mask == 0)
887 return IfClr;
888 }
889
890 // Transform the DAG into an equivalent VSELECT.
891 return DAG.getNode(Opcode: ISD::VSELECT, DL: SDLoc(N), VT: Ty, N1: Cond, N2: IfSet, N3: IfClr);
892 }
893
894 return SDValue();
895}
896
897static bool shouldTransformMulToShiftsAddsSubs(APInt C, EVT VT,
898 SelectionDAG &DAG,
899 const MipsSubtarget &Subtarget) {
900 // Estimate the number of operations the below transform will turn a
901 // constant multiply into. The number is approximately equal to the minimal
902 // number of powers of two that constant can be broken down to by adding
903 // or subtracting them.
904 //
905 // If we have taken more than 12[1] / 8[2] steps to attempt the
906 // optimization for a native sized value, it is more than likely that this
907 // optimization will make things worse.
908 //
909 // [1] MIPS64 requires 6 instructions at most to materialize any constant,
910 // multiplication requires at least 4 cycles, but another cycle (or two)
911 // to retrieve the result from the HI/LO registers.
912 //
913 // [2] For MIPS32, more than 8 steps is expensive as the constant could be
914 // materialized in 2 instructions, multiplication requires at least 4
915 // cycles, but another cycle (or two) to retrieve the result from the
916 // HI/LO registers.
917 //
918 // TODO:
919 // - MaxSteps needs to consider the `VT` of the constant for the current
920 // target.
921 // - Consider to perform this optimization after type legalization.
922 // That allows to remove a workaround for types not supported natively.
923 // - Take in account `-Os, -Oz` flags because this optimization
924 // increases code size.
925 unsigned MaxSteps = Subtarget.isABI_O32() ? 8 : 12;
926
927 SmallVector<APInt, 16> WorkStack(1, C);
928 unsigned Steps = 0;
929 unsigned BitWidth = C.getBitWidth();
930
931 while (!WorkStack.empty()) {
932 APInt Val = WorkStack.pop_back_val();
933
934 if (Val == 0 || Val == 1)
935 continue;
936
937 if (Steps >= MaxSteps)
938 return false;
939
940 if (Val.isPowerOf2()) {
941 ++Steps;
942 continue;
943 }
944
945 APInt Floor = APInt(BitWidth, 1) << Val.logBase2();
946 APInt Ceil = Val.isNegative() ? APInt(BitWidth, 0)
947 : APInt(BitWidth, 1) << C.ceilLogBase2();
948 if ((Val - Floor).ule(RHS: Ceil - Val)) {
949 WorkStack.push_back(Elt: Floor);
950 WorkStack.push_back(Elt: Val - Floor);
951 } else {
952 WorkStack.push_back(Elt: Ceil);
953 WorkStack.push_back(Elt: Ceil - Val);
954 }
955
956 ++Steps;
957 }
958
959 // If the value being multiplied is not supported natively, we have to pay
960 // an additional legalization cost, conservatively assume an increase in the
961 // cost of 3 instructions per step. This values for this heuristic were
962 // determined experimentally.
963 unsigned RegisterSize = DAG.getTargetLoweringInfo()
964 .getRegisterType(Context&: *DAG.getContext(), VT)
965 .getSizeInBits();
966 Steps *= (VT.getSizeInBits() != RegisterSize) * 3;
967 if (Steps > 27)
968 return false;
969
970 return true;
971}
972
973static SDValue genConstMult(SDValue X, APInt C, const SDLoc &DL, EVT VT,
974 EVT ShiftTy, SelectionDAG &DAG) {
975 // Return 0.
976 if (C == 0)
977 return DAG.getConstant(Val: 0, DL, VT);
978
979 // Return x.
980 if (C == 1)
981 return X;
982
983 // If c is power of 2, return (shl x, log2(c)).
984 if (C.isPowerOf2())
985 return DAG.getNode(Opcode: ISD::SHL, DL, VT, N1: X,
986 N2: DAG.getConstant(Val: C.logBase2(), DL, VT: ShiftTy));
987
988 unsigned BitWidth = C.getBitWidth();
989 APInt Floor = APInt(BitWidth, 1) << C.logBase2();
990 APInt Ceil = C.isNegative() ? APInt(BitWidth, 0) :
991 APInt(BitWidth, 1) << C.ceilLogBase2();
992
993 // If |c - floor_c| <= |c - ceil_c|,
994 // where floor_c = pow(2, floor(log2(c))) and ceil_c = pow(2, ceil(log2(c))),
995 // return (add constMult(x, floor_c), constMult(x, c - floor_c)).
996 if ((C - Floor).ule(RHS: Ceil - C)) {
997 SDValue Op0 = genConstMult(X, C: Floor, DL, VT, ShiftTy, DAG);
998 SDValue Op1 = genConstMult(X, C: C - Floor, DL, VT, ShiftTy, DAG);
999 return DAG.getNode(Opcode: ISD::ADD, DL, VT, N1: Op0, N2: Op1);
1000 }
1001
1002 // If |c - floor_c| > |c - ceil_c|,
1003 // return (sub constMult(x, ceil_c), constMult(x, ceil_c - c)).
1004 SDValue Op0 = genConstMult(X, C: Ceil, DL, VT, ShiftTy, DAG);
1005 SDValue Op1 = genConstMult(X, C: Ceil - C, DL, VT, ShiftTy, DAG);
1006 return DAG.getNode(Opcode: ISD::SUB, DL, VT, N1: Op0, N2: Op1);
1007}
1008
1009static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG,
1010 const TargetLowering::DAGCombinerInfo &DCI,
1011 const MipsSETargetLowering *TL,
1012 const MipsSubtarget &Subtarget) {
1013 EVT VT = N->getValueType(ResNo: 0);
1014
1015 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val: N->getOperand(Num: 1)))
1016 if (!VT.isVector() && shouldTransformMulToShiftsAddsSubs(
1017 C: C->getAPIntValue(), VT, DAG, Subtarget))
1018 return genConstMult(X: N->getOperand(Num: 0), C: C->getAPIntValue(), DL: SDLoc(N), VT,
1019 ShiftTy: TL->getScalarShiftAmountTy(DAG.getDataLayout(), VT),
1020 DAG);
1021
1022 return SDValue(N, 0);
1023}
1024
1025static SDValue performDSPShiftCombine(unsigned Opc, SDNode *N, EVT Ty,
1026 SelectionDAG &DAG,
1027 const MipsSubtarget &Subtarget) {
1028 // See if this is a vector splat immediate node.
1029 APInt SplatValue, SplatUndef;
1030 unsigned SplatBitSize;
1031 bool HasAnyUndefs;
1032 unsigned EltSize = Ty.getScalarSizeInBits();
1033 BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(Val: N->getOperand(Num: 1));
1034
1035 if (!Subtarget.hasDSP())
1036 return SDValue();
1037
1038 if (!BV ||
1039 !BV->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
1040 MinSplatBits: EltSize, isBigEndian: !Subtarget.isLittle()) ||
1041 (SplatBitSize != EltSize) ||
1042 (SplatValue.getZExtValue() >= EltSize))
1043 return SDValue();
1044
1045 SDLoc DL(N);
1046 return DAG.getNode(Opcode: Opc, DL, VT: Ty, N1: N->getOperand(Num: 0),
1047 N2: DAG.getConstant(Val: SplatValue.getZExtValue(), DL, VT: MVT::i32));
1048}
1049
1050static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
1051 TargetLowering::DAGCombinerInfo &DCI,
1052 const MipsSubtarget &Subtarget) {
1053 EVT Ty = N->getValueType(ResNo: 0);
1054
1055 if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8))
1056 return SDValue();
1057
1058 return performDSPShiftCombine(Opc: MipsISD::SHLL_DSP, N, Ty, DAG, Subtarget);
1059}
1060
1061// Fold sign-extensions into MipsISD::VEXTRACT_[SZ]EXT_ELT for MSA and fold
1062// constant splats into MipsISD::SHRA_DSP for DSPr2.
1063//
1064// Performs the following transformations:
1065// - Changes MipsISD::VEXTRACT_[SZ]EXT_ELT to sign extension if its
1066// sign/zero-extension is completely overwritten by the new one performed by
1067// the ISD::SRA and ISD::SHL nodes.
1068// - Removes redundant sign extensions performed by an ISD::SRA and ISD::SHL
1069// sequence.
1070//
1071// See performDSPShiftCombine for more information about the transformation
1072// used for DSPr2.
1073static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG,
1074 TargetLowering::DAGCombinerInfo &DCI,
1075 const MipsSubtarget &Subtarget) {
1076 EVT Ty = N->getValueType(ResNo: 0);
1077
1078 if (Subtarget.hasMSA()) {
1079 SDValue Op0 = N->getOperand(Num: 0);
1080 SDValue Op1 = N->getOperand(Num: 1);
1081
1082 // (sra (shl (MipsVExtract[SZ]Ext $a, $b, $c), imm:$d), imm:$d)
1083 // where $d + sizeof($c) == 32
1084 // or $d + sizeof($c) <= 32 and SExt
1085 // -> (MipsVExtractSExt $a, $b, $c)
1086 if (Op0->getOpcode() == ISD::SHL && Op1 == Op0->getOperand(Num: 1)) {
1087 SDValue Op0Op0 = Op0->getOperand(Num: 0);
1088 ConstantSDNode *ShAmount = dyn_cast<ConstantSDNode>(Val&: Op1);
1089
1090 if (!ShAmount)
1091 return SDValue();
1092
1093 if (Op0Op0->getOpcode() != MipsISD::VEXTRACT_SEXT_ELT &&
1094 Op0Op0->getOpcode() != MipsISD::VEXTRACT_ZEXT_ELT)
1095 return SDValue();
1096
1097 EVT ExtendTy = cast<VTSDNode>(Val: Op0Op0->getOperand(Num: 2))->getVT();
1098 unsigned TotalBits = ShAmount->getZExtValue() + ExtendTy.getSizeInBits();
1099
1100 if (TotalBits == 32 ||
1101 (Op0Op0->getOpcode() == MipsISD::VEXTRACT_SEXT_ELT &&
1102 TotalBits <= 32)) {
1103 SDValue Ops[] = { Op0Op0->getOperand(Num: 0), Op0Op0->getOperand(Num: 1),
1104 Op0Op0->getOperand(Num: 2) };
1105 return DAG.getNode(Opcode: MipsISD::VEXTRACT_SEXT_ELT, DL: SDLoc(Op0Op0),
1106 VTList: Op0Op0->getVTList(),
1107 Ops: ArrayRef(Ops, Op0Op0->getNumOperands()));
1108 }
1109 }
1110 }
1111
1112 if ((Ty != MVT::v2i16) && ((Ty != MVT::v4i8) || !Subtarget.hasDSPR2()))
1113 return SDValue();
1114
1115 return performDSPShiftCombine(Opc: MipsISD::SHRA_DSP, N, Ty, DAG, Subtarget);
1116}
1117
1118
1119static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG,
1120 TargetLowering::DAGCombinerInfo &DCI,
1121 const MipsSubtarget &Subtarget) {
1122 EVT Ty = N->getValueType(ResNo: 0);
1123
1124 if (((Ty != MVT::v2i16) || !Subtarget.hasDSPR2()) && (Ty != MVT::v4i8))
1125 return SDValue();
1126
1127 return performDSPShiftCombine(Opc: MipsISD::SHRL_DSP, N, Ty, DAG, Subtarget);
1128}
1129
1130static bool isLegalDSPCondCode(EVT Ty, ISD::CondCode CC) {
1131 bool IsV216 = (Ty == MVT::v2i16);
1132
1133 switch (CC) {
1134 case ISD::SETEQ:
1135 case ISD::SETNE: return true;
1136 case ISD::SETLT:
1137 case ISD::SETLE:
1138 case ISD::SETGT:
1139 case ISD::SETGE: return IsV216;
1140 case ISD::SETULT:
1141 case ISD::SETULE:
1142 case ISD::SETUGT:
1143 case ISD::SETUGE: return !IsV216;
1144 default: return false;
1145 }
1146}
1147
1148static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG) {
1149 EVT Ty = N->getValueType(ResNo: 0);
1150
1151 if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8))
1152 return SDValue();
1153
1154 if (!isLegalDSPCondCode(Ty, CC: cast<CondCodeSDNode>(Val: N->getOperand(Num: 2))->get()))
1155 return SDValue();
1156
1157 return DAG.getNode(Opcode: MipsISD::SETCC_DSP, DL: SDLoc(N), VT: Ty, N1: N->getOperand(Num: 0),
1158 N2: N->getOperand(Num: 1), N3: N->getOperand(Num: 2));
1159}
1160
1161static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) {
1162 EVT Ty = N->getValueType(ResNo: 0);
1163
1164 if (Ty == MVT::v2i16 || Ty == MVT::v4i8) {
1165 SDValue SetCC = N->getOperand(Num: 0);
1166
1167 if (SetCC.getOpcode() != MipsISD::SETCC_DSP)
1168 return SDValue();
1169
1170 return DAG.getNode(Opcode: MipsISD::SELECT_CC_DSP, DL: SDLoc(N), VT: Ty,
1171 N1: SetCC.getOperand(i: 0), N2: SetCC.getOperand(i: 1),
1172 N3: N->getOperand(Num: 1), N4: N->getOperand(Num: 2), N5: SetCC.getOperand(i: 2));
1173 }
1174
1175 return SDValue();
1176}
1177
1178static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG,
1179 const MipsSubtarget &Subtarget) {
1180 EVT Ty = N->getValueType(ResNo: 0);
1181
1182 if (Subtarget.hasMSA() && Ty.is128BitVector() && Ty.isInteger()) {
1183 // Try the following combines:
1184 // (xor (or $a, $b), (build_vector allones))
1185 // (xor (or $a, $b), (bitcast (build_vector allones)))
1186 SDValue Op0 = N->getOperand(Num: 0);
1187 SDValue Op1 = N->getOperand(Num: 1);
1188 SDValue NotOp;
1189
1190 if (ISD::isBuildVectorAllOnes(N: Op0.getNode()))
1191 NotOp = Op1;
1192 else if (ISD::isBuildVectorAllOnes(N: Op1.getNode()))
1193 NotOp = Op0;
1194 else
1195 return SDValue();
1196
1197 if (NotOp->getOpcode() == ISD::OR)
1198 return DAG.getNode(Opcode: MipsISD::VNOR, DL: SDLoc(N), VT: Ty, N1: NotOp->getOperand(Num: 0),
1199 N2: NotOp->getOperand(Num: 1));
1200 }
1201
1202 return SDValue();
1203}
1204
1205// Convert (fp_to_uint (fp16_to_fp x)) into (fp_to_sint (fp16_to_fp x)).
1206static SDValue performFP_TO_UINTCombine(SDNode *N, SelectionDAG &DAG) {
1207 SDValue Src = N->getOperand(Num: 0);
1208 EVT VT = N->getValueType(ResNo: 0);
1209
1210 // Use a trick from TargetLowering::expandFP_TO_UINT: we know that every
1211 // integer value that can be represented by f16 is <= 65504, i.e. a signed
1212 // integer of 17 bits or more can represent all values and fptoui and fptosi
1213 // are equivalent.
1214 //
1215 // NOTE: the result of fptoui is poison when the value does not fit in the
1216 // destination type (e.g. because it is negative).
1217 if (Src.getOpcode() != ISD::FP16_TO_FP || VT.getScalarSizeInBits() < 17)
1218 return SDValue();
1219 return DAG.getNode(Opcode: ISD::FP_TO_SINT, DL: SDLoc(N), VT, Operand: Src);
1220}
1221
1222SDValue
1223MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
1224 SelectionDAG &DAG = DCI.DAG;
1225 SDValue Val;
1226
1227 switch (N->getOpcode()) {
1228 case ISD::AND:
1229 Val = performANDCombine(N, DAG, DCI, Subtarget);
1230 break;
1231 case ISD::OR:
1232 Val = performORCombine(N, DAG, DCI, Subtarget);
1233 break;
1234 case ISD::MUL:
1235 return performMULCombine(N, DAG, DCI, TL: this, Subtarget);
1236 case ISD::SHL:
1237 Val = performSHLCombine(N, DAG, DCI, Subtarget);
1238 break;
1239 case ISD::SRA:
1240 return performSRACombine(N, DAG, DCI, Subtarget);
1241 case ISD::SRL:
1242 return performSRLCombine(N, DAG, DCI, Subtarget);
1243 case ISD::VSELECT:
1244 return performVSELECTCombine(N, DAG);
1245 case ISD::XOR:
1246 Val = performXORCombine(N, DAG, Subtarget);
1247 break;
1248 case ISD::SETCC:
1249 Val = performSETCCCombine(N, DAG);
1250 break;
1251 case ISD::FP_TO_UINT:
1252 Val = performFP_TO_UINTCombine(N, DAG);
1253 break;
1254 }
1255
1256 if (Val.getNode()) {
1257 LLVM_DEBUG(dbgs() << "\nMipsSE DAG Combine:\n";
1258 N->printrWithDepth(dbgs(), &DAG); dbgs() << "\n=> \n";
1259 Val.getNode()->printrWithDepth(dbgs(), &DAG); dbgs() << "\n");
1260 return Val;
1261 }
1262
1263 return MipsTargetLowering::PerformDAGCombine(N, DCI);
1264}
1265
1266MachineBasicBlock *
1267MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
1268 MachineBasicBlock *BB) const {
1269 switch (MI.getOpcode()) {
1270 default:
1271 return MipsTargetLowering::EmitInstrWithCustomInserter(MI, MBB: BB);
1272 case Mips::BPOSGE32_PSEUDO:
1273 return emitBPOSGE32(MI, BB);
1274 case Mips::SNZ_B_PSEUDO:
1275 return emitMSACBranchPseudo(MI, BB, BranchOp: Mips::BNZ_B);
1276 case Mips::SNZ_H_PSEUDO:
1277 return emitMSACBranchPseudo(MI, BB, BranchOp: Mips::BNZ_H);
1278 case Mips::SNZ_W_PSEUDO:
1279 return emitMSACBranchPseudo(MI, BB, BranchOp: Mips::BNZ_W);
1280 case Mips::SNZ_D_PSEUDO:
1281 return emitMSACBranchPseudo(MI, BB, BranchOp: Mips::BNZ_D);
1282 case Mips::SNZ_V_PSEUDO:
1283 return emitMSACBranchPseudo(MI, BB, BranchOp: Mips::BNZ_V);
1284 case Mips::SZ_B_PSEUDO:
1285 return emitMSACBranchPseudo(MI, BB, BranchOp: Mips::BZ_B);
1286 case Mips::SZ_H_PSEUDO:
1287 return emitMSACBranchPseudo(MI, BB, BranchOp: Mips::BZ_H);
1288 case Mips::SZ_W_PSEUDO:
1289 return emitMSACBranchPseudo(MI, BB, BranchOp: Mips::BZ_W);
1290 case Mips::SZ_D_PSEUDO:
1291 return emitMSACBranchPseudo(MI, BB, BranchOp: Mips::BZ_D);
1292 case Mips::SZ_V_PSEUDO:
1293 return emitMSACBranchPseudo(MI, BB, BranchOp: Mips::BZ_V);
1294 case Mips::COPY_FW_PSEUDO:
1295 return emitCOPY_FW(MI, BB);
1296 case Mips::COPY_FD_PSEUDO:
1297 return emitCOPY_FD(MI, BB);
1298 case Mips::INSERT_FW_PSEUDO:
1299 return emitINSERT_FW(MI, BB);
1300 case Mips::INSERT_FD_PSEUDO:
1301 return emitINSERT_FD(MI, BB);
1302 case Mips::INSERT_B_VIDX_PSEUDO:
1303 case Mips::INSERT_B_VIDX64_PSEUDO:
1304 return emitINSERT_DF_VIDX(MI, BB, EltSizeInBytes: 1, IsFP: false);
1305 case Mips::INSERT_H_VIDX_PSEUDO:
1306 case Mips::INSERT_H_VIDX64_PSEUDO:
1307 return emitINSERT_DF_VIDX(MI, BB, EltSizeInBytes: 2, IsFP: false);
1308 case Mips::INSERT_W_VIDX_PSEUDO:
1309 case Mips::INSERT_W_VIDX64_PSEUDO:
1310 return emitINSERT_DF_VIDX(MI, BB, EltSizeInBytes: 4, IsFP: false);
1311 case Mips::INSERT_D_VIDX_PSEUDO:
1312 case Mips::INSERT_D_VIDX64_PSEUDO:
1313 return emitINSERT_DF_VIDX(MI, BB, EltSizeInBytes: 8, IsFP: false);
1314 case Mips::INSERT_FW_VIDX_PSEUDO:
1315 case Mips::INSERT_FW_VIDX64_PSEUDO:
1316 return emitINSERT_DF_VIDX(MI, BB, EltSizeInBytes: 4, IsFP: true);
1317 case Mips::INSERT_FD_VIDX_PSEUDO:
1318 case Mips::INSERT_FD_VIDX64_PSEUDO:
1319 return emitINSERT_DF_VIDX(MI, BB, EltSizeInBytes: 8, IsFP: true);
1320 case Mips::FILL_FW_PSEUDO:
1321 return emitFILL_FW(MI, BB);
1322 case Mips::FILL_FD_PSEUDO:
1323 return emitFILL_FD(MI, BB);
1324 case Mips::FEXP2_W_1_PSEUDO:
1325 return emitFEXP2_W_1(MI, BB);
1326 case Mips::FEXP2_D_1_PSEUDO:
1327 return emitFEXP2_D_1(MI, BB);
1328 }
1329}
1330
1331bool MipsSETargetLowering::isEligibleForTailCallOptimization(
1332 const CCState &CCInfo, unsigned NextStackOffset,
1333 const MipsFunctionInfo &FI) const {
1334 // Exception has to be cleared with eret.
1335 if (FI.isISR())
1336 return false;
1337
1338 // Return false if either the callee or caller has a byval argument.
1339 if (CCInfo.getInRegsParamsCount() > 0 || FI.hasByvalArg())
1340 return false;
1341
1342 // Return true if the callee's argument area is no larger than the caller's.
1343 return NextStackOffset <= FI.getIncomingArgSize();
1344}
1345
1346void MipsSETargetLowering::
1347getOpndList(SmallVectorImpl<SDValue> &Ops,
1348 std::deque<std::pair<unsigned, SDValue>> &RegsToPass,
1349 bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
1350 bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee,
1351 SDValue Chain) const {
1352 Ops.push_back(Elt: Callee);
1353 MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal,
1354 InternalLinkage, IsCallReloc, CLI, Callee,
1355 Chain);
1356}
1357
1358SDValue MipsSETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const {
1359 LoadSDNode &Nd = *cast<LoadSDNode>(Val&: Op);
1360
1361 if (Nd.getMemoryVT() != MVT::f64 || !NoDPLoadStore)
1362 return MipsTargetLowering::lowerLOAD(Op, DAG);
1363
1364 // Replace a double precision load with two i32 loads and a buildpair64.
1365 SDLoc DL(Op);
1366 SDValue Ptr = Nd.getBasePtr(), Chain = Nd.getChain();
1367 EVT PtrVT = Ptr.getValueType();
1368
1369 // i32 load from lower address.
1370 SDValue Lo = DAG.getLoad(VT: MVT::i32, dl: DL, Chain, Ptr, PtrInfo: MachinePointerInfo(),
1371 Alignment: Nd.getAlign(), MMOFlags: Nd.getMemOperand()->getFlags());
1372
1373 // i32 load from higher address.
1374 Ptr = DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, N1: Ptr, N2: DAG.getConstant(Val: 4, DL, VT: PtrVT));
1375 SDValue Hi = DAG.getLoad(
1376 VT: MVT::i32, dl: DL, Chain: Lo.getValue(R: 1), Ptr, PtrInfo: MachinePointerInfo(),
1377 Alignment: commonAlignment(A: Nd.getAlign(), Offset: 4), MMOFlags: Nd.getMemOperand()->getFlags());
1378
1379 if (!Subtarget.isLittle())
1380 std::swap(a&: Lo, b&: Hi);
1381
1382 SDValue BP = DAG.getNode(Opcode: MipsISD::BuildPairF64, DL, VT: MVT::f64, N1: Lo, N2: Hi);
1383 SDValue Ops[2] = {BP, Hi.getValue(R: 1)};
1384 return DAG.getMergeValues(Ops, dl: DL);
1385}
1386
1387SDValue MipsSETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
1388 StoreSDNode &Nd = *cast<StoreSDNode>(Val&: Op);
1389
1390 if (Nd.getMemoryVT() != MVT::f64 || !NoDPLoadStore)
1391 return MipsTargetLowering::lowerSTORE(Op, DAG);
1392
1393 // Replace a double precision store with two extractelement64s and i32 stores.
1394 SDLoc DL(Op);
1395 SDValue Val = Nd.getValue(), Ptr = Nd.getBasePtr(), Chain = Nd.getChain();
1396 EVT PtrVT = Ptr.getValueType();
1397 SDValue Lo = DAG.getNode(Opcode: MipsISD::ExtractElementF64, DL, VT: MVT::i32,
1398 N1: Val, N2: DAG.getConstant(Val: 0, DL, VT: MVT::i32));
1399 SDValue Hi = DAG.getNode(Opcode: MipsISD::ExtractElementF64, DL, VT: MVT::i32,
1400 N1: Val, N2: DAG.getConstant(Val: 1, DL, VT: MVT::i32));
1401
1402 if (!Subtarget.isLittle())
1403 std::swap(a&: Lo, b&: Hi);
1404
1405 // i32 store to lower address.
1406 Chain = DAG.getStore(Chain, dl: DL, Val: Lo, Ptr, PtrInfo: MachinePointerInfo(), Alignment: Nd.getAlign(),
1407 MMOFlags: Nd.getMemOperand()->getFlags(), Metadata: Nd.getAAInfo());
1408
1409 // i32 store to higher address.
1410 Ptr = DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrVT, N1: Ptr, N2: DAG.getConstant(Val: 4, DL, VT: PtrVT));
1411 return DAG.getStore(Chain, dl: DL, Val: Hi, Ptr, PtrInfo: MachinePointerInfo(),
1412 Alignment: commonAlignment(A: Nd.getAlign(), Offset: 4),
1413 MMOFlags: Nd.getMemOperand()->getFlags(), Metadata: Nd.getAAInfo());
1414}
1415
1416SDValue MipsSETargetLowering::lowerBITCAST(SDValue Op,
1417 SelectionDAG &DAG) const {
1418 SDLoc DL(Op);
1419 MVT Src = Op.getOperand(i: 0).getValueType().getSimpleVT();
1420 MVT Dest = Op.getValueType().getSimpleVT();
1421
1422 // Bitcast i64 to double.
1423 if (Src == MVT::i64 && Dest == MVT::f64) {
1424 SDValue Lo, Hi;
1425 std::tie(args&: Lo, args&: Hi) =
1426 DAG.SplitScalar(N: Op.getOperand(i: 0), DL, LoVT: MVT::i32, HiVT: MVT::i32);
1427 return DAG.getNode(Opcode: MipsISD::BuildPairF64, DL, VT: MVT::f64, N1: Lo, N2: Hi);
1428 }
1429
1430 // Bitcast double to i64.
1431 if (Src == MVT::f64 && Dest == MVT::i64) {
1432 // Skip lower bitcast when operand0 has converted float results to integer
1433 // which was done by function SoftenFloatResult.
1434 if (getTypeAction(Context&: *DAG.getContext(), VT: Op.getOperand(i: 0).getValueType()) ==
1435 TargetLowering::TypeSoftenFloat)
1436 return SDValue();
1437 SDValue Lo =
1438 DAG.getNode(Opcode: MipsISD::ExtractElementF64, DL, VT: MVT::i32, N1: Op.getOperand(i: 0),
1439 N2: DAG.getConstant(Val: 0, DL, VT: MVT::i32));
1440 SDValue Hi =
1441 DAG.getNode(Opcode: MipsISD::ExtractElementF64, DL, VT: MVT::i32, N1: Op.getOperand(i: 0),
1442 N2: DAG.getConstant(Val: 1, DL, VT: MVT::i32));
1443 return DAG.getNode(Opcode: ISD::BUILD_PAIR, DL, VT: MVT::i64, N1: Lo, N2: Hi);
1444 }
1445
1446 // Skip other cases of bitcast and use default lowering.
1447 return SDValue();
1448}
1449
1450SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc,
1451 bool HasLo, bool HasHi,
1452 SelectionDAG &DAG) const {
1453 // MIPS32r6/MIPS64r6 removed accumulator based multiplies.
1454 assert(!Subtarget.hasMips32r6());
1455
1456 EVT Ty = Op.getOperand(i: 0).getValueType();
1457 SDLoc DL(Op);
1458 SDValue Mult = DAG.getNode(Opcode: NewOpc, DL, VT: MVT::Untyped,
1459 N1: Op.getOperand(i: 0), N2: Op.getOperand(i: 1));
1460 SDValue Lo, Hi;
1461
1462 if (HasLo)
1463 Lo = DAG.getNode(Opcode: MipsISD::MFLO, DL, VT: Ty, Operand: Mult);
1464 if (HasHi)
1465 Hi = DAG.getNode(Opcode: MipsISD::MFHI, DL, VT: Ty, Operand: Mult);
1466
1467 if (!HasLo || !HasHi)
1468 return HasLo ? Lo : Hi;
1469
1470 SDValue Vals[] = { Lo, Hi };
1471 return DAG.getMergeValues(Ops: Vals, dl: DL);
1472}
1473
1474static SDValue initAccumulator(SDValue In, const SDLoc &DL, SelectionDAG &DAG) {
1475 SDValue InLo, InHi;
1476 std::tie(args&: InLo, args&: InHi) = DAG.SplitScalar(N: In, DL, LoVT: MVT::i32, HiVT: MVT::i32);
1477 return DAG.getNode(Opcode: MipsISD::MTLOHI, DL, VT: MVT::Untyped, N1: InLo, N2: InHi);
1478}
1479
1480static SDValue extractLOHI(SDValue Op, const SDLoc &DL, SelectionDAG &DAG) {
1481 SDValue Lo = DAG.getNode(Opcode: MipsISD::MFLO, DL, VT: MVT::i32, Operand: Op);
1482 SDValue Hi = DAG.getNode(Opcode: MipsISD::MFHI, DL, VT: MVT::i32, Operand: Op);
1483 return DAG.getNode(Opcode: ISD::BUILD_PAIR, DL, VT: MVT::i64, N1: Lo, N2: Hi);
1484}
1485
1486// This function expands mips intrinsic nodes which have 64-bit input operands
1487// or output values.
1488//
1489// out64 = intrinsic-node in64
1490// =>
1491// lo = copy (extract-element (in64, 0))
1492// hi = copy (extract-element (in64, 1))
1493// mips-specific-node
1494// v0 = copy lo
1495// v1 = copy hi
1496// out64 = merge-values (v0, v1)
1497//
1498static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
1499 SDLoc DL(Op);
1500 bool HasChainIn = Op->getOperand(Num: 0).getValueType() == MVT::Other;
1501 SmallVector<SDValue, 3> Ops;
1502 unsigned OpNo = 0;
1503
1504 // See if Op has a chain input.
1505 if (HasChainIn)
1506 Ops.push_back(Elt: Op->getOperand(Num: OpNo++));
1507
1508 // The next operand is the intrinsic opcode.
1509 assert(Op->getOperand(OpNo).getOpcode() == ISD::TargetConstant);
1510
1511 // See if the next operand has type i64.
1512 SDValue Opnd = Op->getOperand(Num: ++OpNo), In64;
1513
1514 if (Opnd.getValueType() == MVT::i64)
1515 In64 = initAccumulator(In: Opnd, DL, DAG);
1516 else
1517 Ops.push_back(Elt: Opnd);
1518
1519 // Push the remaining operands.
1520 for (++OpNo ; OpNo < Op->getNumOperands(); ++OpNo)
1521 Ops.push_back(Elt: Op->getOperand(Num: OpNo));
1522
1523 // Add In64 to the end of the list.
1524 if (In64.getNode())
1525 Ops.push_back(Elt: In64);
1526
1527 // Scan output.
1528 SmallVector<EVT, 2> ResTys;
1529
1530 for (EVT Ty : Op->values())
1531 ResTys.push_back(Elt: (Ty == MVT::i64) ? MVT::Untyped : Ty);
1532
1533 // Create node.
1534 SDValue Val = DAG.getNode(Opcode: Opc, DL, ResultTys: ResTys, Ops);
1535 SDValue Out = (ResTys[0] == MVT::Untyped) ? extractLOHI(Op: Val, DL, DAG) : Val;
1536
1537 if (!HasChainIn)
1538 return Out;
1539
1540 assert(Val->getValueType(1) == MVT::Other);
1541 SDValue Vals[] = { Out, SDValue(Val.getNode(), 1) };
1542 return DAG.getMergeValues(Ops: Vals, dl: DL);
1543}
1544
1545// Lower an MSA copy intrinsic into the specified SelectionDAG node
1546static SDValue lowerMSACopyIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
1547 SDLoc DL(Op);
1548 SDValue Vec = Op->getOperand(Num: 1);
1549 SDValue Idx = Op->getOperand(Num: 2);
1550 EVT ResTy = Op->getValueType(ResNo: 0);
1551 EVT EltTy = Vec->getValueType(ResNo: 0).getVectorElementType();
1552
1553 SDValue Result = DAG.getNode(Opcode: Opc, DL, VT: ResTy, N1: Vec, N2: Idx,
1554 N3: DAG.getValueType(EltTy));
1555
1556 return Result;
1557}
1558
1559static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) {
1560 EVT ResVecTy = Op->getValueType(ResNo: 0);
1561 EVT ViaVecTy = ResVecTy;
1562 bool BigEndian = !DAG.getSubtarget().getTargetTriple().isLittleEndian();
1563 SDLoc DL(Op);
1564
1565 // When ResVecTy == MVT::v2i64, LaneA is the upper 32 bits of the lane and
1566 // LaneB is the lower 32-bits. Otherwise LaneA and LaneB are alternating
1567 // lanes.
1568 SDValue LaneA = Op->getOperand(Num: OpNr);
1569 SDValue LaneB;
1570
1571 if (ResVecTy == MVT::v2i64) {
1572 // In case of the index being passed as an immediate value, set the upper
1573 // lane to 0 so that the splati.d instruction can be matched.
1574 if (isa<ConstantSDNode>(Val: LaneA))
1575 LaneB = DAG.getConstant(Val: 0, DL, VT: MVT::i32);
1576 // Having the index passed in a register, set the upper lane to the same
1577 // value as the lower - this results in the BUILD_VECTOR node not being
1578 // expanded through stack. This way we are able to pattern match the set of
1579 // nodes created here to splat.d.
1580 else
1581 LaneB = LaneA;
1582 ViaVecTy = MVT::v4i32;
1583 if(BigEndian)
1584 std::swap(a&: LaneA, b&: LaneB);
1585 } else
1586 LaneB = LaneA;
1587
1588 SDValue Ops[16] = { LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB,
1589 LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB };
1590
1591 SDValue Result = DAG.getBuildVector(
1592 VT: ViaVecTy, DL, Ops: ArrayRef(Ops, ViaVecTy.getVectorNumElements()));
1593
1594 if (ViaVecTy != ResVecTy) {
1595 SDValue One = DAG.getConstant(Val: 1, DL, VT: ViaVecTy);
1596 Result = DAG.getNode(Opcode: ISD::BITCAST, DL, VT: ResVecTy,
1597 Operand: DAG.getNode(Opcode: ISD::AND, DL, VT: ViaVecTy, N1: Result, N2: One));
1598 }
1599
1600 return Result;
1601}
1602
1603static SDValue lowerMSASplatImm(SDValue Op, unsigned ImmOp, SelectionDAG &DAG,
1604 bool IsSigned = false) {
1605 auto *CImm = cast<ConstantSDNode>(Val: Op->getOperand(Num: ImmOp));
1606 return DAG.getConstant(
1607 Val: APInt(Op->getValueType(ResNo: 0).getScalarType().getSizeInBits(),
1608 IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned),
1609 DL: SDLoc(Op), VT: Op->getValueType(ResNo: 0));
1610}
1611
1612static SDValue getBuildVectorSplat(EVT VecTy, SDValue SplatValue,
1613 bool BigEndian, SelectionDAG &DAG) {
1614 EVT ViaVecTy = VecTy;
1615 SDValue SplatValueA = SplatValue;
1616 SDValue SplatValueB = SplatValue;
1617 SDLoc DL(SplatValue);
1618
1619 if (VecTy == MVT::v2i64) {
1620 // v2i64 BUILD_VECTOR must be performed via v4i32 so split into i32's.
1621 ViaVecTy = MVT::v4i32;
1622
1623 SplatValueA = DAG.getNode(Opcode: ISD::TRUNCATE, DL, VT: MVT::i32, Operand: SplatValue);
1624 SplatValueB = DAG.getNode(Opcode: ISD::SRL, DL, VT: MVT::i64, N1: SplatValue,
1625 N2: DAG.getConstant(Val: 32, DL, VT: MVT::i32));
1626 SplatValueB = DAG.getNode(Opcode: ISD::TRUNCATE, DL, VT: MVT::i32, Operand: SplatValueB);
1627 }
1628
1629 // We currently hold the parts in little endian order. Swap them if
1630 // necessary.
1631 if (BigEndian)
1632 std::swap(a&: SplatValueA, b&: SplatValueB);
1633
1634 SDValue Ops[16] = { SplatValueA, SplatValueB, SplatValueA, SplatValueB,
1635 SplatValueA, SplatValueB, SplatValueA, SplatValueB,
1636 SplatValueA, SplatValueB, SplatValueA, SplatValueB,
1637 SplatValueA, SplatValueB, SplatValueA, SplatValueB };
1638
1639 SDValue Result = DAG.getBuildVector(
1640 VT: ViaVecTy, DL, Ops: ArrayRef(Ops, ViaVecTy.getVectorNumElements()));
1641
1642 if (VecTy != ViaVecTy)
1643 Result = DAG.getNode(Opcode: ISD::BITCAST, DL, VT: VecTy, Operand: Result);
1644
1645 return Result;
1646}
1647
1648static SDValue lowerMSABinaryBitImmIntr(SDValue Op, SelectionDAG &DAG,
1649 unsigned Opc, SDValue Imm,
1650 bool BigEndian) {
1651 EVT VecTy = Op->getValueType(ResNo: 0);
1652 SDValue Exp2Imm;
1653 SDLoc DL(Op);
1654
1655 // The DAG Combiner can't constant fold bitcasted vectors yet so we must do it
1656 // here for now.
1657 if (VecTy == MVT::v2i64) {
1658 if (ConstantSDNode *CImm = dyn_cast<ConstantSDNode>(Val&: Imm)) {
1659 APInt BitImm = APInt(64, 1) << CImm->getAPIntValue();
1660
1661 SDValue BitImmHiOp = DAG.getConstant(Val: BitImm.lshr(shiftAmt: 32).trunc(width: 32), DL,
1662 VT: MVT::i32);
1663 SDValue BitImmLoOp = DAG.getConstant(Val: BitImm.trunc(width: 32), DL, VT: MVT::i32);
1664
1665 if (BigEndian)
1666 std::swap(a&: BitImmLoOp, b&: BitImmHiOp);
1667
1668 Exp2Imm = DAG.getNode(
1669 Opcode: ISD::BITCAST, DL, VT: MVT::v2i64,
1670 Operand: DAG.getBuildVector(VT: MVT::v4i32, DL,
1671 Ops: {BitImmLoOp, BitImmHiOp, BitImmLoOp, BitImmHiOp}));
1672 }
1673 }
1674
1675 if (!Exp2Imm.getNode()) {
1676 // We couldnt constant fold, do a vector shift instead
1677
1678 // Extend i32 to i64 if necessary. Sign or zero extend doesn't matter since
1679 // only values 0-63 are valid.
1680 if (VecTy == MVT::v2i64)
1681 Imm = DAG.getNode(Opcode: ISD::ZERO_EXTEND, DL, VT: MVT::i64, Operand: Imm);
1682
1683 Exp2Imm = getBuildVectorSplat(VecTy, SplatValue: Imm, BigEndian, DAG);
1684
1685 Exp2Imm = DAG.getNode(Opcode: ISD::SHL, DL, VT: VecTy, N1: DAG.getConstant(Val: 1, DL, VT: VecTy),
1686 N2: Exp2Imm);
1687 }
1688
1689 return DAG.getNode(Opcode: Opc, DL, VT: VecTy, N1: Op->getOperand(Num: 1), N2: Exp2Imm);
1690}
1691
1692static SDValue truncateVecElts(SDValue Op, SelectionDAG &DAG) {
1693 SDLoc DL(Op);
1694 EVT ResTy = Op->getValueType(ResNo: 0);
1695 SDValue Vec = Op->getOperand(Num: 2);
1696 bool BigEndian = !DAG.getSubtarget().getTargetTriple().isLittleEndian();
1697 MVT ResEltTy = ResTy == MVT::v2i64 ? MVT::i64 : MVT::i32;
1698 SDValue ConstValue = DAG.getConstant(Val: Vec.getScalarValueSizeInBits() - 1,
1699 DL, VT: ResEltTy);
1700 SDValue SplatVec = getBuildVectorSplat(VecTy: ResTy, SplatValue: ConstValue, BigEndian, DAG);
1701
1702 return DAG.getNode(Opcode: ISD::AND, DL, VT: ResTy, N1: Vec, N2: SplatVec);
1703}
1704
1705static SDValue lowerMSABitClear(SDValue Op, SelectionDAG &DAG) {
1706 EVT ResTy = Op->getValueType(ResNo: 0);
1707 SDLoc DL(Op);
1708 SDValue One = DAG.getConstant(Val: 1, DL, VT: ResTy);
1709 SDValue Bit = DAG.getNode(Opcode: ISD::SHL, DL, VT: ResTy, N1: One, N2: truncateVecElts(Op, DAG));
1710
1711 return DAG.getNode(Opcode: ISD::AND, DL, VT: ResTy, N1: Op->getOperand(Num: 1),
1712 N2: DAG.getNOT(DL, Val: Bit, VT: ResTy));
1713}
1714
1715static SDValue lowerMSABitClearImm(SDValue Op, SelectionDAG &DAG) {
1716 SDLoc DL(Op);
1717 EVT ResTy = Op->getValueType(ResNo: 0);
1718 APInt BitImm = APInt(ResTy.getScalarSizeInBits(), 1)
1719 << Op->getConstantOperandAPInt(Num: 2);
1720 SDValue BitMask = DAG.getConstant(Val: ~BitImm, DL, VT: ResTy);
1721
1722 return DAG.getNode(Opcode: ISD::AND, DL, VT: ResTy, N1: Op->getOperand(Num: 1), N2: BitMask);
1723}
1724
1725SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
1726 SelectionDAG &DAG) const {
1727 SDLoc DL(Op);
1728 unsigned Intrinsic = Op->getConstantOperandVal(Num: 0);
1729 switch (Intrinsic) {
1730 default:
1731 return SDValue();
1732 case Intrinsic::mips_shilo:
1733 return lowerDSPIntr(Op, DAG, Opc: MipsISD::SHILO);
1734 case Intrinsic::mips_dpau_h_qbl:
1735 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPAU_H_QBL);
1736 case Intrinsic::mips_dpau_h_qbr:
1737 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPAU_H_QBR);
1738 case Intrinsic::mips_dpsu_h_qbl:
1739 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPSU_H_QBL);
1740 case Intrinsic::mips_dpsu_h_qbr:
1741 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPSU_H_QBR);
1742 case Intrinsic::mips_dpa_w_ph:
1743 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPA_W_PH);
1744 case Intrinsic::mips_dps_w_ph:
1745 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPS_W_PH);
1746 case Intrinsic::mips_dpax_w_ph:
1747 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPAX_W_PH);
1748 case Intrinsic::mips_dpsx_w_ph:
1749 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPSX_W_PH);
1750 case Intrinsic::mips_mulsa_w_ph:
1751 return lowerDSPIntr(Op, DAG, Opc: MipsISD::MULSA_W_PH);
1752 case Intrinsic::mips_mult:
1753 return lowerDSPIntr(Op, DAG, Opc: MipsISD::Mult);
1754 case Intrinsic::mips_multu:
1755 return lowerDSPIntr(Op, DAG, Opc: MipsISD::Multu);
1756 case Intrinsic::mips_madd:
1757 return lowerDSPIntr(Op, DAG, Opc: MipsISD::MAdd);
1758 case Intrinsic::mips_maddu:
1759 return lowerDSPIntr(Op, DAG, Opc: MipsISD::MAddu);
1760 case Intrinsic::mips_msub:
1761 return lowerDSPIntr(Op, DAG, Opc: MipsISD::MSub);
1762 case Intrinsic::mips_msubu:
1763 return lowerDSPIntr(Op, DAG, Opc: MipsISD::MSubu);
1764 case Intrinsic::mips_addv_b:
1765 case Intrinsic::mips_addv_h:
1766 case Intrinsic::mips_addv_w:
1767 case Intrinsic::mips_addv_d:
1768 return DAG.getNode(Opcode: ISD::ADD, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
1769 N2: Op->getOperand(Num: 2));
1770 case Intrinsic::mips_addvi_b:
1771 case Intrinsic::mips_addvi_h:
1772 case Intrinsic::mips_addvi_w:
1773 case Intrinsic::mips_addvi_d:
1774 return DAG.getNode(Opcode: ISD::ADD, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
1775 N2: lowerMSASplatImm(Op, ImmOp: 2, DAG));
1776 case Intrinsic::mips_and_v:
1777 return DAG.getNode(Opcode: ISD::AND, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
1778 N2: Op->getOperand(Num: 2));
1779 case Intrinsic::mips_andi_b:
1780 return DAG.getNode(Opcode: ISD::AND, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
1781 N2: lowerMSASplatImm(Op, ImmOp: 2, DAG));
1782 case Intrinsic::mips_bclr_b:
1783 case Intrinsic::mips_bclr_h:
1784 case Intrinsic::mips_bclr_w:
1785 case Intrinsic::mips_bclr_d:
1786 return lowerMSABitClear(Op, DAG);
1787 case Intrinsic::mips_bclri_b:
1788 case Intrinsic::mips_bclri_h:
1789 case Intrinsic::mips_bclri_w:
1790 case Intrinsic::mips_bclri_d:
1791 return lowerMSABitClearImm(Op, DAG);
1792 case Intrinsic::mips_binsli_b:
1793 case Intrinsic::mips_binsli_h:
1794 case Intrinsic::mips_binsli_w:
1795 case Intrinsic::mips_binsli_d: {
1796 // binsli_x(IfClear, IfSet, nbits) -> (vselect LBitsMask, IfSet, IfClear)
1797 EVT VecTy = Op->getValueType(ResNo: 0);
1798 EVT EltTy = VecTy.getVectorElementType();
1799 if (Op->getConstantOperandVal(Num: 3) >= EltTy.getSizeInBits())
1800 report_fatal_error(reason: "Immediate out of range");
1801 APInt Mask = APInt::getHighBitsSet(numBits: EltTy.getSizeInBits(),
1802 hiBitsSet: Op->getConstantOperandVal(Num: 3) + 1);
1803 return DAG.getNode(Opcode: ISD::VSELECT, DL, VT: VecTy,
1804 N1: DAG.getConstant(Val: Mask, DL, VT: VecTy, isTarget: true),
1805 N2: Op->getOperand(Num: 2), N3: Op->getOperand(Num: 1));
1806 }
1807 case Intrinsic::mips_binsri_b:
1808 case Intrinsic::mips_binsri_h:
1809 case Intrinsic::mips_binsri_w:
1810 case Intrinsic::mips_binsri_d: {
1811 // binsri_x(IfClear, IfSet, nbits) -> (vselect RBitsMask, IfSet, IfClear)
1812 EVT VecTy = Op->getValueType(ResNo: 0);
1813 EVT EltTy = VecTy.getVectorElementType();
1814 if (Op->getConstantOperandVal(Num: 3) >= EltTy.getSizeInBits())
1815 report_fatal_error(reason: "Immediate out of range");
1816 APInt Mask = APInt::getLowBitsSet(numBits: EltTy.getSizeInBits(),
1817 loBitsSet: Op->getConstantOperandVal(Num: 3) + 1);
1818 return DAG.getNode(Opcode: ISD::VSELECT, DL, VT: VecTy,
1819 N1: DAG.getConstant(Val: Mask, DL, VT: VecTy, isTarget: true),
1820 N2: Op->getOperand(Num: 2), N3: Op->getOperand(Num: 1));
1821 }
1822 case Intrinsic::mips_bmnz_v:
1823 return DAG.getNode(Opcode: ISD::VSELECT, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 3),
1824 N2: Op->getOperand(Num: 2), N3: Op->getOperand(Num: 1));
1825 case Intrinsic::mips_bmnzi_b:
1826 return DAG.getNode(Opcode: ISD::VSELECT, DL, VT: Op->getValueType(ResNo: 0),
1827 N1: lowerMSASplatImm(Op, ImmOp: 3, DAG), N2: Op->getOperand(Num: 2),
1828 N3: Op->getOperand(Num: 1));
1829 case Intrinsic::mips_bmz_v:
1830 return DAG.getNode(Opcode: ISD::VSELECT, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 3),
1831 N2: Op->getOperand(Num: 1), N3: Op->getOperand(Num: 2));
1832 case Intrinsic::mips_bmzi_b:
1833 return DAG.getNode(Opcode: ISD::VSELECT, DL, VT: Op->getValueType(ResNo: 0),
1834 N1: lowerMSASplatImm(Op, ImmOp: 3, DAG), N2: Op->getOperand(Num: 1),
1835 N3: Op->getOperand(Num: 2));
1836 case Intrinsic::mips_bneg_b:
1837 case Intrinsic::mips_bneg_h:
1838 case Intrinsic::mips_bneg_w:
1839 case Intrinsic::mips_bneg_d: {
1840 EVT VecTy = Op->getValueType(ResNo: 0);
1841 SDValue One = DAG.getConstant(Val: 1, DL, VT: VecTy);
1842
1843 return DAG.getNode(Opcode: ISD::XOR, DL, VT: VecTy, N1: Op->getOperand(Num: 1),
1844 N2: DAG.getNode(Opcode: ISD::SHL, DL, VT: VecTy, N1: One,
1845 N2: truncateVecElts(Op, DAG)));
1846 }
1847 case Intrinsic::mips_bnegi_b:
1848 case Intrinsic::mips_bnegi_h:
1849 case Intrinsic::mips_bnegi_w:
1850 case Intrinsic::mips_bnegi_d:
1851 return lowerMSABinaryBitImmIntr(Op, DAG, Opc: ISD::XOR, Imm: Op->getOperand(Num: 2),
1852 BigEndian: !Subtarget.isLittle());
1853 case Intrinsic::mips_bnz_b:
1854 case Intrinsic::mips_bnz_h:
1855 case Intrinsic::mips_bnz_w:
1856 case Intrinsic::mips_bnz_d:
1857 return DAG.getNode(Opcode: MipsISD::VALL_NONZERO, DL, VT: Op->getValueType(ResNo: 0),
1858 Operand: Op->getOperand(Num: 1));
1859 case Intrinsic::mips_bnz_v:
1860 return DAG.getNode(Opcode: MipsISD::VANY_NONZERO, DL, VT: Op->getValueType(ResNo: 0),
1861 Operand: Op->getOperand(Num: 1));
1862 case Intrinsic::mips_bsel_v:
1863 // bsel_v(Mask, IfClear, IfSet) -> (vselect Mask, IfSet, IfClear)
1864 return DAG.getNode(Opcode: ISD::VSELECT, DL, VT: Op->getValueType(ResNo: 0),
1865 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 3),
1866 N3: Op->getOperand(Num: 2));
1867 case Intrinsic::mips_bseli_b:
1868 // bseli_v(Mask, IfClear, IfSet) -> (vselect Mask, IfSet, IfClear)
1869 return DAG.getNode(Opcode: ISD::VSELECT, DL, VT: Op->getValueType(ResNo: 0),
1870 N1: Op->getOperand(Num: 1), N2: lowerMSASplatImm(Op, ImmOp: 3, DAG),
1871 N3: Op->getOperand(Num: 2));
1872 case Intrinsic::mips_bset_b:
1873 case Intrinsic::mips_bset_h:
1874 case Intrinsic::mips_bset_w:
1875 case Intrinsic::mips_bset_d: {
1876 EVT VecTy = Op->getValueType(ResNo: 0);
1877 SDValue One = DAG.getConstant(Val: 1, DL, VT: VecTy);
1878
1879 return DAG.getNode(Opcode: ISD::OR, DL, VT: VecTy, N1: Op->getOperand(Num: 1),
1880 N2: DAG.getNode(Opcode: ISD::SHL, DL, VT: VecTy, N1: One,
1881 N2: truncateVecElts(Op, DAG)));
1882 }
1883 case Intrinsic::mips_bseti_b:
1884 case Intrinsic::mips_bseti_h:
1885 case Intrinsic::mips_bseti_w:
1886 case Intrinsic::mips_bseti_d:
1887 return lowerMSABinaryBitImmIntr(Op, DAG, Opc: ISD::OR, Imm: Op->getOperand(Num: 2),
1888 BigEndian: !Subtarget.isLittle());
1889 case Intrinsic::mips_bz_b:
1890 case Intrinsic::mips_bz_h:
1891 case Intrinsic::mips_bz_w:
1892 case Intrinsic::mips_bz_d:
1893 return DAG.getNode(Opcode: MipsISD::VALL_ZERO, DL, VT: Op->getValueType(ResNo: 0),
1894 Operand: Op->getOperand(Num: 1));
1895 case Intrinsic::mips_bz_v:
1896 return DAG.getNode(Opcode: MipsISD::VANY_ZERO, DL, VT: Op->getValueType(ResNo: 0),
1897 Operand: Op->getOperand(Num: 1));
1898 case Intrinsic::mips_ceq_b:
1899 case Intrinsic::mips_ceq_h:
1900 case Intrinsic::mips_ceq_w:
1901 case Intrinsic::mips_ceq_d:
1902 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
1903 RHS: Op->getOperand(Num: 2), Cond: ISD::SETEQ);
1904 case Intrinsic::mips_ceqi_b:
1905 case Intrinsic::mips_ceqi_h:
1906 case Intrinsic::mips_ceqi_w:
1907 case Intrinsic::mips_ceqi_d:
1908 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
1909 RHS: lowerMSASplatImm(Op, ImmOp: 2, DAG, IsSigned: true), Cond: ISD::SETEQ);
1910 case Intrinsic::mips_cle_s_b:
1911 case Intrinsic::mips_cle_s_h:
1912 case Intrinsic::mips_cle_s_w:
1913 case Intrinsic::mips_cle_s_d:
1914 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
1915 RHS: Op->getOperand(Num: 2), Cond: ISD::SETLE);
1916 case Intrinsic::mips_clei_s_b:
1917 case Intrinsic::mips_clei_s_h:
1918 case Intrinsic::mips_clei_s_w:
1919 case Intrinsic::mips_clei_s_d:
1920 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
1921 RHS: lowerMSASplatImm(Op, ImmOp: 2, DAG, IsSigned: true), Cond: ISD::SETLE);
1922 case Intrinsic::mips_cle_u_b:
1923 case Intrinsic::mips_cle_u_h:
1924 case Intrinsic::mips_cle_u_w:
1925 case Intrinsic::mips_cle_u_d:
1926 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
1927 RHS: Op->getOperand(Num: 2), Cond: ISD::SETULE);
1928 case Intrinsic::mips_clei_u_b:
1929 case Intrinsic::mips_clei_u_h:
1930 case Intrinsic::mips_clei_u_w:
1931 case Intrinsic::mips_clei_u_d:
1932 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
1933 RHS: lowerMSASplatImm(Op, ImmOp: 2, DAG), Cond: ISD::SETULE);
1934 case Intrinsic::mips_clt_s_b:
1935 case Intrinsic::mips_clt_s_h:
1936 case Intrinsic::mips_clt_s_w:
1937 case Intrinsic::mips_clt_s_d:
1938 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
1939 RHS: Op->getOperand(Num: 2), Cond: ISD::SETLT);
1940 case Intrinsic::mips_clti_s_b:
1941 case Intrinsic::mips_clti_s_h:
1942 case Intrinsic::mips_clti_s_w:
1943 case Intrinsic::mips_clti_s_d:
1944 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
1945 RHS: lowerMSASplatImm(Op, ImmOp: 2, DAG, IsSigned: true), Cond: ISD::SETLT);
1946 case Intrinsic::mips_clt_u_b:
1947 case Intrinsic::mips_clt_u_h:
1948 case Intrinsic::mips_clt_u_w:
1949 case Intrinsic::mips_clt_u_d:
1950 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
1951 RHS: Op->getOperand(Num: 2), Cond: ISD::SETULT);
1952 case Intrinsic::mips_clti_u_b:
1953 case Intrinsic::mips_clti_u_h:
1954 case Intrinsic::mips_clti_u_w:
1955 case Intrinsic::mips_clti_u_d:
1956 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
1957 RHS: lowerMSASplatImm(Op, ImmOp: 2, DAG), Cond: ISD::SETULT);
1958 case Intrinsic::mips_copy_s_b:
1959 case Intrinsic::mips_copy_s_h:
1960 case Intrinsic::mips_copy_s_w:
1961 return lowerMSACopyIntr(Op, DAG, Opc: MipsISD::VEXTRACT_SEXT_ELT);
1962 case Intrinsic::mips_copy_s_d:
1963 if (Subtarget.hasMips64())
1964 // Lower directly into VEXTRACT_SEXT_ELT since i64 is legal on Mips64.
1965 return lowerMSACopyIntr(Op, DAG, Opc: MipsISD::VEXTRACT_SEXT_ELT);
1966 else {
1967 // Lower into the generic EXTRACT_VECTOR_ELT node and let the type
1968 // legalizer and EXTRACT_VECTOR_ELT lowering sort it out.
1969 return DAG.getNode(Opcode: ISD::EXTRACT_VECTOR_ELT, DL: SDLoc(Op),
1970 VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
1971 N2: Op->getOperand(Num: 2));
1972 }
1973 case Intrinsic::mips_copy_u_b:
1974 case Intrinsic::mips_copy_u_h:
1975 case Intrinsic::mips_copy_u_w:
1976 return lowerMSACopyIntr(Op, DAG, Opc: MipsISD::VEXTRACT_ZEXT_ELT);
1977 case Intrinsic::mips_copy_u_d:
1978 if (Subtarget.hasMips64())
1979 // Lower directly into VEXTRACT_ZEXT_ELT since i64 is legal on Mips64.
1980 return lowerMSACopyIntr(Op, DAG, Opc: MipsISD::VEXTRACT_ZEXT_ELT);
1981 else {
1982 // Lower into the generic EXTRACT_VECTOR_ELT node and let the type
1983 // legalizer and EXTRACT_VECTOR_ELT lowering sort it out.
1984 // Note: When i64 is illegal, this results in copy_s.w instructions
1985 // instead of copy_u.w instructions. This makes no difference to the
1986 // behaviour since i64 is only illegal when the register file is 32-bit.
1987 return DAG.getNode(Opcode: ISD::EXTRACT_VECTOR_ELT, DL: SDLoc(Op),
1988 VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
1989 N2: Op->getOperand(Num: 2));
1990 }
1991 case Intrinsic::mips_div_s_b:
1992 case Intrinsic::mips_div_s_h:
1993 case Intrinsic::mips_div_s_w:
1994 case Intrinsic::mips_div_s_d:
1995 return DAG.getNode(Opcode: ISD::SDIV, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
1996 N2: Op->getOperand(Num: 2));
1997 case Intrinsic::mips_div_u_b:
1998 case Intrinsic::mips_div_u_h:
1999 case Intrinsic::mips_div_u_w:
2000 case Intrinsic::mips_div_u_d:
2001 return DAG.getNode(Opcode: ISD::UDIV, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2002 N2: Op->getOperand(Num: 2));
2003 case Intrinsic::mips_fadd_w:
2004 case Intrinsic::mips_fadd_d:
2005 // TODO: If intrinsics have fast-math-flags, propagate them.
2006 return DAG.getNode(Opcode: ISD::FADD, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2007 N2: Op->getOperand(Num: 2));
2008 // Don't lower mips_fcaf_[wd] since LLVM folds SETFALSE condcodes away
2009 case Intrinsic::mips_fceq_w:
2010 case Intrinsic::mips_fceq_d:
2011 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
2012 RHS: Op->getOperand(Num: 2), Cond: ISD::SETOEQ);
2013 case Intrinsic::mips_fcle_w:
2014 case Intrinsic::mips_fcle_d:
2015 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
2016 RHS: Op->getOperand(Num: 2), Cond: ISD::SETOLE);
2017 case Intrinsic::mips_fclt_w:
2018 case Intrinsic::mips_fclt_d:
2019 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
2020 RHS: Op->getOperand(Num: 2), Cond: ISD::SETOLT);
2021 case Intrinsic::mips_fcne_w:
2022 case Intrinsic::mips_fcne_d:
2023 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
2024 RHS: Op->getOperand(Num: 2), Cond: ISD::SETONE);
2025 case Intrinsic::mips_fcor_w:
2026 case Intrinsic::mips_fcor_d:
2027 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
2028 RHS: Op->getOperand(Num: 2), Cond: ISD::SETO);
2029 case Intrinsic::mips_fcueq_w:
2030 case Intrinsic::mips_fcueq_d:
2031 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
2032 RHS: Op->getOperand(Num: 2), Cond: ISD::SETUEQ);
2033 case Intrinsic::mips_fcule_w:
2034 case Intrinsic::mips_fcule_d:
2035 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
2036 RHS: Op->getOperand(Num: 2), Cond: ISD::SETULE);
2037 case Intrinsic::mips_fcult_w:
2038 case Intrinsic::mips_fcult_d:
2039 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
2040 RHS: Op->getOperand(Num: 2), Cond: ISD::SETULT);
2041 case Intrinsic::mips_fcun_w:
2042 case Intrinsic::mips_fcun_d:
2043 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
2044 RHS: Op->getOperand(Num: 2), Cond: ISD::SETUO);
2045 case Intrinsic::mips_fcune_w:
2046 case Intrinsic::mips_fcune_d:
2047 return DAG.getSetCC(DL, VT: Op->getValueType(ResNo: 0), LHS: Op->getOperand(Num: 1),
2048 RHS: Op->getOperand(Num: 2), Cond: ISD::SETUNE);
2049 case Intrinsic::mips_fdiv_w:
2050 case Intrinsic::mips_fdiv_d:
2051 // TODO: If intrinsics have fast-math-flags, propagate them.
2052 return DAG.getNode(Opcode: ISD::FDIV, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2053 N2: Op->getOperand(Num: 2));
2054 case Intrinsic::mips_ffint_u_w:
2055 case Intrinsic::mips_ffint_u_d:
2056 return DAG.getNode(Opcode: ISD::UINT_TO_FP, DL, VT: Op->getValueType(ResNo: 0),
2057 Operand: Op->getOperand(Num: 1));
2058 case Intrinsic::mips_ffint_s_w:
2059 case Intrinsic::mips_ffint_s_d:
2060 return DAG.getNode(Opcode: ISD::SINT_TO_FP, DL, VT: Op->getValueType(ResNo: 0),
2061 Operand: Op->getOperand(Num: 1));
2062 case Intrinsic::mips_fill_b:
2063 case Intrinsic::mips_fill_h:
2064 case Intrinsic::mips_fill_w:
2065 case Intrinsic::mips_fill_d: {
2066 EVT ResTy = Op->getValueType(ResNo: 0);
2067 SmallVector<SDValue, 16> Ops(ResTy.getVectorNumElements(),
2068 Op->getOperand(Num: 1));
2069
2070 // If ResTy is v2i64 then the type legalizer will break this node down into
2071 // an equivalent v4i32.
2072 return DAG.getBuildVector(VT: ResTy, DL, Ops);
2073 }
2074 case Intrinsic::mips_fexp2_w:
2075 case Intrinsic::mips_fexp2_d: {
2076 // TODO: If intrinsics have fast-math-flags, propagate them.
2077 EVT ResTy = Op->getValueType(ResNo: 0);
2078 return DAG.getNode(
2079 Opcode: ISD::FMUL, DL: SDLoc(Op), VT: ResTy, N1: Op->getOperand(Num: 1),
2080 N2: DAG.getNode(Opcode: ISD::FEXP2, DL: SDLoc(Op), VT: ResTy, Operand: Op->getOperand(Num: 2)));
2081 }
2082 case Intrinsic::mips_flog2_w:
2083 case Intrinsic::mips_flog2_d:
2084 return DAG.getNode(Opcode: ISD::FLOG2, DL, VT: Op->getValueType(ResNo: 0), Operand: Op->getOperand(Num: 1));
2085 case Intrinsic::mips_fmadd_w:
2086 case Intrinsic::mips_fmadd_d:
2087 return DAG.getNode(Opcode: ISD::FMA, DL: SDLoc(Op), VT: Op->getValueType(ResNo: 0),
2088 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2), N3: Op->getOperand(Num: 3));
2089 case Intrinsic::mips_fmul_w:
2090 case Intrinsic::mips_fmul_d:
2091 // TODO: If intrinsics have fast-math-flags, propagate them.
2092 return DAG.getNode(Opcode: ISD::FMUL, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2093 N2: Op->getOperand(Num: 2));
2094 case Intrinsic::mips_fmsub_w:
2095 case Intrinsic::mips_fmsub_d: {
2096 // TODO: If intrinsics have fast-math-flags, propagate them.
2097 return DAG.getNode(Opcode: MipsISD::FMS, DL: SDLoc(Op), VT: Op->getValueType(ResNo: 0),
2098 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2), N3: Op->getOperand(Num: 3));
2099 }
2100 case Intrinsic::mips_frint_w:
2101 case Intrinsic::mips_frint_d:
2102 return DAG.getNode(Opcode: ISD::FRINT, DL, VT: Op->getValueType(ResNo: 0), Operand: Op->getOperand(Num: 1));
2103 case Intrinsic::mips_fsqrt_w:
2104 case Intrinsic::mips_fsqrt_d:
2105 return DAG.getNode(Opcode: ISD::FSQRT, DL, VT: Op->getValueType(ResNo: 0), Operand: Op->getOperand(Num: 1));
2106 case Intrinsic::mips_fsub_w:
2107 case Intrinsic::mips_fsub_d:
2108 // TODO: If intrinsics have fast-math-flags, propagate them.
2109 return DAG.getNode(Opcode: ISD::FSUB, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2110 N2: Op->getOperand(Num: 2));
2111 case Intrinsic::mips_ftrunc_u_w:
2112 case Intrinsic::mips_ftrunc_u_d:
2113 return DAG.getNode(Opcode: ISD::FP_TO_UINT, DL, VT: Op->getValueType(ResNo: 0),
2114 Operand: Op->getOperand(Num: 1));
2115 case Intrinsic::mips_ftrunc_s_w:
2116 case Intrinsic::mips_ftrunc_s_d:
2117 return DAG.getNode(Opcode: ISD::FP_TO_SINT, DL, VT: Op->getValueType(ResNo: 0),
2118 Operand: Op->getOperand(Num: 1));
2119 case Intrinsic::mips_ilvev_b:
2120 case Intrinsic::mips_ilvev_h:
2121 case Intrinsic::mips_ilvev_w:
2122 case Intrinsic::mips_ilvev_d:
2123 return DAG.getNode(Opcode: MipsISD::ILVEV, DL, VT: Op->getValueType(ResNo: 0),
2124 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2));
2125 case Intrinsic::mips_ilvl_b:
2126 case Intrinsic::mips_ilvl_h:
2127 case Intrinsic::mips_ilvl_w:
2128 case Intrinsic::mips_ilvl_d:
2129 return DAG.getNode(Opcode: MipsISD::ILVL, DL, VT: Op->getValueType(ResNo: 0),
2130 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2));
2131 case Intrinsic::mips_ilvod_b:
2132 case Intrinsic::mips_ilvod_h:
2133 case Intrinsic::mips_ilvod_w:
2134 case Intrinsic::mips_ilvod_d:
2135 return DAG.getNode(Opcode: MipsISD::ILVOD, DL, VT: Op->getValueType(ResNo: 0),
2136 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2));
2137 case Intrinsic::mips_ilvr_b:
2138 case Intrinsic::mips_ilvr_h:
2139 case Intrinsic::mips_ilvr_w:
2140 case Intrinsic::mips_ilvr_d:
2141 return DAG.getNode(Opcode: MipsISD::ILVR, DL, VT: Op->getValueType(ResNo: 0),
2142 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2));
2143 case Intrinsic::mips_insert_b:
2144 case Intrinsic::mips_insert_h:
2145 case Intrinsic::mips_insert_w:
2146 case Intrinsic::mips_insert_d:
2147 return DAG.getNode(Opcode: ISD::INSERT_VECTOR_ELT, DL: SDLoc(Op), VT: Op->getValueType(ResNo: 0),
2148 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 3), N3: Op->getOperand(Num: 2));
2149 case Intrinsic::mips_insve_b:
2150 case Intrinsic::mips_insve_h:
2151 case Intrinsic::mips_insve_w:
2152 case Intrinsic::mips_insve_d: {
2153 // Report an error for out of range values.
2154 int64_t Max;
2155 switch (Intrinsic) {
2156 case Intrinsic::mips_insve_b: Max = 15; break;
2157 case Intrinsic::mips_insve_h: Max = 7; break;
2158 case Intrinsic::mips_insve_w: Max = 3; break;
2159 case Intrinsic::mips_insve_d: Max = 1; break;
2160 default: llvm_unreachable("Unmatched intrinsic");
2161 }
2162 int64_t Value = cast<ConstantSDNode>(Val: Op->getOperand(Num: 2))->getSExtValue();
2163 if (Value < 0 || Value > Max)
2164 report_fatal_error(reason: "Immediate out of range");
2165 return DAG.getNode(Opcode: MipsISD::INSVE, DL, VT: Op->getValueType(ResNo: 0),
2166 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2), N3: Op->getOperand(Num: 3),
2167 N4: DAG.getConstant(Val: 0, DL, VT: MVT::i32));
2168 }
2169 case Intrinsic::mips_ldi_b:
2170 case Intrinsic::mips_ldi_h:
2171 case Intrinsic::mips_ldi_w:
2172 case Intrinsic::mips_ldi_d:
2173 return lowerMSASplatImm(Op, ImmOp: 1, DAG, IsSigned: true);
2174 case Intrinsic::mips_lsa:
2175 case Intrinsic::mips_dlsa: {
2176 EVT ResTy = Op->getValueType(ResNo: 0);
2177 return DAG.getNode(Opcode: ISD::ADD, DL: SDLoc(Op), VT: ResTy, N1: Op->getOperand(Num: 1),
2178 N2: DAG.getNode(Opcode: ISD::SHL, DL: SDLoc(Op), VT: ResTy,
2179 N1: Op->getOperand(Num: 2), N2: Op->getOperand(Num: 3)));
2180 }
2181 case Intrinsic::mips_maddv_b:
2182 case Intrinsic::mips_maddv_h:
2183 case Intrinsic::mips_maddv_w:
2184 case Intrinsic::mips_maddv_d: {
2185 EVT ResTy = Op->getValueType(ResNo: 0);
2186 return DAG.getNode(Opcode: ISD::ADD, DL: SDLoc(Op), VT: ResTy, N1: Op->getOperand(Num: 1),
2187 N2: DAG.getNode(Opcode: ISD::MUL, DL: SDLoc(Op), VT: ResTy,
2188 N1: Op->getOperand(Num: 2), N2: Op->getOperand(Num: 3)));
2189 }
2190 case Intrinsic::mips_max_s_b:
2191 case Intrinsic::mips_max_s_h:
2192 case Intrinsic::mips_max_s_w:
2193 case Intrinsic::mips_max_s_d:
2194 return DAG.getNode(Opcode: ISD::SMAX, DL, VT: Op->getValueType(ResNo: 0),
2195 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2));
2196 case Intrinsic::mips_max_u_b:
2197 case Intrinsic::mips_max_u_h:
2198 case Intrinsic::mips_max_u_w:
2199 case Intrinsic::mips_max_u_d:
2200 return DAG.getNode(Opcode: ISD::UMAX, DL, VT: Op->getValueType(ResNo: 0),
2201 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2));
2202 case Intrinsic::mips_maxi_s_b:
2203 case Intrinsic::mips_maxi_s_h:
2204 case Intrinsic::mips_maxi_s_w:
2205 case Intrinsic::mips_maxi_s_d:
2206 return DAG.getNode(Opcode: ISD::SMAX, DL, VT: Op->getValueType(ResNo: 0),
2207 N1: Op->getOperand(Num: 1), N2: lowerMSASplatImm(Op, ImmOp: 2, DAG, IsSigned: true));
2208 case Intrinsic::mips_maxi_u_b:
2209 case Intrinsic::mips_maxi_u_h:
2210 case Intrinsic::mips_maxi_u_w:
2211 case Intrinsic::mips_maxi_u_d:
2212 return DAG.getNode(Opcode: ISD::UMAX, DL, VT: Op->getValueType(ResNo: 0),
2213 N1: Op->getOperand(Num: 1), N2: lowerMSASplatImm(Op, ImmOp: 2, DAG));
2214 case Intrinsic::mips_min_s_b:
2215 case Intrinsic::mips_min_s_h:
2216 case Intrinsic::mips_min_s_w:
2217 case Intrinsic::mips_min_s_d:
2218 return DAG.getNode(Opcode: ISD::SMIN, DL, VT: Op->getValueType(ResNo: 0),
2219 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2));
2220 case Intrinsic::mips_min_u_b:
2221 case Intrinsic::mips_min_u_h:
2222 case Intrinsic::mips_min_u_w:
2223 case Intrinsic::mips_min_u_d:
2224 return DAG.getNode(Opcode: ISD::UMIN, DL, VT: Op->getValueType(ResNo: 0),
2225 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2));
2226 case Intrinsic::mips_mini_s_b:
2227 case Intrinsic::mips_mini_s_h:
2228 case Intrinsic::mips_mini_s_w:
2229 case Intrinsic::mips_mini_s_d:
2230 return DAG.getNode(Opcode: ISD::SMIN, DL, VT: Op->getValueType(ResNo: 0),
2231 N1: Op->getOperand(Num: 1), N2: lowerMSASplatImm(Op, ImmOp: 2, DAG, IsSigned: true));
2232 case Intrinsic::mips_mini_u_b:
2233 case Intrinsic::mips_mini_u_h:
2234 case Intrinsic::mips_mini_u_w:
2235 case Intrinsic::mips_mini_u_d:
2236 return DAG.getNode(Opcode: ISD::UMIN, DL, VT: Op->getValueType(ResNo: 0),
2237 N1: Op->getOperand(Num: 1), N2: lowerMSASplatImm(Op, ImmOp: 2, DAG));
2238 case Intrinsic::mips_mod_s_b:
2239 case Intrinsic::mips_mod_s_h:
2240 case Intrinsic::mips_mod_s_w:
2241 case Intrinsic::mips_mod_s_d:
2242 return DAG.getNode(Opcode: ISD::SREM, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2243 N2: Op->getOperand(Num: 2));
2244 case Intrinsic::mips_mod_u_b:
2245 case Intrinsic::mips_mod_u_h:
2246 case Intrinsic::mips_mod_u_w:
2247 case Intrinsic::mips_mod_u_d:
2248 return DAG.getNode(Opcode: ISD::UREM, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2249 N2: Op->getOperand(Num: 2));
2250 case Intrinsic::mips_mulv_b:
2251 case Intrinsic::mips_mulv_h:
2252 case Intrinsic::mips_mulv_w:
2253 case Intrinsic::mips_mulv_d:
2254 return DAG.getNode(Opcode: ISD::MUL, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2255 N2: Op->getOperand(Num: 2));
2256 case Intrinsic::mips_msubv_b:
2257 case Intrinsic::mips_msubv_h:
2258 case Intrinsic::mips_msubv_w:
2259 case Intrinsic::mips_msubv_d: {
2260 EVT ResTy = Op->getValueType(ResNo: 0);
2261 return DAG.getNode(Opcode: ISD::SUB, DL: SDLoc(Op), VT: ResTy, N1: Op->getOperand(Num: 1),
2262 N2: DAG.getNode(Opcode: ISD::MUL, DL: SDLoc(Op), VT: ResTy,
2263 N1: Op->getOperand(Num: 2), N2: Op->getOperand(Num: 3)));
2264 }
2265 case Intrinsic::mips_nlzc_b:
2266 case Intrinsic::mips_nlzc_h:
2267 case Intrinsic::mips_nlzc_w:
2268 case Intrinsic::mips_nlzc_d:
2269 return DAG.getNode(Opcode: ISD::CTLZ, DL, VT: Op->getValueType(ResNo: 0), Operand: Op->getOperand(Num: 1));
2270 case Intrinsic::mips_nor_v: {
2271 SDValue Res = DAG.getNode(Opcode: ISD::OR, DL, VT: Op->getValueType(ResNo: 0),
2272 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2));
2273 return DAG.getNOT(DL, Val: Res, VT: Res->getValueType(ResNo: 0));
2274 }
2275 case Intrinsic::mips_nori_b: {
2276 SDValue Res = DAG.getNode(Opcode: ISD::OR, DL, VT: Op->getValueType(ResNo: 0),
2277 N1: Op->getOperand(Num: 1),
2278 N2: lowerMSASplatImm(Op, ImmOp: 2, DAG));
2279 return DAG.getNOT(DL, Val: Res, VT: Res->getValueType(ResNo: 0));
2280 }
2281 case Intrinsic::mips_or_v:
2282 return DAG.getNode(Opcode: ISD::OR, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2283 N2: Op->getOperand(Num: 2));
2284 case Intrinsic::mips_ori_b:
2285 return DAG.getNode(Opcode: ISD::OR, DL, VT: Op->getValueType(ResNo: 0),
2286 N1: Op->getOperand(Num: 1), N2: lowerMSASplatImm(Op, ImmOp: 2, DAG));
2287 case Intrinsic::mips_pckev_b:
2288 case Intrinsic::mips_pckev_h:
2289 case Intrinsic::mips_pckev_w:
2290 case Intrinsic::mips_pckev_d:
2291 return DAG.getNode(Opcode: MipsISD::PCKEV, DL, VT: Op->getValueType(ResNo: 0),
2292 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2));
2293 case Intrinsic::mips_pckod_b:
2294 case Intrinsic::mips_pckod_h:
2295 case Intrinsic::mips_pckod_w:
2296 case Intrinsic::mips_pckod_d:
2297 return DAG.getNode(Opcode: MipsISD::PCKOD, DL, VT: Op->getValueType(ResNo: 0),
2298 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2));
2299 case Intrinsic::mips_pcnt_b:
2300 case Intrinsic::mips_pcnt_h:
2301 case Intrinsic::mips_pcnt_w:
2302 case Intrinsic::mips_pcnt_d:
2303 return DAG.getNode(Opcode: ISD::CTPOP, DL, VT: Op->getValueType(ResNo: 0), Operand: Op->getOperand(Num: 1));
2304 case Intrinsic::mips_sat_s_b:
2305 case Intrinsic::mips_sat_s_h:
2306 case Intrinsic::mips_sat_s_w:
2307 case Intrinsic::mips_sat_s_d:
2308 case Intrinsic::mips_sat_u_b:
2309 case Intrinsic::mips_sat_u_h:
2310 case Intrinsic::mips_sat_u_w:
2311 case Intrinsic::mips_sat_u_d: {
2312 // Report an error for out of range values.
2313 int64_t Max;
2314 switch (Intrinsic) {
2315 case Intrinsic::mips_sat_s_b:
2316 case Intrinsic::mips_sat_u_b: Max = 7; break;
2317 case Intrinsic::mips_sat_s_h:
2318 case Intrinsic::mips_sat_u_h: Max = 15; break;
2319 case Intrinsic::mips_sat_s_w:
2320 case Intrinsic::mips_sat_u_w: Max = 31; break;
2321 case Intrinsic::mips_sat_s_d:
2322 case Intrinsic::mips_sat_u_d: Max = 63; break;
2323 default: llvm_unreachable("Unmatched intrinsic");
2324 }
2325 int64_t Value = cast<ConstantSDNode>(Val: Op->getOperand(Num: 2))->getSExtValue();
2326 if (Value < 0 || Value > Max)
2327 report_fatal_error(reason: "Immediate out of range");
2328 return SDValue();
2329 }
2330 case Intrinsic::mips_shf_b:
2331 case Intrinsic::mips_shf_h:
2332 case Intrinsic::mips_shf_w: {
2333 int64_t Value = cast<ConstantSDNode>(Val: Op->getOperand(Num: 2))->getSExtValue();
2334 if (Value < 0 || Value > 255)
2335 report_fatal_error(reason: "Immediate out of range");
2336 return DAG.getNode(Opcode: MipsISD::SHF, DL, VT: Op->getValueType(ResNo: 0),
2337 N1: Op->getOperand(Num: 2), N2: Op->getOperand(Num: 1));
2338 }
2339 case Intrinsic::mips_sldi_b:
2340 case Intrinsic::mips_sldi_h:
2341 case Intrinsic::mips_sldi_w:
2342 case Intrinsic::mips_sldi_d: {
2343 // Report an error for out of range values.
2344 int64_t Max;
2345 switch (Intrinsic) {
2346 case Intrinsic::mips_sldi_b: Max = 15; break;
2347 case Intrinsic::mips_sldi_h: Max = 7; break;
2348 case Intrinsic::mips_sldi_w: Max = 3; break;
2349 case Intrinsic::mips_sldi_d: Max = 1; break;
2350 default: llvm_unreachable("Unmatched intrinsic");
2351 }
2352 int64_t Value = cast<ConstantSDNode>(Val: Op->getOperand(Num: 3))->getSExtValue();
2353 if (Value < 0 || Value > Max)
2354 report_fatal_error(reason: "Immediate out of range");
2355 return SDValue();
2356 }
2357 case Intrinsic::mips_sll_b:
2358 case Intrinsic::mips_sll_h:
2359 case Intrinsic::mips_sll_w:
2360 case Intrinsic::mips_sll_d:
2361 return DAG.getNode(Opcode: ISD::SHL, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2362 N2: truncateVecElts(Op, DAG));
2363 case Intrinsic::mips_slli_b:
2364 case Intrinsic::mips_slli_h:
2365 case Intrinsic::mips_slli_w:
2366 case Intrinsic::mips_slli_d:
2367 return DAG.getNode(Opcode: ISD::SHL, DL, VT: Op->getValueType(ResNo: 0),
2368 N1: Op->getOperand(Num: 1), N2: lowerMSASplatImm(Op, ImmOp: 2, DAG));
2369 case Intrinsic::mips_splat_b:
2370 case Intrinsic::mips_splat_h:
2371 case Intrinsic::mips_splat_w:
2372 case Intrinsic::mips_splat_d:
2373 // We can't lower via VECTOR_SHUFFLE because it requires constant shuffle
2374 // masks, nor can we lower via BUILD_VECTOR & EXTRACT_VECTOR_ELT because
2375 // EXTRACT_VECTOR_ELT can't extract i64's on MIPS32.
2376 // Instead we lower to MipsISD::VSHF and match from there.
2377 return DAG.getNode(Opcode: MipsISD::VSHF, DL, VT: Op->getValueType(ResNo: 0),
2378 N1: lowerMSASplatZExt(Op, OpNr: 2, DAG), N2: Op->getOperand(Num: 1),
2379 N3: Op->getOperand(Num: 1));
2380 case Intrinsic::mips_splati_b:
2381 case Intrinsic::mips_splati_h:
2382 case Intrinsic::mips_splati_w:
2383 case Intrinsic::mips_splati_d:
2384 return DAG.getNode(Opcode: MipsISD::VSHF, DL, VT: Op->getValueType(ResNo: 0),
2385 N1: lowerMSASplatImm(Op, ImmOp: 2, DAG), N2: Op->getOperand(Num: 1),
2386 N3: Op->getOperand(Num: 1));
2387 case Intrinsic::mips_sra_b:
2388 case Intrinsic::mips_sra_h:
2389 case Intrinsic::mips_sra_w:
2390 case Intrinsic::mips_sra_d:
2391 return DAG.getNode(Opcode: ISD::SRA, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2392 N2: truncateVecElts(Op, DAG));
2393 case Intrinsic::mips_srai_b:
2394 case Intrinsic::mips_srai_h:
2395 case Intrinsic::mips_srai_w:
2396 case Intrinsic::mips_srai_d:
2397 return DAG.getNode(Opcode: ISD::SRA, DL, VT: Op->getValueType(ResNo: 0),
2398 N1: Op->getOperand(Num: 1), N2: lowerMSASplatImm(Op, ImmOp: 2, DAG));
2399 case Intrinsic::mips_srari_b:
2400 case Intrinsic::mips_srari_h:
2401 case Intrinsic::mips_srari_w:
2402 case Intrinsic::mips_srari_d: {
2403 // Report an error for out of range values.
2404 int64_t Max;
2405 switch (Intrinsic) {
2406 case Intrinsic::mips_srari_b: Max = 7; break;
2407 case Intrinsic::mips_srari_h: Max = 15; break;
2408 case Intrinsic::mips_srari_w: Max = 31; break;
2409 case Intrinsic::mips_srari_d: Max = 63; break;
2410 default: llvm_unreachable("Unmatched intrinsic");
2411 }
2412 int64_t Value = cast<ConstantSDNode>(Val: Op->getOperand(Num: 2))->getSExtValue();
2413 if (Value < 0 || Value > Max)
2414 report_fatal_error(reason: "Immediate out of range");
2415 return SDValue();
2416 }
2417 case Intrinsic::mips_srl_b:
2418 case Intrinsic::mips_srl_h:
2419 case Intrinsic::mips_srl_w:
2420 case Intrinsic::mips_srl_d:
2421 return DAG.getNode(Opcode: ISD::SRL, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2422 N2: truncateVecElts(Op, DAG));
2423 case Intrinsic::mips_srli_b:
2424 case Intrinsic::mips_srli_h:
2425 case Intrinsic::mips_srli_w:
2426 case Intrinsic::mips_srli_d:
2427 return DAG.getNode(Opcode: ISD::SRL, DL, VT: Op->getValueType(ResNo: 0),
2428 N1: Op->getOperand(Num: 1), N2: lowerMSASplatImm(Op, ImmOp: 2, DAG));
2429 case Intrinsic::mips_srlri_b:
2430 case Intrinsic::mips_srlri_h:
2431 case Intrinsic::mips_srlri_w:
2432 case Intrinsic::mips_srlri_d: {
2433 // Report an error for out of range values.
2434 int64_t Max;
2435 switch (Intrinsic) {
2436 case Intrinsic::mips_srlri_b: Max = 7; break;
2437 case Intrinsic::mips_srlri_h: Max = 15; break;
2438 case Intrinsic::mips_srlri_w: Max = 31; break;
2439 case Intrinsic::mips_srlri_d: Max = 63; break;
2440 default: llvm_unreachable("Unmatched intrinsic");
2441 }
2442 int64_t Value = cast<ConstantSDNode>(Val: Op->getOperand(Num: 2))->getSExtValue();
2443 if (Value < 0 || Value > Max)
2444 report_fatal_error(reason: "Immediate out of range");
2445 return SDValue();
2446 }
2447 case Intrinsic::mips_subv_b:
2448 case Intrinsic::mips_subv_h:
2449 case Intrinsic::mips_subv_w:
2450 case Intrinsic::mips_subv_d:
2451 return DAG.getNode(Opcode: ISD::SUB, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2452 N2: Op->getOperand(Num: 2));
2453 case Intrinsic::mips_subvi_b:
2454 case Intrinsic::mips_subvi_h:
2455 case Intrinsic::mips_subvi_w:
2456 case Intrinsic::mips_subvi_d:
2457 return DAG.getNode(Opcode: ISD::SUB, DL, VT: Op->getValueType(ResNo: 0),
2458 N1: Op->getOperand(Num: 1), N2: lowerMSASplatImm(Op, ImmOp: 2, DAG));
2459 case Intrinsic::mips_vshf_b:
2460 case Intrinsic::mips_vshf_h:
2461 case Intrinsic::mips_vshf_w:
2462 case Intrinsic::mips_vshf_d:
2463 return DAG.getNode(Opcode: MipsISD::VSHF, DL, VT: Op->getValueType(ResNo: 0),
2464 N1: Op->getOperand(Num: 1), N2: Op->getOperand(Num: 2), N3: Op->getOperand(Num: 3));
2465 case Intrinsic::mips_xor_v:
2466 return DAG.getNode(Opcode: ISD::XOR, DL, VT: Op->getValueType(ResNo: 0), N1: Op->getOperand(Num: 1),
2467 N2: Op->getOperand(Num: 2));
2468 case Intrinsic::mips_xori_b:
2469 return DAG.getNode(Opcode: ISD::XOR, DL, VT: Op->getValueType(ResNo: 0),
2470 N1: Op->getOperand(Num: 1), N2: lowerMSASplatImm(Op, ImmOp: 2, DAG));
2471 case Intrinsic::thread_pointer: {
2472 EVT PtrVT = getPointerTy(DL: DAG.getDataLayout());
2473 return DAG.getNode(Opcode: MipsISD::ThreadPointer, DL, VT: PtrVT);
2474 }
2475 }
2476}
2477
2478static SDValue lowerMSALoadIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr,
2479 const MipsSubtarget &Subtarget) {
2480 SDLoc DL(Op);
2481 SDValue ChainIn = Op->getOperand(Num: 0);
2482 SDValue Address = Op->getOperand(Num: 2);
2483 SDValue Offset = Op->getOperand(Num: 3);
2484 EVT ResTy = Op->getValueType(ResNo: 0);
2485 EVT PtrTy = Address->getValueType(ResNo: 0);
2486
2487 // For N64 addresses have the underlying type MVT::i64. This intrinsic
2488 // however takes an i32 signed constant offset. The actual type of the
2489 // intrinsic is a scaled signed i10.
2490 if (Subtarget.isABI_N64())
2491 Offset = DAG.getNode(Opcode: ISD::SIGN_EXTEND, DL, VT: PtrTy, Operand: Offset);
2492
2493 Address = DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrTy, N1: Address, N2: Offset);
2494 return DAG.getLoad(VT: ResTy, dl: DL, Chain: ChainIn, Ptr: Address, PtrInfo: MachinePointerInfo(),
2495 Alignment: Align(16));
2496}
2497
2498SDValue MipsSETargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,
2499 SelectionDAG &DAG) const {
2500 unsigned Intr = Op->getConstantOperandVal(Num: 1);
2501 switch (Intr) {
2502 default:
2503 return SDValue();
2504 case Intrinsic::mips_extp:
2505 return lowerDSPIntr(Op, DAG, Opc: MipsISD::EXTP);
2506 case Intrinsic::mips_extpdp:
2507 return lowerDSPIntr(Op, DAG, Opc: MipsISD::EXTPDP);
2508 case Intrinsic::mips_extr_w:
2509 return lowerDSPIntr(Op, DAG, Opc: MipsISD::EXTR_W);
2510 case Intrinsic::mips_extr_r_w:
2511 return lowerDSPIntr(Op, DAG, Opc: MipsISD::EXTR_R_W);
2512 case Intrinsic::mips_extr_rs_w:
2513 return lowerDSPIntr(Op, DAG, Opc: MipsISD::EXTR_RS_W);
2514 case Intrinsic::mips_extr_s_h:
2515 return lowerDSPIntr(Op, DAG, Opc: MipsISD::EXTR_S_H);
2516 case Intrinsic::mips_mthlip:
2517 return lowerDSPIntr(Op, DAG, Opc: MipsISD::MTHLIP);
2518 case Intrinsic::mips_mulsaq_s_w_ph:
2519 return lowerDSPIntr(Op, DAG, Opc: MipsISD::MULSAQ_S_W_PH);
2520 case Intrinsic::mips_maq_s_w_phl:
2521 return lowerDSPIntr(Op, DAG, Opc: MipsISD::MAQ_S_W_PHL);
2522 case Intrinsic::mips_maq_s_w_phr:
2523 return lowerDSPIntr(Op, DAG, Opc: MipsISD::MAQ_S_W_PHR);
2524 case Intrinsic::mips_maq_sa_w_phl:
2525 return lowerDSPIntr(Op, DAG, Opc: MipsISD::MAQ_SA_W_PHL);
2526 case Intrinsic::mips_maq_sa_w_phr:
2527 return lowerDSPIntr(Op, DAG, Opc: MipsISD::MAQ_SA_W_PHR);
2528 case Intrinsic::mips_dpaq_s_w_ph:
2529 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPAQ_S_W_PH);
2530 case Intrinsic::mips_dpsq_s_w_ph:
2531 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPSQ_S_W_PH);
2532 case Intrinsic::mips_dpaq_sa_l_w:
2533 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPAQ_SA_L_W);
2534 case Intrinsic::mips_dpsq_sa_l_w:
2535 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPSQ_SA_L_W);
2536 case Intrinsic::mips_dpaqx_s_w_ph:
2537 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPAQX_S_W_PH);
2538 case Intrinsic::mips_dpaqx_sa_w_ph:
2539 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPAQX_SA_W_PH);
2540 case Intrinsic::mips_dpsqx_s_w_ph:
2541 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPSQX_S_W_PH);
2542 case Intrinsic::mips_dpsqx_sa_w_ph:
2543 return lowerDSPIntr(Op, DAG, Opc: MipsISD::DPSQX_SA_W_PH);
2544 case Intrinsic::mips_ld_b:
2545 case Intrinsic::mips_ld_h:
2546 case Intrinsic::mips_ld_w:
2547 case Intrinsic::mips_ld_d:
2548 return lowerMSALoadIntr(Op, DAG, Intr, Subtarget);
2549 }
2550}
2551
2552static SDValue lowerMSAStoreIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr,
2553 const MipsSubtarget &Subtarget) {
2554 SDLoc DL(Op);
2555 SDValue ChainIn = Op->getOperand(Num: 0);
2556 SDValue Value = Op->getOperand(Num: 2);
2557 SDValue Address = Op->getOperand(Num: 3);
2558 SDValue Offset = Op->getOperand(Num: 4);
2559 EVT PtrTy = Address->getValueType(ResNo: 0);
2560
2561 // For N64 addresses have the underlying type MVT::i64. This intrinsic
2562 // however takes an i32 signed constant offset. The actual type of the
2563 // intrinsic is a scaled signed i10.
2564 if (Subtarget.isABI_N64())
2565 Offset = DAG.getNode(Opcode: ISD::SIGN_EXTEND, DL, VT: PtrTy, Operand: Offset);
2566
2567 Address = DAG.getNode(Opcode: ISD::ADD, DL, VT: PtrTy, N1: Address, N2: Offset);
2568
2569 return DAG.getStore(Chain: ChainIn, dl: DL, Val: Value, Ptr: Address, PtrInfo: MachinePointerInfo(),
2570 Alignment: Align(16));
2571}
2572
2573SDValue MipsSETargetLowering::lowerINTRINSIC_VOID(SDValue Op,
2574 SelectionDAG &DAG) const {
2575 unsigned Intr = Op->getConstantOperandVal(Num: 1);
2576 switch (Intr) {
2577 default:
2578 return SDValue();
2579 case Intrinsic::mips_st_b:
2580 case Intrinsic::mips_st_h:
2581 case Intrinsic::mips_st_w:
2582 case Intrinsic::mips_st_d:
2583 return lowerMSAStoreIntr(Op, DAG, Intr, Subtarget);
2584 }
2585}
2586
2587// Lower ISD::EXTRACT_VECTOR_ELT into MipsISD::VEXTRACT_SEXT_ELT.
2588//
2589// The non-value bits resulting from ISD::EXTRACT_VECTOR_ELT are undefined. We
2590// choose to sign-extend but we could have equally chosen zero-extend. The
2591// DAGCombiner will fold any sign/zero extension of the ISD::EXTRACT_VECTOR_ELT
2592// result into this node later (possibly changing it to a zero-extend in the
2593// process).
2594SDValue MipsSETargetLowering::
2595lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const {
2596 SDLoc DL(Op);
2597 EVT ResTy = Op->getValueType(ResNo: 0);
2598 SDValue Op0 = Op->getOperand(Num: 0);
2599 EVT VecTy = Op0->getValueType(ResNo: 0);
2600
2601 if (!VecTy.is128BitVector())
2602 return SDValue();
2603
2604 if (ResTy.isInteger()) {
2605 SDValue Op1 = Op->getOperand(Num: 1);
2606 EVT EltTy = VecTy.getVectorElementType();
2607 return DAG.getNode(Opcode: MipsISD::VEXTRACT_SEXT_ELT, DL, VT: ResTy, N1: Op0, N2: Op1,
2608 N3: DAG.getValueType(EltTy));
2609 }
2610
2611 return Op;
2612}
2613
2614static bool isConstantOrUndef(const SDValue Op) {
2615 if (Op->isUndef())
2616 return true;
2617 if (isa<ConstantSDNode>(Val: Op))
2618 return true;
2619 if (isa<ConstantFPSDNode>(Val: Op))
2620 return true;
2621 return false;
2622}
2623
2624static bool isConstantOrUndefBUILD_VECTOR(const BuildVectorSDNode *Op) {
2625 for (unsigned i = 0; i < Op->getNumOperands(); ++i)
2626 if (isConstantOrUndef(Op: Op->getOperand(Num: i)))
2627 return true;
2628 return false;
2629}
2630
2631// Lowers ISD::BUILD_VECTOR into appropriate SelectionDAG nodes for the
2632// backend.
2633//
2634// Lowers according to the following rules:
2635// - Constant splats are legal as-is as long as the SplatBitSize is a power of
2636// 2 less than or equal to 64 and the value fits into a signed 10-bit
2637// immediate
2638// - Constant splats are lowered to bitconverted BUILD_VECTORs if SplatBitSize
2639// is a power of 2 less than or equal to 64 and the value does not fit into a
2640// signed 10-bit immediate
2641// - Non-constant splats are legal as-is.
2642// - Non-constant non-splats are lowered to sequences of INSERT_VECTOR_ELT.
2643// - All others are illegal and must be expanded.
2644SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op,
2645 SelectionDAG &DAG) const {
2646 BuildVectorSDNode *Node = cast<BuildVectorSDNode>(Val&: Op);
2647 EVT ResTy = Op->getValueType(ResNo: 0);
2648 SDLoc DL(Op);
2649 APInt SplatValue, SplatUndef;
2650 unsigned SplatBitSize;
2651 bool HasAnyUndefs;
2652
2653 if (!Subtarget.hasMSA() || !ResTy.is128BitVector())
2654 return SDValue();
2655
2656 if (Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
2657 HasAnyUndefs, MinSplatBits: 8,
2658 isBigEndian: !Subtarget.isLittle()) && SplatBitSize <= 64) {
2659 // We can only cope with 8, 16, 32, or 64-bit elements
2660 if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
2661 SplatBitSize != 64)
2662 return SDValue();
2663
2664 // If the value isn't an integer type we will have to bitcast
2665 // from an integer type first. Also, if there are any undefs, we must
2666 // lower them to defined values first.
2667 if (ResTy.isInteger() && !HasAnyUndefs)
2668 return Op;
2669
2670 EVT ViaVecTy;
2671
2672 switch (SplatBitSize) {
2673 default:
2674 return SDValue();
2675 case 8:
2676 ViaVecTy = MVT::v16i8;
2677 break;
2678 case 16:
2679 ViaVecTy = MVT::v8i16;
2680 break;
2681 case 32:
2682 ViaVecTy = MVT::v4i32;
2683 break;
2684 case 64:
2685 // There's no fill.d to fall back on for 64-bit values
2686 return SDValue();
2687 }
2688
2689 // SelectionDAG::getConstant will promote SplatValue appropriately.
2690 SDValue Result = DAG.getConstant(Val: SplatValue, DL, VT: ViaVecTy);
2691
2692 // Bitcast to the type we originally wanted
2693 if (ViaVecTy != ResTy)
2694 Result = DAG.getNode(Opcode: ISD::BITCAST, DL: SDLoc(Node), VT: ResTy, Operand: Result);
2695
2696 return Result;
2697 } else if (DAG.isSplatValue(V: Op, /* AllowUndefs */ false))
2698 return Op;
2699 else if (!isConstantOrUndefBUILD_VECTOR(Op: Node)) {
2700 // Use INSERT_VECTOR_ELT operations rather than expand to stores.
2701 // The resulting code is the same length as the expansion, but it doesn't
2702 // use memory operations
2703 EVT ResTy = Node->getValueType(ResNo: 0);
2704
2705 assert(ResTy.isVector());
2706
2707 unsigned NumElts = ResTy.getVectorNumElements();
2708 SDValue Vector = DAG.getUNDEF(VT: ResTy);
2709 for (unsigned i = 0; i < NumElts; ++i) {
2710 Vector = DAG.getNode(Opcode: ISD::INSERT_VECTOR_ELT, DL, VT: ResTy, N1: Vector,
2711 N2: Node->getOperand(Num: i),
2712 N3: DAG.getConstant(Val: i, DL, VT: MVT::i32));
2713 }
2714 return Vector;
2715 }
2716
2717 return SDValue();
2718}
2719
2720// Lower VECTOR_SHUFFLE into SHF (if possible).
2721//
2722// SHF splits the vector into blocks of four elements, then shuffles these
2723// elements according to a <4 x i2> constant (encoded as an integer immediate).
2724//
2725// It is therefore possible to lower into SHF when the mask takes the form:
2726// <a, b, c, d, a+4, b+4, c+4, d+4, a+8, b+8, c+8, d+8, ...>
2727// When undef's appear they are treated as if they were whatever value is
2728// necessary in order to fit the above forms.
2729//
2730// For example:
2731// %2 = shufflevector <8 x i16> %0, <8 x i16> undef,
2732// <8 x i32> <i32 3, i32 2, i32 1, i32 0,
2733// i32 7, i32 6, i32 5, i32 4>
2734// is lowered to:
2735// (SHF_H $w0, $w1, 27)
2736// where the 27 comes from:
2737// 3 + (2 << 2) + (1 << 4) + (0 << 6)
2738static SDValue lowerVECTOR_SHUFFLE_SHF(SDValue Op, EVT ResTy,
2739 SmallVector<int, 16> Indices,
2740 SelectionDAG &DAG) {
2741 int SHFIndices[4] = { -1, -1, -1, -1 };
2742
2743 if (Indices.size() < 4)
2744 return SDValue();
2745
2746 for (unsigned i = 0; i < 4; ++i) {
2747 for (unsigned j = i; j < Indices.size(); j += 4) {
2748 int Idx = Indices[j];
2749
2750 // Convert from vector index to 4-element subvector index
2751 // If an index refers to an element outside of the subvector then give up
2752 if (Idx != -1) {
2753 Idx -= 4 * (j / 4);
2754 if (Idx < 0 || Idx >= 4)
2755 return SDValue();
2756 }
2757
2758 // If the mask has an undef, replace it with the current index.
2759 // Note that it might still be undef if the current index is also undef
2760 if (SHFIndices[i] == -1)
2761 SHFIndices[i] = Idx;
2762
2763 // Check that non-undef values are the same as in the mask. If they
2764 // aren't then give up
2765 if (!(Idx == -1 || Idx == SHFIndices[i]))
2766 return SDValue();
2767 }
2768 }
2769
2770 // Calculate the immediate. Replace any remaining undefs with zero
2771 APInt Imm(32, 0);
2772 for (int i = 3; i >= 0; --i) {
2773 int Idx = SHFIndices[i];
2774
2775 if (Idx == -1)
2776 Idx = 0;
2777
2778 Imm <<= 2;
2779 Imm |= Idx & 0x3;
2780 }
2781
2782 SDLoc DL(Op);
2783 return DAG.getNode(Opcode: MipsISD::SHF, DL, VT: ResTy,
2784 N1: DAG.getTargetConstant(Val: Imm, DL, VT: MVT::i32),
2785 N2: Op->getOperand(Num: 0));
2786}
2787
2788/// Determine whether a range fits a regular pattern of values.
2789/// This function accounts for the possibility of jumping over the End iterator.
2790template <typename ValType>
2791static bool
2792fitsRegularPattern(typename SmallVectorImpl<ValType>::const_iterator Begin,
2793 unsigned CheckStride,
2794 typename SmallVectorImpl<ValType>::const_iterator End,
2795 ValType ExpectedIndex, unsigned ExpectedIndexStride) {
2796 auto &I = Begin;
2797
2798 while (I != End) {
2799 if (*I != -1 && *I != ExpectedIndex)
2800 return false;
2801 ExpectedIndex += ExpectedIndexStride;
2802
2803 // Incrementing past End is undefined behaviour so we must increment one
2804 // step at a time and check for End at each step.
2805 for (unsigned n = 0; n < CheckStride && I != End; ++n, ++I)
2806 ; // Empty loop body.
2807 }
2808 return true;
2809}
2810
2811// Determine whether VECTOR_SHUFFLE is a SPLATI.
2812//
2813// It is a SPLATI when the mask is:
2814// <x, x, x, ...>
2815// where x is any valid index.
2816//
2817// When undef's appear in the mask they are treated as if they were whatever
2818// value is necessary in order to fit the above form.
2819static bool isVECTOR_SHUFFLE_SPLATI(SDValue Op, EVT ResTy,
2820 SmallVector<int, 16> Indices,
2821 SelectionDAG &DAG) {
2822 assert((Indices.size() % 2) == 0);
2823
2824 int SplatIndex = -1;
2825 for (const auto &V : Indices) {
2826 if (V != -1) {
2827 SplatIndex = V;
2828 break;
2829 }
2830 }
2831
2832 return fitsRegularPattern<int>(Begin: Indices.begin(), CheckStride: 1, End: Indices.end(), ExpectedIndex: SplatIndex,
2833 ExpectedIndexStride: 0);
2834}
2835
2836// Lower VECTOR_SHUFFLE into ILVEV (if possible).
2837//
2838// ILVEV interleaves the even elements from each vector.
2839//
2840// It is possible to lower into ILVEV when the mask consists of two of the
2841// following forms interleaved:
2842// <0, 2, 4, ...>
2843// <n, n+2, n+4, ...>
2844// where n is the number of elements in the vector.
2845// For example:
2846// <0, 0, 2, 2, 4, 4, ...>
2847// <0, n, 2, n+2, 4, n+4, ...>
2848//
2849// When undef's appear in the mask they are treated as if they were whatever
2850// value is necessary in order to fit the above forms.
2851static SDValue lowerVECTOR_SHUFFLE_ILVEV(SDValue Op, EVT ResTy,
2852 SmallVector<int, 16> Indices,
2853 SelectionDAG &DAG) {
2854 assert((Indices.size() % 2) == 0);
2855
2856 SDValue Wt;
2857 SDValue Ws;
2858 const auto &Begin = Indices.begin();
2859 const auto &End = Indices.end();
2860
2861 // Check even elements are taken from the even elements of one half or the
2862 // other and pick an operand accordingly.
2863 if (fitsRegularPattern<int>(Begin, CheckStride: 2, End, ExpectedIndex: 0, ExpectedIndexStride: 2))
2864 Wt = Op->getOperand(Num: 0);
2865 else if (fitsRegularPattern<int>(Begin, CheckStride: 2, End, ExpectedIndex: Indices.size(), ExpectedIndexStride: 2))
2866 Wt = Op->getOperand(Num: 1);
2867 else
2868 return SDValue();
2869
2870 // Check odd elements are taken from the even elements of one half or the
2871 // other and pick an operand accordingly.
2872 if (fitsRegularPattern<int>(Begin: Begin + 1, CheckStride: 2, End, ExpectedIndex: 0, ExpectedIndexStride: 2))
2873 Ws = Op->getOperand(Num: 0);
2874 else if (fitsRegularPattern<int>(Begin: Begin + 1, CheckStride: 2, End, ExpectedIndex: Indices.size(), ExpectedIndexStride: 2))
2875 Ws = Op->getOperand(Num: 1);
2876 else
2877 return SDValue();
2878
2879 return DAG.getNode(Opcode: MipsISD::ILVEV, DL: SDLoc(Op), VT: ResTy, N1: Ws, N2: Wt);
2880}
2881
2882// Lower VECTOR_SHUFFLE into ILVOD (if possible).
2883//
2884// ILVOD interleaves the odd elements from each vector.
2885//
2886// It is possible to lower into ILVOD when the mask consists of two of the
2887// following forms interleaved:
2888// <1, 3, 5, ...>
2889// <n+1, n+3, n+5, ...>
2890// where n is the number of elements in the vector.
2891// For example:
2892// <1, 1, 3, 3, 5, 5, ...>
2893// <1, n+1, 3, n+3, 5, n+5, ...>
2894//
2895// When undef's appear in the mask they are treated as if they were whatever
2896// value is necessary in order to fit the above forms.
2897static SDValue lowerVECTOR_SHUFFLE_ILVOD(SDValue Op, EVT ResTy,
2898 SmallVector<int, 16> Indices,
2899 SelectionDAG &DAG) {
2900 assert((Indices.size() % 2) == 0);
2901
2902 SDValue Wt;
2903 SDValue Ws;
2904 const auto &Begin = Indices.begin();
2905 const auto &End = Indices.end();
2906
2907 // Check even elements are taken from the odd elements of one half or the
2908 // other and pick an operand accordingly.
2909 if (fitsRegularPattern<int>(Begin, CheckStride: 2, End, ExpectedIndex: 1, ExpectedIndexStride: 2))
2910 Wt = Op->getOperand(Num: 0);
2911 else if (fitsRegularPattern<int>(Begin, CheckStride: 2, End, ExpectedIndex: Indices.size() + 1, ExpectedIndexStride: 2))
2912 Wt = Op->getOperand(Num: 1);
2913 else
2914 return SDValue();
2915
2916 // Check odd elements are taken from the odd elements of one half or the
2917 // other and pick an operand accordingly.
2918 if (fitsRegularPattern<int>(Begin: Begin + 1, CheckStride: 2, End, ExpectedIndex: 1, ExpectedIndexStride: 2))
2919 Ws = Op->getOperand(Num: 0);
2920 else if (fitsRegularPattern<int>(Begin: Begin + 1, CheckStride: 2, End, ExpectedIndex: Indices.size() + 1, ExpectedIndexStride: 2))
2921 Ws = Op->getOperand(Num: 1);
2922 else
2923 return SDValue();
2924
2925 return DAG.getNode(Opcode: MipsISD::ILVOD, DL: SDLoc(Op), VT: ResTy, N1: Ws, N2: Wt);
2926}
2927
2928// Lower VECTOR_SHUFFLE into ILVR (if possible).
2929//
2930// ILVR interleaves consecutive elements from the right (lowest-indexed) half of
2931// each vector.
2932//
2933// It is possible to lower into ILVR when the mask consists of two of the
2934// following forms interleaved:
2935// <0, 1, 2, ...>
2936// <n, n+1, n+2, ...>
2937// where n is the number of elements in the vector.
2938// For example:
2939// <0, 0, 1, 1, 2, 2, ...>
2940// <0, n, 1, n+1, 2, n+2, ...>
2941//
2942// When undef's appear in the mask they are treated as if they were whatever
2943// value is necessary in order to fit the above forms.
2944static SDValue lowerVECTOR_SHUFFLE_ILVR(SDValue Op, EVT ResTy,
2945 SmallVector<int, 16> Indices,
2946 SelectionDAG &DAG) {
2947 assert((Indices.size() % 2) == 0);
2948
2949 SDValue Wt;
2950 SDValue Ws;
2951 const auto &Begin = Indices.begin();
2952 const auto &End = Indices.end();
2953
2954 // Check even elements are taken from the right (lowest-indexed) elements of
2955 // one half or the other and pick an operand accordingly.
2956 if (fitsRegularPattern<int>(Begin, CheckStride: 2, End, ExpectedIndex: 0, ExpectedIndexStride: 1))
2957 Wt = Op->getOperand(Num: 0);
2958 else if (fitsRegularPattern<int>(Begin, CheckStride: 2, End, ExpectedIndex: Indices.size(), ExpectedIndexStride: 1))
2959 Wt = Op->getOperand(Num: 1);
2960 else
2961 return SDValue();
2962
2963 // Check odd elements are taken from the right (lowest-indexed) elements of
2964 // one half or the other and pick an operand accordingly.
2965 if (fitsRegularPattern<int>(Begin: Begin + 1, CheckStride: 2, End, ExpectedIndex: 0, ExpectedIndexStride: 1))
2966 Ws = Op->getOperand(Num: 0);
2967 else if (fitsRegularPattern<int>(Begin: Begin + 1, CheckStride: 2, End, ExpectedIndex: Indices.size(), ExpectedIndexStride: 1))
2968 Ws = Op->getOperand(Num: 1);
2969 else
2970 return SDValue();
2971
2972 return DAG.getNode(Opcode: MipsISD::ILVR, DL: SDLoc(Op), VT: ResTy, N1: Ws, N2: Wt);
2973}
2974
2975// Lower VECTOR_SHUFFLE into ILVL (if possible).
2976//
2977// ILVL interleaves consecutive elements from the left (highest-indexed) half
2978// of each vector.
2979//
2980// It is possible to lower into ILVL when the mask consists of two of the
2981// following forms interleaved:
2982// <x, x+1, x+2, ...>
2983// <n+x, n+x+1, n+x+2, ...>
2984// where n is the number of elements in the vector and x is half n.
2985// For example:
2986// <x, x, x+1, x+1, x+2, x+2, ...>
2987// <x, n+x, x+1, n+x+1, x+2, n+x+2, ...>
2988//
2989// When undef's appear in the mask they are treated as if they were whatever
2990// value is necessary in order to fit the above forms.
2991static SDValue lowerVECTOR_SHUFFLE_ILVL(SDValue Op, EVT ResTy,
2992 SmallVector<int, 16> Indices,
2993 SelectionDAG &DAG) {
2994 assert((Indices.size() % 2) == 0);
2995
2996 unsigned HalfSize = Indices.size() / 2;
2997 SDValue Wt;
2998 SDValue Ws;
2999 const auto &Begin = Indices.begin();
3000 const auto &End = Indices.end();
3001
3002 // Check even elements are taken from the left (highest-indexed) elements of
3003 // one half or the other and pick an operand accordingly.
3004 if (fitsRegularPattern<int>(Begin, CheckStride: 2, End, ExpectedIndex: HalfSize, ExpectedIndexStride: 1))
3005 Wt = Op->getOperand(Num: 0);
3006 else if (fitsRegularPattern<int>(Begin, CheckStride: 2, End, ExpectedIndex: Indices.size() + HalfSize, ExpectedIndexStride: 1))
3007 Wt = Op->getOperand(Num: 1);
3008 else
3009 return SDValue();
3010
3011 // Check odd elements are taken from the left (highest-indexed) elements of
3012 // one half or the other and pick an operand accordingly.
3013 if (fitsRegularPattern<int>(Begin: Begin + 1, CheckStride: 2, End, ExpectedIndex: HalfSize, ExpectedIndexStride: 1))
3014 Ws = Op->getOperand(Num: 0);
3015 else if (fitsRegularPattern<int>(Begin: Begin + 1, CheckStride: 2, End, ExpectedIndex: Indices.size() + HalfSize,
3016 ExpectedIndexStride: 1))
3017 Ws = Op->getOperand(Num: 1);
3018 else
3019 return SDValue();
3020
3021 return DAG.getNode(Opcode: MipsISD::ILVL, DL: SDLoc(Op), VT: ResTy, N1: Ws, N2: Wt);
3022}
3023
3024// Lower VECTOR_SHUFFLE into PCKEV (if possible).
3025//
3026// PCKEV copies the even elements of each vector into the result vector.
3027//
3028// It is possible to lower into PCKEV when the mask consists of two of the
3029// following forms concatenated:
3030// <0, 2, 4, ...>
3031// <n, n+2, n+4, ...>
3032// where n is the number of elements in the vector.
3033// For example:
3034// <0, 2, 4, ..., 0, 2, 4, ...>
3035// <0, 2, 4, ..., n, n+2, n+4, ...>
3036//
3037// When undef's appear in the mask they are treated as if they were whatever
3038// value is necessary in order to fit the above forms.
3039static SDValue lowerVECTOR_SHUFFLE_PCKEV(SDValue Op, EVT ResTy,
3040 SmallVector<int, 16> Indices,
3041 SelectionDAG &DAG) {
3042 assert((Indices.size() % 2) == 0);
3043
3044 SDValue Wt;
3045 SDValue Ws;
3046 const auto &Begin = Indices.begin();
3047 const auto &Mid = Indices.begin() + Indices.size() / 2;
3048 const auto &End = Indices.end();
3049
3050 if (fitsRegularPattern<int>(Begin, CheckStride: 1, End: Mid, ExpectedIndex: 0, ExpectedIndexStride: 2))
3051 Wt = Op->getOperand(Num: 0);
3052 else if (fitsRegularPattern<int>(Begin, CheckStride: 1, End: Mid, ExpectedIndex: Indices.size(), ExpectedIndexStride: 2))
3053 Wt = Op->getOperand(Num: 1);
3054 else
3055 return SDValue();
3056
3057 if (fitsRegularPattern<int>(Begin: Mid, CheckStride: 1, End, ExpectedIndex: 0, ExpectedIndexStride: 2))
3058 Ws = Op->getOperand(Num: 0);
3059 else if (fitsRegularPattern<int>(Begin: Mid, CheckStride: 1, End, ExpectedIndex: Indices.size(), ExpectedIndexStride: 2))
3060 Ws = Op->getOperand(Num: 1);
3061 else
3062 return SDValue();
3063
3064 return DAG.getNode(Opcode: MipsISD::PCKEV, DL: SDLoc(Op), VT: ResTy, N1: Ws, N2: Wt);
3065}
3066
3067// Lower VECTOR_SHUFFLE into PCKOD (if possible).
3068//
3069// PCKOD copies the odd elements of each vector into the result vector.
3070//
3071// It is possible to lower into PCKOD when the mask consists of two of the
3072// following forms concatenated:
3073// <1, 3, 5, ...>
3074// <n+1, n+3, n+5, ...>
3075// where n is the number of elements in the vector.
3076// For example:
3077// <1, 3, 5, ..., 1, 3, 5, ...>
3078// <1, 3, 5, ..., n+1, n+3, n+5, ...>
3079//
3080// When undef's appear in the mask they are treated as if they were whatever
3081// value is necessary in order to fit the above forms.
3082static SDValue lowerVECTOR_SHUFFLE_PCKOD(SDValue Op, EVT ResTy,
3083 SmallVector<int, 16> Indices,
3084 SelectionDAG &DAG) {
3085 assert((Indices.size() % 2) == 0);
3086
3087 SDValue Wt;
3088 SDValue Ws;
3089 const auto &Begin = Indices.begin();
3090 const auto &Mid = Indices.begin() + Indices.size() / 2;
3091 const auto &End = Indices.end();
3092
3093 if (fitsRegularPattern<int>(Begin, CheckStride: 1, End: Mid, ExpectedIndex: 1, ExpectedIndexStride: 2))
3094 Wt = Op->getOperand(Num: 0);
3095 else if (fitsRegularPattern<int>(Begin, CheckStride: 1, End: Mid, ExpectedIndex: Indices.size() + 1, ExpectedIndexStride: 2))
3096 Wt = Op->getOperand(Num: 1);
3097 else
3098 return SDValue();
3099
3100 if (fitsRegularPattern<int>(Begin: Mid, CheckStride: 1, End, ExpectedIndex: 1, ExpectedIndexStride: 2))
3101 Ws = Op->getOperand(Num: 0);
3102 else if (fitsRegularPattern<int>(Begin: Mid, CheckStride: 1, End, ExpectedIndex: Indices.size() + 1, ExpectedIndexStride: 2))
3103 Ws = Op->getOperand(Num: 1);
3104 else
3105 return SDValue();
3106
3107 return DAG.getNode(Opcode: MipsISD::PCKOD, DL: SDLoc(Op), VT: ResTy, N1: Ws, N2: Wt);
3108}
3109
3110// Lower VECTOR_SHUFFLE into VSHF.
3111//
3112// This mostly consists of converting the shuffle indices in Indices into a
3113// BUILD_VECTOR and adding it as an operand to the resulting VSHF. There is
3114// also code to eliminate unused operands of the VECTOR_SHUFFLE. For example,
3115// if the type is v8i16 and all the indices are less than 8 then the second
3116// operand is unused and can be replaced with anything. We choose to replace it
3117// with the used operand since this reduces the number of instructions overall.
3118//
3119// NOTE: SPLATI shuffle masks may contain UNDEFs, since isSPLATI() treats
3120// UNDEFs as same as SPLATI index.
3121// For other instances we use the last valid index if UNDEF is
3122// encountered.
3123static SDValue lowerVECTOR_SHUFFLE_VSHF(SDValue Op, EVT ResTy,
3124 const SmallVector<int, 16> &Indices,
3125 const bool isSPLATI,
3126 SelectionDAG &DAG) {
3127 SmallVector<SDValue, 16> Ops;
3128 SDValue Op0;
3129 SDValue Op1;
3130 EVT MaskVecTy = ResTy.changeVectorElementTypeToInteger();
3131 EVT MaskEltTy = MaskVecTy.getVectorElementType();
3132 bool Using1stVec = false;
3133 bool Using2ndVec = false;
3134 SDLoc DL(Op);
3135 int ResTyNumElts = ResTy.getVectorNumElements();
3136
3137 for (int i = 0; i < ResTyNumElts; ++i) {
3138 // Idx == -1 means UNDEF/poison
3139 int Idx = Indices[i];
3140
3141 if (0 <= Idx && Idx < ResTyNumElts)
3142 Using1stVec = true;
3143 if (ResTyNumElts <= Idx && Idx < ResTyNumElts * 2)
3144 Using2ndVec = true;
3145 }
3146
3147 // Find the first non-undef index. This index is used as a default when there
3148 // is a leading UNDEF/poison.
3149 int SplatIndex = 0;
3150 for (int Idx : Indices)
3151 if (Idx >= 0) {
3152 SplatIndex = Idx;
3153 break;
3154 }
3155
3156 int LastValidIndex = SplatIndex;
3157 for (size_t i = 0; i < Indices.size(); i++) {
3158 int Idx = Indices[i];
3159 if (Idx < 0) {
3160 // Continue using splati index or use the last valid index.
3161 Idx = isSPLATI ? SplatIndex : LastValidIndex;
3162 } else {
3163 LastValidIndex = Idx;
3164 }
3165 Ops.push_back(Elt: DAG.getTargetConstant(Val: Idx, DL, VT: MaskEltTy));
3166 }
3167
3168 SDValue MaskVec = DAG.getBuildVector(VT: MaskVecTy, DL, Ops);
3169
3170 if (Using1stVec && Using2ndVec) {
3171 Op0 = Op->getOperand(Num: 0);
3172 Op1 = Op->getOperand(Num: 1);
3173 } else if (Using1stVec)
3174 Op0 = Op1 = Op->getOperand(Num: 0);
3175 else if (Using2ndVec)
3176 Op0 = Op1 = Op->getOperand(Num: 1);
3177 else
3178 llvm_unreachable("shuffle vector mask references neither vector operand?");
3179
3180 // VECTOR_SHUFFLE concatenates the vectors in an vectorwise fashion.
3181 // <0b00, 0b01> + <0b10, 0b11> -> <0b00, 0b01, 0b10, 0b11>
3182 // VSHF concatenates the vectors in a bitwise fashion:
3183 // <0b00, 0b01> + <0b10, 0b11> ->
3184 // 0b0100 + 0b1110 -> 0b01001110
3185 // <0b10, 0b11, 0b00, 0b01>
3186 // We must therefore swap the operands to get the correct result.
3187 return DAG.getNode(Opcode: MipsISD::VSHF, DL, VT: ResTy, N1: MaskVec, N2: Op1, N3: Op0);
3188}
3189
3190// Lower VECTOR_SHUFFLE into one of a number of instructions depending on the
3191// indices in the shuffle.
3192SDValue MipsSETargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
3193 SelectionDAG &DAG) const {
3194 ShuffleVectorSDNode *Node = cast<ShuffleVectorSDNode>(Val&: Op);
3195 EVT ResTy = Op->getValueType(ResNo: 0);
3196
3197 if (!ResTy.is128BitVector())
3198 return SDValue();
3199
3200 int ResTyNumElts = ResTy.getVectorNumElements();
3201 SmallVector<int, 16> Indices;
3202
3203 for (int i = 0; i < ResTyNumElts; ++i)
3204 Indices.push_back(Elt: Node->getMaskElt(Idx: i));
3205
3206 // splati.[bhwd] is preferable to the others but is matched from
3207 // MipsISD::VSHF.
3208 if (isVECTOR_SHUFFLE_SPLATI(Op, ResTy, Indices, DAG))
3209 return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, isSPLATI: true, DAG);
3210 SDValue Result;
3211 if ((Result = lowerVECTOR_SHUFFLE_ILVEV(Op, ResTy, Indices, DAG)))
3212 return Result;
3213 if ((Result = lowerVECTOR_SHUFFLE_ILVOD(Op, ResTy, Indices, DAG)))
3214 return Result;
3215 if ((Result = lowerVECTOR_SHUFFLE_ILVL(Op, ResTy, Indices, DAG)))
3216 return Result;
3217 if ((Result = lowerVECTOR_SHUFFLE_ILVR(Op, ResTy, Indices, DAG)))
3218 return Result;
3219 if ((Result = lowerVECTOR_SHUFFLE_PCKEV(Op, ResTy, Indices, DAG)))
3220 return Result;
3221 if ((Result = lowerVECTOR_SHUFFLE_PCKOD(Op, ResTy, Indices, DAG)))
3222 return Result;
3223 if ((Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG)))
3224 return Result;
3225 return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, isSPLATI: false, DAG);
3226}
3227
3228MachineBasicBlock *
3229MipsSETargetLowering::emitBPOSGE32(MachineInstr &MI,
3230 MachineBasicBlock *BB) const {
3231 // $bb:
3232 // bposge32_pseudo $vr0
3233 // =>
3234 // $bb:
3235 // bposge32 $tbb
3236 // $fbb:
3237 // li $vr2, 0
3238 // b $sink
3239 // $tbb:
3240 // li $vr1, 1
3241 // $sink:
3242 // $vr0 = phi($vr2, $fbb, $vr1, $tbb)
3243
3244 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3245 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3246 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
3247 DebugLoc DL = MI.getDebugLoc();
3248 const BasicBlock *LLVM_BB = BB->getBasicBlock();
3249 MachineFunction::iterator It = std::next(x: MachineFunction::iterator(BB));
3250 MachineFunction *F = BB->getParent();
3251 MachineBasicBlock *FBB = F->CreateMachineBasicBlock(BB: LLVM_BB);
3252 MachineBasicBlock *TBB = F->CreateMachineBasicBlock(BB: LLVM_BB);
3253 MachineBasicBlock *Sink = F->CreateMachineBasicBlock(BB: LLVM_BB);
3254 F->insert(MBBI: It, MBB: FBB);
3255 F->insert(MBBI: It, MBB: TBB);
3256 F->insert(MBBI: It, MBB: Sink);
3257
3258 // Transfer the remainder of BB and its successor edges to Sink.
3259 Sink->splice(Where: Sink->begin(), Other: BB, From: std::next(x: MachineBasicBlock::iterator(MI)),
3260 To: BB->end());
3261 Sink->transferSuccessorsAndUpdatePHIs(FromMBB: BB);
3262
3263 // Add successors.
3264 BB->addSuccessor(Succ: FBB);
3265 BB->addSuccessor(Succ: TBB);
3266 FBB->addSuccessor(Succ: Sink);
3267 TBB->addSuccessor(Succ: Sink);
3268
3269 // Insert the real bposge32 instruction to $BB.
3270 BuildMI(BB, MIMD: DL, MCID: TII->get(Opcode: Mips::BPOSGE32)).addMBB(MBB: TBB);
3271 // Insert the real bposge32c instruction to $BB.
3272 BuildMI(BB, MIMD: DL, MCID: TII->get(Opcode: Mips::BPOSGE32C_MMR3)).addMBB(MBB: TBB);
3273
3274 // Fill $FBB.
3275 Register VR2 = RegInfo.createVirtualRegister(RegClass: RC);
3276 BuildMI(BB&: *FBB, I: FBB->end(), MIMD: DL, MCID: TII->get(Opcode: Mips::ADDiu), DestReg: VR2)
3277 .addReg(RegNo: Mips::ZERO).addImm(Val: 0);
3278 BuildMI(BB&: *FBB, I: FBB->end(), MIMD: DL, MCID: TII->get(Opcode: Mips::B)).addMBB(MBB: Sink);
3279
3280 // Fill $TBB.
3281 Register VR1 = RegInfo.createVirtualRegister(RegClass: RC);
3282 BuildMI(BB&: *TBB, I: TBB->end(), MIMD: DL, MCID: TII->get(Opcode: Mips::ADDiu), DestReg: VR1)
3283 .addReg(RegNo: Mips::ZERO).addImm(Val: 1);
3284
3285 // Insert phi function to $Sink.
3286 BuildMI(BB&: *Sink, I: Sink->begin(), MIMD: DL, MCID: TII->get(Opcode: Mips::PHI),
3287 DestReg: MI.getOperand(i: 0).getReg())
3288 .addReg(RegNo: VR2)
3289 .addMBB(MBB: FBB)
3290 .addReg(RegNo: VR1)
3291 .addMBB(MBB: TBB);
3292
3293 MI.eraseFromParent(); // The pseudo instruction is gone now.
3294 return Sink;
3295}
3296
3297MachineBasicBlock *MipsSETargetLowering::emitMSACBranchPseudo(
3298 MachineInstr &MI, MachineBasicBlock *BB, unsigned BranchOp) const {
3299 // $bb:
3300 // vany_nonzero $rd, $ws
3301 // =>
3302 // $bb:
3303 // bnz.b $ws, $tbb
3304 // b $fbb
3305 // $fbb:
3306 // li $rd1, 0
3307 // b $sink
3308 // $tbb:
3309 // li $rd2, 1
3310 // $sink:
3311 // $rd = phi($rd1, $fbb, $rd2, $tbb)
3312
3313 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3314 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3315 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
3316 DebugLoc DL = MI.getDebugLoc();
3317 const BasicBlock *LLVM_BB = BB->getBasicBlock();
3318 MachineFunction::iterator It = std::next(x: MachineFunction::iterator(BB));
3319 MachineFunction *F = BB->getParent();
3320 MachineBasicBlock *FBB = F->CreateMachineBasicBlock(BB: LLVM_BB);
3321 MachineBasicBlock *TBB = F->CreateMachineBasicBlock(BB: LLVM_BB);
3322 MachineBasicBlock *Sink = F->CreateMachineBasicBlock(BB: LLVM_BB);
3323 F->insert(MBBI: It, MBB: FBB);
3324 F->insert(MBBI: It, MBB: TBB);
3325 F->insert(MBBI: It, MBB: Sink);
3326
3327 // Transfer the remainder of BB and its successor edges to Sink.
3328 Sink->splice(Where: Sink->begin(), Other: BB, From: std::next(x: MachineBasicBlock::iterator(MI)),
3329 To: BB->end());
3330 Sink->transferSuccessorsAndUpdatePHIs(FromMBB: BB);
3331
3332 // Add successors.
3333 BB->addSuccessor(Succ: FBB);
3334 BB->addSuccessor(Succ: TBB);
3335 FBB->addSuccessor(Succ: Sink);
3336 TBB->addSuccessor(Succ: Sink);
3337
3338 // Insert the real bnz.b instruction to $BB.
3339 BuildMI(BB, MIMD: DL, MCID: TII->get(Opcode: BranchOp))
3340 .addReg(RegNo: MI.getOperand(i: 1).getReg())
3341 .addMBB(MBB: TBB);
3342
3343 // Fill $FBB.
3344 Register RD1 = RegInfo.createVirtualRegister(RegClass: RC);
3345 BuildMI(BB&: *FBB, I: FBB->end(), MIMD: DL, MCID: TII->get(Opcode: Mips::ADDiu), DestReg: RD1)
3346 .addReg(RegNo: Mips::ZERO).addImm(Val: 0);
3347 BuildMI(BB&: *FBB, I: FBB->end(), MIMD: DL, MCID: TII->get(Opcode: Mips::B)).addMBB(MBB: Sink);
3348
3349 // Fill $TBB.
3350 Register RD2 = RegInfo.createVirtualRegister(RegClass: RC);
3351 BuildMI(BB&: *TBB, I: TBB->end(), MIMD: DL, MCID: TII->get(Opcode: Mips::ADDiu), DestReg: RD2)
3352 .addReg(RegNo: Mips::ZERO).addImm(Val: 1);
3353
3354 // Insert phi function to $Sink.
3355 BuildMI(BB&: *Sink, I: Sink->begin(), MIMD: DL, MCID: TII->get(Opcode: Mips::PHI),
3356 DestReg: MI.getOperand(i: 0).getReg())
3357 .addReg(RegNo: RD1)
3358 .addMBB(MBB: FBB)
3359 .addReg(RegNo: RD2)
3360 .addMBB(MBB: TBB);
3361
3362 MI.eraseFromParent(); // The pseudo instruction is gone now.
3363 return Sink;
3364}
3365
3366// Emit the COPY_FW pseudo instruction.
3367//
3368// copy_fw_pseudo $fd, $ws, n
3369// =>
3370// copy_u_w $rt, $ws, $n
3371// mtc1 $rt, $fd
3372//
3373// When n is zero, the equivalent operation can be performed with (potentially)
3374// zero instructions due to register overlaps. This optimization is never valid
3375// for lane 1 because it would require FR=0 mode which isn't supported by MSA.
3376MachineBasicBlock *
3377MipsSETargetLowering::emitCOPY_FW(MachineInstr &MI,
3378 MachineBasicBlock *BB) const {
3379 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3380 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3381 DebugLoc DL = MI.getDebugLoc();
3382 Register Fd = MI.getOperand(i: 0).getReg();
3383 Register Ws = MI.getOperand(i: 1).getReg();
3384 unsigned Lane = MI.getOperand(i: 2).getImm();
3385
3386 if (Lane == 0) {
3387 unsigned Wt = Ws;
3388 if (!Subtarget.useOddSPReg()) {
3389 // We must copy to an even-numbered MSA register so that the
3390 // single-precision sub-register is also guaranteed to be even-numbered.
3391 Wt = RegInfo.createVirtualRegister(RegClass: &Mips::MSA128WEvensRegClass);
3392
3393 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::COPY), DestReg: Wt).addReg(RegNo: Ws);
3394 }
3395
3396 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::COPY), DestReg: Fd).addReg(RegNo: Wt, Flags: {}, SubReg: Mips::sub_lo);
3397 } else {
3398 Register Wt = RegInfo.createVirtualRegister(
3399 RegClass: Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass
3400 : &Mips::MSA128WEvensRegClass);
3401
3402 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::SPLATI_W), DestReg: Wt).addReg(RegNo: Ws).addImm(Val: Lane);
3403 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::COPY), DestReg: Fd).addReg(RegNo: Wt, Flags: {}, SubReg: Mips::sub_lo);
3404 }
3405
3406 MI.eraseFromParent(); // The pseudo instruction is gone now.
3407 return BB;
3408}
3409
3410// Emit the COPY_FD pseudo instruction.
3411//
3412// copy_fd_pseudo $fd, $ws, n
3413// =>
3414// splati.d $wt, $ws, $n
3415// copy $fd, $wt:sub_64
3416//
3417// When n is zero, the equivalent operation can be performed with (potentially)
3418// zero instructions due to register overlaps. This optimization is always
3419// valid because FR=1 mode which is the only supported mode in MSA.
3420MachineBasicBlock *
3421MipsSETargetLowering::emitCOPY_FD(MachineInstr &MI,
3422 MachineBasicBlock *BB) const {
3423 assert(Subtarget.isFP64bit());
3424
3425 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3426 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3427 Register Fd = MI.getOperand(i: 0).getReg();
3428 Register Ws = MI.getOperand(i: 1).getReg();
3429 unsigned Lane = MI.getOperand(i: 2).getImm() * 2;
3430 DebugLoc DL = MI.getDebugLoc();
3431
3432 if (Lane == 0)
3433 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::COPY), DestReg: Fd).addReg(RegNo: Ws, Flags: {}, SubReg: Mips::sub_64);
3434 else {
3435 Register Wt = RegInfo.createVirtualRegister(RegClass: &Mips::MSA128DRegClass);
3436
3437 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::SPLATI_D), DestReg: Wt).addReg(RegNo: Ws).addImm(Val: 1);
3438 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::COPY), DestReg: Fd).addReg(RegNo: Wt, Flags: {}, SubReg: Mips::sub_64);
3439 }
3440
3441 MI.eraseFromParent(); // The pseudo instruction is gone now.
3442 return BB;
3443}
3444
3445// Emit the INSERT_FW pseudo instruction.
3446//
3447// insert_fw_pseudo $wd, $wd_in, $n, $fs
3448// =>
3449// subreg_to_reg $wt:sub_lo, $fs
3450// insve_w $wd[$n], $wd_in, $wt[0]
3451MachineBasicBlock *
3452MipsSETargetLowering::emitINSERT_FW(MachineInstr &MI,
3453 MachineBasicBlock *BB) const {
3454 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3455 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3456 DebugLoc DL = MI.getDebugLoc();
3457 Register Wd = MI.getOperand(i: 0).getReg();
3458 Register Wd_in = MI.getOperand(i: 1).getReg();
3459 unsigned Lane = MI.getOperand(i: 2).getImm();
3460 Register Fs = MI.getOperand(i: 3).getReg();
3461 Register Wt = RegInfo.createVirtualRegister(
3462 RegClass: Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass
3463 : &Mips::MSA128WEvensRegClass);
3464
3465 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::SUBREG_TO_REG), DestReg: Wt)
3466 .addReg(RegNo: Fs)
3467 .addImm(Val: Mips::sub_lo);
3468 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::INSVE_W), DestReg: Wd)
3469 .addReg(RegNo: Wd_in)
3470 .addImm(Val: Lane)
3471 .addReg(RegNo: Wt)
3472 .addImm(Val: 0);
3473
3474 MI.eraseFromParent(); // The pseudo instruction is gone now.
3475 return BB;
3476}
3477
3478// Emit the INSERT_FD pseudo instruction.
3479//
3480// insert_fd_pseudo $wd, $fs, n
3481// =>
3482// subreg_to_reg $wt:sub_64, $fs
3483// insve_d $wd[$n], $wd_in, $wt[0]
3484MachineBasicBlock *
3485MipsSETargetLowering::emitINSERT_FD(MachineInstr &MI,
3486 MachineBasicBlock *BB) const {
3487 assert(Subtarget.isFP64bit());
3488
3489 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3490 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3491 DebugLoc DL = MI.getDebugLoc();
3492 Register Wd = MI.getOperand(i: 0).getReg();
3493 Register Wd_in = MI.getOperand(i: 1).getReg();
3494 unsigned Lane = MI.getOperand(i: 2).getImm();
3495 Register Fs = MI.getOperand(i: 3).getReg();
3496 Register Wt = RegInfo.createVirtualRegister(RegClass: &Mips::MSA128DRegClass);
3497
3498 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::SUBREG_TO_REG), DestReg: Wt)
3499 .addReg(RegNo: Fs)
3500 .addImm(Val: Mips::sub_64);
3501 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::INSVE_D), DestReg: Wd)
3502 .addReg(RegNo: Wd_in)
3503 .addImm(Val: Lane)
3504 .addReg(RegNo: Wt)
3505 .addImm(Val: 0);
3506
3507 MI.eraseFromParent(); // The pseudo instruction is gone now.
3508 return BB;
3509}
3510
3511// Emit the INSERT_([BHWD]|F[WD])_VIDX pseudo instruction.
3512//
3513// For integer:
3514// (INSERT_([BHWD]|F[WD])_PSEUDO $wd, $wd_in, $n, $rs)
3515// =>
3516// (SLL $lanetmp1, $lane, <log2size)
3517// (SLD_B $wdtmp1, $wd_in, $wd_in, $lanetmp1)
3518// (INSERT_[BHWD], $wdtmp2, $wdtmp1, 0, $rs)
3519// (NEG $lanetmp2, $lanetmp1)
3520// (SLD_B $wd, $wdtmp2, $wdtmp2, $lanetmp2)
3521//
3522// For floating point:
3523// (INSERT_([BHWD]|F[WD])_PSEUDO $wd, $wd_in, $n, $fs)
3524// =>
3525// (SUBREG_TO_REG $wt, $fs, <subreg>)
3526// (SLL $lanetmp1, $lane, <log2size)
3527// (SLD_B $wdtmp1, $wd_in, $wd_in, $lanetmp1)
3528// (INSVE_[WD], $wdtmp2, 0, $wdtmp1, 0)
3529// (NEG $lanetmp2, $lanetmp1)
3530// (SLD_B $wd, $wdtmp2, $wdtmp2, $lanetmp2)
3531MachineBasicBlock *MipsSETargetLowering::emitINSERT_DF_VIDX(
3532 MachineInstr &MI, MachineBasicBlock *BB, unsigned EltSizeInBytes,
3533 bool IsFP) const {
3534 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3535 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3536 DebugLoc DL = MI.getDebugLoc();
3537 Register Wd = MI.getOperand(i: 0).getReg();
3538 Register SrcVecReg = MI.getOperand(i: 1).getReg();
3539 Register LaneReg = MI.getOperand(i: 2).getReg();
3540 Register SrcValReg = MI.getOperand(i: 3).getReg();
3541
3542 const TargetRegisterClass *VecRC = nullptr;
3543 // FIXME: This should be true for N32 too.
3544 const TargetRegisterClass *GPRRC =
3545 Subtarget.isABI_N64() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
3546 unsigned SubRegIdx = Subtarget.isABI_N64() ? Mips::sub_32 : 0;
3547 unsigned ShiftOp = Subtarget.isABI_N64() ? Mips::DSLL : Mips::SLL;
3548 unsigned EltLog2Size;
3549 unsigned InsertOp = 0;
3550 unsigned InsveOp = 0;
3551 switch (EltSizeInBytes) {
3552 default:
3553 llvm_unreachable("Unexpected size");
3554 case 1:
3555 EltLog2Size = 0;
3556 InsertOp = Mips::INSERT_B;
3557 InsveOp = Mips::INSVE_B;
3558 VecRC = &Mips::MSA128BRegClass;
3559 break;
3560 case 2:
3561 EltLog2Size = 1;
3562 InsertOp = Mips::INSERT_H;
3563 InsveOp = Mips::INSVE_H;
3564 VecRC = &Mips::MSA128HRegClass;
3565 break;
3566 case 4:
3567 EltLog2Size = 2;
3568 InsertOp = Mips::INSERT_W;
3569 InsveOp = Mips::INSVE_W;
3570 VecRC = &Mips::MSA128WRegClass;
3571 break;
3572 case 8:
3573 EltLog2Size = 3;
3574 InsertOp = Mips::INSERT_D;
3575 InsveOp = Mips::INSVE_D;
3576 VecRC = &Mips::MSA128DRegClass;
3577 break;
3578 }
3579
3580 if (IsFP) {
3581 Register Wt = RegInfo.createVirtualRegister(RegClass: VecRC);
3582 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::SUBREG_TO_REG), DestReg: Wt)
3583 .addReg(RegNo: SrcValReg)
3584 .addImm(Val: EltSizeInBytes == 8 ? Mips::sub_64 : Mips::sub_lo);
3585 SrcValReg = Wt;
3586 }
3587
3588 // Convert the lane index into a byte index
3589 if (EltSizeInBytes != 1) {
3590 Register LaneTmp1 = RegInfo.createVirtualRegister(RegClass: GPRRC);
3591 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: ShiftOp), DestReg: LaneTmp1)
3592 .addReg(RegNo: LaneReg)
3593 .addImm(Val: EltLog2Size);
3594 LaneReg = LaneTmp1;
3595 }
3596
3597 // Rotate bytes around so that the desired lane is element zero
3598 Register WdTmp1 = RegInfo.createVirtualRegister(RegClass: VecRC);
3599 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::SLD_B), DestReg: WdTmp1)
3600 .addReg(RegNo: SrcVecReg)
3601 .addReg(RegNo: SrcVecReg)
3602 .addReg(RegNo: LaneReg, Flags: {}, SubReg: SubRegIdx);
3603
3604 Register WdTmp2 = RegInfo.createVirtualRegister(RegClass: VecRC);
3605 if (IsFP) {
3606 // Use insve.df to insert to element zero
3607 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: InsveOp), DestReg: WdTmp2)
3608 .addReg(RegNo: WdTmp1)
3609 .addImm(Val: 0)
3610 .addReg(RegNo: SrcValReg)
3611 .addImm(Val: 0);
3612 } else {
3613 // Use insert.df to insert to element zero
3614 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: InsertOp), DestReg: WdTmp2)
3615 .addReg(RegNo: WdTmp1)
3616 .addReg(RegNo: SrcValReg)
3617 .addImm(Val: 0);
3618 }
3619
3620 // Rotate elements the rest of the way for a full rotation.
3621 // sld.df inteprets $rt modulo the number of columns so we only need to negate
3622 // the lane index to do this.
3623 Register LaneTmp2 = RegInfo.createVirtualRegister(RegClass: GPRRC);
3624 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Subtarget.isABI_N64() ? Mips::DSUB : Mips::SUB),
3625 DestReg: LaneTmp2)
3626 .addReg(RegNo: Subtarget.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO)
3627 .addReg(RegNo: LaneReg);
3628 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::SLD_B), DestReg: Wd)
3629 .addReg(RegNo: WdTmp2)
3630 .addReg(RegNo: WdTmp2)
3631 .addReg(RegNo: LaneTmp2, Flags: {}, SubReg: SubRegIdx);
3632
3633 MI.eraseFromParent(); // The pseudo instruction is gone now.
3634 return BB;
3635}
3636
3637// Emit the FILL_FW pseudo instruction.
3638//
3639// fill_fw_pseudo $wd, $fs
3640// =>
3641// implicit_def $wt1
3642// insert_subreg $wt2:subreg_lo, $wt1, $fs
3643// splati.w $wd, $wt2[0]
3644MachineBasicBlock *
3645MipsSETargetLowering::emitFILL_FW(MachineInstr &MI,
3646 MachineBasicBlock *BB) const {
3647 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3648 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3649 DebugLoc DL = MI.getDebugLoc();
3650 Register Wd = MI.getOperand(i: 0).getReg();
3651 Register Fs = MI.getOperand(i: 1).getReg();
3652 Register Wt1 = RegInfo.createVirtualRegister(
3653 RegClass: Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass
3654 : &Mips::MSA128WEvensRegClass);
3655 Register Wt2 = RegInfo.createVirtualRegister(
3656 RegClass: Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass
3657 : &Mips::MSA128WEvensRegClass);
3658
3659 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::IMPLICIT_DEF), DestReg: Wt1);
3660 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::INSERT_SUBREG), DestReg: Wt2)
3661 .addReg(RegNo: Wt1)
3662 .addReg(RegNo: Fs)
3663 .addImm(Val: Mips::sub_lo);
3664 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::SPLATI_W), DestReg: Wd).addReg(RegNo: Wt2).addImm(Val: 0);
3665
3666 MI.eraseFromParent(); // The pseudo instruction is gone now.
3667 return BB;
3668}
3669
3670// Emit the FILL_FD pseudo instruction.
3671//
3672// fill_fd_pseudo $wd, $fs
3673// =>
3674// implicit_def $wt1
3675// insert_subreg $wt2:subreg_64, $wt1, $fs
3676// splati.d $wd, $wt2[0]
3677MachineBasicBlock *
3678MipsSETargetLowering::emitFILL_FD(MachineInstr &MI,
3679 MachineBasicBlock *BB) const {
3680 assert(Subtarget.isFP64bit());
3681
3682 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3683 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3684 DebugLoc DL = MI.getDebugLoc();
3685 Register Wd = MI.getOperand(i: 0).getReg();
3686 Register Fs = MI.getOperand(i: 1).getReg();
3687 Register Wt1 = RegInfo.createVirtualRegister(RegClass: &Mips::MSA128DRegClass);
3688 Register Wt2 = RegInfo.createVirtualRegister(RegClass: &Mips::MSA128DRegClass);
3689
3690 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::IMPLICIT_DEF), DestReg: Wt1);
3691 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::INSERT_SUBREG), DestReg: Wt2)
3692 .addReg(RegNo: Wt1)
3693 .addReg(RegNo: Fs)
3694 .addImm(Val: Mips::sub_64);
3695 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::SPLATI_D), DestReg: Wd).addReg(RegNo: Wt2).addImm(Val: 0);
3696
3697 MI.eraseFromParent(); // The pseudo instruction is gone now.
3698 return BB;
3699}
3700
3701// Emit the FEXP2_W_1 pseudo instructions.
3702//
3703// fexp2_w_1_pseudo $wd, $wt
3704// =>
3705// ldi.w $ws, 1
3706// fexp2.w $wd, $ws, $wt
3707MachineBasicBlock *
3708MipsSETargetLowering::emitFEXP2_W_1(MachineInstr &MI,
3709 MachineBasicBlock *BB) const {
3710 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3711 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3712 const TargetRegisterClass *RC = &Mips::MSA128WRegClass;
3713 Register Ws1 = RegInfo.createVirtualRegister(RegClass: RC);
3714 Register Ws2 = RegInfo.createVirtualRegister(RegClass: RC);
3715 DebugLoc DL = MI.getDebugLoc();
3716
3717 // Splat 1.0 into a vector
3718 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::LDI_W), DestReg: Ws1).addImm(Val: 1);
3719 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::FFINT_U_W), DestReg: Ws2).addReg(RegNo: Ws1);
3720
3721 // Emit 1.0 * fexp2(Wt)
3722 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::FEXP2_W), DestReg: MI.getOperand(i: 0).getReg())
3723 .addReg(RegNo: Ws2)
3724 .addReg(RegNo: MI.getOperand(i: 1).getReg());
3725
3726 MI.eraseFromParent(); // The pseudo instruction is gone now.
3727 return BB;
3728}
3729
3730// Emit the FEXP2_D_1 pseudo instructions.
3731//
3732// fexp2_d_1_pseudo $wd, $wt
3733// =>
3734// ldi.d $ws, 1
3735// fexp2.d $wd, $ws, $wt
3736MachineBasicBlock *
3737MipsSETargetLowering::emitFEXP2_D_1(MachineInstr &MI,
3738 MachineBasicBlock *BB) const {
3739 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3740 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
3741 const TargetRegisterClass *RC = &Mips::MSA128DRegClass;
3742 Register Ws1 = RegInfo.createVirtualRegister(RegClass: RC);
3743 Register Ws2 = RegInfo.createVirtualRegister(RegClass: RC);
3744 DebugLoc DL = MI.getDebugLoc();
3745
3746 // Splat 1.0 into a vector
3747 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::LDI_D), DestReg: Ws1).addImm(Val: 1);
3748 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::FFINT_U_D), DestReg: Ws2).addReg(RegNo: Ws1);
3749
3750 // Emit 1.0 * fexp2(Wt)
3751 BuildMI(BB&: *BB, I&: MI, MIMD: DL, MCID: TII->get(Opcode: Mips::FEXP2_D), DestReg: MI.getOperand(i: 0).getReg())
3752 .addReg(RegNo: Ws2)
3753 .addReg(RegNo: MI.getOperand(i: 1).getReg());
3754
3755 MI.eraseFromParent(); // The pseudo instruction is gone now.
3756 return BB;
3757}
3758