LLVM: lib/Target/Mips/Mips16HardFloat.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

20#include

21

22using namespace llvm;

23

24#define DEBUG_TYPE "mips16-hard-float"

25

26namespace {

27

28 class Mips16HardFloat : public ModulePass {

29 public:

30 static char ID;

31

33

34 StringRef getPassName() const override { return "MIPS16 Hard Float Pass"; }

35

36 void getAnalysisUsage(AnalysisUsage &AU) const override {

39 }

40

41 bool runOnModule(Module &M) override;

42 };

43

44}

45

47 std::vector<Type *> AsmArgTypes;

48 std::vector<Value *> AsmArgs;

49

55}

56

57char Mips16HardFloat::ID = 0;

58

59

60

61

62

66

67

68

69

71 switch (T->getTypeID()) {

78 if (ST->getNumElements() != 2)

79 break;

80 if ((ST->getElementType(0)->isFloatTy()) &&

81 (ST->getElementType(1)->isFloatTy()))

83 if ((ST->getElementType(0)->isDoubleTy()) &&

84 (ST->getElementType(1)->isDoubleTy()))

86 break;

87 }

88 default:

89 break;

90 }

92}

93

94

95

100

101

105

107 switch (F.arg_size()) {

108 case 0:

110 case 1:{

111 TypeID ArgTypeID = F.getFunctionType()->getParamType(0)->getTypeID();

112 switch (ArgTypeID) {

117 default:

119 }

120 }

121 default: {

122 TypeID ArgTypeID0 = F.getFunctionType()->getParamType(0)->getTypeID();

123 TypeID ArgTypeID1 = F.getFunctionType()->getParamType(1)->getTypeID();

124 switch(ArgTypeID0) {

126 switch (ArgTypeID1) {

131 default:

133 }

134 }

136 switch (ArgTypeID1) {

141 default:

143 }

144 }

145 default:

147 }

148 }

149 }

151}

152

153

154

155

157 if (F.arg_size() >=1) {

158 Type *ArgType = F.getFunctionType()->getParamType(0);

162 return true;

163 default:

164 break;

165 }

166 }

167 return false;

168}

169

171 Type* RetType = F.getReturnType();

173}

174

176 Type* RetType = FT.getReturnType();

178}

179

183

184

185

187 bool ToFP) {

188 std::string MI = ToFP ? "mtc1 ": "mfc1 ";

189 std::string AsmText;

190

191 switch (PV) {

193 AsmText += MI + "$$4, f12\n";

194 break;

195

197 AsmText += MI + "$$4, f12\n";

198 AsmText += MI + "$$5, f14\n";

199 break;

200

202 AsmText += MI + "$$4, f12\n";

203 if (LE) {

204 AsmText += MI + "$$6, f14\n";

205 AsmText += MI + "$$7, f15\n";

206 } else {

207 AsmText += MI + "$$7, f14\n";

208 AsmText += MI + "$$6, f15\n";

209 }

210 break;

211

213 if (LE) {

214 AsmText += MI + "$$4, f12\n";

215 AsmText += MI + "$$5, f13\n";

216 } else {

217 AsmText += MI + "$$5, f12\n";

218 AsmText += MI + "$$4, f13\n";

219 }

220 break;

221

223 if (LE) {

224 AsmText += MI + "$$4, f12\n";

225 AsmText += MI + "$$5, f13\n";

226 AsmText += MI + "$$6, f14\n";

227 AsmText += MI + "$$7, f15\n";

228 } else {

229 AsmText += MI + "$$5, f12\n";

230 AsmText += MI + "$$4, f13\n";

231 AsmText += MI + "$$7, f14\n";

232 AsmText += MI + "$$6, f15\n";

233 }

234 break;

235

237 if (LE) {

238 AsmText += MI + "$$4, f12\n";

239 AsmText += MI + "$$5, f13\n";

240 } else {

241 AsmText += MI + "$$5, f12\n";

242 AsmText += MI + "$$4, f13\n";

243 }

244 AsmText += MI + "$$6, f14\n";

245 break;

246

248 break;

249 }

250

251 return AsmText;

252}

253

254

255

258

260 return;

263 std::string Name(F.getName());

264 std::string SectionName = ".mips16.call.fp." + Name;

265 std::string StubName = "__call_stub_fp_" + Name;

266

267

268

273 FStub->addFnAttr("mips16_fp_stub");

