Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions clang/lib/Basic/Targets/AIE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &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<std::string> &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<bool>(Feature)
.Case("bfp16", HasBFP16)
.Case("acc2048", HasAcc2048)
.Default(false);
}

llvm::SmallVector<Builtin::InfosShard>
Expand Down
17 changes: 17 additions & 0 deletions clang/lib/Basic/Targets/AIE.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ class LLVM_LIBRARY_VISIBILITY AIETargetInfo : public TargetInfo {
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;

bool
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
const std::vector<std::string> &FeaturesVec) const override;

bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override;

bool hasFeature(StringRef Feature) const override;

llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;

BuiltinVaListKind getBuiltinVaListKind() const override {
Expand Down Expand Up @@ -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
Expand Down
31 changes: 31 additions & 0 deletions clang/test/CodeGen/aie/aie2p/aie2p-capability-select.cc
Original file line number Diff line number Diff line change
@@ -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
28 changes: 28 additions & 0 deletions clang/test/Preprocessor/aie-capability-macros.c
Original file line number Diff line number Diff line change
@@ -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__
5 changes: 4 additions & 1 deletion llvm/lib/Target/AIE/AIE2P.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<i20, 0>;

//===----------------------------------------------------------------------===//
Expand All @@ -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.
Expand Down
29 changes: 29 additions & 0 deletions llvm/lib/Target/AIE/AIEFeatures.td
Original file line number Diff line number Diff line change
@@ -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">;
17 changes: 17 additions & 0 deletions llvm/lib/Target/AIE/aie2p/AIE2PSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down