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