/src/llvm-project/llvm/lib/Target/Hexagon/HexagonSubtarget.h
Line | Count | Source (jump to first uncovered line) |
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 | 0 | const Triple &getTargetTriple() const { return TargetTriple; } |
115 | 48.8k | bool isEnvironmentMusl() const { |
116 | 48.8k | return TargetTriple.getEnvironment() == Triple::Musl; |
117 | 48.8k | } |
118 | | |
119 | | /// getInstrItins - Return the instruction itineraries based on subtarget |
120 | | /// selection. |
121 | 112k | const InstrItineraryData *getInstrItineraryData() const override { |
122 | 112k | return &InstrItins; |
123 | 112k | } |
124 | 19.6M | const HexagonInstrInfo *getInstrInfo() const override { return &InstrInfo; } |
125 | 33.8M | const HexagonRegisterInfo *getRegisterInfo() const override { |
126 | 33.8M | return &RegInfo; |
127 | 33.8M | } |
128 | 294k | const HexagonTargetLowering *getTargetLowering() const override { |
129 | 294k | return &TLInfo; |
130 | 294k | } |
131 | 1.59M | const HexagonFrameLowering *getFrameLowering() const override { |
132 | 1.59M | return &FrameLowering; |
133 | 1.59M | } |
134 | 38.4k | const HexagonSelectionDAGInfo *getSelectionDAGInfo() const override { |
135 | 38.4k | return &TSInfo; |
136 | 38.4k | } |
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 | 0 | bool isXRaySupported() const override { return true; } |
146 | | |
147 | 0 | bool hasV5Ops() const { |
148 | 0 | return getHexagonArchVersion() >= Hexagon::ArchEnum::V5; |
149 | 0 | } |
150 | 0 | bool hasV5OpsOnly() const { |
151 | 0 | return getHexagonArchVersion() == Hexagon::ArchEnum::V5; |
152 | 0 | } |
153 | 0 | bool hasV55Ops() const { |
154 | 0 | return getHexagonArchVersion() >= Hexagon::ArchEnum::V55; |
155 | 0 | } |
156 | 0 | bool hasV55OpsOnly() const { |
157 | 0 | return getHexagonArchVersion() == Hexagon::ArchEnum::V55; |
158 | 0 | } |
159 | 4.93M | bool hasV60Ops() const { |
160 | 4.93M | return getHexagonArchVersion() >= Hexagon::ArchEnum::V60; |
161 | 4.93M | } |
162 | 1.76M | bool hasV60OpsOnly() const { |
163 | 1.76M | return getHexagonArchVersion() == Hexagon::ArchEnum::V60; |
164 | 1.76M | } |
165 | 20.2k | bool hasV62Ops() const { |
166 | 20.2k | return getHexagonArchVersion() >= Hexagon::ArchEnum::V62; |
167 | 20.2k | } |
168 | 0 | bool hasV62OpsOnly() const { |
169 | 0 | return getHexagonArchVersion() == Hexagon::ArchEnum::V62; |
170 | 0 | } |
171 | 4.77k | bool hasV65Ops() const { |
172 | 4.77k | return getHexagonArchVersion() >= Hexagon::ArchEnum::V65; |
173 | 4.77k | } |
174 | 0 | bool hasV65OpsOnly() const { |
175 | 0 | return getHexagonArchVersion() == Hexagon::ArchEnum::V65; |
176 | 0 | } |
177 | 4 | bool hasV66Ops() const { |
178 | 4 | return getHexagonArchVersion() >= Hexagon::ArchEnum::V66; |
179 | 4 | } |
180 | 0 | bool hasV66OpsOnly() const { |
181 | 0 | return getHexagonArchVersion() == Hexagon::ArchEnum::V66; |
182 | 0 | } |
183 | 1 | bool hasV67Ops() const { |
184 | 1 | return getHexagonArchVersion() >= Hexagon::ArchEnum::V67; |
185 | 1 | } |
186 | 0 | bool hasV67OpsOnly() const { |
187 | 0 | return getHexagonArchVersion() == Hexagon::ArchEnum::V67; |
188 | 0 | } |
189 | 0 | bool hasV68Ops() const { |
190 | 0 | return getHexagonArchVersion() >= Hexagon::ArchEnum::V68; |
191 | 0 | } |
192 | 0 | bool hasV68OpsOnly() const { |
193 | 0 | return getHexagonArchVersion() == Hexagon::ArchEnum::V68; |
194 | 0 | } |
195 | 0 | bool hasV69Ops() const { |
196 | 0 | return getHexagonArchVersion() >= Hexagon::ArchEnum::V69; |
197 | 0 | } |
198 | 0 | bool hasV69OpsOnly() const { |
199 | 0 | return getHexagonArchVersion() == Hexagon::ArchEnum::V69; |
200 | 0 | } |
201 | 0 | bool hasV71Ops() const { |
202 | 0 | return getHexagonArchVersion() >= Hexagon::ArchEnum::V71; |
203 | 0 | } |
204 | 0 | bool hasV71OpsOnly() const { |
205 | 0 | return getHexagonArchVersion() == Hexagon::ArchEnum::V71; |
206 | 0 | } |
207 | 0 | bool hasV73Ops() const { |
208 | 0 | return getHexagonArchVersion() >= Hexagon::ArchEnum::V73; |
209 | 0 | } |
210 | 0 | bool hasV73OpsOnly() const { |
211 | 0 | return getHexagonArchVersion() == Hexagon::ArchEnum::V73; |
212 | 0 | } |
213 | | |
214 | 0 | bool useAudioOps() const { return UseAudioOps; } |
215 | 9.22k | bool useCompound() const { return UseCompound; } |
216 | 14.4k | bool useLongCalls() const { return UseLongCalls; } |
217 | 1.09k | bool useMemops() const { return UseMemops; } |
218 | 8.46k | bool usePackets() const { return UsePackets; } |
219 | 8.46k | bool useNewValueJumps() const { return UseNewValueJumps; } |
220 | 3.84M | bool useNewValueStores() const { return UseNewValueStores; } |
221 | 88.8k | bool useSmallData() const { return UseSmallData; } |
222 | 0 | bool useUnsafeMath() const { return UseUnsafeMath; } |
223 | 0 | bool useZRegOps() const { return UseZRegOps; } |
224 | 0 | bool useCabac() const { return UseCabac; } |
225 | | |
226 | 539k | bool isTinyCore() const { return HexagonProcFamily == TinyCore; } |
227 | 517k | bool isTinyCoreWithDuplex() const { return isTinyCore() && EnableDuplex; } |
228 | | |
229 | 0 | bool useHVXIEEEFPOps() const { return UseHVXIEEEFPOps && useHVXOps(); } |
230 | 0 | bool useHVXQFloatOps() const { |
231 | 0 | return UseHVXQFloatOps && HexagonHVXVersion >= Hexagon::ArchEnum::V68; |
232 | 0 | } |
233 | 0 | bool useHVXFloatingPoint() const { return UseHVXFloatingPoint; } |
234 | 2.27M | bool useHVXOps() const { |
235 | 2.27M | return HexagonHVXVersion > Hexagon::ArchEnum::NoArch; |
236 | 2.27M | } |
237 | 0 | bool useHVXV60Ops() const { |
238 | 0 | return HexagonHVXVersion >= Hexagon::ArchEnum::V60; |
239 | 0 | } |
240 | 0 | bool useHVXV62Ops() const { |
241 | 0 | return HexagonHVXVersion >= Hexagon::ArchEnum::V62; |
242 | 0 | } |
243 | 0 | bool useHVXV65Ops() const { |
244 | 0 | return HexagonHVXVersion >= Hexagon::ArchEnum::V65; |
245 | 0 | } |
246 | 0 | bool useHVXV66Ops() const { |
247 | 0 | return HexagonHVXVersion >= Hexagon::ArchEnum::V66; |
248 | 0 | } |
249 | 0 | bool useHVXV67Ops() const { |
250 | 0 | return HexagonHVXVersion >= Hexagon::ArchEnum::V67; |
251 | 0 | } |
252 | 1 | bool useHVXV68Ops() const { |
253 | 1 | return HexagonHVXVersion >= Hexagon::ArchEnum::V68; |
254 | 1 | } |
255 | 0 | bool useHVXV69Ops() const { |
256 | 0 | return HexagonHVXVersion >= Hexagon::ArchEnum::V69; |
257 | 0 | } |
258 | 0 | bool useHVXV71Ops() const { |
259 | 0 | return HexagonHVXVersion >= Hexagon::ArchEnum::V71; |
260 | 0 | } |
261 | 0 | bool useHVXV73Ops() const { |
262 | 0 | return HexagonHVXVersion >= Hexagon::ArchEnum::V73; |
263 | 0 | } |
264 | 0 | bool useHVX128BOps() const { return useHVXOps() && UseHVX128BOps; } |
265 | 0 | bool useHVX64BOps() const { return useHVXOps() && UseHVX64BOps; } |
266 | | |
267 | 0 | bool hasMemNoShuf() const { return HasMemNoShuf; } |
268 | 35.3k | bool hasReservedR19() const { return ReservedR19; } |
269 | | bool usePredicatedCalls() const; |
270 | | |
271 | 0 | bool noreturnStackElim() const { return NoreturnStackElim; } |
272 | | |
273 | 4.86M | 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 | 10.9k | 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 | 8.46k | AntiDepBreakMode getAntiDepBreakMode() const override { return ANTIDEP_ALL; } |
284 | | /// True if the subtarget should run a scheduler after register |
285 | | /// allocation. |
286 | 8.46k | bool enablePostRAScheduler() const override { return true; } |
287 | | |
288 | | bool enableSubRegLiveness() const override; |
289 | | |
290 | 0 | const std::string &getCPUString () const { return CPUString; } |
291 | | |
292 | 6.72M | const Hexagon::ArchEnum &getHexagonArchVersion() const { |
293 | 6.72M | return HexagonArchVersion; |
294 | 6.72M | } |
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 | 0 | unsigned getVectorLength() const { |
314 | 0 | assert(useHVXOps()); |
315 | 0 | if (useHVX64BOps()) |
316 | 0 | return 64; |
317 | 0 | if (useHVX128BOps()) |
318 | 0 | return 128; |
319 | 0 | llvm_unreachable("Invalid HVX vector length settings"); |
320 | 0 | } |
321 | | |
322 | 0 | ArrayRef<MVT> getHVXElementTypes() const { |
323 | 0 | static MVT Types[] = {MVT::i8, MVT::i16, MVT::i32}; |
324 | 0 | static MVT TypesV68[] = {MVT::i8, MVT::i16, MVT::i32, MVT::f16, MVT::f32}; |
325 | |
|
326 | 0 | if (useHVXV68Ops() && useHVXFloatingPoint()) |
327 | 0 | return ArrayRef(TypesV68); |
328 | 0 | return ArrayRef(Types); |
329 | 0 | } |
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 | 172k | Align getTypeAlignment(MVT Ty) const { |
336 | 172k | if (isHVXVectorType(Ty, true)) |
337 | 0 | return Align(getVectorLength()); |
338 | 172k | return Align(std::max<unsigned>(1, Ty.getSizeInBits() / 8)); |
339 | 172k | } |
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 |