LLVM API Documentation

ARMTargetMachine.cpp
Go to the documentation of this file.
00001 //===-- ARMTargetMachine.cpp - Define TargetMachine for ARM ---------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //
00011 //===----------------------------------------------------------------------===//
00012 
00013 #include "ARM.h"
00014 #include "ARMTargetMachine.h"
00015 #include "ARMFrameLowering.h"
00016 #include "llvm/CodeGen/Passes.h"
00017 #include "llvm/MC/MCAsmInfo.h"
00018 #include "llvm/PassManager.h"
00019 #include "llvm/Support/CommandLine.h"
00020 #include "llvm/Support/FormattedStream.h"
00021 #include "llvm/Support/TargetRegistry.h"
00022 #include "llvm/Target/TargetOptions.h"
00023 #include "llvm/Transforms/Scalar.h"
00024 using namespace llvm;
00025 
00026 static cl::opt<bool>
00027 DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden,
00028                    cl::desc("Inhibit optimization of S->D register accesses on A15"),
00029                    cl::init(false));
00030 
00031 static cl::opt<bool>
00032 EnableAtomicTidy("arm-atomic-cfg-tidy", cl::Hidden,
00033                  cl::desc("Run SimplifyCFG after expanding atomic operations"
00034                           " to make use of cmpxchg flow-based information"),
00035                  cl::init(true));
00036 
00037 extern "C" void LLVMInitializeARMTarget() {
00038   // Register the target.
00039   RegisterTargetMachine<ARMLETargetMachine> X(TheARMLETarget);
00040   RegisterTargetMachine<ARMBETargetMachine> Y(TheARMBETarget);
00041   RegisterTargetMachine<ThumbLETargetMachine> A(TheThumbLETarget);
00042   RegisterTargetMachine<ThumbBETargetMachine> B(TheThumbBETarget);
00043 }
00044 
00045 
00046 /// TargetMachine ctor - Create an ARM architecture model.
00047 ///
00048 ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, StringRef TT,
00049                                            StringRef CPU, StringRef FS,
00050                                            const TargetOptions &Options,
00051                                            Reloc::Model RM, CodeModel::Model CM,
00052                                            CodeGenOpt::Level OL, bool isLittle)
00053     : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
00054       Subtarget(TT, CPU, FS, *this, isLittle, Options) {
00055 
00056   // Default to triple-appropriate float ABI
00057   if (Options.FloatABIType == FloatABI::Default)
00058     this->Options.FloatABIType =
00059         Subtarget.isTargetHardFloat() ? FloatABI::Hard : FloatABI::Soft;
00060 }
00061 
00062 void ARMBaseTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
00063   // Add first the target-independent BasicTTI pass, then our ARM pass. This
00064   // allows the ARM pass to delegate to the target independent layer when
00065   // appropriate.
00066   PM.add(createBasicTargetTransformInfoPass(this));
00067   PM.add(createARMTargetTransformInfoPass(this));
00068 }
00069 
00070 
00071 void ARMTargetMachine::anchor() { }
00072 
00073 ARMTargetMachine::ARMTargetMachine(const Target &T, StringRef TT, StringRef CPU,
00074                                    StringRef FS, const TargetOptions &Options,
00075                                    Reloc::Model RM, CodeModel::Model CM,
00076                                    CodeGenOpt::Level OL, bool isLittle)
00077     : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle) {
00078   initAsmInfo();
00079   if (!Subtarget.hasARMOps())
00080     report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not "
00081                        "support ARM mode execution!");
00082 }
00083 
00084 void ARMLETargetMachine::anchor() { }
00085 
00086 ARMLETargetMachine::ARMLETargetMachine(const Target &T, StringRef TT,
00087                                        StringRef CPU, StringRef FS,
00088                                        const TargetOptions &Options,
00089                                        Reloc::Model RM, CodeModel::Model CM,
00090                                        CodeGenOpt::Level OL)
00091     : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
00092 
00093 void ARMBETargetMachine::anchor() { }
00094 
00095 ARMBETargetMachine::ARMBETargetMachine(const Target &T, StringRef TT,
00096                                        StringRef CPU, StringRef FS,
00097                                        const TargetOptions &Options,
00098                                        Reloc::Model RM, CodeModel::Model CM,
00099                                        CodeGenOpt::Level OL)
00100     : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
00101 
00102 void ThumbTargetMachine::anchor() { }
00103 
00104 ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT,
00105                                        StringRef CPU, StringRef FS,
00106                                        const TargetOptions &Options,
00107                                        Reloc::Model RM, CodeModel::Model CM,
00108                                        CodeGenOpt::Level OL, bool isLittle)
00109     : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL,
00110                            isLittle) {
00111   initAsmInfo();
00112 }
00113 
00114 void ThumbLETargetMachine::anchor() { }
00115 
00116 ThumbLETargetMachine::ThumbLETargetMachine(const Target &T, StringRef TT,
00117                                            StringRef CPU, StringRef FS,
00118                                            const TargetOptions &Options,
00119                                            Reloc::Model RM, CodeModel::Model CM,
00120                                            CodeGenOpt::Level OL)
00121     : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
00122 
00123 void ThumbBETargetMachine::anchor() { }
00124 
00125 ThumbBETargetMachine::ThumbBETargetMachine(const Target &T, StringRef TT,
00126                                            StringRef CPU, StringRef FS,
00127                                            const TargetOptions &Options,
00128                                            Reloc::Model RM, CodeModel::Model CM,
00129                                            CodeGenOpt::Level OL)
00130     : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
00131 
00132 namespace {
00133 /// ARM Code Generator Pass Configuration Options.
00134 class ARMPassConfig : public TargetPassConfig {
00135 public:
00136   ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM)
00137     : TargetPassConfig(TM, PM) {}
00138 
00139   ARMBaseTargetMachine &getARMTargetMachine() const {
00140     return getTM<ARMBaseTargetMachine>();
00141   }
00142 
00143   const ARMSubtarget &getARMSubtarget() const {
00144     return *getARMTargetMachine().getSubtargetImpl();
00145   }
00146 
00147   void addIRPasses() override;
00148   bool addPreISel() override;
00149   bool addInstSelector() override;
00150   bool addPreRegAlloc() override;
00151   bool addPreSched2() override;
00152   bool addPreEmitPass() override;
00153 };
00154 } // namespace
00155 
00156 TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
00157   return new ARMPassConfig(this, PM);
00158 }
00159 
00160 void ARMPassConfig::addIRPasses() {
00161   if (TM->Options.ThreadModel == ThreadModel::Single)
00162     addPass(createLowerAtomicPass());
00163   else
00164     addPass(createAtomicExpandPass(TM));
00165 
00166   // Cmpxchg instructions are often used with a subsequent comparison to
00167   // determine whether it succeeded. We can exploit existing control-flow in
00168   // ldrex/strex loops to simplify this, but it needs tidying up.
00169   const ARMSubtarget *Subtarget = &getARMSubtarget();
00170   if (Subtarget->hasAnyDataBarrier() && !Subtarget->isThumb1Only())
00171     if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy)
00172       addPass(createCFGSimplificationPass());
00173 
00174   TargetPassConfig::addIRPasses();
00175 }
00176 
00177 bool ARMPassConfig::addPreISel() {
00178   if (TM->getOptLevel() != CodeGenOpt::None)
00179     addPass(createGlobalMergePass(TM));
00180 
00181   return false;
00182 }
00183 
00184 bool ARMPassConfig::addInstSelector() {
00185   addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));
00186 
00187   const ARMSubtarget *Subtarget = &getARMSubtarget();
00188   if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() &&
00189       TM->Options.EnableFastISel)
00190     addPass(createARMGlobalBaseRegPass());
00191   return false;
00192 }
00193 
00194 bool ARMPassConfig::addPreRegAlloc() {
00195   if (getOptLevel() != CodeGenOpt::None)
00196     addPass(createARMLoadStoreOptimizationPass(true));
00197   if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9())
00198     addPass(createMLxExpansionPass());
00199   // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be
00200   // enabled when NEON is available.
00201   if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA15() &&
00202     getARMSubtarget().hasNEON() && !DisableA15SDOptimization) {
00203     addPass(createA15SDOptimizerPass());
00204   }
00205   return true;
00206 }
00207 
00208 bool ARMPassConfig::addPreSched2() {
00209   if (getOptLevel() != CodeGenOpt::None) {
00210     addPass(createARMLoadStoreOptimizationPass());
00211     printAndVerify("After ARM load / store optimizer");
00212 
00213     if (getARMSubtarget().hasNEON())
00214       addPass(createExecutionDependencyFixPass(&ARM::DPRRegClass));
00215   }
00216 
00217   // Expand some pseudo instructions into multiple instructions to allow
00218   // proper scheduling.
00219   addPass(createARMExpandPseudoPass());
00220 
00221   if (getOptLevel() != CodeGenOpt::None) {
00222     if (!getARMSubtarget().isThumb1Only()) {
00223       // in v8, IfConversion depends on Thumb instruction widths
00224       if (getARMSubtarget().restrictIT() &&
00225           !getARMSubtarget().prefers32BitThumb())
00226         addPass(createThumb2SizeReductionPass());
00227       addPass(&IfConverterID);
00228     }
00229   }
00230   if (getARMSubtarget().isThumb2())
00231     addPass(createThumb2ITBlockPass());
00232 
00233   return true;
00234 }
00235 
00236 bool ARMPassConfig::addPreEmitPass() {
00237   if (getARMSubtarget().isThumb2()) {
00238     if (!getARMSubtarget().prefers32BitThumb())
00239       addPass(createThumb2SizeReductionPass());
00240 
00241     // Constant island pass work on unbundled instructions.
00242     addPass(&UnpackMachineBundlesID);
00243   }
00244 
00245   addPass(createARMOptimizeBarriersPass());
00246   addPass(createARMConstantIslandPass());
00247 
00248   return true;
00249 }