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"
13#include "MCTargetDesc/MipsBaseInfo.h"
14#include "Mips16HardFloatInfo.h"
15#include "MipsMachineFunction.h"
16#include "MipsRegisterInfo.h"
17#include "MipsTargetMachine.h"
18#include "llvm/CodeGen/MachineInstrBuilder.h"
19#include "llvm/CodeGen/TargetInstrInfo.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(s1: Name, s2: RHS.Name) < 0;
32 }
33 bool operator==(const Mips16IntrinsicHelperType &RHS) const {
34 return std::strcmp(s1: Name, s2: RHS.Name) == 0;
35 }
36};
37} // namespace
38
39static const Mips16IntrinsicHelperType Mips16IntrinsicHelper[] = {
40 {.Name: "__fixunsdfsi", .Helper: "__mips16_call_stub_2" },
41 {.Name: "ceil", .Helper: "__mips16_call_stub_df_2"},
42 {.Name: "ceilf", .Helper: "__mips16_call_stub_sf_1"},
43 {.Name: "copysign", .Helper: "__mips16_call_stub_df_10"},
44 {.Name: "copysignf", .Helper: "__mips16_call_stub_sf_5"},
45 {.Name: "cos", .Helper: "__mips16_call_stub_df_2"},
46 {.Name: "cosf", .Helper: "__mips16_call_stub_sf_1"},
47 {.Name: "exp2", .Helper: "__mips16_call_stub_df_2"},
48 {.Name: "exp2f", .Helper: "__mips16_call_stub_sf_1"},
49 {.Name: "floor", .Helper: "__mips16_call_stub_df_2"},
50 {.Name: "floorf", .Helper: "__mips16_call_stub_sf_1"},
51 {.Name: "log2", .Helper: "__mips16_call_stub_df_2"},
52 {.Name: "log2f", .Helper: "__mips16_call_stub_sf_1"},
53 {.Name: "nearbyint", .Helper: "__mips16_call_stub_df_2"},
54 {.Name: "nearbyintf", .Helper: "__mips16_call_stub_sf_1"},
55 {.Name: "rint", .Helper: "__mips16_call_stub_df_2"},
56 {.Name: "rintf", .Helper: "__mips16_call_stub_sf_1"},
57 {.Name: "sin", .Helper: "__mips16_call_stub_df_2"},
58 {.Name: "sinf", .Helper: "__mips16_call_stub_sf_1"},
59 {.Name: "sqrt", .Helper: "__mips16_call_stub_df_2"},
60 {.Name: "sqrtf", .Helper: "__mips16_call_stub_sf_1"},
61 {.Name: "trunc", .Helper: "__mips16_call_stub_df_2"},
62 {.Name: "truncf", .Helper: "__mips16_call_stub_sf_1"},
63};
64
65Mips16TargetLowering::Mips16TargetLowering(const MipsTargetMachine &TM,
66 const MipsSubtarget &STI)
67 : MipsTargetLowering(TM, STI) {
68
69 // Set up the register classes
70 addRegisterClass(VT: MVT::i32, RC: &Mips::CPU16RegsRegClass);
71
72 setOperationAction(Op: ISD::ATOMIC_FENCE, VT: MVT::Other, Action: LibCall);
73 setOperationAction(Op: ISD::ATOMIC_CMP_SWAP, VT: MVT::i32, Action: LibCall);
74 setOperationAction(Op: ISD::ATOMIC_SWAP, VT: MVT::i32, Action: LibCall);
75 setOperationAction(Op: ISD::ATOMIC_LOAD_ADD, VT: MVT::i32, Action: LibCall);
76 setOperationAction(Op: ISD::ATOMIC_LOAD_SUB, VT: MVT::i32, Action: LibCall);
77 setOperationAction(Op: ISD::ATOMIC_LOAD_AND, VT: MVT::i32, Action: LibCall);
78 setOperationAction(Op: ISD::ATOMIC_LOAD_OR, VT: MVT::i32, Action: LibCall);
79 setOperationAction(Op: ISD::ATOMIC_LOAD_XOR, VT: MVT::i32, Action: LibCall);
80 setOperationAction(Op: ISD::ATOMIC_LOAD_NAND, VT: MVT::i32, Action: LibCall);
81 setOperationAction(Op: ISD::ATOMIC_LOAD_MIN, VT: MVT::i32, Action: LibCall);
82 setOperationAction(Op: ISD::ATOMIC_LOAD_MAX, VT: MVT::i32, Action: LibCall);
83 setOperationAction(Op: ISD::ATOMIC_LOAD_UMIN, VT: MVT::i32, Action: LibCall);
84 setOperationAction(Op: ISD::ATOMIC_LOAD_UMAX, VT: MVT::i32, Action: LibCall);
85
86 setOperationAction(Op: ISD::ROTR, VT: MVT::i32, Action: Expand);
87 setOperationAction(Op: ISD::ROTR, VT: MVT::i64, Action: Expand);
88 setOperationAction(Op: ISD::BSWAP, VT: MVT::i32, Action: Expand);
89 setOperationAction(Op: ISD::BSWAP, VT: MVT::i64, Action: Expand);
90
91 computeRegisterProperties(TRI: STI.getRegisterInfo());
92}
93
94const MipsTargetLowering *
95llvm::createMips16TargetLowering(const MipsTargetMachine &TM,
96 const MipsSubtarget &STI) {
97 return new Mips16TargetLowering(TM, STI);
98}
99
100bool Mips16TargetLowering::allowsMisalignedMemoryAccesses(
101 EVT VT, unsigned, Align, MachineMemOperand::Flags, unsigned *Fast) const {
102 return false;
103}
104
105MachineBasicBlock *
106Mips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
107 MachineBasicBlock *BB) const {
108 switch (MI.getOpcode()) {
109 default:
110 return MipsTargetLowering::EmitInstrWithCustomInserter(MI, MBB: BB);
111 case Mips::SelBeqZ:
112 return emitSel16(Opc: Mips::BeqzRxImm16, MI, BB);
113 case Mips::SelBneZ:
114 return emitSel16(Opc: Mips::BnezRxImm16, MI, BB);
115 case Mips::SelTBteqZCmpi:
116 return emitSeliT16(Opc1: Mips::Bteqz16, Opc2: Mips::CmpiRxImmX16, MI, BB);
117 case Mips::SelTBteqZSlti:
118 return emitSeliT16(Opc1: Mips::Bteqz16, Opc2: Mips::SltiRxImmX16, MI, BB);
119 case Mips::SelTBteqZSltiu:
120 return emitSeliT16(Opc1: Mips::Bteqz16, Opc2: Mips::SltiuRxImmX16, MI, BB);
121 case Mips::SelTBtneZCmpi:
122 return emitSeliT16(Opc1: Mips::Btnez16, Opc2: Mips::CmpiRxImmX16, MI, BB);
123 case Mips::SelTBtneZSlti:
124 return emitSeliT16(Opc1: Mips::Btnez16, Opc2: Mips::SltiRxImmX16, MI, BB);
125 case Mips::SelTBtneZSltiu:
126 return emitSeliT16(Opc1: Mips::Btnez16, Opc2: Mips::SltiuRxImmX16, MI, BB);
127 case Mips::SelTBteqZCmp:
128 return emitSelT16(Opc1: Mips::Bteqz16, Opc2: Mips::CmpRxRy16, MI, BB);
129 case Mips::SelTBteqZSlt:
130 return emitSelT16(Opc1: Mips::Bteqz16, Opc2: Mips::SltRxRy16, MI, BB);
131 case Mips::SelTBteqZSltu:
132 return emitSelT16(Opc1: Mips::Bteqz16, Opc2: Mips::SltuRxRy16, MI, BB);
133 case Mips::SelTBtneZCmp:
134 return emitSelT16(Opc1: Mips::Btnez16, Opc2: Mips::CmpRxRy16, MI, BB);
135 case Mips::SelTBtneZSlt:
136 return emitSelT16(Opc1: Mips::Btnez16, Opc2: Mips::SltRxRy16, MI, BB);
137 case Mips::SelTBtneZSltu:
138 return emitSelT16(Opc1: Mips::Btnez16, Opc2: Mips::SltuRxRy16, MI, BB);
139 case Mips::BteqzT8CmpX16:
140 return emitFEXT_T8I816_ins(BtOpc: Mips::Bteqz16, CmpOpc: Mips::CmpRxRy16, MI, BB);
141 case Mips::BteqzT8SltX16:
142 return emitFEXT_T8I816_ins(BtOpc: Mips::Bteqz16, CmpOpc: 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(BtOpc: Mips::Bteqz16, CmpOpc: Mips::SltuRxRy16, MI, BB);
147 case Mips::BtnezT8CmpX16:
148 return emitFEXT_T8I816_ins(BtOpc: Mips::Btnez16, CmpOpc: Mips::CmpRxRy16, MI, BB);
149 case Mips::BtnezT8SltX16:
150 return emitFEXT_T8I816_ins(BtOpc: Mips::Btnez16, CmpOpc: 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(BtOpc: Mips::Btnez16, CmpOpc: Mips::SltuRxRy16, MI, BB);
155 case Mips::BteqzT8CmpiX16: return emitFEXT_T8I8I16_ins(
156 BtOpc: Mips::Bteqz16, CmpiOpc: Mips::CmpiRxImm16, CmpiXOpc: Mips::CmpiRxImmX16, ImmSigned: false, MI, BB);
157 case Mips::BteqzT8SltiX16: return emitFEXT_T8I8I16_ins(
158 BtOpc: Mips::Bteqz16, CmpiOpc: Mips::SltiRxImm16, CmpiXOpc: Mips::SltiRxImmX16, ImmSigned: true, MI, BB);
159 case Mips::BteqzT8SltiuX16: return emitFEXT_T8I8I16_ins(
160 BtOpc: Mips::Bteqz16, CmpiOpc: Mips::SltiuRxImm16, CmpiXOpc: Mips::SltiuRxImmX16, ImmSigned: false, MI, BB);
161 case Mips::BtnezT8CmpiX16: return emitFEXT_T8I8I16_ins(
162 BtOpc: Mips::Btnez16, CmpiOpc: Mips::CmpiRxImm16, CmpiXOpc: Mips::CmpiRxImmX16, ImmSigned: false, MI, BB);
163 case Mips::BtnezT8SltiX16: return emitFEXT_T8I8I16_ins(
164 BtOpc: Mips::Btnez16, CmpiOpc: Mips::SltiRxImm16, CmpiXOpc: Mips::SltiRxImmX16, ImmSigned: true, MI, BB);
165 case Mips::BtnezT8SltiuX16: return emitFEXT_T8I8I16_ins(
166 BtOpc: Mips::Btnez16, CmpiOpc: Mips::SltiuRxImm16, CmpiXOpc: Mips::SltiuRxImmX16, ImmSigned: false, MI, BB);
167 break;
168 case Mips::SltCCRxRy16:
169 return emitFEXT_CCRX16_ins(SltOpc: Mips::SltRxRy16, MI, BB);
170 break;
171 case Mips::SltiCCRxImmX16:
172 return emitFEXT_CCRXI16_ins
173 (SltiOpc: Mips::SltiRxImm16, SltiXOpc: Mips::SltiRxImmX16, MI, BB);
174 case Mips::SltiuCCRxImmX16:
175 return emitFEXT_CCRXI16_ins
176 (SltiOpc: Mips::SltiuRxImm16, SltiXOpc: Mips::SltiuRxImmX16, MI, BB);
177 case Mips::SltuCCRxRy16:
178 return emitFEXT_CCRX16_ins
179 (SltOpc: 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>(Val: RetTy)) {
316 // check if it's complex
317 if (SRetTy->getNumElements() == 2) {
318 if ((SRetTy->getElementType(N: 0)->isFloatTy()) &&
319 (SRetTy->getElementType(N: 1)->isFloatTy())) {
320 result = scMips16Helper[stubNum];
321 } else if ((SRetTy->getElementType(N: 0)->isDoubleTy()) &&
322 (SRetTy->getElementType(N: 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
341static bool isMips16HardFloatLibcall(StringRef Name) {
342 // FIXME: Use getSupportedLibcallImpl instead of blindly parsing the name.
343 iota_range<RTLIB::LibcallImpl> ParsedLibcalls =
344 RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName(Name);
345 return !ParsedLibcalls.empty() &&
346 binary_search(Range: MipsSubtarget::HardFloatLibCalls,
347 Value: *ParsedLibcalls.begin());
348}
349
350void Mips16TargetLowering::getOpndList(
351 SmallVectorImpl<SDValue> &Ops,
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;
356 MachineFunction &MF = DAG.getMachineFunction();
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>(Val&: CLI.Callee)) {
369 if (isMips16HardFloatLibcall(Name: S->getSymbol()))
370 LookupHelper = false;
371 else {
372 const char *Symbol = S->getSymbol();
373 Mips16IntrinsicHelperType IntrinsicFind = { .Name: Symbol, .Helper: "" };
374 const Mips16HardFloatInfo::FuncSignature *Signature =
375 Mips16HardFloatInfo::findFuncSignature(name: Symbol);
376 if (!IsPICCall && Signature &&
377 FuncInfo->StubsNeeded.try_emplace(k: Symbol, args&: 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 =
396 llvm::lower_bound(Range: Mips16IntrinsicHelper, Value&: IntrinsicFind);
397 if (Helper != std::end(arr: 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>(Val&: CLI.Callee)) {
407
408 if (isMips16HardFloatLibcall(Name: G->getGlobal()->getName()))
409 LookupHelper = false;
410 }
411 if (LookupHelper)
412 Mips16HelperFunction =
413 getMips16HelperFunction(RetTy: CLI.RetTy, Args&: CLI.getArgs(), needHelper&: 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::R2;
422 if (NeedMips16Helper) {
423 RegsToPass.push_front(x: std::make_pair(x&: V0Reg, y&: Callee));
424 JumpTarget = DAG.getExternalSymbol(Sym: Mips16HelperFunction,
425 VT: getPointerTy(DL: DAG.getDataLayout()));
426 ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(Val&: JumpTarget);
427 JumpTarget = getAddrGlobal(N: S, DL: CLI.DL, Ty: JumpTarget.getValueType(), DAG,
428 Flag: MipsII::MO_GOT, Chain,
429 PtrInfo: FuncInfo->callPtrInfo(MF, ES: S->getSymbol()));
430 } else
431 RegsToPass.push_front(x: std::make_pair(x: (unsigned)Mips::R25, y&: Callee));
432 }
433
434 Ops.push_back(Elt: JumpTarget);
435
436 MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal,
437 LocalLinkage, IsCallReloc, CLI, Callee,
438 Chain);
439}
440
441MachineBasicBlock *
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();
453 MachineFunction::iterator It = ++BB->getIterator();
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(BB: LLVM_BB);
464 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(BB: LLVM_BB);
465 F->insert(MBBI: It, MBB: copy0MBB);
466 F->insert(MBBI: It, MBB: sinkMBB);
467
468 // Transfer the remainder of BB and its successor edges to sinkMBB.
469 sinkMBB->splice(Where: sinkMBB->begin(), Other: BB,
470 From: std::next(x: MachineBasicBlock::iterator(MI)), To: BB->end());
471 sinkMBB->transferSuccessorsAndUpdatePHIs(FromMBB: BB);
472
473 // Next, add the true and fallthrough blocks as its successors.
474 BB->addSuccessor(Succ: copy0MBB);
475 BB->addSuccessor(Succ: sinkMBB);
476
477 BuildMI(BB, MIMD: DL, MCID: TII->get(Opcode: Opc))
478 .addReg(RegNo: MI.getOperand(i: 3).getReg())
479 .addMBB(MBB: sinkMBB);
480
481 // copy0MBB:
482 // %FalseValue = ...
483 // # fallthrough to sinkMBB
484 BB = copy0MBB;
485
486 // Update machine-CFG edges
487 BB->addSuccessor(Succ: sinkMBB);
488
489 // sinkMBB:
490 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
491 // ...
492 BB = sinkMBB;
493
494 BuildMI(BB&: *BB, I: BB->begin(), MIMD: DL, MCID: TII->get(Opcode: Mips::PHI), DestReg: MI.getOperand(i: 0).getReg())
495 .addReg(RegNo: MI.getOperand(i: 1).getReg())
496 .addMBB(MBB: thisMBB)
497 .addReg(RegNo: MI.getOperand(i: 2).getReg())
498 .addMBB(MBB: copy0MBB);
499
500 MI.eraseFromParent(); // The pseudo instruction is gone now.
501 return BB;
502}
503
504MachineBasicBlock *
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();
516 MachineFunction::iterator It = ++BB->getIterator();
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(BB: LLVM_BB);
527 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(BB: LLVM_BB);
528 F->insert(MBBI: It, MBB: copy0MBB);
529 F->insert(MBBI: It, MBB: sinkMBB);
530
531 // Transfer the remainder of BB and its successor edges to sinkMBB.
532 sinkMBB->splice(Where: sinkMBB->begin(), Other: BB,
533 From: std::next(x: MachineBasicBlock::iterator(MI)), To: BB->end());
534 sinkMBB->transferSuccessorsAndUpdatePHIs(FromMBB: BB);
535
536 // Next, add the true and fallthrough blocks as its successors.
537 BB->addSuccessor(Succ: copy0MBB);
538 BB->addSuccessor(Succ: sinkMBB);
539
540 BuildMI(BB, MIMD: DL, MCID: TII->get(Opcode: Opc2))
541 .addReg(RegNo: MI.getOperand(i: 3).getReg())
542 .addReg(RegNo: MI.getOperand(i: 4).getReg());
543 BuildMI(BB, MIMD: DL, MCID: TII->get(Opcode: Opc1)).addMBB(MBB: sinkMBB);
544
545 // copy0MBB:
546 // %FalseValue = ...
547 // # fallthrough to sinkMBB
548 BB = copy0MBB;
549
550 // Update machine-CFG edges
551 BB->addSuccessor(Succ: sinkMBB);
552
553 // sinkMBB:
554 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
555 // ...
556 BB = sinkMBB;
557
558 BuildMI(BB&: *BB, I: BB->begin(), MIMD: DL, MCID: TII->get(Opcode: Mips::PHI), DestReg: MI.getOperand(i: 0).getReg())
559 .addReg(RegNo: MI.getOperand(i: 1).getReg())
560 .addMBB(MBB: thisMBB)
561 .addReg(RegNo: MI.getOperand(i: 2).getReg())
562 .addMBB(MBB: copy0MBB);
563
564 MI.eraseFromParent(); // The pseudo instruction is gone now.
565 return BB;
566
567}
568
569MachineBasicBlock *
570Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2,
571 MachineInstr &MI,
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();
582 MachineFunction::iterator It = ++BB->getIterator();
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(BB: LLVM_BB);
593 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(BB: LLVM_BB);
594 F->insert(MBBI: It, MBB: copy0MBB);
595 F->insert(MBBI: It, MBB: sinkMBB);
596
597 // Transfer the remainder of BB and its successor edges to sinkMBB.
598 sinkMBB->splice(Where: sinkMBB->begin(), Other: BB,
599 From: std::next(x: MachineBasicBlock::iterator(MI)), To: BB->end());
600 sinkMBB->transferSuccessorsAndUpdatePHIs(FromMBB: BB);
601
602 // Next, add the true and fallthrough blocks as its successors.
603 BB->addSuccessor(Succ: copy0MBB);
604 BB->addSuccessor(Succ: sinkMBB);
605
606 BuildMI(BB, MIMD: DL, MCID: TII->get(Opcode: Opc2))
607 .addReg(RegNo: MI.getOperand(i: 3).getReg())
608 .addImm(Val: MI.getOperand(i: 4).getImm());
609 BuildMI(BB, MIMD: DL, MCID: TII->get(Opcode: Opc1)).addMBB(MBB: sinkMBB);
610
611 // copy0MBB:
612 // %FalseValue = ...
613 // # fallthrough to sinkMBB
614 BB = copy0MBB;
615
616 // Update machine-CFG edges
617 BB->addSuccessor(Succ: sinkMBB);
618
619 // sinkMBB:
620 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
621 // ...
622 BB = sinkMBB;
623
624 BuildMI(BB&: *BB, I: BB->begin(), MIMD: DL, MCID: TII->get(Opcode: Mips::PHI), DestReg: MI.getOperand(i: 0).getReg())
625 .addReg(RegNo: MI.getOperand(i: 1).getReg())
626 .addMBB(MBB: thisMBB)
627 .addReg(RegNo: MI.getOperand(i: 2).getReg())
628 .addMBB(MBB: copy0MBB);
629
630 MI.eraseFromParent(); // The pseudo instruction is gone now.
631 return BB;
632
633}
634
635MachineBasicBlock *
636Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc,
637 MachineInstr &MI,
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(i: 0).getReg();
643 Register regY = MI.getOperand(i: 1).getReg();
644 MachineBasicBlock *target = MI.getOperand(i: 2).getMBB();
645 BuildMI(BB&: *BB, I&: MI, MIMD: MI.getDebugLoc(), MCID: TII->get(Opcode: CmpOpc))
646 .addReg(RegNo: regX)
647 .addReg(RegNo: regY);
648 BuildMI(BB&: *BB, I&: MI, MIMD: MI.getDebugLoc(), MCID: TII->get(Opcode: BtOpc)).addMBB(MBB: 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(i: 0).getReg();
660 int64_t imm = MI.getOperand(i: 1).getImm();
661 MachineBasicBlock *target = MI.getOperand(i: 2).getMBB();
662 unsigned CmpOpc;
663 if (isUInt<8>(x: imm))
664 CmpOpc = CmpiOpc;
665 else if ((!ImmSigned && isUInt<16>(x: imm)) ||
666 (ImmSigned && isInt<16>(x: imm)))
667 CmpOpc = CmpiXOpc;
668 else
669 llvm_unreachable("immediate field not usable");
670 BuildMI(BB&: *BB, I&: MI, MIMD: MI.getDebugLoc(), MCID: TII->get(Opcode: CmpOpc)).addReg(RegNo: regX).addImm(Val: imm);
671 BuildMI(BB&: *BB, I&: MI, MIMD: MI.getDebugLoc(), MCID: TII->get(Opcode: BtOpc)).addMBB(MBB: target);
672 MI.eraseFromParent(); // The pseudo instruction is gone now.
673 return BB;
674}
675
676static unsigned Mips16WhichOp8uOr16simm
677 (unsigned shortOp, unsigned longOp, int64_t Imm) {
678 if (isUInt<8>(x: Imm))
679 return shortOp;
680 else if (isInt<16>(x: Imm))
681 return longOp;
682 else
683 llvm_unreachable("immediate field not usable");
684}
685
686MachineBasicBlock *
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(i: 0).getReg();
693 Register regX = MI.getOperand(i: 1).getReg();
694 Register regY = MI.getOperand(i: 2).getReg();
695 BuildMI(BB&: *BB, I&: MI, MIMD: MI.getDebugLoc(), MCID: TII->get(Opcode: SltOpc))
696 .addReg(RegNo: regX)
697 .addReg(RegNo: regY);
698 BuildMI(BB&: *BB, I&: MI, MIMD: MI.getDebugLoc(), MCID: TII->get(Opcode: Mips::MoveR3216), DestReg: CC)
699 .addReg(RegNo: Mips::R24);
700 MI.eraseFromParent(); // The pseudo instruction is gone now.
701 return BB;
702}
703
704MachineBasicBlock *
705Mips16TargetLowering::emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc,
706 MachineInstr &MI,
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(i: 0).getReg();
712 Register regX = MI.getOperand(i: 1).getReg();
713 int64_t Imm = MI.getOperand(i: 2).getImm();
714 unsigned SltOpc = Mips16WhichOp8uOr16simm(shortOp: SltiOpc, longOp: SltiXOpc, Imm);
715 BuildMI(BB&: *BB, I&: MI, MIMD: MI.getDebugLoc(), MCID: TII->get(Opcode: SltOpc)).addReg(RegNo: regX).addImm(Val: Imm);
716 BuildMI(BB&: *BB, I&: MI, MIMD: MI.getDebugLoc(), MCID: TII->get(Opcode: Mips::MoveR3216), DestReg: CC)
717 .addReg(RegNo: Mips::R24);
718 MI.eraseFromParent(); // The pseudo instruction is gone now.
719 return BB;
720
721}
722