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