1 //===- HexagonSubtarget.h - Define Subtarget for the Hexagon ----*- C++ -*-===// 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 // This file declares the Hexagon specific subclass of TargetSubtarget. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONSUBTARGET_H 15 #define LLVM_LIB_TARGET_HEXAGON_HEXAGONSUBTARGET_H 16 17 #include "HexagonDepArch.h" 18 #include "HexagonFrameLowering.h" 19 #include "HexagonISelLowering.h" 20 #include "HexagonInstrInfo.h" 21 #include "HexagonRegisterInfo.h" 22 #include "HexagonSelectionDAGInfo.h" 23 #include "llvm/ADT/SmallSet.h" 24 #include "llvm/ADT/StringRef.h" 25 #include "llvm/CodeGen/ScheduleDAGMutation.h" 26 #include "llvm/CodeGen/TargetSubtargetInfo.h" 27 #include "llvm/MC/MCInstrItineraries.h" 28 #include <memory> 29 #include <string> 30 #include <vector> 31 32 #define GET_SUBTARGETINFO_HEADER 33 #include "HexagonGenSubtargetInfo.inc" 34 35 namespace llvm { 36 37 class MachineInstr; 38 class SDep; 39 class SUnit; 40 class TargetMachine; 41 class Triple; 42 43 class HexagonSubtarget : public HexagonGenSubtargetInfo { 44 virtual void anchor(); 45 46 bool UseHVX64BOps = false; 47 bool UseHVX128BOps = false; 48 49 bool UseLongCalls = false; 50 bool UseMemops = false; 51 bool UsePackets = false; 52 bool UseNewValueJumps = false; 53 bool UseNewValueStores = false; 54 bool UseSmallData = false; 55 56 bool HasMemNoShuf = false; 57 bool EnableDuplex = false; 58 bool ReservedR19 = false; 59 60 public: 61 Hexagon::ArchEnum HexagonArchVersion; 62 Hexagon::ArchEnum HexagonHVXVersion = Hexagon::ArchEnum::V4; 63 CodeGenOpt::Level OptLevel; 64 /// True if the target should use Back-Skip-Back scheduling. This is the 65 /// default for V60. 66 bool UseBSBScheduling; 67 68 struct UsrOverflowMutation : public ScheduleDAGMutation { 69 void apply(ScheduleDAGInstrs *DAG) override; 70 }; 71 struct HVXMemLatencyMutation : public ScheduleDAGMutation { 72 void apply(ScheduleDAGInstrs *DAG) override; 73 }; 74 struct CallMutation : public ScheduleDAGMutation { 75 void apply(ScheduleDAGInstrs *DAG) override; 76 private: 77 bool shouldTFRICallBind(const HexagonInstrInfo &HII, 78 const SUnit &Inst1, const SUnit &Inst2) const; 79 }; 80 struct BankConflictMutation : public ScheduleDAGMutation { 81 void apply(ScheduleDAGInstrs *DAG) override; 82 }; 83 84 private: 85 std::string CPUString; 86 HexagonInstrInfo InstrInfo; 87 HexagonRegisterInfo RegInfo; 88 HexagonTargetLowering TLInfo; 89 HexagonSelectionDAGInfo TSInfo; 90 HexagonFrameLowering FrameLowering; 91 InstrItineraryData InstrItins; 92 93 public: 94 HexagonSubtarget(const Triple &TT, StringRef CPU, StringRef FS, 95 const TargetMachine &TM); 96 97 /// getInstrItins - Return the instruction itineraries based on subtarget 98 /// selection. getInstrItineraryData()99 const InstrItineraryData *getInstrItineraryData() const override { 100 return &InstrItins; 101 } getInstrInfo()102 const HexagonInstrInfo *getInstrInfo() const override { return &InstrInfo; } getRegisterInfo()103 const HexagonRegisterInfo *getRegisterInfo() const override { 104 return &RegInfo; 105 } getTargetLowering()106 const HexagonTargetLowering *getTargetLowering() const override { 107 return &TLInfo; 108 } getFrameLowering()109 const HexagonFrameLowering *getFrameLowering() const override { 110 return &FrameLowering; 111 } getSelectionDAGInfo()112 const HexagonSelectionDAGInfo *getSelectionDAGInfo() const override { 113 return &TSInfo; 114 } 115 116 HexagonSubtarget &initializeSubtargetDependencies(StringRef CPU, 117 StringRef FS); 118 119 /// ParseSubtargetFeatures - Parses features string setting specified 120 /// subtarget options. Definition of function is auto generated by tblgen. 121 void ParseSubtargetFeatures(StringRef CPU, StringRef FS); 122 hasV5Ops()123 bool hasV5Ops() const { 124 return getHexagonArchVersion() >= Hexagon::ArchEnum::V5; 125 } hasV5OpsOnly()126 bool hasV5OpsOnly() const { 127 return getHexagonArchVersion() == Hexagon::ArchEnum::V5; 128 } hasV55Ops()129 bool hasV55Ops() const { 130 return getHexagonArchVersion() >= Hexagon::ArchEnum::V55; 131 } hasV55OpsOnly()132 bool hasV55OpsOnly() const { 133 return getHexagonArchVersion() == Hexagon::ArchEnum::V55; 134 } hasV60Ops()135 bool hasV60Ops() const { 136 return getHexagonArchVersion() >= Hexagon::ArchEnum::V60; 137 } hasV60OpsOnly()138 bool hasV60OpsOnly() const { 139 return getHexagonArchVersion() == Hexagon::ArchEnum::V60; 140 } hasV62Ops()141 bool hasV62Ops() const { 142 return getHexagonArchVersion() >= Hexagon::ArchEnum::V62; 143 } hasV62OpsOnly()144 bool hasV62OpsOnly() const { 145 return getHexagonArchVersion() == Hexagon::ArchEnum::V62; 146 } hasV65Ops()147 bool hasV65Ops() const { 148 return getHexagonArchVersion() >= Hexagon::ArchEnum::V65; 149 } hasV65OpsOnly()150 bool hasV65OpsOnly() const { 151 return getHexagonArchVersion() == Hexagon::ArchEnum::V65; 152 } 153 useLongCalls()154 bool useLongCalls() const { return UseLongCalls; } useMemops()155 bool useMemops() const { return UseMemops; } usePackets()156 bool usePackets() const { return UsePackets; } useNewValueJumps()157 bool useNewValueJumps() const { return UseNewValueJumps; } useNewValueStores()158 bool useNewValueStores() const { return UseNewValueStores; } useSmallData()159 bool useSmallData() const { return UseSmallData; } 160 useHVXOps()161 bool useHVXOps() const { return HexagonHVXVersion > Hexagon::ArchEnum::V4; } useHVX128BOps()162 bool useHVX128BOps() const { return useHVXOps() && UseHVX128BOps; } useHVX64BOps()163 bool useHVX64BOps() const { return useHVXOps() && UseHVX64BOps; } 164 hasMemNoShuf()165 bool hasMemNoShuf() const { return HasMemNoShuf; } hasReservedR19()166 bool hasReservedR19() const { return ReservedR19; } 167 bool usePredicatedCalls() const; 168 useBSBScheduling()169 bool useBSBScheduling() const { return UseBSBScheduling; } 170 bool enableMachineScheduler() const override; 171 172 // Always use the TargetLowering default scheduler. 173 // FIXME: This will use the vliw scheduler which is probably just hurting 174 // compiler time and will be removed eventually anyway. enableMachineSchedDefaultSched()175 bool enableMachineSchedDefaultSched() const override { return false; } 176 getAntiDepBreakMode()177 AntiDepBreakMode getAntiDepBreakMode() const override { return ANTIDEP_ALL; } enablePostRAScheduler()178 bool enablePostRAScheduler() const override { return true; } 179 180 bool enableSubRegLiveness() const override; 181 getCPUString()182 const std::string &getCPUString () const { return CPUString; } 183 getHexagonArchVersion()184 const Hexagon::ArchEnum &getHexagonArchVersion() const { 185 return HexagonArchVersion; 186 } 187 188 void getPostRAMutations( 189 std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) 190 const override; 191 192 void getSMSMutations( 193 std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) 194 const override; 195 196 /// Enable use of alias analysis during code generation (during MI 197 /// scheduling, DAGCombine, etc.). 198 bool useAA() const override; 199 200 /// Perform target specific adjustments to the latency of a schedule 201 /// dependency. 202 void adjustSchedDependency(SUnit *def, SUnit *use, SDep& dep) const override; 203 getVectorLength()204 unsigned getVectorLength() const { 205 assert(useHVXOps()); 206 if (useHVX64BOps()) 207 return 64; 208 if (useHVX128BOps()) 209 return 128; 210 llvm_unreachable("Invalid HVX vector length settings"); 211 } 212 getHVXElementTypes()213 ArrayRef<MVT> getHVXElementTypes() const { 214 static MVT Types[] = { MVT::i8, MVT::i16, MVT::i32 }; 215 return makeArrayRef(Types); 216 } 217 218 bool isHVXVectorType(MVT VecTy, bool IncludeBool = false) const { 219 if (!VecTy.isVector() || !useHVXOps()) 220 return false; 221 MVT ElemTy = VecTy.getVectorElementType(); 222 if (!IncludeBool && ElemTy == MVT::i1) 223 return false; 224 225 unsigned HwLen = getVectorLength(); 226 unsigned NumElems = VecTy.getVectorNumElements(); 227 ArrayRef<MVT> ElemTypes = getHVXElementTypes(); 228 229 if (IncludeBool && ElemTy == MVT::i1) { 230 // Special case for the v512i1, etc. 231 if (8*HwLen == NumElems) 232 return true; 233 // Boolean HVX vector types are formed from regular HVX vector types 234 // by replacing the element type with i1. 235 for (MVT T : ElemTypes) 236 if (NumElems * T.getSizeInBits() == 8*HwLen) 237 return true; 238 return false; 239 } 240 241 unsigned VecWidth = VecTy.getSizeInBits(); 242 if (VecWidth != 8*HwLen && VecWidth != 16*HwLen) 243 return false; 244 return llvm::any_of(ElemTypes, [ElemTy] (MVT T) { return ElemTy == T; }); 245 } 246 getTypeAlignment(MVT Ty)247 unsigned getTypeAlignment(MVT Ty) const { 248 if (isHVXVectorType(Ty, true)) 249 return getVectorLength(); 250 return Ty.getSizeInBits() / 8; 251 } 252 253 unsigned getL1CacheLineSize() const; 254 unsigned getL1PrefetchDistance() const; 255 256 private: 257 // Helper function responsible for increasing the latency only. 258 void updateLatency(MachineInstr &SrcInst, MachineInstr &DstInst, SDep &Dep) 259 const; 260 void restoreLatency(SUnit *Src, SUnit *Dst) const; 261 void changeLatency(SUnit *Src, SUnit *Dst, unsigned Lat) const; 262 bool isBestZeroLatency(SUnit *Src, SUnit *Dst, const HexagonInstrInfo *TII, 263 SmallSet<SUnit*, 4> &ExclSrc, SmallSet<SUnit*, 4> &ExclDst) const; 264 }; 265 266 } // end namespace llvm 267 268 #endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONSUBTARGET_H 269