https://github.com/ianayl updated https://github.com/llvm/llvm-project/pull/227468
>From 0fbf5c511392b91022eb85c2334ff950c07e1808 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Mon, 28 Sep 2026 17:35:39 -0700 Subject: [PATCH 1/6] WIP addition of IGCA to OffloadArch --- clang/include/clang/Basic/OffloadArch.h | 14 ++++- clang/lib/Basic/OffloadArch.cpp | 19 ++++++ clang/unittests/Basic/OffloadArchTest.cpp | 2 + .../llvm/TargetParser/IntelGPUTargetParser.h | 57 ++++++++++++++++++ .../lib/TargetParser/IntelGPUTargetParser.cpp | 60 +++++++++++++++++++ 5 files changed, 151 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/OffloadArch.h b/clang/include/clang/Basic/OffloadArch.h index a0e5e72db220bb..4aaeb8981b73a3 100644 --- a/clang/include/clang/Basic/OffloadArch.h +++ b/clang/include/clang/Basic/OffloadArch.h @@ -22,6 +22,9 @@ enum GPUKind : uint8_t; namespace AMDGPU { enum GPUKind : uint8_t; } +namespace IntelGPU { +struct IGCATarget; +} } // namespace llvm namespace clang { @@ -39,6 +42,7 @@ class OffloadArch { AMDGCNSPIRV, // The 'amdgcnspirv' pseudo target. IntelCPU, // Kind is an IntelArch. IntelGPU, // Kind is an IntelArch. + IntelIGCA, // Kind is an Intel IGCA Target Generic, // The 'generic' processor model. }; @@ -64,6 +68,7 @@ class OffloadArch { static OffloadArch getAMDGPU(llvm::AMDGPU::GPUKind K) { return {TargetArch::AMDGPU, static_cast<uint32_t>(K)}; } + static OffloadArch getIntelIGCA(llvm::IntelGPU::IGCATarget T); static constexpr OffloadArch getIntel(TargetArch V, IntelArch A) { return {V, static_cast<uint32_t>(A)}; } @@ -85,18 +90,23 @@ class OffloadArch { bool isAMDGCNSPIRV() const { return V == TargetArch::AMDGCNSPIRV; } bool isIntelCPU() const { return V == TargetArch::IntelCPU; } bool isIntelGPU() const { return V == TargetArch::IntelGPU; } + // TODO: Decide whether IntelIGCA counts as Intel here. clang-sycl-linker + // uses isIntel() to decide on AOT compilation, and runAOTCompile would then + // need an IntelIGCA dispatch. bool isIntel() const { return isIntelCPU() || isIntelGPU(); } bool isGeneric() const { return V == TargetArch::Generic; } bool isUnused() const { return V == TargetArch::Unused; } bool isUnknown() const { return V == TargetArch::Unknown; } + bool isIntelIGCA() const { return V == TargetArch::IntelIGCA; } - // Only valid when isNVPTX() / isAMDGPU() respectively. + // Only valid when isNVPTX() / isAMDGPU() / isIntelIGCA() respectively. llvm::NVPTX::GPUKind nvptxKind() const { return static_cast<llvm::NVPTX::GPUKind>(Kind); } llvm::AMDGPU::GPUKind amdgpuKind() const { return static_cast<llvm::AMDGPU::GPUKind>(Kind); } + llvm::IntelGPU::IGCATarget igcaTarget() const; bool operator==(const OffloadArch &Other) const { return V == Other.V && Kind == Other.Kind; @@ -106,6 +116,8 @@ class OffloadArch { bool operator<(const OffloadArch &Other) const { return std::tie(V, Kind) < std::tie(Other.V, Other.Kind); } + // TODO test cases for whether or not IntelIGCA functions properly for these + // comparisons }; const char *OffloadArchToString(OffloadArch A); diff --git a/clang/lib/Basic/OffloadArch.cpp b/clang/lib/Basic/OffloadArch.cpp index f8c811f552f387..93de61a3ebd876 100644 --- a/clang/lib/Basic/OffloadArch.cpp +++ b/clang/lib/Basic/OffloadArch.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/TargetParser/AMDGPUTargetParser.h" #include "llvm/TargetParser/NVPTXTargetParser.h" +#include "llvm/TargetParser/IntelGPUTargetParser.h" #include "llvm/TargetParser/Triple.h" namespace clang { @@ -23,6 +24,14 @@ OffloadArch OffloadArch::HIPDefault() { return getAMDGPU(llvm::AMDGPU::parseArchAMDGCN("gfx906")); } +OffloadArch OffloadArch::getIntelIGCA(llvm::IntelGPU::IGCATarget T) { + return {TargetArch::IntelIGCA, T.pack()}; +} + +llvm::IntelGPU::IGCATarget OffloadArch::igcaTarget() const { + return llvm::IntelGPU::IGCATarget::unpack(Kind); +} + const char *OffloadArchToString(OffloadArch A) { switch (A.targetArch()) { case OffloadArch::TargetArch::Unused: @@ -39,6 +48,8 @@ const char *OffloadArchToString(OffloadArch A) { return "graniterapids"; case OffloadArch::TargetArch::IntelGPU: return "bmg_g21"; + case OffloadArch::TargetArch::IntelIGCA: + return llvm::IntelGPU::getIGCATargetName(A.igcaTarget()).data(); case OffloadArch::TargetArch::Generic: return "generic"; } @@ -54,6 +65,8 @@ const char *OffloadArchToVirtualArchString(OffloadArch A) { return "compute_amdgcn"; case OffloadArch::TargetArch::Unknown: return "unknown"; + case OffloadArch::TargetArch::IntelIGCA: + return llvm::IntelGPU::getIGCATargetName(A.igcaTarget()).data(); case OffloadArch::TargetArch::Unused: case OffloadArch::TargetArch::IntelCPU: case OffloadArch::TargetArch::IntelGPU: @@ -85,9 +98,12 @@ OffloadArch StringToOffloadArch(llvm::StringRef S) { return OffloadArch::getNVPTX(NV); if (llvm::AMDGPU::GPUKind AK = llvm::AMDGPU::parseArchAMDGCN(S)) return OffloadArch::getAMDGPU(AK); + if (llvm::IntelGPU::IGCATarget IT = llvm::IntelGPU::parseIGCATarget(S)) + return OffloadArch::getIntelIGCA(IT); return OffloadArch::getUnknown(); } +// TODO: Append the IGCA target names once the IGCA target table exists. void fillValidOffloadArchList(llvm::SmallVectorImpl<llvm::StringRef> &Values) { #define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX) \ Values.push_back(NAME); @@ -95,6 +111,7 @@ void fillValidOffloadArchList(llvm::SmallVectorImpl<llvm::StringRef> &Values) { llvm::AMDGPU::fillValidArchListAMDGCN(Values, llvm::Triple::NoSubArch); } +// TODO: Confirm IntelIGCA needs no subarch mapping; these only cover AMDGPU. OffloadArch getSubArchOffloadArch(llvm::Triple::SubArchType SubArch) { llvm::AMDGPU::GPUKind AK = llvm::AMDGPU::getGPUKindFromSubArch(SubArch); if (AK == llvm::AMDGPU::GK_NONE) @@ -126,6 +143,8 @@ llvm::Triple OffloadArchToTriple(const llvm::Triple &DefaultToolchainTriple, return llvm::Triple(llvm::Triple::amdgpu, llvm::Triple::NoSubArch, llvm::Triple::AMD, llvm::Triple::AMDHSA); + // TODO: Handle IntelIGCA, which currently gets an empty triple, so + // --offload-arch=igca_* cannot pick an offload toolchain. return {}; } diff --git a/clang/unittests/Basic/OffloadArchTest.cpp b/clang/unittests/Basic/OffloadArchTest.cpp index 013ed75fbd57eb..f46ec566c7f037 100644 --- a/clang/unittests/Basic/OffloadArchTest.cpp +++ b/clang/unittests/Basic/OffloadArchTest.cpp @@ -54,6 +54,8 @@ TEST(OffloadArchTest, Unknown) { } // Names must round-trip through parse -> string. +// TODO: Add IGCA targets (e.g. "igca_20ca"), plus IntelIGCA classification and +// ==/< ordering tests. TEST(OffloadArchTest, RoundTrip) { for (const char *Name : {"sm_52", "sm_90a", "gfx906", "gfx1201", "gfx12-generic", "amdgcnspirv", diff --git a/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h b/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h index 4ae635e97167ba..b344e99070b485 100644 --- a/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h +++ b/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h @@ -34,6 +34,48 @@ enum GPUKind : uint8_t { #include "llvm/TargetParser/IntelGPUTargetParser.def" }; +// TODO Do I want the IGCA_ prefix here? +enum class IGCAFeatureSet : uint8_t { + IGCA_CORE = 0, + IGCA_COMPUTE, + IGCA_RENDER +}; + +// TODO these need to be tested: +struct IGCATarget { + uint16_t Target = 0; + IGCAFeatureSet FeatureSet = IGCAFeatureSet::IGCA_CORE; + bool IsExactFeatureSet = false; + + /// Return true if the IGCATarget is a valid, properly initialized target. + bool isValid() const { return Target != 0; } + explicit operator bool() const { return isValid(); } + + bool isCore() const { return FeatureSet == IGCAFeatureSet::IGCA_CORE; } + bool isExact() const { return IsExactFeatureSet; } + bool isCompute() const { return FeatureSet == IGCAFeatureSet::IGCA_COMPUTE; } + bool isRender() const { return FeatureSet == IGCAFeatureSet::IGCA_RENDER; } + bool isComputeExact() const { return isCompute() && isExact(); }; + bool isRenderExact() const { return isRender() && isExact(); }; + + /// Pack an IGCATarget into an uint32_t. + /// + /// We encode as [31:16] Target, [2:1] FeatureSet, [0] IsExactFeatureSet. + /// [15:3] is left as reserved. + uint32_t pack() const; + + /// Obtain an IGCATarget from a packed uint32_t. + static IGCATarget unpack(uint32_t V); + + friend bool operator==(IGCATarget A, IGCATarget B) { + // TODO is this bad? + return A.pack() == B.pack(); + } + + /// Return an invalid IGCA Target that returns false on IGCATarget::isValid(). + static IGCATarget invalid() { return IGCATarget{}; } +}; + /// \return the device name that \p GPUIPVersion identifies, as reported by the /// driver, e.g. "xe-pvc". If the table lists no such device, return an empty /// string. Only the major and minor versions are looked at, so every revision @@ -44,6 +86,21 @@ LLVM_ABI StringRef getArchName(uint32_t GPUIPVersion); /// \return the numeric name of \p GPUIPVersion, e.g. "xe_35.11.0". LLVM_ABI std::string getNumericArchName(uint32_t GPUIPVersion); +/// Parse an IGCA Target. +IGCATarget parseIGCATarget(StringRef TargetStr); + +/// Return the IGCA string for a given IGCA Target, i.e. "igca_60ca". Returns +/// empty string if Target is not a valid target. +std::string getIGCATargetName(IGCATarget Target); +// TODO to carry stringref's, I need to create that IGCA Target table +// If that IGCA Target table gets really verbose, we should just use the +// strings from that table and use StringRef here instead of std::string. +// TODO DO STRINGREF'S + +// TODO +// - get igcatarget +// - translate other targets? + } // namespace IntelGPU } // namespace llvm diff --git a/llvm/lib/TargetParser/IntelGPUTargetParser.cpp b/llvm/lib/TargetParser/IntelGPUTargetParser.cpp index 4b4d162ffbfff7..67721b5fda0fda 100644 --- a/llvm/lib/TargetParser/IntelGPUTargetParser.cpp +++ b/llvm/lib/TargetParser/IntelGPUTargetParser.cpp @@ -63,3 +63,63 @@ std::string llvm::IntelGPU::getNumericArchName(uint32_t GPUIPVersion) { return ("xe_" + Twine(Major) + "." + Twine(Minor) + "." + Twine(Revision)) .str(); } + +IGCATarget llvm::IntelGPU::parseIGCATarget(StringRef MaybeTarget) { + if (!MaybeTarget.consume_front("igca_")) + return IGCATarget::invalid(); + + uint16_t Target; + if (MaybeTarget.consumeInteger(10, Target)) + return IGCATarget::invalid(); + // TODO check that Target contains a valid target level + + IGCAFeatureSet FS = IGCAFeatureSet::IGCA_CORE; + if (MaybeTarget.consume_front("c")) + FS = IGCAFeatureSet::IGCA_COMPUTE; + else if (MaybeTarget.consume_front("r")) + FS = IGCAFeatureSet::IGCA_RENDER; + bool IsExactFS = MaybeTarget.consume_front("a"); + if (!MaybeTarget.empty()) + return IGCATarget::invalid(); + + return { Target, FS, IsExactFS }; +} + +static constexpr uint32_t IGCATargetShift = 16; +static constexpr uint32_t IGCAFeatureSetShift = 1; +static constexpr uint32_t IGCAIsExactFSShift = 0; +static constexpr uint32_t IGCAFeatureSetMask = 0x03; +static constexpr uint32_t IGCAIsExactFSMask = 0x1; + +// An IGCA Target is packed as follows: +// +// 31 16 15 3 2 1 0 0 +// +------------------+--------------+-------------+-----------+ +// | Target | Reserved | Feature set | Is Exact? | +// +------------------+--------------+-------------+-----------+ +// 16 bits 13 bits 2 bits 1 bit +// +uint32_t llvm::IntelGPU::IGCATarget::pack() const { + // TODO add debug mode asserts here + return uint32_t(Target) << IGCATargetShift | + (uint32_t(FeatureSet) & IGCAFeatureSetMask) << IGCAFeatureSetShift | + (uint32_t(IsExactFeatureSet) & IGCAIsExactFSMask) + << IGCAIsExactFSShift; +} + +IGCATarget llvm::IntelGPU::IGCATarget::unpack(uint32_t V) { + return { + uint16_t(V >> IGCATargetShift), + IGCAFeatureSet((V >> IGCAFeatureSetShift) & IGCAFeatureSetMask), + bool((V >> IGCAIsExactFSShift) & IGCAIsExactFSMask) + }; +} + +std::string llvm::IntelGPU::getIGCATargetName(IGCATarget T) { + if (!T) + return ""; + + StringRef FS = T.isCompute() ? "c" : T.isRender() ? "r" : ""; + StringRef Exact = T.isExact() ? "a" : ""; + return ("igca_" + Twine(T.Target) + FS + Exact).str(); +} >From e77b8e687eb00e98d09df7a145b397a195155161 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Tue, 29 Sep 2026 12:22:01 -0700 Subject: [PATCH 2/6] Properly define IGCA targets in targetparser.def, and collapse IGCATarget struct to wrap around uint32_t packed representation instead --- clang/include/clang/Basic/OffloadArch.h | 2 +- clang/lib/Basic/OffloadArch.cpp | 2 +- .../TargetParser/IntelGPUTargetParser.def | 27 ++++- .../llvm/TargetParser/IntelGPUTargetParser.h | 103 ++++++++++-------- .../lib/TargetParser/IntelGPUTargetParser.cpp | 80 +++++++------- .../TargetParser/IntelGPUTargetParserTest.cpp | 89 +++++++++++++++ 6 files changed, 219 insertions(+), 84 deletions(-) diff --git a/clang/include/clang/Basic/OffloadArch.h b/clang/include/clang/Basic/OffloadArch.h index 4aaeb8981b73a3..a030192746c0d8 100644 --- a/clang/include/clang/Basic/OffloadArch.h +++ b/clang/include/clang/Basic/OffloadArch.h @@ -23,7 +23,7 @@ namespace AMDGPU { enum GPUKind : uint8_t; } namespace IntelGPU { -struct IGCATarget; +class IGCATarget; } } // namespace llvm diff --git a/clang/lib/Basic/OffloadArch.cpp b/clang/lib/Basic/OffloadArch.cpp index 93de61a3ebd876..6e06bbb433ada5 100644 --- a/clang/lib/Basic/OffloadArch.cpp +++ b/clang/lib/Basic/OffloadArch.cpp @@ -103,12 +103,12 @@ OffloadArch StringToOffloadArch(llvm::StringRef S) { return OffloadArch::getUnknown(); } -// TODO: Append the IGCA target names once the IGCA target table exists. void fillValidOffloadArchList(llvm::SmallVectorImpl<llvm::StringRef> &Values) { #define NVPTX_GPU(NAME, KIND, VIRTUAL, SM_ID, MIN_VER, MAX_VER, SUFFIX) \ Values.push_back(NAME); #include "llvm/TargetParser/NVPTXTargetParser.def" llvm::AMDGPU::fillValidArchListAMDGCN(Values, llvm::Triple::NoSubArch); + llvm::IntelGPU::fillValidIGCATargetList(Values); } // TODO: Confirm IntelIGCA needs no subarch mapping; these only cover AMDGPU. diff --git a/llvm/include/llvm/TargetParser/IntelGPUTargetParser.def b/llvm/include/llvm/TargetParser/IntelGPUTargetParser.def index bd3b0a4634e066..9d3876ca9c78b5 100644 --- a/llvm/include/llvm/TargetParser/IntelGPUTargetParser.def +++ b/llvm/include/llvm/TargetParser/IntelGPUTargetParser.def @@ -17,7 +17,8 @@ // GK_<KIND>. // MAJOR - Major component of the device's GPU IP version. // MINOR - Minor component of the device's GPU IP version. -// IGCA_TARGET - Numeric IGCA target. +// IGCA_TARGET - Numeric IGCA target: Targets should also be defined +// in the INTEL_IGCA_TARGET table. // IGCA_FEATURE_SETS - Token naming the IGCA feature sets the device // implements: Core (none), Compute ("c"), // Render ("r"), ComputeExact ("ca") or @@ -37,6 +38,15 @@ // Several devices can share a major and a minor version. The rows are ordered // so that the name to print for such a group comes first. // +// This file also includes a list of valid IGCA targets, which can be used to +// compile binaries with support different GPU architectures and feature sets: +// +// INTEL_IGCA_TARGET(TARGET) +// TARGET - Numeric IGCA target level, e.g. 60. corresponds to +// "igca_60". A defined IGCA target means feature sets, +// i.e. "igca_<TARGET>c", or "igca_<Target>ra" are also +// accepted. +// //===----------------------------------------------------------------------===// #ifndef INTEL_GPU @@ -92,5 +102,20 @@ INTEL_GPU_COMPAT("xe-bmg", XE_BMG, 40, Render) INTEL_GPU_COMPAT("xe-mtl", XE_MTL, 30, Render) INTEL_GPU_COMPAT("xe-dg2", XE_DG2, 15, RenderExact) +// IGCA target levels. Only targets defined here are valid. +#ifndef INTEL_IGCA_TARGET +#define INTEL_IGCA_TARGET(TARGET) +#endif + +INTEL_IGCA_TARGET(10) +INTEL_IGCA_TARGET(15) +INTEL_IGCA_TARGET(20) +INTEL_IGCA_TARGET(30) +INTEL_IGCA_TARGET(35) +INTEL_IGCA_TARGET(40) +INTEL_IGCA_TARGET(50) +INTEL_IGCA_TARGET(60) + #undef INTEL_GPU #undef INTEL_GPU_COMPAT +#undef INTEL_IGCA_TARGET diff --git a/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h b/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h index b344e99070b485..4931937be3af40 100644 --- a/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h +++ b/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h @@ -22,6 +22,8 @@ #include <string> namespace llvm { +template <typename T> class SmallVectorImpl; + namespace IntelGPU { /// Intel GPU architecture names, covering both physical devices and the @@ -34,46 +36,62 @@ enum GPUKind : uint8_t { #include "llvm/TargetParser/IntelGPUTargetParser.def" }; -// TODO Do I want the IGCA_ prefix here? -enum class IGCAFeatureSet : uint8_t { +enum IGCAFeatureSet : uint8_t { IGCA_CORE = 0, IGCA_COMPUTE, IGCA_RENDER }; -// TODO these need to be tested: -struct IGCATarget { - uint16_t Target = 0; - IGCAFeatureSet FeatureSet = IGCAFeatureSet::IGCA_CORE; - bool IsExactFeatureSet = false; - - /// Return true if the IGCATarget is a valid, properly initialized target. - bool isValid() const { return Target != 0; } +/// Wrapper around an IGCA target's uint32_t representation, packed using the +/// following format: +/// +/// 31 16 15 3 2 1 0 0 +/// +------------------+--------------+-------------+-----------+ +/// | Target | Reserved | Feature set | Is Exact? | +/// +------------------+--------------+-------------+-----------+ +/// 16 bits 13 bits 2 bits 1 bit +/// +/// Target == 0 denotes an invalid IGCA Target. +class IGCATarget { + uint32_t V = 0; + constexpr explicit IGCATarget(uint32_t V) : V(V) {} + +public: + static constexpr uint32_t TargetShift = 16; + static constexpr uint32_t FeatureSetShift = 1; + static constexpr uint32_t IsExactShift = 0; + static constexpr uint32_t FeatureSetMask = 0x3; + static constexpr uint32_t IsExactMask = 0x1; + + constexpr IGCATarget(uint16_t Target, IGCAFeatureSet FeatureSet, bool IsExact) + : V(uint32_t(Target) << TargetShift | + (uint32_t(FeatureSet) & FeatureSetMask) << FeatureSetShift | + (uint32_t(IsExact) & IsExactMask) << IsExactShift) {} + + /// \return an invalid IGCATarget. + static constexpr IGCATarget invalid() { return IGCATarget(0); } + + /// \return the packed uint32_t representation of the IGCA target. + constexpr uint32_t pack() const { return V; } + /// Wrap a packed uint32_t IGCA target with an IGCATarget class. + static constexpr IGCATarget unpack(uint32_t V) { return IGCATarget(V); } + + uint16_t getTarget() const { return uint16_t(V >> TargetShift); } + IGCAFeatureSet getFeatureSet() const { + return IGCAFeatureSet((V >> FeatureSetShift) & FeatureSetMask); + } + bool isExact() const { return (V >> IsExactShift) & IsExactMask; } + bool isValid() const { return getTarget() != 0; } explicit operator bool() const { return isValid(); } - bool isCore() const { return FeatureSet == IGCAFeatureSet::IGCA_CORE; } - bool isExact() const { return IsExactFeatureSet; } - bool isCompute() const { return FeatureSet == IGCAFeatureSet::IGCA_COMPUTE; } - bool isRender() const { return FeatureSet == IGCAFeatureSet::IGCA_RENDER; } - bool isComputeExact() const { return isCompute() && isExact(); }; - bool isRenderExact() const { return isRender() && isExact(); }; - - /// Pack an IGCATarget into an uint32_t. - /// - /// We encode as [31:16] Target, [2:1] FeatureSet, [0] IsExactFeatureSet. - /// [15:3] is left as reserved. - uint32_t pack() const; - - /// Obtain an IGCATarget from a packed uint32_t. - static IGCATarget unpack(uint32_t V); - - friend bool operator==(IGCATarget A, IGCATarget B) { - // TODO is this bad? - return A.pack() == B.pack(); - } + bool isCore() const { return getFeatureSet() == IGCA_CORE; } + bool isCompute() const { return getFeatureSet() == IGCA_COMPUTE; } + bool isRender() const { return getFeatureSet() == IGCA_RENDER; } + bool isComputeExact() const { return isCompute() && isExact(); } + bool isRenderExact() const { return isRender() && isExact(); } - /// Return an invalid IGCA Target that returns false on IGCATarget::isValid(). - static IGCATarget invalid() { return IGCATarget{}; } + friend bool operator==(IGCATarget A, IGCATarget B) { return A.V == B.V; } + friend bool operator!=(IGCATarget A, IGCATarget B) { return A.V != B.V; } }; /// \return the device name that \p GPUIPVersion identifies, as reported by the @@ -86,20 +104,17 @@ LLVM_ABI StringRef getArchName(uint32_t GPUIPVersion); /// \return the numeric name of \p GPUIPVersion, e.g. "xe_35.11.0". LLVM_ABI std::string getNumericArchName(uint32_t GPUIPVersion); -/// Parse an IGCA Target. -IGCATarget parseIGCATarget(StringRef TargetStr); +/// Parse an IGCA target string, such as "igca_60ca". \return an invalid +/// IGCATarget if \p TargetStr is not a known target in +/// IntelGPUTargetParser.def +LLVM_ABI IGCATarget parseIGCATarget(StringRef TargetStr); -/// Return the IGCA string for a given IGCA Target, i.e. "igca_60ca". Returns -/// empty string if Target is not a valid target. -std::string getIGCATargetName(IGCATarget Target); -// TODO to carry stringref's, I need to create that IGCA Target table -// If that IGCA Target table gets really verbose, we should just use the -// strings from that table and use StringRef here instead of std::string. -// TODO DO STRINGREF'S +/// \return the \p Target as a string, i.e. "igca_60ca". \return an empty string +/// if \p Target is invalid or not a known target in IntelGPUTargetParser.def. +LLVM_ABI StringRef getIGCATargetName(IGCATarget Target); -// TODO -// - get igcatarget -// - translate other targets? +/// Append every legal IGCA target spelling to \p Values. +LLVM_ABI void fillValidIGCATargetList(SmallVectorImpl<StringRef> &Values); } // namespace IntelGPU } // namespace llvm diff --git a/llvm/lib/TargetParser/IntelGPUTargetParser.cpp b/llvm/lib/TargetParser/IntelGPUTargetParser.cpp index 67721b5fda0fda..7b861b71e4c6a6 100644 --- a/llvm/lib/TargetParser/IntelGPUTargetParser.cpp +++ b/llvm/lib/TargetParser/IntelGPUTargetParser.cpp @@ -64,62 +64,68 @@ std::string llvm::IntelGPU::getNumericArchName(uint32_t GPUIPVersion) { .str(); } +/// Check that Level is a known IGCA Target in IntelGPUTargetParser.def. +bool isKnownIGCATargetLevel(uint16_t Level) { + switch (Level) { +#define INTEL_IGCA_TARGET(TARGET) case TARGET: +#include "llvm/TargetParser/IntelGPUTargetParser.def" + return true; + default: + return false; + } +} + IGCATarget llvm::IntelGPU::parseIGCATarget(StringRef MaybeTarget) { if (!MaybeTarget.consume_front("igca_")) return IGCATarget::invalid(); uint16_t Target; - if (MaybeTarget.consumeInteger(10, Target)) + if (MaybeTarget.consumeInteger(10, Target) || !isKnownIGCATargetLevel(Target)) return IGCATarget::invalid(); - // TODO check that Target contains a valid target level IGCAFeatureSet FS = IGCAFeatureSet::IGCA_CORE; if (MaybeTarget.consume_front("c")) FS = IGCAFeatureSet::IGCA_COMPUTE; else if (MaybeTarget.consume_front("r")) FS = IGCAFeatureSet::IGCA_RENDER; - bool IsExactFS = MaybeTarget.consume_front("a"); + // Exact form needs to either be compute or render: + bool IsExactFS = ( + FS != IGCAFeatureSet::IGCA_CORE && MaybeTarget.consume_front("a") + ); if (!MaybeTarget.empty()) return IGCATarget::invalid(); return { Target, FS, IsExactFS }; } -static constexpr uint32_t IGCATargetShift = 16; -static constexpr uint32_t IGCAFeatureSetShift = 1; -static constexpr uint32_t IGCAIsExactFSShift = 0; -static constexpr uint32_t IGCAFeatureSetMask = 0x03; -static constexpr uint32_t IGCAIsExactFSMask = 0x1; - -// An IGCA Target is packed as follows: -// -// 31 16 15 3 2 1 0 0 -// +------------------+--------------+-------------+-----------+ -// | Target | Reserved | Feature set | Is Exact? | -// +------------------+--------------+-------------+-----------+ -// 16 bits 13 bits 2 bits 1 bit -// -uint32_t llvm::IntelGPU::IGCATarget::pack() const { - // TODO add debug mode asserts here - return uint32_t(Target) << IGCATargetShift | - (uint32_t(FeatureSet) & IGCAFeatureSetMask) << IGCAFeatureSetShift | - (uint32_t(IsExactFeatureSet) & IGCAIsExactFSMask) - << IGCAIsExactFSShift; -} - -IGCATarget llvm::IntelGPU::IGCATarget::unpack(uint32_t V) { - return { - uint16_t(V >> IGCATargetShift), - IGCAFeatureSet((V >> IGCAFeatureSetShift) & IGCAFeatureSetMask), - bool((V >> IGCAIsExactFSShift) & IGCAIsExactFSMask) - }; +StringRef llvm::IntelGPU::getIGCATargetName(IGCATarget T) { + switch (T.pack()) { +#define INTEL_IGCA_TARGET(TARGET) \ + case IGCATarget(TARGET, IGCAFeatureSet::IGCA_CORE, false).pack(): \ + return "igca_" #TARGET; \ + case IGCATarget(TARGET, IGCAFeatureSet::IGCA_COMPUTE, false).pack(): \ + return "igca_" #TARGET "c"; \ + case IGCATarget(TARGET, IGCAFeatureSet::IGCA_COMPUTE, true).pack(): \ + return "igca_" #TARGET "ca"; \ + case IGCATarget(TARGET, IGCAFeatureSet::IGCA_RENDER, false).pack(): \ + return "igca_" #TARGET "r"; \ + case IGCATarget(TARGET, IGCAFeatureSet::IGCA_RENDER, true).pack(): \ + return "igca_" #TARGET "ra"; +#include "llvm/TargetParser/IntelGPUTargetParser.def" + default: + return ""; + } } -std::string llvm::IntelGPU::getIGCATargetName(IGCATarget T) { - if (!T) - return ""; +#define INTEL_IGCA_TARGET_FEATURESETS(TARGET) \ + "igca_" #TARGET, "igca_" #TARGET "c", "igca_" #TARGET "ca", \ + "igca_" #TARGET "r", "igca_" #TARGET "ra" - StringRef FS = T.isCompute() ? "c" : T.isRender() ? "r" : ""; - StringRef Exact = T.isExact() ? "a" : ""; - return ("igca_" + Twine(T.Target) + FS + Exact).str(); +void llvm::IntelGPU::fillValidIGCATargetList( + SmallVectorImpl<StringRef> &Values) { +#define INTEL_IGCA_TARGET(TARGET) \ + Values.append({INTEL_IGCA_TARGET_FEATURESETS(TARGET)}); +#include "llvm/TargetParser/IntelGPUTargetParser.def" } + +#undef INTEL_IGCA_TARGET_FEATURESETS diff --git a/llvm/unittests/TargetParser/IntelGPUTargetParserTest.cpp b/llvm/unittests/TargetParser/IntelGPUTargetParserTest.cpp index ab8d456769d0da..93a31558e7e03e 100644 --- a/llvm/unittests/TargetParser/IntelGPUTargetParserTest.cpp +++ b/llvm/unittests/TargetParser/IntelGPUTargetParserTest.cpp @@ -78,4 +78,93 @@ TEST(IntelGPUTargetParserTest, NumericArchName) { "xe_12.60.7"); } +TEST(IntelGPUTargetParserTest, IGCATargetBehavior) { + IntelGPU::IGCATarget T(60, IntelGPU::IGCA_COMPUTE, true); + EXPECT_TRUE(T.isValid()); + EXPECT_EQ(T.getTarget(), 60); + EXPECT_EQ(T.getFeatureSet(), IntelGPU::IGCA_COMPUTE); + EXPECT_TRUE(T.isExact()); + EXPECT_TRUE(T.isComputeExact()); + EXPECT_FALSE(T.isRender()); + EXPECT_EQ(IntelGPU::IGCATarget::unpack(T.pack()), T); + EXPECT_NE(T, IntelGPU::IGCATarget(60, IntelGPU::IGCA_COMPUTE, false)); + // Invalid behavior: + EXPECT_FALSE(IntelGPU::IGCATarget::invalid()); + EXPECT_EQ(IntelGPU::IGCATarget::invalid().pack(), 0u); +} + +TEST(IntelGPUTargetParserTest, ParseIGCATarget) { + using IntelGPU::IGCATarget; + EXPECT_EQ(IntelGPU::parseIGCATarget("igca_10"), + IGCATarget(10, IntelGPU::IGCA_CORE, false)); + EXPECT_EQ(IntelGPU::parseIGCATarget("igca_20c"), + IGCATarget(20, IntelGPU::IGCA_COMPUTE, false)); + EXPECT_EQ(IntelGPU::parseIGCATarget("igca_20ca"), + IGCATarget(20, IntelGPU::IGCA_COMPUTE, true)); + EXPECT_EQ(IntelGPU::parseIGCATarget("igca_15r"), + IGCATarget(15, IntelGPU::IGCA_RENDER, false)); + EXPECT_EQ(IntelGPU::parseIGCATarget("igca_15ra"), + IGCATarget(15, IntelGPU::IGCA_RENDER, true)); + // Only levels in the table are valid targets. + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_42")); + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_0")); + // Cannot have exact without naming feature set: + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_10a")); + // Malformed spellings: + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_")); + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_10x")); + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_10cr")); + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_10caa")); + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca10")); + EXPECT_FALSE(IntelGPU::parseIGCATarget("IGCA_10")); + EXPECT_FALSE(IntelGPU::parseIGCATarget("")); +} + +TEST(IntelGPUTargetParserTest, IGCATargetName) { + using IntelGPU::IGCATarget; + EXPECT_EQ(IntelGPU::getIGCATargetName( + IGCATarget(60, IntelGPU::IGCA_CORE, false)), + "igca_60"); + EXPECT_EQ(IntelGPU::getIGCATargetName( + IGCATarget(60, IntelGPU::IGCA_COMPUTE, true)), + "igca_60ca"); + EXPECT_EQ(IntelGPU::getIGCATargetName( + IGCATarget(15, IntelGPU::IGCA_RENDER, false)), + "igca_15r"); + EXPECT_EQ(IntelGPU::getIGCATargetName(IGCATarget::invalid()), ""); + // A level that is not in the table has no spelling, and neither does an + // exact core target. + EXPECT_EQ(IntelGPU::getIGCATargetName( + IGCATarget(11, IntelGPU::IGCA_CORE, false)), + ""); + EXPECT_EQ(IntelGPU::getIGCATargetName( + IGCATarget(10, IntelGPU::IGCA_CORE, true)), + ""); +} + +TEST(IntelGPUTargetParserTest, EveryIGCASpellingRoundTrips) { + SmallVector<StringRef> Names; + IntelGPU::fillValidIGCATargetList(Names); + EXPECT_FALSE(Names.empty()); + for (StringRef Name : Names) { + IntelGPU::IGCATarget T = IntelGPU::parseIGCATarget(Name); + EXPECT_TRUE(T.isValid()) << Name; + EXPECT_EQ(IntelGPU::getIGCATargetName(T), Name); + } +} + +TEST(IntelGPUTargetParserTest, EveryDeviceHasValidIGCATargetLevel) { + // Every device's defined IGCA target should have a corresponding entry in + // INTEL_IGCA_TARGET: +#define INTEL_IGCA_TARGET_CHECK(NAME, IGCA_TARGET) \ + EXPECT_TRUE(IntelGPU::parseIGCATarget("igca_" #IGCA_TARGET).isValid()) \ + << NAME; +#define INTEL_GPU(NAME, KIND, MAJOR, MINOR, IGCA_TARGET, IGCA_FEATURE_SETS) \ + INTEL_IGCA_TARGET_CHECK(NAME, IGCA_TARGET) +#define INTEL_GPU_COMPAT(NAME, KIND, IGCA_TARGET, IGCA_FEATURE_SETS) \ + INTEL_IGCA_TARGET_CHECK(NAME, IGCA_TARGET) +#include "llvm/TargetParser/IntelGPUTargetParser.def" +#undef INTEL_IGCA_TARGET_CHECK +} + } // namespace >From 7fdfd295d0523c9e612a4dc4579f79ffa527fa60 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Tue, 29 Sep 2026 13:23:23 -0700 Subject: [PATCH 3/6] fix nvptx test... I'm not so sure about the change... --- .../test/Misc/target-invalid-cpu-note/nvptx.c | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/clang/test/Misc/target-invalid-cpu-note/nvptx.c b/clang/test/Misc/target-invalid-cpu-note/nvptx.c index 20dbd8dc6aa3b6..528348dfba595c 100644 --- a/clang/test/Misc/target-invalid-cpu-note/nvptx.c +++ b/clang/test/Misc/target-invalid-cpu-note/nvptx.c @@ -128,4 +128,44 @@ // CHECK-SAME: {{^}}, polaris11 // CHECK-SAME: {{^}}, tongapro // CHECK-SAME: {{^}}, stoney +// CHECK-SAME: {{^}}, igca_10 +// CHECK-SAME: {{^}}, igca_10c +// CHECK-SAME: {{^}}, igca_10ca +// CHECK-SAME: {{^}}, igca_10r +// CHECK-SAME: {{^}}, igca_10ra +// CHECK-SAME: {{^}}, igca_15 +// CHECK-SAME: {{^}}, igca_15c +// CHECK-SAME: {{^}}, igca_15ca +// CHECK-SAME: {{^}}, igca_15r +// CHECK-SAME: {{^}}, igca_15ra +// CHECK-SAME: {{^}}, igca_20 +// CHECK-SAME: {{^}}, igca_20c +// CHECK-SAME: {{^}}, igca_20ca +// CHECK-SAME: {{^}}, igca_20r +// CHECK-SAME: {{^}}, igca_20ra +// CHECK-SAME: {{^}}, igca_30 +// CHECK-SAME: {{^}}, igca_30c +// CHECK-SAME: {{^}}, igca_30ca +// CHECK-SAME: {{^}}, igca_30r +// CHECK-SAME: {{^}}, igca_30ra +// CHECK-SAME: {{^}}, igca_35 +// CHECK-SAME: {{^}}, igca_35c +// CHECK-SAME: {{^}}, igca_35ca +// CHECK-SAME: {{^}}, igca_35r +// CHECK-SAME: {{^}}, igca_35ra +// CHECK-SAME: {{^}}, igca_40 +// CHECK-SAME: {{^}}, igca_40c +// CHECK-SAME: {{^}}, igca_40ca +// CHECK-SAME: {{^}}, igca_40r +// CHECK-SAME: {{^}}, igca_40ra +// CHECK-SAME: {{^}}, igca_50 +// CHECK-SAME: {{^}}, igca_50c +// CHECK-SAME: {{^}}, igca_50ca +// CHECK-SAME: {{^}}, igca_50r +// CHECK-SAME: {{^}}, igca_50ra +// CHECK-SAME: {{^}}, igca_60 +// CHECK-SAME: {{^}}, igca_60c +// CHECK-SAME: {{^}}, igca_60ca +// CHECK-SAME: {{^}}, igca_60r +// CHECK-SAME: {{^}}, igca_60ra // CHECK-SAME: {{$}} >From 5949a6914849eca4d58411a190714e810e1c1c08 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Tue, 29 Sep 2026 13:24:24 -0700 Subject: [PATCH 4/6] clang-format --- clang/lib/Basic/OffloadArch.cpp | 2 +- .../llvm/TargetParser/IntelGPUTargetParser.h | 8 ++--- .../lib/TargetParser/IntelGPUTargetParser.cpp | 9 +++--- .../TargetParser/IntelGPUTargetParserTest.cpp | 30 +++++++++---------- 4 files changed, 22 insertions(+), 27 deletions(-) diff --git a/clang/lib/Basic/OffloadArch.cpp b/clang/lib/Basic/OffloadArch.cpp index 6e06bbb433ada5..c22aa528265fdb 100644 --- a/clang/lib/Basic/OffloadArch.cpp +++ b/clang/lib/Basic/OffloadArch.cpp @@ -10,8 +10,8 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/TargetParser/AMDGPUTargetParser.h" -#include "llvm/TargetParser/NVPTXTargetParser.h" #include "llvm/TargetParser/IntelGPUTargetParser.h" +#include "llvm/TargetParser/NVPTXTargetParser.h" #include "llvm/TargetParser/Triple.h" namespace clang { diff --git a/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h b/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h index 4931937be3af40..339becdd102225 100644 --- a/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h +++ b/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h @@ -36,11 +36,7 @@ enum GPUKind : uint8_t { #include "llvm/TargetParser/IntelGPUTargetParser.def" }; -enum IGCAFeatureSet : uint8_t { - IGCA_CORE = 0, - IGCA_COMPUTE, - IGCA_RENDER -}; +enum IGCAFeatureSet : uint8_t { IGCA_CORE = 0, IGCA_COMPUTE, IGCA_RENDER }; /// Wrapper around an IGCA target's uint32_t representation, packed using the /// following format: @@ -105,7 +101,7 @@ LLVM_ABI StringRef getArchName(uint32_t GPUIPVersion); LLVM_ABI std::string getNumericArchName(uint32_t GPUIPVersion); /// Parse an IGCA target string, such as "igca_60ca". \return an invalid -/// IGCATarget if \p TargetStr is not a known target in +/// IGCATarget if \p TargetStr is not a known target in /// IntelGPUTargetParser.def LLVM_ABI IGCATarget parseIGCATarget(StringRef TargetStr); diff --git a/llvm/lib/TargetParser/IntelGPUTargetParser.cpp b/llvm/lib/TargetParser/IntelGPUTargetParser.cpp index 7b861b71e4c6a6..0e1163dff9aec8 100644 --- a/llvm/lib/TargetParser/IntelGPUTargetParser.cpp +++ b/llvm/lib/TargetParser/IntelGPUTargetParser.cpp @@ -82,20 +82,19 @@ IGCATarget llvm::IntelGPU::parseIGCATarget(StringRef MaybeTarget) { uint16_t Target; if (MaybeTarget.consumeInteger(10, Target) || !isKnownIGCATargetLevel(Target)) return IGCATarget::invalid(); - + IGCAFeatureSet FS = IGCAFeatureSet::IGCA_CORE; if (MaybeTarget.consume_front("c")) FS = IGCAFeatureSet::IGCA_COMPUTE; else if (MaybeTarget.consume_front("r")) FS = IGCAFeatureSet::IGCA_RENDER; // Exact form needs to either be compute or render: - bool IsExactFS = ( - FS != IGCAFeatureSet::IGCA_CORE && MaybeTarget.consume_front("a") - ); + bool IsExactFS = + (FS != IGCAFeatureSet::IGCA_CORE && MaybeTarget.consume_front("a")); if (!MaybeTarget.empty()) return IGCATarget::invalid(); - return { Target, FS, IsExactFS }; + return {Target, FS, IsExactFS}; } StringRef llvm::IntelGPU::getIGCATargetName(IGCATarget T) { diff --git a/llvm/unittests/TargetParser/IntelGPUTargetParserTest.cpp b/llvm/unittests/TargetParser/IntelGPUTargetParserTest.cpp index 93a31558e7e03e..f1c55912305ece 100644 --- a/llvm/unittests/TargetParser/IntelGPUTargetParserTest.cpp +++ b/llvm/unittests/TargetParser/IntelGPUTargetParserTest.cpp @@ -122,24 +122,24 @@ TEST(IntelGPUTargetParserTest, ParseIGCATarget) { TEST(IntelGPUTargetParserTest, IGCATargetName) { using IntelGPU::IGCATarget; - EXPECT_EQ(IntelGPU::getIGCATargetName( - IGCATarget(60, IntelGPU::IGCA_CORE, false)), - "igca_60"); - EXPECT_EQ(IntelGPU::getIGCATargetName( - IGCATarget(60, IntelGPU::IGCA_COMPUTE, true)), - "igca_60ca"); - EXPECT_EQ(IntelGPU::getIGCATargetName( - IGCATarget(15, IntelGPU::IGCA_RENDER, false)), - "igca_15r"); + EXPECT_EQ( + IntelGPU::getIGCATargetName(IGCATarget(60, IntelGPU::IGCA_CORE, false)), + "igca_60"); + EXPECT_EQ( + IntelGPU::getIGCATargetName(IGCATarget(60, IntelGPU::IGCA_COMPUTE, true)), + "igca_60ca"); + EXPECT_EQ( + IntelGPU::getIGCATargetName(IGCATarget(15, IntelGPU::IGCA_RENDER, false)), + "igca_15r"); EXPECT_EQ(IntelGPU::getIGCATargetName(IGCATarget::invalid()), ""); // A level that is not in the table has no spelling, and neither does an // exact core target. - EXPECT_EQ(IntelGPU::getIGCATargetName( - IGCATarget(11, IntelGPU::IGCA_CORE, false)), - ""); - EXPECT_EQ(IntelGPU::getIGCATargetName( - IGCATarget(10, IntelGPU::IGCA_CORE, true)), - ""); + EXPECT_EQ( + IntelGPU::getIGCATargetName(IGCATarget(11, IntelGPU::IGCA_CORE, false)), + ""); + EXPECT_EQ( + IntelGPU::getIGCATargetName(IGCATarget(10, IntelGPU::IGCA_CORE, true)), + ""); } TEST(IntelGPUTargetParserTest, EveryIGCASpellingRoundTrips) { >From adf084bb47a080760de2e687707d64dfa7ad7acb Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Thu, 1 Oct 2026 15:58:22 -0700 Subject: [PATCH 5/6] Enforce that only certain IGCA target feature sets can exist, simplify code and logic --- .../test/Misc/target-invalid-cpu-note/nvptx.c | 20 --- .../TargetParser/IntelGPUTargetParser.def | 53 +++++-- .../llvm/TargetParser/IntelGPUTargetParser.h | 62 +++++--- .../lib/TargetParser/IntelGPUTargetParser.cpp | 63 ++------ .../TargetParser/IntelGPUTargetParserTest.cpp | 139 +++++++++++++----- 5 files changed, 199 insertions(+), 138 deletions(-) diff --git a/clang/test/Misc/target-invalid-cpu-note/nvptx.c b/clang/test/Misc/target-invalid-cpu-note/nvptx.c index 528348dfba595c..b8f1bd806ef6af 100644 --- a/clang/test/Misc/target-invalid-cpu-note/nvptx.c +++ b/clang/test/Misc/target-invalid-cpu-note/nvptx.c @@ -129,43 +129,23 @@ // CHECK-SAME: {{^}}, tongapro // CHECK-SAME: {{^}}, stoney // CHECK-SAME: {{^}}, igca_10 -// CHECK-SAME: {{^}}, igca_10c -// CHECK-SAME: {{^}}, igca_10ca // CHECK-SAME: {{^}}, igca_10r -// CHECK-SAME: {{^}}, igca_10ra // CHECK-SAME: {{^}}, igca_15 -// CHECK-SAME: {{^}}, igca_15c -// CHECK-SAME: {{^}}, igca_15ca // CHECK-SAME: {{^}}, igca_15r // CHECK-SAME: {{^}}, igca_15ra // CHECK-SAME: {{^}}, igca_20 // CHECK-SAME: {{^}}, igca_20c // CHECK-SAME: {{^}}, igca_20ca -// CHECK-SAME: {{^}}, igca_20r -// CHECK-SAME: {{^}}, igca_20ra // CHECK-SAME: {{^}}, igca_30 -// CHECK-SAME: {{^}}, igca_30c -// CHECK-SAME: {{^}}, igca_30ca // CHECK-SAME: {{^}}, igca_30r -// CHECK-SAME: {{^}}, igca_30ra // CHECK-SAME: {{^}}, igca_35 -// CHECK-SAME: {{^}}, igca_35c -// CHECK-SAME: {{^}}, igca_35ca // CHECK-SAME: {{^}}, igca_35r // CHECK-SAME: {{^}}, igca_35ra // CHECK-SAME: {{^}}, igca_40 -// CHECK-SAME: {{^}}, igca_40c -// CHECK-SAME: {{^}}, igca_40ca // CHECK-SAME: {{^}}, igca_40r -// CHECK-SAME: {{^}}, igca_40ra // CHECK-SAME: {{^}}, igca_50 -// CHECK-SAME: {{^}}, igca_50c -// CHECK-SAME: {{^}}, igca_50ca // CHECK-SAME: {{^}}, igca_50r -// CHECK-SAME: {{^}}, igca_50ra // CHECK-SAME: {{^}}, igca_60 // CHECK-SAME: {{^}}, igca_60c -// CHECK-SAME: {{^}}, igca_60ca // CHECK-SAME: {{^}}, igca_60r -// CHECK-SAME: {{^}}, igca_60ra // CHECK-SAME: {{$}} diff --git a/llvm/include/llvm/TargetParser/IntelGPUTargetParser.def b/llvm/include/llvm/TargetParser/IntelGPUTargetParser.def index 9d3876ca9c78b5..362b004f737106 100644 --- a/llvm/include/llvm/TargetParser/IntelGPUTargetParser.def +++ b/llvm/include/llvm/TargetParser/IntelGPUTargetParser.def @@ -41,11 +41,15 @@ // This file also includes a list of valid IGCA targets, which can be used to // compile binaries with support different GPU architectures and feature sets: // -// INTEL_IGCA_TARGET(TARGET) -// TARGET - Numeric IGCA target level, e.g. 60. corresponds to -// "igca_60". A defined IGCA target means feature sets, -// i.e. "igca_<TARGET>c", or "igca_<Target>ra" are also -// accepted. +// INTEL_IGCA_TARGET(NAME, TARGET, FEATURE_SET) +// One row per valid IGCA target spelling. Only the combinations listed +// are valid. +// NAME - Name of the IGCA target, e.g. "igca_15ra". Name must +// agree with the other columns. +// TARGET - Numeric IGCA target level, e.g. 60. +// FEATURE_SET - Feature set of the current target, i.e. "Compute" for +// "c" suffix, "Render" for "r", "ComputeExact" for +// "ca", "Core" for "", etc. // //===----------------------------------------------------------------------===// @@ -102,19 +106,38 @@ INTEL_GPU_COMPAT("xe-bmg", XE_BMG, 40, Render) INTEL_GPU_COMPAT("xe-mtl", XE_MTL, 30, Render) INTEL_GPU_COMPAT("xe-dg2", XE_DG2, 15, RenderExact) -// IGCA target levels. Only targets defined here are valid. +// IGCA targets. Only targets listed here are valid. #ifndef INTEL_IGCA_TARGET -#define INTEL_IGCA_TARGET(TARGET) +#define INTEL_IGCA_TARGET(NAME, TARGET, FEATURE_SET) #endif -INTEL_IGCA_TARGET(10) -INTEL_IGCA_TARGET(15) -INTEL_IGCA_TARGET(20) -INTEL_IGCA_TARGET(30) -INTEL_IGCA_TARGET(35) -INTEL_IGCA_TARGET(40) -INTEL_IGCA_TARGET(50) -INTEL_IGCA_TARGET(60) +INTEL_IGCA_TARGET("igca_10", 10, Core) +INTEL_IGCA_TARGET("igca_10r", 10, Render) + +INTEL_IGCA_TARGET("igca_15", 15, Core) +INTEL_IGCA_TARGET("igca_15r", 15, Render) +INTEL_IGCA_TARGET("igca_15ra", 15, RenderExact) + +INTEL_IGCA_TARGET("igca_20", 20, Core) +INTEL_IGCA_TARGET("igca_20c", 20, Compute) +INTEL_IGCA_TARGET("igca_20ca", 20, ComputeExact) + +INTEL_IGCA_TARGET("igca_30", 30, Core) +INTEL_IGCA_TARGET("igca_30r", 30, Render) + +INTEL_IGCA_TARGET("igca_35", 35, Core) +INTEL_IGCA_TARGET("igca_35r", 35, Render) +INTEL_IGCA_TARGET("igca_35ra", 35, RenderExact) + +INTEL_IGCA_TARGET("igca_40", 40, Core) +INTEL_IGCA_TARGET("igca_40r", 40, Render) + +INTEL_IGCA_TARGET("igca_50", 50, Core) +INTEL_IGCA_TARGET("igca_50r", 50, Render) + +INTEL_IGCA_TARGET("igca_60", 60, Core) +INTEL_IGCA_TARGET("igca_60c", 60, Compute) +INTEL_IGCA_TARGET("igca_60r", 60, Render) #undef INTEL_GPU #undef INTEL_GPU_COMPAT diff --git a/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h b/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h index 339becdd102225..7d8e1cf1ab4f8b 100644 --- a/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h +++ b/llvm/include/llvm/TargetParser/IntelGPUTargetParser.h @@ -16,6 +16,7 @@ #ifndef LLVM_TARGETPARSER_INTELGPUTARGETPARSER_H #define LLVM_TARGETPARSER_INTELGPUTARGETPARSER_H +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include <cstdint> @@ -36,7 +37,16 @@ enum GPUKind : uint8_t { #include "llvm/TargetParser/IntelGPUTargetParser.def" }; -enum IGCAFeatureSet : uint8_t { IGCA_CORE = 0, IGCA_COMPUTE, IGCA_RENDER }; +/// Represents an IGCA feature set, including whether or not it is exact. The +/// values are bitfields where the last bit represents exact. See IGCA Target +/// representation below for more info. +enum class IGCAFeatureSet : uint8_t { + Core = 0b000, + Compute = 0b010, + ComputeExact = 0b011, + Render = 0b100, + RenderExact = 0b101, +}; /// Wrapper around an IGCA target's uint32_t representation, packed using the /// following format: @@ -54,15 +64,12 @@ class IGCATarget { public: static constexpr uint32_t TargetShift = 16; - static constexpr uint32_t FeatureSetShift = 1; - static constexpr uint32_t IsExactShift = 0; - static constexpr uint32_t FeatureSetMask = 0x3; + static constexpr uint32_t FeatureSetMask = 0x7; static constexpr uint32_t IsExactMask = 0x1; - constexpr IGCATarget(uint16_t Target, IGCAFeatureSet FeatureSet, bool IsExact) + constexpr IGCATarget(uint16_t Target, IGCAFeatureSet FeatureSet) : V(uint32_t(Target) << TargetShift | - (uint32_t(FeatureSet) & FeatureSetMask) << FeatureSetShift | - (uint32_t(IsExact) & IsExactMask) << IsExactShift) {} + (llvm::to_underlying(FeatureSet) & FeatureSetMask)) {} /// \return an invalid IGCATarget. static constexpr IGCATarget invalid() { return IGCATarget(0); } @@ -73,18 +80,39 @@ class IGCATarget { static constexpr IGCATarget unpack(uint32_t V) { return IGCATarget(V); } uint16_t getTarget() const { return uint16_t(V >> TargetShift); } + /// \return the feature set, including whether it is exact. + /// + /// To check if a target has a feature set regardless of exactness, use + /// hasCompute() or hasRender() instead of raw comparison between + /// IGCAFeatureSet enums. IGCAFeatureSet getFeatureSet() const { - return IGCAFeatureSet((V >> FeatureSetShift) & FeatureSetMask); + return IGCAFeatureSet(V & FeatureSetMask); } - bool isExact() const { return (V >> IsExactShift) & IsExactMask; } + bool isExact() const { return V & IsExactMask; } bool isValid() const { return getTarget() != 0; } explicit operator bool() const { return isValid(); } - bool isCore() const { return getFeatureSet() == IGCA_CORE; } - bool isCompute() const { return getFeatureSet() == IGCA_COMPUTE; } - bool isRender() const { return getFeatureSet() == IGCA_RENDER; } - bool isComputeExact() const { return isCompute() && isExact(); } - bool isRenderExact() const { return isRender() && isExact(); } + bool isCore() const { return getFeatureSet() == IGCAFeatureSet::Core; } + /// \return true if the target has a non-exact Compute feature set. + bool isCompute() const { return getFeatureSet() == IGCAFeatureSet::Compute; } + /// \return true if the target has a non-exact Render feature set. + bool isRender() const { return getFeatureSet() == IGCAFeatureSet::Render; } + bool isComputeExact() const { + return getFeatureSet() == IGCAFeatureSet::ComputeExact; + } + bool isRenderExact() const { + return getFeatureSet() == IGCAFeatureSet::RenderExact; + } + /// \return true if target has either Compute or ComputeExact feature set. + bool hasCompute() const { + return (llvm::to_underlying(getFeatureSet()) & ~IsExactMask) == + llvm::to_underlying(IGCAFeatureSet::Compute); + } + /// \return true if target has either Render or RenderExact feature set. + bool hasRender() const { + return (llvm::to_underlying(getFeatureSet()) & ~IsExactMask) == + llvm::to_underlying(IGCAFeatureSet::Render); + } friend bool operator==(IGCATarget A, IGCATarget B) { return A.V == B.V; } friend bool operator!=(IGCATarget A, IGCATarget B) { return A.V != B.V; } @@ -100,16 +128,16 @@ LLVM_ABI StringRef getArchName(uint32_t GPUIPVersion); /// \return the numeric name of \p GPUIPVersion, e.g. "xe_35.11.0". LLVM_ABI std::string getNumericArchName(uint32_t GPUIPVersion); -/// Parse an IGCA target string, such as "igca_60ca". \return an invalid +/// Parse an IGCA target string, such as "igca_20ca". \return an invalid /// IGCATarget if \p TargetStr is not a known target in /// IntelGPUTargetParser.def LLVM_ABI IGCATarget parseIGCATarget(StringRef TargetStr); -/// \return the \p Target as a string, i.e. "igca_60ca". \return an empty string +/// \return the \p Target as a string, i.e. "igca_20ca". \return an empty string /// if \p Target is invalid or not a known target in IntelGPUTargetParser.def. LLVM_ABI StringRef getIGCATargetName(IGCATarget Target); -/// Append every legal IGCA target spelling to \p Values. +/// Append every valid IGCA target spelling to \p Values. LLVM_ABI void fillValidIGCATargetList(SmallVectorImpl<StringRef> &Values); } // namespace IntelGPU diff --git a/llvm/lib/TargetParser/IntelGPUTargetParser.cpp b/llvm/lib/TargetParser/IntelGPUTargetParser.cpp index 0e1163dff9aec8..20335d30dc392b 100644 --- a/llvm/lib/TargetParser/IntelGPUTargetParser.cpp +++ b/llvm/lib/TargetParser/IntelGPUTargetParser.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "llvm/TargetParser/IntelGPUTargetParser.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include <cassert> @@ -64,67 +65,31 @@ std::string llvm::IntelGPU::getNumericArchName(uint32_t GPUIPVersion) { .str(); } -/// Check that Level is a known IGCA Target in IntelGPUTargetParser.def. -bool isKnownIGCATargetLevel(uint16_t Level) { - switch (Level) { -#define INTEL_IGCA_TARGET(TARGET) case TARGET: -#include "llvm/TargetParser/IntelGPUTargetParser.def" - return true; - default: - return false; - } -} - IGCATarget llvm::IntelGPU::parseIGCATarget(StringRef MaybeTarget) { - if (!MaybeTarget.consume_front("igca_")) - return IGCATarget::invalid(); - - uint16_t Target; - if (MaybeTarget.consumeInteger(10, Target) || !isKnownIGCATargetLevel(Target)) - return IGCATarget::invalid(); - - IGCAFeatureSet FS = IGCAFeatureSet::IGCA_CORE; - if (MaybeTarget.consume_front("c")) - FS = IGCAFeatureSet::IGCA_COMPUTE; - else if (MaybeTarget.consume_front("r")) - FS = IGCAFeatureSet::IGCA_RENDER; - // Exact form needs to either be compute or render: - bool IsExactFS = - (FS != IGCAFeatureSet::IGCA_CORE && MaybeTarget.consume_front("a")); - if (!MaybeTarget.empty()) - return IGCATarget::invalid(); - - return {Target, FS, IsExactFS}; + return StringSwitch<IGCATarget>(MaybeTarget) +#define INTEL_IGCA_TARGET(NAME, TARGET, FEATURE_SET) \ + .Case(NAME, IGCATarget(TARGET, IGCAFeatureSet::FEATURE_SET)) +#include "llvm/TargetParser/IntelGPUTargetParser.def" + .Default(IGCATarget::invalid()); } StringRef llvm::IntelGPU::getIGCATargetName(IGCATarget T) { switch (T.pack()) { -#define INTEL_IGCA_TARGET(TARGET) \ - case IGCATarget(TARGET, IGCAFeatureSet::IGCA_CORE, false).pack(): \ - return "igca_" #TARGET; \ - case IGCATarget(TARGET, IGCAFeatureSet::IGCA_COMPUTE, false).pack(): \ - return "igca_" #TARGET "c"; \ - case IGCATarget(TARGET, IGCAFeatureSet::IGCA_COMPUTE, true).pack(): \ - return "igca_" #TARGET "ca"; \ - case IGCATarget(TARGET, IGCAFeatureSet::IGCA_RENDER, false).pack(): \ - return "igca_" #TARGET "r"; \ - case IGCATarget(TARGET, IGCAFeatureSet::IGCA_RENDER, true).pack(): \ - return "igca_" #TARGET "ra"; +#define INTEL_IGCA_TARGET(NAME, TARGET, FEATURE_SET) \ + case IGCATarget(TARGET, IGCAFeatureSet::FEATURE_SET).pack(): \ + return NAME; #include "llvm/TargetParser/IntelGPUTargetParser.def" default: return ""; } } -#define INTEL_IGCA_TARGET_FEATURESETS(TARGET) \ - "igca_" #TARGET, "igca_" #TARGET "c", "igca_" #TARGET "ca", \ - "igca_" #TARGET "r", "igca_" #TARGET "ra" - +// TODO: Ensure -fsycl --offload-arch provides a list of valid IGCA +// architectures, similar to how compiling for an nvptx triple returns a list +// of valid GPU architectures. The user trying to input an invalid IGCA target +// without being told what IGCA targets actually exist might get confusing. void llvm::IntelGPU::fillValidIGCATargetList( SmallVectorImpl<StringRef> &Values) { -#define INTEL_IGCA_TARGET(TARGET) \ - Values.append({INTEL_IGCA_TARGET_FEATURESETS(TARGET)}); +#define INTEL_IGCA_TARGET(NAME, TARGET, FEATURE_SET) Values.push_back(NAME); #include "llvm/TargetParser/IntelGPUTargetParser.def" } - -#undef INTEL_IGCA_TARGET_FEATURESETS diff --git a/llvm/unittests/TargetParser/IntelGPUTargetParserTest.cpp b/llvm/unittests/TargetParser/IntelGPUTargetParserTest.cpp index f1c55912305ece..b9685a61c4271d 100644 --- a/llvm/unittests/TargetParser/IntelGPUTargetParserTest.cpp +++ b/llvm/unittests/TargetParser/IntelGPUTargetParserTest.cpp @@ -79,33 +79,68 @@ TEST(IntelGPUTargetParserTest, NumericArchName) { } TEST(IntelGPUTargetParserTest, IGCATargetBehavior) { - IntelGPU::IGCATarget T(60, IntelGPU::IGCA_COMPUTE, true); - EXPECT_TRUE(T.isValid()); - EXPECT_EQ(T.getTarget(), 60); - EXPECT_EQ(T.getFeatureSet(), IntelGPU::IGCA_COMPUTE); - EXPECT_TRUE(T.isExact()); - EXPECT_TRUE(T.isComputeExact()); - EXPECT_FALSE(T.isRender()); - EXPECT_EQ(IntelGPU::IGCATarget::unpack(T.pack()), T); - EXPECT_NE(T, IntelGPU::IGCATarget(60, IntelGPU::IGCA_COMPUTE, false)); + using IntelGPU::IGCAFeatureSet; + using IntelGPU::IGCATarget; + IGCATarget C{60, IGCAFeatureSet::ComputeExact}; + EXPECT_TRUE(C.isValid()); + EXPECT_EQ(C.getTarget(), 60); + EXPECT_EQ(C.getFeatureSet(), IGCAFeatureSet::ComputeExact); + EXPECT_TRUE(C.isExact()); + // An exact feature set is still of its class: + EXPECT_TRUE(C.hasCompute()); + EXPECT_TRUE(C.isComputeExact()); + EXPECT_FALSE(C.isCore()); + EXPECT_FALSE(C.isCompute()); + EXPECT_FALSE(C.isRender()); + EXPECT_FALSE(C.hasRender()); + EXPECT_FALSE(C.isRenderExact()); + EXPECT_EQ(IGCATarget::unpack(C.pack()), C); + EXPECT_NE(C, IGCATarget(60, IGCAFeatureSet::Compute)); + // A feature set that is not exact: + IGCATarget R{60, IGCAFeatureSet::Render}; + EXPECT_TRUE(R.isRender()); + EXPECT_FALSE(R.isRenderExact()); + EXPECT_FALSE(R.isExact()); + EXPECT_FALSE(R.isCompute()); + EXPECT_TRUE(R.hasRender()); + EXPECT_FALSE(R.hasCompute()); + EXPECT_EQ(IGCATarget::unpack(R.pack()), R); + IGCATarget Core{60, IGCAFeatureSet::Core}; + EXPECT_TRUE(Core.isCore()); // Invalid behavior: - EXPECT_FALSE(IntelGPU::IGCATarget::invalid()); - EXPECT_EQ(IntelGPU::IGCATarget::invalid().pack(), 0u); + EXPECT_FALSE(IGCATarget::invalid()); + EXPECT_EQ(IGCATarget::invalid().pack(), 0u); } TEST(IntelGPUTargetParserTest, ParseIGCATarget) { + using IntelGPU::IGCAFeatureSet; using IntelGPU::IGCATarget; EXPECT_EQ(IntelGPU::parseIGCATarget("igca_10"), - IGCATarget(10, IntelGPU::IGCA_CORE, false)); + IGCATarget(10, IGCAFeatureSet::Core)); EXPECT_EQ(IntelGPU::parseIGCATarget("igca_20c"), - IGCATarget(20, IntelGPU::IGCA_COMPUTE, false)); + IGCATarget(20, IGCAFeatureSet::Compute)); EXPECT_EQ(IntelGPU::parseIGCATarget("igca_20ca"), - IGCATarget(20, IntelGPU::IGCA_COMPUTE, true)); + IGCATarget(20, IGCAFeatureSet::ComputeExact)); EXPECT_EQ(IntelGPU::parseIGCATarget("igca_15r"), - IGCATarget(15, IntelGPU::IGCA_RENDER, false)); + IGCATarget(15, IGCAFeatureSet::Render)); EXPECT_EQ(IntelGPU::parseIGCATarget("igca_15ra"), - IGCATarget(15, IntelGPU::IGCA_RENDER, true)); - // Only levels in the table are valid targets. + IGCATarget(15, IGCAFeatureSet::RenderExact)); + EXPECT_EQ(IntelGPU::parseIGCATarget("igca_35ra"), + IGCATarget(35, IGCAFeatureSet::RenderExact)); + EXPECT_EQ(IntelGPU::parseIGCATarget("igca_60c"), + IGCATarget(60, IGCAFeatureSet::Compute)); + EXPECT_EQ(IntelGPU::parseIGCATarget("igca_60r"), + IGCATarget(60, IGCAFeatureSet::Render)); + // Not all target levels support all feature sets: + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_10c")); + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_20r")); + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_20ra")); + // Only some target levels have an exact feature set: + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_10ra")); + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_30ra")); + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_60ca")); + EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_60ra")); + // Only target levels in the table are valid targets: EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_42")); EXPECT_FALSE(IntelGPU::parseIGCATarget("igca_0")); // Cannot have exact without naming feature set: @@ -121,25 +156,25 @@ TEST(IntelGPUTargetParserTest, ParseIGCATarget) { } TEST(IntelGPUTargetParserTest, IGCATargetName) { + using IntelGPU::IGCAFeatureSet; using IntelGPU::IGCATarget; + EXPECT_EQ(IntelGPU::getIGCATargetName(IGCATarget(60, IGCAFeatureSet::Core)), + "igca_60"); EXPECT_EQ( - IntelGPU::getIGCATargetName(IGCATarget(60, IntelGPU::IGCA_CORE, false)), - "igca_60"); - EXPECT_EQ( - IntelGPU::getIGCATargetName(IGCATarget(60, IntelGPU::IGCA_COMPUTE, true)), - "igca_60ca"); - EXPECT_EQ( - IntelGPU::getIGCATargetName(IGCATarget(15, IntelGPU::IGCA_RENDER, false)), - "igca_15r"); + IntelGPU::getIGCATargetName(IGCATarget(20, IGCAFeatureSet::ComputeExact)), + "igca_20ca"); + EXPECT_EQ(IntelGPU::getIGCATargetName(IGCATarget(15, IGCAFeatureSet::Render)), + "igca_15r"); + // A target that does not exist / is not valid should produce "" to signify + // invalid target. EXPECT_EQ(IntelGPU::getIGCATargetName(IGCATarget::invalid()), ""); - // A level that is not in the table has no spelling, and neither does an - // exact core target. + EXPECT_EQ(IntelGPU::getIGCATargetName(IGCATarget(11, IGCAFeatureSet::Core)), + ""); EXPECT_EQ( - IntelGPU::getIGCATargetName(IGCATarget(11, IntelGPU::IGCA_CORE, false)), + IntelGPU::getIGCATargetName(IGCATarget(60, IGCAFeatureSet::ComputeExact)), ""); EXPECT_EQ( - IntelGPU::getIGCATargetName(IGCATarget(10, IntelGPU::IGCA_CORE, true)), - ""); + IntelGPU::getIGCATargetName(IGCATarget(10, IGCAFeatureSet::Compute)), ""); } TEST(IntelGPUTargetParserTest, EveryIGCASpellingRoundTrips) { @@ -153,16 +188,46 @@ TEST(IntelGPUTargetParserTest, EveryIGCASpellingRoundTrips) { } } -TEST(IntelGPUTargetParserTest, EveryDeviceHasValidIGCATargetLevel) { - // Every device's defined IGCA target should have a corresponding entry in - // INTEL_IGCA_TARGET: -#define INTEL_IGCA_TARGET_CHECK(NAME, IGCA_TARGET) \ - EXPECT_TRUE(IntelGPU::parseIGCATarget("igca_" #IGCA_TARGET).isValid()) \ +// Spell an IGCA target from its fields, independently of the NAME column. +std::string expectedIGCASpelling(uint16_t Target, + IntelGPU::IGCAFeatureSet FeatureSet) { + std::string Name = "igca_" + std::to_string(Target); + switch (FeatureSet) { + case IntelGPU::IGCAFeatureSet::Core: + return Name; + case IntelGPU::IGCAFeatureSet::Compute: + return Name + "c"; + case IntelGPU::IGCAFeatureSet::ComputeExact: + return Name + "ca"; + case IntelGPU::IGCAFeatureSet::Render: + return Name + "r"; + case IntelGPU::IGCAFeatureSet::RenderExact: + return Name + "ra"; + } + return ""; +} + +TEST(IntelGPUTargetParserTest, IGCASpellingsMatchFields) { + // Every INTEL_IGCA_TARGET's NAME must agree with information in the rest of + // its row. +#define INTEL_IGCA_TARGET(NAME, TARGET, FEATURE_SET) \ + EXPECT_EQ(NAME, expectedIGCASpelling( \ + TARGET, IntelGPU::IGCAFeatureSet::FEATURE_SET)); +#include "llvm/TargetParser/IntelGPUTargetParser.def" +} + +TEST(IntelGPUTargetParserTest, EveryDeviceHasValidIGCATarget) { + // Every device's IGCA target and feature sets should have a corresponding + // entry in INTEL_IGCA_TARGET: +#define INTEL_IGCA_TARGET_CHECK(NAME, IGCA_TARGET, IGCA_FEATURE_SETS) \ + EXPECT_NE(IntelGPU::getIGCATargetName(IntelGPU::IGCATarget( \ + IGCA_TARGET, IntelGPU::IGCAFeatureSet::IGCA_FEATURE_SETS)), \ + "") \ << NAME; #define INTEL_GPU(NAME, KIND, MAJOR, MINOR, IGCA_TARGET, IGCA_FEATURE_SETS) \ - INTEL_IGCA_TARGET_CHECK(NAME, IGCA_TARGET) + INTEL_IGCA_TARGET_CHECK(NAME, IGCA_TARGET, IGCA_FEATURE_SETS) #define INTEL_GPU_COMPAT(NAME, KIND, IGCA_TARGET, IGCA_FEATURE_SETS) \ - INTEL_IGCA_TARGET_CHECK(NAME, IGCA_TARGET) + INTEL_IGCA_TARGET_CHECK(NAME, IGCA_TARGET, IGCA_FEATURE_SETS) #include "llvm/TargetParser/IntelGPUTargetParser.def" #undef INTEL_IGCA_TARGET_CHECK } >From 7420a14b004047c5bd2f5050f20da2f19e7d13c8 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Thu, 8 Oct 2026 13:44:59 -0700 Subject: [PATCH 6/6] fillValidOffloadArchList is a bit misleading isnt it haha --- clang/lib/Basic/OffloadArch.cpp | 1 - .../test/Misc/target-invalid-cpu-note/nvptx.c | 20 ------------------- 2 files changed, 21 deletions(-) diff --git a/clang/lib/Basic/OffloadArch.cpp b/clang/lib/Basic/OffloadArch.cpp index c22aa528265fdb..2127b12b30875c 100644 --- a/clang/lib/Basic/OffloadArch.cpp +++ b/clang/lib/Basic/OffloadArch.cpp @@ -108,7 +108,6 @@ void fillValidOffloadArchList(llvm::SmallVectorImpl<llvm::StringRef> &Values) { Values.push_back(NAME); #include "llvm/TargetParser/NVPTXTargetParser.def" llvm::AMDGPU::fillValidArchListAMDGCN(Values, llvm::Triple::NoSubArch); - llvm::IntelGPU::fillValidIGCATargetList(Values); } // TODO: Confirm IntelIGCA needs no subarch mapping; these only cover AMDGPU. diff --git a/clang/test/Misc/target-invalid-cpu-note/nvptx.c b/clang/test/Misc/target-invalid-cpu-note/nvptx.c index b8f1bd806ef6af..20dbd8dc6aa3b6 100644 --- a/clang/test/Misc/target-invalid-cpu-note/nvptx.c +++ b/clang/test/Misc/target-invalid-cpu-note/nvptx.c @@ -128,24 +128,4 @@ // CHECK-SAME: {{^}}, polaris11 // CHECK-SAME: {{^}}, tongapro // CHECK-SAME: {{^}}, stoney -// CHECK-SAME: {{^}}, igca_10 -// CHECK-SAME: {{^}}, igca_10r -// CHECK-SAME: {{^}}, igca_15 -// CHECK-SAME: {{^}}, igca_15r -// CHECK-SAME: {{^}}, igca_15ra -// CHECK-SAME: {{^}}, igca_20 -// CHECK-SAME: {{^}}, igca_20c -// CHECK-SAME: {{^}}, igca_20ca -// CHECK-SAME: {{^}}, igca_30 -// CHECK-SAME: {{^}}, igca_30r -// CHECK-SAME: {{^}}, igca_35 -// CHECK-SAME: {{^}}, igca_35r -// CHECK-SAME: {{^}}, igca_35ra -// CHECK-SAME: {{^}}, igca_40 -// CHECK-SAME: {{^}}, igca_40r -// CHECK-SAME: {{^}}, igca_50 -// CHECK-SAME: {{^}}, igca_50r -// CHECK-SAME: {{^}}, igca_60 -// CHECK-SAME: {{^}}, igca_60c -// CHECK-SAME: {{^}}, igca_60r // CHECK-SAME: {{$}} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
