This patch enables llvm to switch between compiling for mips32/mips64
authorReed Kotler <rkotler@mips.com>
Tue, 9 Apr 2013 19:46:01 +0000 (19:46 +0000)
committerReed Kotler <rkotler@mips.com>
Tue, 9 Apr 2013 19:46:01 +0000 (19:46 +0000)
and mips16 on a per function basis.

Because this patch is somewhat involved I have provide an overview of the
key pieces of it.

The patch is written so as to not change the behavior of the non mixed
mode. We have tested this a lot but it is something new to switch subtargets
so we don't want any chance of regression in the mainline compiler until
we have more confidence in this.

Mips32/64 are very different from Mip16 as is the case of ARM vs Thumb1.
For that reason there are derived versions of the register info, frame info,
instruction info and instruction selection classes.

Now we register three separate passes for instruction selection.
One which is used to switch subtargets (MipsModuleISelDAGToDAG.cpp) and then
one for each of the current subtargets (Mips16ISelDAGToDAG.cpp and
MipsSEISelDAGToDAG.cpp).

When the ModuleISel pass runs, it determines if there is a need to switch
subtargets and if so, the owning pointers in MipsTargetMachine are
appropriately changed.

When 16Isel or SEIsel is run, they will return immediately without doing
any work if the current subtarget mode does not apply to them.

In addition, MipsAsmPrinter needs to be reset on a function basis.

The pass BasicTargetTransformInfo is substituted with a null pass since the
pass is immutable and really needs to be a function pass for it to be
used with changing subtargets. This will be fixed in a follow on patch.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179118 91177308-0d34-0410-b5e6-96231b3b80d8

24 files changed:
lib/Target/Mips/CMakeLists.txt
lib/Target/Mips/Mips16ISelDAGToDAG.cpp
lib/Target/Mips/Mips16ISelDAGToDAG.h
lib/Target/Mips/MipsAsmPrinter.cpp
lib/Target/Mips/MipsConstantIslandPass.cpp
lib/Target/Mips/MipsLongBranch.cpp
lib/Target/Mips/MipsModuleISelDAGToDAG.cpp [new file with mode: 0644]
lib/Target/Mips/MipsModuleISelDAGToDAG.h [new file with mode: 0644]
lib/Target/Mips/MipsSEISelDAGToDAG.cpp
lib/Target/Mips/MipsSEISelDAGToDAG.h
lib/Target/Mips/MipsSEISelLowering.cpp
lib/Target/Mips/MipsSubtarget.cpp
lib/Target/Mips/MipsSubtarget.h
lib/Target/Mips/MipsTargetMachine.cpp
lib/Target/Mips/MipsTargetMachine.h
test/CodeGen/Mips/mips16_32_1.ll [new file with mode: 0644]
test/CodeGen/Mips/mips16_32_10.ll [new file with mode: 0644]
test/CodeGen/Mips/mips16_32_3.ll [new file with mode: 0644]
test/CodeGen/Mips/mips16_32_4.ll [new file with mode: 0644]
test/CodeGen/Mips/mips16_32_5.ll [new file with mode: 0644]
test/CodeGen/Mips/mips16_32_6.ll [new file with mode: 0644]
test/CodeGen/Mips/mips16_32_7.ll [new file with mode: 0644]
test/CodeGen/Mips/mips16_32_8.ll [new file with mode: 0644]
test/CodeGen/Mips/mips16_32_9.ll [new file with mode: 0644]

index cf8bb189e475f417b46d712e0649bb6ea8143863..a75e8bd4dee17e90f889ee73a37d72e5ee963698 100644 (file)
@@ -32,6 +32,7 @@ add_llvm_target(MipsCodeGen
   MipsLongBranch.cpp
   MipsMCInstLower.cpp
   MipsMachineFunction.cpp
+  MipsModuleISelDAGToDAG.cpp
   MipsRegisterInfo.cpp
   MipsSEFrameLowering.cpp
   MipsSEInstrInfo.cpp
index 00b3449300c5286ad809bcd764559d184be8776d..2ffd3a992962f7f08974fae8bec93d2e98e49178 100644 (file)
 #include "llvm/Target/TargetMachine.h"
 using namespace llvm;
 
+bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
+  if (!Subtarget.inMips16Mode())
+    return false;
+  return MipsDAGToDAGISel::runOnMachineFunction(MF);
+}
 /// Select multiply instructions.
 std::pair<SDNode*, SDNode*>
 Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, DebugLoc DL, EVT Ty,
index baa85877d957e757c79cb7d461c15c994931b21e..f05f9b766df862625aee24003843295b0471e2a9 100644 (file)
@@ -28,6 +28,8 @@ private:
 
   SDValue getMips16SPAliasReg();
 
+  virtual bool runOnMachineFunction(MachineFunction &MF);
+
   void getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg);
 
   virtual bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
index 1876cb6ffae4d3b4844f31bab73a5af38323559e..e0ddade15f84b1cf3a00b0a3440e38dd28116b0b 100644 (file)
 using namespace llvm;
 
 bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+  // Initialize TargetLoweringObjectFile.
+  if (Subtarget->allowMixed16_32())
+    const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
+      .Initialize(OutContext, TM);
   MipsFI = MF.getInfo<MipsFunctionInfo>();
   AsmPrinter::runOnMachineFunction(MF);
   return true;
index b5de1ebad22bb26123d3944c30b9b42b688cf0bb..1951324cf1a1f968660c1aeaea95f1fe4ef54156 100644 (file)
@@ -80,6 +80,10 @@ FunctionPass *llvm::createMipsConstantIslandPass(MipsTargetMachine &tm) {
 }
 
 bool MipsConstantIslands::runOnMachineFunction(MachineFunction &F) {
-  return true;
+  // The intention is for this to be a mips16 only pass for now
+  // FIXME:
+  // if (!TM.getSubtarget<MipsSubtarget>().inMips16Mode())
+  //  return false;
+  return false;
 }
 
