MipsSubtarget.cpp revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
1//===-- MipsSubtarget.cpp - Mips Subtarget Information --------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Mips specific subclass of TargetSubtargetInfo.
11//
12//===----------------------------------------------------------------------===//
13
14#include "MipsMachineFunction.h"
15#include "Mips.h"
16#include "MipsRegisterInfo.h"
17#include "MipsSubtarget.h"
18#include "MipsTargetMachine.h"
19#include "llvm/IR/Attributes.h"
20#include "llvm/IR/Function.h"
21#include "llvm/Support/CommandLine.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/TargetRegistry.h"
24#include "llvm/Support/raw_ostream.h"
25
26using namespace llvm;
27
28#define DEBUG_TYPE "mips-subtarget"
29
30#define GET_SUBTARGETINFO_TARGET_DESC
31#define GET_SUBTARGETINFO_CTOR
32#include "MipsGenSubtargetInfo.inc"
33
34// FIXME: Maybe this should be on by default when Mips16 is specified
35//
36static cl::opt<bool> Mixed16_32(
37  "mips-mixed-16-32",
38  cl::init(false),
39  cl::desc("Allow for a mixture of Mips16 "
40           "and Mips32 code in a single source file"),
41  cl::Hidden);
42
43static cl::opt<bool> Mips_Os16(
44  "mips-os16",
45  cl::init(false),
46  cl::desc("Compile all functions that don' use "
47           "floating point as Mips 16"),
48  cl::Hidden);
49
50static cl::opt<bool>
51Mips16HardFloat("mips16-hard-float", cl::NotHidden,
52                cl::desc("MIPS: mips16 hard float enable."),
53                cl::init(false));
54
55static cl::opt<bool>
56Mips16ConstantIslands(
57  "mips16-constant-islands", cl::NotHidden,
58  cl::desc("MIPS: mips16 constant islands enable."),
59  cl::init(true));
60
61/// Select the Mips CPU for the given triple and cpu name.
62/// FIXME: Merge with the copy in MipsMCTargetDesc.cpp
63static inline StringRef selectMipsCPU(StringRef TT, StringRef CPU) {
64  if (CPU.empty() || CPU == "generic") {
65    Triple TheTriple(TT);
66    if (TheTriple.getArch() == Triple::mips ||
67        TheTriple.getArch() == Triple::mipsel)
68      CPU = "mips32";
69    else
70      CPU = "mips64";
71  }
72  return CPU;
73}
74
75void MipsSubtarget::anchor() { }
76
77MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU,
78                             const std::string &FS, bool little,
79                             Reloc::Model _RM, MipsTargetMachine *_TM)
80    : MipsGenSubtargetInfo(TT, CPU, FS), MipsArchVersion(Mips32),
81      MipsABI(UnknownABI), IsLittle(little), IsSingleFloat(false),
82      IsFP64bit(false), IsNaN2008bit(false), IsGP64bit(false), HasVFPU(false),
83      HasCnMips(false), IsLinux(true), HasMips3_32(false), HasMips3_32r2(false),
84      HasMips4_32(false), HasMips4_32r2(false), HasMips5_32r2(false),
85      InMips16Mode(false), InMips16HardFloat(Mips16HardFloat),
86      InMicroMipsMode(false), HasDSP(false), HasDSPR2(false),
87      AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), HasMSA(false),
88      RM(_RM), OverrideMode(NoOverride), TM(_TM), TargetTriple(TT) {
89  std::string CPUName = CPU;
90  CPUName = selectMipsCPU(TT, CPUName);
91
92  // Parse features string.
93  ParseSubtargetFeatures(CPUName, FS);
94
95  if (InMips16Mode && !TM->Options.UseSoftFloat) {
96    // Hard float for mips16 means essentially to compile as soft float
97    // but to use a runtime library for soft float that is written with
98    // native mips32 floating point instructions (those runtime routines
99    // run in mips32 hard float mode).
100    TM->Options.UseSoftFloat = true;
101    TM->Options.FloatABIType = FloatABI::Soft;
102    InMips16HardFloat = true;
103  }
104
105  PreviousInMips16Mode = InMips16Mode;
106
107  // Initialize scheduling itinerary for the specified CPU.
108  InstrItins = getInstrItineraryForCPU(CPUName);
109
110  // Don't even attempt to generate code for MIPS-I, MIPS-II, MIPS-III, and
111  // MIPS-V. They have not been tested and currently exist for the integrated
112  // assembler only.
113  if (MipsArchVersion == Mips1)
114    report_fatal_error("Code generation for MIPS-I is not implemented", false);
115  if (MipsArchVersion == Mips2)
116    report_fatal_error("Code generation for MIPS-II is not implemented", false);
117  if (MipsArchVersion == Mips3)
118    report_fatal_error("Code generation for MIPS-III is not implemented",
119                       false);
120  if (MipsArchVersion == Mips5)
121    report_fatal_error("Code generation for MIPS-V is not implemented", false);
122
123  // Assert exactly one ABI was chosen.
124  assert(MipsABI != UnknownABI);
125  assert((((getFeatureBits() & Mips::FeatureO32) != 0) +
126          ((getFeatureBits() & Mips::FeatureEABI) != 0) +
127          ((getFeatureBits() & Mips::FeatureN32) != 0) +
128          ((getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
129
130  // Check if Architecture and ABI are compatible.
131  assert(((!isGP64bit() && (isABI_O32() || isABI_EABI())) ||
132          (isGP64bit() && (isABI_N32() || isABI_N64()))) &&
133         "Invalid  Arch & ABI pair.");
134
135  if (hasMSA() && !isFP64bit())
136    report_fatal_error("MSA requires a 64-bit FPU register file (FR=1 mode). "
137                       "See -mattr=+fp64.",
138                       false);
139
140  if (hasMips32r6()) {
141    StringRef ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
142
143    assert(isFP64bit());
144    assert(isNaN2008());
145    if (hasDSP())
146      report_fatal_error(ISA + " is not compatible with the DSP ASE", false);
147  }
148
149  // Is the target system Linux ?
150  if (TT.find("linux") == std::string::npos)
151    IsLinux = false;
152
153  // Set UseSmallSection.
154  // TODO: Investigate the IsLinux check. I suspect it's really checking for
155  //       bare-metal.
156  UseSmallSection = !IsLinux && (RM == Reloc::Static);
157}
158
159bool
160MipsSubtarget::enablePostRAScheduler(CodeGenOpt::Level OptLevel,
161                                    TargetSubtargetInfo::AntiDepBreakMode &Mode,
162                                     RegClassVector &CriticalPathRCs) const {
163  Mode = TargetSubtargetInfo::ANTIDEP_NONE;
164  CriticalPathRCs.clear();
165  CriticalPathRCs.push_back(isGP64bit() ? &Mips::GPR64RegClass
166                                        : &Mips::GPR32RegClass);
167  return OptLevel >= CodeGenOpt::Aggressive;
168}
169
170//FIXME: This logic for reseting the subtarget along with
171// the helper classes can probably be simplified but there are a lot of
172// cases so we will defer rewriting this to later.
173//
174void MipsSubtarget::resetSubtarget(MachineFunction *MF) {
175  bool ChangeToMips16 = false, ChangeToNoMips16 = false;
176  DEBUG(dbgs() << "resetSubtargetFeatures" << "\n");
177  AttributeSet FnAttrs = MF->getFunction()->getAttributes();
178  ChangeToMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex,
179                                        "mips16");
180  ChangeToNoMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex,
181                                        "nomips16");
182  assert (!(ChangeToMips16 & ChangeToNoMips16) &&
183          "mips16 and nomips16 specified on the same function");
184  if (ChangeToMips16) {
185    if (PreviousInMips16Mode)
186      return;
187    OverrideMode = Mips16Override;
188    PreviousInMips16Mode = true;
189    TM->setHelperClassesMips16();
190    return;
191  } else if (ChangeToNoMips16) {
192    if (!PreviousInMips16Mode)
193      return;
194    OverrideMode = NoMips16Override;
195    PreviousInMips16Mode = false;
196    TM->setHelperClassesMipsSE();
197    return;
198  } else {
199    if (OverrideMode == NoOverride)
200      return;
201    OverrideMode = NoOverride;
202    DEBUG(dbgs() << "back to default" << "\n");
203    if (inMips16Mode() && !PreviousInMips16Mode) {
204      TM->setHelperClassesMips16();
205      PreviousInMips16Mode = true;
206    } else if (!inMips16Mode() && PreviousInMips16Mode) {
207      TM->setHelperClassesMipsSE();
208      PreviousInMips16Mode = false;
209    }
210    return;
211  }
212}
213
214bool MipsSubtarget::mipsSEUsesSoftFloat() const {
215  return TM->Options.UseSoftFloat && !InMips16HardFloat;
216}
217
218bool MipsSubtarget::useConstantIslands() {
219  DEBUG(dbgs() << "use constant islands " << Mips16ConstantIslands << "\n");
220  return Mips16ConstantIslands;
221}
222