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