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