Home | History | Annotate | Download | only in Hexagon
      1 //===-- HexagonTargetMachine.cpp - Define TargetMachine for Hexagon -------===//
      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 Hexagon target spec.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "HexagonTargetMachine.h"
     15 #include "Hexagon.h"
     16 #include "HexagonISelLowering.h"
     17 #include "HexagonMachineScheduler.h"
     18 #include "HexagonTargetObjectFile.h"
     19 #include "HexagonTargetTransformInfo.h"
     20 #include "llvm/CodeGen/Passes.h"
     21 #include "llvm/CodeGen/TargetPassConfig.h"
     22 #include "llvm/IR/LegacyPassManager.h"
     23 #include "llvm/IR/Module.h"
     24 #include "llvm/Support/CommandLine.h"
     25 #include "llvm/Support/TargetRegistry.h"
     26 #include "llvm/Transforms/Scalar.h"
     27 
     28 using namespace llvm;
     29 
     30 static cl::opt<bool> EnableRDFOpt("rdf-opt", cl::Hidden, cl::ZeroOrMore,
     31   cl::init(true), cl::desc("Enable RDF-based optimizations"));
     32 
     33 static cl::opt<bool> DisableHardwareLoops("disable-hexagon-hwloops",
     34   cl::Hidden, cl::desc("Disable Hardware Loops for Hexagon target"));
     35 
     36 static cl::opt<bool> DisableAModeOpt("disable-hexagon-amodeopt",
     37   cl::Hidden, cl::ZeroOrMore, cl::init(false),
     38   cl::desc("Disable Hexagon Addressing Mode Optimization"));
     39 
     40 static cl::opt<bool> DisableHexagonCFGOpt("disable-hexagon-cfgopt",
     41   cl::Hidden, cl::ZeroOrMore, cl::init(false),
     42   cl::desc("Disable Hexagon CFG Optimization"));
     43 
     44 static cl::opt<bool> DisableStoreWidening("disable-store-widen",
     45   cl::Hidden, cl::init(false), cl::desc("Disable store widening"));
     46 
     47 static cl::opt<bool> EnableExpandCondsets("hexagon-expand-condsets",
     48   cl::init(true), cl::Hidden, cl::ZeroOrMore,
     49   cl::desc("Early expansion of MUX"));
     50 
     51 static cl::opt<bool> EnableEarlyIf("hexagon-eif", cl::init(true), cl::Hidden,
     52   cl::ZeroOrMore, cl::desc("Enable early if-conversion"));
     53 
     54 static cl::opt<bool> EnableGenInsert("hexagon-insert", cl::init(true),
     55   cl::Hidden, cl::desc("Generate \"insert\" instructions"));
     56 
     57 static cl::opt<bool> EnableCommGEP("hexagon-commgep", cl::init(true),
     58   cl::Hidden, cl::ZeroOrMore, cl::desc("Enable commoning of GEP instructions"));
     59 
     60 static cl::opt<bool> EnableGenExtract("hexagon-extract", cl::init(true),
     61   cl::Hidden, cl::desc("Generate \"extract\" instructions"));
     62 
     63 static cl::opt<bool> EnableGenMux("hexagon-mux", cl::init(true), cl::Hidden,
     64   cl::desc("Enable converting conditional transfers into MUX instructions"));
     65 
     66 static cl::opt<bool> EnableGenPred("hexagon-gen-pred", cl::init(true),
     67   cl::Hidden, cl::desc("Enable conversion of arithmetic operations to "
     68   "predicate instructions"));
     69 
     70 static cl::opt<bool> DisableHSDR("disable-hsdr", cl::init(false), cl::Hidden,
     71   cl::desc("Disable splitting double registers"));
     72 
     73 static cl::opt<bool> EnableBitSimplify("hexagon-bit", cl::init(true),
     74   cl::Hidden, cl::desc("Bit simplification"));
     75 
     76 static cl::opt<bool> EnableLoopResched("hexagon-loop-resched", cl::init(true),
     77   cl::Hidden, cl::desc("Loop rescheduling"));
     78 
     79 static cl::opt<bool> HexagonNoOpt("hexagon-noopt", cl::init(false),
     80   cl::Hidden, cl::desc("Disable backend optimizations"));
     81 
     82 /// HexagonTargetMachineModule - Note that this is used on hosts that
     83 /// cannot link in a library unless there are references into the
     84 /// library.  In particular, it seems that it is not possible to get
     85 /// things to work on Win32 without this.  Though it is unused, do not
     86 /// remove it.
     87 extern "C" int HexagonTargetMachineModule;
     88 int HexagonTargetMachineModule = 0;
     89 
     90 extern "C" void LLVMInitializeHexagonTarget() {
     91   // Register the target.
     92   RegisterTargetMachine<HexagonTargetMachine> X(TheHexagonTarget);
     93 }
     94 
     95 static ScheduleDAGInstrs *createVLIWMachineSched(MachineSchedContext *C) {
     96   return new VLIWMachineScheduler(C, make_unique<ConvergingVLIWScheduler>());
     97 }
     98 
     99 static MachineSchedRegistry
    100 SchedCustomRegistry("hexagon", "Run Hexagon's custom scheduler",
    101                     createVLIWMachineSched);
    102 
    103 namespace llvm {
    104   FunctionPass *createHexagonBitSimplify();
    105   FunctionPass *createHexagonBranchRelaxation();
    106   FunctionPass *createHexagonCallFrameInformation();
    107   FunctionPass *createHexagonCFGOptimizer();
    108   FunctionPass *createHexagonCommonGEP();
    109   FunctionPass *createHexagonCopyToCombine();
    110   FunctionPass *createHexagonEarlyIfConversion();
    111   FunctionPass *createHexagonExpandCondsets();
    112   FunctionPass *createHexagonFixupHwLoops();
    113   FunctionPass *createHexagonGenExtract();
    114   FunctionPass *createHexagonGenInsert();
    115   FunctionPass *createHexagonGenMux();
    116   FunctionPass *createHexagonGenPredicate();
    117   FunctionPass *createHexagonHardwareLoops();
    118   FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM,
    119                                      CodeGenOpt::Level OptLevel);
    120   FunctionPass *createHexagonLoopRescheduling();
    121   FunctionPass *createHexagonNewValueJump();
    122   FunctionPass *createHexagonOptimizeSZextends();
    123   FunctionPass *createHexagonOptAddrMode();
    124   FunctionPass *createHexagonPacketizer();
    125   FunctionPass *createHexagonPeephole();
    126   FunctionPass *createHexagonRDFOpt();
    127   FunctionPass *createHexagonSplitConst32AndConst64();
    128   FunctionPass *createHexagonSplitDoubleRegs();
    129   FunctionPass *createHexagonStoreWidening();
    130 } // end namespace llvm;
    131 
    132 static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
    133   if (!RM.hasValue())
    134     return Reloc::Static;
    135   return *RM;
    136 }
    137 
    138 HexagonTargetMachine::HexagonTargetMachine(const Target &T, const Triple &TT,
    139                                            StringRef CPU, StringRef FS,
    140                                            const TargetOptions &Options,
    141                                            Optional<Reloc::Model> RM,
    142                                            CodeModel::Model CM,
    143                                            CodeGenOpt::Level OL)
    144     // Specify the vector alignment explicitly. For v512x1, the calculated
    145     // alignment would be 512*alignment(i1), which is 512 bytes, instead of
    146     // the required minimum of 64 bytes.
    147     : LLVMTargetMachine(
    148           T, "e-m:e-p:32:32:32-a:0-n16:32-"
    149              "i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-"
    150              "v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048",
    151           TT, CPU, FS, Options, getEffectiveRelocModel(RM), CM,
    152           (HexagonNoOpt ? CodeGenOpt::None : OL)),
    153       TLOF(make_unique<HexagonTargetObjectFile>()) {
    154   initAsmInfo();
    155 }
    156 
    157 const HexagonSubtarget *
    158 HexagonTargetMachine::getSubtargetImpl(const Function &F) const {
    159   AttributeSet FnAttrs = F.getAttributes();
    160   Attribute CPUAttr =
    161       FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-cpu");
    162   Attribute FSAttr =
    163       FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-features");
    164 
    165   std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
    166                         ? CPUAttr.getValueAsString().str()
    167                         : TargetCPU;
    168   std::string FS = !FSAttr.hasAttribute(Attribute::None)
    169                        ? FSAttr.getValueAsString().str()
    170                        : TargetFS;
    171 
    172   auto &I = SubtargetMap[CPU + FS];
    173   if (!I) {
    174     // This needs to be done before we create a new subtarget since any
    175     // creation will depend on the TM and the code generation flags on the
    176     // function that reside in TargetOptions.
    177     resetTargetOptions(F);
    178     I = llvm::make_unique<HexagonSubtarget>(TargetTriple, CPU, FS, *this);
    179   }
    180   return I.get();
    181 }
    182 
    183 TargetIRAnalysis HexagonTargetMachine::getTargetIRAnalysis() {
    184   return TargetIRAnalysis([this](const Function &F) {
    185     return TargetTransformInfo(HexagonTTIImpl(this, F));
    186   });
    187 }
    188 
    189 
    190 HexagonTargetMachine::~HexagonTargetMachine() {}
    191 
    192 namespace {
    193 /// Hexagon Code Generator Pass Configuration Options.
    194 class HexagonPassConfig : public TargetPassConfig {
    195 public:
    196   HexagonPassConfig(HexagonTargetMachine *TM, PassManagerBase &PM)
    197     : TargetPassConfig(TM, PM) {}
    198 
    199   HexagonTargetMachine &getHexagonTargetMachine() const {
    200     return getTM<HexagonTargetMachine>();
    201   }
    202 
    203   ScheduleDAGInstrs *
    204   createMachineScheduler(MachineSchedContext *C) const override {
    205     return createVLIWMachineSched(C);
    206   }
    207 
    208   void addIRPasses() override;
    209   bool addInstSelector() override;
    210   void addPreRegAlloc() override;
    211   void addPostRegAlloc() override;
    212   void addPreSched2() override;
    213   void addPreEmitPass() override;
    214 };
    215 } // namespace
    216 
    217 TargetPassConfig *HexagonTargetMachine::createPassConfig(PassManagerBase &PM) {
    218   return new HexagonPassConfig(this, PM);
    219 }
    220 
    221 void HexagonPassConfig::addIRPasses() {
    222   TargetPassConfig::addIRPasses();
    223   bool NoOpt = (getOptLevel() == CodeGenOpt::None);
    224 
    225   addPass(createAtomicExpandPass(TM));
    226   if (!NoOpt) {
    227     if (EnableCommGEP)
    228       addPass(createHexagonCommonGEP());
    229     // Replace certain combinations of shifts and ands with extracts.
    230     if (EnableGenExtract)
    231       addPass(createHexagonGenExtract());
    232   }
    233 }
    234 
    235 bool HexagonPassConfig::addInstSelector() {
    236   HexagonTargetMachine &TM = getHexagonTargetMachine();
    237   bool NoOpt = (getOptLevel() == CodeGenOpt::None);
    238 
    239   if (!NoOpt)
    240     addPass(createHexagonOptimizeSZextends());
    241 
    242   addPass(createHexagonISelDag(TM, getOptLevel()));
    243 
    244   if (!NoOpt) {
    245     // Create logical operations on predicate registers.
    246     if (EnableGenPred)
    247       addPass(createHexagonGenPredicate(), false);
    248     // Rotate loops to expose bit-simplification opportunities.
    249     if (EnableLoopResched)
    250       addPass(createHexagonLoopRescheduling(), false);
    251     // Split double registers.
    252     if (!DisableHSDR)
    253       addPass(createHexagonSplitDoubleRegs());
    254     // Bit simplification.
    255     if (EnableBitSimplify)
    256       addPass(createHexagonBitSimplify(), false);
    257     addPass(createHexagonPeephole());
    258     printAndVerify("After hexagon peephole pass");
    259     if (EnableGenInsert)
    260       addPass(createHexagonGenInsert(), false);
    261     if (EnableEarlyIf)
    262       addPass(createHexagonEarlyIfConversion(), false);
    263   }
    264 
    265   return false;
    266 }
    267 
    268 void HexagonPassConfig::addPreRegAlloc() {
    269   if (getOptLevel() != CodeGenOpt::None) {
    270     if (EnableExpandCondsets) {
    271       Pass *Exp = createHexagonExpandCondsets();
    272       insertPass(&RegisterCoalescerID, IdentifyingPassPtr(Exp));
    273     }
    274     if (!DisableStoreWidening)
    275       addPass(createHexagonStoreWidening(), false);
    276     if (!DisableHardwareLoops)
    277       addPass(createHexagonHardwareLoops(), false);
    278   }
    279   if (TM->getOptLevel() >= CodeGenOpt::Default)
    280     addPass(&MachinePipelinerID);
    281 }
    282 
    283 void HexagonPassConfig::addPostRegAlloc() {
    284   if (getOptLevel() != CodeGenOpt::None) {
    285     if (EnableRDFOpt)
    286       addPass(createHexagonRDFOpt());
    287     if (!DisableHexagonCFGOpt)
    288       addPass(createHexagonCFGOptimizer(), false);
    289     if (!DisableAModeOpt)
    290       addPass(createHexagonOptAddrMode(), false);
    291   }
    292 }
    293 
    294 void HexagonPassConfig::addPreSched2() {
    295   addPass(createHexagonCopyToCombine(), false);
    296   if (getOptLevel() != CodeGenOpt::None)
    297     addPass(&IfConverterID, false);
    298   addPass(createHexagonSplitConst32AndConst64());
    299 }
    300 
    301 void HexagonPassConfig::addPreEmitPass() {
    302   bool NoOpt = (getOptLevel() == CodeGenOpt::None);
    303 
    304   if (!NoOpt)
    305     addPass(createHexagonNewValueJump(), false);
    306 
    307   addPass(createHexagonBranchRelaxation(), false);
    308 
    309   // Create Packets.
    310   if (!NoOpt) {
    311     if (!DisableHardwareLoops)
    312       addPass(createHexagonFixupHwLoops(), false);
    313     // Generate MUX from pairs of conditional transfers.
    314     if (EnableGenMux)
    315       addPass(createHexagonGenMux(), false);
    316 
    317     addPass(createHexagonPacketizer(), false);
    318   }
    319 
    320   // Add CFI instructions if necessary.
    321   addPass(createHexagonCallFrameInformation(), false);
    322 }
    323