1 //===- MipsLegalizerInfo.cpp ------------------------------------*- C++ -*-===//
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 /// \file
9 /// This file implements the targeting of the Machinelegalizer class for Mips.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
12
13 #include "MipsLegalizerInfo.h"
14 #include "MipsTargetMachine.h"
15 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
16 #include "llvm/IR/IntrinsicsMips.h"
17
18 using namespace llvm;
19
20 struct TypesAndMemOps {
21 LLT ValTy;
22 LLT PtrTy;
23 unsigned MemSize;
24 bool MustBeNaturallyAligned;
25 };
26
27 static bool
CheckTy0Ty1MemSizeAlign(const LegalityQuery & Query,std::initializer_list<TypesAndMemOps> SupportedValues)28 CheckTy0Ty1MemSizeAlign(const LegalityQuery &Query,
29 std::initializer_list<TypesAndMemOps> SupportedValues) {
30 for (auto &Val : SupportedValues) {
31 if (Val.ValTy != Query.Types[0])
32 continue;
33 if (Val.PtrTy != Query.Types[1])
34 continue;
35 if (Val.MemSize != Query.MMODescrs[0].SizeInBits)
36 continue;
37 if (Val.MustBeNaturallyAligned &&
38 Query.MMODescrs[0].SizeInBits % Query.MMODescrs[0].AlignInBits != 0)
39 continue;
40 return true;
41 }
42 return false;
43 }
44
CheckTyN(unsigned N,const LegalityQuery & Query,std::initializer_list<LLT> SupportedValues)45 static bool CheckTyN(unsigned N, const LegalityQuery &Query,
46 std::initializer_list<LLT> SupportedValues) {
47 for (auto &Val : SupportedValues)
48 if (Val == Query.Types[N])
49 return true;
50 return false;
51 }
52
MipsLegalizerInfo(const MipsSubtarget & ST)53 MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
54 using namespace TargetOpcode;
55
56 const LLT s1 = LLT::scalar(1);
57 const LLT s32 = LLT::scalar(32);
58 const LLT s64 = LLT::scalar(64);
59 const LLT v16s8 = LLT::vector(16, 8);
60 const LLT v8s16 = LLT::vector(8, 16);
61 const LLT v4s32 = LLT::vector(4, 32);
62 const LLT v2s64 = LLT::vector(2, 64);
63 const LLT p0 = LLT::pointer(0, 32);
64
65 getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL})
66 .legalIf([=, &ST](const LegalityQuery &Query) {
67 if (CheckTyN(0, Query, {s32}))
68 return true;
69 if (ST.hasMSA() && CheckTyN(0, Query, {v16s8, v8s16, v4s32, v2s64}))
70 return true;
71 return false;
72 })
73 .clampScalar(0, s32, s32);
74
75 getActionDefinitionsBuilder({G_UADDO, G_UADDE, G_USUBO, G_USUBE, G_UMULO})
76 .lowerFor({{s32, s1}});
77
78 getActionDefinitionsBuilder(G_UMULH)
79 .legalFor({s32})
80 .maxScalar(0, s32);
81
82 getActionDefinitionsBuilder({G_LOAD, G_STORE})
83 .legalIf([=, &ST](const LegalityQuery &Query) {
84 if (CheckTy0Ty1MemSizeAlign(Query, {{s32, p0, 8, ST.hasMips32r6()},
85 {s32, p0, 16, ST.hasMips32r6()},
86 {s32, p0, 32, ST.hasMips32r6()},
87 {p0, p0, 32, ST.hasMips32r6()},
88 {s64, p0, 64, ST.hasMips32r6()}}))
89 return true;
90 if (ST.hasMSA() &&
91 CheckTy0Ty1MemSizeAlign(Query, {{v16s8, p0, 128, false},
92 {v8s16, p0, 128, false},
93 {v4s32, p0, 128, false},
94 {v2s64, p0, 128, false}}))
95 return true;
96 return false;
97 })
98 .minScalar(0, s32);
99
100 getActionDefinitionsBuilder(G_IMPLICIT_DEF)
101 .legalFor({s32, s64});
102
103 getActionDefinitionsBuilder(G_UNMERGE_VALUES)
104 .legalFor({{s32, s64}});
105
106 getActionDefinitionsBuilder(G_MERGE_VALUES)
107 .legalFor({{s64, s32}});
108
109 getActionDefinitionsBuilder({G_ZEXTLOAD, G_SEXTLOAD})
110 .legalForTypesWithMemDesc({{s32, p0, 8, 8},
111 {s32, p0, 16, 8}})
112 .clampScalar(0, s32, s32);
113
114 getActionDefinitionsBuilder({G_ZEXT, G_SEXT})
115 .legalIf([](const LegalityQuery &Query) { return false; })
116 .maxScalar(0, s32);
117
118 getActionDefinitionsBuilder(G_TRUNC)
119 .legalIf([](const LegalityQuery &Query) { return false; })
120 .maxScalar(1, s32);
121
122 getActionDefinitionsBuilder(G_SELECT)
123 .legalForCartesianProduct({p0, s32, s64}, {s32})
124 .minScalar(0, s32)
125 .minScalar(1, s32);
126
127 getActionDefinitionsBuilder(G_BRCOND)
128 .legalFor({s32})
129 .minScalar(0, s32);
130
131 getActionDefinitionsBuilder(G_BRJT)
132 .legalFor({{p0, s32}});
133
134 getActionDefinitionsBuilder(G_BRINDIRECT)
135 .legalFor({p0});
136
137 getActionDefinitionsBuilder(G_PHI)
138 .legalFor({p0, s32, s64})
139 .minScalar(0, s32);
140
141 getActionDefinitionsBuilder({G_AND, G_OR, G_XOR})
142 .legalFor({s32})
143 .clampScalar(0, s32, s32);
144
145 getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UDIV, G_UREM})
146 .legalIf([=, &ST](const LegalityQuery &Query) {
147 if (CheckTyN(0, Query, {s32}))
148 return true;
149 if (ST.hasMSA() && CheckTyN(0, Query, {v16s8, v8s16, v4s32, v2s64}))
150 return true;
151 return false;
152 })
153 .minScalar(0, s32)
154 .libcallFor({s64});
155
156 getActionDefinitionsBuilder({G_SHL, G_ASHR, G_LSHR})
157 .legalFor({{s32, s32}})
158 .clampScalar(1, s32, s32)
159 .clampScalar(0, s32, s32);
160
161 getActionDefinitionsBuilder(G_ICMP)
162 .legalForCartesianProduct({s32}, {s32, p0})
163 .clampScalar(1, s32, s32)
164 .minScalar(0, s32);
165
166 getActionDefinitionsBuilder(G_CONSTANT)
167 .legalFor({s32})
168 .clampScalar(0, s32, s32);
169
170 getActionDefinitionsBuilder({G_PTR_ADD, G_INTTOPTR})
171 .legalFor({{p0, s32}});
172
173 getActionDefinitionsBuilder(G_PTRTOINT)
174 .legalFor({{s32, p0}});
175
176 getActionDefinitionsBuilder(G_FRAME_INDEX)
177 .legalFor({p0});
178
179 getActionDefinitionsBuilder({G_GLOBAL_VALUE, G_JUMP_TABLE})
180 .legalFor({p0});
181
182 getActionDefinitionsBuilder(G_DYN_STACKALLOC)
183 .lowerFor({{p0, s32}});
184
185 getActionDefinitionsBuilder(G_VASTART)
186 .legalFor({p0});
187
188 getActionDefinitionsBuilder(G_BSWAP)
189 .legalIf([=, &ST](const LegalityQuery &Query) {
190 if (ST.hasMips32r2() && CheckTyN(0, Query, {s32}))
191 return true;
192 return false;
193 })
194 .lowerIf([=, &ST](const LegalityQuery &Query) {
195 if (!ST.hasMips32r2() && CheckTyN(0, Query, {s32}))
196 return true;
197 return false;
198 })
199 .maxScalar(0, s32);
200
201 getActionDefinitionsBuilder(G_BITREVERSE)
202 .lowerFor({s32})
203 .maxScalar(0, s32);
204
205 // FP instructions
206 getActionDefinitionsBuilder(G_FCONSTANT)
207 .legalFor({s32, s64});
208
209 getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FABS, G_FSQRT})
210 .legalIf([=, &ST](const LegalityQuery &Query) {
211 if (CheckTyN(0, Query, {s32, s64}))
212 return true;
213 if (ST.hasMSA() && CheckTyN(0, Query, {v16s8, v8s16, v4s32, v2s64}))
214 return true;
215 return false;
216 });
217
218 getActionDefinitionsBuilder(G_FCMP)
219 .legalFor({{s32, s32}, {s32, s64}})
220 .minScalar(0, s32);
221
222 getActionDefinitionsBuilder({G_FCEIL, G_FFLOOR})
223 .libcallFor({s32, s64});
224
225 getActionDefinitionsBuilder(G_FPEXT)
226 .legalFor({{s64, s32}});
227
228 getActionDefinitionsBuilder(G_FPTRUNC)
229 .legalFor({{s32, s64}});
230
231 // FP to int conversion instructions
232 getActionDefinitionsBuilder(G_FPTOSI)
233 .legalForCartesianProduct({s32}, {s64, s32})
234 .libcallForCartesianProduct({s64}, {s64, s32})
235 .minScalar(0, s32);
236
237 getActionDefinitionsBuilder(G_FPTOUI)
238 .libcallForCartesianProduct({s64}, {s64, s32})
239 .lowerForCartesianProduct({s32}, {s64, s32})
240 .minScalar(0, s32);
241
242 // Int to FP conversion instructions
243 getActionDefinitionsBuilder(G_SITOFP)
244 .legalForCartesianProduct({s64, s32}, {s32})
245 .libcallForCartesianProduct({s64, s32}, {s64})
246 .minScalar(1, s32);
247
248 getActionDefinitionsBuilder(G_UITOFP)
249 .libcallForCartesianProduct({s64, s32}, {s64})
250 .customForCartesianProduct({s64, s32}, {s32})
251 .minScalar(1, s32);
252
253 getActionDefinitionsBuilder(G_SEXT_INREG).lower();
254
255 computeTables();
256 verify(*ST.getInstrInfo());
257 }
258
legalizeCustom(MachineInstr & MI,MachineRegisterInfo & MRI,MachineIRBuilder & MIRBuilder,GISelChangeObserver & Observer) const259 bool MipsLegalizerInfo::legalizeCustom(MachineInstr &MI,
260 MachineRegisterInfo &MRI,
261 MachineIRBuilder &MIRBuilder,
262 GISelChangeObserver &Observer) const {
263
264 using namespace TargetOpcode;
265
266 MIRBuilder.setInstr(MI);
267 const MipsSubtarget &STI =
268 static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget());
269 const LLT s32 = LLT::scalar(32);
270 const LLT s64 = LLT::scalar(64);
271
272 switch (MI.getOpcode()) {
273 case G_UITOFP: {
274 Register Dst = MI.getOperand(0).getReg();
275 Register Src = MI.getOperand(1).getReg();
276 LLT DstTy = MRI.getType(Dst);
277 LLT SrcTy = MRI.getType(Src);
278
279 if (SrcTy != s32)
280 return false;
281 if (DstTy != s32 && DstTy != s64)
282 return false;
283
284 // Let 0xABCDEFGH be given unsigned in MI.getOperand(1). First let's convert
285 // unsigned to double. Mantissa has 52 bits so we use following trick:
286 // First make floating point bit mask 0x43300000ABCDEFGH.
287 // Mask represents 2^52 * 0x1.00000ABCDEFGH i.e. 0x100000ABCDEFGH.0 .
288 // Next, subtract 2^52 * 0x1.0000000000000 i.e. 0x10000000000000.0 from it.
289 // Done. Trunc double to float if needed.
290
291 MachineInstrBuilder Bitcast = MIRBuilder.buildInstr(
292 STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64, {s64},
293 {Src, MIRBuilder.buildConstant(s32, UINT32_C(0x43300000))});
294 Bitcast.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(),
295 *STI.getRegBankInfo());
296
297 MachineInstrBuilder TwoP52FP = MIRBuilder.buildFConstant(
298 s64, BitsToDouble(UINT64_C(0x4330000000000000)));
299
300 if (DstTy == s64)
301 MIRBuilder.buildFSub(Dst, Bitcast, TwoP52FP);
302 else {
303 MachineInstrBuilder ResF64 = MIRBuilder.buildFSub(s64, Bitcast, TwoP52FP);
304 MIRBuilder.buildFPTrunc(Dst, ResF64);
305 }
306
307 MI.eraseFromParent();
308 break;
309 }
310 default:
311 return false;
312 }
313
314 return true;
315 }
316
SelectMSA3OpIntrinsic(MachineInstr & MI,unsigned Opcode,MachineIRBuilder & MIRBuilder,const MipsSubtarget & ST)317 static bool SelectMSA3OpIntrinsic(MachineInstr &MI, unsigned Opcode,
318 MachineIRBuilder &MIRBuilder,
319 const MipsSubtarget &ST) {
320 assert(ST.hasMSA() && "MSA intrinsic not supported on target without MSA.");
321 if (!MIRBuilder.buildInstr(Opcode)
322 .add(MI.getOperand(0))
323 .add(MI.getOperand(2))
324 .add(MI.getOperand(3))
325 .constrainAllUses(MIRBuilder.getTII(), *ST.getRegisterInfo(),
326 *ST.getRegBankInfo()))
327 return false;
328 MI.eraseFromParent();
329 return true;
330 }
331
MSA3OpIntrinsicToGeneric(MachineInstr & MI,unsigned Opcode,MachineIRBuilder & MIRBuilder,const MipsSubtarget & ST)332 static bool MSA3OpIntrinsicToGeneric(MachineInstr &MI, unsigned Opcode,
333 MachineIRBuilder &MIRBuilder,
334 const MipsSubtarget &ST) {
335 assert(ST.hasMSA() && "MSA intrinsic not supported on target without MSA.");
336 MIRBuilder.buildInstr(Opcode)
337 .add(MI.getOperand(0))
338 .add(MI.getOperand(2))
339 .add(MI.getOperand(3));
340 MI.eraseFromParent();
341 return true;
342 }
343
MSA2OpIntrinsicToGeneric(MachineInstr & MI,unsigned Opcode,MachineIRBuilder & MIRBuilder,const MipsSubtarget & ST)344 static bool MSA2OpIntrinsicToGeneric(MachineInstr &MI, unsigned Opcode,
345 MachineIRBuilder &MIRBuilder,
346 const MipsSubtarget &ST) {
347 assert(ST.hasMSA() && "MSA intrinsic not supported on target without MSA.");
348 MIRBuilder.buildInstr(Opcode)
349 .add(MI.getOperand(0))
350 .add(MI.getOperand(2));
351 MI.eraseFromParent();
352 return true;
353 }
354
legalizeIntrinsic(MachineInstr & MI,MachineRegisterInfo & MRI,MachineIRBuilder & MIRBuilder) const355 bool MipsLegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
356 MachineRegisterInfo &MRI,
357 MachineIRBuilder &MIRBuilder) const {
358 const MipsSubtarget &ST =
359 static_cast<const MipsSubtarget &>(MI.getMF()->getSubtarget());
360 const MipsInstrInfo &TII = *ST.getInstrInfo();
361 const MipsRegisterInfo &TRI = *ST.getRegisterInfo();
362 const RegisterBankInfo &RBI = *ST.getRegBankInfo();
363 MIRBuilder.setInstr(MI);
364
365 switch (MI.getIntrinsicID()) {
366 case Intrinsic::memcpy:
367 case Intrinsic::memset:
368 case Intrinsic::memmove:
369 if (createMemLibcall(MIRBuilder, MRI, MI) ==
370 LegalizerHelper::UnableToLegalize)
371 return false;
372 MI.eraseFromParent();
373 return true;
374 case Intrinsic::trap: {
375 MachineInstr *Trap = MIRBuilder.buildInstr(Mips::TRAP);
376 MI.eraseFromParent();
377 return constrainSelectedInstRegOperands(*Trap, TII, TRI, RBI);
378 }
379 case Intrinsic::vacopy: {
380 Register Tmp = MRI.createGenericVirtualRegister(LLT::pointer(0, 32));
381 MachinePointerInfo MPO;
382 MIRBuilder.buildLoad(Tmp, MI.getOperand(2),
383 *MI.getMF()->getMachineMemOperand(
384 MPO, MachineMemOperand::MOLoad, 4, 4));
385 MIRBuilder.buildStore(Tmp, MI.getOperand(1),
386 *MI.getMF()->getMachineMemOperand(
387 MPO, MachineMemOperand::MOStore, 4, 4));
388 MI.eraseFromParent();
389 return true;
390 }
391 case Intrinsic::mips_addv_b:
392 case Intrinsic::mips_addv_h:
393 case Intrinsic::mips_addv_w:
394 case Intrinsic::mips_addv_d:
395 return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_ADD, MIRBuilder, ST);
396 case Intrinsic::mips_addvi_b:
397 return SelectMSA3OpIntrinsic(MI, Mips::ADDVI_B, MIRBuilder, ST);
398 case Intrinsic::mips_addvi_h:
399 return SelectMSA3OpIntrinsic(MI, Mips::ADDVI_H, MIRBuilder, ST);
400 case Intrinsic::mips_addvi_w:
401 return SelectMSA3OpIntrinsic(MI, Mips::ADDVI_W, MIRBuilder, ST);
402 case Intrinsic::mips_addvi_d:
403 return SelectMSA3OpIntrinsic(MI, Mips::ADDVI_D, MIRBuilder, ST);
404 case Intrinsic::mips_subv_b:
405 case Intrinsic::mips_subv_h:
406 case Intrinsic::mips_subv_w:
407 case Intrinsic::mips_subv_d:
408 return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_SUB, MIRBuilder, ST);
409 case Intrinsic::mips_subvi_b:
410 return SelectMSA3OpIntrinsic(MI, Mips::SUBVI_B, MIRBuilder, ST);
411 case Intrinsic::mips_subvi_h:
412 return SelectMSA3OpIntrinsic(MI, Mips::SUBVI_H, MIRBuilder, ST);
413 case Intrinsic::mips_subvi_w:
414 return SelectMSA3OpIntrinsic(MI, Mips::SUBVI_W, MIRBuilder, ST);
415 case Intrinsic::mips_subvi_d:
416 return SelectMSA3OpIntrinsic(MI, Mips::SUBVI_D, MIRBuilder, ST);
417 case Intrinsic::mips_mulv_b:
418 case Intrinsic::mips_mulv_h:
419 case Intrinsic::mips_mulv_w:
420 case Intrinsic::mips_mulv_d:
421 return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_MUL, MIRBuilder, ST);
422 case Intrinsic::mips_div_s_b:
423 case Intrinsic::mips_div_s_h:
424 case Intrinsic::mips_div_s_w:
425 case Intrinsic::mips_div_s_d:
426 return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_SDIV, MIRBuilder, ST);
427 case Intrinsic::mips_mod_s_b:
428 case Intrinsic::mips_mod_s_h:
429 case Intrinsic::mips_mod_s_w:
430 case Intrinsic::mips_mod_s_d:
431 return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_SREM, MIRBuilder, ST);
432 case Intrinsic::mips_div_u_b:
433 case Intrinsic::mips_div_u_h:
434 case Intrinsic::mips_div_u_w:
435 case Intrinsic::mips_div_u_d:
436 return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_UDIV, MIRBuilder, ST);
437 case Intrinsic::mips_mod_u_b:
438 case Intrinsic::mips_mod_u_h:
439 case Intrinsic::mips_mod_u_w:
440 case Intrinsic::mips_mod_u_d:
441 return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_UREM, MIRBuilder, ST);
442 case Intrinsic::mips_fadd_w:
443 case Intrinsic::mips_fadd_d:
444 return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_FADD, MIRBuilder, ST);
445 case Intrinsic::mips_fsub_w:
446 case Intrinsic::mips_fsub_d:
447 return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_FSUB, MIRBuilder, ST);
448 case Intrinsic::mips_fmul_w:
449 case Intrinsic::mips_fmul_d:
450 return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_FMUL, MIRBuilder, ST);
451 case Intrinsic::mips_fdiv_w:
452 case Intrinsic::mips_fdiv_d:
453 return MSA3OpIntrinsicToGeneric(MI, TargetOpcode::G_FDIV, MIRBuilder, ST);
454 case Intrinsic::mips_fmax_a_w:
455 return SelectMSA3OpIntrinsic(MI, Mips::FMAX_A_W, MIRBuilder, ST);
456 case Intrinsic::mips_fmax_a_d:
457 return SelectMSA3OpIntrinsic(MI, Mips::FMAX_A_D, MIRBuilder, ST);
458 case Intrinsic::mips_fsqrt_w:
459 return MSA2OpIntrinsicToGeneric(MI, TargetOpcode::G_FSQRT, MIRBuilder, ST);
460 case Intrinsic::mips_fsqrt_d:
461 return MSA2OpIntrinsicToGeneric(MI, TargetOpcode::G_FSQRT, MIRBuilder, ST);
462 default:
463 break;
464 }
465 return true;
466 }
467