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 CodeGenOptLevel 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 HexagonProcFamilyEnum HexagonProcFamily = Others; 99 Triple TargetTriple; 100 101 // The following objects can use the TargetTriple, so they must be 102 // declared after it. 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 bool hasV71Ops() const { 202 return getHexagonArchVersion() >= Hexagon::ArchEnum::V71; 203 } 204 bool hasV71OpsOnly() const { 205 return getHexagonArchVersion() == Hexagon::ArchEnum::V71; 206 } 207 bool hasV73Ops() const { 208 return getHexagonArchVersion() >= Hexagon::ArchEnum::V73; 209 } 210 bool hasV73OpsOnly() const { 211 return getHexagonArchVersion() == Hexagon::ArchEnum::V73; 212 } 213 214 bool useAudioOps() const { return UseAudioOps; } 215 bool useCompound() const { return UseCompound; } 216 bool useLongCalls() const { return UseLongCalls; } 217 bool useMemops() const { return UseMemops; } 218 bool usePackets() const { return UsePackets; } 219 bool useNewValueJumps() const { return UseNewValueJumps; } 220 bool useNewValueStores() const { return UseNewValueStores; } 221 bool useSmallData() const { return UseSmallData; } 222 bool useUnsafeMath() const { return UseUnsafeMath; } 223 bool useZRegOps() const { return UseZRegOps; } 224 bool useCabac() const { return UseCabac; } 225 226 bool isTinyCore() const { return HexagonProcFamily == TinyCore; } 227 bool isTinyCoreWithDuplex() const { return isTinyCore() && EnableDuplex; } 228 229 bool useHVXIEEEFPOps() const { return UseHVXIEEEFPOps && useHVXOps(); } 230 bool useHVXQFloatOps() const { 231 return UseHVXQFloatOps && HexagonHVXVersion >= Hexagon::ArchEnum::V68; 232 } 233 bool useHVXFloatingPoint() const { return UseHVXFloatingPoint; } 234 bool useHVXOps() const { 235 return HexagonHVXVersion > Hexagon::ArchEnum::NoArch; 236 } 237 bool useHVXV60Ops() const { 238 return HexagonHVXVersion >= Hexagon::ArchEnum::V60; 239 } 240 bool useHVXV62Ops() const { 241 return HexagonHVXVersion >= Hexagon::ArchEnum::V62; 242 } 243 bool useHVXV65Ops() const { 244 return HexagonHVXVersion >= Hexagon::ArchEnum::V65; 245 } 246 bool useHVXV66Ops() const { 247 return HexagonHVXVersion >= Hexagon::ArchEnum::V66; 248 } 249 bool useHVXV67Ops() const { 250 return HexagonHVXVersion >= Hexagon::ArchEnum::V67; 251 } 252 bool useHVXV68Ops() const { 253 return HexagonHVXVersion >= Hexagon::ArchEnum::V68; 254 } 255 bool useHVXV69Ops() const { 256 return HexagonHVXVersion >= Hexagon::ArchEnum::V69; 257 } 258 bool useHVXV71Ops() const { 259 return HexagonHVXVersion >= Hexagon::ArchEnum::V71; 260 } 261 bool useHVXV73Ops() const { 262 return HexagonHVXVersion >= Hexagon::ArchEnum::V73; 263 } 264 bool useHVX128BOps() const { return useHVXOps() && UseHVX128BOps; } 265 bool useHVX64BOps() const { return useHVXOps() && UseHVX64BOps; } 266 267 bool hasMemNoShuf() const { return HasMemNoShuf; } 268 bool hasReservedR19() const { return ReservedR19; } 269 bool usePredicatedCalls() const; 270 271 bool noreturnStackElim() const { return NoreturnStackElim; } 272 273 bool useBSBScheduling() const { return UseBSBScheduling; } 274 bool enableMachineScheduler() const override; 275 276 // Always use the TargetLowering default scheduler. 277 // FIXME: This will use the vliw scheduler which is probably just hurting 278 // compiler time and will be removed eventually anyway. 279 bool enableMachineSchedDefaultSched() const override { return false; } 280 281 // For use with PostRAScheduling: get the anti-dependence breaking that should 282 // be performed before post-RA scheduling. 283 AntiDepBreakMode getAntiDepBreakMode() const override { return ANTIDEP_ALL; } 284 /// True if the subtarget should run a scheduler after register 285 /// allocation. 286 bool enablePostRAScheduler() const override { return true; } 287 288 bool enableSubRegLiveness() const override; 289 290 const std::string &getCPUString () const { return CPUString; } 291 292 const Hexagon::ArchEnum &getHexagonArchVersion() const { 293 return HexagonArchVersion; 294 } 295 296 void getPostRAMutations( 297 std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) 298 const override; 299 300 void getSMSMutations( 301 std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) 302 const override; 303 304 /// Enable use of alias analysis during code generation (during MI 305 /// scheduling, DAGCombine, etc.). 306 bool useAA() const override; 307 308 /// Perform target specific adjustments to the latency of a schedule 309 /// dependency. 310 void adjustSchedDependency(SUnit *Def, int DefOpIdx, SUnit *Use, int UseOpIdx, 311 SDep &Dep) const override; 312 313 unsigned getVectorLength() const { 314 assert(useHVXOps()); 315 if (useHVX64BOps()) 316 return 64; 317 if (useHVX128BOps()) 318 return 128; 319 llvm_unreachable("Invalid HVX vector length settings"); 320 } 321 322 ArrayRef<MVT> getHVXElementTypes() const { 323 static MVT Types[] = {MVT::i8, MVT::i16, MVT::i32}; 324 static MVT TypesV68[] = {MVT::i8, MVT::i16, MVT::i32, MVT::f16, MVT::f32}; 325 326 if (useHVXV68Ops() && useHVXFloatingPoint()) 327 return ArrayRef(TypesV68); 328 return ArrayRef(Types); 329 } 330 331 bool isHVXElementType(MVT Ty, bool IncludeBool = false) const; 332 bool isHVXVectorType(EVT VecTy, bool IncludeBool = false) const; 333 bool isTypeForHVX(Type *VecTy, bool IncludeBool = false) const; 334 335 Align getTypeAlignment(MVT Ty) const { 336 if (isHVXVectorType(Ty, true)) 337 return Align(getVectorLength()); 338 return Align(std::max<unsigned>(1, Ty.getSizeInBits() / 8)); 339 } 340 341 unsigned getL1CacheLineSize() const; 342 unsigned getL1PrefetchDistance() const; 343 344 Intrinsic::ID getIntrinsicId(unsigned Opc) const; 345 346 private: 347 // Helper function responsible for increasing the latency only. 348 int updateLatency(MachineInstr &SrcInst, MachineInstr &DstInst, 349 bool IsArtificial, int Latency) const; 350 void restoreLatency(SUnit *Src, SUnit *Dst) const; 351 void changeLatency(SUnit *Src, SUnit *Dst, unsigned Lat) const; 352 bool isBestZeroLatency(SUnit *Src, SUnit *Dst, const HexagonInstrInfo *TII, 353 SmallSet<SUnit*, 4> &ExclSrc, SmallSet<SUnit*, 4> &ExclDst) const; 354 }; 355 356 } // end namespace llvm 357 358 #endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONSUBTARGET_H 359