1 //===--- AMDGPU.h - Declare AMDGPU target feature support -------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file declares AMDGPU TargetInfo objects.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
15 #define LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
16 
17 #include "clang/AST/Type.h"
18 #include "clang/Basic/TargetInfo.h"
19 #include "clang/Basic/TargetOptions.h"
20 #include "llvm/ADT/Triple.h"
21 #include "llvm/Support/Compiler.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   struct LLVM_LIBRARY_VISIBILITY AddrSpace {
32     unsigned Generic, Global, Local, Constant, Private;
33     AddrSpace(bool IsGenericZero_ = false) {
34       if (IsGenericZero_) {
35         Generic = 0;
36         Global = 1;
37         Local = 3;
38         Constant = 2;
39         Private = 5;
40       } else {
41         Generic = 4;
42         Global = 1;
43         Local = 3;
44         Constant = 2;
45         Private = 0;
46       }
47     }
48   };
49 
50   /// \brief The GPU profiles supported by the AMDGPU target.
51   enum GPUKind {
52     GK_NONE,
53     GK_R600,
54     GK_R600_DOUBLE_OPS,
55     GK_R700,
56     GK_R700_DOUBLE_OPS,
57     GK_EVERGREEN,
58     GK_EVERGREEN_DOUBLE_OPS,
59     GK_NORTHERN_ISLANDS,
60     GK_CAYMAN,
61     GK_GFX6,
62     GK_GFX7,
63     GK_GFX8,
64     GK_GFX9
65   } GPU;
66 
67   bool hasFP64 : 1;
68   bool hasFMAF : 1;
69   bool hasLDEXPF : 1;
70   const AddrSpace AS;
71 
72   static bool hasFullSpeedFMAF32(StringRef GPUName) {
73     return parseAMDGCNName(GPUName) >= GK_GFX9;
74   }
75 
76   static bool isAMDGCN(const llvm::Triple &TT) {
77     return TT.getArch() == llvm::Triple::amdgcn;
78   }
79 
80   static bool isGenericZero(const llvm::Triple &TT) {
81     return TT.getEnvironmentName() == "amdgiz" ||
82            TT.getEnvironmentName() == "amdgizcl";
83   }
84 
85 public:
86   AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
87 
88   void setAddressSpaceMap(bool DefaultIsPrivate);
89 
90   void adjust(LangOptions &Opts) override;
91 
92   uint64_t getPointerWidthV(unsigned AddrSpace) const override {
93     if (GPU <= GK_CAYMAN)
94       return 32;
95 
96     if (AddrSpace == AS.Private || AddrSpace == AS.Local) {
97       return 32;
98     }
99     return 64;
100   }
101 
102   uint64_t getPointerAlignV(unsigned AddrSpace) const override {
103     return getPointerWidthV(AddrSpace);
104   }
105 
106   uint64_t getMaxPointerWidth() const override {
107     return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
108   }
109 
110   const char *getClobbers() const override { return ""; }
111 
112   ArrayRef<const char *> getGCCRegNames() const override;
113 
114   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
115     return None;
116   }
117 
118   bool validateAsmConstraint(const char *&Name,
119                              TargetInfo::ConstraintInfo &Info) const override {
120     switch (*Name) {
121     default:
122       break;
123     case 'v': // vgpr
124     case 's': // sgpr
125       Info.setAllowsRegister();
126       return true;
127     }
128     return false;
129   }
130 
131   bool
132   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
133                  StringRef CPU,
134                  const std::vector<std::string> &FeatureVec) const override;
135 
136   void adjustTargetOptions(const CodeGenOptions &CGOpts,
137                            TargetOptions &TargetOpts) const override;
138 
139   ArrayRef<Builtin::Info> getTargetBuiltins() const override;
140 
141   void getTargetDefines(const LangOptions &Opts,
142                         MacroBuilder &Builder) const override;
143 
144   BuiltinVaListKind getBuiltinVaListKind() const override {
145     return TargetInfo::CharPtrBuiltinVaList;
146   }
147 
148   static GPUKind parseR600Name(StringRef Name);
149 
150   static GPUKind parseAMDGCNName(StringRef Name);
151 
152   bool isValidCPUName(StringRef Name) const override {
153     if (getTriple().getArch() == llvm::Triple::amdgcn)
154       return GK_NONE != parseAMDGCNName(Name);
155     else
156       return GK_NONE != parseR600Name(Name);
157   }
158 
159   bool setCPU(const std::string &Name) override {
160     if (getTriple().getArch() == llvm::Triple::amdgcn)
161       GPU = parseAMDGCNName(Name);
162     else
163       GPU = parseR600Name(Name);
164 
165     return GPU != GK_NONE;
166   }
167 
168   void setSupportedOpenCLOpts() override {
169     auto &Opts = getSupportedOpenCLOpts();
170     Opts.support("cl_clang_storage_class_specifiers");
171     Opts.support("cl_khr_icd");
172 
173     if (hasFP64)
174       Opts.support("cl_khr_fp64");
175     if (GPU >= GK_EVERGREEN) {
176       Opts.support("cl_khr_byte_addressable_store");
177       Opts.support("cl_khr_global_int32_base_atomics");
178       Opts.support("cl_khr_global_int32_extended_atomics");
179       Opts.support("cl_khr_local_int32_base_atomics");
180       Opts.support("cl_khr_local_int32_extended_atomics");
181     }
182     if (GPU >= GK_GFX6) {
183       Opts.support("cl_khr_fp16");
184       Opts.support("cl_khr_int64_base_atomics");
185       Opts.support("cl_khr_int64_extended_atomics");
186       Opts.support("cl_khr_mipmap_image");
187       Opts.support("cl_khr_subgroups");
188       Opts.support("cl_khr_3d_image_writes");
189       Opts.support("cl_amd_media_ops");
190       Opts.support("cl_amd_media_ops2");
191     }
192   }
193 
194   LangAS::ID getOpenCLTypeAddrSpace(const Type *T) const override {
195     auto BT = dyn_cast<BuiltinType>(T);
196 
197     if (!BT)
198       return TargetInfo::getOpenCLTypeAddrSpace(T);
199 
200     switch (BT->getKind()) {
201 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix)                   \
202   case BuiltinType::Id:                                                        \
203     return LangAS::opencl_constant;
204 #include "clang/Basic/OpenCLImageTypes.def"
205 
206     default:
207       return TargetInfo::getOpenCLTypeAddrSpace(T);
208     }
209   }
210 
211   llvm::Optional<unsigned> getConstantAddressSpace() const override {
212     return LangAS::FirstTargetAddressSpace + AS.Constant;
213   }
214 
215   /// \returns Target specific vtbl ptr address space.
216   unsigned getVtblPtrAddressSpace() const override { return AS.Constant; }
217 
218   /// \returns If a target requires an address within a target specific address
219   /// space \p AddressSpace to be converted in order to be used, then return the
220   /// corresponding target specific DWARF address space.
221   ///
222   /// \returns Otherwise return None and no conversion will be emitted in the
223   /// DWARF.
224   Optional<unsigned>
225   getDWARFAddressSpace(unsigned AddressSpace) const override {
226     const unsigned DWARF_Private = 1;
227     const unsigned DWARF_Local = 2;
228     if (AddressSpace == AS.Private) {
229       return DWARF_Private;
230     } else if (AddressSpace == AS.Local) {
231       return DWARF_Local;
232     } else {
233       return None;
234     }
235   }
236 
237   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
238     switch (CC) {
239     default:
240       return CCCR_Warning;
241     case CC_C:
242     case CC_OpenCLKernel:
243       return CCCR_OK;
244     }
245   }
246 
247   // In amdgcn target the null pointer in global, constant, and generic
248   // address space has value 0 but in private and local address space has
249   // value ~0.
250   uint64_t getNullPointerValue(unsigned AS) const override {
251     return AS == LangAS::opencl_local ? ~0 : 0;
252   }
253 };
254 
255 } // namespace targets
256 } // namespace clang
257 
258 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H
259