diff --git a/clang/lib/Basic/Targets/AIE.cpp b/clang/lib/Basic/Targets/AIE.cpp index 75d86871aece..86d790170e79 100644 --- a/clang/lib/Basic/Targets/AIE.cpp +++ b/clang/lib/Basic/Targets/AIE.cpp @@ -16,6 +16,7 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/MacroBuilder.h" #include "clang/Basic/TargetBuiltins.h" +#include "llvm/ADT/StringSwitch.h" using namespace clang; using namespace clang::targets; @@ -41,6 +42,50 @@ void AIETargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__AIECC__"); Builder.defineMacro("__PEANO__"); Builder.defineMacro("__ELF__"); + + // Capability macros derived from the resolved SubtargetFeatures. A kernel + // selects a code path by capability (for example #if __AIE_HAS_BFP16__) + // instead of hard-coding the generation with an arch macro. + if (HasBFP16) + Builder.defineMacro("__AIE_HAS_BFP16__"); + if (HasAcc2048) + Builder.defineMacro("__AIE_HAS_ACC2048__"); +} + +bool AIETargetInfo::initFeatureMap( + llvm::StringMap &Features, DiagnosticsEngine &Diags, StringRef CPU, + const std::vector &FeaturesVec) const { + // Per-generation default capability set. aie2p carries native bfp16 and the + // 2048-bit accumulator. Capability is a set, not a level, so this is keyed + // off the concrete target rather than assumed to grow monotonically across + // generations. User -target-feature flags are applied on top by the base. + if (isAIE2P(getTriple())) { + Features["bfp16"] = true; + Features["acc2048"] = true; + } + return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); +} + +bool AIETargetInfo::handleTargetFeatures(std::vector &Features, + DiagnosticsEngine &Diags) { + for (const auto &Feature : Features) { + if (Feature == "+bfp16") + HasBFP16 = true; + else if (Feature == "-bfp16") + HasBFP16 = false; + else if (Feature == "+acc2048") + HasAcc2048 = true; + else if (Feature == "-acc2048") + HasAcc2048 = false; + } + return true; +} + +bool AIETargetInfo::hasFeature(StringRef Feature) const { + return llvm::StringSwitch(Feature) + .Case("bfp16", HasBFP16) + .Case("acc2048", HasAcc2048) + .Default(false); } llvm::SmallVector diff --git a/clang/lib/Basic/Targets/AIE.h b/clang/lib/Basic/Targets/AIE.h index c7b708c08179..cf441417d59e 100644 --- a/clang/lib/Basic/Targets/AIE.h +++ b/clang/lib/Basic/Targets/AIE.h @@ -111,6 +111,16 @@ class LLVM_LIBRARY_VISIBILITY AIETargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; + bool + initFeatureMap(llvm::StringMap &Features, DiagnosticsEngine &Diags, + StringRef CPU, + const std::vector &FeaturesVec) const override; + + bool handleTargetFeatures(std::vector &Features, + DiagnosticsEngine &Diags) override; + + bool hasFeature(StringRef Feature) const override; + llvm::SmallVector getTargetBuiltins() const override; BuiltinVaListKind getBuiltinVaListKind() const override { @@ -158,6 +168,13 @@ class LLVM_LIBRARY_VISIBILITY AIETargetInfo : public TargetInfo { const char *getFloat16Mangling() const override { return "7float16"; } bool treatFloat16AsVendorType() const override { return true; } + +protected: + // Subtarget capability bits, mirroring the AIE backend SubtargetFeatures. + // Default off; enabled per-generation in initFeatureMap and resolved from the + // -target-feature list in handleTargetFeatures. + bool HasBFP16 = false; + bool HasAcc2048 = false; }; } // namespace targets diff --git a/clang/test/CodeGen/aie/aie2p/aie2p-capability-select.cc b/clang/test/CodeGen/aie/aie2p/aie2p-capability-select.cc new file mode 100644 index 000000000000..f280a7d0cd60 --- /dev/null +++ b/clang/test/CodeGen/aie/aie2p/aie2p-capability-select.cc @@ -0,0 +1,31 @@ +//===- aie2p-capability-select.cc -------------------------------*- C++ -*-===// +// +// This file is licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// A kernel selects the multiply-accumulate path by capability, not by arch. +// There is no __AIEARCH__ / __AIE_ARCH__ guard here: the choice is driven by +// the __AIE_HAS_BFP16__ capability macro, which is toggled by a SubtargetFeature. +// REQUIRES: aie-registered-target + +// Default aie2p: bfp16 is available, so the native path is selected. +// RUN: %clang_cc1 -triple aie2p -emit-llvm -o - %s | \ +// RUN: FileCheck %s --check-prefix=NATIVE + +// aie2p with the capability turned off: the emulated fallback is selected. +// RUN: %clang_cc1 -triple aie2p -target-feature -bfp16 -emit-llvm -o - %s | \ +// RUN: FileCheck %s --check-prefix=EMULATED + +int mac_path() { +#if defined(__AIE_HAS_BFP16__) + return 16; // native block-floating-point path +#else + return 32; // emulated fallback path +#endif +} + +// NATIVE: ret i32 16 +// EMULATED: ret i32 32 diff --git a/clang/test/Preprocessor/aie-capability-macros.c b/clang/test/Preprocessor/aie-capability-macros.c new file mode 100644 index 000000000000..d0b0449c2537 --- /dev/null +++ b/clang/test/Preprocessor/aie-capability-macros.c @@ -0,0 +1,28 @@ +//===- aie-capability-macros.c ----------------------------------*- C++ -*-===// +// +// This file is licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// The AIE capability macros are derived from SubtargetFeatures, so a kernel can +// query a capability instead of hard-coding the generation with an arch macro. +// REQUIRES: aie-registered-target + +// aie2p enables bfp16 by default, so the capability macro is defined. +// RUN: %clang_cc1 -E -dM -triple=aie2p < /dev/null | \ +// RUN: FileCheck -match-full-lines -check-prefix BFP16 %s + +// The same target with the feature turned off does not define the macro, +// showing the macro tracks the capability rather than the target name. +// RUN: %clang_cc1 -E -dM -triple=aie2p -target-feature -bfp16 < /dev/null | \ +// RUN: FileCheck -check-prefix NO-BFP16 %s + +// A different revision (aie2ps) does not carry bfp16, so the macro is absent. +// This is the point of a capability set: it is not a monotonic level. +// RUN: %clang_cc1 -E -dM -triple=aie2ps < /dev/null | \ +// RUN: FileCheck -check-prefix NO-BFP16 %s + +// BFP16: #define __AIE_HAS_BFP16__ 1 +// NO-BFP16-NOT: __AIE_HAS_BFP16__ diff --git a/llvm/lib/Target/AIE/AIE2P.td b/llvm/lib/Target/AIE/AIE2P.td index 866109e0c8ae..8312cfe067b9 100644 --- a/llvm/lib/Target/AIE/AIE2P.td +++ b/llvm/lib/Target/AIE/AIE2P.td @@ -16,6 +16,9 @@ include "llvm/Target/AIETarget.td" // includes extra definitions for the usage of the CodeGenFormat Backend include "llvm/Target/CodeGenFormat.td" +// Per-generation capability SubtargetFeatures. +include "AIEFeatures.td" + def ptr0 : PtrValueType; //===----------------------------------------------------------------------===// @@ -39,7 +42,7 @@ include "AIECombine.td" // AIEngine V2 processors supported. //===----------------------------------------------------------------------===// -def : ProcessorModel<"aie2p", AIE2PSchedModel, []>; +def : ProcessorModel<"aie2p", AIE2PSchedModel, [FeatureBFP16, FeatureAcc2048]>; //===----------------------------------------------------------------------===// // Define the AIE2PEngine target. diff --git a/llvm/lib/Target/AIE/AIEFeatures.td b/llvm/lib/Target/AIE/AIEFeatures.td new file mode 100644 index 000000000000..471191ad434a --- /dev/null +++ b/llvm/lib/Target/AIE/AIEFeatures.td @@ -0,0 +1,29 @@ +//===-- AIEFeatures.td - AIE subtarget capability set ------*- tablegen -*-===// +// +// This file is licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// (c) Copyright 2026 Advanced Micro Devices, Inc. or its affiliates +// +//===----------------------------------------------------------------------===// +// +// SubtargetFeatures describing per-generation AIE capability deltas. These let +// a compiler pass or a kernel query a capability (has(FeatureBFP16)) instead of +// hard-coding the generation by CPU name / arch macro. This is a capability +// SET, not a monotonic level: a later generation is not required to be a +// superset of an earlier one (e.g. bfp16 is aie2p-only). +// +//===----------------------------------------------------------------------===// + +// Native block-floating-point (bfp16, ebs8/ebs16) multiply-accumulate support. +// aie2p only. +def FeatureBFP16 + : SubtargetFeature< + "bfp16", "HasBFP16", "true", + "Native block-floating-point (bfp16) multiply-accumulate support">; + +// 2048-bit wide accumulator register file. +def FeatureAcc2048 + : SubtargetFeature<"acc2048", "HasAcc2048", "true", + "2048-bit wide accumulator register file">; diff --git a/llvm/lib/Target/AIE/aie2p/AIE2PSubtarget.h b/llvm/lib/Target/AIE/aie2p/AIE2PSubtarget.h index 5576134cf2b7..4c93fbf0d137 100644 --- a/llvm/lib/Target/AIE/aie2p/AIE2PSubtarget.h +++ b/llvm/lib/Target/AIE/aie2p/AIE2PSubtarget.h @@ -32,6 +32,16 @@ class StringRef; class AIE2PSubtarget : public AIE2PGenSubtargetInfo { virtual void anchor(); + + // Subtarget capability bits generated from the AIEFeatures.td + // SubtargetFeatures and assigned by ParseSubtargetFeatures. Declared ahead of + // the members whose initialization runs ParseSubtargetFeatures (FrameLowering + // et al.) so the in-class default initializer cannot clobber a parsed value. +#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ + bool ATTRIBUTE = DEFAULT; +#include "AIE2PGenSubtargetInfo.inc" +#undef GET_SUBTARGETINFO_MACRO + std::string CPUName; // FIXME: Do we need a custom AIE2PAddrSpaceInfo? AIE2AddrSpaceInfo AddrSpaceInfo; @@ -58,6 +68,13 @@ class AIE2PSubtarget : public AIE2PGenSubtargetInfo { void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); + // Capability queries generated from AIEFeatures.td (e.g. hasBFP16(), + // hasAcc2048()). Prefer these over checking the CPU name or an arch macro. +#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ + bool GETTER() const { return ATTRIBUTE; } +#include "AIE2PGenSubtargetInfo.inc" +#undef GET_SUBTARGETINFO_MACRO + const AIE2PFrameLowering *getFrameLowering() const override { return &FrameLowering; }