274 FStub->addFnAttr(Attribute::Naked);

275 FStub->addFnAttr(Attribute::NoInline);

276 FStub->addFnAttr(Attribute::NoUnwind);

282

283 std::string AsmText;

284 AsmText += ".set reorder\n";

287 AsmText += "move 18, 31\n";

288 AsmText += "jal " + Name + "\n";

289 } else {

290 AsmText += "lui 25, %hi(" + Name + ")\n";

291 AsmText += "addiu 25, 25, %lo(" + Name + ")\n";

292 }

293

294 switch (RV) {

296 AsmText += "mfc1 2, f0\n";

297 break;

298

300 if (LE) {

301 AsmText += "mfc1 2, f0\n";

302 AsmText += "mfc1 3, f1\n";

303 } else {

304 AsmText += "mfc1 3, f0\n";

305 AsmText += "mfc1 2, f1\n";

306 }

307 break;

308

310 if (LE) {

311 AsmText += "mfc1 2, f0\n";

312 AsmText += "mfc1 3, f2\n";

313 } else {

314 AsmText += "mfc1 3, f0\n";

315 AsmText += "mfc1 3, f2\n";

316 }

317 break;

318

320 if (LE) {

321 AsmText += "mfc1 4, f2\n";

322 AsmText += "mfc1 5, f3\n";

323 AsmText += "mfc1 2, f0\n";

324 AsmText += "mfc1 3, f1\n";

325

326 } else {

327 AsmText += "mfc1 5, f2\n";

328 AsmText += "mfc1 4, f3\n";

329 AsmText += "mfc1 3, f0\n";

330 AsmText += "mfc1 2, f1\n";

331 }

332 break;

333

335 break;

336 }

337

339 AsmText += "jr 18\n";

340 else

341 AsmText += "jr 25\n";

343

345}

346

347

349 "fabs", "fabsf",

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.i32", "llvm.powi.f64.i32",

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",

368};

369

373

374

375

381 for (auto &BB: F)

382 for (auto &I: BB) {

384 Value *RVal = RI->getReturnValue();

385 if (!RVal) continue;

386

387

388

389

390

391

392

395 if (RV == NoFPRet) continue;

396 static const char *const Helper[NoFPRet] = {

397 "__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc",

398 "__mips16_ret_dc"

399 };

400 const char *Name = Helper[RV];

401 AttributeList A;

402 Value *Params[] = {RVal};

404

405

406

407

408

409

410 A = A.addFnAttribute(C, "__Mips16RetHelper");

411 A = A.addFnAttribute(

413 A = A.addFnAttribute(C, Attribute::NoInline);

418 Function *F_ = CI->getCalledFunction();

422 F.addFnAttr("saveS2");

423 }

425

426

429 F.addFnAttr("saveS2");

430 }

435 }

436 }

437 }

438 }

439 }

441}

442

448 std::string Name(F->getName());

449 std::string SectionName = ".mips16.fn." + Name;

450 std::string StubName = "__fn_stub_" + Name;

451 std::string LocalName = "$$__fn_local_" + Name;

453 (F->getFunctionType(),

455 FStub->addFnAttr("mips16_fp_stub");

456 FStub->addFnAttr(Attribute::Naked);

457 FStub->addFnAttr(Attribute::NoUnwind);

458 FStub->addFnAttr(Attribute::NoInline);

462

463 std::string AsmText;

464 if (PicMode) {

465 AsmText += ".set noreorder\n";

466 AsmText += ".cpload 25\n";

467 AsmText += ".set reorder\n";

468 AsmText += ".reloc 0, R_MIPS_NONE, " + Name + "\n";

469 AsmText += "la 25, " + LocalName + "\n";

470 } else

471 AsmText += "la 25, " + Name + "\n";

473 AsmText += "jr 25\n";

474 AsmText += LocalName + " = " + Name + "\n";

476

478}

479

480

483 F.removeFnAttr("use-soft-float");

484 if (F.hasFnAttribute("use-soft-float")) {

486 }

487 F.addFnAttr("use-soft-float", "false");

488}

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506bool Mips16HardFloat::runOnModule(Module &M) {

507 auto &TM = static_cast<const MipsTargetMachine &>(

508 getAnalysis().getTM());

509 LLVM_DEBUG(errs() << "Run on Module Mips16HardFloat\n");

511 for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {

512 if (F->hasFnAttribute("nomips16") &&

513 F->hasFnAttribute("use-soft-float")) {

515 continue;

516 }

517 if (F->isDeclaration() || F->hasFnAttribute("mips16_fp_stub") ||

518 F->hasFnAttribute("nomips16")) continue;

521 if (V != NoSig) {

524 }

525 }

527}

