Home | History | Annotate | Line # | Download | only in Hexagon
      1 //===- HexagonSubtarget.h - Define Subtarget for the Hexagon ----*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file declares the Hexagon specific subclass of TargetSubtarget.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONSUBTARGET_H
     14 #define LLVM_LIB_TARGET_HEXAGON_HEXAGONSUBTARGET_H
     15 
     16 #include "HexagonArch.h"
     17 #include "HexagonFrameLowering.h"
     18 #include "HexagonISelLowering.h"
     19 #include "HexagonInstrInfo.h"
     20 #include "HexagonRegisterInfo.h"
     21 #include "HexagonSelectionDAGInfo.h"
     22 #include "llvm/ADT/SmallSet.h"
     23 #include "llvm/ADT/StringRef.h"
     24 #include "llvm/CodeGen/ScheduleDAGMutation.h"
     25 #include "llvm/CodeGen/TargetSubtargetInfo.h"
     26 #include "llvm/MC/MCInstrItineraries.h"
     27 #include <memory>
     28 #include <string>
     29 #include <vector>
     30 
     31 #define GET_SUBTARGETINFO_HEADER
     32 #include "HexagonGenSubtargetInfo.inc"
     33 
     34 namespace llvm {
     35 
     36 class MachineInstr;
     37 class SDep;
     38 class SUnit;
     39 class TargetMachine;
     40 class Triple;
     41 
     42 class HexagonSubtarget : public HexagonGenSubtargetInfo {
     43   virtual void anchor();
     44 
     45   bool UseHVX64BOps = false;
     46   bool UseHVX128BOps = false;
     47 
     48   bool UseAudioOps = false;
     49   bool UseCompound = false;
     50   bool UseLongCalls = false;
     51   bool UseMemops = false;
     52   bool UsePackets = false;
     53   bool UseNewValueJumps = false;
     54   bool UseNewValueStores = false;
     55   bool UseSmallData = false;
     56   bool UseUnsafeMath = false;
     57   bool UseZRegOps = false;
     58 
     59   bool HasPreV65 = false;
     60   bool HasMemNoShuf = false;
     61   bool EnableDuplex = false;
     62   bool ReservedR19 = false;
     63   bool NoreturnStackElim = false;
     64 
     65 public:
     66   Hexagon::ArchEnum HexagonArchVersion;
     67   Hexagon::ArchEnum HexagonHVXVersion = Hexagon::ArchEnum::NoArch;
     68   CodeGenOpt::Level OptLevel;
     69   /// True if the target should use Back-Skip-Back scheduling. This is the
     70   /// default for V60.
     71   bool UseBSBScheduling;
     72 
     73   struct UsrOverflowMutation : public ScheduleDAGMutation {
     74     void apply(ScheduleDAGInstrs *DAG) override;
     75   };
     76   struct HVXMemLatencyMutation : public ScheduleDAGMutation {
     77     void apply(ScheduleDAGInstrs *DAG) override;
     78   };
     79   struct CallMutation : public ScheduleDAGMutation {
     80     void apply(ScheduleDAGInstrs *DAG) override;
     81   private:
     82     bool shouldTFRICallBind(const HexagonInstrInfo &HII,
     83           const SUnit &Inst1, const SUnit &Inst2) const;
     84   };
     85   struct BankConflictMutation : public ScheduleDAGMutation {
     86     void apply(ScheduleDAGInstrs *DAG) override;
     87   };
     88 
     89 private:
     90   enum HexagonProcFamilyEnum { Others, TinyCore };
     91 
     92   std::string CPUString;
     93   Triple TargetTriple;
     94 
     95   // The following objects can use the TargetTriple, so they must be
     96   // declared after it.
     97   HexagonProcFamilyEnum HexagonProcFamily = Others;
     98   HexagonInstrInfo InstrInfo;
     99   HexagonRegisterInfo RegInfo;
    100   HexagonTargetLowering TLInfo;
    101   HexagonSelectionDAGInfo TSInfo;
    102   HexagonFrameLowering FrameLowering;
    103   InstrItineraryData InstrItins;
    104 
    105 public:
    106   HexagonSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
    107                    const TargetMachine &TM);
    108 
    109   const Triple &getTargetTriple() const { return TargetTriple; }
    110   bool isEnvironmentMusl() const {
    111     return TargetTriple.getEnvironment() == Triple::Musl;
    112   }
    113 
    114   /// getInstrItins - Return the instruction itineraries based on subtarget
    115   /// selection.
    116   const InstrItineraryData *getInstrItineraryData() const override {
    117     return &InstrItins;
    118   }
    119   const HexagonInstrInfo *getInstrInfo() const override { return &InstrInfo; }
    120   const HexagonRegisterInfo *getRegisterInfo() const override {
    121     return &RegInfo;
    122   }
    123   const HexagonTargetLowering *getTargetLowering() const override {
    124     return &TLInfo;
    125   }
    126   const HexagonFrameLowering *getFrameLowering() const override {
    127     return &FrameLowering;
    128   }
    129   const HexagonSelectionDAGInfo *getSelectionDAGInfo() const override {
    130     return &TSInfo;
    131   }
    132 
    133   HexagonSubtarget &initializeSubtargetDependencies(StringRef CPU,
    134                                                     StringRef FS);
    135 
    136   /// ParseSubtargetFeatures - Parses features string setting specified
    137   /// subtarget options.  Definition of function is auto generated by tblgen.
    138   void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
    139 
    140   bool hasV5Ops() const {
    141     return getHexagonArchVersion() >= Hexagon::ArchEnum::V5;
    142   }
    143   bool hasV5OpsOnly() const {
    144     return getHexagonArchVersion() == Hexagon::ArchEnum::V5;
    145   }
    146   bool hasV55Ops() const {
    147     return getHexagonArchVersion() >= Hexagon::ArchEnum::V55;
    148   }
    149   bool hasV55OpsOnly() const {
    150     return getHexagonArchVersion() == Hexagon::ArchEnum::V55;
    151   }
    152   bool hasV60Ops() const {
    153     return getHexagonArchVersion() >= Hexagon::ArchEnum::V60;
    154   }
    155   bool hasV60OpsOnly() const {
    156     return getHexagonArchVersion() == Hexagon::ArchEnum::V60;
    157   }
    158   bool hasV62Ops() const {
    159     return getHexagonArchVersion() >= Hexagon::ArchEnum::V62;
    160   }
    161   bool hasV62OpsOnly() const {
    162     return getHexagonArchVersion() == Hexagon::ArchEnum::V62;
    163   }
    164   bool hasV65Ops() const {
    165     return getHexagonArchVersion() >= Hexagon::ArchEnum::V65;
    166   }
    167   bool hasV65OpsOnly() const {
    168     return getHexagonArchVersion() == Hexagon::ArchEnum::V65;
    169   }
    170   bool hasV66Ops() const {
    171     return getHexagonArchVersion() >= Hexagon::ArchEnum::V66;
    172   }
    173   bool hasV66OpsOnly() const {
    174     return getHexagonArchVersion() == Hexagon::ArchEnum::V66;
    175   }
    176   bool hasV67Ops() const {
    177     return getHexagonArchVersion() >= Hexagon::ArchEnum::V67;
    178   }
    179   bool hasV67OpsOnly() const {
    180     return getHexagonArchVersion() == Hexagon::ArchEnum::V67;
    181   }
    182   bool hasV68Ops() const {
    183     return getHexagonArchVersion() >= Hexagon::ArchEnum::V68;
    184   }
    185   bool hasV68OpsOnly() const {
    186     return getHexagonArchVersion() == Hexagon::ArchEnum::V68;
    187   }
    188 
    189   bool useAudioOps() const { return UseAudioOps; }
    190   bool useCompound() const { return UseCompound; }
    191   bool useLongCalls() const { return UseLongCalls; }
    192   bool useMemops() const { return UseMemops; }
    193   bool usePackets() const { return UsePackets; }
    194   bool useNewValueJumps() const { return UseNewValueJumps; }
    195   bool useNewValueStores() const { return UseNewValueStores; }
    196   bool useSmallData() const { return UseSmallData; }
    197   bool useUnsafeMath() const { return UseUnsafeMath; }
    198   bool useZRegOps() const { return UseZRegOps; }
    199 
    200   bool isTinyCore() const { return HexagonProcFamily == TinyCore; }
    201   bool isTinyCoreWithDuplex() const { return isTinyCore() && EnableDuplex; }
    202 
    203   bool useHVXOps() const {
    204     return HexagonHVXVersion > Hexagon::ArchEnum::NoArch;
    205   }
    206   bool useHVXV60Ops() const {
    207     return HexagonHVXVersion >= Hexagon::ArchEnum::V60;
    208   }
    209   bool useHVXV62Ops() const {
    210     return HexagonHVXVersion >= Hexagon::ArchEnum::V62;
    211   }
    212   bool useHVXV65Ops() const {
    213     return HexagonHVXVersion >= Hexagon::ArchEnum::V65;
    214   }
    215   bool useHVXV66Ops() const {
    216     return HexagonHVXVersion >= Hexagon::ArchEnum::V66;
    217   }
    218   bool useHVXV67Ops() const {
    219     return HexagonHVXVersion >= Hexagon::ArchEnum::V67;
    220   }
    221   bool useHVXV68Ops() const {
    222     return HexagonHVXVersion >= Hexagon::ArchEnum::V68;
    223   }
    224   bool useHVX128BOps() const { return useHVXOps() && UseHVX128BOps; }
    225   bool useHVX64BOps() const { return useHVXOps() && UseHVX64BOps; }
    226 
    227   bool hasMemNoShuf() const { return HasMemNoShuf; }
    228   bool hasReservedR19() const { return ReservedR19; }
    229   bool usePredicatedCalls() const;
    230 
    231   bool noreturnStackElim() const { return NoreturnStackElim; }
    232 
    233   bool useBSBScheduling() const { return UseBSBScheduling; }
    234   bool enableMachineScheduler() const override;
    235 
    236   // Always use the TargetLowering default scheduler.
    237   // FIXME: This will use the vliw scheduler which is probably just hurting
    238   // compiler time and will be removed eventually anyway.
    239   bool enableMachineSchedDefaultSched() const override { return false; }
    240 
    241   // For use with PostRAScheduling: get the anti-dependence breaking that should
    242   // be performed before post-RA scheduling.
    243   AntiDepBreakMode getAntiDepBreakMode() const override { return ANTIDEP_ALL; }
    244   /// True if the subtarget should run a scheduler after register
    245   /// allocation.
    246   bool enablePostRAScheduler() const override { return true; }
    247 
    248   bool enableSubRegLiveness() const override;
    249 
    250   const std::string &getCPUString () const { return CPUString; }
    251 
    252   const Hexagon::ArchEnum &getHexagonArchVersion() const {
    253     return HexagonArchVersion;
    254   }
    255 
    256   void getPostRAMutations(
    257       std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations)
    258       const override;
    259 
    260   void getSMSMutations(
    261       std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations)
    262       const override;
    263 
    264   /// Enable use of alias analysis during code generation (during MI
    265   /// scheduling, DAGCombine, etc.).
    266   bool useAA() const override;
    267 
    268   /// Perform target specific adjustments to the latency of a schedule
    269   /// dependency.
    270   void adjustSchedDependency(SUnit *Def, int DefOpIdx, SUnit *Use, int UseOpIdx,
    271                              SDep &Dep) const override;
    272 
    273   unsigned getVectorLength() const {
    274     assert(useHVXOps());
    275     if (useHVX64BOps())
    276       return 64;
    277     if (useHVX128BOps())
    278       return 128;
    279     llvm_unreachable("Invalid HVX vector length settings");
    280   }
    281 
    282   ArrayRef<MVT> getHVXElementTypes() const {
    283     static MVT Types[] = { MVT::i8, MVT::i16, MVT::i32 };
    284     return makeArrayRef(Types);
    285   }
    286 
    287   bool isHVXElementType(MVT Ty, bool IncludeBool = false) const;
    288   bool isHVXVectorType(MVT VecTy, bool IncludeBool = false) const;
    289   bool isTypeForHVX(Type *VecTy, bool IncludeBool = false) const;
    290 
    291   unsigned getTypeAlignment(MVT Ty) const {
    292     if (isHVXVectorType(Ty, true))
    293       return getVectorLength();
    294     return Ty.getSizeInBits() / 8;
    295   }
    296 
    297   unsigned getL1CacheLineSize() const;
    298   unsigned getL1PrefetchDistance() const;
    299 
    300 private:
    301   // Helper function responsible for increasing the latency only.
    302   void updateLatency(MachineInstr &SrcInst, MachineInstr &DstInst, SDep &Dep)
    303       const;
    304   void restoreLatency(SUnit *Src, SUnit *Dst) const;
    305   void changeLatency(SUnit *Src, SUnit *Dst, unsigned Lat) const;
    306   bool isBestZeroLatency(SUnit *Src, SUnit *Dst, const HexagonInstrInfo *TII,
    307       SmallSet<SUnit*, 4> &ExclSrc, SmallSet<SUnit*, 4> &ExclDst) const;
    308 };
    309 
    310 } // end namespace llvm
    311 
    312 #endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONSUBTARGET_H
    313