Coverage Report

Created: 2020-02-25 14:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Basic/Targets/AMDGPU.h
Line
Count
Source (jump to first uncovered line)
1
//===--- AMDGPU.h - Declare AMDGPU target feature support -------*- 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 AMDGPU TargetInfo objects.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
14
#define LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
15
16
#include "clang/Basic/TargetInfo.h"
17
#include "clang/Basic/TargetOptions.h"
18
#include "llvm/ADT/StringSet.h"
19
#include "llvm/ADT/Triple.h"
20
#include "llvm/Support/Compiler.h"
21
#include "llvm/Support/TargetParser.h"
22
23
namespace clang {
24
namespace targets {
25
26
class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
27
28
  static const Builtin::Info BuiltinInfo[];
29
  static const char *const GCCRegNames[];
30
31
  enum AddrSpace {
32
    Generic = 0,
33
    Global = 1,
34
    Local = 3,
35
    Constant = 4,
36
    Private = 5
37
  };
38
  static const LangASMap AMDGPUDefIsGenMap;
39
  static const LangASMap AMDGPUDefIsPrivMap;
40
41
  llvm::AMDGPU::GPUKind GPUKind;
42
  unsigned GPUFeatures;
43
44
875
  bool hasFP64() const {
45
875
    return getTriple().getArch() == llvm::Triple::amdgcn ||
46
875
           
!!(GPUFeatures & llvm::AMDGPU::FEATURE_FP64)197
;
47
875
  }
48
49
  /// Has fast fma f32
50
581
  bool hasFastFMAF() const {
51
581
    return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_FMA_F32);
52
581
  }
53
54
  /// Has fast fma f64
55
293
  bool hasFastFMA() const {
56
293
    return getTriple().getArch() == llvm::Triple::amdgcn;
57
293
  }
58
59
293
  bool hasFMAF() const {
60
293
    return getTriple().getArch() == llvm::Triple::amdgcn ||
61
293
           
!!(GPUFeatures & llvm::AMDGPU::FEATURE_FMA)65
;
62
293
  }
63
64
186
  bool hasFullRateDenormalsF32() const {
65
186
    return !!(GPUFeatures & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
66
186
  }
67
68
293
  bool hasLDEXPF() const {
69
293
    return getTriple().getArch() == llvm::Triple::amdgcn ||
70
293
           
!!(GPUFeatures & llvm::AMDGPU::FEATURE_LDEXP)65
;
71
293
  }
72
73
2.61k
  static bool isAMDGCN(const llvm::Triple &TT) {
74
2.61k
    return TT.getArch() == llvm::Triple::amdgcn;
75
2.61k
  }
76
77
1.00k
  static bool isR600(const llvm::Triple &TT) {
78
1.00k
    return TT.getArch() == llvm::Triple::r600;
79
1.00k
  }
80
81
public:
82
  AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
83
84
  void setAddressSpaceMap(bool DefaultIsPrivate);
85
86
  void adjust(LangOptions &Opts) override;
87
88
1.00k
  uint64_t getPointerWidthV(unsigned AddrSpace) const override {
89
1.00k
    if (isR600(getTriple()))
90
46
      return 32;
91
958
92
958
    if (AddrSpace == Private || 
AddrSpace == Local840
)
93
520
      return 32;
94
438
95
438
    return 64;
96
438
  }
97
98
491
  uint64_t getPointerAlignV(unsigned AddrSpace) const override {
99
491
    return getPointerWidthV(AddrSpace);
100
491
  }
101
102
2.29k
  uint64_t getMaxPointerWidth() const override {
103
2.29k
    return getTriple().getArch() == llvm::Triple::amdgcn ? 
642.07k
:
32214
;
104
2.29k
  }
105
106
4
  const char *getClobbers() const override { return ""; }
107
108
  ArrayRef<const char *> getGCCRegNames() const override;
109
110
6
  ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
111
6
    return None;
112
6
  }
113
114
  /// Accepted register names: (n, m is unsigned integer, n < m)
115
  /// v
116
  /// s
117
  /// {vn}, {v[n]}
118
  /// {sn}, {s[n]}
119
  /// {S} , where S is a special register name
120
  ////{v[n:m]}
121
  /// {s[n:m]}
122
  bool validateAsmConstraint(const char *&Name,
123
60
                             TargetInfo::ConstraintInfo &Info) const override {
124
60
    static const ::llvm::StringSet<> SpecialRegs({
125
60
        "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma",
126
60
        "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo",
127
60
        "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi",
128
60
    });
129
60
130
60
    StringRef S(Name);
131
60
    bool HasLeftParen = false;
132
60
    if (S.front() == '{') {
133
45
      HasLeftParen = true;
134
45
      S = S.drop_front();
135
45
    }
136
60
    if (S.empty())
137
1
      return false;
138
59
    if (S.front() != 'v' && 
S.front() != 's'14
) {
139
8
      if (!HasLeftParen)
140
0
        return false;
141
8
      auto E = S.find('}');
142
8
      if (!SpecialRegs.count(S.substr(0, E)))
143
5
        return false;
144
3
      S = S.drop_front(E + 1);
145
3
      if (!S.empty())
146
2
        return false;
147
1
      // Found {S} where S is a special register.
148
1
      Info.setAllowsRegister();
149
1
      Name = S.data() - 1;
150
1
      return true;
151
1
    }
152
51
    S = S.drop_front();
153
51
    if (!HasLeftParen) {
154
15
      if (!S.empty())
155
4
        return false;
156
11
      // Found s or v.
157
11
      Info.setAllowsRegister();
158
11
      Name = S.data() - 1;
159
11
      return true;
160
11
    }
161
36
    bool HasLeftBracket = false;
162
36
    if (!S.empty() && 
S.front() == '['35
) {
163
21
      HasLeftBracket = true;
164
21
      S = S.drop_front();
165
21
    }
166
36
    unsigned long long N;
167
36
    if (S.empty() || 
consumeUnsignedInteger(S, 10, N)35
)
168
4
      return false;
169
32
    if (!S.empty() && 
S.front() == ':'31
) {
170
14
      if (!HasLeftBracket)
171
0
        return false;
172
14
      S = S.drop_front();
173
14
      unsigned long long M;
174
14
      if (consumeUnsignedInteger(S, 10, M) || 
N >= M12
)
175
3
        return false;
176
29
    }
177
29
    if (HasLeftBracket) {
178
16
      if (S.empty() || S.front() != ']')
179
2
        return false;
180
14
      S = S.drop_front();
181
14
    }
182
29
    
if (27
S.empty()27
||
S.front() != '}'24
)
183
5
      return false;
184
22
    S = S.drop_front();
185
22
    if (!S.empty())
186
2
      return false;
187
20
    // Found {vn}, {sn}, {v[n]}, {s[n]}, {v[n:m]}, or {s[n:m]}.
188
20
    Info.setAllowsRegister();
189
20
    Name = S.data() - 1;
190
20
    return true;
191
20
  }
192
193
  // \p Constraint will be left pointing at the last character of
194
  // the constraint.  In practice, it won't be changed unless the
195
  // constraint is longer than one character.
196
2
  std::string convertConstraint(const char *&Constraint) const override {
197
2
    const char *Begin = Constraint;
198
2
    TargetInfo::ConstraintInfo Info("", "");
199
2
    if (validateAsmConstraint(Constraint, Info))
200
2
      return std::string(Begin).substr(0, Constraint - Begin + 1);
201
0
202
0
    Constraint = Begin;
203
0
    return std::string(1, *Constraint);
204
0
  }
205
206
  bool
207
  initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
208
                 StringRef CPU,
209
                 const std::vector<std::string> &FeatureVec) const override;
