LLVM API Documentation
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 }