24 #define DEBUG_TYPE "mips16-hard-float"
33 StringRef getPassName()
const override {
return "MIPS16 Hard Float Pass"; }
35 bool runOnModule(
Module &M)
override;
42 std::vector<llvm::Type *> AsmArgTypes;
43 std::vector<llvm::Value *> AsmArgs;
124 switch (ArgTypeID1) {
134 switch (ArgTypeID1) {
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";
268 std::string StubName =
"__call_stub_fp_" +
Name;
277 FStub->
addFnAttr(llvm::Attribute::Naked);
278 FStub->
addFnAttr(llvm::Attribute::NoInline);
279 FStub->
addFnAttr(llvm::Attribute::NoUnwind);
287 AsmText +=
".set reorder\n";
290 AsmText +=
"move $$18, $$31\n";
291 AsmText +=
"jal " + Name +
"\n";
293 AsmText +=
"lui $$25, %hi(" + Name +
")\n";
294 AsmText +=
"addiu $$25, $$25, %lo(" + Name +
")\n";
299 AsmText +=
"mfc1 $$2, $$f0\n";
304 AsmText +=
"mfc1 $$2, $$f0\n";
305 AsmText +=
"mfc1 $$3, $$f1\n";
307 AsmText +=
"mfc1 $$3, $$f0\n";
308 AsmText +=
"mfc1 $$2, $$f1\n";
314 AsmText +=
"mfc1 $$2, $$f0\n";
315 AsmText +=
"mfc1 $$3, $$f2\n";
317 AsmText +=
"mfc1 $$3, $$f0\n";
318 AsmText +=
"mfc1 $$3, $$f2\n";
324 AsmText +=
"mfc1 $$4, $$f2\n";
325 AsmText +=
"mfc1 $$5, $$f3\n";
326 AsmText +=
"mfc1 $$2, $$f0\n";
327 AsmText +=
"mfc1 $$3, $$f1\n";
330 AsmText +=
"mfc1 $$5, $$f2\n";
331 AsmText +=
"mfc1 $$4, $$f3\n";
332 AsmText +=
"mfc1 $$3, $$f0\n";
333 AsmText +=
"mfc1 $$2, $$f1\n";
342 AsmText +=
"jr $$18\n";
344 AsmText +=
"jr $$25\n";
345 EmitInlineAsm(Context, BB, AsmText);
355 "llvm.ceil.f32",
"llvm.ceil.f64",
356 "llvm.copysign.f32",
"llvm.copysign.f64",
357 "llvm.cos.f32",
"llvm.cos.f64",
358 "llvm.exp.f32",
"llvm.exp.f64",
359 "llvm.exp2.f32",
"llvm.exp2.f64",
360 "llvm.fabs.f32",
"llvm.fabs.f64",
361 "llvm.floor.f32",
"llvm.floor.f64",
362 "llvm.fma.f32",
"llvm.fma.f64",
363 "llvm.log.f32",
"llvm.log.f64",
364 "llvm.log10.f32",
"llvm.log10.f64",
365 "llvm.nearbyint.f32",
"llvm.nearbyint.f64",
366 "llvm.pow.f32",
"llvm.pow.f64",
367 "llvm.powi.f32",
"llvm.powi.f64",
368 "llvm.rint.f32",
"llvm.rint.f64",
369 "llvm.round.f32",
"llvm.round.f64",
370 "llvm.sin.f32",
"llvm.sin.f64",
371 "llvm.sqrt.f32",
"llvm.sqrt.f64",
372 "llvm.trunc.f32",
"llvm.trunc.f64",
385 bool Modified =
false;
390 if (
const ReturnInst *RI = dyn_cast<ReturnInst>(&
I)) {
391 Value *RVal = RI->getReturnValue();
403 static const char *
const Helper[
NoFPRet] = {
404 "__mips16_ret_sf",
"__mips16_ret_df",
"__mips16_ret_sc",
407 const char *
Name = Helper[RV];
409 Value *Params[] = {RVal};
418 "__Mips16RetHelper");
420 Attribute::ReadNone);
422 Attribute::NoInline);
425 }
else if (
const CallInst *CI = dyn_cast<CallInst>(&
I)) {
427 Function *F_ = CI->getCalledFunction();
431 F.addFnAttr(
"saveS2");
438 F.addFnAttr(
"saveS2");
459 std::string StubName =
"__fn_stub_" +
Name;
460 std::string LocalName =
"$$__fn_local_" +
Name;
465 FStub->
addFnAttr(llvm::Attribute::Naked);
466 FStub->
addFnAttr(llvm::Attribute::NoUnwind);
467 FStub->
addFnAttr(llvm::Attribute::NoInline);
474 AsmText +=
".set noreorder\n";
475 AsmText +=
".cpload $$25\n";
476 AsmText +=
".set reorder\n";
477 AsmText +=
".reloc 0, R_MIPS_NONE, " + Name +
"\n";
478 AsmText +=
"la $$25, " + LocalName +
"\n";
480 AsmText +=
"la $$25, " + Name +
"\n";
482 AsmText +=
"jr $$25\n";
483 AsmText += LocalName +
" = " + Name +
"\n";
484 EmitInlineAsm(Context, BB, AsmText);
494 DEBUG(
errs() <<
"removing -use-soft-float\n");
496 "use-soft-float",
"false");
499 DEBUG(
errs() <<
"still has -use-soft-float\n");
523 bool Mips16HardFloat::runOnModule(
Module &M) {
524 DEBUG(
errs() <<
"Run on Module Mips16HardFloat\n");
525 bool Modified =
false;
527 if (
F->hasFnAttribute(
"nomips16") &&
528 F->hasFnAttribute(
"use-soft-float")) {
532 if (
F->isDeclaration() ||
F->hasFnAttribute(
"mips16_fp_stub") ||
533 F->hasFnAttribute(
"nomips16"))
continue;
Return a value (possibly void), from a function.
const_iterator end(StringRef path)
Get end iterator over path.
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
static bool needsFPReturnHelper(Function &F)
unsigned getStructNumElements() const
A Module instance is used to store all the information related to an LLVM module. ...
2: 32-bit floating point type
static void removeUseSoftFloat(Function &F)
This class represents a function call, abstracting a target machine's calling convention.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
const_iterator begin(StringRef path)
Get begin iterator over path.
Type * getReturnType() const
Returns the type of the ret val.
StringRef getName() const
Return a constant reference to the value's name.
void removeAttributes(unsigned i, AttributeSet Attrs)
removes the attributes from the list of attributes.
static bool needsFPHelperFromSig(Function &F)
TypeID
Definitions of all of the base types for the Type system.
void addAttributes(unsigned i, AttributeSet Attrs)
adds the attributes to the list of attributes.
static bool needsFPStubFromParams(Function &F)
static FPReturnVariant whichFPReturnVariant(Type *T)
Class to represent function types.
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.
TypeID getTypeID() const
Return the type id for the type.
static bool isIntrinsicInline(Function *F)
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
static void assureFPCallStub(Function &F, Module *M, const MipsTargetMachine &TM)
Type * getParamType(unsigned i) const
Parameter type accessors.
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeSet AttributeList)
Look up the specified function in the module symbol table.
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.
AttributeSet addAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const
Add an attribute to the attribute set at the given index.
Type * getContainedType(unsigned i) const
This method is used to implement the type iterator (defined at the end of the file).
This function has undefined behavior.
static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, const MipsTargetMachine &TM)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
static Type * getVoidTy(LLVMContext &C)
bool isPositionIndependent() const
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ModulePass * createMips16HardFloatPass(MipsTargetMachine &TM)
Iterator for intrusive lists based on ilist_node.
static CallInst * Create(Value *Func, ArrayRef< Value * > Args, ArrayRef< OperandBundleDef > Bundles=None, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
bool isLittleEndian() const
static FPParamVariant whichFPParamVariantNeeded(Function &F)
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
static const char *const IntrinsicInline[]
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
FunctionType * getFunctionType() const
Returns the FunctionType for me.
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.
3: 64-bit floating point type
Type * getReturnType() const
const Type::TypeID DoubleTyID
LLVM Value Representation.
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.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=nullptr)
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
void setSection(StringRef S)
Change the section for this global.
static std::string swapFPIntParams(FPParamVariant PV, Module *M, bool LE, bool ToFP)
LLVMContext & getContext() const
Get the global data context.