528

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

Module.h This file contains the declarations for the Module class.

FPReturnVariant

Definition Mips16HardFloat.cpp:63

@ CDRet

Definition Mips16HardFloat.cpp:64

@ NoFPRet

Definition Mips16HardFloat.cpp:64

@ DRet

Definition Mips16HardFloat.cpp:64

@ CFRet

Definition Mips16HardFloat.cpp:64

@ FRet

Definition Mips16HardFloat.cpp:64

static bool fixupFPReturnAndCall(Function &F, Module *M, const MipsTargetMachine &TM)

Definition Mips16HardFloat.cpp:376

static bool needsFPStubFromParams(Function &F)

Definition Mips16HardFloat.cpp:156

static bool needsFPReturnHelper(Function &F)

Definition Mips16HardFloat.cpp:170

static bool needsFPHelperFromSig(Function &F)

Definition Mips16HardFloat.cpp:180

const Type::TypeID FloatTyID

Definition Mips16HardFloat.cpp:103

static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, const MipsTargetMachine &TM)

Definition Mips16HardFloat.cpp:443

FPParamVariant

Definition Mips16HardFloat.cpp:96

@ DDSig

Definition Mips16HardFloat.cpp:98

@ DFSig

Definition Mips16HardFloat.cpp:98

@ FDSig

Definition Mips16HardFloat.cpp:97

@ NoSig

Definition Mips16HardFloat.cpp:98

@ FFSig

Definition Mips16HardFloat.cpp:97

@ DSig

Definition Mips16HardFloat.cpp:98

@ FSig

Definition Mips16HardFloat.cpp:97

Type::TypeID TypeID

Definition Mips16HardFloat.cpp:102

static void removeUseSoftFloat(Function &F)

Definition Mips16HardFloat.cpp:481

static const char *const IntrinsicInline[]

Definition Mips16HardFloat.cpp:348

static bool isIntrinsicInline(Function *F)

Definition Mips16HardFloat.cpp:370

static void emitInlineAsm(LLVMContext &C, BasicBlock *BB, StringRef AsmText)

Definition Mips16HardFloat.cpp:46

static FPReturnVariant whichFPReturnVariant(Type *T)

Definition Mips16HardFloat.cpp:70

const Type::TypeID DoubleTyID

Definition Mips16HardFloat.cpp:104

static std::string swapFPIntParams(FPParamVariant PV, Module *M, bool LE, bool ToFP)

Definition Mips16HardFloat.cpp:186

static FPParamVariant whichFPParamVariantNeeded(Function &F)

Definition Mips16HardFloat.cpp:106

static void assureFPCallStub(Function &F, Module *M, const MipsTargetMachine &TM)

Definition Mips16HardFloat.cpp:256

static cl::opt< bool > Mips16HardFloat("mips16-hard-float", cl::NotHidden, cl::desc("Enable mips16 hard float."), cl::init(false))

Target-Independent Code Generator Pass Configuration Options pass.

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

static LLVM_ABI 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...

static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)

This static method is the primary way of constructing a FunctionType.

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)

const Function & getFunction() const

LLVMContext & getContext() const

getContext - Return a reference to the LLVMContext associated with this function.

Type * getReturnType() const

Returns the type of the ret val.

LLVM_ABI void setSection(StringRef S)

Change the section for this global.

LLVM_ABI bool isDeclaration() const

Return true if the primary definition of this global value is outside of the current translation unit...

@ InternalLinkage

Rename collisions when linking (static functions).

static LLVM_ABI 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()

bool isLittleEndian() const

ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...

A Module instance is used to store all the information related to an LLVM module.

virtual void getAnalysisUsage(AnalysisUsage &) const

getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...

Return a value (possibly void), from a function.

StringRef - Represent a constant reference to a string, i.e.

Class to represent struct types.

bool isPositionIndependent() const

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 LLVM_ABI 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.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

auto binary_search(R &&Range, T &&Value)

Provide wrappers to std::binary_search which take ranges instead of having to pass begin/end explicit...

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

ModulePass * createMips16HardFloatPass()

Definition Mips16HardFloat.cpp:529