LLVM 24.0.0git
IntelGPUTargetParser.cpp
Go to the documentation of this file.
1//===-- IntelGPUTargetParser - Parser for Intel GPU targets ---------------===//
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 implements a target parser for the Intel GPU list.
10//
11//===----------------------------------------------------------------------===//
12
14#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/Twine.h"
19#include <cassert>
20
21using namespace llvm;
22using namespace IntelGPU;
23
24// A GPU IP version packs four fields, from the most significant bit down:
25//
26// 31 22 21 14 13 6 5 0
27// +---------------+----------+----------+----------+
28// | major | minor | reserved | revision |
29// +---------------+----------+----------+----------+
30// 10 bits 8 bits 8 bits 6 bits
31//
32// The reserved bits carry no information.
33static constexpr uint32_t GPUIPMajorShift = 22;
34static constexpr uint32_t GPUIPMinorShift = 14;
35[[maybe_unused]] static constexpr uint32_t GPUIPMajorMask = 0x3ff;
36static constexpr uint32_t GPUIPMinorMask = 0xff;
37static constexpr uint32_t GPUIPRevisionMask = 0x3f;
38
39// The bits that identify a device: the major and the minor version. Neither the
40// revision nor the reserved bits take part in the lookup, because every
41// revision of a device is one device as far as the compiler is concerned.
42static constexpr uint32_t GPUIPDeviceMask = ~0u << GPUIPMinorShift;
43
44// Pack a major and a minor version the way a GPU IP version does, so that a
45// row of the table can be compared against a reported version as it is. A value
46// too wide for its field would silently corrupt the fields above it, which
47// would mean a typo in IntelGPUTargetParser.def going unnoticed.
48static constexpr uint32_t packDevice(uint32_t Major, uint32_t Minor) {
49 assert((Major & ~GPUIPMajorMask) == 0 && "major version too wide");
50 assert((Minor & ~GPUIPMinorMask) == 0 && "minor version too wide");
51 return (Major << GPUIPMajorShift) | (Minor << GPUIPMinorShift);
52}
53
55 const uint32_t Device = GPUIPVersion & GPUIPDeviceMask;
56#define INTEL_GPU(NAME, KIND, MAJOR, MINOR, IGCA_TARGET, IGCA_FEATURE_SETS) \
57 if (Device == packDevice(MAJOR, MINOR)) \
58 return NAME;
59#include "llvm/TargetParser/IntelGPUTargetParser.def"
60 return "";
61}
62
64 const uint32_t Major = GPUIPVersion >> GPUIPMajorShift;
65 const uint32_t Minor = (GPUIPVersion >> GPUIPMinorShift) & GPUIPMinorMask;
66 const uint32_t Revision = GPUIPVersion & GPUIPRevisionMask;
67 return ("xe_" + Twine(Major) + "." + Twine(Minor) + "." + Twine(Revision))
68 .str();
69}
70
72 switch (Kind) {
73 case GK_NONE:
74 return "";
75#define INTEL_GPU(NAME, KIND, MAJOR, MINOR, IGCA_TARGET, IGCA_FEATURE_SETS) \
76 case GK_##KIND: \
77 return NAME;
78#define INTEL_GPU_COMPAT(NAME, KIND, IGCA_TARGET, IGCA_FEATURE_SETS) \
79 case GK_##KIND: \
80 return NAME;
81#include "llvm/TargetParser/IntelGPUTargetParser.def"
82 }
83 llvm_unreachable("invalid Intel GPU kind");
84}
85
87 // A numeric name ends in a revision, e.g. "xe_12.60.7". Only the major and
88 // minor versions name a device, so the revision may be any number and is not
89 // looked up.
90 if (Name.starts_with("xe_")) {
91 auto [Device, Revision] = Name.rsplit('.');
92 if (Device.count('.') != 1 || Revision.empty() ||
93 !all_of(Revision, isDigit))
94 return GK_NONE;
95 Name = Device;
96 }
97
98 return StringSwitch<GPUKind>(Name)
99#define INTEL_GPU(NAME, KIND, MAJOR, MINOR, IGCA_TARGET, IGCA_FEATURE_SETS) \
100 .Case(NAME, GK_##KIND).Case("xe_" #MAJOR "." #MINOR, GK_##KIND)
101#define INTEL_GPU_COMPAT(NAME, KIND, IGCA_TARGET, IGCA_FEATURE_SETS) \
102 .Case(NAME, GK_##KIND)
103#define INTEL_GPU_ALIAS(NAME, KIND) .Case(NAME, GK_##KIND)
104#include "llvm/TargetParser/IntelGPUTargetParser.def"
106}
107
108namespace {
109// The IGCA target of each row in IntelGPUTargetParser.def, e.g. {20,
110// ComputeExact} for xe-pvc. Several rows can have the same IGCA target, e.g.
111// the nine igca_10r devices, so entries repeat.
112struct DeviceIGCATarget {
113 uint16_t Target;
114 IGCAFeatureSet FeatureSet;
115};
116constexpr DeviceIGCATarget DeviceIGCATargets[] = {
117#define INTEL_GPU(NAME, KIND, MAJOR, MINOR, IGCA_TARGET, IGCA_FEATURE_SETS) \
118 {IGCA_TARGET, IGCAFeatureSet::IGCA_FEATURE_SETS},
119#define INTEL_GPU_COMPAT(NAME, KIND, IGCA_TARGET, IGCA_FEATURE_SETS) \
120 {IGCA_TARGET, IGCAFeatureSet::IGCA_FEATURE_SETS},
121#include "llvm/TargetParser/IntelGPUTargetParser.def"
122};
123
124// All five possible names for each device's numeric IGCA target, e.g. igca_20,
125// igca_20c, igca_20ca, igca_20r and igca_20ra for xe-pvc. Which of them are
126// valid is decided by the IGCATarget constructor, so the rule is in one place.
127// The names are string literals, so getIGCATargetName() can return them.
128struct IGCATargetNameEntry {
129 const char *Name;
130 uint16_t Target;
131 IGCAFeatureSet FeatureSet;
132};
133#define IGCA_TARGET_NAMES(TARGET) \
134 {"igca_" #TARGET, TARGET, IGCAFeatureSet::Core}, \
135 {"igca_" #TARGET "c", TARGET, IGCAFeatureSet::Compute}, \
136 {"igca_" #TARGET "ca", TARGET, IGCAFeatureSet::ComputeExact}, \
137 {"igca_" #TARGET "r", TARGET, IGCAFeatureSet::Render}, \
138 {"igca_" #TARGET "ra", TARGET, IGCAFeatureSet::RenderExact},
139constexpr IGCATargetNameEntry IGCATargetNames[] = {
140#define INTEL_GPU(NAME, KIND, MAJOR, MINOR, IGCA_TARGET, IGCA_FEATURE_SETS) \
141 IGCA_TARGET_NAMES(IGCA_TARGET)
142#define INTEL_GPU_COMPAT(NAME, KIND, IGCA_TARGET, IGCA_FEATURE_SETS) \
143 IGCA_TARGET_NAMES(IGCA_TARGET)
144#include "llvm/TargetParser/IntelGPUTargetParser.def"
145};
146#undef IGCA_TARGET_NAMES
147} // namespace
148
149/// \return true if a device with the IGCA feature set \p DeviceFeatureSet can
150/// run code built for the IGCA feature set \p RequestedFeatureSet at the
151/// device's own numeric IGCA target. For example, xe-pvc (igca_20ca,
152/// ComputeExact) can run code built for igca_20ca, igca_20c and igca_20, but
153/// not igca_20r.
154static bool deviceCanRunIGCAFeatureSet(IGCAFeatureSet DeviceFeatureSet,
155 IGCAFeatureSet RequestedFeatureSet) {
156 // Every device runs code built for the Core IGCA feature set, e.g. igca_20.
157 if (RequestedFeatureSet == IGCAFeatureSet::Core)
158 return true;
159 // A device runs code built for its own IGCA feature set, e.g. igca_20ca.
160 if (RequestedFeatureSet == DeviceFeatureSet)
161 return true;
162 // An exact IGCA feature set also runs code built for its non-exact form,
163 // e.g. igca_20c.
164 if (DeviceFeatureSet == IGCAFeatureSet::ComputeExact)
165 return RequestedFeatureSet == IGCAFeatureSet::Compute;
166 if (DeviceFeatureSet == IGCAFeatureSet::RenderExact)
167 return RequestedFeatureSet == IGCAFeatureSet::Render;
168 return false;
169}
170
171bool llvm::IntelGPU::IGCATarget::isKnownIGCATarget(uint32_t Packed) {
172 // A value with any of bits 3-15 set is not an IGCA target, e.g. igca_20c
173 // (0x00140002) with bit 3 set.
174 if (Packed & ReservedMask)
175 return false;
176 // Split the value into its numeric IGCA target and feature set, e.g. 20 and
177 // Compute for igca_20c.
178 uint16_t RequestedTarget = uint16_t(Packed >> TargetShift);
179 auto RequestedFeatureSet = IGCAFeatureSet(Packed & FeatureSetMask);
180 for (const DeviceIGCATarget &D : DeviceIGCATargets)
181 if (D.Target == RequestedTarget &&
182 deviceCanRunIGCAFeatureSet(D.FeatureSet, RequestedFeatureSet))
183 return true;
184 return false;
185}
186
188 for (const IGCATargetNameEntry &E : IGCATargetNames)
189 if (MaybeTarget == E.Name)
190 return IGCATarget(E.Target, E.FeatureSet);
191 return IGCATarget::invalid();
192}
193
195 for (const IGCATargetNameEntry &E : IGCATargetNames)
196 if (E.Target == T.getTarget() && E.FeatureSet == T.getFeatureSet())
197 return E.Name;
198 return "";
199}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static constexpr uint32_t GPUIPMajorMask
static constexpr uint32_t GPUIPMajorShift
static constexpr uint32_t GPUIPRevisionMask
static constexpr uint32_t GPUIPMinorMask
static constexpr uint32_t packDevice(uint32_t Major, uint32_t Minor)
static constexpr uint32_t GPUIPMinorShift
static bool deviceCanRunIGCAFeatureSet(IGCAFeatureSet DeviceFeatureSet, IGCAFeatureSet RequestedFeatureSet)
static constexpr uint32_t GPUIPDeviceMask
#define T
This file contains some templates that are useful if you are working with the STL at all.
This file contains some functions that are useful when dealing with strings.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
Wrapper around an IGCA target's uint32_t representation, packed using the following format:
static constexpr IGCATarget invalid()
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
A switch()-like statement whose cases are string literals.
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI GPUKind parseArch(StringRef Name)
LLVM_ABI std::string getNumericArchName(uint32_t GPUIPVersion)
IGCAFeatureSet
Represents an IGCA feature set, including whether or not it is exact.
LLVM_ABI IGCATarget parseIGCATarget(StringRef MaybeTarget)
Parse an IGCA target string such as "igca_20ca".
LLVM_ABI StringRef getIGCATargetName(IGCATarget Target)
LLVM_ABI StringRef getArchName(uint32_t GPUIPVersion)
GPUKind
Intel GPU architecture names, covering both physical devices and the compatibility names that stand f...
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.