210
211
  void adjustTargetOptions(const CodeGenOptions &CGOpts,
212
                           TargetOptions &TargetOpts) const override;
213
214
  ArrayRef<Builtin::Info> getTargetBuiltins() const override;
215
216
  void getTargetDefines(const LangOptions &Opts,
217
                        MacroBuilder &Builder) const override;
218
219
216
  BuiltinVaListKind getBuiltinVaListKind() const override {
220
216
    return TargetInfo::CharPtrBuiltinVaList;
221
216
  }
222
223
16
  bool isValidCPUName(StringRef Name) const override {
224
16
    if (getTriple().getArch() == llvm::Triple::amdgcn)
225
16
      return llvm::AMDGPU::parseArchAMDGCN(Name) != llvm::AMDGPU::GK_NONE;
226
0
    return llvm::AMDGPU::parseArchR600(Name) != llvm::AMDGPU::GK_NONE;
227
0
  }
228
229
  void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
230
231
162
  bool setCPU(const std::string &Name) override {
232
162
    if (getTriple().getArch() == llvm::Triple::amdgcn) {
233
101
      GPUKind = llvm::AMDGPU::parseArchAMDGCN(Name);
234
101
      GPUFeatures = llvm::AMDGPU::getArchAttrAMDGCN(GPUKind);
235
101
    } else {
236
61
      GPUKind = llvm::AMDGPU::parseArchR600(Name);
237
61
      GPUFeatures = llvm::AMDGPU::getArchAttrR600(GPUKind);
238
61
    }
239
162
240
162
    return GPUKind != llvm::AMDGPU::GK_NONE;
241
162
  }
