[flang-commits] [clang] [flang] [flang] Emit target features for PPC (PR #169860)
Kelvin Li via flang-commits
flang-commits at lists.llvm.org
Thu Nov 27 15:28:46 PST 2025
https://github.com/kkwli updated https://github.com/llvm/llvm-project/pull/169860
>From dce9682ebe8fbd85121afe2aae1c95a37ec71fa3 Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Mon, 20 Oct 2025 09:19:40 -0400
Subject: [PATCH 1/3] [flang] Emit target features for PPC
---
clang/lib/Driver/ToolChains/Flang.cpp | 1 +
flang/include/flang/Frontend/TargetOptions.h | 3 +
flang/lib/Frontend/CompilerInstance.cpp | 72 ++++++++++++++++++-
flang/lib/Lower/Bridge.cpp | 2 +-
.../Driver/target-cpu-features-invalid.f90 | 17 +++--
flang/test/Lower/target-features-ppc.f90 | 15 ++++
6 files changed, 100 insertions(+), 10 deletions(-)
create mode 100644 flang/test/Lower/target-features-ppc.f90
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 438de23be0103..4bb7612999d40 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -544,6 +544,7 @@ void Flang::addTargetOptions(const ArgList &Args,
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
+ getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
AddPPCTargetArgs(Args, CmdArgs);
break;
case llvm::Triple::loongarch64:
diff --git a/flang/include/flang/Frontend/TargetOptions.h b/flang/include/flang/Frontend/TargetOptions.h
index f6e5634d5a995..96b94c5f98965 100644
--- a/flang/include/flang/Frontend/TargetOptions.h
+++ b/flang/include/flang/Frontend/TargetOptions.h
@@ -42,6 +42,9 @@ class TargetOptions {
/// the command line.
std::vector<std::string> featuresAsWritten;
+ /// The default target features.
+ std::string targetFeatureStr;
+
/// The real KINDs disabled for this target
std::vector<int> disabledRealKinds;
diff --git a/flang/lib/Frontend/CompilerInstance.cpp b/flang/lib/Frontend/CompilerInstance.cpp
index 5920ed82114f8..f9f6417aaf815 100644
--- a/flang/lib/Frontend/CompilerInstance.cpp
+++ b/flang/lib/Frontend/CompilerInstance.cpp
@@ -28,6 +28,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/PPCTargetParser.h"
#include "llvm/TargetParser/TargetParser.h"
#include "llvm/TargetParser/Triple.h"
@@ -318,8 +319,67 @@ getExplicitAndImplicitNVPTXTargetFeatures(clang::DiagnosticsEngine &diags,
return llvm::join(featuresVec, ",");
}
+enum ppcCPU {prePwr8, prePwr10};
+static std::optional<ppcCPU> ppcType(std::string &cpu) {
+ return llvm::StringSwitch<std::optional<ppcCPU>>(cpu)
+ .Case("future", std::nullopt)
+ .Case("pwr11", std::nullopt)
+ .Case("pwr10", std::nullopt)
+ .Case("pwr9", prePwr10)
+ .Case("pwr8", prePwr10)
+ .Default(prePwr8);
+}
+
+static std::string
+getExplicitAndImplicitPPCTargetFeatures(clang::DiagnosticsEngine &diags,
+ TargetOptions &targetOpts,
+ const llvm::Triple triple) {
+ std::vector<std::string> featuresVec;
+ std::optional<llvm::StringMap<bool>> FeaturesOpt =
+ llvm::PPC::getPPCDefaultTargetFeatures(triple, targetOpts.cpu);
+ if (FeaturesOpt) {
+ for (auto &I : FeaturesOpt.value()) {
+ featuresVec.push_back(
+ (llvm::Twine(I.second ? "+" : "-") + I.first().str()).str());
+ }
+ }
+ // Check if the feature already exists.
+ for (auto v : targetOpts.featuresAsWritten) {
+ if (std::find(featuresVec.begin(), featuresVec.end(), v) ==
+ featuresVec.end()) {
+ featuresVec.push_back(v);
+ }
+ }
+
+ // Some features are not supported in earlier CPUs.
+ std::map<std::string_view, std::vector<ppcCPU>> unsupportedFeatures{
+ {"+mma", {prePwr8, prePwr10}},
+ {"+paired-vector-memops", {prePwr8, prePwr10}},
+ {"+pcrelative-memops", {prePwr8, prePwr10}},
+ {"+prefix-instrs", {prePwr8, prePwr10}},
+ {"+privileged", {prePwr8}},
+ {"+rop-protect", {prePwr8}}};
+ // Check if there are any unsupported features specified.
+ if (auto cpuType = ppcType(targetOpts.cpu)) {
+ for (auto f : unsupportedFeatures) {
+ for (auto g : f.second) {
+ if (cpuType.value() == g) {
+ if (llvm::is_contained(featuresVec, f.first)) {
+ diags.Report(clang::diag::err_opt_not_valid_on_target) << f.first;
+ return std::string();
+ }
+ }
+ }
+ }
+ }
+
+ llvm::sort(featuresVec);
+ targetOpts.targetFeatureStr = llvm::join(featuresVec, ",");
+ return targetOpts.targetFeatureStr;
+}
+
std::string CompilerInstance::getTargetFeatures() {
- const TargetOptions &targetOpts = getInvocation().getTargetOpts();
+ TargetOptions &targetOpts = getInvocation().getTargetOpts();
const llvm::Triple triple(targetOpts.triple);
// Clang does not append all target features to the clang -cc1 invocation.
@@ -334,13 +394,16 @@ std::string CompilerInstance::getTargetFeatures() {
} else if (triple.isNVPTX()) {
return getExplicitAndImplicitNVPTXTargetFeatures(getDiagnostics(),
targetOpts, triple);
+ } else if (triple.isPPC()) {
+ return getExplicitAndImplicitPPCTargetFeatures(getDiagnostics(),
+ targetOpts, triple);
}
return llvm::join(targetOpts.featuresAsWritten.begin(),
targetOpts.featuresAsWritten.end(), ",");
}
bool CompilerInstance::setUpTargetMachine() {
- const TargetOptions &targetOpts = getInvocation().getTargetOpts();
+ TargetOptions &targetOpts = getInvocation().getTargetOpts();
const std::string &theTriple = targetOpts.triple;
// Create `Target`
@@ -371,6 +434,11 @@ bool CompilerInstance::setUpTargetMachine() {
/*Reloc::Model=*/CGOpts.getRelocationModel(),
/*CodeModel::Model=*/cm, OptLevel));
assert(targetMachine && "Failed to create TargetMachine");
+
+ if (!triple.isPPC()) {
+ targetOpts.targetFeatureStr = targetMachine->getTargetFeatureString();
+ }
+
if (cm.has_value()) {
if ((cm == llvm::CodeModel::Medium || cm == llvm::CodeModel::Large) &&
triple.getArch() == llvm::Triple::x86_64) {
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 6f9dc32297272..cdeff1240cfd8 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -7159,7 +7159,7 @@ Fortran::lower::LoweringBridge::LoweringBridge(
targetOpts.atomicIgnoreDenormalMode);
fir::setAtomicFineGrainedMemory(*module, targetOpts.atomicFineGrainedMemory);
fir::setAtomicRemoteMemory(*module, targetOpts.atomicRemoteMemory);
- fir::setTargetFeatures(*module, targetMachine.getTargetFeatureString());
+ fir::setTargetFeatures(*module, targetOpts.targetFeatureStr);
fir::support::setMLIRDataLayout(*module, targetMachine.createDataLayout());
fir::setIdent(*module, Fortran::common::getFlangFullVersion());
if (cgOpts.RecordCommandLine)
diff --git a/flang/test/Driver/target-cpu-features-invalid.f90 b/flang/test/Driver/target-cpu-features-invalid.f90
index 288da8d57e81d..0b7b517944d2d 100644
--- a/flang/test/Driver/target-cpu-features-invalid.f90
+++ b/flang/test/Driver/target-cpu-features-invalid.f90
@@ -1,16 +1,19 @@
-! REQUIRES: aarch64-registered-target, amdgpu-registered-target
+! : aarch64-registered-target, amdgpu-registered-target, powerpc-registered-target
! Test that invalid cpu and features are ignored.
-! RUN: %flang_fc1 -triple aarch64-linux-gnu -target-cpu supercpu \
-! RUN: -o /dev/null -S %s 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-CPU
+! RUN: %if aarch64-registered-target %{ %flang_fc1 -triple aarch64-linux-gnu -target-cpu supercpu \
+! RUN: -o /dev/null -S %s 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-CPU %}
-! RUN: %flang_fc1 -triple aarch64-linux-gnu -target-feature +superspeed \
-! RUN: -o /dev/null -S %s 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-FEATURE
+! RUN: %if aarch64-registered-target %{ %flang_fc1 -triple aarch64-linux-gnu -target-feature +superspeed \
+! RUN: -o /dev/null -S %s 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-FEATURE %}
-! RUN: not %flang_fc1 -triple amdgcn-amd-amdhsa -target-feature +wavefrontsize32 \
-! RUN: -target-feature +wavefrontsize64 -o /dev/null -S %s 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-WAVEFRONT
+! RUN: %if amdgpu-registered-target %{ not %flang_fc1 -triple amdgcn-amd-amdhsa -target-feature +wavefrontsize32 \
+! RUN: -target-feature +wavefrontsize64 -o /dev/null -S %s 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-WAVEFRONT %}
+
+! RUN: %if powerpc-registered-target %{ not %flang_fc1 -triple powerpc64le-linux-gnu -target-feature +mma -target-cpu pwr9 -o /dev/null -S %s 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-PPC-FEATURE %}
! CHECK-INVALID-CPU: 'supercpu' is not a recognized processor for this target (ignoring processor)
! CHECK-INVALID-FEATURE: '+superspeed' is not a recognized feature for this target (ignoring feature)
! CHECK-INVALID-WAVEFRONT: 'wavefrontsize32' and 'wavefrontsize64' are mutually exclusive
+! CHECK-INVALID-PPC-FEATURE: option '+mma' cannot be specified on this target
diff --git a/flang/test/Lower/target-features-ppc.f90 b/flang/test/Lower/target-features-ppc.f90
new file mode 100644
index 0000000000000..1c3429e6936a0
--- /dev/null
+++ b/flang/test/Lower/target-features-ppc.f90
@@ -0,0 +1,15 @@
+! REQUIRES: target=powerpc{{.*}}
+! RUN: %flang_fc1 -emit-fir -target-cpu pwr10 %s -o - | FileCheck %s --check-prefixes=ALL,FEATURE
+! RUN: %flang_fc1 -emit-fir -target-cpu pwr10 -target-feature +privileged %s -o - | FileCheck %s --check-prefixes=ALL,BOTH
+
+! ALL: module attributes {
+
+! ALL: fir.target_cpu = "pwr10"
+
+! FEATURE: fir.target_features = #llvm.target_features<[
+! FEATURE: "+64bit-support", "+allow-unaligned-fp-access", "+altivec", "+bpermd", "+cmpb", "+crbits", "+crypto", "+direct-move", "+extdiv", "+fast-MFLR", "+fcpsgn", "+fpcvt", "+fprnd", "+fpu", "+fre", "+fres", "+frsqrte", "+frsqrtes", "+fsqrt", "+fuse-add-logical", "+fuse-arith-add", "+fuse-logical", "+fuse-logical-add", "+fuse-sha3", "+fuse-store", "+fusion", "+hard-float", "+icbt", "+isa-v206-instructions", "+isa-v207-instructions", "+isa-v30-instructions", "+isa-v31-instructions", "+isel", "+ldbrx", "+lfiwax", "+mfocrf", "+mma", "+paired-vector-memops", "+partword-atomics", "+pcrelative-memops", "+popcntd", "+power10-vector", "+power8-altivec", "+power8-vector", "+power9-altivec", "+power9-vector", "+ppc-postra-sched", "+ppc-prera-sched", "+predictable-select-expensive", "+prefix-instrs", "+quadword-atomics", "+recipprec", "+stfiwx", "+two-const-nr", "+vsx"
+! FEATURE: ]>
+
+! BOTH: fir.target_features = #llvm.target_features<[
+! BOTH: "+64bit-support", "+allow-unaligned-fp-access", "+altivec", "+bpermd", "+cmpb", "+crbits", "+crypto", "+direct-move", "+extdiv", "+fast-MFLR", "+fcpsgn", "+fpcvt", "+fprnd", "+fpu", "+fre", "+fres", "+frsqrte", "+frsqrtes", "+fsqrt", "+fuse-add-logical", "+fuse-arith-add", "+fuse-logical", "+fuse-logical-add", "+fuse-sha3", "+fuse-store", "+fusion", "+hard-float", "+icbt", "+isa-v206-instructions", "+isa-v207-instructions", "+isa-v30-instructions", "+isa-v31-instructions", "+isel", "+ldbrx", "+lfiwax", "+mfocrf", "+mma", "+paired-vector-memops", "+partword-atomics", "+pcrelative-memops", "+popcntd", "+power10-vector", "+power8-altivec", "+power8-vector", "+power9-altivec", "+power9-vector", "+ppc-postra-sched", "+ppc-prera-sched", "+predictable-select-expensive", "+prefix-instrs", "+privileged", "+quadword-atomics", "+recipprec", "+stfiwx", "+two-const-nr", "+vsx"
+! BOTH: ]>
>From 848ce41939eda4a158a14b245eef41dad2471d3d Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Thu, 27 Nov 2025 18:11:52 -0500
Subject: [PATCH 2/3] remove comment lines
---
flang/test/Driver/target-cpu-features-invalid.f90 | 2 --
1 file changed, 2 deletions(-)
diff --git a/flang/test/Driver/target-cpu-features-invalid.f90 b/flang/test/Driver/target-cpu-features-invalid.f90
index 0b7b517944d2d..664c183ff692b 100644
--- a/flang/test/Driver/target-cpu-features-invalid.f90
+++ b/flang/test/Driver/target-cpu-features-invalid.f90
@@ -1,5 +1,3 @@
-! : aarch64-registered-target, amdgpu-registered-target, powerpc-registered-target
-
! Test that invalid cpu and features are ignored.
! RUN: %if aarch64-registered-target %{ %flang_fc1 -triple aarch64-linux-gnu -target-cpu supercpu \
>From 000dc93ea29e07e33b8d19f7cb5ae0221f0fe12d Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Thu, 27 Nov 2025 18:26:46 -0500
Subject: [PATCH 3/3] fix format
---
flang/lib/Frontend/CompilerInstance.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/flang/lib/Frontend/CompilerInstance.cpp b/flang/lib/Frontend/CompilerInstance.cpp
index f9f6417aaf815..8174ae0cfaade 100644
--- a/flang/lib/Frontend/CompilerInstance.cpp
+++ b/flang/lib/Frontend/CompilerInstance.cpp
@@ -319,7 +319,7 @@ getExplicitAndImplicitNVPTXTargetFeatures(clang::DiagnosticsEngine &diags,
return llvm::join(featuresVec, ",");
}
-enum ppcCPU {prePwr8, prePwr10};
+enum ppcCPU { prePwr8, prePwr10 };
static std::optional<ppcCPU> ppcType(std::string &cpu) {
return llvm::StringSwitch<std::optional<ppcCPU>>(cpu)
.Case("future", std::nullopt)
@@ -395,8 +395,8 @@ std::string CompilerInstance::getTargetFeatures() {
return getExplicitAndImplicitNVPTXTargetFeatures(getDiagnostics(),
targetOpts, triple);
} else if (triple.isPPC()) {
- return getExplicitAndImplicitPPCTargetFeatures(getDiagnostics(),
- targetOpts, triple);
+ return getExplicitAndImplicitPPCTargetFeatures(getDiagnostics(), targetOpts,
+ triple);
}
return llvm::join(targetOpts.featuresAsWritten.begin(),
targetOpts.featuresAsWritten.end(), ",");
More information about the flang-commits
mailing list