LLVM 24.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"
20
21using namespace llvm;
22
23#define DEBUG_TYPE "mips-lower"
24
25namespace {
26struct Mips16IntrinsicHelperType{
27 const char* Name;
28 const char* Helper;
29
30 bool operator<(const Mips16IntrinsicHelperType &RHS) const {
31 return std::strcmp(Name, RHS.Name) < 0;
32 }
33 bool operator==(const Mips16IntrinsicHelperType &RHS) const {
34 return std::strcmp(Name, RHS.Name) == 0;
35 }
36};
37} // namespace
38
39static const Mips16IntrinsicHelperType Mips16IntrinsicHelper[] = {
40 {"__fixunsdfsi", "__mips16_call_stub_2" },
41 {"ceil", "__mips16_call_stub_df_2"},
42 {"ceilf", "__mips16_call_stub_sf_1"},
43 {"copysign", "__mips16_call_stub_df_10"},
44 {"copysignf", "__mips16_call_stub_sf_5"},
45 {"cos", "__mips16_call_stub_df_2"},
46 {"cosf", "__mips16_call_stub_sf_1"},
47 {"exp2", "__mips16_call_stub_df_2"},
48 {"exp2f", "__mips16_call_stub_sf_1"},
49 {"floor", "__mips16_call_stub_df_2"},
50 {"floorf", "__mips16_call_stub_sf_1"},
51 {"log2", "__mips16_call_stub_df_2"},
52 {"log2f", "__mips16_call_stub_sf_1"},
53 {"nearbyint", "__mips16_call_stub_df_2"},
54 {"nearbyintf", "__mips16_call_stub_sf_1"},
55 {"rint", "__mips16_call_stub_df_2"},
56 {"rintf", "__mips16_call_stub_sf_1"},
57 {"sin", "__mips16_call_stub_df_2"},
58 {"sinf", "__mips16_call_stub_sf_1"},
59 {"sqrt", "__mips16_call_stub_df_2"},
60 {"sqrtf", "__mips16_call_stub_sf_1"},
61 {"trunc", "__mips16_call_stub_df_2"},
62 {"truncf", "__mips16_call_stub_sf_1"},
63};
64
93
96 const MipsSubtarget &STI) {
97 return new Mips16TargetLowering(TM, STI);
98}
99
101 EVT VT, unsigned, Align, MachineMemOperand::Flags, unsigned *Fast) const {
102 return false;
103}
104
107 MachineBasicBlock *BB) const {
108 switch (MI.getOpcode()) {
109 default:
111 case Mips::SelBeqZ:
112 return emitSel16(Mips::BeqzRxImm16, MI, BB);
113 case Mips::SelBneZ:
114 return emitSel16(Mips::BnezRxImm16, MI, BB);
115 case Mips::SelTBteqZCmpi:
116 return emitSeliT16(Mips::Bteqz16, Mips::CmpiRxImmX16, MI, BB);
117 case Mips::SelTBteqZSlti:
118 return emitSeliT16(Mips::Bteqz16, Mips::SltiRxImmX16, MI, BB);
119 case Mips::SelTBteqZSltiu:
120 return emitSeliT16(Mips::Bteqz16, Mips::SltiuRxImmX16, MI, BB);
121 case Mips::SelTBtneZCmpi:
122 return emitSeliT16(Mips::Btnez16, Mips::CmpiRxImmX16, MI, BB);
123 case Mips::SelTBtneZSlti:
124 return emitSeliT16(Mips::Btnez16, Mips::SltiRxImmX16, MI, BB);
125 case Mips::SelTBtneZSltiu:
126 return emitSeliT16(Mips::Btnez16, Mips::SltiuRxImmX16, MI, BB);
127 case Mips::SelTBteqZCmp:
128 return emitSelT16(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);
129 case Mips::SelTBteqZSlt:
130 return emitSelT16(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);
131 case Mips::SelTBteqZSltu:
132 return emitSelT16(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);
133 case Mips::SelTBtneZCmp:
134 return emitSelT16(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);
135 case Mips::SelTBtneZSlt:
136 return emitSelT16(Mips::Btnez16, Mips::SltRxRy16, MI, BB);
137 case Mips::SelTBtneZSltu:
138 return emitSelT16(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);
139 case Mips::BteqzT8CmpX16:
140 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);
141 case Mips::BteqzT8SltX16:
142 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);
143 case Mips::BteqzT8SltuX16:
144 // TBD: figure out a way to get this or remove the instruction
145 // altogether.
146 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);
147 case Mips::BtnezT8CmpX16:
148 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);
149 case Mips::BtnezT8SltX16:
150 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltRxRy16, MI, BB);
151 case Mips::BtnezT8SltuX16:
152 // TBD: figure out a way to get this or remove the instruction
153 // altogether.
154 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);
155 case Mips::BteqzT8CmpiX16: return emitFEXT_T8I8I16_ins(
156 Mips::Bteqz16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);
157 case Mips::BteqzT8SltiX16: return emitFEXT_T8I8I16_ins(
158 Mips::Bteqz16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);
159 case Mips::BteqzT8SltiuX16: return emitFEXT_T8I8I16_ins(
160 Mips::Bteqz16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);
161 case Mips::BtnezT8CmpiX16: return emitFEXT_T8I8I16_ins(
162 Mips::Btnez16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);
163 case Mips::BtnezT8SltiX16: return emitFEXT_T8I8I16_ins(
164 Mips::Btnez16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);
165 case Mips::BtnezT8SltiuX16: return emitFEXT_T8I8I16_ins(
166 Mips::Btnez16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);
167 break;
168 case Mips::SltCCRxRy16:
169 return emitFEXT_CCRX16_ins(Mips::SltRxRy16, MI, BB);
170 break;
171 case Mips::SltiCCRxImmX16:
172 return emitFEXT_CCRXI16_ins
173 (Mips::SltiRxImm16, Mips::SltiRxImmX16, MI, BB);
174 case Mips::SltiuCCRxImmX16:
175 return emitFEXT_CCRXI16_ins
176 (Mips::SltiuRxImm16, Mips::SltiuRxImmX16, MI, BB);
177 case Mips::SltuCCRxRy16:
178 return emitFEXT_CCRX16_ins
179 (Mips::SltuRxRy16, MI, BB);
180 }
181}
182
183bool Mips16TargetLowering::isEligibleForTailCallOptimization(
184 const CCState &CCInfo, unsigned NextStackOffset,
185 const MipsFunctionInfo &FI) const {
186 // No tail call optimization for mips16.
187 return false;
188}
189
190//
191// The Mips16 hard float is a crazy quilt inherited from gcc. I have a much
192// cleaner way to do all of this but it will have to wait until the traditional
193// gcc mechanism is completed.
194//
195// For Pic, in order for Mips16 code to call Mips32 code which according the abi
196// have either arguments or returned values placed in floating point registers,
197// we use a set of helper functions. (This includes functions which return type
198// complex which on Mips are returned in a pair of floating point registers).
199//
200// This is an encoding that we inherited from gcc.
201// In Mips traditional O32, N32 ABI, floating point numbers are passed in
202// floating point argument registers 1,2 only when the first and optionally
203// the second arguments are float (sf) or double (df).
204// For Mips16 we are only concerned with the situations where floating point
205// arguments are being passed in floating point registers by the ABI, because
206// Mips16 mode code cannot execute floating point instructions to load those
207// values and hence helper functions are needed.
208// The possibilities are (), (sf), (sf, sf), (sf, df), (df), (df, sf), (df, df)
209// the helper function suffixs for these are:
210// 0, 1, 5, 9, 2, 6, 10
211// this suffix can then be calculated as follows:
212// for a given argument Arg:
213// Arg1x, Arg2x = 1 : Arg is sf
214// 2 : Arg is df
215// 0: Arg is neither sf or df
216// So this stub is the string for number Arg1x + Arg2x*4.
217// However not all numbers between 0 and 10 are possible, we check anyway and
218// assert if the impossible exists.
219//
220
221unsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber
222 (ArgListTy &Args) const {
223 unsigned int resultNum = 0;
224 if (Args.size() >= 1) {
225 Type *t = Args[0].Ty;
226 if (t->isFloatTy()) {
227 resultNum = 1;
228 }
229 else if (t->isDoubleTy()) {
230 resultNum = 2;
231 }
232 }
233 if (resultNum) {
234 if (Args.size() >=2) {
235 Type *t = Args[1].Ty;
236 if (t->isFloatTy()) {
237 resultNum += 4;
238 }
239 else if (t->isDoubleTy()) {
240 resultNum += 8;
241 }
242 }
243 }
244 return resultNum;
245}
246
247//
248// Prefixes are attached to stub numbers depending on the return type.
249// return type: float sf_
250// double df_
251// single complex sc_
252// double complext dc_
253// others NO PREFIX
254//
255//
256// The full name of a helper function is__mips16_call_stub +
257// return type dependent prefix + stub number
258//
259// FIXME: This is something that probably should be in a different source file
260// and perhaps done differently but my main purpose is to not waste runtime
261// on something that we can enumerate in the source. Another possibility is
262// to have a python script to generate these mapping tables. This will do
263// for now. There are a whole series of helper function mapping arrays, one
264// for each return type class as outlined above. There there are 11 possible
265// entries. Ones with 0 are ones which should never be selected.
266//
267// All the arrays are similar except for ones which return neither
268// sf, df, sc, dc, in which we only care about ones which have sf or df as a
269// first parameter.
270//
271#define P_ "__mips16_call_stub_"
272#define MAX_STUB_NUMBER 10
273#define T1 P "1", P "2", 0, 0, P "5", P "6", 0, 0, P "9", P "10"
274#define T P "0" , T1
275#define P P_
276static char const * vMips16Helper[MAX_STUB_NUMBER+1] =
277 {nullptr, T1 };
278#undef P
279#define P P_ "sf_"
280static char const * sfMips16Helper[MAX_STUB_NUMBER+1] =
281 { T };
282#undef P
283#define P P_ "df_"
284static char const * dfMips16Helper[MAX_STUB_NUMBER+1] =
285 { T };
286#undef P
287#define P P_ "sc_"
288static char const * scMips16Helper[MAX_STUB_NUMBER+1] =
289 { T };
290#undef P
291#define P P_ "dc_"
292static char const * dcMips16Helper[MAX_STUB_NUMBER+1] =
293 { T };
294#undef P
295#undef P_
296
297
298const char* Mips16TargetLowering::
299 getMips16HelperFunction
300 (Type* RetTy, ArgListTy &Args, bool &needHelper) const {
301 const unsigned int stubNum = getMips16HelperFunctionStubNumber(Args);
302#ifndef NDEBUG
303 const unsigned int maxStubNum = 10;
304 assert(stubNum <= maxStubNum);
305 const bool validStubNum[maxStubNum+1] =
306 {true, true, true, false, false, true, true, false, false, true, true};
307 assert(validStubNum[stubNum]);
308#endif
309 const char *result;
310 if (RetTy->isFloatTy()) {
311 result = sfMips16Helper[stubNum];
312 }
313 else if (RetTy ->isDoubleTy()) {
314 result = dfMips16Helper[stubNum];
315 } else if (StructType *SRetTy = dyn_cast<StructType>(RetTy)) {
316 // check if it's complex
317 if (SRetTy->getNumElements() == 2) {
318 if ((SRetTy->getElementType(0)->isFloatTy()) &&
319 (SRetTy->getElementType(1)->isFloatTy())) {
320 result = scMips16Helper[stubNum];
321 } else if ((SRetTy->getElementType(0)->isDoubleTy()) &&
322 (SRetTy->getElementType(1)->isDoubleTy())) {
323 result = dcMips16Helper[stubNum];
324 } else {
325 llvm_unreachable("Uncovered condition");
326 }
327 } else {
328 llvm_unreachable("Uncovered condition");
329 }
330 } else {
331 if (stubNum == 0) {
332 needHelper = false;
333 return "";
334 }
335 result = vMips16Helper[stubNum];
336 }
337 needHelper = true;
338 return result;
339}
340
342 // FIXME: Use getSupportedLibcallImpl instead of blindly parsing the name.
343 iota_range<RTLIB::LibcallImpl> ParsedLibcalls =
345 return !ParsedLibcalls.empty() &&
347 *ParsedLibcalls.begin());
348}
349
350void Mips16TargetLowering::getOpndList(
352 std::deque<std::pair<unsigned, SDValue>> &RegsToPass, bool IsPICCall,
353 bool GlobalOrExternal, bool LocalLinkage, bool IsCallReloc,
354 CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const {
355 SelectionDAG &DAG = CLI.DAG;
357 MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
358 const char* Mips16HelperFunction = nullptr;
359 bool NeedMips16Helper = false;
360
361 if (Subtarget.inMips16HardFloat()) {
362 //
363 // currently we don't have symbols tagged with the mips16 or mips32
364 // qualifier so we will assume that we don't know what kind it is.
365 // and generate the helper
366 //
367 bool LookupHelper = true;
368 if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) {
369 if (isMips16HardFloatLibcall(S->getSymbol()))
370 LookupHelper = false;
371 else {
372 const char *Symbol = S->getSymbol();
373 Mips16IntrinsicHelperType IntrinsicFind = { Symbol, "" };
374 const Mips16HardFloatInfo::FuncSignature *Signature =
376 if (!IsPICCall && Signature &&
377 FuncInfo->StubsNeeded.try_emplace(Symbol, Signature).second) {
378 //
379 // S2 is normally saved if the stub is for a function which
380 // returns a float or double value and is not otherwise. This is
381 // because more work is required after the function the stub
382 // is calling completes, and so the stub cannot directly return
383 // and the stub has no stack space to store the return address so
384 // S2 is used for that purpose.
385 // In order to take advantage of not saving S2, we need to also
386 // optimize the call in the stub and this requires some further
387 // functionality in MipsAsmPrinter which we don't have yet.
388 // So for now we always save S2. The optimization will be done
389 // in a follow-on patch.
390 //
391 if (true || (Signature->RetSig != Mips16HardFloatInfo::NoFPRet))
392 FuncInfo->setSaveS2();
393 }
394 // one more look at list of intrinsics
395 const Mips16IntrinsicHelperType *Helper =
397 if (Helper != std::end(Mips16IntrinsicHelper) &&
398 *Helper == IntrinsicFind) {
399 Mips16HelperFunction = Helper->Helper;
400 NeedMips16Helper = true;
401 LookupHelper = false;
402 }
403
404 }
405 } else if (GlobalAddressSDNode *G =
406 dyn_cast<GlobalAddressSDNode>(CLI.Callee)) {
407
408 if (isMips16HardFloatLibcall(G->getGlobal()->getName()))
409 LookupHelper = false;
410 }
411 if (LookupHelper)
412 Mips16HelperFunction =
413 getMips16HelperFunction(CLI.RetTy, CLI.getArgs(), NeedMips16Helper);
414 }
415
416 SDValue JumpTarget = Callee;
417
418 // T9 should contain the address of the callee function if
419 // -relocation-model=pic or it is an indirect call.
420 if (IsPICCall || !GlobalOrExternal) {
421 unsigned V0Reg = Mips::V0;
422 if (NeedMips16Helper) {
423 RegsToPass.push_front(std::make_pair(V0Reg, Callee));
424 JumpTarget = DAG.getExternalSymbol(Mips16HelperFunction,
426 ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(JumpTarget);
427 JumpTarget = getAddrGlobal(S, CLI.DL, JumpTarget.getValueType(), DAG,
428 MipsII::MO_GOT, Chain,
429 FuncInfo->callPtrInfo(MF, S->getSymbol()));
430 } else
431 RegsToPass.push_front(std::make_pair((unsigned)Mips::T9, Callee));
432 }
433
434 Ops.push_back(JumpTarget);
435
436 MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal,
437 LocalLinkage, IsCallReloc, CLI, Callee,
438 Chain);
439}
440
442Mips16TargetLowering::emitSel16(unsigned Opc, MachineInstr &MI,
443 MachineBasicBlock *BB) const {
444 if (Subtarget.getCLOpts().mips16_dont_expand_cond_pseudo)
445 return BB;
446 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
447 DebugLoc DL = MI.getDebugLoc();
448 // To "insert" a SELECT_CC instruction, we actually have to insert the
449 // diamond control-flow pattern. The incoming instruction knows the
450 // destination vreg to set, the condition code register to branch on, the
451 // true/false values to select between, and a branch opcode to use.
452 const BasicBlock *LLVM_BB = BB->getBasicBlock();
454
455 // thisMBB:
456 // ...
457 // TrueVal = ...
458 // setcc r1, r2, r3
459 // bNE r1, r0, copy1MBB
460 // fallthrough --> copy0MBB
461 MachineBasicBlock *thisMBB = BB;
462 MachineFunction *F = BB->getParent();
463 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
464 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
465 F->insert(It, copy0MBB);
466 F->insert(It, sinkMBB);
467
468 // Transfer the remainder of BB and its successor edges to sinkMBB.
469 sinkMBB->splice(sinkMBB->begin(), BB,
470 std::next(MachineBasicBlock::iterator(MI)), BB->end());
472
473 // Next, add the true and fallthrough blocks as its successors.
474 BB->addSuccessor(copy0MBB);
475 BB->addSuccessor(sinkMBB);
476
477 BuildMI(BB, DL, TII->get(Opc))
478 .addReg(MI.getOperand(3).getReg())
479 .addMBB(sinkMBB);
480
481 // copy0MBB:
482 // %FalseValue = ...
483 // # fallthrough to sinkMBB
484 BB = copy0MBB;
485
486 // Update machine-CFG edges
487 BB->addSuccessor(sinkMBB);
488
489 // sinkMBB:
490 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
491 // ...
492 BB = sinkMBB;
493
494 BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
495 .addReg(MI.getOperand(1).getReg())
496 .addMBB(thisMBB)
497 .addReg(MI.getOperand(2).getReg())
498 .addMBB(copy0MBB);
499
500 MI.eraseFromParent(); // The pseudo instruction is gone now.
501 return BB;
502}
503
505Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr &MI,
506 MachineBasicBlock *BB) const {
507 if (Subtarget.getCLOpts().mips16_dont_expand_cond_pseudo)
508 return BB;
509 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
510 DebugLoc DL = MI.getDebugLoc();
511 // To "insert" a SELECT_CC instruction, we actually have to insert the
512 // diamond control-flow pattern. The incoming instruction knows the
513 // destination vreg to set, the condition code register to branch on, the
514 // true/false values to select between, and a branch opcode to use.
515 const BasicBlock *LLVM_BB = BB->getBasicBlock();
517
518 // thisMBB:
519 // ...
520 // TrueVal = ...
521 // setcc r1, r2, r3
522 // bNE r1, r0, copy1MBB
523 // fallthrough --> copy0MBB
524 MachineBasicBlock *thisMBB = BB;
525 MachineFunction *F = BB->getParent();
526 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
527 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
528 F->insert(It, copy0MBB);
529 F->insert(It, sinkMBB);
530
531 // Transfer the remainder of BB and its successor edges to sinkMBB.
532 sinkMBB->splice(sinkMBB->begin(), BB,
533 std::next(MachineBasicBlock::iterator(MI)), BB->end());
535
536 // Next, add the true and fallthrough blocks as its successors.
537 BB->addSuccessor(copy0MBB);
538 BB->addSuccessor(sinkMBB);
539
540 BuildMI(BB, DL, TII->get(Opc2))
541 .addReg(MI.getOperand(3).getReg())
542 .addReg(MI.getOperand(4).getReg());
543 BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);
544
545 // copy0MBB:
546 // %FalseValue = ...
547 // # fallthrough to sinkMBB
548 BB = copy0MBB;
549
550 // Update machine-CFG edges
551 BB->addSuccessor(sinkMBB);
552
553 // sinkMBB:
554 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
555 // ...
556 BB = sinkMBB;
557
558 BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
559 .addReg(MI.getOperand(1).getReg())
560 .addMBB(thisMBB)
561 .addReg(MI.getOperand(2).getReg())
562 .addMBB(copy0MBB);
563
564 MI.eraseFromParent(); // The pseudo instruction is gone now.
565 return BB;
566
567}
568
570Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2,
572 MachineBasicBlock *BB) const {
573 if (Subtarget.getCLOpts().mips16_dont_expand_cond_pseudo)
574 return BB;
575 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
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 .addImm(MI.getOperand(4).getImm());
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::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc,
638 MachineBasicBlock *BB) const {
639 if (Subtarget.getCLOpts().mips16_dont_expand_cond_pseudo)
640 return BB;
641 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
642 Register regX = MI.getOperand(0).getReg();
643 Register regY = MI.getOperand(1).getReg();
644 MachineBasicBlock *target = MI.getOperand(2).getMBB();
645 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc))
646 .addReg(regX)
647 .addReg(regY);
648 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);
649 MI.eraseFromParent(); // The pseudo instruction is gone now.
650 return BB;
651}
652
653MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins(
654 unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned,
655 MachineInstr &MI, MachineBasicBlock *BB) const {
656 if (Subtarget.getCLOpts().mips16_dont_expand_cond_pseudo)
657 return BB;
658 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
659 Register regX = MI.getOperand(0).getReg();
660 int64_t imm = MI.getOperand(1).getImm();
661 MachineBasicBlock *target = MI.getOperand(2).getMBB();
662 unsigned CmpOpc;
663 if (isUInt<8>(imm))
664 CmpOpc = CmpiOpc;
665 else if ((!ImmSigned && isUInt<16>(imm)) ||
666 (ImmSigned && isInt<16>(imm)))
667 CmpOpc = CmpiXOpc;
668 else
669 llvm_unreachable("immediate field not usable");
670 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc)).addReg(regX).addImm(imm);
671 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);
672 MI.eraseFromParent(); // The pseudo instruction is gone now.
673 return BB;
674}
675
677 (unsigned shortOp, unsigned longOp, int64_t Imm) {
678 if (isUInt<8>(Imm))
679 return shortOp;
680 else if (isInt<16>(Imm))
681 return longOp;
682 else
683 llvm_unreachable("immediate field not usable");
684}
685
687Mips16TargetLowering::emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr &MI,
688 MachineBasicBlock *BB) const {
689 if (Subtarget.getCLOpts().mips16_dont_expand_cond_pseudo)
690 return BB;
691 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
692 Register CC = MI.getOperand(0).getReg();
693 Register regX = MI.getOperand(1).getReg();
694 Register regY = MI.getOperand(2).getReg();
695 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc))
696 .addReg(regX)
697 .addReg(regY);
698 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)
699 .addReg(Mips::T8);
700 MI.eraseFromParent(); // The pseudo instruction is gone now.
701 return BB;
702}
703
705Mips16TargetLowering::emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc,
707 MachineBasicBlock *BB) const {
708 if (Subtarget.getCLOpts().mips16_dont_expand_cond_pseudo)
709 return BB;
710 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
711 Register CC = MI.getOperand(0).getReg();
712 Register regX = MI.getOperand(1).getReg();
713 int64_t Imm = MI.getOperand(2).getImm();
714 unsigned SltOpc = Mips16WhichOp8uOr16simm(SltiOpc, SltiXOpc, Imm);
715 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc)).addReg(regX).addImm(Imm);
716 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)
717 .addReg(Mips::T8);
718 MI.eraseFromParent(); // The pseudo instruction is gone now.
719 return BB;
720
721}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned Imm
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define G(x, y, z)
Definition MD5.cpp:55
Promote Memory to Register
Definition Mem2Reg.cpp:110
static char const * vMips16Helper[MAX_STUB_NUMBER+1]
#define T
static char const * dcMips16Helper[MAX_STUB_NUMBER+1]
static char const * dfMips16Helper[MAX_STUB_NUMBER+1]
static const Mips16IntrinsicHelperType Mips16IntrinsicHelper[]
#define MAX_STUB_NUMBER
static char const * sfMips16Helper[MAX_STUB_NUMBER+1]
#define T1
static unsigned Mips16WhichOp8uOr16simm(unsigned shortOp, unsigned longOp, int64_t Imm)
static char const * scMips16Helper[MAX_STUB_NUMBER+1]
static bool isMips16HardFloatLibcall(StringRef Name)
Value * RHS
CCState - This class holds information needed while lowering arguments and return values.
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...
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
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 '...
MachineInstrBundleIterator< MachineInstr > iterator
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
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
const MipsRegisterInfo * getRegisterInfo() const override
static const RTLIB::LibcallImpl HardFloatLibCalls[34]
SDValue getAddrGlobal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flag, SDValue Chain, const MachinePointerInfo &PtrInfo) const
MipsTargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI)
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 LocalLinkage, 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
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.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
MachineFunction & getMachineFunction() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
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...
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition Type.h:155
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition Type.h:158
self_iterator getIterator()
Definition ilist_node.h:123
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:797
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
FuncSignature const * findFuncSignature(const char *name)
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
Definition APSInt.h:360
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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:2055
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
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:2068
@ Fast
Assign the register banks as fast as possible (default).
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
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
static iota_range< RTLIB::LibcallImpl > lookupLibcallImplName(StringRef Name)
Check if a function name is a recognized runtime call of any kind.
constexpr auto begin() const
Definition Sequence.h:317
constexpr bool empty() const
Definition Sequence.h:315