242
243
294
  void setSupportedOpenCLOpts() override {
244
294
    auto &Opts = getSupportedOpenCLOpts();
245
294
    Opts.support("cl_clang_storage_class_specifiers");
246
294
    Opts.support("cl_khr_icd");
247
294
248
294
    bool IsAMDGCN = isAMDGCN(getTriple());
249
294
250
294
    if (hasFP64())
251
228
      Opts.support("cl_khr_fp64");
252
294
253
294
    if (IsAMDGCN || 
GPUKind >= llvm::AMDGPU::GK_CEDAR66
) {
254
269
      Opts.support("cl_khr_byte_addressable_store");
255
269
      Opts.support("cl_khr_global_int32_base_atomics");
256
269
      Opts.support("cl_khr_global_int32_extended_atomics");
257
269
      Opts.support("cl_khr_local_int32_base_atomics");
258
269
      Opts.support("cl_khr_local_int32_extended_atomics");
259
269
    }
260
294
261
294
    if (IsAMDGCN) {
262
228
      Opts.support("cl_khr_fp16");
263
228
      Opts.support("cl_khr_int64_base_atomics");
264
228
      Opts.support("cl_khr_int64_extended_atomics");
265
228
      Opts.support("cl_khr_mipmap_image");
266
228
      Opts.support("cl_khr_mipmap_image_writes");
267
228
      Opts.support("cl_khr_subgroups");
268
228
      Opts.support("cl_khr_3d_image_writes");
269
228
      Opts.support("cl_amd_media_ops");
270
228
      Opts.support("cl_amd_media_ops2");
271
228
    }
272
294
  }
273
274
40
  LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override {
275
40
    switch (TK) {
276
18
    case OCLTK_Image:
277
18
      return LangAS::opencl_constant;
278
0
279
12
    case OCLTK_ClkEvent:
280
12
    case OCLTK_Queue:
281
12
    case OCLTK_ReserveID:
282
12
      return LangAS::opencl_global;
283
12
284
12
    default:
285
10
      return TargetInfo::getOpenCLTypeAddrSpace(TK);
286
40
    }
287
40
  }
288
289
119
  LangAS getOpenCLBuiltinAddressSpace(unsigned AS) const override {
290
119
    switch (AS) {
291
46
    case 0:
292
46
      return LangAS::opencl_generic;
293
0
    case 1:
294
0
      return LangAS::opencl_global;
295
58
    case 3:
296
58
      return LangAS::opencl_local;
297
12
    case 4:
298
12
      return LangAS::opencl_constant;
299
0
    case 5:
300
0
      return LangAS::opencl_private;
301
3
    default:
302
3
      return getLangASFromTargetAS(AS);
303
119
    }
304
119
  }
305
306
6
  LangAS getCUDABuiltinAddressSpace(unsigned AS) const override {
307
6
    return LangAS::Default;
308
6
  }
309
310
46
  llvm::Optional<LangAS> getConstantAddressSpace() const override {
311
46
    return getLangASFromTargetAS(Constant);
312
46
  }
313
314
  /// \returns Target specific vtbl ptr address space.
315
0
  unsigned getVtblPtrAddressSpace() const override {
316
0
    return static_cast<unsigned>(Constant);
317
0
  }
318
319
  /// \returns If a target requires an address within a target specific address
320
  /// space \p AddressSpace to be converted in order to be used, then return the
321
  /// corresponding target specific DWARF address space.
322
  ///
323
  /// \returns Otherwise return None and no conversion will be emitted in the
324
  /// DWARF.
325
  Optional<unsigned>
326
203
  getDWARFAddressSpace(unsigned AddressSpace) const override {
327
203
    const unsigned DWARF_Private = 1;
328
203
    const unsigned DWARF_Local = 2;
329
203
    if (AddressSpace == Private) {
330
78
      return DWARF_Private;
331
125
    } else if (AddressSpace == Local) {
332
26
      return DWARF_Local;
333
99
    } else {
334
99
      return None;
335
99
    }
336
203
  }
337
338
0
  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
339
0
    switch (CC) {
340
0
    default:
341
0
      return CCCR_Warning;
342
0
    case CC_C:
343
0
    case CC_OpenCLKernel:
344
0
      return CCCR_OK;
345
0
    }
346
0
  }
347
348
  // In amdgcn target the null pointer in global, constant, and generic
349
  // address space has value 0 but in private and local address space has
350
  // value ~0.
351
2.53k
  uint64_t getNullPointerValue(LangAS AS) const override {
352
2.53k
    return AS == LangAS::opencl_local ? 
~0356
:
02.18k
;
353
2.53k
  }
354
355
  void setAuxTarget(const TargetInfo *Aux) override;
356
};
357
358
} // namespace targets
359
} // namespace clang
360
361
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H