MipsOs16.cpp revision 276479
154359Sroberto//===---- MipsOs16.cpp for Mips Option -Os16 --------===// 254359Sroberto// 354359Sroberto// The LLVM Compiler Infrastructure 454359Sroberto// 554359Sroberto// This file is distributed under the University of Illinois Open Source 654359Sroberto// License. See LICENSE.TXT for details. 754359Sroberto// 854359Sroberto//===----------------------------------------------------------------------===// 954359Sroberto// 1054359Sroberto// This file defines an optimization phase for the MIPS target. 1154359Sroberto// 1254359Sroberto//===----------------------------------------------------------------------===// 1354359Sroberto 1454359Sroberto#include "MipsOs16.h" 1554359Sroberto#include "llvm/IR/Module.h" 1654359Sroberto#include "llvm/Support/CommandLine.h" 1754359Sroberto#include "llvm/Support/Debug.h" 1854359Sroberto#include "llvm/Support/raw_ostream.h" 1954359Sroberto 2054359Sroberto#define DEBUG_TYPE "mips-os16" 2154359Sroberto 2254359Sroberto 2354359Srobertostatic cl::opt<std::string> Mips32FunctionMask( 2454359Sroberto "mips32-function-mask", 2554359Sroberto cl::init(""), 2654359Sroberto cl::desc("Force function to be mips32"), 2754359Sroberto cl::Hidden); 2854359Sroberto 2954359Srobertonamespace { 3054359Sroberto 3154359Sroberto // Figure out if we need float point based on the function signature. 3254359Sroberto // We need to move variables in and/or out of floating point 3354359Sroberto // registers because of the ABI 3454359Sroberto // 3554359Sroberto bool needsFPFromSig(Function &F) { 3654359Sroberto Type* RetType = F.getReturnType(); 3754359Sroberto switch (RetType->getTypeID()) { 3854359Sroberto case Type::FloatTyID: 3954359Sroberto case Type::DoubleTyID: 4054359Sroberto return true; 4154359Sroberto default: 4254359Sroberto ; 4354359Sroberto } 4454359Sroberto if (F.arg_size() >=1) { 4554359Sroberto Argument &Arg = F.getArgumentList().front(); 4654359Sroberto switch (Arg.getType()->getTypeID()) { 4754359Sroberto case Type::FloatTyID: 4854359Sroberto case Type::DoubleTyID: 4954359Sroberto return true; 5054359Sroberto default: 5154359Sroberto ; 5254359Sroberto } 5354359Sroberto } 5454359Sroberto return false; 5554359Sroberto } 5654359Sroberto 5754359Sroberto // Figure out if the function will need floating point operations 5854359Sroberto // 5954359Sroberto bool needsFP(Function &F) { 6054359Sroberto if (needsFPFromSig(F)) 6154359Sroberto return true; 6254359Sroberto for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) 6354359Sroberto for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); 6454359Sroberto I != E; ++I) { 6554359Sroberto const Instruction &Inst = *I; 6654359Sroberto switch (Inst.getOpcode()) { 6754359Sroberto case Instruction::FAdd: 6854359Sroberto case Instruction::FSub: 6954359Sroberto case Instruction::FMul: 7054359Sroberto case Instruction::FDiv: 7154359Sroberto case Instruction::FRem: 7254359Sroberto case Instruction::FPToUI: 7354359Sroberto case Instruction::FPToSI: 7454359Sroberto case Instruction::UIToFP: 7554359Sroberto case Instruction::SIToFP: 7654359Sroberto case Instruction::FPTrunc: 7754359Sroberto case Instruction::FPExt: 7854359Sroberto case Instruction::FCmp: 7954359Sroberto return true; 8054359Sroberto default: 8154359Sroberto ; 8254359Sroberto } 8354359Sroberto if (const CallInst *CI = dyn_cast<CallInst>(I)) { 8454359Sroberto DEBUG(dbgs() << "Working on call" << "\n"); 8554359Sroberto Function &F_ = *CI->getCalledFunction(); 8654359Sroberto if (needsFPFromSig(F_)) 8754359Sroberto return true; 8854359Sroberto } 8954359Sroberto } 9054359Sroberto return false; 9154359Sroberto } 9254359Sroberto} 9354359Srobertonamespace llvm { 9454359Sroberto 9554359Sroberto 9654359Srobertobool MipsOs16::runOnModule(Module &M) { 9754359Sroberto bool usingMask = Mips32FunctionMask.length() > 0; 9854359Sroberto bool doneUsingMask = false; // this will make it stop repeating 9954359Sroberto DEBUG(dbgs() << "Run on Module MipsOs16 \n" << Mips32FunctionMask << "\n"); 10054359Sroberto if (usingMask) 10154359Sroberto DEBUG(dbgs() << "using mask \n" << Mips32FunctionMask << "\n"); 10254359Sroberto unsigned int functionIndex = 0; 10354359Sroberto bool modified = false; 10454359Sroberto for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { 10554359Sroberto if (F->isDeclaration()) continue; 10654359Sroberto DEBUG(dbgs() << "Working on " << F->getName() << "\n"); 10754359Sroberto if (usingMask) { 10854359Sroberto if (!doneUsingMask) { 10954359Sroberto if (functionIndex == Mips32FunctionMask.length()) 11054359Sroberto functionIndex = 0; 11154359Sroberto switch (Mips32FunctionMask[functionIndex]) { 11254359Sroberto case '1': 11354359Sroberto DEBUG(dbgs() << "mask forced mips32: " << F->getName() << "\n"); 11454359Sroberto F->addFnAttr("nomips16"); 11554359Sroberto break; 11654359Sroberto case '.': 11754359Sroberto doneUsingMask = true; 11854359Sroberto break; 11954359Sroberto default: 12054359Sroberto break; 12154359Sroberto } 12254359Sroberto functionIndex++; 12354359Sroberto } 12454359Sroberto } 12554359Sroberto else { 12654359Sroberto if (needsFP(*F)) { 12754359Sroberto DEBUG(dbgs() << "os16 forced mips32: " << F->getName() << "\n"); 12854359Sroberto F->addFnAttr("nomips16"); 12954359Sroberto } 13054359Sroberto else { 13154359Sroberto DEBUG(dbgs() << "os16 forced mips16: " << F->getName() << "\n"); 13254359Sroberto F->addFnAttr("mips16"); 13354359Sroberto } 13454359Sroberto } 13554359Sroberto } 13654359Sroberto return modified; 13754359Sroberto} 13854359Sroberto 13954359Srobertochar MipsOs16::ID = 0; 14054359Sroberto 14154359Sroberto} 14254359Sroberto 14354359SrobertoModulePass *llvm::createMipsOs16(MipsTargetMachine &TM) { 14454359Sroberto return new MipsOs16; 14554359Sroberto} 14654359Sroberto 14754359Sroberto 14854359Sroberto