LLVM API Documentation

AArch64TargetMachine.cpp
Go to the documentation of this file.
00001 //===-- AArch64TargetMachine.cpp - Define TargetMachine for AArch64 -------===//
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 "AArch64.h"
00014 #include "AArch64TargetMachine.h"
00015 #include "llvm/CodeGen/Passes.h"
00016 #include "llvm/CodeGen/RegAllocRegistry.h"
00017 #include "llvm/PassManager.h"
00018 #include "llvm/Support/CommandLine.h"
00019 #include "llvm/Support/TargetRegistry.h"
00020 #include "llvm/Target/TargetOptions.h"
00021 #include "llvm/Transforms/Scalar.h"
00022 using namespace llvm;
00023 
00024 static cl::opt<bool>
00025 EnableCCMP("aarch64-ccmp", cl::desc("Enable the CCMP formation pass"),
00026            cl::init(true), cl::Hidden);
00027 
00028 static cl::opt<bool> EnableMCR("aarch64-mcr",
00029                                cl::desc("Enable the machine combiner pass"),
00030                                cl::init(true), cl::Hidden);
00031 
00032 static cl::opt<bool>
00033 EnableStPairSuppress("aarch64-stp-suppress", cl::desc("Suppress STP for AArch64"),
00034                      cl::init(true), cl::Hidden);
00035 
00036 static cl::opt<bool>
00037 EnableAdvSIMDScalar("aarch64-simd-scalar", cl::desc("Enable use of AdvSIMD scalar"
00038                     " integer instructions"), cl::init(false), cl::Hidden);
00039 
00040 static cl::opt<bool>
00041 EnablePromoteConstant("aarch64-promote-const", cl::desc("Enable the promote "
00042                       "constant pass"), cl::init(true), cl::Hidden);
00043 
00044 static cl::opt<bool>
00045 EnableCollectLOH("aarch64-collect-loh", cl::desc("Enable the pass that emits the"
00046                  " linker optimization hints (LOH)"), cl::init(true),
00047                  cl::Hidden);
00048 
00049 static cl::opt<bool>
00050 EnableDeadRegisterElimination("aarch64-dead-def-elimination", cl::Hidden,
00051                               cl::desc("Enable the pass that removes dead"
00052                                        " definitons and replaces stores to"
00053                                        " them with stores to the zero"
00054                                        " register"),
00055                               cl::init(true));
00056 
00057 static cl::opt<bool>
00058 EnableLoadStoreOpt("aarch64-load-store-opt", cl::desc("Enable the load/store pair"
00059                    " optimization pass"), cl::init(true), cl::Hidden);
00060 
00061 static cl::opt<bool>
00062 EnableAtomicTidy("aarch64-atomic-cfg-tidy", cl::Hidden,
00063                  cl::desc("Run SimplifyCFG after expanding atomic operations"
00064                           " to make use of cmpxchg flow-based information"),
00065                  cl::init(true));
00066 
00067 static cl::opt<bool>
00068 EnableEarlyIfConversion("aarch64-enable-early-ifcvt", cl::Hidden,
00069                         cl::desc("Run early if-conversion"),
00070                         cl::init(true));
00071 
00072 static cl::opt<bool>
00073 EnableCondOpt("aarch64-condopt",
00074               cl::desc("Enable the condition optimizer pass"),
00075               cl::init(true), cl::Hidden);
00076 
00077 static cl::opt<bool>
00078 EnablePBQP("aarch64-pbqp", cl::Hidden,
00079            cl::desc("Use PBQP register allocator (experimental)"),
00080            cl::init(false));
00081 
00082 extern "C" void LLVMInitializeAArch64Target() {
00083   // Register the target.
00084   RegisterTargetMachine<AArch64leTargetMachine> X(TheAArch64leTarget);
00085   RegisterTargetMachine<AArch64beTargetMachine> Y(TheAArch64beTarget);
00086   RegisterTargetMachine<AArch64leTargetMachine> Z(TheARM64Target);
00087 }
00088 
00089 /// TargetMachine ctor - Create an AArch64 architecture model.
00090 ///
00091 AArch64TargetMachine::AArch64TargetMachine(const Target &T, StringRef TT,
00092                                            StringRef CPU, StringRef FS,
00093                                            const TargetOptions &Options,
00094                                            Reloc::Model RM, CodeModel::Model CM,
00095                                            CodeGenOpt::Level OL,
00096                                            bool LittleEndian)
00097     : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
00098       Subtarget(TT, CPU, FS, *this, LittleEndian),
00099       usingPBQP(false) {
00100   initAsmInfo();
00101 
00102   if (EnablePBQP && Subtarget.isCortexA57() && OL != CodeGenOpt::None) {
00103     usingPBQP = true;
00104     RegisterRegAlloc::setDefault(createAArch64A57PBQPRegAlloc);
00105   }
00106 }
00107 
00108 void AArch64leTargetMachine::anchor() { }
00109 
00110 AArch64leTargetMachine::
00111 AArch64leTargetMachine(const Target &T, StringRef TT,
00112                        StringRef CPU, StringRef FS, const TargetOptions &Options,
00113                        Reloc::Model RM, CodeModel::Model CM,
00114                        CodeGenOpt::Level OL)
00115   : AArch64TargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
00116 
00117 void AArch64beTargetMachine::anchor() { }
00118 
00119 AArch64beTargetMachine::
00120 AArch64beTargetMachine(const Target &T, StringRef TT,
00121                        StringRef CPU, StringRef FS, const TargetOptions &Options,
00122                        Reloc::Model RM, CodeModel::Model CM,
00123                        CodeGenOpt::Level OL)
00124   : AArch64TargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
00125 
00126 namespace {
00127 /// AArch64 Code Generator Pass Configuration Options.
00128 class AArch64PassConfig : public TargetPassConfig {
00129 public:
00130   AArch64PassConfig(AArch64TargetMachine *TM, PassManagerBase &PM)
00131       : TargetPassConfig(TM, PM) {
00132     if (TM->getOptLevel() != CodeGenOpt::None)
00133       substitutePass(&PostRASchedulerID, &PostMachineSchedulerID);
00134   }
00135 
00136   AArch64TargetMachine &getAArch64TargetMachine() const {
00137     return getTM<AArch64TargetMachine>();
00138   }
00139 
00140   void addIRPasses()  override;
00141   bool addPreISel() override;
00142   bool addInstSelector() override;
00143   bool addILPOpts() override;
00144   bool addPreRegAlloc() override;
00145   bool addPostRegAlloc() override;
00146   bool addPreSched2() override;
00147   bool addPreEmitPass() override;
00148 };
00149 } // namespace
00150 
00151 void AArch64TargetMachine::addAnalysisPasses(PassManagerBase &PM) {
00152   // Add first the target-independent BasicTTI pass, then our AArch64 pass. This
00153   // allows the AArch64 pass to delegate to the target independent layer when
00154   // appropriate.
00155   PM.add(createBasicTargetTransformInfoPass(this));
00156   PM.add(createAArch64TargetTransformInfoPass(this));
00157 }
00158 
00159 TargetPassConfig *AArch64TargetMachine::createPassConfig(PassManagerBase &PM) {
00160   return new AArch64PassConfig(this, PM);
00161 }
00162 
00163 void AArch64PassConfig::addIRPasses() {
00164   // Always expand atomic operations, we don't deal with atomicrmw or cmpxchg
00165   // ourselves.
00166   addPass(createAtomicExpandPass(TM));
00167 
00168   // Cmpxchg instructions are often used with a subsequent comparison to
00169   // determine whether it succeeded. We can exploit existing control-flow in
00170   // ldrex/strex loops to simplify this, but it needs tidying up.
00171   if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy)
00172     addPass(createCFGSimplificationPass());
00173 
00174   TargetPassConfig::addIRPasses();
00175 }
00176 
00177 // Pass Pipeline Configuration
00178 bool AArch64PassConfig::addPreISel() {
00179   // Run promote constant before global merge, so that the promoted constants
00180   // get a chance to be merged
00181   if (TM->getOptLevel() != CodeGenOpt::None && EnablePromoteConstant)
00182     addPass(createAArch64PromoteConstantPass());
00183   if (TM->getOptLevel() != CodeGenOpt::None)
00184     addPass(createGlobalMergePass(TM));
00185   if (TM->getOptLevel() != CodeGenOpt::None)
00186     addPass(createAArch64AddressTypePromotionPass());
00187 
00188   return false;
00189 }
00190 
00191 bool AArch64PassConfig::addInstSelector() {
00192   addPass(createAArch64ISelDag(getAArch64TargetMachine(), getOptLevel()));
00193 
00194   // For ELF, cleanup any local-dynamic TLS accesses (i.e. combine as many
00195   // references to _TLS_MODULE_BASE_ as possible.
00196   if (TM->getSubtarget<AArch64Subtarget>().isTargetELF() &&
00197       getOptLevel() != CodeGenOpt::None)
00198     addPass(createAArch64CleanupLocalDynamicTLSPass());
00199 
00200   return false;
00201 }
00202 
00203 bool AArch64PassConfig::addILPOpts() {
00204   if (EnableCondOpt)
00205     addPass(createAArch64ConditionOptimizerPass());
00206   if (EnableCCMP)
00207     addPass(createAArch64ConditionalCompares());
00208   if (EnableMCR)
00209     addPass(&MachineCombinerID);
00210   if (EnableEarlyIfConversion)
00211     addPass(&EarlyIfConverterID);
00212   if (EnableStPairSuppress)
00213     addPass(createAArch64StorePairSuppressPass());
00214   return true;
00215 }
00216 
00217 bool AArch64PassConfig::addPreRegAlloc() {
00218   // Use AdvSIMD scalar instructions whenever profitable.
00219   if (TM->getOptLevel() != CodeGenOpt::None && EnableAdvSIMDScalar) {
00220     addPass(createAArch64AdvSIMDScalar());
00221     // The AdvSIMD pass may produce copies that can be rewritten to
00222     // be register coaleascer friendly.
00223     addPass(&PeepholeOptimizerID);
00224   }
00225   return true;
00226 }
00227 
00228 bool AArch64PassConfig::addPostRegAlloc() {
00229   // Change dead register definitions to refer to the zero register.
00230   if (TM->getOptLevel() != CodeGenOpt::None && EnableDeadRegisterElimination)
00231     addPass(createAArch64DeadRegisterDefinitions());
00232   if (TM->getOptLevel() != CodeGenOpt::None &&
00233       TM->getSubtarget<AArch64Subtarget>().isCortexA57() &&
00234       !static_cast<const AArch64TargetMachine *>(TM)->isPBQPUsed())
00235     // Improve performance for some FP/SIMD code for A57.
00236     addPass(createAArch64A57FPLoadBalancing());
00237   return true;
00238 }
00239 
00240 bool AArch64PassConfig::addPreSched2() {
00241   // Expand some pseudo instructions to allow proper scheduling.
00242   addPass(createAArch64ExpandPseudoPass());
00243   // Use load/store pair instructions when possible.
00244   if (TM->getOptLevel() != CodeGenOpt::None && EnableLoadStoreOpt)
00245     addPass(createAArch64LoadStoreOptimizationPass());
00246   return true;
00247 }
00248 
00249 bool AArch64PassConfig::addPreEmitPass() {
00250   // Relax conditional branch instructions if they're otherwise out of
00251   // range of their destination.
00252   addPass(createAArch64BranchRelaxation());
00253   if (TM->getOptLevel() != CodeGenOpt::None && EnableCollectLOH &&
00254       TM->getSubtarget<AArch64Subtarget>().isTargetMachO())
00255     addPass(createAArch64CollectLOHPass());
00256   return true;
00257 }