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