https://github.com/tommat01 updated https://github.com/llvm/llvm-project/pull/222074
>From f42f403b3d35bd85d6481ea6f76c17e6959e5e49 Mon Sep 17 00:00:00 2001 From: Tomas Matheson <[email protected]> Date: Tue, 8 Sep 2026 18:23:21 +0100 Subject: [PATCH] [AsmPrinter] target-features optimization remarks In clang we have --print-enabled-extensions which will print the AArch64 extensions enabled for a given TU. However, sometimes it is useful to be able to print out the actual subtarget features for each function, for debugging/testing purposes. Add an optimization remark for that. --- ...imization-remark-target-features-aarch64.c | 30 +++++++++++++ .../optimization-remark-target-features-arm.c | 19 ++++++++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 17 +++++++ .../optimization-remark-target-features.ll | 45 +++++++++++++++++++ .../optimization-remark-target-features.ll | 30 +++++++++++++ 5 files changed, 141 insertions(+) create mode 100644 clang/test/Frontend/optimization-remark-target-features-aarch64.c create mode 100644 clang/test/Frontend/optimization-remark-target-features-arm.c create mode 100644 llvm/test/CodeGen/AArch64/optimization-remark-target-features.ll create mode 100644 llvm/test/CodeGen/ARM/optimization-remark-target-features.ll diff --git a/clang/test/Frontend/optimization-remark-target-features-aarch64.c b/clang/test/Frontend/optimization-remark-target-features-aarch64.c new file mode 100644 index 0000000000000..f73c69ec7daa7 --- /dev/null +++ b/clang/test/Frontend/optimization-remark-target-features-aarch64.c @@ -0,0 +1,30 @@ +// REQUIRES: aarch64-registered-target +// RUN: %clang --target=aarch64-unknown-linux-gnu --rtlib=compiler-rt \ +// RUN: -S -O0 -Rpass-analysis=target-features -fno-caret-diagnostics %s -o /dev/null 2>&1 | FileCheck %s + +int baseline(void) { return 0; } +__attribute__((target("sve2"))) int targeted(void) { return 1; } +__attribute__((target_clones("sve2", "default"))) int clones(void) { return 2; } +__attribute__((target_version("sve2"))) int versioned(void) { return 3; } +__attribute__((target_version("default"))) int versioned(void) { return 4; } +int caller(void) { return clones() + versioned(); } + +// Inspect the subtarget used for each emitted function, including FMV variants +// and their resolvers. Default functions must not inherit variant features. +// CHECK-NOT: Enabled features +// CHECK: {{.*}}remark: Enabled features for @baseline: +// CHECK-NOT: {{(^|[ ,])(sve|sve2)(,| |$)}} +// CHECK-NEXT: {{.*}}remark: Enabled features for @targeted: {{([^,]+,)*}}fp-armv8,fullfp16,{{([^,]+,)*}}sve,sve2{{(,.*)?}} [-Rpass-analysis=target-features] +// CHECK-NEXT: {{.*}}remark: Enabled features for @clones._Msve2: {{([^,]+,)*}}fp-armv8,fullfp16,{{([^,]+,)*}}sve,sve2{{(,.*)?}} [-Rpass-analysis=target-features] +// CHECK-NEXT: {{.*}}remark: Enabled features for @clones.default: +// CHECK-NOT: {{(^|[ ,])(sve|sve2)(,| |$)}} +// CHECK-NEXT: {{.*}}remark: Enabled features for @versioned._Msve2: {{([^,]+,)*}}fp-armv8,fullfp16,{{([^,]+,)*}}sve,sve2{{(,.*)?}} [-Rpass-analysis=target-features] +// CHECK-NEXT: {{.*}}remark: Enabled features for @versioned.default: +// CHECK-NOT: {{(^|[ ,])(sve|sve2)(,| |$)}} +// CHECK-NEXT: {{.*}}remark: Enabled features for @caller: +// CHECK-NOT: {{(^|[ ,])(sve|sve2)(,| |$)}} +// CHECK-NEXT: {{.*}}remark: Enabled features for @clones.resolver: +// CHECK-NOT: {{(^|[ ,])(sve|sve2)(,| |$)}} +// CHECK-NEXT: {{.*}}remark: Enabled features for @versioned.resolver: +// CHECK-NOT: {{(^|[ ,])(sve|sve2)(,| |$)}} +// CHECK-NOT: Enabled features diff --git a/clang/test/Frontend/optimization-remark-target-features-arm.c b/clang/test/Frontend/optimization-remark-target-features-arm.c new file mode 100644 index 0000000000000..e27de210236f4 --- /dev/null +++ b/clang/test/Frontend/optimization-remark-target-features-arm.c @@ -0,0 +1,19 @@ +// REQUIRES: arm-registered-target +// RUN: %clang --target=armv7-unknown-linux-gnueabi \ +// RUN: -S -O0 -Rpass-analysis=target-features -fno-caret-diagnostics %s -o /dev/null 2>&1 | FileCheck %s + +int baseline(void) { return 0; } +__attribute__((target("thumb"))) int thumb_function(void) { return 1; } +__attribute__((target("arm"))) int arm_function(void) { return 2; } +int baseline_again(void) { return 3; } + +// ARM and Thumb functions in the same translation unit use distinct subtargets. +// CHECK-NOT: Enabled features +// CHECK: {{.*}}remark: Enabled features for @baseline: +// CHECK-NOT: {{(^|[ ,])thumb-mode(,| |$)}} +// CHECK-NEXT: {{.*}}remark: Enabled features for @thumb_function: {{([^,]+,)*}}thumb-mode{{(,.*)?}} [-Rpass-analysis=target-features] +// CHECK-NEXT: {{.*}}remark: Enabled features for @arm_function: +// CHECK-NOT: {{(^|[ ,])thumb-mode(,| |$)}} +// CHECK-NEXT: {{.*}}remark: Enabled features for @baseline_again: +// CHECK-NOT: {{(^|[ ,])thumb-mode(,| |$)}} +// CHECK-NOT: Enabled features diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 3d06677d1706b..5440e1a3cdbae 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2425,6 +2425,23 @@ void AsmPrinter::emitFunctionBody() { << " instructions in function"; ORE->emit(R); + if (ORE->allowExtraAnalysis("target-features")) { + const Function &F = MF->getFunction(); + std::string FunctionName; + raw_string_ostream OS(FunctionName); + F.printAsOperand(OS, /*PrintType=*/false); + + MachineOptimizationRemarkAnalysis Remark( + "target-features", "EnabledFeatures", F.getSubprogram(), &MF->front()); + Remark << "Enabled features for " << ore::NV("Function", FunctionName) + << ": "; + // The processor feature table is sorted by feature name. + ListSeparator LS(","); + for (const auto *Feature : MF->getSubtarget().getEnabledProcessorFeatures()) + Remark << LS << ore::NV("Feature", Feature->key()); + ORE->emit(Remark); + } + // If the function is empty and the object file uses .subsections_via_symbols, // then we need to emit *something* to the function body to prevent the // labels from collapsing together. Just emit a noop. diff --git a/llvm/test/CodeGen/AArch64/optimization-remark-target-features.ll b/llvm/test/CodeGen/AArch64/optimization-remark-target-features.ll new file mode 100644 index 0000000000000..ebf1ce000789c --- /dev/null +++ b/llvm/test/CodeGen/AArch64/optimization-remark-target-features.ll @@ -0,0 +1,45 @@ +; RUN: llc -mtriple=aarch64-linux-gnu -mcpu=generic -pass-remarks-analysis=target-features %s -o /dev/null 2>&1 | FileCheck %s +; RUN: llc -mtriple=aarch64-linux-gnu -mcpu=generic -mattr=+sve2 -pass-remarks-analysis=target-features %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=COMMAND +; RUN: llc -mtriple=aarch64-linux-gnu -mcpu=generic -pass-remarks-output=- -pass-remarks-filter=target-features %s -o /dev/null | FileCheck %s --check-prefix=YAML + +; CPU defaults, implications and explicit disabling are resolved per function. +define void @baseline() { ret void } +define void @enabled() "target-features"="+sve2" { ret void } +define void @disabled() "target-features"="+sve2,-sve" { ret void } +define void @cpu() "target-cpu"="neoverse-v1" { ret void } +define void @baseline_again() { ret void } +define void @"escaped\0Aname"() { ret void } + +; Declarations and aliases do not create machine functions. +declare void @declaration() +@alias = alias void (), ptr @baseline + +; The baseline is unchanged after functions with custom attributes. +; CHECK-NOT: Enabled features +; CHECK: remark: <unknown>:0:0: Enabled features for @baseline: [[BASELINE:enable-select-opt,ete,fixed-load-latency-4,fp-armv8,fuse-adrp-add,fuse-aes,neon,trbe,use-postra-scheduler]]{{$}} +; CHECK-NEXT: remark: <unknown>:0:0: Enabled features for @enabled: {{([^,]+,)*}}fp-armv8,fullfp16,{{([^,]+,)*}}sve,sve2{{(,.*)?$}} +; CHECK-NEXT: remark: <unknown>:0:0: Enabled features for @disabled: +; CHECK-NOT: {{(^|[ ,])(sve|sve2)(,|$)}} +; CHECK-NEXT: remark: <unknown>:0:0: Enabled features for @cpu: {{([^,]+,)*}}bf16,{{([^,]+,)*}}sve{{(,.*)?$}} +; CHECK-NEXT: remark: <unknown>:0:0: Enabled features for @baseline_again: [[BASELINE]]{{$}} +; CHECK-NEXT: remark: <unknown>:0:0: Enabled features for @"escaped\0Aname": [[BASELINE]]{{$}} +; CHECK-NOT: Enabled features + +; llc appends -mattr to existing function attributes, so the command line +; re-enables features explicitly disabled by the IR. +; COMMAND: remark: <unknown>:0:0: Enabled features for @baseline: {{([^,]+,)*}}sve,sve2{{(,.*)?$}} +; COMMAND: remark: <unknown>:0:0: Enabled features for @disabled: {{([^,]+,)*}}sve,sve2{{(,.*)?$}} + +; Saved analysis remarks expose individual features as structured arguments. +; YAML: --- !Analysis +; YAML-NEXT: Pass: target-features +; YAML-NEXT: Name: EnabledFeatures +; YAML-NEXT: Function: baseline +; YAML: - Feature: fp-armv8 +; YAML: Function: enabled +; YAML: - Feature: fullfp16 +; YAML: - Feature: sve{{$}} +; YAML: - Feature: sve2{{$}} +; YAML: Function: disabled +; YAML-NOT: - Feature: {{sve2?$}} +; YAML: ... diff --git a/llvm/test/CodeGen/ARM/optimization-remark-target-features.ll b/llvm/test/CodeGen/ARM/optimization-remark-target-features.ll new file mode 100644 index 0000000000000..6182fb5e70e44 --- /dev/null +++ b/llvm/test/CodeGen/ARM/optimization-remark-target-features.ll @@ -0,0 +1,30 @@ +; RUN: llc -mtriple=armv7-linux-gnueabi -mcpu=generic -pass-remarks-analysis=target-features %s -o /dev/null 2>&1 | FileCheck %s +; RUN: llc -mtriple=armv7-linux-gnueabi -mcpu=generic -mattr=+neon -pass-remarks-analysis=target-features %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=COMMAND + +; CPU defaults, implications and explicit disabling are resolved per function. +define void @baseline() { ret void } +define void @enabled() "target-features"="+neon" { ret void } +define void @disabled() "target-features"="+neon,-vfp3" { ret void } +define void @cpu() "target-cpu"="cortex-a8" { ret void } +define void @baseline_again() { ret void } +define void @"escaped\0Aname"() { ret void } + +; Declarations and aliases do not create machine functions. +declare void @declaration() +@alias = alias void (), ptr @baseline + +; The baseline is unchanged after functions with custom attributes. +; CHECK-NOT: Enabled features +; CHECK: remark: <unknown>:0:0: Enabled features for @baseline: [[BASELINE:.*]] +; CHECK-NEXT: remark: <unknown>:0:0: Enabled features for @enabled: {{([^,]+,)*}}neon,{{([^,]+,)*}}vfp2,{{([^,]+,)*}}vfp3{{(,.*)?$}} +; CHECK-NEXT: remark: <unknown>:0:0: Enabled features for @disabled: +; CHECK-NOT: {{(^|[ ,])(neon|vfp3)(,|$)}} +; CHECK-NEXT: remark: <unknown>:0:0: Enabled features for @cpu: {{([^,]+,)*}}neon,{{([^,]+,)*}}vfp3{{(,.*)?$}} +; CHECK-NEXT: remark: <unknown>:0:0: Enabled features for @baseline_again: [[BASELINE]]{{$}} +; CHECK-NEXT: remark: <unknown>:0:0: Enabled features for @"escaped\0Aname": [[BASELINE]]{{$}} +; CHECK-NOT: Enabled features + +; llc appends -mattr to existing function attributes, so the command line +; re-enables features explicitly disabled by the IR. +; COMMAND: remark: <unknown>:0:0: Enabled features for @baseline: {{([^,]+,)*}}neon{{(,.*)?$}} +; COMMAND: remark: <unknown>:0:0: Enabled features for @disabled: {{([^,]+,)*}}neon{{(,.*)?$}} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
