diff options
Diffstat (limited to 'lib/Target/Mips/Mips16HardFloat.cpp')
-rw-r--r-- | lib/Target/Mips/Mips16HardFloat.cpp | 64 |
1 files changed, 59 insertions, 5 deletions
diff --git a/lib/Target/Mips/Mips16HardFloat.cpp b/lib/Target/Mips/Mips16HardFloat.cpp index 7e456aa..81bf18c 100644 --- a/lib/Target/Mips/Mips16HardFloat.cpp +++ b/lib/Target/Mips/Mips16HardFloat.cpp @@ -16,6 +16,7 @@ #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> #include <string> static void inlineAsmOut @@ -321,6 +322,37 @@ static void assureFPCallStub(Function &F, Module *M, } // +// Functions that are llvm intrinsics and don't need helpers. +// +static const char *IntrinsicInline[] = + {"fabs", + "fabsf", + "llvm.ceil.f32", "llvm.ceil.f64", + "llvm.copysign.f32", "llvm.copysign.f64", + "llvm.cos.f32", "llvm.cos.f64", + "llvm.exp.f32", "llvm.exp.f64", + "llvm.exp2.f32", "llvm.exp2.f64", + "llvm.fabs.f32", "llvm.fabs.f64", + "llvm.floor.f32", "llvm.floor.f64", + "llvm.fma.f32", "llvm.fma.f64", + "llvm.log.f32", "llvm.log.f64", + "llvm.log10.f32", "llvm.log10.f64", + "llvm.nearbyint.f32", "llvm.nearbyint.f64", + "llvm.pow.f32", "llvm.pow.f64", + "llvm.powi.f32", "llvm.powi.f64", + "llvm.rint.f32", "llvm.rint.f64", + "llvm.round.f32", "llvm.round.f64", + "llvm.sin.f32", "llvm.sin.f64", + "llvm.sqrt.f32", "llvm.sqrt.f64", + "llvm.trunc.f32", "llvm.trunc.f64", + }; + +static bool isIntrinsicInline(Function *F) { + return std::binary_search( + IntrinsicInline, array_endof(IntrinsicInline), + F->getName()); +} +// // Returns of float, double and complex need to be handled with a helper // function. // @@ -372,7 +404,7 @@ static bool fixupFPReturnAndCall // helper functions if (Subtarget.getRelocationModel() != Reloc::PIC_ ) { Function *F_ = CI->getCalledFunction(); - if (F_ && needsFPHelperFromSig(*F_)) { + if (F_ && !isIntrinsicInline(F_) && needsFPHelperFromSig(*F_)) { assureFPCallStub(*F_, M, Subtarget); Modified=true; } @@ -390,7 +422,7 @@ static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, std::string Name = F->getName(); std::string SectionName = ".mips16.fn." + Name; std::string StubName = "__fn_stub_" + Name; - std::string LocalName = "__fn_local_" + Name; + std::string LocalName = "$$__fn_local_" + Name; Function *FStub = Function::Create (F->getFunctionType(), Function::InternalLinkage, StubName, M); @@ -405,19 +437,36 @@ static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, IAH.Out(" .set macro"); if (PicMode) { IAH.Out(".set noreorder"); - IAH.Out(".cpload $$2"); + IAH.Out(".cpload $$25"); IAH.Out(".set reorder"); IAH.Out(".reloc 0,R_MIPS_NONE," + Name); IAH.Out("la $$25," + LocalName); } - else - IAH.Out("la $$25, " + Name); + else { + IAH.Out(".set reorder"); + IAH.Out("la $$25," + Name); + } swapFPIntParams(PV, M, IAH, LE, false); IAH.Out("jr $$25"); IAH.Out(LocalName + " = " + Name); new UnreachableInst(FStub->getContext(), BB); } +// +// remove the use-soft-float attribute +// +static void removeUseSoftFloat(Function &F) { + AttributeSet A; + DEBUG(errs() << "removing -use-soft-float\n"); + A = A.addAttribute(F.getContext(), AttributeSet::FunctionIndex, + "use-soft-float", "false"); + F.removeAttributes(AttributeSet::FunctionIndex, A); + if (F.hasFnAttribute("use-soft-float")) { + DEBUG(errs() << "still has -use-soft-float\n"); + } + F.addAttributes(AttributeSet::FunctionIndex, A); +} + namespace llvm { // @@ -441,6 +490,11 @@ bool Mips16HardFloat::runOnModule(Module &M) { DEBUG(errs() << "Run on Module Mips16HardFloat\n"); bool Modified = false; for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->hasFnAttribute("nomips16") && + F->hasFnAttribute("use-soft-float")) { + removeUseSoftFloat(*F); + continue; + } if (F->isDeclaration() || F->hasFnAttribute("mips16_fp_stub") || F->hasFnAttribute("nomips16")) continue; Modified |= fixupFPReturnAndCall(*F, &M, Subtarget); |