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