1ff0cc061SDimitry Andric //===-- TargetParser - Parser for target features ---------------*- C++ -*-===//
2ff0cc061SDimitry Andric //
3ff0cc061SDimitry Andric //                     The LLVM Compiler Infrastructure
4ff0cc061SDimitry Andric //
5ff0cc061SDimitry Andric // This file is distributed under the University of Illinois Open Source
6ff0cc061SDimitry Andric // License. See LICENSE.TXT for details.
7ff0cc061SDimitry Andric //
8ff0cc061SDimitry Andric //===----------------------------------------------------------------------===//
9ff0cc061SDimitry Andric //
10ff0cc061SDimitry Andric // This file implements a target parser to recognise hardware features such as
11ff0cc061SDimitry Andric // FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
12ff0cc061SDimitry Andric //
13ff0cc061SDimitry Andric //===----------------------------------------------------------------------===//
14ff0cc061SDimitry Andric 
15ff0cc061SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h"
16ff0cc061SDimitry Andric #include "llvm/Support/TargetParser.h"
17*b5893f02SDimitry Andric #include "llvm/ADT/ArrayRef.h"
18ff0cc061SDimitry Andric #include "llvm/ADT/StringSwitch.h"
197d523365SDimitry Andric #include "llvm/ADT/Twine.h"
20ff0cc061SDimitry Andric 
21ff0cc061SDimitry Andric using namespace llvm;
22*b5893f02SDimitry Andric using namespace AMDGPU;
23ff0cc061SDimitry Andric 
24ff0cc061SDimitry Andric namespace {
25ff0cc061SDimitry Andric 
26*b5893f02SDimitry Andric struct GPUInfo {
27*b5893f02SDimitry Andric   StringLiteral Name;
28*b5893f02SDimitry Andric   StringLiteral CanonicalName;
29*b5893f02SDimitry Andric   AMDGPU::GPUKind Kind;
30*b5893f02SDimitry Andric   unsigned Features;
31ff0cc061SDimitry Andric };
3297bc6c73SDimitry Andric 
33*b5893f02SDimitry Andric constexpr GPUInfo R600GPUs[26] = {
34*b5893f02SDimitry Andric   // Name       Canonical    Kind        Features
35*b5893f02SDimitry Andric   //            Name
36*b5893f02SDimitry Andric   {{"r600"},    {"r600"},    GK_R600,    FEATURE_NONE },
37*b5893f02SDimitry Andric   {{"rv630"},   {"r600"},    GK_R600,    FEATURE_NONE },
38*b5893f02SDimitry Andric   {{"rv635"},   {"r600"},    GK_R600,    FEATURE_NONE },
39*b5893f02SDimitry Andric   {{"r630"},    {"r630"},    GK_R630,    FEATURE_NONE },
40*b5893f02SDimitry Andric   {{"rs780"},   {"rs880"},   GK_RS880,   FEATURE_NONE },
41*b5893f02SDimitry Andric   {{"rs880"},   {"rs880"},   GK_RS880,   FEATURE_NONE },
42*b5893f02SDimitry Andric   {{"rv610"},   {"rs880"},   GK_RS880,   FEATURE_NONE },
43*b5893f02SDimitry Andric   {{"rv620"},   {"rs880"},   GK_RS880,   FEATURE_NONE },
44*b5893f02SDimitry Andric   {{"rv670"},   {"rv670"},   GK_RV670,   FEATURE_NONE },
45*b5893f02SDimitry Andric   {{"rv710"},   {"rv710"},   GK_RV710,   FEATURE_NONE },
46*b5893f02SDimitry Andric   {{"rv730"},   {"rv730"},   GK_RV730,   FEATURE_NONE },
47*b5893f02SDimitry Andric   {{"rv740"},   {"rv770"},   GK_RV770,   FEATURE_NONE },
48*b5893f02SDimitry Andric   {{"rv770"},   {"rv770"},   GK_RV770,   FEATURE_NONE },
49*b5893f02SDimitry Andric   {{"cedar"},   {"cedar"},   GK_CEDAR,   FEATURE_NONE },
50*b5893f02SDimitry Andric   {{"palm"},    {"cedar"},   GK_CEDAR,   FEATURE_NONE },
51*b5893f02SDimitry Andric   {{"cypress"}, {"cypress"}, GK_CYPRESS, FEATURE_FMA  },
52*b5893f02SDimitry Andric   {{"hemlock"}, {"cypress"}, GK_CYPRESS, FEATURE_FMA  },
53*b5893f02SDimitry Andric   {{"juniper"}, {"juniper"}, GK_JUNIPER, FEATURE_NONE },
54*b5893f02SDimitry Andric   {{"redwood"}, {"redwood"}, GK_REDWOOD, FEATURE_NONE },
55*b5893f02SDimitry Andric   {{"sumo"},    {"sumo"},    GK_SUMO,    FEATURE_NONE },
56*b5893f02SDimitry Andric   {{"sumo2"},   {"sumo"},    GK_SUMO,    FEATURE_NONE },
57*b5893f02SDimitry Andric   {{"barts"},   {"barts"},   GK_BARTS,   FEATURE_NONE },
58*b5893f02SDimitry Andric   {{"caicos"},  {"caicos"},  GK_CAICOS,  FEATURE_NONE },
59*b5893f02SDimitry Andric   {{"aruba"},   {"cayman"},  GK_CAYMAN,  FEATURE_FMA  },
60*b5893f02SDimitry Andric   {{"cayman"},  {"cayman"},  GK_CAYMAN,  FEATURE_FMA  },
61*b5893f02SDimitry Andric   {{"turks"},   {"turks"},   GK_TURKS,   FEATURE_NONE }
62d88c1a5aSDimitry Andric };
63d88c1a5aSDimitry Andric 
64*b5893f02SDimitry Andric // This table should be sorted by the value of GPUKind
65*b5893f02SDimitry Andric // Don't bother listing the implicitly true features
66*b5893f02SDimitry Andric constexpr GPUInfo AMDGCNGPUs[33] = {
67*b5893f02SDimitry Andric   // Name         Canonical    Kind        Features
68*b5893f02SDimitry Andric   //              Name
69*b5893f02SDimitry Andric   {{"gfx600"},    {"gfx600"},  GK_GFX600,  FEATURE_FAST_FMA_F32},
70*b5893f02SDimitry Andric   {{"tahiti"},    {"gfx600"},  GK_GFX600,  FEATURE_FAST_FMA_F32},
71*b5893f02SDimitry Andric   {{"gfx601"},    {"gfx601"},  GK_GFX601,  FEATURE_NONE},
72*b5893f02SDimitry Andric   {{"hainan"},    {"gfx601"},  GK_GFX601,  FEATURE_NONE},
73*b5893f02SDimitry Andric   {{"oland"},     {"gfx601"},  GK_GFX601,  FEATURE_NONE},
74*b5893f02SDimitry Andric   {{"pitcairn"},  {"gfx601"},  GK_GFX601,  FEATURE_NONE},
75*b5893f02SDimitry Andric   {{"verde"},     {"gfx601"},  GK_GFX601,  FEATURE_NONE},
76*b5893f02SDimitry Andric   {{"gfx700"},    {"gfx700"},  GK_GFX700,  FEATURE_NONE},
77*b5893f02SDimitry Andric   {{"kaveri"},    {"gfx700"},  GK_GFX700,  FEATURE_NONE},
78*b5893f02SDimitry Andric   {{"gfx701"},    {"gfx701"},  GK_GFX701,  FEATURE_FAST_FMA_F32},
79*b5893f02SDimitry Andric   {{"hawaii"},    {"gfx701"},  GK_GFX701,  FEATURE_FAST_FMA_F32},
80*b5893f02SDimitry Andric   {{"gfx702"},    {"gfx702"},  GK_GFX702,  FEATURE_FAST_FMA_F32},
81*b5893f02SDimitry Andric   {{"gfx703"},    {"gfx703"},  GK_GFX703,  FEATURE_NONE},
82*b5893f02SDimitry Andric   {{"kabini"},    {"gfx703"},  GK_GFX703,  FEATURE_NONE},
83*b5893f02SDimitry Andric   {{"mullins"},   {"gfx703"},  GK_GFX703,  FEATURE_NONE},
84*b5893f02SDimitry Andric   {{"gfx704"},    {"gfx704"},  GK_GFX704,  FEATURE_NONE},
85*b5893f02SDimitry Andric   {{"bonaire"},   {"gfx704"},  GK_GFX704,  FEATURE_NONE},
86*b5893f02SDimitry Andric   {{"gfx801"},    {"gfx801"},  GK_GFX801,  FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
87*b5893f02SDimitry Andric   {{"carrizo"},   {"gfx801"},  GK_GFX801,  FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
88*b5893f02SDimitry Andric   {{"gfx802"},    {"gfx802"},  GK_GFX802,  FEATURE_FAST_DENORMAL_F32},
89*b5893f02SDimitry Andric   {{"iceland"},   {"gfx802"},  GK_GFX802,  FEATURE_FAST_DENORMAL_F32},
90*b5893f02SDimitry Andric   {{"tonga"},     {"gfx802"},  GK_GFX802,  FEATURE_FAST_DENORMAL_F32},
91*b5893f02SDimitry Andric   {{"gfx803"},    {"gfx803"},  GK_GFX803,  FEATURE_FAST_DENORMAL_F32},
92*b5893f02SDimitry Andric   {{"fiji"},      {"gfx803"},  GK_GFX803,  FEATURE_FAST_DENORMAL_F32},
93*b5893f02SDimitry Andric   {{"polaris10"}, {"gfx803"},  GK_GFX803,  FEATURE_FAST_DENORMAL_F32},
94*b5893f02SDimitry Andric   {{"polaris11"}, {"gfx803"},  GK_GFX803,  FEATURE_FAST_DENORMAL_F32},
95*b5893f02SDimitry Andric   {{"gfx810"},    {"gfx810"},  GK_GFX810,  FEATURE_FAST_DENORMAL_F32},
96*b5893f02SDimitry Andric   {{"stoney"},    {"gfx810"},  GK_GFX810,  FEATURE_FAST_DENORMAL_F32},
97*b5893f02SDimitry Andric   {{"gfx900"},    {"gfx900"},  GK_GFX900,  FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
98*b5893f02SDimitry Andric   {{"gfx902"},    {"gfx902"},  GK_GFX902,  FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
99*b5893f02SDimitry Andric   {{"gfx904"},    {"gfx904"},  GK_GFX904,  FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
100*b5893f02SDimitry Andric   {{"gfx906"},    {"gfx906"},  GK_GFX906,  FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
101*b5893f02SDimitry Andric   {{"gfx909"},    {"gfx909"},  GK_GFX909,  FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32},
102ff0cc061SDimitry Andric };
1037d523365SDimitry Andric 
getArchEntry(AMDGPU::GPUKind AK,ArrayRef<GPUInfo> Table)104*b5893f02SDimitry Andric const GPUInfo *getArchEntry(AMDGPU::GPUKind AK, ArrayRef<GPUInfo> Table) {
105*b5893f02SDimitry Andric   GPUInfo Search = { {""}, {""}, AK, AMDGPU::FEATURE_NONE };
106d88c1a5aSDimitry Andric 
107*b5893f02SDimitry Andric   auto I = std::lower_bound(Table.begin(), Table.end(), Search,
108*b5893f02SDimitry Andric     [](const GPUInfo &A, const GPUInfo &B) {
109*b5893f02SDimitry Andric       return A.Kind < B.Kind;
110*b5893f02SDimitry Andric     });
1117d523365SDimitry Andric 
112*b5893f02SDimitry Andric   if (I == Table.end())
113*b5893f02SDimitry Andric     return nullptr;
114*b5893f02SDimitry Andric   return I;
115*b5893f02SDimitry Andric }
116ff0cc061SDimitry Andric 
117ff0cc061SDimitry Andric } // namespace
118ff0cc061SDimitry Andric 
getArchNameAMDGCN(GPUKind AK)119*b5893f02SDimitry Andric StringRef llvm::AMDGPU::getArchNameAMDGCN(GPUKind AK) {
120*b5893f02SDimitry Andric   if (const auto *Entry = getArchEntry(AK, AMDGCNGPUs))
121*b5893f02SDimitry Andric     return Entry->CanonicalName;
122*b5893f02SDimitry Andric   return "";
123ff0cc061SDimitry Andric }
124ff0cc061SDimitry Andric 
getArchNameR600(GPUKind AK)125*b5893f02SDimitry Andric StringRef llvm::AMDGPU::getArchNameR600(GPUKind AK) {
126*b5893f02SDimitry Andric   if (const auto *Entry = getArchEntry(AK, R600GPUs))
127*b5893f02SDimitry Andric     return Entry->CanonicalName;
128*b5893f02SDimitry Andric   return "";
12997bc6c73SDimitry Andric }
13097bc6c73SDimitry Andric 
parseArchAMDGCN(StringRef CPU)131*b5893f02SDimitry Andric AMDGPU::GPUKind llvm::AMDGPU::parseArchAMDGCN(StringRef CPU) {
132*b5893f02SDimitry Andric   for (const auto C : AMDGCNGPUs) {
133*b5893f02SDimitry Andric     if (CPU == C.Name)
134*b5893f02SDimitry Andric       return C.Kind;
13597bc6c73SDimitry Andric   }
13697bc6c73SDimitry Andric 
137*b5893f02SDimitry Andric   return AMDGPU::GPUKind::GK_NONE;
13897bc6c73SDimitry Andric }
13997bc6c73SDimitry Andric 
parseArchR600(StringRef CPU)140*b5893f02SDimitry Andric AMDGPU::GPUKind llvm::AMDGPU::parseArchR600(StringRef CPU) {
141*b5893f02SDimitry Andric   for (const auto C : R600GPUs) {
142*b5893f02SDimitry Andric     if (CPU == C.Name)
143*b5893f02SDimitry Andric       return C.Kind;
1447d523365SDimitry Andric   }
1457d523365SDimitry Andric 
146*b5893f02SDimitry Andric   return AMDGPU::GPUKind::GK_NONE;
1477d523365SDimitry Andric }
1487d523365SDimitry Andric 
getArchAttrAMDGCN(GPUKind AK)149*b5893f02SDimitry Andric unsigned AMDGPU::getArchAttrAMDGCN(GPUKind AK) {
150*b5893f02SDimitry Andric   if (const auto *Entry = getArchEntry(AK, AMDGCNGPUs))
151*b5893f02SDimitry Andric     return Entry->Features;
152*b5893f02SDimitry Andric   return FEATURE_NONE;
1537d523365SDimitry Andric }
1547d523365SDimitry Andric 
getArchAttrR600(GPUKind AK)155*b5893f02SDimitry Andric unsigned AMDGPU::getArchAttrR600(GPUKind AK) {
156*b5893f02SDimitry Andric   if (const auto *Entry = getArchEntry(AK, R600GPUs))
157*b5893f02SDimitry Andric     return Entry->Features;
158*b5893f02SDimitry Andric   return FEATURE_NONE;
1597d523365SDimitry Andric }
1607d523365SDimitry Andric 
fillValidArchListAMDGCN(SmallVectorImpl<StringRef> & Values)161*b5893f02SDimitry Andric void AMDGPU::fillValidArchListAMDGCN(SmallVectorImpl<StringRef> &Values) {
162*b5893f02SDimitry Andric   // XXX: Should this only report unique canonical names?
163*b5893f02SDimitry Andric   for (const auto C : AMDGCNGPUs)
164*b5893f02SDimitry Andric     Values.push_back(C.Name);
16597bc6c73SDimitry Andric }
16697bc6c73SDimitry Andric 
fillValidArchListR600(SmallVectorImpl<StringRef> & Values)167*b5893f02SDimitry Andric void AMDGPU::fillValidArchListR600(SmallVectorImpl<StringRef> &Values) {
168*b5893f02SDimitry Andric   for (const auto C : R600GPUs)
169*b5893f02SDimitry Andric     Values.push_back(C.Name);
17097bc6c73SDimitry Andric }
17197bc6c73SDimitry Andric 
getIsaVersion(StringRef GPU)172*b5893f02SDimitry Andric AMDGPU::IsaVersion AMDGPU::getIsaVersion(StringRef GPU) {
173*b5893f02SDimitry Andric   if (GPU == "generic")
174*b5893f02SDimitry Andric     return {7, 0, 0};
17597bc6c73SDimitry Andric 
176*b5893f02SDimitry Andric   AMDGPU::GPUKind AK = parseArchAMDGCN(GPU);
177*b5893f02SDimitry Andric   if (AK == AMDGPU::GPUKind::GK_NONE)
178*b5893f02SDimitry Andric     return {0, 0, 0};
17997bc6c73SDimitry Andric 
180*b5893f02SDimitry Andric   switch (AK) {
181*b5893f02SDimitry Andric   case GK_GFX600: return {6, 0, 0};
182*b5893f02SDimitry Andric   case GK_GFX601: return {6, 0, 1};
183*b5893f02SDimitry Andric   case GK_GFX700: return {7, 0, 0};
184*b5893f02SDimitry Andric   case GK_GFX701: return {7, 0, 1};
185*b5893f02SDimitry Andric   case GK_GFX702: return {7, 0, 2};
186*b5893f02SDimitry Andric   case GK_GFX703: return {7, 0, 3};
187*b5893f02SDimitry Andric   case GK_GFX704: return {7, 0, 4};
188*b5893f02SDimitry Andric   case GK_GFX801: return {8, 0, 1};
189*b5893f02SDimitry Andric   case GK_GFX802: return {8, 0, 2};
190*b5893f02SDimitry Andric   case GK_GFX803: return {8, 0, 3};
191*b5893f02SDimitry Andric   case GK_GFX810: return {8, 1, 0};
192*b5893f02SDimitry Andric   case GK_GFX900: return {9, 0, 0};
193*b5893f02SDimitry Andric   case GK_GFX902: return {9, 0, 2};
194*b5893f02SDimitry Andric   case GK_GFX904: return {9, 0, 4};
195*b5893f02SDimitry Andric   case GK_GFX906: return {9, 0, 6};
196*b5893f02SDimitry Andric   case GK_GFX909: return {9, 0, 9};
197*b5893f02SDimitry Andric   default:        return {0, 0, 0};
1983ca95b02SDimitry Andric   }
1994ba319b5SDimitry Andric }
200