index 2efe534053a2411664599a34781207afe48bd77f..bf5ad37031191efbfb0c77aaf82db357ebd156b3 100644 (file)
@@ -399,6 +399,8 @@ static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) {
 }
 
 bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) {
+  if (TM.getSubtarget<MipsSubtarget>().inMips16Mode())
+    return false;
   if ((TM.getRelocationModel() == Reloc::PIC_) &&
       TM.getSubtarget<MipsSubtarget>().isABI_O32() &&
       F.getInfo<MipsFunctionInfo>()->globalBaseRegSet())
diff --git a/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp b/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp
new file mode 100644 (file)
index 0000000..c6abf17
--- /dev/null
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+// Instruction Selector Subtarget Control
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// This file defines a pass used to change the subtarget for the
+// Mips Instruction selector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsISelDAGToDAG.h"
+#include "MipsModuleISelDAGToDAG.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+bool MipsModuleDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
+  DEBUG(errs() << "In MipsModuleDAGToDAGISel::runMachineFunction\n");
+  const_cast<MipsSubtarget&>(Subtarget).resetSubtarget(&MF);
+  return false;
+}
+
+char MipsModuleDAGToDAGISel::ID = 0;
+
+}
+
+
+llvm::FunctionPass *llvm::createMipsModuleISelDag(MipsTargetMachine &TM) {
+  return new MipsModuleDAGToDAGISel(TM);
+}
+
+
diff --git a/lib/Target/Mips/MipsModuleISelDAGToDAG.h b/lib/Target/Mips/MipsModuleISelDAGToDAG.h
new file mode 100644 (file)
index 0000000..fda35ae
--- /dev/null
@@ -0,0 +1,66 @@
+//===---- MipsModuleISelDAGToDAG.h -  Change Subtarget             --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a pass used to change the subtarget for the
+// Mips Instruction selector.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MIPSMODULEISELDAGTODAG_H
+#define MIPSMODULEISELDAGTODAG_H
+
+#include "Mips.h"
+#include "MipsSubtarget.h"
+#include "MipsTargetMachine.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+
+
+//===----------------------------------------------------------------------===//
+// Instruction Selector Implementation
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// MipsModuleDAGToDAGISel - MIPS specific code to select MIPS machine
+// instructions for SelectionDAG operations.
+//===----------------------------------------------------------------------===//
+namespace llvm {
+
+class MipsModuleDAGToDAGISel : public MachineFunctionPass {
+public:
+
+  static char ID;
+
+  explicit MipsModuleDAGToDAGISel(MipsTargetMachine &TM_)
+    : MachineFunctionPass(ID),
+      TM(TM_), Subtarget(TM.getSubtarget<MipsSubtarget>()) {}
+
+  // Pass Name
+  virtual const char *getPassName() const {
+    return "MIPS DAG->DAG Pattern Instruction Selection";
+  }
+
+  virtual bool runOnMachineFunction(MachineFunction &MF);
+
+  virtual SDNode *Select(SDNode *N) {
+    llvm_unreachable("unexpected");
+  }
+
+protected:
+  /// Keep a pointer to the MipsSubtarget around so that we can make the right
+  /// decision when generating code for different targets.
+  const TargetMachine &TM;
+  const MipsSubtarget &Subtarget;
+};
+
+/// createMipsISelDag - This pass converts a legalized DAG into a
+/// MIPS-specific DAG, ready for instruction scheduling.
+FunctionPass *createMipsModuleISelDag(MipsTargetMachine &TM);
+}
+
+#endif
index d6d220750c616a9eef50e68178cf05200b2d73e1..0fc3c5e6ad98120ab29484e35ae9f18dc15affb0 100644 (file)
 #include "llvm/Target/TargetMachine.h"
 using namespace llvm;
 
