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