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