blob: 14055d608e11df09f228e590e69a7bf5f5270c3e [file] [log] [blame]
Reed Kotler783c7942013-05-10 22:25:39 +00001//===---- Mips16HardFloat.cpp for Mips16 Hard Float --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a pass needed for Mips16 Hard Float
11//
12//===----------------------------------------------------------------------===//
13
Reed Kotler783c7942013-05-10 22:25:39 +000014#include "Mips16HardFloat.h"
15#include "llvm/IR/Module.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "llvm/IR/Value.h"
Reed Kotler783c7942013-05-10 22:25:39 +000017#include "llvm/Support/Debug.h"
18#include "llvm/Support/raw_ostream.h"
Reed Kotlerd265e882013-08-11 21:30:27 +000019#include <algorithm>
Reed Kotler783c7942013-05-10 22:25:39 +000020#include <string>
21
Chandler Carruth84e68b22014-04-22 02:41:26 +000022#define DEBUG_TYPE "mips16-hard-float"
23
Reed Kotler2c4657d2013-05-14 02:00:24 +000024static void inlineAsmOut
25 (LLVMContext &C, StringRef AsmString, BasicBlock *BB ) {
26 std::vector<llvm::Type *> AsmArgTypes;
27 std::vector<llvm::Value*> AsmArgs;
28 llvm::FunctionType *AsmFTy =
29 llvm::FunctionType::get(Type::getVoidTy(C),
30 AsmArgTypes, false);
31 llvm::InlineAsm *IA =
32 llvm::InlineAsm::get(AsmFTy, AsmString, "", true,
33 /* IsAlignStack */ false,
34 llvm::InlineAsm::AD_ATT);
35 CallInst::Create(IA, AsmArgs, "", BB);
36}
37
38namespace {
39
40class InlineAsmHelper {
41 LLVMContext &C;
42 BasicBlock *BB;
43public:
44 InlineAsmHelper(LLVMContext &C_, BasicBlock *BB_) :
45 C(C_), BB(BB_) {
46 }
47
48 void Out(StringRef AsmString) {
49 inlineAsmOut(C, AsmString, BB);
50 }
51
52};
53}
Reed Kotler783c7942013-05-10 22:25:39 +000054//
55// Return types that matter for hard float are:
56// float, double, complex float, and complex double
57//
58enum FPReturnVariant {
59 FRet, DRet, CFRet, CDRet, NoFPRet
60};
61
62//
63// Determine which FP return type this function has
64//
65static FPReturnVariant whichFPReturnVariant(Type *T) {
66 switch (T->getTypeID()) {
67 case Type::FloatTyID:
68 return FRet;
69 case Type::DoubleTyID:
70 return DRet;
71 case Type::StructTyID:
72 if (T->getStructNumElements() != 2)
73 break;
74 if ((T->getContainedType(0)->isFloatTy()) &&
75 (T->getContainedType(1)->isFloatTy()))
76 return CFRet;
77 if ((T->getContainedType(0)->isDoubleTy()) &&
78 (T->getContainedType(1)->isDoubleTy()))
79 return CDRet;
80 break;
81 default:
82 break;
83 }
84 return NoFPRet;
85}
86
87//
Reed Kotler2c4657d2013-05-14 02:00:24 +000088// Parameter type that matter are float, (float, float), (float, double),
89// double, (double, double), (double, float)
90//
91enum FPParamVariant {
92 FSig, FFSig, FDSig,
93 DSig, DDSig, DFSig, NoSig
94};
95
96// which floating point parameter signature variant we are dealing with
97//
98typedef Type::TypeID TypeID;
99const Type::TypeID FloatTyID = Type::FloatTyID;
100const Type::TypeID DoubleTyID = Type::DoubleTyID;
101
102static FPParamVariant whichFPParamVariantNeeded(Function &F) {
103 switch (F.arg_size()) {
104 case 0:
105 return NoSig;
106 case 1:{
107 TypeID ArgTypeID = F.getFunctionType()->getParamType(0)->getTypeID();
108 switch (ArgTypeID) {
109 case FloatTyID:
110 return FSig;
111 case DoubleTyID:
112 return DSig;
113 default:
114 return NoSig;
115 }
116 }
117 default: {
118 TypeID ArgTypeID0 = F.getFunctionType()->getParamType(0)->getTypeID();
119 TypeID ArgTypeID1 = F.getFunctionType()->getParamType(1)->getTypeID();
120 switch(ArgTypeID0) {
121 case FloatTyID: {
122 switch (ArgTypeID1) {
123 case FloatTyID:
124 return FFSig;
125 case DoubleTyID:
126 return FDSig;
127 default:
128 return FSig;
129 }
130 }
131 case DoubleTyID: {
132 switch (ArgTypeID1) {
133 case FloatTyID:
134 return DFSig;
135 case DoubleTyID:
136 return DDSig;
137 default:
138 return DSig;
139 }
140 }
141 default:
142 return NoSig;
143 }
144 }
145 }
146 llvm_unreachable("can't get here");
147}
148
149// Figure out if we need float point based on the function parameters.
150// We need to move variables in and/or out of floating point
151// registers because of the ABI
152//
153static bool needsFPStubFromParams(Function &F) {
154 if (F.arg_size() >=1) {
155 Type *ArgType = F.getFunctionType()->getParamType(0);
156 switch (ArgType->getTypeID()) {
157 case Type::FloatTyID:
158 case Type::DoubleTyID:
159 return true;
160 default:
161 break;
162 }
163 }
164 return false;
165}
166
167static bool needsFPReturnHelper(Function &F) {
168 Type* RetType = F.getReturnType();
169 return whichFPReturnVariant(RetType) != NoFPRet;
170}
171
Reed Kotler2500bd62013-12-18 23:57:48 +0000172static bool needsFPReturnHelper(const FunctionType &FT) {
173 Type* RetType = FT.getReturnType();
174 return whichFPReturnVariant(RetType) != NoFPRet;
175}
176
Reed Kotler2c4657d2013-05-14 02:00:24 +0000177static bool needsFPHelperFromSig(Function &F) {
178 return needsFPStubFromParams(F) || needsFPReturnHelper(F);
179}
180
181//
182// We swap between FP and Integer registers to allow Mips16 and Mips32 to
183// interoperate
184//
185
Reed Kotlercad47f02013-05-14 02:13:45 +0000186static void swapFPIntParams
187 (FPParamVariant PV, Module *M, InlineAsmHelper &IAH,
188 bool LE, bool ToFP) {
Reed Kotler2c4657d2013-05-14 02:00:24 +0000189 //LLVMContext &Context = M->getContext();
190 std::string MI = ToFP? "mtc1 ": "mfc1 ";
191 switch (PV) {
192 case FSig:
193 IAH.Out(MI + "$$4,$$f12");
194 break;
195 case FFSig:
196 IAH.Out(MI +"$$4,$$f12");
197 IAH.Out(MI + "$$5,$$f14");
198 break;
199 case FDSig:
200 IAH.Out(MI + "$$4,$$f12");
201 if (LE) {
202 IAH.Out(MI + "$$6,$$f14");
203 IAH.Out(MI + "$$7,$$f15");
204 } else {
205 IAH.Out(MI + "$$7,$$f14");
206 IAH.Out(MI + "$$6,$$f15");
207 }
208 break;
209 case DSig:
210 if (LE) {
211 IAH.Out(MI + "$$4,$$f12");
212 IAH.Out(MI + "$$5,$$f13");
213 } else {
214 IAH.Out(MI + "$$5,$$f12");
215 IAH.Out(MI + "$$4,$$f13");
216 }
217 break;
218 case DDSig:
219 if (LE) {
220 IAH.Out(MI + "$$4,$$f12");
221 IAH.Out(MI + "$$5,$$f13");
222 IAH.Out(MI + "$$6,$$f14");
223 IAH.Out(MI + "$$7,$$f15");
224 } else {
225 IAH.Out(MI + "$$5,$$f12");
226 IAH.Out(MI + "$$4,$$f13");
227 IAH.Out(MI + "$$7,$$f14");
228 IAH.Out(MI + "$$6,$$f15");
229 }
230 break;
231 case DFSig:
232 if (LE) {
233 IAH.Out(MI + "$$4,$$f12");
234 IAH.Out(MI + "$$5,$$f13");
235 } else {
236 IAH.Out(MI + "$$5,$$f12");
237 IAH.Out(MI + "$$4,$$f13");
238 }
239 IAH.Out(MI + "$$6,$$f14");
240 break;
241 case NoSig:
242 return;
243 }
244}
245//
246// Make sure that we know we already need a stub for this function.
247// Having called needsFPHelperFromSig
248//
Reed Kotler4cdaa7d2014-02-14 19:16:39 +0000249static void assureFPCallStub(Function &F, Module *M,
250 const MipsSubtarget &Subtarget) {
Reed Kotler2c4657d2013-05-14 02:00:24 +0000251 // for now we only need them for static relocation
Reed Kotler821e86f2013-05-14 06:00:01 +0000252 if (Subtarget.getRelocationModel() == Reloc::PIC_)
Reed Kotler2c4657d2013-05-14 02:00:24 +0000253 return;
254 LLVMContext &Context = M->getContext();
255 bool LE = Subtarget.isLittle();
256 std::string Name = F.getName();
257 std::string SectionName = ".mips16.call.fp." + Name;
Reed Kotler302ae6b2013-08-01 02:26:31 +0000258 std::string StubName = "__call_stub_fp_" + Name;
Reed Kotler2c4657d2013-05-14 02:00:24 +0000259 //
260 // see if we already have the stub
261 //
262 Function *FStub = M->getFunction(StubName);
263 if (FStub && !FStub->isDeclaration()) return;
264 FStub = Function::Create(F.getFunctionType(),
265 Function::InternalLinkage, StubName, M);
266 FStub->addFnAttr("mips16_fp_stub");
267 FStub->addFnAttr(llvm::Attribute::Naked);
Reed Kotler302ae6b2013-08-01 02:26:31 +0000268 FStub->addFnAttr(llvm::Attribute::NoInline);
Reed Kotler2c4657d2013-05-14 02:00:24 +0000269 FStub->addFnAttr(llvm::Attribute::NoUnwind);
270 FStub->addFnAttr("nomips16");
271 FStub->setSection(SectionName);
272 BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub);
273 InlineAsmHelper IAH(Context, BB);
Reed Kotler302ae6b2013-08-01 02:26:31 +0000274 IAH.Out(".set reorder");
Reed Kotler2c4657d2013-05-14 02:00:24 +0000275 FPReturnVariant RV = whichFPReturnVariant(FStub->getReturnType());
276 FPParamVariant PV = whichFPParamVariantNeeded(F);
277 swapFPIntParams(PV, M, IAH, LE, true);
278 if (RV != NoFPRet) {
279 IAH.Out("move $$18, $$31");
280 IAH.Out("jal " + Name);
281 } else {
282 IAH.Out("lui $$25,%hi(" + Name + ")");
283 IAH.Out("addiu $$25,$$25,%lo(" + Name + ")" );
284 }
285 switch (RV) {
286 case FRet:
287 IAH.Out("mfc1 $$2,$$f0");
288 break;
289 case DRet:
290 if (LE) {
291 IAH.Out("mfc1 $$2,$$f0");
292 IAH.Out("mfc1 $$3,$$f1");
293 } else {
294 IAH.Out("mfc1 $$3,$$f0");
295 IAH.Out("mfc1 $$2,$$f1");
296 }
297 break;
298 case CFRet:
299 if (LE) {
300 IAH.Out("mfc1 $$2,$$f0");
301 IAH.Out("mfc1 $$3,$$f2");
302 } else {
303 IAH.Out("mfc1 $$3,$$f0");
304 IAH.Out("mfc1 $$3,$$f2");
305 }
306 break;
307 case CDRet:
308 if (LE) {
309 IAH.Out("mfc1 $$4,$$f2");
310 IAH.Out("mfc1 $$5,$$f3");
311 IAH.Out("mfc1 $$2,$$f0");
312 IAH.Out("mfc1 $$3,$$f1");
313
314 } else {
315 IAH.Out("mfc1 $$5,$$f2");
316 IAH.Out("mfc1 $$4,$$f3");
317 IAH.Out("mfc1 $$3,$$f0");
318 IAH.Out("mfc1 $$2,$$f1");
319 }
320 break;
321 case NoFPRet:
322 break;
323 }
324 if (RV != NoFPRet)
325 IAH.Out("jr $$18");
326 else
327 IAH.Out("jr $$25");
328 new UnreachableInst(Context, BB);
329}
330
331//
Reed Kotler5fdadce2013-09-01 04:12:59 +0000332// Functions that are llvm intrinsics and don't need helpers.
Reed Kotlerd265e882013-08-11 21:30:27 +0000333//
Benjamin Kramerc9b7d472013-08-12 09:37:29 +0000334static const char *IntrinsicInline[] =
Reed Kotler5fdadce2013-09-01 04:12:59 +0000335 {"fabs",
Reed Kotler339c7412013-10-08 19:55:01 +0000336 "fabsf",
Reed Kotler5fdadce2013-09-01 04:12:59 +0000337 "llvm.ceil.f32", "llvm.ceil.f64",
338 "llvm.copysign.f32", "llvm.copysign.f64",
339 "llvm.cos.f32", "llvm.cos.f64",
340 "llvm.exp.f32", "llvm.exp.f64",
341 "llvm.exp2.f32", "llvm.exp2.f64",
342 "llvm.fabs.f32", "llvm.fabs.f64",
343 "llvm.floor.f32", "llvm.floor.f64",
344 "llvm.fma.f32", "llvm.fma.f64",
345 "llvm.log.f32", "llvm.log.f64",
346 "llvm.log10.f32", "llvm.log10.f64",
347 "llvm.nearbyint.f32", "llvm.nearbyint.f64",
348 "llvm.pow.f32", "llvm.pow.f64",
349 "llvm.powi.f32", "llvm.powi.f64",
350 "llvm.rint.f32", "llvm.rint.f64",
351 "llvm.round.f32", "llvm.round.f64",
352 "llvm.sin.f32", "llvm.sin.f64",
353 "llvm.sqrt.f32", "llvm.sqrt.f64",
354 "llvm.trunc.f32", "llvm.trunc.f64",
355 };
Reed Kotlerd265e882013-08-11 21:30:27 +0000356
Benjamin Kramerc9b7d472013-08-12 09:37:29 +0000357static bool isIntrinsicInline(Function *F) {
Benjamin Kramer502b9e12014-04-12 16:15:53 +0000358 return std::binary_search(std::begin(IntrinsicInline),
359 std::end(IntrinsicInline), F->getName());
Reed Kotlerd265e882013-08-11 21:30:27 +0000360}
361//
Reed Kotler783c7942013-05-10 22:25:39 +0000362// Returns of float, double and complex need to be handled with a helper
Reed Kotler515e9372013-05-16 02:17:42 +0000363// function.
Reed Kotler783c7942013-05-10 22:25:39 +0000364//
365static bool fixupFPReturnAndCall
366 (Function &F, Module *M, const MipsSubtarget &Subtarget) {
367 bool Modified = false;
368 LLVMContext &C = M->getContext();
369 Type *MyVoid = Type::getVoidTy(C);
370 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
371 for (BasicBlock::iterator I = BB->begin(), E = BB->end();
372 I != E; ++I) {
373 Instruction &Inst = *I;
374 if (const ReturnInst *RI = dyn_cast<ReturnInst>(I)) {
375 Value *RVal = RI->getReturnValue();
376 if (!RVal) continue;
377 //
378 // If there is a return value and it needs a helper function,
379 // figure out which one and add a call before the actual
380 // return to this helper. The purpose of the helper is to move
381 // floating point values from their soft float return mapping to
382 // where they would have been mapped to in floating point registers.
383 //
384 Type *T = RVal->getType();
385 FPReturnVariant RV = whichFPReturnVariant(T);
386 if (RV == NoFPRet) continue;
387 static const char* Helper[NoFPRet] =
388 {"__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc",
389 "__mips16_ret_dc"};
390 const char *Name = Helper[RV];
391 AttributeSet A;
392 Value *Params[] = {RVal};
393 Modified = true;
394 //
395 // These helper functions have a different calling ABI so
396 // this __Mips16RetHelper indicates that so that later
397 // during call setup, the proper call lowering to the helper
398 // functions will take place.
399 //
400 A = A.addAttribute(C, AttributeSet::FunctionIndex,
401 "__Mips16RetHelper");
402 A = A.addAttribute(C, AttributeSet::FunctionIndex,
403 Attribute::ReadNone);
Reed Kotler302ae6b2013-08-01 02:26:31 +0000404 A = A.addAttribute(C, AttributeSet::FunctionIndex,
405 Attribute::NoInline);
Reed Kotler783c7942013-05-10 22:25:39 +0000406 Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T, NULL));
407 CallInst::Create(F, Params, "", &Inst );
Reed Kotler2c4657d2013-05-14 02:00:24 +0000408 } else if (const CallInst *CI = dyn_cast<CallInst>(I)) {
Reed Kotler2500bd62013-12-18 23:57:48 +0000409 const Value* V = CI->getCalledValue();
Craig Topper062a2ba2014-04-25 05:30:21 +0000410 const Type* T = nullptr;
Reed Kotler2500bd62013-12-18 23:57:48 +0000411 if (V) T = V->getType();
Craig Topper062a2ba2014-04-25 05:30:21 +0000412 const PointerType *PFT=nullptr;
Reed Kotler2500bd62013-12-18 23:57:48 +0000413 if (T) PFT = dyn_cast<PointerType>(T);
Craig Topper062a2ba2014-04-25 05:30:21 +0000414 const FunctionType *FT=nullptr;
Reed Kotler2500bd62013-12-18 23:57:48 +0000415 if (PFT) FT = dyn_cast<FunctionType>(PFT->getElementType());
Reed Kotler0ff40012013-12-10 14:29:38 +0000416 Function *F_ = CI->getCalledFunction();
Reed Kotler2500bd62013-12-18 23:57:48 +0000417 if (FT && needsFPReturnHelper(*FT) &&
418 !(F_ && isIntrinsicInline(F_))) {
419 Modified=true;
420 F.addFnAttr("saveS2");
421 }
Reed Kotler0ff40012013-12-10 14:29:38 +0000422 if (F_ && !isIntrinsicInline(F_)) {
Reed Kotler2c4657d2013-05-14 02:00:24 +0000423 // pic mode calls are handled by already defined
424 // helper functions
Reed Kotler0ff40012013-12-10 14:29:38 +0000425 if (needsFPReturnHelper(*F_)) {
Reed Kotler2c4657d2013-05-14 02:00:24 +0000426 Modified=true;
Reed Kotler0ff40012013-12-10 14:29:38 +0000427 F.addFnAttr("saveS2");
428 }
429 if (Subtarget.getRelocationModel() != Reloc::PIC_ ) {
430 if (needsFPHelperFromSig(*F_)) {
431 assureFPCallStub(*F_, M, Subtarget);
432 Modified=true;
433 }
Reed Kotler2c4657d2013-05-14 02:00:24 +0000434 }
435 }
Reed Kotler783c7942013-05-10 22:25:39 +0000436 }
437 }
438 return Modified;
439}
440
Reed Kotler515e9372013-05-16 02:17:42 +0000441static void createFPFnStub(Function *F, Module *M, FPParamVariant PV,
442 const MipsSubtarget &Subtarget ) {
443 bool PicMode = Subtarget.getRelocationModel() == Reloc::PIC_;
444 bool LE = Subtarget.isLittle();
445 LLVMContext &Context = M->getContext();
446 std::string Name = F->getName();
447 std::string SectionName = ".mips16.fn." + Name;
448 std::string StubName = "__fn_stub_" + Name;
Reed Kotlera6ce7972013-09-25 20:58:50 +0000449 std::string LocalName = "$$__fn_local_" + Name;
Reed Kotler515e9372013-05-16 02:17:42 +0000450 Function *FStub = Function::Create
451 (F->getFunctionType(),
Reed Kotler302ae6b2013-08-01 02:26:31 +0000452 Function::InternalLinkage, StubName, M);
Reed Kotler515e9372013-05-16 02:17:42 +0000453 FStub->addFnAttr("mips16_fp_stub");
454 FStub->addFnAttr(llvm::Attribute::Naked);
455 FStub->addFnAttr(llvm::Attribute::NoUnwind);
Reed Kotler302ae6b2013-08-01 02:26:31 +0000456 FStub->addFnAttr(llvm::Attribute::NoInline);
Reed Kotler515e9372013-05-16 02:17:42 +0000457 FStub->addFnAttr("nomips16");
458 FStub->setSection(SectionName);
459 BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub);
460 InlineAsmHelper IAH(Context, BB);
461 IAH.Out(" .set macro");
462 if (PicMode) {
463 IAH.Out(".set noreorder");
Reed Kotlera6ce7972013-09-25 20:58:50 +0000464 IAH.Out(".cpload $$25");
Reed Kotler515e9372013-05-16 02:17:42 +0000465 IAH.Out(".set reorder");
466 IAH.Out(".reloc 0,R_MIPS_NONE," + Name);
467 IAH.Out("la $$25," + LocalName);
468 }
Reed Kotler78fb2912013-09-21 01:37:52 +0000469 else {
470 IAH.Out(".set reorder");
Reed Kotlera6ce7972013-09-25 20:58:50 +0000471 IAH.Out("la $$25," + Name);
Reed Kotler78fb2912013-09-21 01:37:52 +0000472 }
Reed Kotler515e9372013-05-16 02:17:42 +0000473 swapFPIntParams(PV, M, IAH, LE, false);
474 IAH.Out("jr $$25");
475 IAH.Out(LocalName + " = " + Name);
476 new UnreachableInst(FStub->getContext(), BB);
477}
478
Reed Kotlerc03807a2013-08-30 19:40:56 +0000479//
480// remove the use-soft-float attribute
481//
482static void removeUseSoftFloat(Function &F) {
483 AttributeSet A;
484 DEBUG(errs() << "removing -use-soft-float\n");
485 A = A.addAttribute(F.getContext(), AttributeSet::FunctionIndex,
486 "use-soft-float", "false");
487 F.removeAttributes(AttributeSet::FunctionIndex, A);
488 if (F.hasFnAttribute("use-soft-float")) {
489 DEBUG(errs() << "still has -use-soft-float\n");
490 }
491 F.addAttributes(AttributeSet::FunctionIndex, A);
492}
493
Reed Kotler783c7942013-05-10 22:25:39 +0000494namespace llvm {
495
496//
497// This pass only makes sense when the underlying chip has floating point but
498// we are compiling as mips16.
499// For all mips16 functions (that are not stubs we have already generated), or
500// declared via attributes as nomips16, we must:
501// 1) fixup all returns of float, double, single and double complex
502// by calling a helper function before the actual return.
Reed Kotler4cdaa7d2014-02-14 19:16:39 +0000503// 2) generate helper functions (stubs) that can be called by mips32
504// functions that will move parameters passed normally passed in
505// floating point
Reed Kotler515e9372013-05-16 02:17:42 +0000506// registers the soft float equivalents.
Reed Kotler783c7942013-05-10 22:25:39 +0000507// 3) in the case of static relocation, generate helper functions so that
508// mips16 functions can call extern functions of unknown type (mips16 or
Reed Kotler515e9372013-05-16 02:17:42 +0000509// mips32).
Reed Kotler783c7942013-05-10 22:25:39 +0000510// 4) TBD. For pic, calls to extern functions of unknown type are handled by
511// predefined helper functions in libc but this work is currently done
512// during call lowering but it should be moved here in the future.
513//
514bool Mips16HardFloat::runOnModule(Module &M) {
515 DEBUG(errs() << "Run on Module Mips16HardFloat\n");
516 bool Modified = false;
517 for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
Reed Kotlerc03807a2013-08-30 19:40:56 +0000518 if (F->hasFnAttribute("nomips16") &&
519 F->hasFnAttribute("use-soft-float")) {
520 removeUseSoftFloat(*F);
521 continue;
522 }
Reed Kotler783c7942013-05-10 22:25:39 +0000523 if (F->isDeclaration() || F->hasFnAttribute("mips16_fp_stub") ||
524 F->hasFnAttribute("nomips16")) continue;
525 Modified |= fixupFPReturnAndCall(*F, &M, Subtarget);
Reed Kotler515e9372013-05-16 02:17:42 +0000526 FPParamVariant V = whichFPParamVariantNeeded(*F);
527 if (V != NoSig) {
528 Modified = true;
529 createFPFnStub(F, &M, V, Subtarget);
530 }
Reed Kotler783c7942013-05-10 22:25:39 +0000531 }
532 return Modified;
533}
534
535char Mips16HardFloat::ID = 0;
536
537}
538
539ModulePass *llvm::createMips16HardFloat(MipsTargetMachine &TM) {
540 return new Mips16HardFloat(TM);
541}
542