/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Target/Mips/MipsOs16.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===---- MipsOs16.cpp for Mips Option -Os16 --------===// |
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 an optimization phase for the MIPS target. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "Mips.h" |
15 | | #include "llvm/IR/Instructions.h" |
16 | | #include "llvm/IR/Module.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(""), |
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 | 7 | MipsOs16() : ModulePass(ID) {} |
37 | | |
38 | 0 | 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 | 20 | static bool needsFPFromSig(Function &F) { |
51 | 20 | Type* RetType = F.getReturnType(); |
52 | 20 | switch (RetType->getTypeID()) { |
53 | 5 | case Type::FloatTyID: |
54 | 5 | case Type::DoubleTyID: |
55 | 5 | return true; |
56 | 15 | default: |
57 | 15 | ; |
58 | 20 | } |
59 | 15 | if (15 F.arg_size() >=115 ) { |
60 | 5 | Argument &Arg = *F.arg_begin(); |
61 | 5 | switch (Arg.getType()->getTypeID()) { |
62 | 3 | case Type::FloatTyID: |
63 | 3 | case Type::DoubleTyID: |
64 | 3 | return true; |
65 | 2 | default: |
66 | 2 | ; |
67 | 5 | } |
68 | 5 | } |
69 | 12 | return false; |
70 | 20 | } |
71 | | |
72 | | // Figure out if the function will need floating point operations |
73 | | // |
74 | 18 | static bool needsFP(Function &F) { |
75 | 18 | if (needsFPFromSig(F)) |
76 | 6 | return true; |
77 | 21 | for (Function::const_iterator BB = F.begin(), E = F.end(); 12 BB != E21 ; ++BB9 ) |
78 | 12 | for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); |
79 | 37 | I != E37 ; ++I25 ) { |
80 | 28 | const Instruction &Inst = *I; |
81 | 28 | switch (Inst.getOpcode()) { |
82 | 1 | case Instruction::FAdd: |
83 | 1 | case Instruction::FSub: |
84 | 1 | case Instruction::FMul: |
85 | 1 | case Instruction::FDiv: |
86 | 1 | case Instruction::FRem: |
87 | 1 | case Instruction::FPToUI: |
88 | 1 | case Instruction::FPToSI: |
89 | 1 | case Instruction::UIToFP: |
90 | 1 | case Instruction::SIToFP: |
91 | 1 | case Instruction::FPTrunc: |
92 | 1 | case Instruction::FPExt: |
93 | 1 | case Instruction::FCmp: |
94 | 1 | return true; |
95 | 27 | default: |
96 | 27 | ; |
97 | 28 | } |
98 | 27 | if (const CallInst *27 CI27 = dyn_cast<CallInst>(I)) { |
99 | 2 | DEBUG(dbgs() << "Working on call" << "\n"); |
100 | 2 | Function &F_ = *CI->getCalledFunction(); |
101 | 2 | if (needsFPFromSig(F_)) |
102 | 2 | return true; |
103 | 2 | } |
104 | 12 | } |
105 | 9 | return false; |
106 | 18 | } |
107 | | |
108 | | |
109 | 7 | bool MipsOs16::runOnModule(Module &M) { |
110 | 7 | bool usingMask = Mips32FunctionMask.length() > 0; |
111 | 7 | bool doneUsingMask = false; // this will make it stop repeating |
112 | 7 | |
113 | 7 | DEBUG(dbgs() << "Run on Module MipsOs16 \n" << Mips32FunctionMask << "\n"); |
114 | 7 | if (usingMask) |
115 | 7 | DEBUG(dbgs() << "using mask \n" << Mips32FunctionMask << "\n"); |
116 | 7 | |
117 | 7 | unsigned int functionIndex = 0; |
118 | 7 | bool modified = false; |
119 | 7 | |
120 | 80 | for (auto &F : M) { |
121 | 80 | if (F.isDeclaration()) |
122 | 24 | continue; |
123 | 56 | |
124 | 56 | DEBUG56 (dbgs() << "Working on " << F.getName() << "\n"); |
125 | 56 | if (usingMask56 ) { |
126 | 38 | if (!doneUsingMask38 ) { |
127 | 37 | if (functionIndex == Mips32FunctionMask.length()) |
128 | 5 | functionIndex = 0; |
129 | 37 | switch (Mips32FunctionMask[functionIndex]) { |
130 | 23 | case '1': |
131 | 23 | DEBUG(dbgs() << "mask forced mips32: " << F.getName() << "\n"); |
132 | 23 | F.addFnAttr("nomips16"); |
133 | 23 | break; |
134 | 1 | case '.': |
135 | 1 | doneUsingMask = true; |
136 | 1 | break; |
137 | 13 | default: |
138 | 13 | break; |
139 | 37 | } |
140 | 37 | functionIndex++; |
141 | 37 | } |
142 | 38 | } |
143 | 18 | else { |
144 | 18 | if (needsFP(F)18 ) { |
145 | 9 | DEBUG(dbgs() << "os16 forced mips32: " << F.getName() << "\n"); |
146 | 9 | F.addFnAttr("nomips16"); |
147 | 9 | } |
148 | 9 | else { |
149 | 9 | DEBUG(dbgs() << "os16 forced mips16: " << F.getName() << "\n"); |
150 | 9 | F.addFnAttr("mips16"); |
151 | 9 | } |
152 | 18 | } |
153 | 80 | } |
154 | 7 | |
155 | 7 | return modified; |
156 | 7 | } |
157 | | |
158 | 7 | ModulePass *llvm::createMipsOs16Pass() { return new MipsOs16(); } |