LLVM  4.0.0
MipsTargetMachine.cpp
Go to the documentation of this file.
1 //===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===//
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 // Implements the info about Mips target spec.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "MipsTargetMachine.h"
15 #include "Mips.h"
16 #include "Mips16FrameLowering.h"
17 #include "Mips16ISelDAGToDAG.h"
18 #include "Mips16ISelLowering.h"
19 #include "Mips16InstrInfo.h"
20 #include "MipsFrameLowering.h"
21 #include "MipsInstrInfo.h"
22 #include "MipsSEFrameLowering.h"
23 #include "MipsSEISelDAGToDAG.h"
24 #include "MipsSEISelLowering.h"
25 #include "MipsSEInstrInfo.h"
26 #include "MipsTargetObjectFile.h"
28 #include "llvm/CodeGen/Passes.h"
31 #include "llvm/Support/Debug.h"
34 #include "llvm/Transforms/Scalar.h"
35 
36 using namespace llvm;
37 
38 #define DEBUG_TYPE "mips"
39 
40 extern "C" void LLVMInitializeMipsTarget() {
41  // Register the target.
46 }
47 
48 static std::string computeDataLayout(const Triple &TT, StringRef CPU,
49  const TargetOptions &Options,
50  bool isLittle) {
51  std::string Ret = "";
52  MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions);
53 
54  // There are both little and big endian mips.
55  if (isLittle)
56  Ret += "e";
57  else
58  Ret += "E";
59 
60  if (ABI.IsO32())
61  Ret += "-m:m";
62  else
63  Ret += "-m:e";
64 
65  // Pointers are 32 bit on some ABIs.
66  if (!ABI.IsN64())
67  Ret += "-p:32:32";
68 
69  // 8 and 16 bit integers only need to have natural alignment, but try to
70  // align them to 32 bits. 64 bit integers have natural alignment.
71  Ret += "-i8:8:32-i16:16:32-i64:64";
72 
73  // 32 bit registers are always available and the stack is at least 64 bit
74  // aligned. On N64 64 bit registers are also available and the stack is
75  // 128 bit aligned.
76  if (ABI.IsN64() || ABI.IsN32())
77  Ret += "-n32:64-S128";
78  else
79  Ret += "-n32-S64";
80 
81  return Ret;
82 }
83 
86  if (!RM.hasValue() || CM == CodeModel::JITDefault)
87  return Reloc::Static;
88  return *RM;
89 }
90 
91 // On function prologue, the stack is created by decrementing
92 // its pointer. Once decremented, all references are done with positive
93 // offset from the stack/frame pointer, using StackGrowsUp enables
94 // an easier handling.
95 // Using CodeModel::Large enables different CALL behavior.
97  StringRef CPU, StringRef FS,
98  const TargetOptions &Options,
101  bool isLittle)
102  : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT,
103  CPU, FS, Options, getEffectiveRelocModel(CM, RM), CM,
104  OL),
105  isLittle(isLittle), TLOF(make_unique<MipsTargetObjectFile>()),
106  ABI(MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)),
107  Subtarget(nullptr), DefaultSubtarget(TT, CPU, FS, isLittle, *this),
108  NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16",
109  isLittle, *this),
110  Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16",
111  isLittle, *this) {
112  Subtarget = &DefaultSubtarget;
113  initAsmInfo();
114 }
115 
117 
118 void MipsebTargetMachine::anchor() { }
119 
121  StringRef CPU, StringRef FS,
122  const TargetOptions &Options,
124  CodeModel::Model CM,
126  : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
127 
128 void MipselTargetMachine::anchor() { }
129 
131  StringRef CPU, StringRef FS,
132  const TargetOptions &Options,
134  CodeModel::Model CM,
136  : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
137 
138 const MipsSubtarget *
140  Attribute CPUAttr = F.getFnAttribute("target-cpu");
141  Attribute FSAttr = F.getFnAttribute("target-features");
142 
143  std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
144  ? CPUAttr.getValueAsString().str()
145  : TargetCPU;
146  std::string FS = !FSAttr.hasAttribute(Attribute::None)
147  ? FSAttr.getValueAsString().str()
148  : TargetFS;
149  bool hasMips16Attr =
151  bool hasNoMips16Attr =
153 
154  // FIXME: This is related to the code below to reset the target options,
155  // we need to know whether or not the soft float flag is set on the
156  // function, so we can enable it as a subtarget feature.
157  bool softFloat =
158  F.hasFnAttribute("use-soft-float") &&
159  F.getFnAttribute("use-soft-float").getValueAsString() == "true";
160 
161  if (hasMips16Attr)
162  FS += FS.empty() ? "+mips16" : ",+mips16";
163  else if (hasNoMips16Attr)
164  FS += FS.empty() ? "-mips16" : ",-mips16";
165  if (softFloat)
166  FS += FS.empty() ? "+soft-float" : ",+soft-float";
167 
168  auto &I = SubtargetMap[CPU + FS];
169  if (!I) {
170  // This needs to be done before we create a new subtarget since any
171  // creation will depend on the TM and the code generation flags on the
172  // function that reside in TargetOptions.
174  I = llvm::make_unique<MipsSubtarget>(TargetTriple, CPU, FS, isLittle,
175  *this);
176  }
177  return I.get();
178 }
179 
181  DEBUG(dbgs() << "resetSubtarget\n");
182 
183  Subtarget = const_cast<MipsSubtarget *>(getSubtargetImpl(*MF->getFunction()));
184  MF->setSubtarget(Subtarget);
185  return;
186 }
187 
188 namespace {
189 /// Mips Code Generator Pass Configuration Options.
190 class MipsPassConfig : public TargetPassConfig {
191 public:
192  MipsPassConfig(MipsTargetMachine *TM, PassManagerBase &PM)
193  : TargetPassConfig(TM, PM) {
194  // The current implementation of long branch pass requires a scratch
195  // register ($at) to be available before branch instructions. Tail merging
196  // can break this requirement, so disable it when long branch pass is
197  // enabled.
198  EnableTailMerge = !getMipsSubtarget().enableLongBranchPass();
199  }
200 
201  MipsTargetMachine &getMipsTargetMachine() const {
202  return getTM<MipsTargetMachine>();
203  }
204 
205  const MipsSubtarget &getMipsSubtarget() const {
206  return *getMipsTargetMachine().getSubtargetImpl();
207  }
208 
209  void addIRPasses() override;
210  bool addInstSelector() override;
211  void addPreEmitPass() override;
212 
213  void addPreRegAlloc() override;
214 
215 };
216 } // namespace
217 
219  return new MipsPassConfig(this, PM);
220 }
221 
222 void MipsPassConfig::addIRPasses() {
224  addPass(createAtomicExpandPass(&getMipsTargetMachine()));
225  if (getMipsSubtarget().os16())
226  addPass(createMipsOs16Pass(getMipsTargetMachine()));
227  if (getMipsSubtarget().inMips16HardFloat())
228  addPass(createMips16HardFloatPass(getMipsTargetMachine()));
229 }
230 // Install an instruction selector pass using
231 // the ISelDag to gen Mips code.
232 bool MipsPassConfig::addInstSelector() {
233  addPass(createMipsModuleISelDagPass(getMipsTargetMachine()));
234  addPass(createMips16ISelDag(getMipsTargetMachine(), getOptLevel()));
235  addPass(createMipsSEISelDag(getMipsTargetMachine(), getOptLevel()));
236  return false;
237 }
238 
239 void MipsPassConfig::addPreRegAlloc() {
240  addPass(createMipsOptimizePICCallPass(getMipsTargetMachine()));
241 }
242 
244  return TargetIRAnalysis([this](const Function &F) {
245  if (Subtarget->allowMixed16_32()) {
246  DEBUG(errs() << "No Target Transform Info Pass Added\n");
247  // FIXME: This is no longer necessary as the TTI returned is per-function.
249  }
250 
251  DEBUG(errs() << "Target Transform Info Pass Added\n");
252  return TargetTransformInfo(BasicTTIImpl(this, F));
253  });
254 }
255 
256 // Implemented by targets that want to run passes immediately before
257 // machine code is emitted. return true if -print-machineinstrs should
258 // print out the code after the passes.
259 void MipsPassConfig::addPreEmitPass() {
260  MipsTargetMachine &TM = getMipsTargetMachine();
261 
262  // The delay slot filler pass can potientially create forbidden slot (FS)
263  // hazards for MIPSR6 which the hazard schedule pass (HSP) will fix. Any
264  // (new) pass that creates compact branches after the HSP must handle FS
265  // hazards itself or be pipelined before the HSP.
266  addPass(createMipsDelaySlotFillerPass(TM));
267  addPass(createMipsHazardSchedule());
268  addPass(createMipsLongBranchPass(TM));
269  addPass(createMipsConstantIslandPass());
270 }
static ARMBaseTargetMachine::ARMABI computeTargetABI(const Triple &TT, StringRef CPU, const TargetOptions &Options)
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
MCTargetOptions MCOptions
Machine level options.
bool hasValue() const
Definition: Optional.h:125
virtual void addIRPasses()
Add common target configurable passes that perform LLVM IR to IR transforms following machine indepen...
FunctionPass * createMipsSEISelDag(MipsTargetMachine &TM, CodeGenOpt::Level OptLevel)
Triple TargetTriple
Triple string, CPU name, and target feature strings the TargetMachine instance is created with...
FunctionPass * createMipsOptimizePICCallPass(MipsTargetMachine &TM)
Return an OptimizeCall object.
Target & getTheMipselTarget()
Analysis pass providing the TargetTransformInfo.
void resetSubtarget(MachineFunction *MF)
Reset the subtarget for the Mips target.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition: Function.h:234
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
bool hasAttribute(AttrKind Val) const
Return true if the attribute is present.
Definition: Attributes.cpp:185
TargetPassConfig * createPassConfig(PassManagerBase &PM) override
Create a pass configuration object to be used by addPassToEmitX methods for generating a pipeline of ...
FunctionPass * createAtomicExpandPass(const TargetMachine *TM)
No attributes have been set.
Definition: Attributes.h:69
Target-Independent Code Generator Pass Configuration Options.
#define F(x, y, z)
Definition: MD5.cpp:51
Target & getTheMips64Target()
Function Alias Analysis false
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
MipsebTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Optional< Reloc::Model > RM, CodeModel::Model CM, CodeGenOpt::Level OL)
FunctionPass * createMipsHazardSchedule()
Returns a pass that clears pipeline hazards.
static std::string computeDataLayout(const Triple &TT, StringRef CPU, const TargetOptions &Options, bool isLittle)
Target & getTheMips64elTarget()
Concrete BasicTTIImpl that can be used if no further customization is needed.
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&...args)
Constructs a new T() with the given args and returns a unique_ptr<T> which owns the object...
Definition: STLExtras.h:845
static Reloc::Model getEffectiveRelocModel(Optional< Reloc::Model > RM)
FunctionPass * createMipsLongBranchPass(MipsTargetMachine &TM)
createMipsLongBranchPass - Returns a pass that converts branches to long branches.
bool IsN32() const
Definition: MipsABIInfo.h:43
void setSubtarget(const TargetSubtargetInfo *ST)
bool IsN64() const
Definition: MipsABIInfo.h:44
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
This class describes a target machine that is implemented with the LLVM target-independent code gener...
FunctionPass * createMipsConstantIslandPass()
Returns a pass that converts branches to long branches.
FunctionPass * createMipsModuleISelDagPass(MipsTargetMachine &TM)
FunctionPass * createMips16ISelDag(MipsTargetMachine &TM, CodeGenOpt::Level OptLevel)
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:225
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
ModulePass * createMips16HardFloatPass(MipsTargetMachine &TM)
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
TargetIRAnalysis getTargetIRAnalysis() override
Get a TargetIRAnalysis implementation for the target.
bool IsO32() const
Definition: MipsABIInfo.h:42
MipselTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Optional< Reloc::Model > RM, CodeModel::Model CM, CodeGenOpt::Level OL)
FunctionPass * createMipsDelaySlotFillerPass(MipsTargetMachine &TM)
createMipsDelaySlotFillerPass - Returns a pass that fills in delay slots in Mips MachineFunctions ...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
Target - Wrapper for Target specific information.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:130
Target & getTheMipsTarget()
ModulePass * createMipsOs16Pass(MipsTargetMachine &TM)
Definition: MipsOs16.cpp:158
Basic Alias true
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Definition: Module.cpp:384
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.h:226
#define I(x, y, z)
Definition: MD5.cpp:54
void resetTargetOptions(const Function &F) const
Reset the target options based on the function's attributes.
const MipsSubtarget * getSubtargetImpl() const
bool allowMixed16_32() const
StringRef getValueAsString() const
Return the attribute's value as a string.
Definition: Attributes.cpp:178
MipsTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Optional< Reloc::Model > RM, CodeModel::Model CM, CodeGenOpt::Level OL, bool isLittle)
static MipsABIInfo computeTargetABI(const Triple &TT, StringRef CPU, const MCTargetOptions &Options)
Definition: MipsABIInfo.cpp:50
RegisterTargetMachine - Helper template for registering a target machine implementation, for use in the target machine initialization function.
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:537
#define DEBUG(X)
Definition: Debug.h:100
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml","ocaml 3.10-compatible collector")
This pass exposes codegen information to IR-level passes.
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
void LLVMInitializeMipsTarget()