24 #define DEBUG_TYPE "mips16-hard-float" 34 StringRef getPassName()
const override {
return "MIPS16 Hard Float Pass"; }
41 bool runOnModule(
Module &M)
override;
47 std::vector<Type *> AsmArgTypes;
48 std::vector<Value *> AsmArgs;
71 switch (
T->getTypeID()) {
78 if (
ST->getNumElements() != 2)
80 if ((
ST->getElementType(0)->isFloatTy()) &&
81 (
ST->getElementType(1)->isFloatTy()))
83 if ((
ST->getElementType(0)->isDoubleTy()) &&
84 (
ST->getElementType(1)->isDoubleTy()))
107 switch (
F.arg_size()) {
111 TypeID ArgTypeID =
F.getFunctionType()->getParamType(0)->getTypeID();
122 TypeID ArgTypeID0 =
F.getFunctionType()->getParamType(0)->getTypeID();
123 TypeID ArgTypeID1 =
F.getFunctionType()->getParamType(1)->getTypeID();
126 switch (ArgTypeID1) {
136 switch (ArgTypeID1) {
157 if (
F.arg_size() >=1) {
158 Type *ArgType =
F.getFunctionType()->getParamType(0);
171 Type* RetType =
F.getReturnType();
188 std::string
MI = ToFP ?
"mtc1 ":
"mfc1 ";
193 AsmText +=
MI +
"$$4, $$f12\n";
197 AsmText +=
MI +
"$$4, $$f12\n";
198 AsmText +=
MI +
"$$5, $$f14\n";
202 AsmText +=
MI +
"$$4, $$f12\n";
204 AsmText +=
MI +
"$$6, $$f14\n";
205 AsmText +=
MI +
"$$7, $$f15\n";
207 AsmText +=
MI +
"$$7, $$f14\n";
208 AsmText +=
MI +
"$$6, $$f15\n";
214 AsmText +=
MI +
"$$4, $$f12\n";
215 AsmText +=
MI +
"$$5, $$f13\n";
217 AsmText +=
MI +
"$$5, $$f12\n";
218 AsmText +=
MI +
"$$4, $$f13\n";
224 AsmText +=
MI +
"$$4, $$f12\n";
225 AsmText +=
MI +
"$$5, $$f13\n";
226 AsmText +=
MI +
"$$6, $$f14\n";
227 AsmText +=
MI +
"$$7, $$f15\n";
229 AsmText +=
MI +
"$$5, $$f12\n";
230 AsmText +=
MI +
"$$4, $$f13\n";
231 AsmText +=
MI +
"$$7, $$f14\n";
232 AsmText +=
MI +
"$$6, $$f15\n";
238 AsmText +=
MI +
"$$4, $$f12\n";
239 AsmText +=
MI +
"$$5, $$f13\n";
241 AsmText +=
MI +
"$$5, $$f12\n";
242 AsmText +=
MI +
"$$4, $$f13\n";
244 AsmText +=
MI +
"$$6, $$f14\n";
259 if (
TM.isPositionIndependent())
262 bool LE =
TM.isLittleEndian();
263 std::string
Name(
F.getName());
265 std::string StubName =
"__call_stub_fp_" +
Name;
269 Function *FStub = M->getFunction(StubName);
284 AsmText +=
".set reorder\n";
287 AsmText +=
"move $$18, $$31\n";
288 AsmText +=
"jal " +
Name +
"\n";
290 AsmText +=
"lui $$25, %hi(" +
Name +
")\n";
291 AsmText +=
"addiu $$25, $$25, %lo(" +
Name +
")\n";
296 AsmText +=
"mfc1 $$2, $$f0\n";
301 AsmText +=
"mfc1 $$2, $$f0\n";
302 AsmText +=
"mfc1 $$3, $$f1\n";
304 AsmText +=
"mfc1 $$3, $$f0\n";
305 AsmText +=
"mfc1 $$2, $$f1\n";
311 AsmText +=
"mfc1 $$2, $$f0\n";
312 AsmText +=
"mfc1 $$3, $$f2\n";
314 AsmText +=
"mfc1 $$3, $$f0\n";
315 AsmText +=
"mfc1 $$3, $$f2\n";
321 AsmText +=
"mfc1 $$4, $$f2\n";
322 AsmText +=
"mfc1 $$5, $$f3\n";
323 AsmText +=
"mfc1 $$2, $$f0\n";
324 AsmText +=
"mfc1 $$3, $$f1\n";
327 AsmText +=
"mfc1 $$5, $$f2\n";
328 AsmText +=
"mfc1 $$4, $$f3\n";
329 AsmText +=
"mfc1 $$3, $$f0\n";
330 AsmText +=
"mfc1 $$2, $$f1\n";
339 AsmText +=
"jr $$18\n";
341 AsmText +=
"jr $$25\n";
350 "llvm.ceil.f32",
"llvm.ceil.f64",
351 "llvm.copysign.f32",
"llvm.copysign.f64",
352 "llvm.cos.f32",
"llvm.cos.f64",
353 "llvm.exp.f32",
"llvm.exp.f64",
354 "llvm.exp2.f32",
"llvm.exp2.f64",
355 "llvm.fabs.f32",
"llvm.fabs.f64",
356 "llvm.floor.f32",
"llvm.floor.f64",
357 "llvm.fma.f32",
"llvm.fma.f64",
358 "llvm.log.f32",
"llvm.log.f64",
359 "llvm.log10.f32",
"llvm.log10.f64",
360 "llvm.nearbyint.f32",
"llvm.nearbyint.f64",
361 "llvm.pow.f32",
"llvm.pow.f64",
362 "llvm.powi.f32",
"llvm.powi.f64",
363 "llvm.rint.f32",
"llvm.rint.f64",
364 "llvm.round.f32",
"llvm.round.f64",
365 "llvm.sin.f32",
"llvm.sin.f64",
366 "llvm.sqrt.f32",
"llvm.sqrt.f64",
367 "llvm.trunc.f32",
"llvm.trunc.f64",
384 if (
const ReturnInst *RI = dyn_cast<ReturnInst>(&
I)) {
385 Value *RVal = RI->getReturnValue();
397 static const char *
const Helper[
NoFPRet] = {
398 "__mips16_ret_sf",
"__mips16_ret_df",
"__mips16_ret_sc",
401 const char *
Name = Helper[RV];
403 Value *Params[] = {RVal};
412 "__Mips16RetHelper");
414 Attribute::ReadNone);
416 Attribute::NoInline);
419 }
else if (
const CallInst *CI = dyn_cast<CallInst>(&
I)) {
421 Function *F_ = CI->getCalledFunction();
425 F.addFnAttr(
"saveS2");
432 F.addFnAttr(
"saveS2");
434 if (!
TM.isPositionIndependent()) {
448 bool PicMode =
TM.isPositionIndependent();
449 bool LE =
TM.isLittleEndian();
451 std::string
Name(
F->getName());
453 std::string StubName =
"__fn_stub_" +
Name;
456 (
F->getFunctionType(),
468 AsmText +=
".set noreorder\n";
469 AsmText +=
".cpload $$25\n";
470 AsmText +=
".set reorder\n";
471 AsmText +=
".reloc 0, R_MIPS_NONE, " +
Name +
"\n";
472 AsmText +=
"la $$25, " +
LocalName +
"\n";
474 AsmText +=
"la $$25, " +
Name +
"\n";
476 AsmText +=
"jr $$25\n";
487 B.addAttribute(
"use-soft-float",
"false");
489 if (
F.hasFnAttribute(
"use-soft-float")) {
511 bool Mips16HardFloat::runOnModule(
Module &M) {
512 auto &
TM = static_cast<const MipsTargetMachine &>(
513 getAnalysis<TargetPassConfig>().getTM<TargetMachine>());
517 if (
F->hasFnAttribute(
"nomips16") &&
518 F->hasFnAttribute(
"use-soft-float")) {
522 if (
F->isDeclaration() ||
F->hasFnAttribute(
"mips16_fp_stub") ||
523 F->hasFnAttribute(
"nomips16"))
continue;
Return a value (possibly void), from a function.
const_iterator end(StringRef path)
Get end iterator over path.
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
This class represents lattice values for constants.
static bool needsFPReturnHelper(Function &F)
A Module instance is used to store all the information related to an LLVM module.
32-bit floating point type
static void removeUseSoftFloat(Function &F)
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
This class represents a function call, abstracting a target machine's calling convention.
AnalysisUsage & addRequired()
TypeID getTypeID() const
Return the type id for the type.
Class to represent struct types.
static bool needsFPHelperFromSig(Function &F)
TypeID
Definitions of all of the base types for the Type system.
Target-Independent Code Generator Pass Configuration Options.
static bool needsFPStubFromParams(Function &F)
static FPReturnVariant whichFPReturnVariant(Type *T)
Class to represent function types.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Type * getType() const
All values are typed, get the type of this value.
const Type::TypeID FloatTyID
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static bool isIntrinsicInline(Function *F)
static void assureFPCallStub(Function &F, Module *M, const MipsTargetMachine &TM)
Type * getReturnType() const
Returns the type of the ret val.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
LLVM Basic Block Representation.
static bool fixupFPReturnAndCall(Function &F, Module *M, const MipsTargetMachine &TM)
The instances of the Type class are immutable: once they are created, they are never changed.
This is an important class for using LLVM in a threaded context.
This function has undefined behavior.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, const MipsTargetMachine &TM)
Represent the analysis usage information of a pass.
static Type * getVoidTy(LLVMContext &C)
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
ModulePass * createMips16HardFloatPass()
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Iterator for intrusive lists based on ilist_node.
Module.h This file contains the declarations for the Module class.
Type * getReturnType() const
static FPParamVariant whichFPParamVariantNeeded(Function &F)
static const char *const IntrinsicInline[]
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Rename collisions when linking (static functions).
static InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT)
InlineAsm::get - Return the specified uniqued inline asm string.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
64-bit floating point type
const Type::TypeID DoubleTyID
LLVM Value Representation.
static void emitInlineAsm(LLVMContext &C, BasicBlock *BB, StringRef AsmText)
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
static cl::opt< bool > Mips16HardFloat("mips16-hard-float", cl::NotHidden, cl::desc("Enable mips16 hard float."), cl::init(false))
StringRef - Represent a constant reference to a string, i.e.
void setSection(StringRef S)
Change the section for this global.
static std::string swapFPIntParams(FPParamVariant PV, Module *M, bool LE, bool ToFP)