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