summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/Mips/CMakeLists.txt1
-rw-r--r--lib/Target/Mips/MipsOs16.cpp113
-rw-r--r--lib/Target/Mips/MipsOs16.h49
-rw-r--r--lib/Target/Mips/MipsSubtarget.cpp9
-rw-r--r--lib/Target/Mips/MipsSubtarget.h7
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp7
-rw-r--r--test/CodeGen/Mips/fpneeded.ll149
-rw-r--r--test/CodeGen/Mips/fpnotneeded.ll77
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