LLVM 19.0.0git
Mips16ISelLowering.cpp
Go to the documentation of this file.
1//===-- Mips16ISelLowering.h - Mips16 DAG Lowering Interface ----*- 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//
9// Subclass of MipsTargetLowering specialized for mips16.
10//
11//===----------------------------------------------------------------------===//
12#include "Mips16ISelLowering.h"
14#include "Mips16HardFloatInfo.h"
15#include "MipsMachineFunction.h"
16#include "MipsRegisterInfo.h"
17#include "MipsTargetMachine.h"
21
22using namespace llvm;
23
24#define DEBUG_TYPE "mips-lower"
25
27 "mips16-dont-expand-cond-pseudo",
28 cl::init(false),
29 cl::desc("Don't expand conditional move related "
30 "pseudos for Mips 16"),
32
33namespace {
34struct Mips16Libcall {
35 RTLIB::Libcall Libcall;
36 const char *Name;
37
38 bool operator<(const Mips16Libcall &RHS) const {
39 return std::strcmp(Name, RHS.Name) < 0;
40 }
41};
42
43struct Mips16IntrinsicHelperType{
44 const char* Name;
45 const char* Helper;
46
47 bool operator<(const Mips16IntrinsicHelperType &RHS) const {
48 return std::strcmp(Name, RHS.Name) < 0;
49 }
50 bool operator==(const Mips16IntrinsicHelperType &RHS) const {
51 return std::strcmp(Name, RHS.Name) == 0;
52 }
53};
54}
55
56// Libcalls for which no helper is generated. Sorted by name for binary search.
57static const Mips16Libcall HardFloatLibCalls[] = {
58 { RTLIB::ADD_F64, "__mips16_adddf3" },
59 { RTLIB::ADD_F32, "__mips16_addsf3" },
60 { RTLIB::DIV_F64, "__mips16_divdf3" },
61 { RTLIB::DIV_F32, "__mips16_divsf3" },
62 { RTLIB::OEQ_F64, "__mips16_eqdf2" },
63 { RTLIB::OEQ_F32, "__mips16_eqsf2" },
64 { RTLIB::FPEXT_F32_F64, "__mips16_extendsfdf2" },
65 { RTLIB::FPTOSINT_F64_I32, "__mips16_fix_truncdfsi" },
66 { RTLIB::FPTOSINT_F32_I32, "__mips16_fix_truncsfsi" },
67 { RTLIB::SINTTOFP_I32_F64, "__mips16_floatsidf" },
68 { RTLIB::SINTTOFP_I32_F32, "__mips16_floatsisf" },
69 { RTLIB::UINTTOFP_I32_F64, "__mips16_floatunsidf" },
70 { RTLIB::UINTTOFP_I32_F32, "__mips16_floatunsisf" },
71 { RTLIB::OGE_F64, "__mips16_gedf2" },
72 { RTLIB::OGE_F32, "__mips16_gesf2" },
73 { RTLIB::OGT_F64, "__mips16_gtdf2" },
74 { RTLIB::OGT_F32, "__mips16_gtsf2" },
75 { RTLIB::OLE_F64, "__mips16_ledf2" },
76 { RTLIB::OLE_F32, "__mips16_lesf2" },
77 { RTLIB::OLT_F64, "__mips16_ltdf2" },
78 { RTLIB::OLT_F32, "__mips16_ltsf2" },
79 { RTLIB::MUL_F64, "__mips16_muldf3" },
80 { RTLIB::MUL_F32, "__mips16_mulsf3" },
81 { RTLIB::UNE_F64, "__mips16_nedf2" },
82 { RTLIB::UNE_F32, "__mips16_nesf2" },
83 { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_dc" }, // No associated libcall.
84 { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_df" }, // No associated libcall.
85 { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sc" }, // No associated libcall.
86 { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sf" }, // No associated libcall.
87 { RTLIB::SUB_F64, "__mips16_subdf3" },
88 { RTLIB::SUB_F32, "__mips16_subsf3" },
89 { RTLIB::FPROUND_F64_F32, "__mips16_truncdfsf2" },
90 { RTLIB::UO_F64, "__mips16_unorddf2" },
91 { RTLIB::UO_F32, "__mips16_unordsf2" }
92};
93
94static const Mips16IntrinsicHelperType Mips16IntrinsicHelper[] = {
95 {"__fixunsdfsi", "__mips16_call_stub_2" },
96 {"ceil", "__mips16_call_stub_df_2"},
97 {"ceilf", "__mips16_call_stub_sf_1"},
98 {"copysign", "__mips16_call_stub_df_10"},
99 {"copysignf", "__mips16_call_stub_sf_5"},
100 {"cos", "__mips16_call_stub_df_2"},
101 {"cosf", "__mips16_call_stub_sf_1"},
102 {"exp2", "__mips16_call_stub_df_2"},
103 {"exp2f", "__mips16_call_stub_sf_1"},
104 {"floor", "__mips16_call_stub_df_2"},
105 {"floorf", "__mips16_call_stub_sf_1"},
106 {"log2", "__mips16_call_stub_df_2"},
107 {"log2f", "__mips16_call_stub_sf_1"},
108 {"nearbyint", "__mips16_call_stub_df_2"},
109 {"nearbyintf", "__mips16_call_stub_sf_1"},
110 {"rint", "__mips16_call_stub_df_2"},
111 {"rintf", "__mips16_call_stub_sf_1"},
112 {"sin", "__mips16_call_stub_df_2"},
113 {"sinf", "__mips16_call_stub_sf_1"},
114 {"sqrt", "__mips16_call_stub_df_2"},
115 {"sqrtf", "__mips16_call_stub_sf_1"},
116 {"trunc", "__mips16_call_stub_df_2"},
117 {"truncf", "__mips16_call_stub_sf_1"},
118};
119
121 const MipsSubtarget &STI)
122 : MipsTargetLowering(TM, STI) {
123
124 // Set up the register classes
125 addRegisterClass(MVT::i32, &Mips::CPU16RegsRegClass);
126
127 if (!Subtarget.useSoftFloat())
128 setMips16HardFloatLibCalls();
129
143
148
150}
151
152const MipsTargetLowering *
154 const MipsSubtarget &STI) {
155 return new Mips16TargetLowering(TM, STI);
156}
157
159 EVT VT, unsigned, Align, MachineMemOperand::Flags, unsigned *Fast) const {
160 return false;
161}
162
165 MachineBasicBlock *BB) const {
166 switch (MI.getOpcode()) {
167 default:
169 case Mips::SelBeqZ:
170 return emitSel16(Mips::BeqzRxImm16, MI, BB);
171 case Mips::SelBneZ:
172 return emitSel16(Mips::BnezRxImm16, MI, BB);
173 case Mips::SelTBteqZCmpi:
174 return emitSeliT16(Mips::Bteqz16, Mips::CmpiRxImmX16, MI, BB);
175 case Mips::SelTBteqZSlti:
176 return emitSeliT16(Mips::Bteqz16, Mips::SltiRxImmX16, MI, BB);
177 case Mips::SelTBteqZSltiu:
178 return emitSeliT16(Mips::Bteqz16, Mips::SltiuRxImmX16, MI, BB);
179 case Mips::SelTBtneZCmpi:
180 return emitSeliT16(Mips::Btnez16, Mips::CmpiRxImmX16, MI, BB);
181 case Mips::SelTBtneZSlti:
182 return emitSeliT16(Mips::Btnez16, Mips::SltiRxImmX16, MI, BB);
183 case Mips::SelTBtneZSltiu:
184 return emitSeliT16(Mips::Btnez16, Mips::SltiuRxImmX16, MI, BB);
185 case Mips::SelTBteqZCmp:
186 return emitSelT16(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);
187 case Mips::SelTBteqZSlt:
188 return emitSelT16(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);
189 case Mips::SelTBteqZSltu:
190 return emitSelT16(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);
191 case Mips::SelTBtneZCmp:
192 return emitSelT16(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);
193 case Mips::SelTBtneZSlt:
194 return emitSelT16(Mips::Btnez16, Mips::SltRxRy16, MI, BB);
195 case Mips::SelTBtneZSltu:
196 return emitSelT16(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);
197 case Mips::BteqzT8CmpX16:
198 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);
199 case Mips::BteqzT8SltX16:
200 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);
201 case Mips::BteqzT8SltuX16:
202 // TBD: figure out a way to get this or remove the instruction
203 // altogether.
204 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);
205 case Mips::BtnezT8CmpX16:
206 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);
207 case Mips::BtnezT8SltX16:
208 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltRxRy16, MI, BB);
209 case Mips::BtnezT8SltuX16:
210 // TBD: figure out a way to get this or remove the instruction
211 // altogether.
212 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);
213 case Mips::BteqzT8CmpiX16: return emitFEXT_T8I8I16_ins(
214 Mips::Bteqz16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);
215 case Mips::BteqzT8SltiX16: return emitFEXT_T8I8I16_ins(
216 Mips::Bteqz16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);
217 case Mips::BteqzT8SltiuX16: return emitFEXT_T8I8I16_ins(
218 Mips::Bteqz16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);
219 case Mips::BtnezT8CmpiX16: return emitFEXT_T8I8I16_ins(
220 Mips::Btnez16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);
221 case Mips::BtnezT8SltiX16: return emitFEXT_T8I8I16_ins(
222 Mips::Btnez16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);
223 case Mips::BtnezT8SltiuX16: return emitFEXT_T8I8I16_ins(
224 Mips::Btnez16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);
225 break;
226 case Mips::SltCCRxRy16:
227 return emitFEXT_CCRX16_ins(Mips::SltRxRy16, MI, BB);
228 break;
229 case Mips::SltiCCRxImmX16:
230 return emitFEXT_CCRXI16_ins
231 (Mips::SltiRxImm16, Mips::SltiRxImmX16, MI, BB);
232 case Mips::SltiuCCRxImmX16:
233 return emitFEXT_CCRXI16_ins
234 (Mips::SltiuRxImm16, Mips::SltiuRxImmX16, MI, BB);
235 case Mips::SltuCCRxRy16:
236 return emitFEXT_CCRX16_ins
237 (Mips::SltuRxRy16, MI, BB);
238 }
239}
240
241bool Mips16TargetLowering::isEligibleForTailCallOptimization(
242 const CCState &CCInfo, unsigned NextStackOffset,
243 const MipsFunctionInfo &FI) const {
244 // No tail call optimization for mips16.
245 return false;
246}
247
248void Mips16TargetLowering::setMips16HardFloatLibCalls() {
249 for (unsigned I = 0; I != std::size(HardFloatLibCalls); ++I) {
250 assert((I == 0 || HardFloatLibCalls[I - 1] < HardFloatLibCalls[I]) &&
251 "Array not sorted!");
252 if (HardFloatLibCalls[I].Libcall != RTLIB::UNKNOWN_LIBCALL)
254 }
255}
256
257//
258// The Mips16 hard float is a crazy quilt inherited from gcc. I have a much
259// cleaner way to do all of this but it will have to wait until the traditional
260// gcc mechanism is completed.
261//
262// For Pic, in order for Mips16 code to call Mips32 code which according the abi
263// have either arguments or returned values placed in floating point registers,
264// we use a set of helper functions. (This includes functions which return type
265// complex which on Mips are returned in a pair of floating point registers).
266//
267// This is an encoding that we inherited from gcc.
268// In Mips traditional O32, N32 ABI, floating point numbers are passed in
269// floating point argument registers 1,2 only when the first and optionally
270// the second arguments are float (sf) or double (df).
271// For Mips16 we are only concerned with the situations where floating point
272// arguments are being passed in floating point registers by the ABI, because
273// Mips16 mode code cannot execute floating point instructions to load those
274// values and hence helper functions are needed.
275// The possibilities are (), (sf), (sf, sf), (sf, df), (df), (df, sf), (df, df)
276// the helper function suffixs for these are:
277// 0, 1, 5, 9, 2, 6, 10
278// this suffix can then be calculated as follows:
279// for a given argument Arg:
280// Arg1x, Arg2x = 1 : Arg is sf
281// 2 : Arg is df
282// 0: Arg is neither sf or df
283// So this stub is the string for number Arg1x + Arg2x*4.
284// However not all numbers between 0 and 10 are possible, we check anyway and
285// assert if the impossible exists.
286//
287
288unsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber
289 (ArgListTy &Args) const {
290 unsigned int resultNum = 0;
291 if (Args.size() >= 1) {
292 Type *t = Args[0].Ty;
293 if (t->isFloatTy()) {
294 resultNum = 1;
295 }
296 else if (t->isDoubleTy()) {
297 resultNum = 2;
298 }
299 }
300 if (resultNum) {
301 if (Args.size() >=2) {
302 Type *t = Args[1].Ty;
303 if (t->isFloatTy()) {
304 resultNum += 4;
305 }
306 else if (t->isDoubleTy()) {
307 resultNum += 8;
308 }
309 }
310 }
311 return resultNum;
312}
313
314//
315// Prefixes are attached to stub numbers depending on the return type.
316// return type: float sf_
317// double df_
318// single complex sc_
319// double complext dc_
320// others NO PREFIX
321//
322//
323// The full name of a helper function is__mips16_call_stub +
324// return type dependent prefix + stub number
325//
326// FIXME: This is something that probably should be in a different source file
327// and perhaps done differently but my main purpose is to not waste runtime
328// on something that we can enumerate in the source. Another possibility is
329// to have a python script to generate these mapping tables. This will do
330// for now. There are a whole series of helper function mapping arrays, one
331// for each return type class as outlined above. There there are 11 possible
332// entries. Ones with 0 are ones which should never be selected.
333//
334// All the arrays are similar except for ones which return neither
335// sf, df, sc, dc, in which we only care about ones which have sf or df as a
336// first parameter.
337//
338#define P_ "__mips16_call_stub_"
339#define MAX_STUB_NUMBER 10
340#define T1 P "1", P "2", 0, 0, P "5", P "6", 0, 0, P "9", P "10"
341#define T P "0" , T1
342#define P P_
343static char const * vMips16Helper[MAX_STUB_NUMBER+1] =
344 {nullptr, T1 };
345#undef P
346#define P P_ "sf_"
347static char const * sfMips16Helper[MAX_STUB_NUMBER+1] =
348 { T };
349#undef P
350#define P P_ "df_"
351static char const * dfMips16Helper[MAX_STUB_NUMBER+1] =
352 { T };
353#undef P
354#define P P_ "sc_"
355static char const * scMips16Helper[MAX_STUB_NUMBER+1] =
356 { T };
357#undef P
358#define P P_ "dc_"
359static char const * dcMips16Helper[MAX_STUB_NUMBER+1] =
360 { T };
361#undef P
362#undef P_
363
364
365const char* Mips16TargetLowering::
366 getMips16HelperFunction
367 (Type* RetTy, ArgListTy &Args, bool &needHelper) const {
368 const unsigned int stubNum = getMips16HelperFunctionStubNumber(Args);
369#ifndef NDEBUG
370 const unsigned int maxStubNum = 10;
371 assert(stubNum <= maxStubNum);
372 const bool validStubNum[maxStubNum+1] =
373 {true, true, true, false, false, true, true, false, false, true, true};
374 assert(validStubNum[stubNum]);
375#endif
376 const char *result;
377 if (RetTy->isFloatTy()) {
378 result = sfMips16Helper[stubNum];
379 }
380 else if (RetTy ->isDoubleTy()) {
381 result = dfMips16Helper[stubNum];
382 } else if (StructType *SRetTy = dyn_cast<StructType>(RetTy)) {
383 // check if it's complex
384 if (SRetTy->getNumElements() == 2) {
385 if ((SRetTy->getElementType(0)->isFloatTy()) &&
386 (SRetTy->getElementType(1)->isFloatTy())) {
387 result = scMips16Helper[stubNum];
388 } else if ((SRetTy->getElementType(0)->isDoubleTy()) &&
389 (SRetTy->getElementType(1)->isDoubleTy())) {
390 result = dcMips16Helper[stubNum];
391 } else {
392 llvm_unreachable("Uncovered condition");
393 }
394 } else {
395 llvm_unreachable("Uncovered condition");
396 }
397 } else {
398 if (stubNum == 0) {
399 needHelper = false;
400 return "";
401 }
402 result = vMips16Helper[stubNum];
403 }
404 needHelper = true;
405 return result;
406}
407
408void Mips16TargetLowering::
409getOpndList(SmallVectorImpl<SDValue> &Ops,
410 std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
411 bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
412 bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee,
413 SDValue Chain) const {
414 SelectionDAG &DAG = CLI.DAG;
416 MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
417 const char* Mips16HelperFunction = nullptr;
418 bool NeedMips16Helper = false;
419
421 //
422 // currently we don't have symbols tagged with the mips16 or mips32
423 // qualifier so we will assume that we don't know what kind it is.
424 // and generate the helper
425 //
426 bool LookupHelper = true;
427 if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) {
428 Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, S->getSymbol() };
429
430 if (std::binary_search(std::begin(HardFloatLibCalls),
431 std::end(HardFloatLibCalls), Find))
432 LookupHelper = false;
433 else {
434 const char *Symbol = S->getSymbol();
435 Mips16IntrinsicHelperType IntrinsicFind = { Symbol, "" };
436 const Mips16HardFloatInfo::FuncSignature *Signature =
438 if (!IsPICCall && (Signature && (FuncInfo->StubsNeeded.find(Symbol) ==
439 FuncInfo->StubsNeeded.end()))) {
440 FuncInfo->StubsNeeded[Symbol] = Signature;
441 //
442 // S2 is normally saved if the stub is for a function which
443 // returns a float or double value and is not otherwise. This is
444 // because more work is required after the function the stub
445 // is calling completes, and so the stub cannot directly return
446 // and the stub has no stack space to store the return address so
447 // S2 is used for that purpose.
448 // In order to take advantage of not saving S2, we need to also
449 // optimize the call in the stub and this requires some further
450 // functionality in MipsAsmPrinter which we don't have yet.
451 // So for now we always save S2. The optimization will be done
452 // in a follow-on patch.
453 //
454 if (true || (Signature->RetSig != Mips16HardFloatInfo::NoFPRet))
455 FuncInfo->setSaveS2();
456 }
457 // one more look at list of intrinsics
458 const Mips16IntrinsicHelperType *Helper =
460 if (Helper != std::end(Mips16IntrinsicHelper) &&
461 *Helper == IntrinsicFind) {
462 Mips16HelperFunction = Helper->Helper;
463 NeedMips16Helper = true;
464 LookupHelper = false;
465 }
466
467 }
468 } else if (GlobalAddressSDNode *G =
469 dyn_cast<GlobalAddressSDNode>(CLI.Callee)) {
470 Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL,
471 G->getGlobal()->getName().data() };
472
473 if (std::binary_search(std::begin(HardFloatLibCalls),
474 std::end(HardFloatLibCalls), Find))
475 LookupHelper = false;
476 }
477 if (LookupHelper)
478 Mips16HelperFunction =
479 getMips16HelperFunction(CLI.RetTy, CLI.getArgs(), NeedMips16Helper);
480 }
481
482 SDValue JumpTarget = Callee;
483
484 // T9 should contain the address of the callee function if
485 // -relocation-model=pic or it is an indirect call.
486 if (IsPICCall || !GlobalOrExternal) {
487 unsigned V0Reg = Mips::V0;
488 if (NeedMips16Helper) {
489 RegsToPass.push_front(std::make_pair(V0Reg, Callee));
490 JumpTarget = DAG.getExternalSymbol(Mips16HelperFunction,
492 ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(JumpTarget);
493 JumpTarget = getAddrGlobal(S, CLI.DL, JumpTarget.getValueType(), DAG,
494 MipsII::MO_GOT, Chain,
495 FuncInfo->callPtrInfo(MF, S->getSymbol()));
496 } else
497 RegsToPass.push_front(std::make_pair((unsigned)Mips::T9, Callee));
498 }
499
500 Ops.push_back(JumpTarget);
501
502 MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal,
503 InternalLinkage, IsCallReloc, CLI, Callee,
504 Chain);
505}
506
508Mips16TargetLowering::emitSel16(unsigned Opc, MachineInstr &MI,
509 MachineBasicBlock *BB) const {
511 return BB;
513 DebugLoc DL = MI.getDebugLoc();
514 // To "insert" a SELECT_CC instruction, we actually have to insert the
515 // diamond control-flow pattern. The incoming instruction knows the
516 // destination vreg to set, the condition code register to branch on, the
517 // true/false values to select between, and a branch opcode to use.
518 const BasicBlock *LLVM_BB = BB->getBasicBlock();
520
521 // thisMBB:
522 // ...
523 // TrueVal = ...
524 // setcc r1, r2, r3
525 // bNE r1, r0, copy1MBB
526 // fallthrough --> copy0MBB
527 MachineBasicBlock *thisMBB = BB;
528 MachineFunction *F = BB->getParent();
529 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
530 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
531 F->insert(It, copy0MBB);
532 F->insert(It, sinkMBB);
533
534 // Transfer the remainder of BB and its successor edges to sinkMBB.
535 sinkMBB->splice(sinkMBB->begin(), BB,
536 std::next(MachineBasicBlock::iterator(MI)), BB->end());
538
539 // Next, add the true and fallthrough blocks as its successors.
540 BB->addSuccessor(copy0MBB);
541 BB->addSuccessor(sinkMBB);
542
543 BuildMI(BB, DL, TII->get(Opc))
544 .addReg(MI.getOperand(3).getReg())
545 .addMBB(sinkMBB);
546
547 // copy0MBB:
548 // %FalseValue = ...
549 // # fallthrough to sinkMBB
550 BB = copy0MBB;
551
552 // Update machine-CFG edges
553 BB->addSuccessor(sinkMBB);
554
555 // sinkMBB:
556 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
557 // ...
558 BB = sinkMBB;
559
560 BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
561 .addReg(MI.getOperand(1).getReg())
562 .addMBB(thisMBB)
563 .addReg(MI.getOperand(2).getReg())
564 .addMBB(copy0MBB);
565
566 MI.eraseFromParent(); // The pseudo instruction is gone now.
567 return BB;
568}
569
571Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr &MI,
572 MachineBasicBlock *BB) const {
574 return BB;
576 DebugLoc DL = MI.getDebugLoc();
577 // To "insert" a SELECT_CC instruction, we actually have to insert the
578 // diamond control-flow pattern. The incoming instruction knows the
579 // destination vreg to set, the condition code register to branch on, the
580 // true/false values to select between, and a branch opcode to use.
581 const BasicBlock *LLVM_BB = BB->getBasicBlock();
583
584 // thisMBB:
585 // ...
586 // TrueVal = ...
587 // setcc r1, r2, r3
588 // bNE r1, r0, copy1MBB
589 // fallthrough --> copy0MBB
590 MachineBasicBlock *thisMBB = BB;
591 MachineFunction *F = BB->getParent();
592 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
593 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
594 F->insert(It, copy0MBB);
595 F->insert(It, sinkMBB);
596
597 // Transfer the remainder of BB and its successor edges to sinkMBB.
598 sinkMBB->splice(sinkMBB->begin(), BB,
599 std::next(MachineBasicBlock::iterator(MI)), BB->end());
601
602 // Next, add the true and fallthrough blocks as its successors.
603 BB->addSuccessor(copy0MBB);
604 BB->addSuccessor(sinkMBB);
605
606 BuildMI(BB, DL, TII->get(Opc2))
607 .addReg(MI.getOperand(3).getReg())
608 .addReg(MI.getOperand(4).getReg());
609 BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);
610
611 // copy0MBB:
612 // %FalseValue = ...
613 // # fallthrough to sinkMBB
614 BB = copy0MBB;
615
616 // Update machine-CFG edges
617 BB->addSuccessor(sinkMBB);
618
619 // sinkMBB:
620 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
621 // ...
622 BB = sinkMBB;
623
624 BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
625 .addReg(MI.getOperand(1).getReg())
626 .addMBB(thisMBB)
627 .addReg(MI.getOperand(2).getReg())
628 .addMBB(copy0MBB);
629
630 MI.eraseFromParent(); // The pseudo instruction is gone now.
631 return BB;
632
633}
634
636Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2,
638 MachineBasicBlock *BB) const {
640 return BB;
642 DebugLoc DL = MI.getDebugLoc();
643 // To "insert" a SELECT_CC instruction, we actually have to insert the
644 // diamond control-flow pattern. The incoming instruction knows the
645 // destination vreg to set, the condition code register to branch on, the
646 // true/false values to select between, and a branch opcode to use.
647 const BasicBlock *LLVM_BB = BB->getBasicBlock();
649
650 // thisMBB:
651 // ...
652 // TrueVal = ...
653 // setcc r1, r2, r3
654 // bNE r1, r0, copy1MBB
655 // fallthrough --> copy0MBB
656 MachineBasicBlock *thisMBB = BB;
657 MachineFunction *F = BB->getParent();
658 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
659 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
660 F->insert(It, copy0MBB);
661 F->insert(It, sinkMBB);
662
663 // Transfer the remainder of BB and its successor edges to sinkMBB.
664 sinkMBB->splice(sinkMBB->begin(), BB,
665 std::next(MachineBasicBlock::iterator(MI)), BB->end());
667
668 // Next, add the true and fallthrough blocks as its successors.
669 BB->addSuccessor(copy0MBB);
670 BB->addSuccessor(sinkMBB);
671
672 BuildMI(BB, DL, TII->get(Opc2))
673 .addReg(MI.getOperand(3).getReg())
674 .addImm(MI.getOperand(4).getImm());
675 BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);
676
677 // copy0MBB:
678 // %FalseValue = ...
679 // # fallthrough to sinkMBB
680 BB = copy0MBB;
681
682 // Update machine-CFG edges
683 BB->addSuccessor(sinkMBB);
684
685 // sinkMBB:
686 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
687 // ...
688 BB = sinkMBB;
689
690 BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
691 .addReg(MI.getOperand(1).getReg())
692 .addMBB(thisMBB)
693 .addReg(MI.getOperand(2).getReg())
694 .addMBB(copy0MBB);
695
696 MI.eraseFromParent(); // The pseudo instruction is gone now.
697 return BB;
698
699}
700
702Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc,
704 MachineBasicBlock *BB) const {
706 return BB;
708 Register regX = MI.getOperand(0).getReg();
709 Register regY = MI.getOperand(1).getReg();
710 MachineBasicBlock *target = MI.getOperand(2).getMBB();
711 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc))
712 .addReg(regX)
713 .addReg(regY);
714 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);
715 MI.eraseFromParent(); // The pseudo instruction is gone now.
716 return BB;
717}
718
719MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins(
720 unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned,
721 MachineInstr &MI, MachineBasicBlock *BB) const {
723 return BB;
725 Register regX = MI.getOperand(0).getReg();
726 int64_t imm = MI.getOperand(1).getImm();
727 MachineBasicBlock *target = MI.getOperand(2).getMBB();
728 unsigned CmpOpc;
729 if (isUInt<8>(imm))
730 CmpOpc = CmpiOpc;
731 else if ((!ImmSigned && isUInt<16>(imm)) ||
732 (ImmSigned && isInt<16>(imm)))
733 CmpOpc = CmpiXOpc;
734 else
735 llvm_unreachable("immediate field not usable");
736 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc)).addReg(regX).addImm(imm);
737 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);
738 MI.eraseFromParent(); // The pseudo instruction is gone now.
739 return BB;
740}
741
743 (unsigned shortOp, unsigned longOp, int64_t Imm) {
744 if (isUInt<8>(Imm))
745 return shortOp;
746 else if (isInt<16>(Imm))
747 return longOp;
748 else
749 llvm_unreachable("immediate field not usable");
750}
751
753Mips16TargetLowering::emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr &MI,
754 MachineBasicBlock *BB) const {
756 return BB;
758 Register CC = MI.getOperand(0).getReg();
759 Register regX = MI.getOperand(1).getReg();
760 Register regY = MI.getOperand(2).getReg();
761 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc))
762 .addReg(regX)
763 .addReg(regY);
764 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)
765 .addReg(Mips::T8);
766 MI.eraseFromParent(); // The pseudo instruction is gone now.
767 return BB;
768}
769
771Mips16TargetLowering::emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc,
773 MachineBasicBlock *BB) const {
775 return BB;
777 Register CC = MI.getOperand(0).getReg();
778 Register regX = MI.getOperand(1).getReg();
779 int64_t Imm = MI.getOperand(2).getImm();
780 unsigned SltOpc = Mips16WhichOp8uOr16simm(SltiOpc, SltiXOpc, Imm);
781 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc)).addReg(regX).addImm(Imm);
782 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)
783 .addReg(Mips::T8);
784 MI.eraseFromParent(); // The pseudo instruction is gone now.
785 return BB;
786
787}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
return RetTy
std::string Name
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
static const T * Find(StringRef S, ArrayRef< T > A)
Find KV in array using binary search.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#define G(x, y, z)
Definition: MD5.cpp:56
static char const * vMips16Helper[MAX_STUB_NUMBER+1]
static char const * dcMips16Helper[MAX_STUB_NUMBER+1]
static cl::opt< bool > DontExpandCondPseudos16("mips16-dont-expand-cond-pseudo", cl::init(false), cl::desc("Don't expand conditional move related " "pseudos for Mips 16"), cl::Hidden)
static char const * dfMips16Helper[MAX_STUB_NUMBER+1]
static const Mips16IntrinsicHelperType Mips16IntrinsicHelper[]
#define MAX_STUB_NUMBER
static char const * sfMips16Helper[MAX_STUB_NUMBER+1]
static const Mips16Libcall HardFloatLibCalls[]
#define T1
static unsigned Mips16WhichOp8uOr16simm(unsigned shortOp, unsigned longOp, int64_t Imm)
static char const * scMips16Helper[MAX_STUB_NUMBER+1]
const char LLVMTargetMachineRef TM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Value * RHS
LLVM Basic Block Representation.
Definition: BasicBlock.h:60
CCState - This class holds information needed while lowering arguments and return values.
A debug info location.
Definition: DebugLoc.h:33
const char * getSymbol() const
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
Definition: MachineInstr.h:69
Flags
Flags values. These may be or'd together.
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Mips16TargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI)
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const override
Determine if the target supports unaligned memory accesses.
MipsFunctionInfo - This class is derived from MachineFunction private Mips target-specific informatio...
MachinePointerInfo callPtrInfo(MachineFunction &MF, const char *ES)
Create a MachinePointerInfo that has an ExternalSymbolPseudoSourceValue object representing a GOT ent...
std::map< const char *, const Mips16HardFloatInfo::FuncSignature * > StubsNeeded
bool useSoftFloat() const
const MipsInstrInfo * getInstrInfo() const override
const MipsRegisterInfo * getRegisterInfo() const override
bool inMips16HardFloat() const
SDValue getAddrGlobal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flag, SDValue Chain, const MachinePointerInfo &PtrInfo) const
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
virtual void getOpndList(SmallVectorImpl< SDValue > &Ops, std::deque< std::pair< unsigned, SDValue > > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const
This function fills Ops, which is the list of operands that will later be used when a function call n...
const MipsSubtarget & Subtarget
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
EVT getValueType() const
Return the ValueType of the referenced return value.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:225
const DataLayout & getDataLayout() const
Definition: SelectionDAG.h:472
SDValue getExternalSymbol(const char *Sym, EVT VT)
MachineFunction & getMachineFunction() const
Definition: SelectionDAG.h:469
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void push_back(const T &Elt)
Definition: SmallVector.h:426
Class to represent struct types.
Definition: DerivedTypes.h:216
TargetInstrInfo - Interface to description of machine instruction set.
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setLibcallName(RTLIB::Libcall Call, const char *Name)
Rename the default libcall routine name for the specified libcall.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition: Type.h:154
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition: Type.h:157
self_iterator getIterator()
Definition: ilist_node.h:109
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:41
@ ATOMIC_LOAD_NAND
Definition: ISDOpcodes.h:1269
@ BSWAP
Byte Swap and Counting operators.
Definition: ISDOpcodes.h:714
@ ATOMIC_LOAD_MAX
Definition: ISDOpcodes.h:1271
@ ATOMIC_LOAD_UMIN
Definition: ISDOpcodes.h:1272
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
Definition: ISDOpcodes.h:1233
@ ATOMIC_LOAD_OR
Definition: ISDOpcodes.h:1267
@ ATOMIC_LOAD_XOR
Definition: ISDOpcodes.h:1268
@ ATOMIC_LOAD_MIN
Definition: ISDOpcodes.h:1270
@ ATOMIC_LOAD_AND
Definition: ISDOpcodes.h:1265
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
Definition: ISDOpcodes.h:1248
@ ATOMIC_LOAD_UMAX
Definition: ISDOpcodes.h:1273
@ ATOMIC_LOAD_ADD
Definition: ISDOpcodes.h:1263
@ ATOMIC_LOAD_SUB
Definition: ISDOpcodes.h:1264
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
Definition: ISDOpcodes.h:1262
FuncSignature const * findFuncSignature(const char *name)
@ MO_GOT
MO_GOT - Represents the offset into the global offset table at which the address the relocation entry...
Definition: MipsBaseInfo.h:38
Libcall
RTLIB::Libcall enum - This enum defines all of the runtime library calls the backend can emit.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:450
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool operator<(int64_t V1, const APSInt &V2)
Definition: APSInt.h:361
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
const MipsTargetLowering * createMips16TargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI)
Create MipsTargetLowering objects.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1963
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
Extended Value Type.
Definition: ValueTypes.h:34