diff options
-rw-r--r-- | lib/Target/Mips/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Target/Mips/MipsOs16.cpp | 113 | ||||
-rw-r--r-- | lib/Target/Mips/MipsOs16.h | 49 | ||||
-rw-r--r-- | lib/Target/Mips/MipsSubtarget.cpp | 9 | ||||
-rw-r--r-- | lib/Target/Mips/MipsSubtarget.h | 7 | ||||
-rw-r--r-- | lib/Target/Mips/MipsTargetMachine.cpp | 7 | ||||
-rw-r--r-- | test/CodeGen/Mips/fpneeded.ll | 149 | ||||
-rw-r--r-- | test/CodeGen/Mips/fpnotneeded.ll | 77 |
8 files changed, 411 insertions, 1 deletions
diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index a75e8bd4de..78a9f70c66 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -33,6 +33,7 @@ add_llvm_target(MipsCodeGen MipsMCInstLower.cpp MipsMachineFunction.cpp MipsModuleISelDAGToDAG.cpp + MipsOs16.cpp MipsRegisterInfo.cpp MipsSEFrameLowering.cpp MipsSEInstrInfo.cpp diff --git a/lib/Target/Mips/MipsOs16.cpp b/lib/Target/Mips/MipsOs16.cpp new file mode 100644 index 0000000000..aabc466369 --- /dev/null +++ b/lib/Target/Mips/MipsOs16.cpp @@ -0,0 +1,113 @@ +//===---- MipsOs16.cpp for Mips Option -Os16 --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an optimization phase for the MIPS target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mips-os16" +#include "MipsOs16.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + + // Figure out if we need float point based on the function signature. + // We need to move variables in and/or out of floating point + // registers because of the ABI + // + bool needsFPFromSig(Function &F) { + Type* RetType = F.getReturnType(); + switch (RetType->getTypeID()) { + case Type::FloatTyID: + case Type::DoubleTyID: + return true; + default: + ; + } + if (F.arg_size() >=1) { + Argument &Arg = F.getArgumentList().front(); + switch (Arg.getType()->getTypeID()) { + case Type::FloatTyID: + case Type::DoubleTyID: + return true; + default: + ; + } + } + return false; + } + + // Figure out if the function will need floating point operations + // + bool needsFP(Function &F) { + if (needsFPFromSig(F)) + return true; + for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); + I != E; ++I) { + const Instruction &Inst = *I; + switch (Inst.getOpcode()) { + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: + case Instruction::FRem: + case Instruction::FPToUI: + case Instruction::FPToSI: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::FCmp: + return true; + default: + ; + } + if (const CallInst *CI = dyn_cast<CallInst>(I)) { + DEBUG(dbgs() << "Working on call" << "\n"); + Function &F_ = *CI->getCalledFunction(); + if (needsFPFromSig(F_)) + return true; + } + } + return false; + } +} +namespace llvm { + + +bool MipsOs16::runOnModule(Module &M) { + DEBUG(errs() << "Run on Module MipsOs16\n"); + bool modified = false; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + DEBUG(dbgs() << "Working on " << F->getName() << "\n"); + if (needsFP(*F)) { + DEBUG(dbgs() << " need to compile as nomips16 \n"); + F->addFnAttr("nomips16"); + } + else { + F->addFnAttr("mips16"); + DEBUG(dbgs() << " no need to compile as nomips16 \n"); + } + } + return modified; +} + +char MipsOs16::ID = 0; + +} + +ModulePass *llvm::createMipsOs16(MipsTargetMachine &TM) { + return new MipsOs16; +} + + diff --git a/lib/Target/Mips/MipsOs16.h b/lib/Target/Mips/MipsOs16.h new file mode 100644 index 0000000000..21beef8549 --- /dev/null +++ b/lib/Target/Mips/MipsOs16.h @@ -0,0 +1,49 @@ +//===---- MipsOs16.h for Mips Option -Os16 --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an optimization phase for the MIPS target. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/MipsMCTargetDesc.h" +#include "MipsTargetMachine.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetMachine.h" + + + +#ifndef MIPSOS16_H +#define MIPSOS16_H + +using namespace llvm; + +namespace llvm { + +class MipsOs16 : public ModulePass { + +public: + static char ID; + + MipsOs16() : ModulePass(ID) { + + } + + virtual const char *getPassName() const { + return "MIPS Os16 Optimization"; + } + + virtual bool runOnModule(Module &M); + +}; + +ModulePass *createMipsOs16(MipsTargetMachine &TM); + +} + +#endif diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index b91f5472c8..14a2b27795 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -41,6 +41,13 @@ static cl::opt<bool> Mixed16_32( "and Mips32 code in a single source file"), cl::Hidden); +static cl::opt<bool> Mips_Os16( + "mips-os16", + cl::init(false), + cl::desc("Compile all functions that don' use " + "floating point as Mips 16"), + cl::Hidden); + void MipsSubtarget::anchor() { } MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, @@ -52,7 +59,7 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, IsLinux(true), HasSEInReg(false), HasCondMov(false), HasSwap(false), HasBitCount(false), HasFPIdx(false), InMips16Mode(false), InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), - AllowMixed16_32(Mixed16_32), + AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), RM(_RM), OverrideMode(NoOverride), TM(_TM) { std::string CPUName = CPU; diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 5ad627c4c1..f2f0e15887 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -105,6 +105,11 @@ protected: // Allow mixed Mips16 and Mips32 in one source file bool AllowMixed16_32; + // Optimize for space by compiling all functions as Mips 16 unless + // it needs floating point. Functions needing floating point are + // compiled as Mips32 + bool Os16; + InstrItineraryData InstrItins; // The instance to the register info section object @@ -185,6 +190,8 @@ public: bool allowMixed16_32() const { return AllowMixed16_32;}; + bool os16() const { return Os16;}; + // Grab MipsRegInfo object const MipsReginfo &getMReginfo() const { return MRI; } diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index 18c1ccedfd..ee28e2a122 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -16,6 +16,7 @@ #include "MipsFrameLowering.h" #include "MipsInstrInfo.h" #include "MipsModuleISelDAGToDAG.h" +#include "MipsOs16.h" #include "MipsSEFrameLowering.h" #include "MipsSEInstrInfo.h" #include "MipsSEISelLowering.h" @@ -141,6 +142,7 @@ public: return *getMipsTargetMachine().getSubtargetImpl(); } + virtual void addIRPasses(); virtual bool addInstSelector(); virtual bool addPreEmitPass(); }; @@ -150,6 +152,11 @@ TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { return new MipsPassConfig(this, PM); } +void MipsPassConfig::addIRPasses() { + TargetPassConfig::addIRPasses(); + if (getMipsSubtarget().os16()) + addPass(createMipsOs16(getMipsTargetMachine())); +} // Install an instruction selector pass using // the ISelDag to gen Mips code. bool MipsPassConfig::addInstSelector() { diff --git a/test/CodeGen/Mips/fpneeded.ll b/test/CodeGen/Mips/fpneeded.ll new file mode 100644 index 0000000000..623883a0d5 --- /dev/null +++ b/test/CodeGen/Mips/fpneeded.ll @@ -0,0 +1,149 @@ +; RUN: llc -march=mipsel -mcpu=mips32 -relocation-model=static -O3 < %s -mips-os16 | FileCheck %s -check-prefix=32 + +@x = global float 1.000000e+00, align 4 +@y = global float 2.000000e+00, align 4 +@zz = common global float 0.000000e+00, align 4 +@z = common global float 0.000000e+00, align 4 + +define float @fv() #0 { +entry: + ret float 1.000000e+00 +} + +; 32: .set nomips16 # @fv +; 32: .ent fv +; 32: .set noreorder +; 32: .set nomacro +; 32: .set noat +; 32: jr $ra +; 32: .set at +; 32: .set macro +; 32: .set reorder +; 32: .end fv + +define double @dv() #0 { +entry: + ret double 2.000000e+00 +} + +; 32: .set nomips16 # @dv +; 32: .ent dv +; 32: .set noreorder +; 32: .set nomacro +; 32: .set noat +; 32: jr $ra +; 32: .set at +; 32: .set macro +; 32: .set reorder +; 32: .end dv + +define void @vf(float %x) #0 { +entry: + %x.addr = alloca float, align 4 + store float %x, float* %x.addr, align 4 + ret void +} + +; 32: .set nomips16 # @vf +; 32: .ent vf +; 32: .set noreorder +; 32: .set nomacro +; 32: .set noat +; 32: jr $ra +; 32: .set at +; 32: .set macro +; 32: .set reorder +; 32: .end vf + +define void @vd(double %x) #0 { +entry: + %x.addr = alloca double, align 8 + store double %x, double* %x.addr, align 8 + ret void +} + +; 32: .set nomips16 # @vd +; 32: .ent vd +; 32: .set noreorder +; 32: .set nomacro +; 32: .set noat +; 32: jr $ra +; 32: .set at +; 32: .set macro +; 32: .set reorder +; 32: .end vd + +define void @foo1() #0 { +entry: + store float 1.000000e+00, float* @zz, align 4 + %0 = load float* @y, align 4 + %1 = load float* @x, align 4 + %add = fadd float %0, %1 + store float %add, float* @z, align 4 + ret void +} + +; 32: .set nomips16 # @foo1 +; 32: .ent foo1 +; 32: .set noreorder +; 32: .set nomacro +; 32: .set noat +; 32: jr $ra +; 32: .set at +; 32: .set macro +; 32: .set reorder +; 32: .end foo1 + +define void @foo2() #0 { +entry: + %0 = load float* @x, align 4 + call void @vf(float %0) + ret void +} + + +; 32: .set nomips16 # @foo2 +; 32: .ent foo2 +; 32: .set noreorder +; 32: .set nomacro +; 32: .set noat +; 32: jr $ra +; 32: .set at +; 32: .set macro +; 32: .set reorder +; 32: .end foo2 + +define void @foo3() #0 { +entry: + %call = call float @fv() + store float %call, float* @x, align 4 + ret void +} + +; 32: .set nomips16 # @foo3 +; 32: .ent foo3 +; 32: .set noreorder +; 32: .set nomacro +; 32: .set noat +; 32: jr $ra +; 32: .set at +; 32: .set macro +; 32: .set reorder +; 32: .end foo3 + +attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } + +define void @vv() #0 { +entry: + ret void +} + +; 32: .set mips16 # @vv +; 32: .ent vv + +; 32: save {{.+}} +; 32: restore {{.+}} +; 32: .end vv + + + diff --git a/test/CodeGen/Mips/fpnotneeded.ll b/test/CodeGen/Mips/fpnotneeded.ll new file mode 100644 index 0000000000..dc2ec10817 --- /dev/null +++ b/test/CodeGen/Mips/fpnotneeded.ll @@ -0,0 +1,77 @@ +; RUN: llc -march=mipsel -mcpu=mips32 -relocation-model=static -O3 < %s -mips-os16 | FileCheck %s -check-prefix=32 + +@i = global i32 1, align 4 +@f = global float 1.000000e+00, align 4 + +define void @vv() #0 { +entry: + ret void +} + +; 32: .set mips16 # @vv +; 32: .ent vv + +; 32: save {{.+}} +; 32: restore {{.+}} +; 32: .end vv + +define i32 @iv() #0 { +entry: + %0 = load i32* @i, align 4 + ret i32 %0 +} + +; 32: .set mips16 # @iv +; 32: .ent iv + +; 32: save {{.+}} +; 32: restore {{.+}} +; 32: .end iv + +define void @vif(i32 %i, float %f) #0 { +entry: + %i.addr = alloca i32, align 4 + %f.addr = alloca float, align 4 + store i32 %i, i32* %i.addr, align 4 + store float %f, float* %f.addr, align 4 + ret void +} + +; 32: .set mips16 # @vif +; 32: .ent vif + +; 32: save {{.+}} +; 32: restore {{.+}} +; 32: .end vif + +define void @foo() #0 { +entry: + store float 2.000000e+00, float* @f, align 4 + ret void +} + +; 32: .set mips16 # @foo +; 32: .ent foo + +; 32: save {{.+}} +; 32: restore {{.+}} +; 32: .end foo + +attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } + + +define float @fv() #0 { +entry: + ret float 1.000000e+00 +} + +; 32: .set nomips16 # @fv +; 32: .ent fv +; 32: .set noreorder +; 32: .set nomacro +; 32: .set noat +; 32: jr $ra +; 32: .set at +; 32: .set macro +; 32: .set reorder +; 32: .end fv |