1251607Sdim//===---- MipsOs16.cpp for Mips Option -Os16 --------===// 2251607Sdim// 3251607Sdim// The LLVM Compiler Infrastructure 4251607Sdim// 5251607Sdim// This file is distributed under the University of Illinois Open Source 6251607Sdim// License. See LICENSE.TXT for details. 7251607Sdim// 8251607Sdim//===----------------------------------------------------------------------===// 9251607Sdim// 10251607Sdim// This file defines an optimization phase for the MIPS target. 11251607Sdim// 12251607Sdim//===----------------------------------------------------------------------===// 13251607Sdim 14251607Sdim#define DEBUG_TYPE "mips-os16" 15251607Sdim#include "MipsOs16.h" 16251607Sdim#include "llvm/IR/Module.h" 17263508Sdim#include "llvm/Support/CommandLine.h" 18251607Sdim#include "llvm/Support/Debug.h" 19251607Sdim#include "llvm/Support/raw_ostream.h" 20251607Sdim 21263508Sdim 22263508Sdimstatic cl::opt<std::string> Mips32FunctionMask( 23263508Sdim "mips32-function-mask", 24263508Sdim cl::init(""), 25263508Sdim cl::desc("Force function to be mips32"), 26263508Sdim cl::Hidden); 27263508Sdim 28251607Sdimnamespace { 29251607Sdim 30251607Sdim // Figure out if we need float point based on the function signature. 31251607Sdim // We need to move variables in and/or out of floating point 32251607Sdim // registers because of the ABI 33251607Sdim // 34251607Sdim bool needsFPFromSig(Function &F) { 35251607Sdim Type* RetType = F.getReturnType(); 36251607Sdim switch (RetType->getTypeID()) { 37251607Sdim case Type::FloatTyID: 38251607Sdim case Type::DoubleTyID: 39251607Sdim return true; 40251607Sdim default: 41251607Sdim ; 42251607Sdim } 43251607Sdim if (F.arg_size() >=1) { 44251607Sdim Argument &Arg = F.getArgumentList().front(); 45251607Sdim switch (Arg.getType()->getTypeID()) { 46251607Sdim case Type::FloatTyID: 47251607Sdim case Type::DoubleTyID: 48251607Sdim return true; 49251607Sdim default: 50251607Sdim ; 51251607Sdim } 52251607Sdim } 53251607Sdim return false; 54251607Sdim } 55251607Sdim 56251607Sdim // Figure out if the function will need floating point operations 57251607Sdim // 58251607Sdim bool needsFP(Function &F) { 59251607Sdim if (needsFPFromSig(F)) 60251607Sdim return true; 61251607Sdim for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) 62251607Sdim for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); 63251607Sdim I != E; ++I) { 64251607Sdim const Instruction &Inst = *I; 65251607Sdim switch (Inst.getOpcode()) { 66251607Sdim case Instruction::FAdd: 67251607Sdim case Instruction::FSub: 68251607Sdim case Instruction::FMul: 69251607Sdim case Instruction::FDiv: 70251607Sdim case Instruction::FRem: 71251607Sdim case Instruction::FPToUI: 72251607Sdim case Instruction::FPToSI: 73251607Sdim case Instruction::UIToFP: 74251607Sdim case Instruction::SIToFP: 75251607Sdim case Instruction::FPTrunc: 76251607Sdim case Instruction::FPExt: 77251607Sdim case Instruction::FCmp: 78251607Sdim return true; 79251607Sdim default: 80251607Sdim ; 81251607Sdim } 82251607Sdim if (const CallInst *CI = dyn_cast<CallInst>(I)) { 83251607Sdim DEBUG(dbgs() << "Working on call" << "\n"); 84251607Sdim Function &F_ = *CI->getCalledFunction(); 85251607Sdim if (needsFPFromSig(F_)) 86251607Sdim return true; 87251607Sdim } 88251607Sdim } 89251607Sdim return false; 90251607Sdim } 91251607Sdim} 92251607Sdimnamespace llvm { 93251607Sdim 94251607Sdim 95251607Sdimbool MipsOs16::runOnModule(Module &M) { 96263508Sdim bool usingMask = Mips32FunctionMask.length() > 0; 97263508Sdim bool doneUsingMask = false; // this will make it stop repeating 98263508Sdim DEBUG(dbgs() << "Run on Module MipsOs16 \n" << Mips32FunctionMask << "\n"); 99263508Sdim if (usingMask) 100263508Sdim DEBUG(dbgs() << "using mask \n" << Mips32FunctionMask << "\n"); 101263508Sdim unsigned int functionIndex = 0; 102251607Sdim bool modified = false; 103251607Sdim for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { 104251607Sdim if (F->isDeclaration()) continue; 105251607Sdim DEBUG(dbgs() << "Working on " << F->getName() << "\n"); 106263508Sdim if (usingMask) { 107263508Sdim if (!doneUsingMask) { 108263508Sdim if (functionIndex == Mips32FunctionMask.length()) 109263508Sdim functionIndex = 0; 110263508Sdim switch (Mips32FunctionMask[functionIndex]) { 111263508Sdim case '1': 112263508Sdim DEBUG(dbgs() << "mask forced mips32: " << F->getName() << "\n"); 113263508Sdim F->addFnAttr("nomips16"); 114263508Sdim break; 115263508Sdim case '.': 116263508Sdim doneUsingMask = true; 117263508Sdim break; 118263508Sdim default: 119263508Sdim break; 120263508Sdim } 121263508Sdim functionIndex++; 122263508Sdim } 123251607Sdim } 124251607Sdim else { 125263508Sdim if (needsFP(*F)) { 126263508Sdim DEBUG(dbgs() << "os16 forced mips32: " << F->getName() << "\n"); 127263508Sdim F->addFnAttr("nomips16"); 128263508Sdim } 129263508Sdim else { 130263508Sdim DEBUG(dbgs() << "os16 forced mips16: " << F->getName() << "\n"); 131263508Sdim F->addFnAttr("mips16"); 132263508Sdim } 133251607Sdim } 134251607Sdim } 135251607Sdim return modified; 136251607Sdim} 137251607Sdim 138251607Sdimchar MipsOs16::ID = 0; 139251607Sdim 140251607Sdim} 141251607Sdim 142251607SdimModulePass *llvm::createMipsOs16(MipsTargetMachine &TM) { 143251607Sdim return new MipsOs16; 144251607Sdim} 145251607Sdim 146251607Sdim 147