1//===---- MipsOs16.cpp for Mips Option -Os16 --------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines an optimization phase for the MIPS target.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Mips.h"
14#include "MipsSubtarget.h"
15#include "llvm/IR/Instructions.h"
16#include "llvm/IR/Module.h"
17#include "llvm/Pass.h"
18#include "llvm/Support/Debug.h"
19#include "llvm/Support/raw_ostream.h"
20
21using namespace llvm;
22
23#define DEBUG_TYPE "mips-os16"
24
25namespace {
26 class MipsOs16 : public ModulePass {
27 public:
28 static char ID;
29
30 MipsOs16() : ModulePass(ID) {}
31
32 StringRef getPassName() const override { return "MIPS Os16 Optimization"; }
33
34 bool runOnModule(Module &M) override;
35 };
36
37 char MipsOs16::ID = 0;
38}
39
40// Figure out if we need float point based on the function signature.
41// We need to move variables in and/or out of floating point
42// registers because of the ABI
43//
44static bool needsFPFromSig(Function &F) {
45 Type* RetType = F.getReturnType();
46 switch (RetType->getTypeID()) {
47 case Type::FloatTyID:
48 case Type::DoubleTyID:
49 return true;
50 default:
51 ;
52 }
53 if (F.arg_size() >=1) {
54 Argument &Arg = *F.arg_begin();
55 switch (Arg.getType()->getTypeID()) {
56 case Type::FloatTyID:
57 case Type::DoubleTyID:
58 return true;
59 default:
60 ;
61 }
62 }
63 return false;
64}
65
66// Figure out if the function will need floating point operations
67//
68static bool needsFP(Function &F) {
69 if (needsFPFromSig(F))
70 return true;
71 for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
72 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();
73 I != E; ++I) {
74 const Instruction &Inst = *I;
75 switch (Inst.getOpcode()) {
76 case Instruction::FAdd:
77 case Instruction::FSub:
78 case Instruction::FMul:
79 case Instruction::FDiv:
80 case Instruction::FRem:
81 case Instruction::FPToUI:
82 case Instruction::FPToSI:
83 case Instruction::UIToFP:
84 case Instruction::SIToFP:
85 case Instruction::FPTrunc:
86 case Instruction::FPExt:
87 case Instruction::FCmp:
88 return true;
89 default:
90 ;
91 }
92 if (const CallInst *CI = dyn_cast<CallInst>(Val&: I)) {
93 LLVM_DEBUG(dbgs() << "Working on call"
94 << "\n");
95 Function &F_ = *CI->getCalledFunction();
96 if (needsFPFromSig(F&: F_))
97 return true;
98 }
99 }
100 return false;
101}
102
103
104bool MipsOs16::runOnModule(Module &M) {
105 const MipsOptions &Opts =
106 M.getContext().getLibraryOptions().get<MipsOptions>();
107 StringRef Mips32FunctionMask = Opts.mips32_function_mask;
108 bool usingMask = !Mips32FunctionMask.empty();
109 bool doneUsingMask = false; // this will make it stop repeating
110
111 LLVM_DEBUG(dbgs() << "Run on Module MipsOs16 \n"
112 << Mips32FunctionMask << "\n");
113 if (usingMask)
114 LLVM_DEBUG(dbgs() << "using mask \n" << Mips32FunctionMask << "\n");
115
116 unsigned int functionIndex = 0;
117 bool modified = false;
118
119 for (auto &F : M) {
120 if (F.isDeclaration())
121 continue;
122
123 LLVM_DEBUG(dbgs() << "Working on " << F.getName() << "\n");
124 if (usingMask) {
125 if (!doneUsingMask) {
126 if (functionIndex == Mips32FunctionMask.size())
127 functionIndex = 0;
128 switch (Mips32FunctionMask[functionIndex]) {
129 case '1':
130 LLVM_DEBUG(dbgs() << "mask forced mips32: " << F.getName() << "\n");
131 F.addFnAttr(Kind: "nomips16");
132 break;
133 case '.':
134 doneUsingMask = true;
135 break;
136 default:
137 break;
138 }
139 functionIndex++;
140 }
141 }
142 else {
143 if (needsFP(F)) {
144 LLVM_DEBUG(dbgs() << "os16 forced mips32: " << F.getName() << "\n");
145 F.addFnAttr(Kind: "nomips16");
146 }
147 else {
148 LLVM_DEBUG(dbgs() << "os16 forced mips16: " << F.getName() << "\n");
149 F.addFnAttr(Kind: "mips16");
150 }
151 }
152 }
153
154 return modified;
155}
156
157ModulePass *llvm::createMipsOs16Pass() { return new MipsOs16(); }
158