+bool MipsSEDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
+  if (Subtarget.inMips16Mode())
+    return false;
+  return MipsDAGToDAGISel::runOnMachineFunction(MF);
+}
 
 bool MipsSEDAGToDAGISel::replaceUsesWithZeroReg(MachineRegisterInfo *MRI,
                                                 const MachineInstr& MI) {
index 6137ab040bbc5b2736860c5e42c18cc3c434ed42..0dae73dd5ed78ac7b7ba1757253502e336241de9 100644 (file)
@@ -24,6 +24,9 @@ public:
   explicit MipsSEDAGToDAGISel(MipsTargetMachine &TM) : MipsDAGToDAGISel(TM) {}
 
 private:
+
+  virtual bool runOnMachineFunction(MachineFunction &MF);
+
   bool replaceUsesWithZeroReg(MachineRegisterInfo *MRI, const MachineInstr&);
 
   std::pair<SDNode*, SDNode*> selectMULT(SDNode *N, unsigned Opc, DebugLoc dl,
index 4f219218d31f65ed359eaf9a5f1c27d09b9072b5..df6af096f6efed51e8a4bda732e69f721e85a2d8 100644 (file)
@@ -27,6 +27,9 @@ EnableMipsTailCalls("enable-mips-tail-calls", cl::Hidden,
 MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM)
   : MipsTargetLowering(TM) {
   // Set up the register classes
+
+  clearRegisterClasses();
+
   addRegisterClass(MVT::i32, &Mips::CPURegsRegClass);
 
   if (HasMips64)
index e11e5d142b74171e1391a741939353bad312a1fc..b91f5472c8ba9ee324c2d52d5ab0c804b0b3bc6e 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
+#define DEBUG_TYPE "mips-subtarget"
+
+#include "MipsMachineFunction.h"
 #include "MipsSubtarget.h"
+#include "MipsTargetMachine.h"
 #include "Mips.h"
 #include "MipsRegisterInfo.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
 
 #define GET_SUBTARGETINFO_TARGET_DESC
 #define GET_SUBTARGETINFO_CTOR
 #include "MipsGenSubtargetInfo.inc"
 
+
 using namespace llvm;
 
+// FIXME: Maybe this should be on by default when Mips16 is specified
+//
+static cl::opt<bool> Mixed16_32(
+  "mips-mixed-16-32",
+  cl::init(false),
+  cl::desc("Allow for a mixture of Mips16 "
+           "and Mips32 code in a single source file"),
+  cl::Hidden);
+
 void MipsSubtarget::anchor() { }
 
 MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU,
                              const std::string &FS, bool little,
-                             Reloc::Model _RM) :
+                             Reloc::Model _RM, MipsTargetMachine *_TM) :
   MipsGenSubtargetInfo(TT, CPU, FS),
   MipsArchVersion(Mips32), MipsABI(UnknownABI), IsLittle(little),
   IsSingleFloat(false), IsFP64bit(false), IsGP64bit(false), HasVFPU(false),
   IsLinux(true), HasSEInReg(false), HasCondMov(false), HasSwap(false),
   HasBitCount(false), HasFPIdx(false),
   InMips16Mode(false), InMicroMipsMode(false), HasDSP(false), HasDSPR2(false),
-  RM(_RM)
+  AllowMixed16_32(Mixed16_32),
+  RM(_RM), OverrideMode(NoOverride), TM(_TM)
 {
   std::string CPUName = CPU;
   if (CPUName.empty())
@@ -42,6 +62,8 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU,
   // Parse features string.
   ParseSubtargetFeatures(CPUName, FS);
 
+  PreviousInMips16Mode = InMips16Mode;
+
   // Initialize scheduling itinerary for the specified CPU.
   InstrItins = getInstrItineraryForCPU(CPUName);
 
@@ -72,3 +94,48 @@ MipsSubtarget::enablePostRAScheduler(CodeGenOpt::Level OptLevel,
                             &Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass);
   return OptLevel >= CodeGenOpt::Aggressive;
 }
+
+//FIXME: This logic for reseting the subtarget along with
+// the helper classes can probably be simplified but there are a lot of
+// cases so we will defer rewriting this to later.
+//
+void MipsSubtarget::resetSubtarget(MachineFunction *MF) {
+  bool ChangeToMips16 = false, ChangeToNoMips16 = false;
+  DEBUG(dbgs() << "resetSubtargetFeatures" << "\n");
+  AttributeSet FnAttrs = MF->getFunction()->getAttributes();
+  ChangeToMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex,
+                                        "mips16");
+  ChangeToNoMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex,
+                                        "nomips16");
+  assert (!(ChangeToMips16 & ChangeToNoMips16) &&
+          "mips16 and nomips16 specified on the same function");
+  if (ChangeToMips16) {
+    if (PreviousInMips16Mode)
+      return;
+    OverrideMode = Mips16Override;
+    PreviousInMips16Mode = true;
+    TM->setHelperClassesMips16();
+    return;
+  } else if (ChangeToNoMips16) {
+    if (!PreviousInMips16Mode)
+      return;
+    OverrideMode = NoMips16Override;
+    PreviousInMips16Mode = false;
+    TM->setHelperClassesMipsSE();
+    return;
+  } else {
+    if (OverrideMode == NoOverride)
+      return;
+    OverrideMode = NoOverride;
+    DEBUG(dbgs() << "back to default" << "\n");
+    if (inMips16Mode() && !PreviousInMips16Mode) {
+      TM->setHelperClassesMips16();
+      PreviousInMips16Mode = true;
+    } else if (!inMips16Mode() && PreviousInMips16Mode) {
+      TM->setHelperClassesMipsSE();
+      PreviousInMips16Mode = false;
+    }
+    return;
+  }
+}
+
index 7a2e47ce5a9d901184ee022dbeac8cd51b6b5be8..5ad627c4c1fbe071d2b7d555bd9372e9f01ec257 100644 (file)
@@ -16,7 +16,9 @@
 
 #include "MCTargetDesc/MipsReginfo.h"
 #include "llvm/MC/MCInstrItineraries.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Target/TargetSubtargetInfo.h"
+
 #include <string>
 
 #define GET_SUBTARGETINFO_HEADER
@@ -25,6 +27,8 @@
 namespace llvm {
 class StringRef;
 
+class MipsTargetMachine;
+
 class MipsSubtarget : public MipsGenSubtargetInfo {
   virtual void anchor();
 
@@ -89,12 +93,18 @@ protected:
   // InMips16 -- can process Mips16 instructions
   bool InMips16Mode;
 
+  // PreviousInMips16 -- the function we just processed was in Mips 16 Mode
+  bool PreviousInMips16Mode;
+
   // InMicroMips -- can process MicroMips instructions
   bool InMicroMipsMode;
 
   // HasDSP, HasDSPR2 -- supports DSP ASE.
   bool HasDSP, HasDSPR2;
 
+  // Allow mixed Mips16 and Mips32 in one source file
+  bool AllowMixed16_32;
+
   InstrItineraryData InstrItins;
 
   // The instance to the register info section object
@@ -103,6 +113,12 @@ protected:
   // Relocation Model
   Reloc::Model RM;
 
+  // We can override the determination of whether we are in mips16 mode
+  // as from the command line
+  enum {NoOverride, Mips16Override, NoMips16Override} OverrideMode;
+
+  MipsTargetMachine *TM;
+
 public:
   virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel,
                                      AntiDepBreakMode& Mode,
@@ -118,7 +134,8 @@ public:
   /// This constructor initializes the data members to match that
   /// of the specified triple.
   MipsSubtarget(const std::string &TT, const std::string &CPU,
-                const std::string &FS, bool little, Reloc::Model RM);
+                const std::string &FS, bool little, Reloc::Model RM,
+                MipsTargetMachine *TM);
 
   /// ParseSubtargetFeatures - Parses features string setting specified
   /// subtarget options.  Definition of function is auto generated by tblgen.
@@ -137,7 +154,20 @@ public:
   bool isSingleFloat() const { return IsSingleFloat; }
   bool isNotSingleFloat() const { return !IsSingleFloat; }
   bool hasVFPU() const { return HasVFPU; }
-  bool inMips16Mode() const { return InMips16Mode; }
+  bool inMips16Mode() const {
+    switch (OverrideMode) {
+    case NoOverride:
+      return InMips16Mode;
+    case Mips16Override:
+      return true;
+    case NoMips16Override:
+      return false;
+    }
+    llvm_unreachable("Unexpected mode");
+  }
+  bool inMips16ModeDefault() {
+    return InMips16Mode;
+  }
   bool inMicroMipsMode() const { return InMicroMipsMode; }
   bool hasDSP() const { return HasDSP; }
   bool hasDSPR2() const { return HasDSPR2; }
@@ -153,11 +183,18 @@ public:
   bool hasBitCount()  const { return HasBitCount; }
   bool hasFPIdx()     const { return HasFPIdx; }
 
+  bool allowMixed16_32() const { return AllowMixed16_32;};
+
   // Grab MipsRegInfo object
   const MipsReginfo &getMReginfo() const { return MRI; }
 
   // Grab relocation model
   Reloc::Model getRelocationModel() const {return RM;}
+
+  /// \brief Reset the subtarget for the Mips target.
+  void resetSubtarget(MachineFunction *MF);
+
+
 };
 } // End llvm namespace
 
