xref: /minix3/external/bsd/llvm/dist/llvm/lib/Target/Mips/MipsOs16.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===---- MipsOs16.cpp for Mips Option -Os16                       --------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file defines an optimization phase for the MIPS target.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "MipsOs16.h"
15f4a2713aSLionel Sambuc #include "llvm/IR/Module.h"
16f4a2713aSLionel Sambuc #include "llvm/Support/CommandLine.h"
17f4a2713aSLionel Sambuc #include "llvm/Support/Debug.h"
18f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
19f4a2713aSLionel Sambuc 
20*0a6a1f1dSLionel Sambuc #define DEBUG_TYPE "mips-os16"
21*0a6a1f1dSLionel Sambuc 
22f4a2713aSLionel Sambuc 
23f4a2713aSLionel Sambuc static cl::opt<std::string> Mips32FunctionMask(
24f4a2713aSLionel Sambuc   "mips32-function-mask",
25f4a2713aSLionel Sambuc   cl::init(""),
26f4a2713aSLionel Sambuc   cl::desc("Force function to be mips32"),
27f4a2713aSLionel Sambuc   cl::Hidden);
28f4a2713aSLionel Sambuc 
29f4a2713aSLionel Sambuc namespace {
30f4a2713aSLionel Sambuc 
31f4a2713aSLionel Sambuc   // Figure out if we need float point based on the function signature.
32f4a2713aSLionel Sambuc   // We need to move variables in and/or out of floating point
33f4a2713aSLionel Sambuc   // registers because of the ABI
34f4a2713aSLionel Sambuc   //
needsFPFromSig(Function & F)35f4a2713aSLionel Sambuc   bool needsFPFromSig(Function &F) {
36f4a2713aSLionel Sambuc     Type* RetType = F.getReturnType();
37f4a2713aSLionel Sambuc     switch (RetType->getTypeID()) {
38f4a2713aSLionel Sambuc     case Type::FloatTyID:
39f4a2713aSLionel Sambuc     case Type::DoubleTyID:
40f4a2713aSLionel Sambuc       return true;
41f4a2713aSLionel Sambuc     default:
42f4a2713aSLionel Sambuc       ;
43f4a2713aSLionel Sambuc     }
44f4a2713aSLionel Sambuc     if (F.arg_size() >=1) {
45f4a2713aSLionel Sambuc       Argument &Arg = F.getArgumentList().front();
46f4a2713aSLionel Sambuc       switch (Arg.getType()->getTypeID()) {
47f4a2713aSLionel Sambuc         case Type::FloatTyID:
48f4a2713aSLionel Sambuc         case Type::DoubleTyID:
49f4a2713aSLionel Sambuc           return true;
50f4a2713aSLionel Sambuc         default:
51f4a2713aSLionel Sambuc           ;
52f4a2713aSLionel Sambuc       }
53f4a2713aSLionel Sambuc     }
54f4a2713aSLionel Sambuc     return false;
55f4a2713aSLionel Sambuc   }
56f4a2713aSLionel Sambuc 
57f4a2713aSLionel Sambuc   // Figure out if the function will need floating point operations
58f4a2713aSLionel Sambuc   //
needsFP(Function & F)59f4a2713aSLionel Sambuc   bool needsFP(Function &F) {
60f4a2713aSLionel Sambuc     if (needsFPFromSig(F))
61f4a2713aSLionel Sambuc       return true;
62f4a2713aSLionel Sambuc     for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
63f4a2713aSLionel Sambuc       for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();
64f4a2713aSLionel Sambuc          I != E; ++I) {
65f4a2713aSLionel Sambuc         const Instruction &Inst = *I;
66f4a2713aSLionel Sambuc         switch (Inst.getOpcode()) {
67f4a2713aSLionel Sambuc         case Instruction::FAdd:
68f4a2713aSLionel Sambuc         case Instruction::FSub:
69f4a2713aSLionel Sambuc         case Instruction::FMul:
70f4a2713aSLionel Sambuc         case Instruction::FDiv:
71f4a2713aSLionel Sambuc         case Instruction::FRem:
72f4a2713aSLionel Sambuc         case Instruction::FPToUI:
73f4a2713aSLionel Sambuc         case Instruction::FPToSI:
74f4a2713aSLionel Sambuc         case Instruction::UIToFP:
75f4a2713aSLionel Sambuc         case Instruction::SIToFP:
76f4a2713aSLionel Sambuc         case Instruction::FPTrunc:
77f4a2713aSLionel Sambuc         case Instruction::FPExt:
78f4a2713aSLionel Sambuc         case Instruction::FCmp:
79f4a2713aSLionel Sambuc           return true;
80f4a2713aSLionel Sambuc         default:
81f4a2713aSLionel Sambuc           ;
82f4a2713aSLionel Sambuc         }
83f4a2713aSLionel Sambuc         if (const CallInst *CI = dyn_cast<CallInst>(I)) {
84f4a2713aSLionel Sambuc           DEBUG(dbgs() << "Working on call" << "\n");
85f4a2713aSLionel Sambuc           Function &F_ =  *CI->getCalledFunction();
86f4a2713aSLionel Sambuc           if (needsFPFromSig(F_))
87f4a2713aSLionel Sambuc             return true;
88f4a2713aSLionel Sambuc         }
89f4a2713aSLionel Sambuc       }
90f4a2713aSLionel Sambuc     return false;
91f4a2713aSLionel Sambuc   }
92f4a2713aSLionel Sambuc }
93f4a2713aSLionel Sambuc namespace llvm {
94f4a2713aSLionel Sambuc 
95f4a2713aSLionel Sambuc 
runOnModule(Module & M)96f4a2713aSLionel Sambuc bool MipsOs16::runOnModule(Module &M) {
97f4a2713aSLionel Sambuc   bool usingMask = Mips32FunctionMask.length() > 0;
98f4a2713aSLionel Sambuc   bool doneUsingMask = false; // this will make it stop repeating
99f4a2713aSLionel Sambuc   DEBUG(dbgs() << "Run on Module MipsOs16 \n" << Mips32FunctionMask << "\n");
100f4a2713aSLionel Sambuc   if (usingMask)
101f4a2713aSLionel Sambuc     DEBUG(dbgs() << "using mask \n" << Mips32FunctionMask << "\n");
102f4a2713aSLionel Sambuc   unsigned int functionIndex = 0;
103f4a2713aSLionel Sambuc   bool modified = false;
104f4a2713aSLionel Sambuc   for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
105f4a2713aSLionel Sambuc     if (F->isDeclaration()) continue;
106f4a2713aSLionel Sambuc     DEBUG(dbgs() << "Working on " << F->getName() << "\n");
107f4a2713aSLionel Sambuc     if (usingMask) {
108f4a2713aSLionel Sambuc       if (!doneUsingMask) {
109f4a2713aSLionel Sambuc         if (functionIndex == Mips32FunctionMask.length())
110f4a2713aSLionel Sambuc           functionIndex = 0;
111f4a2713aSLionel Sambuc         switch (Mips32FunctionMask[functionIndex]) {
112f4a2713aSLionel Sambuc         case '1':
113f4a2713aSLionel Sambuc           DEBUG(dbgs() << "mask forced mips32: " << F->getName() << "\n");
114f4a2713aSLionel Sambuc           F->addFnAttr("nomips16");
115f4a2713aSLionel Sambuc           break;
116f4a2713aSLionel Sambuc         case '.':
117f4a2713aSLionel Sambuc           doneUsingMask = true;
118f4a2713aSLionel Sambuc           break;
119f4a2713aSLionel Sambuc         default:
120f4a2713aSLionel Sambuc           break;
121f4a2713aSLionel Sambuc         }
122f4a2713aSLionel Sambuc         functionIndex++;
123f4a2713aSLionel Sambuc       }
124f4a2713aSLionel Sambuc     }
125f4a2713aSLionel Sambuc     else {
126f4a2713aSLionel Sambuc       if (needsFP(*F)) {
127f4a2713aSLionel Sambuc         DEBUG(dbgs() << "os16 forced mips32: " << F->getName() << "\n");
128f4a2713aSLionel Sambuc         F->addFnAttr("nomips16");
129f4a2713aSLionel Sambuc       }
130f4a2713aSLionel Sambuc       else {
131f4a2713aSLionel Sambuc         DEBUG(dbgs() << "os16 forced mips16: " << F->getName() << "\n");
132f4a2713aSLionel Sambuc         F->addFnAttr("mips16");
133f4a2713aSLionel Sambuc       }
134f4a2713aSLionel Sambuc     }
135f4a2713aSLionel Sambuc   }
136f4a2713aSLionel Sambuc   return modified;
137f4a2713aSLionel Sambuc }
138f4a2713aSLionel Sambuc 
139f4a2713aSLionel Sambuc char MipsOs16::ID = 0;
140f4a2713aSLionel Sambuc 
141f4a2713aSLionel Sambuc }
142f4a2713aSLionel Sambuc 
createMipsOs16(MipsTargetMachine & TM)143f4a2713aSLionel Sambuc ModulePass *llvm::createMipsOs16(MipsTargetMachine &TM) {
144f4a2713aSLionel Sambuc   return new MipsOs16;
145f4a2713aSLionel Sambuc }
146f4a2713aSLionel Sambuc 
147f4a2713aSLionel Sambuc 
148