Go to the documentation of this file.
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"),
34 struct Mips16Libcall {
39 return std::strcmp(
Name,
RHS.Name) < 0;
43 struct Mips16IntrinsicHelperType{
47 bool operator<(
const Mips16IntrinsicHelperType &
RHS)
const {
48 return std::strcmp(
Name,
RHS.Name) < 0;
51 return std::strcmp(
Name,
RHS.Name) == 0;
58 { RTLIB::ADD_F64,
"__mips16_adddf3" },
59 { RTLIB::ADD_F32,
"__mips16_addsf3" },
60 { RTLIB::DIV_F64,
"__mips16_divdf3" },
61 { RTLIB::DIV_F32,
"__mips16_divsf3" },
62 { RTLIB::OEQ_F64,
"__mips16_eqdf2" },
63 { RTLIB::OEQ_F32,
"__mips16_eqsf2" },
64 { RTLIB::FPEXT_F32_F64,
"__mips16_extendsfdf2" },
65 { RTLIB::FPTOSINT_F64_I32,
"__mips16_fix_truncdfsi" },
66 { RTLIB::FPTOSINT_F32_I32,
"__mips16_fix_truncsfsi" },
67 { RTLIB::SINTTOFP_I32_F64,
"__mips16_floatsidf" },
68 { RTLIB::SINTTOFP_I32_F32,
"__mips16_floatsisf" },
69 { RTLIB::UINTTOFP_I32_F64,
"__mips16_floatunsidf" },
70 { RTLIB::UINTTOFP_I32_F32,
"__mips16_floatunsisf" },
71 { RTLIB::OGE_F64,
"__mips16_gedf2" },
72 { RTLIB::OGE_F32,
"__mips16_gesf2" },
73 { RTLIB::OGT_F64,
"__mips16_gtdf2" },
74 { RTLIB::OGT_F32,
"__mips16_gtsf2" },
75 { RTLIB::OLE_F64,
"__mips16_ledf2" },
76 { RTLIB::OLE_F32,
"__mips16_lesf2" },
77 { RTLIB::OLT_F64,
"__mips16_ltdf2" },
78 { RTLIB::OLT_F32,
"__mips16_ltsf2" },
79 { RTLIB::MUL_F64,
"__mips16_muldf3" },
80 { RTLIB::MUL_F32,
"__mips16_mulsf3" },
81 { RTLIB::UNE_F64,
"__mips16_nedf2" },
82 { RTLIB::UNE_F32,
"__mips16_nesf2" },
83 { RTLIB::UNKNOWN_LIBCALL,
"__mips16_ret_dc" },
84 { RTLIB::UNKNOWN_LIBCALL,
"__mips16_ret_df" },
85 { RTLIB::UNKNOWN_LIBCALL,
"__mips16_ret_sc" },
86 { RTLIB::UNKNOWN_LIBCALL,
"__mips16_ret_sf" },
87 { RTLIB::SUB_F64,
"__mips16_subdf3" },
88 { RTLIB::SUB_F32,
"__mips16_subsf3" },
89 { RTLIB::FPROUND_F64_F32,
"__mips16_truncdfsf2" },
90 { RTLIB::UO_F64,
"__mips16_unorddf2" },
91 { RTLIB::UO_F32,
"__mips16_unordsf2" }
95 {
"__fixunsdfsi",
"__mips16_call_stub_2" },
96 {
"ceil",
"__mips16_call_stub_df_2"},
97 {
"ceilf",
"__mips16_call_stub_sf_1"},
98 {
"copysign",
"__mips16_call_stub_df_10"},
99 {
"copysignf",
"__mips16_call_stub_sf_5"},
100 {
"cos",
"__mips16_call_stub_df_2"},
101 {
"cosf",
"__mips16_call_stub_sf_1"},
102 {
"exp2",
"__mips16_call_stub_df_2"},
103 {
"exp2f",
"__mips16_call_stub_sf_1"},
104 {
"floor",
"__mips16_call_stub_df_2"},
105 {
"floorf",
"__mips16_call_stub_sf_1"},
106 {
"log2",
"__mips16_call_stub_df_2"},
107 {
"log2f",
"__mips16_call_stub_sf_1"},
108 {
"nearbyint",
"__mips16_call_stub_df_2"},
109 {
"nearbyintf",
"__mips16_call_stub_sf_1"},
110 {
"rint",
"__mips16_call_stub_df_2"},
111 {
"rintf",
"__mips16_call_stub_sf_1"},
112 {
"sin",
"__mips16_call_stub_df_2"},
113 {
"sinf",
"__mips16_call_stub_sf_1"},
114 {
"sqrt",
"__mips16_call_stub_df_2"},
115 {
"sqrtf",
"__mips16_call_stub_sf_1"},
116 {
"trunc",
"__mips16_call_stub_df_2"},
117 {
"truncf",
"__mips16_call_stub_sf_1"},
128 setMips16HardFloatLibCalls();
166 switch (
MI.getOpcode()) {
170 return emitSel16(Mips::BeqzRxImm16,
MI,
BB);
172 return emitSel16(Mips::BnezRxImm16,
MI,
BB);
173 case Mips::SelTBteqZCmpi:
174 return emitSeliT16(Mips::Bteqz16, Mips::CmpiRxImmX16,
MI,
BB);
175 case Mips::SelTBteqZSlti:
176 return emitSeliT16(Mips::Bteqz16, Mips::SltiRxImmX16,
MI,
BB);
177 case Mips::SelTBteqZSltiu:
178 return emitSeliT16(Mips::Bteqz16, Mips::SltiuRxImmX16,
MI,
BB);
179 case Mips::SelTBtneZCmpi:
180 return emitSeliT16(Mips::Btnez16, Mips::CmpiRxImmX16,
MI,
BB);
181 case Mips::SelTBtneZSlti:
182 return emitSeliT16(Mips::Btnez16, Mips::SltiRxImmX16,
MI,
BB);
183 case Mips::SelTBtneZSltiu:
184 return emitSeliT16(Mips::Btnez16, Mips::SltiuRxImmX16,
MI,
BB);
185 case Mips::SelTBteqZCmp:
186 return emitSelT16(Mips::Bteqz16, Mips::CmpRxRy16,
MI,
BB);
187 case Mips::SelTBteqZSlt:
188 return emitSelT16(Mips::Bteqz16, Mips::SltRxRy16,
MI,
BB);
189 case Mips::SelTBteqZSltu:
190 return emitSelT16(Mips::Bteqz16, Mips::SltuRxRy16,
MI,
BB);
191 case Mips::SelTBtneZCmp:
192 return emitSelT16(Mips::Btnez16, Mips::CmpRxRy16,
MI,
BB);
193 case Mips::SelTBtneZSlt:
194 return emitSelT16(Mips::Btnez16, Mips::SltRxRy16,
MI,
BB);
195 case Mips::SelTBtneZSltu:
196 return emitSelT16(Mips::Btnez16, Mips::SltuRxRy16,
MI,
BB);
197 case Mips::BteqzT8CmpX16:
198 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::CmpRxRy16,
MI,
BB);
199 case Mips::BteqzT8SltX16:
200 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltRxRy16,
MI,
BB);
201 case Mips::BteqzT8SltuX16:
204 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltuRxRy16,
MI,
BB);
205 case Mips::BtnezT8CmpX16:
206 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::CmpRxRy16,
MI,
BB);
207 case Mips::BtnezT8SltX16:
208 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltRxRy16,
MI,
BB);
209 case Mips::BtnezT8SltuX16:
212 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltuRxRy16,
MI,
BB);
213 case Mips::BteqzT8CmpiX16:
return emitFEXT_T8I8I16_ins(
214 Mips::Bteqz16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16,
false,
MI,
BB);
215 case Mips::BteqzT8SltiX16:
return emitFEXT_T8I8I16_ins(
216 Mips::Bteqz16, Mips::SltiRxImm16, Mips::SltiRxImmX16,
true,
MI,
BB);
217 case Mips::BteqzT8SltiuX16:
return emitFEXT_T8I8I16_ins(
218 Mips::Bteqz16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16,
false,
MI,
BB);
219 case Mips::BtnezT8CmpiX16:
return emitFEXT_T8I8I16_ins(
220 Mips::Btnez16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16,
false,
MI,
BB);
221 case Mips::BtnezT8SltiX16:
return emitFEXT_T8I8I16_ins(
222 Mips::Btnez16, Mips::SltiRxImm16, Mips::SltiRxImmX16,
true,
MI,
BB);
223 case Mips::BtnezT8SltiuX16:
return emitFEXT_T8I8I16_ins(
224 Mips::Btnez16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16,
false,
MI,
BB);
226 case Mips::SltCCRxRy16:
227 return emitFEXT_CCRX16_ins(Mips::SltRxRy16,
MI,
BB);
229 case Mips::SltiCCRxImmX16:
230 return emitFEXT_CCRXI16_ins
231 (Mips::SltiRxImm16, Mips::SltiRxImmX16,
MI,
BB);
232 case Mips::SltiuCCRxImmX16:
233 return emitFEXT_CCRXI16_ins
234 (Mips::SltiuRxImm16, Mips::SltiuRxImmX16,
MI,
BB);
235 case Mips::SltuCCRxRy16:
236 return emitFEXT_CCRX16_ins
237 (Mips::SltuRxRy16,
MI,
BB);
241 bool Mips16TargetLowering::isEligibleForTailCallOptimization(
242 const CCState &CCInfo,
unsigned NextStackOffset,
248 void Mips16TargetLowering::setMips16HardFloatLibCalls() {
251 "Array not sorted!");
288 unsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber
289 (ArgListTy &
Args)
const {
290 unsigned int resultNum = 0;
291 if (
Args.size() >= 1) {
293 if (
t->isFloatTy()) {
296 else if (
t->isDoubleTy()) {
301 if (
Args.size() >=2) {
303 if (
t->isFloatTy()) {
306 else if (
t->isDoubleTy()) {
338 #define P_ "__mips16_call_stub_"
339 #define MAX_STUB_NUMBER 10
340 #define T1 P "1", P "2", 0, 0, P "5", P "6", 0, 0, P "9", P "10"
365 const char* Mips16TargetLowering::
366 getMips16HelperFunction
367 (
Type* RetTy, ArgListTy &
Args,
bool &needHelper)
const {
368 const unsigned int stubNum = getMips16HelperFunctionStubNumber(
Args);
370 const unsigned int maxStubNum = 10;
371 assert(stubNum <= maxStubNum);
372 const bool validStubNum[maxStubNum+1] =
373 {
true,
true,
true,
false,
false,
true,
true,
false,
false,
true,
true};
374 assert(validStubNum[stubNum]);
380 else if (RetTy ->isDoubleTy()) {
382 }
else if (
StructType *SRetTy = dyn_cast<StructType>(RetTy)) {
384 if (SRetTy->getNumElements() == 2) {
385 if ((SRetTy->getElementType(0)->isFloatTy()) &&
386 (SRetTy->getElementType(1)->isFloatTy())) {
388 }
else if ((SRetTy->getElementType(0)->isDoubleTy()) &&
389 (SRetTy->getElementType(1)->isDoubleTy())) {
408 void Mips16TargetLowering::
410 std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
411 bool IsPICCall,
bool GlobalOrExternal,
bool InternalLinkage,
412 bool IsCallReloc, CallLoweringInfo &CLI,
SDValue Callee,
417 const char* Mips16HelperFunction =
nullptr;
418 bool NeedMips16Helper =
false;
426 bool LookupHelper =
true;
428 Mips16Libcall
Find = { RTLIB::UNKNOWN_LIBCALL,
S->getSymbol() };
432 LookupHelper =
false;
434 const char *
Symbol =
S->getSymbol();
435 Mips16IntrinsicHelperType IntrinsicFind = {
Symbol,
"" };
458 const Mips16IntrinsicHelperType *Helper =
461 *Helper == IntrinsicFind) {
462 Mips16HelperFunction = Helper->Helper;
463 NeedMips16Helper =
true;
464 LookupHelper =
false;
469 dyn_cast<GlobalAddressSDNode>(CLI.Callee)) {
470 Mips16Libcall
Find = { RTLIB::UNKNOWN_LIBCALL,
471 G->getGlobal()->getName().data() };
475 LookupHelper =
false;
478 Mips16HelperFunction =
479 getMips16HelperFunction(CLI.RetTy, CLI.getArgs(), NeedMips16Helper);
486 if (IsPICCall || !GlobalOrExternal) {
487 unsigned V0Reg = Mips::V0;
488 if (NeedMips16Helper) {
489 RegsToPass.push_front(std::make_pair(V0Reg, Callee));
497 RegsToPass.push_front(std::make_pair((
unsigned)Mips::T9, Callee));
500 Ops.push_back(JumpTarget);
503 InternalLinkage, IsCallReloc, CLI, Callee,
531 F->insert(It, copy0MBB);
532 F->insert(It, sinkMBB);
540 BB->addSuccessor(copy0MBB);
541 BB->addSuccessor(sinkMBB);
553 BB->addSuccessor(sinkMBB);
566 MI.eraseFromParent();
571 Mips16TargetLowering::emitSelT16(
unsigned Opc1,
unsigned Opc2,
MachineInstr &
MI,
594 F->insert(It, copy0MBB);
595 F->insert(It, sinkMBB);
603 BB->addSuccessor(copy0MBB);
604 BB->addSuccessor(sinkMBB);
617 BB->addSuccessor(sinkMBB);
630 MI.eraseFromParent();
636 Mips16TargetLowering::emitSeliT16(
unsigned Opc1,
unsigned Opc2,
660 F->insert(It, copy0MBB);
661 F->insert(It, sinkMBB);
669 BB->addSuccessor(copy0MBB);
670 BB->addSuccessor(sinkMBB);
683 BB->addSuccessor(sinkMBB);
696 MI.eraseFromParent();
702 Mips16TargetLowering::emitFEXT_T8I816_ins(
unsigned BtOpc,
unsigned CmpOpc,
715 MI.eraseFromParent();
720 unsigned BtOpc,
unsigned CmpiOpc,
unsigned CmpiXOpc,
bool ImmSigned,
726 int64_t imm =
MI.getOperand(1).getImm();
738 MI.eraseFromParent();
743 (
unsigned shortOp,
unsigned longOp, int64_t
Imm) {
753 Mips16TargetLowering::emitFEXT_CCRX16_ins(
unsigned SltOpc,
MachineInstr &
MI,
766 MI.eraseFromParent();
771 Mips16TargetLowering::emitFEXT_CCRXI16_ins(
unsigned SltiOpc,
unsigned SltiXOpc,
779 int64_t
Imm =
MI.getOperand(2).getImm();
784 MI.eraseFromParent();
std::map< const char *, const Mips16HardFloatInfo::FuncSignature * > StubsNeeded
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
This is an optimization pass for GlobalISel generic memory operations.
static const Mips16IntrinsicHelperType Mips16IntrinsicHelper[]
static const char * sfMips16Helper[MAX_STUB_NUMBER+1]
CCState - This class holds information needed while lowering arguments and return values.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
@ BSWAP
Byte Swap and Counting operators.
static const char * vMips16Helper[MAX_STUB_NUMBER+1]
static const char * dfMips16Helper[MAX_STUB_NUMBER+1]
The instances of the Type class are immutable: once they are created, they are never changed.
Libcall
RTLIB::Libcall enum - This enum defines all of the runtime library calls the backend can emit.
const_iterator end(StringRef path)
Get end iterator over path.
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
const FuncSignature * findFuncSignature(const char *name)
const MipsInstrInfo * getInstrInfo() const override
MipsFunctionInfo - This class is derived from MachineFunction private Mips target-specific informatio...
static const Mips16Libcall HardFloatLibCalls[]
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
SDValue getAddrGlobal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flag, SDValue Chain, const MachinePointerInfo &PtrInfo) const
LLVM Basic Block Representation.
It looks like we only need to define PPCfmarto for these because according to these instructions perform RTO on fma s result
const MipsRegisterInfo * getRegisterInfo() const override
TargetInstrInfo - Interface to description of machine instruction set.
EVT getValueType() const
Return the ValueType of the referenced return value.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
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...
bitcast float %x to i32 %s=and i32 %t, 2147483647 %d=bitcast i32 %s to float ret float %d } declare float @fabsf(float %n) define float @bar(float %x) nounwind { %d=call float @fabsf(float %x) ret float %d } This IR(from PR6194):target datalayout="e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple="x86_64-apple-darwin10.0.0" %0=type { double, double } %struct.float3=type { float, float, float } define void @test(%0, %struct.float3 *nocapture %res) nounwind noinline ssp { entry:%tmp18=extractvalue %0 %0, 0 t
const HexagonInstrInfo * TII
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, bool *Fast) const override
Determine if the target supports unaligned memory accesses.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr size_t array_lengthof(T(&)[N])
Find the length of an array.
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...
constexpr bool isUInt< 16 >(uint64_t x)
Representation of each machine instruction.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
Mips16TargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI)
static const char * scMips16Helper[MAX_STUB_NUMBER+1]
bool operator<(int64_t V1, const APSInt &V2)
initializer< Ty > init(const Ty &Val)
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
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)
Flags
Flags values. These may be or'd together.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
constexpr bool isUInt< 8 >(uint64_t x)
bool operator==(uint64_t V1, const APInt &V2)
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
static const T * Find(StringRef S, ArrayRef< T > A)
Find KV in array using binary search.
@ MO_GOT
MO_GOT - Represents the offset into the global offset table at which the address the relocation entry...
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Class to represent struct types.
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 '...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
static unsigned Mips16WhichOp8uOr16simm(unsigned shortOp, unsigned longOp, int64_t Imm)
Wrapper class representing virtual and physical registers.
amdgpu Simplify well known AMD library false FunctionCallee Callee
constexpr bool isInt< 16 >(int64_t x)
const MipsSubtarget & Subtarget
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Iterator for intrusive lists based on ilist_node.
const DataLayout & getDataLayout() const
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
void setLibcallName(RTLIB::Libcall Call, const char *Name)
Rename the default libcall routine name for the specified libcall.
const MipsTargetLowering * createMips16TargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI)
Create MipsTargetLowering objects.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
const char LLVMTargetMachineRef TM
MachineFunction & getMachineFunction() const
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
static const char * dcMips16Helper[MAX_STUB_NUMBER+1]
SDValue getExternalSymbol(const char *Sym, EVT VT)
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
bool useSoftFloat() const
MachinePointerInfo callPtrInfo(MachineFunction &MF, const char *ES)
Create a MachinePointerInfo that has an ExternalSymbolPseudoSourceValue object representing a GOT ent...
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...
bool inMips16HardFloat() const