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