25#define DEBUG_TYPE "mips16-hard-float"
48 std::vector<Type *> AsmArgTypes;
49 std::vector<Value *> AsmArgs;
58char Mips16HardFloat::ID = 0;
72 switch (
T->getTypeID()) {
79 if (ST->getNumElements() != 2)
81 if ((ST->getElementType(0)->isFloatTy()) &&
82 (ST->getElementType(1)->isFloatTy()))
84 if ((ST->getElementType(0)->isDoubleTy()) &&
85 (ST->getElementType(1)->isDoubleTy()))
108 switch (
F.arg_size()) {
112 TypeID ArgTypeID =
F.getFunctionType()->getParamType(0)->getTypeID();
123 TypeID ArgTypeID0 =
F.getFunctionType()->getParamType(0)->getTypeID();
124 TypeID ArgTypeID1 =
F.getFunctionType()->getParamType(1)->getTypeID();
127 switch (ArgTypeID1) {
137 switch (ArgTypeID1) {
158 if (
F.arg_size() >=1) {
159 Type *ArgType =
F.getFunctionType()->getParamType(0);
172 Type* RetType =
F.getReturnType();
177 Type* RetType = FT.getReturnType();
189 std::string
MI = ToFP ?
"mtc1 ":
"mfc1 ";
194 AsmText +=
MI +
"$$4, $$f12\n";
198 AsmText +=
MI +
"$$4, $$f12\n";
199 AsmText +=
MI +
"$$5, $$f14\n";
203 AsmText +=
MI +
"$$4, $$f12\n";
205 AsmText +=
MI +
"$$6, $$f14\n";
206 AsmText +=
MI +
"$$7, $$f15\n";
208 AsmText +=
MI +
"$$7, $$f14\n";
209 AsmText +=
MI +
"$$6, $$f15\n";
215 AsmText +=
MI +
"$$4, $$f12\n";
216 AsmText +=
MI +
"$$5, $$f13\n";
218 AsmText +=
MI +
"$$5, $$f12\n";
219 AsmText +=
MI +
"$$4, $$f13\n";
225 AsmText +=
MI +
"$$4, $$f12\n";
226 AsmText +=
MI +
"$$5, $$f13\n";
227 AsmText +=
MI +
"$$6, $$f14\n";
228 AsmText +=
MI +
"$$7, $$f15\n";
230 AsmText +=
MI +
"$$5, $$f12\n";
231 AsmText +=
MI +
"$$4, $$f13\n";
232 AsmText +=
MI +
"$$7, $$f14\n";
233 AsmText +=
MI +
"$$6, $$f15\n";
239 AsmText +=
MI +
"$$4, $$f12\n";
240 AsmText +=
MI +
"$$5, $$f13\n";
242 AsmText +=
MI +
"$$5, $$f12\n";
243 AsmText +=
MI +
"$$4, $$f13\n";
245 AsmText +=
MI +
"$$6, $$f14\n";
260 if (TM.isPositionIndependent())
263 bool LE = TM.isLittleEndian();
264 std::string
Name(
F.getName());
266 std::string StubName =
"__call_stub_fp_" +
Name;
270 Function *FStub = M->getFunction(StubName);
273 Function::InternalLinkage, StubName, M);
285 AsmText +=
".set reorder\n";
288 AsmText +=
"move $$18, $$31\n";
289 AsmText +=
"jal " +
Name +
"\n";
291 AsmText +=
"lui $$25, %hi(" +
Name +
")\n";
292 AsmText +=
"addiu $$25, $$25, %lo(" +
Name +
")\n";
297 AsmText +=
"mfc1 $$2, $$f0\n";
302 AsmText +=
"mfc1 $$2, $$f0\n";
303 AsmText +=
"mfc1 $$3, $$f1\n";
305 AsmText +=
"mfc1 $$3, $$f0\n";
306 AsmText +=
"mfc1 $$2, $$f1\n";
312 AsmText +=
"mfc1 $$2, $$f0\n";
313 AsmText +=
"mfc1 $$3, $$f2\n";
315 AsmText +=
"mfc1 $$3, $$f0\n";
316 AsmText +=
"mfc1 $$3, $$f2\n";
322 AsmText +=
"mfc1 $$4, $$f2\n";
323 AsmText +=
"mfc1 $$5, $$f3\n";
324 AsmText +=
"mfc1 $$2, $$f0\n";
325 AsmText +=
"mfc1 $$3, $$f1\n";
328 AsmText +=
"mfc1 $$5, $$f2\n";
329 AsmText +=
"mfc1 $$4, $$f3\n";
330 AsmText +=
"mfc1 $$3, $$f0\n";
331 AsmText +=
"mfc1 $$2, $$f1\n";
340 AsmText +=
"jr $$18\n";
342 AsmText +=
"jr $$25\n";
351 "llvm.ceil.f32",
"llvm.ceil.f64",
352 "llvm.copysign.f32",
"llvm.copysign.f64",
353 "llvm.cos.f32",
"llvm.cos.f64",
354 "llvm.exp.f32",
"llvm.exp.f64",
355 "llvm.exp2.f32",
"llvm.exp2.f64",
356 "llvm.fabs.f32",
"llvm.fabs.f64",
357 "llvm.floor.f32",
"llvm.floor.f64",
358 "llvm.fma.f32",
"llvm.fma.f64",
359 "llvm.log.f32",
"llvm.log.f64",
360 "llvm.log10.f32",
"llvm.log10.f64",
361 "llvm.nearbyint.f32",
"llvm.nearbyint.f64",
362 "llvm.pow.f32",
"llvm.pow.f64",
363 "llvm.powi.f32.i32",
"llvm.powi.f64.i32",
364 "llvm.rint.f32",
"llvm.rint.f64",
365 "llvm.round.f32",
"llvm.round.f64",
366 "llvm.sin.f32",
"llvm.sin.f64",
367 "llvm.sqrt.f32",
"llvm.sqrt.f64",
368 "llvm.trunc.f32",
"llvm.trunc.f64",
385 if (
const ReturnInst *RI = dyn_cast<ReturnInst>(&
I)) {
386 Value *RVal = RI->getReturnValue();
398 static const char *
const Helper[
NoFPRet] = {
399 "__mips16_ret_sf",
"__mips16_ret_df",
"__mips16_ret_sc",
402 const char *
Name = Helper[RV];
404 Value *Params[] = {RVal};
412 A =
A.addFnAttribute(
C,
"__Mips16RetHelper");
413 A =
A.addFnAttribute(
415 A =
A.addFnAttribute(
C, Attribute::NoInline);
418 }
else if (
const CallInst *CI = dyn_cast<CallInst>(&
I)) {
420 Function *F_ = CI->getCalledFunction();
424 F.addFnAttr(
"saveS2");
431 F.addFnAttr(
"saveS2");
433 if (!TM.isPositionIndependent()) {
447 bool PicMode = TM.isPositionIndependent();
448 bool LE = TM.isLittleEndian();
450 std::string
Name(
F->getName());
452 std::string StubName =
"__fn_stub_" +
Name;
455 (
F->getFunctionType(),
456 Function::InternalLinkage, StubName, M);
467 AsmText +=
".set noreorder\n";
468 AsmText +=
".cpload $$25\n";
469 AsmText +=
".set reorder\n";
470 AsmText +=
".reloc 0, R_MIPS_NONE, " +
Name +
"\n";
471 AsmText +=
"la $$25, " +
LocalName +
"\n";
473 AsmText +=
"la $$25, " +
Name +
"\n";
475 AsmText +=
"jr $$25\n";
485 F.removeFnAttr(
"use-soft-float");
486 if (
F.hasFnAttribute(
"use-soft-float")) {
489 F.addFnAttr(
"use-soft-float",
"false");
508bool Mips16HardFloat::runOnModule(
Module &M) {
514 if (
F->hasFnAttribute(
"nomips16") &&
515 F->hasFnAttribute(
"use-soft-float")) {
519 if (
F->isDeclaration() ||
F->hasFnAttribute(
"mips16_fp_stub") ||
520 F->hasFnAttribute(
"nomips16"))
continue;
532 return new Mips16HardFloat();
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static bool fixupFPReturnAndCall(Function &F, Module *M, const MipsTargetMachine &TM)
static bool needsFPStubFromParams(Function &F)
static bool needsFPReturnHelper(Function &F)
static bool needsFPHelperFromSig(Function &F)
const Type::TypeID FloatTyID
static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, const MipsTargetMachine &TM)
static void removeUseSoftFloat(Function &F)
static const char *const IntrinsicInline[]
static bool isIntrinsicInline(Function *F)
static void emitInlineAsm(LLVMContext &C, BasicBlock *BB, StringRef AsmText)
static FPReturnVariant whichFPReturnVariant(Type *T)
const Type::TypeID DoubleTyID
static std::string swapFPIntParams(FPParamVariant PV, Module *M, bool LE, bool ToFP)
static FPParamVariant whichFPParamVariantNeeded(Function &F)
static void assureFPCallStub(Function &F, Module *M, const MipsTargetMachine &TM)
Module.h This file contains the declarations for the Module class.
Target-Independent Code Generator Pass Configuration Options pass.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
static Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Type * getReturnType() const
Returns the type of the ret val.
void setSection(StringRef S)
Change the section for this global.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
static InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)
InlineAsm::get - Return the specified uniqued inline asm string.
This is an important class for using LLVM in a threaded context.
static MemoryEffectsBase none()
Create MemoryEffectsBase that cannot read or write any memory.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
FunctionListType::iterator iterator
The Function iterators.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Return a value (possibly void), from a function.
StringRef - Represent a constant reference to a string, i.e.
Class to represent struct types.
Primary interface to the complete machine description for the target machine.
Target-Independent Code Generator Pass Configuration Options.
The instances of the Type class are immutable: once they are created, they are never changed.
TypeID
Definitions of all of the base types for the Type system.
@ FloatTyID
32-bit floating point type
@ DoubleTyID
64-bit floating point type
static Type * getVoidTy(LLVMContext &C)
TypeID getTypeID() const
Return the type id for the type.
This function has undefined behavior.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
ModulePass * createMips16HardFloatPass()