index 33363580aba7d404776591c2472d70c3790e4bab..18c1ccedfd58d2404cf48766c65761f09659ad33 100644 (file)
 #include "Mips.h"
 #include "MipsFrameLowering.h"
 #include "MipsInstrInfo.h"
+#include "MipsModuleISelDAGToDAG.h"
+#include "MipsSEFrameLowering.h"
+#include "MipsSEInstrInfo.h"
+#include "MipsSEISelLowering.h"
+#include "MipsSEISelDAGToDAG.h"
+#include "Mips16FrameLowering.h"
+#include "Mips16InstrInfo.h"
+#include "Mips16ISelDAGToDAG.h"
+#include "Mips16ISelLowering.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/PassManager.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/TargetRegistry.h"
 using namespace llvm;
 
+
+
 extern "C" void LLVMInitializeMipsTarget() {
   // Register the target.
   RegisterTargetMachine<MipsebTargetMachine> X(TheMipsTarget);
@@ -42,7 +56,7 @@ MipsTargetMachine(const Target &T, StringRef TT,
                   CodeGenOpt::Level OL,
                   bool isLittle)
   : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
-    Subtarget(TT, CPU, FS, isLittle, RM),
+    Subtarget(TT, CPU, FS, isLittle, RM, this),
     DL(isLittle ?
                (Subtarget.isABI_N64() ?
                 "e-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-"
@@ -54,9 +68,46 @@ MipsTargetMachine(const Target &T, StringRef TT,
                 "E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32-S64")),
     InstrInfo(MipsInstrInfo::create(*this)),
     FrameLowering(MipsFrameLowering::create(*this, Subtarget)),
-    TLInfo(MipsTargetLowering::create(*this)), TSInfo(*this), JITInfo() {
+    TLInfo(MipsTargetLowering::create(*this)),
+    TSInfo(*this), JITInfo() {
+}
+
+
+void MipsTargetMachine::setHelperClassesMips16() {
+  InstrInfoSE.swap(InstrInfo);
+  FrameLoweringSE.swap(FrameLowering);
+  TLInfoSE.swap(TLInfo);
+  if (!InstrInfo16) {
+    InstrInfo.reset(MipsInstrInfo::create(*this));
+    FrameLowering.reset(MipsFrameLowering::create(*this, Subtarget));
+    TLInfo.reset(MipsTargetLowering::create(*this));
+  } else {
+    InstrInfo16.swap(InstrInfo);
+    FrameLowering16.swap(FrameLowering);
+    TLInfo16.swap(TLInfo);
+  }
+  assert(TLInfo && "null target lowering 16");
+  assert(InstrInfo && "null instr info 16");
+  assert(FrameLowering && "null frame lowering 16");
 }
 
+void MipsTargetMachine::setHelperClassesMipsSE() {
+  InstrInfo16.swap(InstrInfo);
+  FrameLowering16.swap(FrameLowering);
+  TLInfo16.swap(TLInfo);
+  if (!InstrInfoSE) {
+    InstrInfo.reset(MipsInstrInfo::create(*this));
+    FrameLowering.reset(MipsFrameLowering::create(*this, Subtarget));
+    TLInfo.reset(MipsTargetLowering::create(*this));
+  } else {
+    InstrInfoSE.swap(InstrInfo);
+    FrameLoweringSE.swap(FrameLowering);
+    TLInfoSE.swap(TLInfo);
+  }
+  assert(TLInfo && "null target lowering in SE");
+  assert(InstrInfo && "null instr info SE");
+  assert(FrameLowering && "null frame lowering SE");
+}
 void MipsebTargetMachine::anchor() { }
 
 MipsebTargetMachine::
@@ -102,21 +153,42 @@ TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) {
 // Install an instruction selector pass using
 // the ISelDag to gen Mips code.
 bool MipsPassConfig::addInstSelector() {
-  addPass(createMipsISelDag(getMipsTargetMachine()));
+  if (getMipsSubtarget().allowMixed16_32()) {
+    addPass(createMipsModuleISelDag(getMipsTargetMachine()));
+    addPass(createMips16ISelDag(getMipsTargetMachine()));
+    addPass(createMipsSEISelDag(getMipsTargetMachine()));
+  } else {
+    addPass(createMipsISelDag(getMipsTargetMachine()));
+  }
   return false;
 }
 
+void MipsTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
+  if (Subtarget.allowMixed16_32()) {
+    DEBUG(errs() << "No ");
+    //FIXME: The Basic Target Transform Info
+    // pass needs to become a function pass instead of
+    // being an immutable pass and then this method as it exists now
+    // would be unnecessary.
+    PM.add(createNoTargetTransformInfoPass());
+  } else
+    LLVMTargetMachine::addAnalysisPasses(PM);
+  DEBUG(errs() << "Target Transform Info Pass Added\n");
+}
+
 // Implemented by targets that want to run passes immediately before
 // machine code is emitted. return true if -print-machineinstrs should
 // print out the code after the passes.
 bool MipsPassConfig::addPreEmitPass() {
   MipsTargetMachine &TM = getMipsTargetMachine();
+  const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>();
   addPass(createMipsDelaySlotFillerPass(TM));
 
-  // NOTE: long branch has not been implemented for mips16.
-  if (TM.getSubtarget<MipsSubtarget>().hasStandardEncoding())
+  if (Subtarget.hasStandardEncoding() ||
+      Subtarget.allowMixed16_32())
     addPass(createMipsLongBranchPass(TM));
-  if (TM.getSubtarget<MipsSubtarget>().inMips16Mode())
+  if (Subtarget.inMips16Mode() ||
+      Subtarget.allowMixed16_32())
     addPass(createMipsConstantIslandPass(TM));
 
   return true;
index 7e5f1922643356a44b8b6a7e8436c287581148ab..ee557084fbbff89ddd025dbe0c700d72b5de90e5 100644 (file)
@@ -21,6 +21,8 @@
 #include "MipsSelectionDAGInfo.h"
 #include "MipsSubtarget.h"
 #include "llvm/ADT/OwningPtr.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/Target/TargetFrameLowering.h"
 #include "llvm/Target/TargetMachine.h"
@@ -35,6 +37,12 @@ class MipsTargetMachine : public LLVMTargetMachine {
   OwningPtr<const MipsInstrInfo> InstrInfo;
   OwningPtr<const MipsFrameLowering> FrameLowering;
   OwningPtr<const MipsTargetLowering> TLInfo;
+  OwningPtr<const MipsInstrInfo> InstrInfo16;
+  OwningPtr<const MipsFrameLowering> FrameLowering16;
+  OwningPtr<const MipsTargetLowering> TLInfo16;
+  OwningPtr<const MipsInstrInfo> InstrInfoSE;
+  OwningPtr<const MipsFrameLowering> FrameLoweringSE;
+  OwningPtr<const MipsTargetLowering> TLInfoSE;
   MipsSelectionDAGInfo TSInfo;
   MipsJITInfo JITInfo;
 
@@ -47,6 +55,8 @@ public:
 
   virtual ~MipsTargetMachine() {}
 
+  virtual void addAnalysisPasses(PassManagerBase &PM);
+
   virtual const MipsInstrInfo *getInstrInfo() const
   { return InstrInfo.get(); }
   virtual const TargetFrameLowering *getFrameLowering() const
@@ -73,6 +83,13 @@ public:
   // Pass Pipeline Configuration
   virtual TargetPassConfig *createPassConfig(PassManagerBase &PM);
   virtual bool addCodeEmitter(PassManagerBase &PM, JITCodeEmitter &JCE);
+
+  // Set helper classes
+  void setHelperClassesMips16();
+
+  void setHelperClassesMipsSE();
+
+
 };
 
 /// MipsebTargetMachine - Mips32/64 big endian target machine.
diff --git a/test/CodeGen/Mips/mips16_32_1.ll b/test/CodeGen/Mips/mips16_32_1.ll
new file mode 100644 (file)
index 0000000..6f4826e
--- /dev/null
@@ -0,0 +1,14 @@
+; RUN: llc  -march=mipsel -mcpu=mips16 -relocation-model=pic -O3 < %s -mips-mixed-16-32  | FileCheck %s 
+; RUN: llc  -march=mipsel -mcpu=mips32 -relocation-model=pic -O3 < %s -mips-mixed-16-32  | FileCheck %s 
+
+define void @foo() #0 {
+entry:
+  ret void
+}
+
+; CHECK:       .set    mips16                  # @foo
+; CHECK:       .ent    foo
+; CHECK:       save    {{.+}}
+; CHECK:       restore {{.+}} 
+; CHECK:       .end    foo
+attributes #0 = { nounwind "less-precise-fpmad"="false" "mips16" "no-frame-pointer-elim"="false" "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" }
diff --git a/test/CodeGen/Mips/mips16_32_10.ll b/test/CodeGen/Mips/mips16_32_10.ll
new file mode 100644 (file)
index 0000000..330dbfe
--- /dev/null
@@ -0,0 +1,59 @@
+; RUN: llc  -march=mipsel -mcpu=mips16 -relocation-model=static -O3 < %s -mips-mixed-16-32  | FileCheck %s -check-prefix=16
+
+define void @foo() #0 {
+entry:
+  ret void
+}
+; 16:  .set    nomips16                  # @foo
+; 16:  .ent    foo
+; 16:  .set    noreorder
+; 16:  .set    nomacro
+; 16:  .set    noat
+; 16:  jr      $ra
+; 16:  nop
+; 16:  .set    at
+; 16:  .set    macro
+; 16:  .set    reorder
+; 16:  .end    foo
+
+define void @nofoo() #1 {
+entry:
+  ret void
+}
+
+; 16:  .set    mips16                  # @nofoo
+; 16:  .ent    nofoo
+
+; 16:  save    {{.+}}
+; 16:  restore {{.+}} 
+; 16:  .end    nofoo
+
+define i32 @main() #2 {
+entry:
+  ret i32 0
+}
+
+; 16:  .set    nomips16                  # @main
+; 16:  .ent    main
+; 16:  .set    noreorder
+; 16:  .set    nomacro
+; 16:  .set    noat
+; 16:  jr      $ra
+; 16:  .set    at
+; 16:  .set    macro
+; 16:  .set    reorder
+; 16:  .end    main
+
+
+
+
+
+
+
+
+
+
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "nomips16" "no-frame-pointer-elim"="false" "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" }
+attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "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" }
+attributes #2 = { nounwind "less-precise-fpmad"="false" "nomips16" "no-frame-pointer-elim"="false" "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" }
diff --git a/test/CodeGen/Mips/mips16_32_3.ll b/test/CodeGen/Mips/mips16_32_3.ll
new file mode 100644 (file)
index 0000000..8874a88
--- /dev/null
@@ -0,0 +1,70 @@
+; RUN: llc  -march=mipsel -mcpu=mips16 -relocation-model=static -O3 < %s -mips-mixed-16-32  | FileCheck %s -check-prefix=16
+; RUN: llc  -march=mipsel -mcpu=mips32 -relocation-model=static -O3 < %s -mips-mixed-16-32  | FileCheck %s -check-prefix=32
+
+define void @foo() #0 {
+entry:
+  ret void
+}
+
+; 16:  .set    mips16                  # @foo
+; 16:  .ent    foo
+; 16:  save    {{.+}}
+; 16:  restore {{.+}} 
+; 16:  .end    foo
+; 32:  .set    mips16                  # @foo
+; 32:  .ent    foo
+; 32:  save    {{.+}}
+; 32:  restore {{.+}} 
+; 32:  .end    foo
+define void @nofoo() #1 {
+entry:
+  ret void
+}
+
+; 16:  .set    nomips16                  # @nofoo
+; 16:  .ent    nofoo
+; 16:  .set    noreorder
+; 16:  .set    nomacro
+; 16:  .set    noat
+; 16:  jr      $ra
+; 16:  nop
+; 16:  .set    at
+; 16:  .set    macro
+; 16:  .set    reorder
+; 16:  .end    nofoo
+; 32:  .set    nomips16                  # @nofoo
+; 32:  .ent    nofoo
+; 32:  .set    noreorder
+; 32:  .set    nomacro
+; 32:  .set    noat
+; 32:  jr      $ra
+; 32:  nop
+; 32:  .set    at
+; 32:  .set    macro
+; 32:  .set    reorder
+; 32:  .end    nofoo
+define i32 @main() #2 {
+entry:
+  ret i32 0
+}
+
+; 16:  .set    mips16                  # @main
+; 16:  .ent    main
+; 16:  save    {{.+}}
+; 16:  restore {{.+}} 
+; 16:  .end    main
+; 32:  .set    nomips16                  # @main
+; 32:  .ent    main
+; 32:  .set    noreorder
+; 32:  .set    nomacro
+; 32:  .set    noat
+; 32:  jr      $ra
+; 32:  addiu   $2, $zero, 0
+; 32:  .set    at
+; 32:  .set    macro
+; 32:  .set    reorder
+; 32:  .end    main
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "mips16" "no-frame-pointer-elim"="false" "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" }
+attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "nomips16" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "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" }
diff --git a/test/CodeGen/Mips/mips16_32_4.ll b/test/CodeGen/Mips/mips16_32_4.ll
new file mode 100644 (file)
index 0000000..cdaed6c
--- /dev/null
@@ -0,0 +1,65 @@
+; RUN: llc  -march=mipsel -mcpu=mips16 -relocation-model=static -O3 < %s -mips-mixed-16-32  | FileCheck %s -check-prefix=16
+; RUN: llc  -march=mipsel -mcpu=mips32 -relocation-model=static -O3 < %s -mips-mixed-16-32  | FileCheck %s -check-prefix=32
+
+define void @foo() #0 {
+entry:
+  ret void
+}
+
+; 16:  .set    mips16                  # @foo
+; 16:  .ent    foo
+; 16:  save    {{.+}}
+; 16:  restore {{.+}} 
+; 16:  .end    foo
+; 32:  .set    mips16                  # @foo
+; 32:  .ent    foo
+; 32:  save    {{.+}}
+; 32:  restore {{.+}} 
+; 32:  .end    foo
+define void @nofoo() #1 {
+entry:
+  ret void
+}
+
+; 16:  .set    nomips16                  # @nofoo
+; 16:  .ent    nofoo
+; 16:  .set    noreorder
+; 16:  .set    nomacro
+; 16:  .set    noat
+; 16:  jr      $ra
+; 16:  nop
+; 16:  .set    at
+; 16:  .set    macro
+; 16:  .set    reorder
+; 16:  .end    nofoo
+; 32:  .set    nomips16                  # @nofoo
+; 32:  .ent    nofoo
+; 32:  .set    noreorder
+; 32:  .set    nomacro
+; 32:  .set    noat
+; 32:  jr      $ra
+; 32:  nop
+; 32:  .set    at
+; 32:  .set    macro
+; 32:  .set    reorder
+; 32:  .end    nofoo
+define i32 @main() #2 {
+entry:
+  ret i32 0
+}
+
+; 16:  .set    mips16                  # @main
+; 16:  .ent    main
+; 16:  save    {{.+}}
+; 16:  restore {{.+}} 
+; 16:  .end    main
+; 32:  .set    mips16                  # @main
+; 32:  .ent    main
+; 32:  save    {{.+}}
+; 32:  restore {{.+}} 
+; 32:  .end    main
+
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "mips16" "no-frame-pointer-elim"="false" "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" }
+attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "nomips16" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind "less-precise-fpmad"="false" "mips16" "no-frame-pointer-elim"="false" "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" }
diff --git a/test/CodeGen/Mips/mips16_32_5.ll b/test/CodeGen/Mips/mips16_32_5.ll
new file mode 100644 (file)
index 0000000..45e0bf4
--- /dev/null
@@ -0,0 +1,80 @@
+; RUN: llc  -march=mipsel -mcpu=mips16 -relocation-model=static -O3 < %s -mips-mixed-16-32  | FileCheck %s -check-prefix=16
+; RUN: llc  -march=mipsel -mcpu=mips32 -relocation-model=static -O3 < %s -mips-mixed-16-32  | FileCheck %s -check-prefix=32
+
+define void @foo() #0 {
+entry:
+  ret void
+}
+
+; 16:  .set    mips16                  # @foo
+; 16:  .ent    foo
+; 16:  save    {{.+}}
+; 16:  restore {{.+}} 
+; 16:  .end    foo
+; 32:  .set    mips16                  # @foo
+; 32:  .ent    foo
+; 32:  save    {{.+}}
+; 32:  restore {{.+}} 
+; 32:  .end    foo
+define void @nofoo() #1 {
+entry:
+  ret void
+}
+
+; 16:  .set    nomips16                  # @nofoo
+; 16:  .ent    nofoo
+; 16:  .set    noreorder
+; 16:  .set    nomacro
+; 16:  .set    noat
+; 16:  jr      $ra
+; 16:  nop
+; 16:  .set    at
+; 16:  .set    macro
+; 16:  .set    reorder
+; 16:  .end    nofoo
+; 32:  .set    nomips16                  # @nofoo
+; 32:  .ent    nofoo
+; 32:  .set    noreorder
+; 32:  .set    nomacro
+; 32:  .set    noat
+; 32:  jr      $ra
+; 32:  nop
+; 32:  .set    at
+; 32:  .set    macro
+; 32:  .set    reorder
+; 32:  .end    nofoo
+define i32 @main() #2 {
+entry:
+  ret i32 0
+}
+
+; 16:  .set    nomips16                  # @main
+; 16:  .ent    main
+; 16:  .set    noreorder
+; 16:  .set    nomacro
+; 16:  .set    noat
+; 16:  jr      $ra
+; 16:  addiu   $2, $zero, 0
+; 16:  .set    at
+; 16:  .set    macro
+; 16:  .set    reorder
+; 16:  .end    main
+
+; 32:  .set    nomips16                  # @main
+; 32:  .ent    main
+; 32:  .set    noreorder
+; 32:  .set    nomacro
+; 32:  .set    noat
+; 32:  jr      $ra
+; 32:  addiu   $2, $zero, 0
+; 32:  .set    at
+; 32:  .set    macro
+; 32:  .set    reorder
+; 32:  .end    main
+
+
+
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "mips16" "no-frame-pointer-elim"="false" "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" }
+attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "nomips16" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind "less-precise-fpmad"="false" "nomips16" "no-frame-pointer-elim"="false" "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" }
diff --git a/test/CodeGen/Mips/mips16_32_6.ll b/test/CodeGen/Mips/mips16_32_6.ll
new file mode 100644 (file)
index 0000000..f4b8e7a
--- /dev/null
@@ -0,0 +1,86 @@
+; RUN: llc  -march=mipsel -mcpu=mips16 -relocation-model=static -O3 < %s -mips-mixed-16-32  | FileCheck %s -check-prefix=16
+; RUN: llc  -march=mipsel -mcpu=mips32 -relocation-model=static -O3 < %s -mips-mixed-16-32  | FileCheck %s -check-prefix=32
+
+define void @foo() #0 {
+entry:
+  ret void
+}
+
+; 16:  .set    mips16                  # @foo
+; 16:  .ent    foo
+; 16:  save    {{.+}}
+; 16:  restore {{.+}} 
+; 16:  .end    foo
+; 32:  .set    nomips16                  # @foo
+; 32:  .ent    foo
+; 32:  .set    noreorder
+; 32:  .set    nomacro
+; 32:  .set    noat
+; 32:  jr      $ra
+; 32:  nop
+; 32:  .set    at
+; 32:  .set    macro
+; 32:  .set    reorder
+; 32:  .end    foo
+define void @nofoo() #1 {
+entry:
+  ret void
+}
+
+; 16:  .set    nomips16                  # @nofoo
+; 16:  .ent    nofoo
+; 16:  .set    noreorder
+; 16:  .set    nomacro
+; 16:  .set    noat
+; 16:  jr      $ra
+; 16:  nop
+; 16:  .set    at
+; 16:  .set    macro
+; 16:  .set    reorder
+; 16:  .end    nofoo
+; 32:  .set    nomips16                  # @nofoo
+; 32:  .ent    nofoo
+; 32:  .set    noreorder
+; 32:  .set    nomacro
+; 32:  .set    noat
+; 32:  jr      $ra
+; 32:  nop
+; 32:  .set    at
+; 32:  .set    macro
+; 32:  .set    reorder
+; 32:  .end    nofoo
+define i32 @main() #2 {
+entry:
+  ret i32 0
+}
+
+; 16:  .set    nomips16                  # @main
+; 16:  .ent    main
+; 16:  .set    noreorder
+; 16:  .set    nomacro
+; 16:  .set    noat
+; 16:  jr      $ra
+; 16:  addiu   $2, $zero, 0
+; 16:  .set    at
+; 16:  .set    macro
+; 16:  .set    reorder
+; 16:  .end    main
+
+; 32:  .set    nomips16                  # @main
+; 32:  .ent    main
+; 32:  .set    noreorder
+; 32:  .set    nomacro
+; 32:  .set    noat
+; 32:  jr      $ra
+; 32:  addiu   $2, $zero, 0
+; 32:  .set    at
+; 32:  .set    macro
+; 32:  .set    reorder
+; 32:  .end    main
+
+
+
+
+attributes #0 = { nounwind "less-precise-fpmad"="false"  "no-frame-pointer-elim"="false" "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" }
+attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "nomips16" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind "less-precise-fpmad"="false" "nomips16" "no-frame-pointer-elim"="false" "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" }
diff --git a/test/CodeGen/Mips/mips16_32_7.ll b/test/CodeGen/Mips/mips16_32_7.ll
new file mode 100644 (file)
index 0000000..f8726ea
--- /dev/null
@@ -0,0 +1,76 @@
+; RUN: llc  -march=mipsel -mcpu=mips16 -relocation-model=static -O3 < %s -mips-mixed-16-32  | FileCheck %s -check-prefix=16
+; RUN: llc  -march=mipsel -mcpu=mips32 -relocation-model=static -O3 < %s -mips-mixed-16-32  | FileCheck %s -check-prefix=32
+
+define void @foo() #0 {
+entry:
+  ret void
+}
+
+; 16:  .set    mips16                  # @foo
+; 16:  .ent    foo
+; 16:  save    {{.+}}
+; 16:  restore {{.+}} 
+; 16:  .end    foo
+; 32:  .set    nomips16                  # @foo
+; 32:  .ent    foo
+; 32:  .set    noreorder
+; 32:  .set    nomacro
+; 32:  .set    noat
+; 32:  jr      $ra
+; 32:  nop
+; 32:  .set    at
+; 32:  .set    macro
+; 32:  .set    reorder
+; 32:  .end    foo
+define void @nofoo() #1 {
+entry:
+  ret void
+}
+
+; 16:  .set    nomips16                  # @nofoo
+; 16:  .ent    nofoo
+; 16:  .set    noreorder
+; 16:  .set    nomacro
+; 16:  .set    noat
+; 16:  jr      $ra
+; 16:  nop
+; 16:  .set    at
+; 16:  .set    macro
+; 16:  .set    reorder
+; 16:  .end    nofoo
+; 32:  .set    nomips16                  # @nofoo
+; 32:  .ent    nofoo
+; 32:  .set    noreorder
+; 32:  .set    nomacro
+; 32:  .set    noat
+; 32:  jr      $ra
+; 32:  nop
+; 32:  .set    at
+; 32:  .set    macro
+; 32:  .set    reorder
+; 32:  .end    nofoo
+define i32 @main() #2 {
+entry:
+  ret i32 0
+}
+
+; 16:  .set    mips16                  # @main
+; 16:  .ent    main
+; 16:  save    {{.+}}
+; 16:  restore {{.+}} 
+; 16:  .end    main
+
+; 32:  .set    mips16                  # @main
+; 32:  .ent    main
+; 32:  save    {{.+}}
+; 32:  restore {{.+}} 
+; 32:  .end    main
+
+
+
+
+
+
+attributes #0 = { nounwind "less-precise-fpmad"="false"  "no-frame-pointer-elim"="false" "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" }
+attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "nomips16" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind "less-precise-fpmad"="false" "mips16" "no-frame-pointer-elim"="false" "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" }
diff --git a/test/CodeGen/Mips/mips16_32_8.ll b/test/CodeGen/Mips/mips16_32_8.ll
new file mode 100644 (file)
index 0000000..e51f296
--- /dev/null
@@ -0,0 +1,74 @@
+; RUN: llc  -march=mipsel -mcpu=mips32 -relocation-model=static -O3 < %s -mips-mixed-16-32  | FileCheck %s -check-prefix=32
+
+@x = global float 1.000000e+00, align 4
+@y = global float 0x4007333340000000, align 4
+@i = common global i32 0, align 4
+@f = common global float 0.000000e+00, align 4
+@.str = private unnamed_addr constant [8 x i8] c"f = %f\0A\00", align 1
+@.str1 = private unnamed_addr constant [11 x i8] c"hello %i \0A\00", align 1
+@.str2 = private unnamed_addr constant [13 x i8] c"goodbye %i \0A\00", align 1
+
+define void @foo() #0 {
+entry:
+  store i32 10, i32* @i, align 4
+  ret void
+}
+
+; 32:  .set    mips16                  # @foo
+; 32:  .ent    foo
+; 32:  save    {{.+}}
+; 32:  restore {{.+}} 
+; 32:  .end    foo
+
+define void @nofoo() #1 {
+entry:
+  store i32 20, i32* @i, align 4
+  %0 = load float* @x, align 4
+  %1 = load float* @y, align 4
+  %add = fadd float %0, %1
+  store float %add, float* @f, align 4
+  %2 = load float* @f, align 4
+  %conv = fpext float %2 to double
+  %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([8 x i8]* @.str, i32 0, i32 0), double %conv)
+  ret void
+}
+
+; 32:  .set    nomips16                  # @nofoo
+; 32:  .ent    nofoo
+; 32:  .set    noreorder
+; 32:  .set    nomacro
+; 32:  .set    noat
+; 32:  add.s   {{.+}}
+; 32:  mfc1    {{.+}}
+; 32:  .set    at
+; 32:  .set    macro
+; 32:  .set    reorder
+; 32:  .end    nofoo
+declare i32 @printf(i8*, ...) #2
+
+define i32 @main() #3 {
+entry:
+  call void @foo()
+  %0 = load i32* @i, align 4
+  %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.str1, i32 0, i32 0), i32 %0)
+  call void @nofoo()
+  %1 = load i32* @i, align 4
+  %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @.str2, i32 0, i32 0), i32 %1)
+  ret i32 0
+}
+
+; 32:  .set    nomips16                  # @main
+; 32:  .ent    main
+; 32:  .set    noreorder
+; 32:  .set    nomacro
+; 32:  .set    noat
+; 32:  jr      $ra
+; 32:  .set    at
+; 32:  .set    macro
+; 32:  .set    reorder
+; 32:  .end    main
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "mips16" "no-frame-pointer-elim"="false" "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" }
+attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "nomips16" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "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" }
+attributes #3 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "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" }
diff --git a/test/CodeGen/Mips/mips16_32_9.ll b/test/CodeGen/Mips/mips16_32_9.ll
new file mode 100644 (file)
index 0000000..f5ff368
--- /dev/null
@@ -0,0 +1,51 @@
+; RUN: llc  -march=mipsel -mcpu=mips32 -relocation-model=static -O3 < %s -mips-mixed-16-32  | FileCheck %s -check-prefix=32
+
+define void @foo() #0 {
+entry:
+  ret void
+}
+
+; 32:  .set    mips16                  # @foo
+; 32:  .ent    foo
+; 32:  save    {{.+}}
+; 32:  restore {{.+}} 
+; 32:  .end    foo
+define void @nofoo() #1 {
+entry:
+  ret void
+}
+
+; 32:  .set    nomips16                  # @nofoo
+; 32:  .ent    nofoo
+; 32:  .set    noreorder
+; 32:  .set    nomacro
+; 32:  .set    noat
+; 32:  jr      $ra
+; 32:  nop
+; 32:  .set    at
+; 32:  .set    macro
+; 32:  .set    reorder
+; 32:  .end    nofoo
+define i32 @main() #2 {
+entry:
+  ret i32 0
+}
+
+; 32:  .set    mips16                  # @main
+; 32:  .ent    main
+; 32:  save    {{.+}}
+; 32:  restore {{.+}} 
+; 32:  .end    main
+
+
+
+
+
+
+
+
+
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "mips16" "no-frame-pointer-elim"="false" "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" }
+attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "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" }
+attributes #2 = { nounwind "less-precise-fpmad"="false" "mips16" "no-frame-pointer-elim"="false" "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" }