1b109ea8245e2948ea6d06a6e6cbab7c6788da211Akira Hatanaka//===---- MipsOs16.cpp for Mips Option -Os16 --------===// 274adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler// 374adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler// The LLVM Compiler Infrastructure 474adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler// 574adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler// This file is distributed under the University of Illinois Open Source 674adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler// License. See LICENSE.TXT for details. 774adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler// 874adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler//===----------------------------------------------------------------------===// 974adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler// 1074adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler// This file defines an optimization phase for the MIPS target. 1174adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler// 1274adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler//===----------------------------------------------------------------------===// 1374adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler 144c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar#include "llvm/IR/Instructions.h" 154c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar#include "Mips.h" 1674adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler#include "llvm/IR/Module.h" 170323d4b169279414862174f38ae04add6b747a60Reed Kotler#include "llvm/Support/CommandLine.h" 1874adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler#include "llvm/Support/Debug.h" 1974adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler#include "llvm/Support/raw_ostream.h" 2074adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler 214c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarusing namespace llvm; 22dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 234c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar#define DEBUG_TYPE "mips-os16" 240323d4b169279414862174f38ae04add6b747a60Reed Kotler 250323d4b169279414862174f38ae04add6b747a60Reed Kotlerstatic cl::opt<std::string> Mips32FunctionMask( 260323d4b169279414862174f38ae04add6b747a60Reed Kotler "mips32-function-mask", 270323d4b169279414862174f38ae04add6b747a60Reed Kotler cl::init(""), 280323d4b169279414862174f38ae04add6b747a60Reed Kotler cl::desc("Force function to be mips32"), 290323d4b169279414862174f38ae04add6b747a60Reed Kotler cl::Hidden); 300323d4b169279414862174f38ae04add6b747a60Reed Kotler 3174adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotlernamespace { 324c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar class MipsOs16 : public ModulePass { 334c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar public: 344c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar static char ID; 354c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 364c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar MipsOs16() : ModulePass(ID) {} 374c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 384c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const char *getPassName() const override { 394c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return "MIPS Os16 Optimization"; 404c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } 414c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 424c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar bool runOnModule(Module &M) override; 434c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar }; 444c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 454c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar char MipsOs16::ID = 0; 464c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar} 4774adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler 484c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// Figure out if we need float point based on the function signature. 494c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// We need to move variables in and/or out of floating point 504c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// registers because of the ABI 514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// 524c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic bool needsFPFromSig(Function &F) { 534c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Type* RetType = F.getReturnType(); 544c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar switch (RetType->getTypeID()) { 554c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Type::FloatTyID: 564c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Type::DoubleTyID: 574c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return true; 584c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar default: 594c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ; 604c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } 614c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (F.arg_size() >=1) { 624c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Argument &Arg = F.getArgumentList().front(); 634c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar switch (Arg.getType()->getTypeID()) { 6474adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler case Type::FloatTyID: 6574adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler case Type::DoubleTyID: 6674adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler return true; 6774adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler default: 6874adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler ; 6974adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler } 7074adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler } 714c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return false; 724c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar} 7374adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler 744c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// Figure out if the function will need floating point operations 754c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar// 764c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic bool needsFP(Function &F) { 774c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (needsFPFromSig(F)) 784c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return true; 794c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) 804c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); 8174adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler I != E; ++I) { 824c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const Instruction &Inst = *I; 834c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar switch (Inst.getOpcode()) { 844c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Instruction::FAdd: 854c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Instruction::FSub: 864c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Instruction::FMul: 874c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Instruction::FDiv: 884c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Instruction::FRem: 894c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Instruction::FPToUI: 904c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Instruction::FPToSI: 914c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Instruction::UIToFP: 924c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Instruction::SIToFP: 934c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Instruction::FPTrunc: 944c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Instruction::FPExt: 954c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar case Instruction::FCmp: 964c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return true; 974c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar default: 984c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ; 994c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } 1004c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (const CallInst *CI = dyn_cast<CallInst>(I)) { 1014c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar DEBUG(dbgs() << "Working on call" << "\n"); 1024c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Function &F_ = *CI->getCalledFunction(); 1034c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (needsFPFromSig(F_)) 10474adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler return true; 10574adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler } 1064c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } 1074c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return false; 10874adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler} 10974adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler 11074adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler 11174adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotlerbool MipsOs16::runOnModule(Module &M) { 1120323d4b169279414862174f38ae04add6b747a60Reed Kotler bool usingMask = Mips32FunctionMask.length() > 0; 113f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler bool doneUsingMask = false; // this will make it stop repeating 114de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 1150323d4b169279414862174f38ae04add6b747a60Reed Kotler DEBUG(dbgs() << "Run on Module MipsOs16 \n" << Mips32FunctionMask << "\n"); 1160323d4b169279414862174f38ae04add6b747a60Reed Kotler if (usingMask) 1170323d4b169279414862174f38ae04add6b747a60Reed Kotler DEBUG(dbgs() << "using mask \n" << Mips32FunctionMask << "\n"); 118de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 1190323d4b169279414862174f38ae04add6b747a60Reed Kotler unsigned int functionIndex = 0; 12074adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler bool modified = false; 121de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 122de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto &F : M) { 123de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (F.isDeclaration()) 124de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar continue; 125de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 126de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DEBUG(dbgs() << "Working on " << F.getName() << "\n"); 1270323d4b169279414862174f38ae04add6b747a60Reed Kotler if (usingMask) { 128f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler if (!doneUsingMask) { 129f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler if (functionIndex == Mips32FunctionMask.length()) 130f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler functionIndex = 0; 131f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler switch (Mips32FunctionMask[functionIndex]) { 132f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler case '1': 133de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DEBUG(dbgs() << "mask forced mips32: " << F.getName() << "\n"); 134de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar F.addFnAttr("nomips16"); 135f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler break; 136f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler case '.': 137f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler doneUsingMask = true; 138f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler break; 139f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler default: 140f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler break; 141f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler } 142f2058addc2aa221d0fd744180a2c04a38ebddcd0Reed Kotler functionIndex++; 1430323d4b169279414862174f38ae04add6b747a60Reed Kotler } 14474adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler } 14574adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler else { 146de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (needsFP(F)) { 147de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DEBUG(dbgs() << "os16 forced mips32: " << F.getName() << "\n"); 148de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar F.addFnAttr("nomips16"); 1490323d4b169279414862174f38ae04add6b747a60Reed Kotler } 1500323d4b169279414862174f38ae04add6b747a60Reed Kotler else { 151de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DEBUG(dbgs() << "os16 forced mips16: " << F.getName() << "\n"); 152de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar F.addFnAttr("mips16"); 1530323d4b169279414862174f38ae04add6b747a60Reed Kotler } 15474adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler } 15574adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler } 156de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 15774adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler return modified; 15874adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler} 15974adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler 1604c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga NainarModulePass *llvm::createMipsOs16Pass(MipsTargetMachine &TM) { 16174adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler return new MipsOs16; 16274adad6de8cf947257a53bb08364fa0f4f71b10eReed Kotler} 163