LLVM 22.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 RTLIB::LibcallImpl Impl;
37 const char *Name; // FIXME: Remove this
38
39 bool operator<(const Mips16Libcall &RHS) const {
40 return std::strcmp(Name, RHS.Name) < 0;
41 }
42};
43
44struct Mips16IntrinsicHelperType{
45 const char* Name;
46 const char* Helper;
47
48 bool operator<(const Mips16IntrinsicHelperType &RHS) const {
49 return std::strcmp(Name, RHS.Name) < 0;
50 }
51 bool operator==(const Mips16IntrinsicHelperType &RHS) const {
52 return std::strcmp(Name, RHS.Name) == 0;
53 }
54};
55}
56
57// Libcalls for which no helper is generated. Sorted by name for binary search.
58static const Mips16Libcall HardFloatLibCalls[] = {
59 {RTLIB::ADD_F64, RTLIB::__mips16_adddf3, "__mips16_adddf3"},
60 {RTLIB::ADD_F32, RTLIB::__mips16_addsf3, "__mips16_addsf3"},
61 {RTLIB::DIV_F64, RTLIB::__mips16_divdf3, "__mips16_divdf3"},
62 {RTLIB::DIV_F32, RTLIB::__mips16_divsf3, "__mips16_divsf3"},
63 {RTLIB::OEQ_F64, RTLIB::__mips16_eqdf2, "__mips16_eqdf2"},
64 {RTLIB::OEQ_F32, RTLIB::__mips16_eqsf2, "__mips16_eqsf2"},
65 {RTLIB::FPEXT_F32_F64, RTLIB::__mips16_extendsfdf2, "__mips16_extendsfdf2"},
66 {RTLIB::FPTOSINT_F64_I32, RTLIB::__mips16_fix_truncdfsi,
67 "__mips16_fix_truncdfsi"},
68 {RTLIB::FPTOSINT_F32_I32, RTLIB::__mips16_fix_truncsfsi,
69 "__mips16_fix_truncsfsi"},
70 {RTLIB::SINTTOFP_I32_F64, RTLIB::__mips16_floatsidf, "__mips16_floatsidf"},
71 {RTLIB::SINTTOFP_I32_F32, RTLIB::__mips16_floatsisf, "__mips16_floatsisf"},
72 {RTLIB::UINTTOFP_I32_F64, RTLIB::__mips16_floatunsidf,
73 "__mips16_floatunsidf"},
74 {RTLIB::UINTTOFP_I32_F32, RTLIB::__mips16_floatunsisf,
75 "__mips16_floatunsisf"},
76 {RTLIB::OGE_F64, RTLIB::__mips16_gedf2, "__mips16_gedf2"},
77 {RTLIB::OGE_F32, RTLIB::__mips16_gesf2, "__mips16_gesf2"},
78 {RTLIB::OGT_F64, RTLIB::__mips16_gtdf2, "__mips16_gtdf2"},
79 {RTLIB::OGT_F32, RTLIB::__mips16_gtsf2, "__mips16_gtsf2"},
80 {RTLIB::OLE_F64, RTLIB::__mips16_ledf2, "__mips16_ledf2"},
81 {RTLIB::OLE_F32, RTLIB::__mips16_lesf2, "__mips16_lesf2"},
82 {RTLIB::OLT_F64, RTLIB::__mips16_ltdf2, "__mips16_ltdf2"},
83 {RTLIB::OLT_F32, RTLIB::__mips16_ltsf2, "__mips16_ltsf2"},
84 {RTLIB::MUL_F64, RTLIB::__mips16_muldf3, "__mips16_muldf3"},
85 {RTLIB::MUL_F32, RTLIB::__mips16_mulsf3, "__mips16_mulsf3"},
86 {RTLIB::UNE_F64, RTLIB::__mips16_nedf2, "__mips16_nedf2"},
87 {RTLIB::UNE_F32, RTLIB::__mips16_nesf2, "__mips16_nesf2"},
88 {RTLIB::UNKNOWN_LIBCALL, RTLIB::__mips16_ret_dc,
89 "__mips16_ret_dc"}, // No associated libcall.
90 {RTLIB::UNKNOWN_LIBCALL, RTLIB::__mips16_ret_df,
91 "__mips16_ret_df"}, // No associated libcall.
92 {RTLIB::UNKNOWN_LIBCALL, RTLIB::__mips16_ret_sc,
93 "__mips16_ret_sc"}, // No associated libcall.
94 {RTLIB::UNKNOWN_LIBCALL, RTLIB::__mips16_ret_sf,
95 "__mips16_ret_sf"}, // No associated libcall.
96 {RTLIB::SUB_F64, RTLIB::__mips16_subdf3, "__mips16_subdf3"},
97 {RTLIB::SUB_F32, RTLIB::__mips16_subsf3, "__mips16_subsf3"},
98 {RTLIB::FPROUND_F64_F32, RTLIB::__mips16_truncdfsf2, "__mips16_truncdfsf2"},
99 {RTLIB::UO_F64, RTLIB::__mips16_unorddf2, "__mips16_unorddf2"},
100 {RTLIB::UO_F32, RTLIB::__mips16_unordsf2, "__mips16_unordsf2"}};
101
102static const Mips16IntrinsicHelperType Mips16IntrinsicHelper[] = {
103 {"__fixunsdfsi", "__mips16_call_stub_2" },
104 {"ceil", "__mips16_call_stub_df_2"},
105 {"ceilf", "__mips16_call_stub_sf_1"},
106 {"copysign", "__mips16_call_stub_df_10"},
107 {"copysignf", "__mips16_call_stub_sf_5"},
108 {"cos", "__mips16_call_stub_df_2"},
109 {"cosf", "__mips16_call_stub_sf_1"},
110 {"exp2", "__mips16_call_stub_df_2"},
111 {"exp2f", "__mips16_call_stub_sf_1"},
112 {"floor", "__mips16_call_stub_df_2"},
113 {"floorf", "__mips16_call_stub_sf_1"},
114 {"log2", "__mips16_call_stub_df_2"},
115 {"log2f", "__mips16_call_stub_sf_1"},
116 {"nearbyint", "__mips16_call_stub_df_2"},
117 {"nearbyintf", "__mips16_call_stub_sf_1"},
118 {"rint", "__mips16_call_stub_df_2"},
119 {"rintf", "__mips16_call_stub_sf_1"},
120 {"sin", "__mips16_call_stub_df_2"},
121 {"sinf", "__mips16_call_stub_sf_1"},
122 {"sqrt", "__mips16_call_stub_df_2"},
123 {"sqrtf", "__mips16_call_stub_sf_1"},
124 {"trunc", "__mips16_call_stub_df_2"},
125 {"truncf", "__mips16_call_stub_sf_1"},
126};
127
129 const MipsSubtarget &STI)
130 : MipsTargetLowering(TM, STI) {
131
132 // Set up the register classes
133 addRegisterClass(MVT::i32, &Mips::CPU16RegsRegClass);
134
135 if (!Subtarget.useSoftFloat())
136 setMips16HardFloatLibCalls();
137
151
156
158}
159
160const MipsTargetLowering *
162 const MipsSubtarget &STI) {
163 return new Mips16TargetLowering(TM, STI);
164}
165
167 EVT VT, unsigned, Align, MachineMemOperand::Flags, unsigned *Fast) const {
168 return false;
169}
170
173 MachineBasicBlock *BB) const {
174 switch (MI.getOpcode()) {
175 default:
177 case Mips::SelBeqZ:
178 return emitSel16(Mips::BeqzRxImm16, MI, BB);
179 case Mips::SelBneZ:
180 return emitSel16(Mips::BnezRxImm16, MI, BB);
181 case Mips::SelTBteqZCmpi:
182 return emitSeliT16(Mips::Bteqz16, Mips::CmpiRxImmX16, MI, BB);
183 case Mips::SelTBteqZSlti:
184 return emitSeliT16(Mips::Bteqz16, Mips::SltiRxImmX16, MI, BB);
185 case Mips::SelTBteqZSltiu:
186 return emitSeliT16(Mips::Bteqz16, Mips::SltiuRxImmX16, MI, BB);
187 case Mips::SelTBtneZCmpi:
188 return emitSeliT16(Mips::Btnez16, Mips::CmpiRxImmX16, MI, BB);
189 case Mips::SelTBtneZSlti:
190 return emitSeliT16(Mips::Btnez16, Mips::SltiRxImmX16, MI, BB);
191 case Mips::SelTBtneZSltiu:
192 return emitSeliT16(Mips::Btnez16, Mips::SltiuRxImmX16, MI, BB);
193 case Mips::SelTBteqZCmp:
194 return emitSelT16(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);
195 case Mips::SelTBteqZSlt:
196 return emitSelT16(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);
197 case Mips::SelTBteqZSltu:
198 return emitSelT16(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);
199 case Mips::SelTBtneZCmp:
200 return emitSelT16(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);
201 case Mips::SelTBtneZSlt:
202 return emitSelT16(Mips::Btnez16, Mips::SltRxRy16, MI, BB);
203 case Mips::SelTBtneZSltu:
204 return emitSelT16(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);
205 case Mips::BteqzT8CmpX16:
206 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);
207 case Mips::BteqzT8SltX16:
208 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);
209 case Mips::BteqzT8SltuX16:
210 // TBD: figure out a way to get this or remove the instruction
211 // altogether.
212 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);
213 case Mips::BtnezT8CmpX16:
214 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);
215 case Mips::BtnezT8SltX16:
216 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltRxRy16, MI, BB);
217 case Mips::BtnezT8SltuX16:
218 // TBD: figure out a way to get this or remove the instruction
219 // altogether.
220 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);
221 case Mips::BteqzT8CmpiX16: return emitFEXT_T8I8I16_ins(
222 Mips::Bteqz16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);
223 case Mips::BteqzT8SltiX16: return emitFEXT_T8I8I16_ins(
224 Mips::Bteqz16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);
225 case Mips::BteqzT8SltiuX16: return emitFEXT_T8I8I16_ins(
226 Mips::Bteqz16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);
227 case Mips::BtnezT8CmpiX16: return emitFEXT_T8I8I16_ins(
228 Mips::Btnez16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);
229 case Mips::BtnezT8SltiX16: return emitFEXT_T8I8I16_ins(
230 Mips::Btnez16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);
231 case Mips::BtnezT8SltiuX16: return emitFEXT_T8I8I16_ins(
232 Mips::Btnez16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);
233 break;
234 case Mips::SltCCRxRy16:
235 return emitFEXT_CCRX16_ins(Mips::SltRxRy16, MI, BB);
236 break;
237 case Mips::SltiCCRxImmX16:
238 return emitFEXT_CCRXI16_ins
239 (Mips::SltiRxImm16, Mips::SltiRxImmX16, MI, BB);
240 case Mips::SltiuCCRxImmX16:
241 return emitFEXT_CCRXI16_ins
242 (Mips::SltiuRxImm16, Mips::SltiuRxImmX16, MI, BB);
243 case Mips::SltuCCRxRy16:
244 return emitFEXT_CCRX16_ins
245 (Mips::SltuRxRy16, MI, BB);
246 }
247}
248
249bool Mips16TargetLowering::isEligibleForTailCallOptimization(
250 const CCState &CCInfo, unsigned NextStackOffset,
251 const MipsFunctionInfo &FI) const {
252 // No tail call optimization for mips16.
253 return false;
254}
255
256void Mips16TargetLowering::setMips16HardFloatLibCalls() {
257 for (unsigned I = 0; I != std::size(HardFloatLibCalls); ++I) {
258 assert((I == 0 || HardFloatLibCalls[I - 1] < HardFloatLibCalls[I]) &&
259 "Array not sorted!");
260 if (HardFloatLibCalls[I].Libcall != RTLIB::UNKNOWN_LIBCALL)
262 }
263}
264
265//
266// The Mips16 hard float is a crazy quilt inherited from gcc. I have a much
267// cleaner way to do all of this but it will have to wait until the traditional
268// gcc mechanism is completed.
269//
270// For Pic, in order for Mips16 code to call Mips32 code which according the abi
271// have either arguments or returned values placed in floating point registers,
272// we use a set of helper functions. (This includes functions which return type
273// complex which on Mips are returned in a pair of floating point registers).
274//
275// This is an encoding that we inherited from gcc.
276// In Mips traditional O32, N32 ABI, floating point numbers are passed in
277// floating point argument registers 1,2 only when the first and optionally
278// the second arguments are float (sf) or double (df).
279// For Mips16 we are only concerned with the situations where floating point
280// arguments are being passed in floating point registers by the ABI, because
281// Mips16 mode code cannot execute floating point instructions to load those
282// values and hence helper functions are needed.
283// The possibilities are (), (sf), (sf, sf), (sf, df), (df), (df, sf), (df, df)
284// the helper function suffixs for these are:
285// 0, 1, 5, 9, 2, 6, 10
286// this suffix can then be calculated as follows:
287// for a given argument Arg:
288// Arg1x, Arg2x = 1 : Arg is sf
289// 2 : Arg is df
290// 0: Arg is neither sf or df
291// So this stub is the string for number Arg1x + Arg2x*4.
292// However not all numbers between 0 and 10 are possible, we check anyway and
293// assert if the impossible exists.
294//
295
296unsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber
297 (ArgListTy &Args) const {
298 unsigned int resultNum = 0;
299 if (Args.size() >= 1) {
300 Type *t = Args[0].Ty;
301 if (t->isFloatTy()) {
302 resultNum = 1;
303 }
304 else if (t->isDoubleTy()) {
305 resultNum = 2;
306 }
307 }
308 if (resultNum) {
309 if (Args.size() >=2) {
310 Type *t = Args[1].Ty;
311 if (t->isFloatTy()) {
312 resultNum += 4;
313 }
314 else if (t->isDoubleTy()) {
315 resultNum += 8;
316 }
317 }
318 }
319 return resultNum;
320}
321
322//
323// Prefixes are attached to stub numbers depending on the return type.
324// return type: float sf_
325// double df_
326// single complex sc_
327// double complext dc_
328// others NO PREFIX
329//
330//
331// The full name of a helper function is__mips16_call_stub +
332// return type dependent prefix + stub number
333//
334// FIXME: This is something that probably should be in a different source file
335// and perhaps done differently but my main purpose is to not waste runtime
336// on something that we can enumerate in the source. Another possibility is
337// to have a python script to generate these mapping tables. This will do
338// for now. There are a whole series of helper function mapping arrays, one
339// for each return type class as outlined above. There there are 11 possible
340// entries. Ones with 0 are ones which should never be selected.
341//
342// All the arrays are similar except for ones which return neither
343// sf, df, sc, dc, in which we only care about ones which have sf or df as a
344// first parameter.
345//
346#define P_ "__mips16_call_stub_"
347#define MAX_STUB_NUMBER 10
348#define T1 P "1", P "2", 0, 0, P "5", P "6", 0, 0, P "9", P "10"
349#define T P "0" , T1
350#define P P_
351static char const * vMips16Helper[MAX_STUB_NUMBER+1] =
352 {nullptr, T1 };
353#undef P
354#define P P_ "sf_"
355static char const * sfMips16Helper[MAX_STUB_NUMBER+1] =
356 { T };
357#undef P
358#define P P_ "df_"
359static char const * dfMips16Helper[MAX_STUB_NUMBER+1] =
360 { T };
361#undef P
362#define P P_ "sc_"
363static char const * scMips16Helper[MAX_STUB_NUMBER+1] =
364 { T };
365#undef P
366#define P P_ "dc_"
367static char const * dcMips16Helper[MAX_STUB_NUMBER+1] =
368 { T };
369#undef P
370#undef P_
371
372
373const char* Mips16TargetLowering::
374 getMips16HelperFunction
375 (Type* RetTy, ArgListTy &Args, bool &needHelper) const {
376 const unsigned int stubNum = getMips16HelperFunctionStubNumber(Args);
377#ifndef NDEBUG
378 const unsigned int maxStubNum = 10;
379 assert(stubNum <= maxStubNum);
380 const bool validStubNum[maxStubNum+1] =
381 {true, true, true, false, false, true, true, false, false, true, true};
382 assert(validStubNum[stubNum]);
383#endif
384 const char *result;
385 if (RetTy->isFloatTy()) {
386 result = sfMips16Helper[stubNum];
387 }
388 else if (RetTy ->isDoubleTy()) {
389 result = dfMips16Helper[stubNum];
390 } else if (StructType *SRetTy = dyn_cast<StructType>(RetTy)) {
391 // check if it's complex
392 if (SRetTy->getNumElements() == 2) {
393 if ((SRetTy->getElementType(0)->isFloatTy()) &&
394 (SRetTy->getElementType(1)->isFloatTy())) {
395 result = scMips16Helper[stubNum];
396 } else if ((SRetTy->getElementType(0)->isDoubleTy()) &&
397 (SRetTy->getElementType(1)->isDoubleTy())) {
398 result = dcMips16Helper[stubNum];
399 } else {
400 llvm_unreachable("Uncovered condition");
401 }
402 } else {
403 llvm_unreachable("Uncovered condition");
404 }
405 } else {
406 if (stubNum == 0) {
407 needHelper = false;
408 return "";
409 }
410 result = vMips16Helper[stubNum];
411 }
412 needHelper = true;
413 return result;
414}
415
416void Mips16TargetLowering::
417getOpndList(SmallVectorImpl<SDValue> &Ops,
418 std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
419 bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
420 bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee,
421 SDValue Chain) const {
422 SelectionDAG &DAG = CLI.DAG;
424 MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
425 const char* Mips16HelperFunction = nullptr;
426 bool NeedMips16Helper = false;
427
429 //
430 // currently we don't have symbols tagged with the mips16 or mips32
431 // qualifier so we will assume that we don't know what kind it is.
432 // and generate the helper
433 //
434 bool LookupHelper = true;
435 if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) {
436 Mips16Libcall Find = {RTLIB::UNKNOWN_LIBCALL, RTLIB::Unsupported,
437 S->getSymbol()};
438
440 LookupHelper = false;
441 else {
442 const char *Symbol = S->getSymbol();
443 Mips16IntrinsicHelperType IntrinsicFind = { Symbol, "" };
444 const Mips16HardFloatInfo::FuncSignature *Signature =
446 if (!IsPICCall && Signature &&
447 FuncInfo->StubsNeeded.try_emplace(Symbol, Signature).second) {
448 //
449 // S2 is normally saved if the stub is for a function which
450 // returns a float or double value and is not otherwise. This is
451 // because more work is required after the function the stub
452 // is calling completes, and so the stub cannot directly return
453 // and the stub has no stack space to store the return address so
454 // S2 is used for that purpose.
455 // In order to take advantage of not saving S2, we need to also
456 // optimize the call in the stub and this requires some further
457 // functionality in MipsAsmPrinter which we don't have yet.
458 // So for now we always save S2. The optimization will be done
459 // in a follow-on patch.
460 //
461 if (true || (Signature->RetSig != Mips16HardFloatInfo::NoFPRet))
462 FuncInfo->setSaveS2();
463 }
464 // one more look at list of intrinsics
465 const Mips16IntrinsicHelperType *Helper =
467 if (Helper != std::end(Mips16IntrinsicHelper) &&
468 *Helper == IntrinsicFind) {
469 Mips16HelperFunction = Helper->Helper;
470 NeedMips16Helper = true;
471 LookupHelper = false;
472 }
473
474 }
475 } else if (GlobalAddressSDNode *G =
476 dyn_cast<GlobalAddressSDNode>(CLI.Callee)) {
477 Mips16Libcall Find = {RTLIB::UNKNOWN_LIBCALL, RTLIB::Unsupported,
478 G->getGlobal()->getName().data()};
479
481 LookupHelper = false;
482 }
483 if (LookupHelper)
484 Mips16HelperFunction =
485 getMips16HelperFunction(CLI.RetTy, CLI.getArgs(), NeedMips16Helper);
486 }
487
488 SDValue JumpTarget = Callee;
489
490 // T9 should contain the address of the callee function if
491 // -relocation-model=pic or it is an indirect call.
492 if (IsPICCall || !GlobalOrExternal) {
493 unsigned V0Reg = Mips::V0;
494 if (NeedMips16Helper) {
495 RegsToPass.push_front(std::make_pair(V0Reg, Callee));
496 JumpTarget = DAG.getExternalSymbol(Mips16HelperFunction,
498 ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(JumpTarget);
499 JumpTarget = getAddrGlobal(S, CLI.DL, JumpTarget.getValueType(), DAG,
500 MipsII::MO_GOT, Chain,
501 FuncInfo->callPtrInfo(MF, S->getSymbol()));
502 } else
503 RegsToPass.push_front(std::make_pair((unsigned)Mips::T9, Callee));
504 }
505
506 Ops.push_back(JumpTarget);
507
508 MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal,
509 InternalLinkage, IsCallReloc, CLI, Callee,
510 Chain);
511}
512
514Mips16TargetLowering::emitSel16(unsigned Opc, MachineInstr &MI,
515 MachineBasicBlock *BB) const {
517 return BB;
519 DebugLoc DL = MI.getDebugLoc();
520 // To "insert" a SELECT_CC instruction, we actually have to insert the
521 // diamond control-flow pattern. The incoming instruction knows the
522 // destination vreg to set, the condition code register to branch on, the
523 // true/false values to select between, and a branch opcode to use.
524 const BasicBlock *LLVM_BB = BB->getBasicBlock();
526
527 // thisMBB:
528 // ...
529 // TrueVal = ...
530 // setcc r1, r2, r3
531 // bNE r1, r0, copy1MBB
532 // fallthrough --> copy0MBB
533 MachineBasicBlock *thisMBB = BB;
534 MachineFunction *F = BB->getParent();
535 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
536 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
537 F->insert(It, copy0MBB);
538 F->insert(It, sinkMBB);
539
540 // Transfer the remainder of BB and its successor edges to sinkMBB.
541 sinkMBB->splice(sinkMBB->begin(), BB,
542 std::next(MachineBasicBlock::iterator(MI)), BB->end());
544
545 // Next, add the true and fallthrough blocks as its successors.
546 BB->addSuccessor(copy0MBB);
547 BB->addSuccessor(sinkMBB);
548
549 BuildMI(BB, DL, TII->get(Opc))
550 .addReg(MI.getOperand(3).getReg())
551 .addMBB(sinkMBB);
552
553 // copy0MBB:
554 // %FalseValue = ...
555 // # fallthrough to sinkMBB
556 BB = copy0MBB;
557
558 // Update machine-CFG edges
559 BB->addSuccessor(sinkMBB);
560
561 // sinkMBB:
562 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
563 // ...
564 BB = sinkMBB;
565
566 BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
567 .addReg(MI.getOperand(1).getReg())
568 .addMBB(thisMBB)
569 .addReg(MI.getOperand(2).getReg())
570 .addMBB(copy0MBB);
571
572 MI.eraseFromParent(); // The pseudo instruction is gone now.
573 return BB;
574}
575
577Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr &MI,
578 MachineBasicBlock *BB) const {
580 return BB;
582 DebugLoc DL = MI.getDebugLoc();
583 // To "insert" a SELECT_CC instruction, we actually have to insert the
584 // diamond control-flow pattern. The incoming instruction knows the
585 // destination vreg to set, the condition code register to branch on, the
586 // true/false values to select between, and a branch opcode to use.
587 const BasicBlock *LLVM_BB = BB->getBasicBlock();
589
590 // thisMBB:
591 // ...
592 // TrueVal = ...
593 // setcc r1, r2, r3
594 // bNE r1, r0, copy1MBB
595 // fallthrough --> copy0MBB
596 MachineBasicBlock *thisMBB = BB;
597 MachineFunction *F = BB->getParent();
598 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
599 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
600 F->insert(It, copy0MBB);
601 F->insert(It, sinkMBB);
602
603 // Transfer the remainder of BB and its successor edges to sinkMBB.
604 sinkMBB->splice(sinkMBB->begin(), BB,
605 std::next(MachineBasicBlock::iterator(MI)), BB->end());
607
608 // Next, add the true and fallthrough blocks as its successors.
609 BB->addSuccessor(copy0MBB);
610 BB->addSuccessor(sinkMBB);
611
612 BuildMI(BB, DL, TII->get(Opc2))
613 .addReg(MI.getOperand(3).getReg())
614 .addReg(MI.getOperand(4).getReg());
615 BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);
616
617 // copy0MBB:
618 // %FalseValue = ...
619 // # fallthrough to sinkMBB
620 BB = copy0MBB;
621
622 // Update machine-CFG edges
623 BB->addSuccessor(sinkMBB);
624
625 // sinkMBB:
626 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
627 // ...
628 BB = sinkMBB;
629
630 BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
631 .addReg(MI.getOperand(1).getReg())
632 .addMBB(thisMBB)
633 .addReg(MI.getOperand(2).getReg())
634 .addMBB(copy0MBB);
635
636 MI.eraseFromParent(); // The pseudo instruction is gone now.
637 return BB;
638
639}
640
642Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2,
644 MachineBasicBlock *BB) const {
646 return BB;
648 DebugLoc DL = MI.getDebugLoc();
649 // To "insert" a SELECT_CC instruction, we actually have to insert the
650 // diamond control-flow pattern. The incoming instruction knows the
651 // destination vreg to set, the condition code register to branch on, the
652 // true/false values to select between, and a branch opcode to use.
653 const BasicBlock *LLVM_BB = BB->getBasicBlock();
655
656 // thisMBB:
657 // ...
658 // TrueVal = ...
659 // setcc r1, r2, r3
660 // bNE r1, r0, copy1MBB
661 // fallthrough --> copy0MBB
662 MachineBasicBlock *thisMBB = BB;
663 MachineFunction *F = BB->getParent();
664 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
665 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
666 F->insert(It, copy0MBB);
667 F->insert(It, sinkMBB);
668
669 // Transfer the remainder of BB and its successor edges to sinkMBB.
670 sinkMBB->splice(sinkMBB->begin(), BB,
671 std::next(MachineBasicBlock::iterator(MI)), BB->end());
673
674 // Next, add the true and fallthrough blocks as its successors.
675 BB->addSuccessor(copy0MBB);
676 BB->addSuccessor(sinkMBB);
677
678 BuildMI(BB, DL, TII->get(Opc2))
679 .addReg(MI.getOperand(3).getReg())
680 .addImm(MI.getOperand(4).getImm());
681 BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);
682
683 // copy0MBB:
684 // %FalseValue = ...
685 // # fallthrough to sinkMBB
686 BB = copy0MBB;
687
688 // Update machine-CFG edges
689 BB->addSuccessor(sinkMBB);
690
691 // sinkMBB:
692 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
693 // ...
694 BB = sinkMBB;
695
696 BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
697 .addReg(MI.getOperand(1).getReg())
698 .addMBB(thisMBB)
699 .addReg(MI.getOperand(2).getReg())
700 .addMBB(copy0MBB);
701
702 MI.eraseFromParent(); // The pseudo instruction is gone now.
703 return BB;
704
705}
706
708Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc,
710 MachineBasicBlock *BB) const {
712 return BB;
714 Register regX = MI.getOperand(0).getReg();
715 Register regY = MI.getOperand(1).getReg();
716 MachineBasicBlock *target = MI.getOperand(2).getMBB();
717 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc))
718 .addReg(regX)
719 .addReg(regY);
720 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);
721 MI.eraseFromParent(); // The pseudo instruction is gone now.
722 return BB;
723}
724
725MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins(
726 unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned,
727 MachineInstr &MI, MachineBasicBlock *BB) const {
729 return BB;
731 Register regX = MI.getOperand(0).getReg();
732 int64_t imm = MI.getOperand(1).getImm();
733 MachineBasicBlock *target = MI.getOperand(2).getMBB();
734 unsigned CmpOpc;
735 if (isUInt<8>(imm))
736 CmpOpc = CmpiOpc;
737 else if ((!ImmSigned && isUInt<16>(imm)) ||
738 (ImmSigned && isInt<16>(imm)))
739 CmpOpc = CmpiXOpc;
740 else
741 llvm_unreachable("immediate field not usable");
742 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc)).addReg(regX).addImm(imm);
743 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);
744 MI.eraseFromParent(); // The pseudo instruction is gone now.
745 return BB;
746}
747
749 (unsigned shortOp, unsigned longOp, int64_t Imm) {
750 if (isUInt<8>(Imm))
751 return shortOp;
752 else if (isInt<16>(Imm))
753 return longOp;
754 else
755 llvm_unreachable("immediate field not usable");
756}
757
759Mips16TargetLowering::emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr &MI,
760 MachineBasicBlock *BB) const {
762 return BB;
764 Register CC = MI.getOperand(0).getReg();
765 Register regX = MI.getOperand(1).getReg();
766 Register regY = MI.getOperand(2).getReg();
767 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc))
768 .addReg(regX)
769 .addReg(regY);
770 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)
771 .addReg(Mips::T8);
772 MI.eraseFromParent(); // The pseudo instruction is gone now.
773 return BB;
774}
775
777Mips16TargetLowering::emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc,
779 MachineBasicBlock *BB) const {
781 return BB;
783 Register CC = MI.getOperand(0).getReg();
784 Register regX = MI.getOperand(1).getReg();
785 int64_t Imm = MI.getOperand(2).getImm();
786 unsigned SltOpc = Mips16WhichOp8uOr16simm(SltiOpc, SltiXOpc, Imm);
787 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc)).addReg(regX).addImm(Imm);
788 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)
789 .addReg(Mips::T8);
790 MI.eraseFromParent(); // The pseudo instruction is gone now.
791 return BB;
792
793}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
return RetTy
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]
Value * RHS
LLVM Basic Block Representation.
Definition: BasicBlock.h:62
CCState - This class holds information needed while lowering arguments and return values.
A debug info location.
Definition: DebugLoc.h:124
const char * getSymbol() const
LLVM_ABI 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.
LLVM_ABI 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:72
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:229
const DataLayout & getDataLayout() const
Definition: SelectionDAG.h:498
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
MachineFunction & getMachineFunction() const
Definition: SelectionDAG.h:493
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:574
void push_back(const T &Elt)
Definition: SmallVector.h:414
Class to represent struct types.
Definition: DerivedTypes.h:218
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 setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl)
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:153
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition: Type.h:156
self_iterator getIterator()
Definition: ilist_node.h:134
#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:1379
@ BSWAP
Byte Swap and Counting operators.
Definition: ISDOpcodes.h:765
@ ATOMIC_LOAD_MAX
Definition: ISDOpcodes.h:1381
@ ATOMIC_LOAD_UMIN
Definition: ISDOpcodes.h:1382
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
Definition: ISDOpcodes.h:1343
@ ATOMIC_LOAD_OR
Definition: ISDOpcodes.h:1377
@ ATOMIC_LOAD_XOR
Definition: ISDOpcodes.h:1378
@ ATOMIC_LOAD_MIN
Definition: ISDOpcodes.h:1380
@ ATOMIC_LOAD_AND
Definition: ISDOpcodes.h:1375
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
Definition: ISDOpcodes.h:1358
@ ATOMIC_LOAD_UMAX
Definition: ISDOpcodes.h:1383
@ ATOMIC_LOAD_ADD
Definition: ISDOpcodes.h:1373
@ ATOMIC_LOAD_SUB
Definition: ISDOpcodes.h:1374
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
Definition: ISDOpcodes.h:1372
FuncSignature const * findFuncSignature(const char *name)
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:444
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:362
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
auto binary_search(R &&Range, T &&Value)
Provide wrappers to std::binary_search which take ranges instead of having to pass begin/end explicit...
Definition: STLExtras.h:2000
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:2013
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:35