Coverage Report

Created: 2024-01-17 10:31

/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