24#define DEBUG_TYPE "mips-lower"
27 "mips16-dont-expand-cond-pseudo",
29 cl::desc(
"Don't expand conditional move related "
30 "pseudos for Mips 16"),
35 RTLIB::Libcall Libcall;
36 RTLIB::LibcallImpl Impl;
39 bool operator<(
const Mips16Libcall &RHS)
const {
40 return std::strcmp(Name,
RHS.Name) < 0;
44struct Mips16IntrinsicHelperType{
48 bool operator<(
const Mips16IntrinsicHelperType &RHS)
const {
49 return std::strcmp(Name,
RHS.Name) < 0;
51 bool operator==(
const Mips16IntrinsicHelperType &RHS)
const {
52 return std::strcmp(Name,
RHS.Name) == 0;
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,
93 {RTLIB::UNKNOWN_LIBCALL, RTLIB::impl___mips16_ret_df,
95 {RTLIB::UNKNOWN_LIBCALL, RTLIB::impl___mips16_ret_sc,
97 {RTLIB::UNKNOWN_LIBCALL, RTLIB::impl___mips16_ret_sf,
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"}};
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"},
140 setMips16HardFloatLibCalls();
178 switch (
MI.getOpcode()) {
182 return emitSel16(Mips::BeqzRxImm16,
MI, BB);
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:
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:
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);
238 case Mips::SltCCRxRy16:
239 return emitFEXT_CCRX16_ins(Mips::SltRxRy16,
MI, BB);
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);
253bool Mips16TargetLowering::isEligibleForTailCallOptimization(
254 const CCState &CCInfo,
unsigned NextStackOffset,
260void Mips16TargetLowering::setMips16HardFloatLibCalls() {
263 "Array not sorted!");
300unsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber
301 (ArgListTy &Args)
const {
302 unsigned int resultNum = 0;
303 if (
Args.size() >= 1) {
313 if (
Args.size() >=2) {
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"
377const char* Mips16TargetLowering::
378 getMips16HelperFunction
379 (
Type*
RetTy, ArgListTy &Args,
bool &needHelper)
const {
380 const unsigned int stubNum = getMips16HelperFunctionStubNumber(Args);
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]);
389 if (
RetTy->isFloatTy()) {
392 else if (
RetTy ->isDoubleTy()) {
396 if (SRetTy->getNumElements() == 2) {
397 if ((SRetTy->getElementType(0)->isFloatTy()) &&
398 (SRetTy->getElementType(1)->isFloatTy())) {
400 }
else if ((SRetTy->getElementType(0)->isDoubleTy()) &&
401 (SRetTy->getElementType(1)->isDoubleTy())) {
420void Mips16TargetLowering::
422 std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
423 bool IsPICCall,
bool GlobalOrExternal,
bool InternalLinkage,
424 bool IsCallReloc, CallLoweringInfo &CLI,
SDValue Callee,
429 const char* Mips16HelperFunction =
nullptr;
430 bool NeedMips16Helper =
false;
438 bool LookupHelper =
true;
440 Mips16Libcall
Find = {RTLIB::UNKNOWN_LIBCALL, RTLIB::Unsupported,
444 LookupHelper =
false;
446 const char *
Symbol = S->getSymbol();
447 Mips16IntrinsicHelperType IntrinsicFind = {
Symbol,
"" };
450 if (!IsPICCall && Signature &&
451 FuncInfo->
StubsNeeded.try_emplace(Symbol, Signature).second) {
469 const Mips16IntrinsicHelperType *Helper =
472 *Helper == IntrinsicFind) {
473 Mips16HelperFunction = Helper->Helper;
474 NeedMips16Helper =
true;
475 LookupHelper =
false;
480 dyn_cast<GlobalAddressSDNode>(CLI.Callee)) {
481 Mips16Libcall
Find = {RTLIB::UNKNOWN_LIBCALL, RTLIB::Unsupported,
482 G->getGlobal()->getName().data()};
485 LookupHelper =
false;
488 Mips16HelperFunction =
489 getMips16HelperFunction(CLI.RetTy, CLI.getArgs(), NeedMips16Helper);
496 if (IsPICCall || !GlobalOrExternal) {
497 unsigned V0Reg = Mips::V0;
498 if (NeedMips16Helper) {
499 RegsToPass.push_front(std::make_pair(V0Reg, Callee));
507 RegsToPass.push_front(std::make_pair((
unsigned)Mips::T9, Callee));
513 InternalLinkage, IsCallReloc, CLI, Callee,
541 F->insert(It, copy0MBB);
542 F->insert(It, sinkMBB);
576 MI.eraseFromParent();
581Mips16TargetLowering::emitSelT16(
unsigned Opc1,
unsigned Opc2,
MachineInstr &
MI,
604 F->insert(It, copy0MBB);
605 F->insert(It, sinkMBB);
640 MI.eraseFromParent();
646Mips16TargetLowering::emitSeliT16(
unsigned Opc1,
unsigned Opc2,
670 F->insert(It, copy0MBB);
671 F->insert(It, sinkMBB);
706 MI.eraseFromParent();
712Mips16TargetLowering::emitFEXT_T8I816_ins(
unsigned BtOpc,
unsigned CmpOpc,
725 MI.eraseFromParent();
730 unsigned BtOpc,
unsigned CmpiOpc,
unsigned CmpiXOpc,
bool ImmSigned,
736 int64_t imm =
MI.getOperand(1).getImm();
741 else if ((!ImmSigned && isUInt<16>(imm)) ||
742 (ImmSigned && isInt<16>(imm)))
748 MI.eraseFromParent();
753 (
unsigned shortOp,
unsigned longOp, int64_t Imm) {
756 else if (isInt<16>(Imm))
763Mips16TargetLowering::emitFEXT_CCRX16_ins(
unsigned SltOpc,
MachineInstr &
MI,
776 MI.eraseFromParent();
781Mips16TargetLowering::emitFEXT_CCRXI16_ins(
unsigned SltiOpc,
unsigned SltiXOpc,
789 int64_t
Imm =
MI.getOperand(2).getImm();
794 MI.eraseFromParent();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
const HexagonInstrInfo * TII
static const T * Find(StringRef S, ArrayRef< T > A)
Find KV in array using binary search.
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[]
static char const * sfMips16Helper[MAX_STUB_NUMBER+1]
static const Mips16Libcall HardFloatLibCalls[]
static unsigned Mips16WhichOp8uOr16simm(unsigned shortOp, unsigned longOp, int64_t Imm)
static char const * scMips16Helper[MAX_STUB_NUMBER+1]
LLVM Basic Block Representation.
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...
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.
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.
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...
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...
void push_back(const T &Elt)
Class to represent struct types.
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.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
self_iterator getIterator()
#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.
@ BSWAP
Byte Swap and Counting operators.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ 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)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
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...
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...
This struct is a compact representation of a valid (non-zero power of two) alignment.