Home | History | Annotate | Download | only in AArch64
      1 //===-- AArch64TargetMachine.cpp - Define TargetMachine for AArch64 -------===//
      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 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include "AArch64.h"
     14 #include "AArch64TargetMachine.h"
     15 #include "llvm/PassManager.h"
     16 #include "llvm/CodeGen/Passes.h"
     17 #include "llvm/Support/CommandLine.h"
     18 #include "llvm/Support/TargetRegistry.h"
     19 #include "llvm/Target/TargetOptions.h"
     20 #include "llvm/Transforms/Scalar.h"
     21 using namespace llvm;
     22 
     23 static cl::opt<bool>
     24 EnableCCMP("aarch64-ccmp", cl::desc("Enable the CCMP formation pass"),
     25            cl::init(true), cl::Hidden);
     26 
     27 static cl::opt<bool>
     28 EnableStPairSuppress("aarch64-stp-suppress", cl::desc("Suppress STP for AArch64"),
     29                      cl::init(true), cl::Hidden);
     30 
     31 static cl::opt<bool>
     32 EnableAdvSIMDScalar("aarch64-simd-scalar", cl::desc("Enable use of AdvSIMD scalar"
     33                     " integer instructions"), cl::init(false), cl::Hidden);
     34 
     35 static cl::opt<bool>
     36 EnablePromoteConstant("aarch64-promote-const", cl::desc("Enable the promote "
     37                       "constant pass"), cl::init(true), cl::Hidden);
     38 
     39 static cl::opt<bool>
     40 EnableCollectLOH("aarch64-collect-loh", cl::desc("Enable the pass that emits the"
     41                  " linker optimization hints (LOH)"), cl::init(true),
     42                  cl::Hidden);
     43 
     44 static cl::opt<bool>
     45 EnableDeadRegisterElimination("aarch64-dead-def-elimination", cl::Hidden,
     46                               cl::desc("Enable the pass that removes dead"
     47                                        " definitons and replaces stores to"
     48                                        " them with stores to the zero"
     49                                        " register"),
     50                               cl::init(true));
     51 
     52 static cl::opt<bool>
     53 EnableLoadStoreOpt("aarch64-load-store-opt", cl::desc("Enable the load/store pair"
     54                    " optimization pass"), cl::init(true), cl::Hidden);
     55 
     56 static cl::opt<bool>
     57 EnableAtomicTidy("aarch64-atomic-cfg-tidy", cl::Hidden,
     58                  cl::desc("Run SimplifyCFG after expanding atomic operations"
     59                           " to make use of cmpxchg flow-based information"),
     60                  cl::init(true));
     61 
     62 static cl::opt<bool>
     63 EnableEarlyIfConversion("aarch64-enable-early-ifcvt", cl::Hidden,
     64                         cl::desc("Run early if-conversion"),
     65                         cl::init(true));
     66 
     67 
     68 static cl::opt<bool>
     69 EnableA53Fix835769("aarch64-fix-cortex-a53-835769", cl::Hidden,
     70                 cl::desc("Work around Cortex-A53 erratum 835769"),
     71                 cl::init(false));
     72 
     73 extern "C" void LLVMInitializeAArch64Target() {
     74   // Register the target.
     75   RegisterTargetMachine<AArch64leTargetMachine> X(TheAArch64leTarget);
     76   RegisterTargetMachine<AArch64beTargetMachine> Y(TheAArch64beTarget);
     77 
     78   RegisterTargetMachine<AArch64leTargetMachine> Z(TheARM64leTarget);
     79   RegisterTargetMachine<AArch64beTargetMachine> W(TheARM64beTarget);
     80 }
     81 
     82 /// TargetMachine ctor - Create an AArch64 architecture model.
     83 ///
     84 AArch64TargetMachine::AArch64TargetMachine(const Target &T, StringRef TT,
     85                                            StringRef CPU, StringRef FS,
     86                                            const TargetOptions &Options,
     87                                            Reloc::Model RM, CodeModel::Model CM,
     88                                            CodeGenOpt::Level OL,
     89                                            bool LittleEndian)
     90     : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
     91       Subtarget(TT, CPU, FS, *this, LittleEndian) {
     92   initAsmInfo();
     93 }
     94 
     95 void AArch64leTargetMachine::anchor() { }
     96 
     97 AArch64leTargetMachine::
     98 AArch64leTargetMachine(const Target &T, StringRef TT,
     99                        StringRef CPU, StringRef FS, const TargetOptions &Options,
    100                        Reloc::Model RM, CodeModel::Model CM,
    101                        CodeGenOpt::Level OL)
    102   : AArch64TargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
    103 
    104 void AArch64beTargetMachine::anchor() { }
    105 
    106 AArch64beTargetMachine::
    107 AArch64beTargetMachine(const Target &T, StringRef TT,
    108                        StringRef CPU, StringRef FS, const TargetOptions &Options,
    109                        Reloc::Model RM, CodeModel::Model CM,
    110                        CodeGenOpt::Level OL)
    111   : AArch64TargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
    112 
    113 namespace {
    114 /// AArch64 Code Generator Pass Configuration Options.
    115 class AArch64PassConfig : public TargetPassConfig {
    116 public:
    117   AArch64PassConfig(AArch64TargetMachine *TM, PassManagerBase &PM)
    118       : TargetPassConfig(TM, PM) {}
    119 
    120   AArch64TargetMachine &getAArch64TargetMachine() const {
    121     return getTM<AArch64TargetMachine>();
    122   }
    123 
    124   void addIRPasses()  override;
    125   bool addPreISel() override;
    126   bool addInstSelector() override;
    127   bool addILPOpts() override;
    128   bool addPreRegAlloc() override;
    129   bool addPostRegAlloc() override;
    130   bool addPreSched2() override;
    131   bool addPreEmitPass() override;
    132 };
    133 } // namespace
    134 
    135 void AArch64TargetMachine::addAnalysisPasses(PassManagerBase &PM) {
    136   // Add first the target-independent BasicTTI pass, then our AArch64 pass. This
    137   // allows the AArch64 pass to delegate to the target independent layer when
    138   // appropriate.
    139   PM.add(createBasicTargetTransformInfoPass(this));
    140   PM.add(createAArch64TargetTransformInfoPass(this));
    141 }
    142 
    143 TargetPassConfig *AArch64TargetMachine::createPassConfig(PassManagerBase &PM) {
    144   return new AArch64PassConfig(this, PM);
    145 }
    146 
    147 void AArch64PassConfig::addIRPasses() {
    148   // Always expand atomic operations, we don't deal with atomicrmw or cmpxchg
    149   // ourselves.
    150   addPass(createAtomicExpandLoadLinkedPass(TM));
    151 
    152   // Cmpxchg instructions are often used with a subsequent comparison to
    153   // determine whether it succeeded. We can exploit existing control-flow in
    154   // ldrex/strex loops to simplify this, but it needs tidying up.
    155   if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy)
    156     addPass(createCFGSimplificationPass());
    157 
    158   TargetPassConfig::addIRPasses();
    159 }
    160 
    161 // Pass Pipeline Configuration
    162 bool AArch64PassConfig::addPreISel() {
    163   // Run promote constant before global merge, so that the promoted constants
    164   // get a chance to be merged
    165   if (TM->getOptLevel() != CodeGenOpt::None && EnablePromoteConstant)
    166     addPass(createAArch64PromoteConstantPass());
    167   if (TM->getOptLevel() != CodeGenOpt::None)
    168     addPass(createGlobalMergePass(TM));
    169   if (TM->getOptLevel() != CodeGenOpt::None)
    170     addPass(createAArch64AddressTypePromotionPass());
    171 
    172   return false;
    173 }
    174 
    175 bool AArch64PassConfig::addInstSelector() {
    176   addPass(createAArch64ISelDag(getAArch64TargetMachine(), getOptLevel()));
    177 
    178   // For ELF, cleanup any local-dynamic TLS accesses (i.e. combine as many
    179   // references to _TLS_MODULE_BASE_ as possible.
    180   if (TM->getSubtarget<AArch64Subtarget>().isTargetELF() &&
    181       getOptLevel() != CodeGenOpt::None)
    182     addPass(createAArch64CleanupLocalDynamicTLSPass());
    183 
    184   return false;
    185 }
    186 
    187 bool AArch64PassConfig::addILPOpts() {
    188   if (EnableCCMP)
    189     addPass(createAArch64ConditionalCompares());
    190   if (EnableEarlyIfConversion)
    191     addPass(&EarlyIfConverterID);
    192   if (EnableStPairSuppress)
    193     addPass(createAArch64StorePairSuppressPass());
    194   return true;
    195 }
    196 
    197 bool AArch64PassConfig::addPreRegAlloc() {
    198   // Use AdvSIMD scalar instructions whenever profitable.
    199   if (TM->getOptLevel() != CodeGenOpt::None && EnableAdvSIMDScalar)
    200     addPass(createAArch64AdvSIMDScalar());
    201   return true;
    202 }
    203 
    204 bool AArch64PassConfig::addPostRegAlloc() {
    205   // Change dead register definitions to refer to the zero register.
    206   if (TM->getOptLevel() != CodeGenOpt::None && EnableDeadRegisterElimination)
    207     addPass(createAArch64DeadRegisterDefinitions());
    208   if (TM->getOptLevel() != CodeGenOpt::None &&
    209       TM->getSubtarget<AArch64Subtarget>().isCortexA57())
    210     // Improve performance for some FP/SIMD code for A57.
    211     addPass(createAArch64A57FPLoadBalancing());
    212   return true;
    213 }
    214 
    215 bool AArch64PassConfig::addPreSched2() {
    216   // Expand some pseudo instructions to allow proper scheduling.
    217   addPass(createAArch64ExpandPseudoPass());
    218   // Use load/store pair instructions when possible.
    219   if (TM->getOptLevel() != CodeGenOpt::None && EnableLoadStoreOpt)
    220     addPass(createAArch64LoadStoreOptimizationPass());
    221   return true;
    222 }
    223 
    224 bool AArch64PassConfig::addPreEmitPass() {
    225   if (EnableA53Fix835769)
    226     addPass(createAArch64A53Fix835769());
    227   // Relax conditional branch instructions if they're otherwise out of
    228   // range of their destination.
    229   addPass(createAArch64BranchRelaxation());
    230   if (TM->getOptLevel() != CodeGenOpt::None && EnableCollectLOH &&
    231       TM->getSubtarget<AArch64Subtarget>().isTargetMachO())
    232     addPass(createAArch64CollectLOHPass());
    233   return true;
    234 }
    235