Skip to content

Commit 837bff1

Browse files
authored
[Flang][Lower] Attach target_cpu and target_features attributes to MLIR functions (#78289)
This patch forwards the target CPU and features information from the Flang frontend to MLIR func.func operation attributes, which are later used to populate the target_cpu and target_features llvm.func attributes. This is achieved in two stages: 1. Introduce the `fir.target_cpu` and `fir.target_features` module attributes with information from the target machine immediately after the initial creation of the MLIR module in the lowering bridge. 2. Update the target rewrite flang pass to get this information from the module and pass it along to all func.func MLIR operations, respectively as attributes named `target_cpu` and `target_features`. These attributes will be automatically picked up during Func to LLVM dialect lowering and used to initialize the corresponding llvm.func named attributes. The target rewrite and FIR to LLVM lowering passes are updated with the ability to override these module attributes, and the `CodeGenSpecifics` optimizer class is augmented to make this information available to target-specific MLIR transformations. This completes a full flow by which target CPU and features make it all the way from compiler options to LLVM IR function attributes.
1 parent c366877 commit 837bff1

File tree

19 files changed

+290
-51
lines changed

19 files changed

+290
-51
lines changed

flang/include/flang/Lower/Bridge.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#include <set>
2525

2626
namespace llvm {
27-
class DataLayout;
27+
class TargetMachine;
2828
} // namespace llvm
2929

3030
namespace Fortran {
@@ -65,11 +65,11 @@ class LoweringBridge {
6565
const Fortran::lower::LoweringOptions &loweringOptions,
6666
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
6767
const Fortran::common::LanguageFeatureControl &languageFeatures,
68-
const llvm::DataLayout *dataLayout = nullptr) {
68+
const llvm::TargetMachine &targetMachine) {
6969
return LoweringBridge(ctx, semanticsContext, defaultKinds, intrinsics,
7070
targetCharacteristics, allCooked, triple, kindMap,
7171
loweringOptions, envDefaults, languageFeatures,
72-
dataLayout);
72+
targetMachine);
7373
}
7474

7575
//===--------------------------------------------------------------------===//
@@ -148,7 +148,7 @@ class LoweringBridge {
148148
const Fortran::lower::LoweringOptions &loweringOptions,
149149
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
150150
const Fortran::common::LanguageFeatureControl &languageFeatures,
151-
const llvm::DataLayout *dataLayout);
151+
const llvm::TargetMachine &targetMachine);
152152
LoweringBridge() = delete;
153153
LoweringBridge(const LoweringBridge &) = delete;
154154

flang/include/flang/Optimizer/CodeGen/CGPasses.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ def FIRToLLVMLowering : Pass<"fir-to-llvm-ir", "mlir::ModuleOp"> {
2929
"Override module's target triple.">,
3030
Option<"forcedDataLayout", "datalayout", "std::string", /*default=*/"",
3131
"Override module's data layout.">,
32+
Option<"forcedTargetCPU", "target-cpu", "std::string", /*default=*/"",
33+
"Override module's target CPU.">,
34+
Option<"forcedTargetFeatures", "target-features", "std::string",
35+
/*default=*/"", "Override module's target features.">,
3236
Option<"applyTBAA", "apply-tbaa", "bool", /*default=*/"false",
3337
"Attach TBAA tags to memory accessing operations.">
3438
];
@@ -60,6 +64,10 @@ def TargetRewritePass : Pass<"target-rewrite", "mlir::ModuleOp"> {
6064
let options = [
6165
Option<"forcedTargetTriple", "target", "std::string", /*default=*/"",
6266
"Override module's target triple.">,
67+
Option<"forcedTargetCPU", "target-cpu", "std::string", /*default=*/"",
68+
"Override module's target CPU.">,
69+
Option<"forcedTargetFeatures", "target-features", "std::string",
70+
/*default=*/"", "Override module's target features.">,
6371
Option<"noCharacterConversion", "no-character-conversion",
6472
"bool", /*default=*/"false",
6573
"Disable target-specific conversion of CHARACTER.">,

flang/include/flang/Optimizer/CodeGen/Target.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "flang/Optimizer/Dialect/FIRType.h"
1717
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
18+
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
1819
#include "mlir/IR/BuiltinTypes.h"
1920
#include "llvm/TargetParser/Triple.h"
2021
#include <memory>
@@ -70,17 +71,19 @@ class CodeGenSpecifics {
7071
using TypeAndAttr = std::tuple<mlir::Type, Attributes>;
7172
using Marshalling = std::vector<TypeAndAttr>;
7273

73-
static std::unique_ptr<CodeGenSpecifics> get(mlir::MLIRContext *ctx,
74-
llvm::Triple &&trp,
75-
KindMapping &&kindMap,
76-
const mlir::DataLayout &dl);
74+
static std::unique_ptr<CodeGenSpecifics>
75+
get(mlir::MLIRContext *ctx, llvm::Triple &&trp, KindMapping &&kindMap,
76+
llvm::StringRef targetCPU, mlir::LLVM::TargetFeaturesAttr targetFeatures,
77+
const mlir::DataLayout &dl);
7778

7879
static TypeAndAttr getTypeAndAttr(mlir::Type t) { return TypeAndAttr{t, {}}; }
7980

8081
CodeGenSpecifics(mlir::MLIRContext *ctx, llvm::Triple &&trp,
81-
KindMapping &&kindMap, const mlir::DataLayout &dl)
82+
KindMapping &&kindMap, llvm::StringRef targetCPU,
83+
mlir::LLVM::TargetFeaturesAttr targetFeatures,
84+
const mlir::DataLayout &dl)
8285
: context{*ctx}, triple{std::move(trp)}, kindMap{std::move(kindMap)},
83-
dataLayout{&dl} {}
86+
targetCPU{targetCPU}, targetFeatures{targetFeatures}, dataLayout{&dl} {}
8487
CodeGenSpecifics() = delete;
8588
virtual ~CodeGenSpecifics() {}
8689

@@ -161,6 +164,12 @@ class CodeGenSpecifics {
161164
// Returns width in bits of C/C++ 'int' type size.
162165
virtual unsigned char getCIntTypeWidth() const = 0;
163166

167+
llvm::StringRef getTargetCPU() const { return targetCPU; }
168+
169+
mlir::LLVM::TargetFeaturesAttr getTargetFeatures() const {
170+
return targetFeatures;
171+
}
172+
164173
const mlir::DataLayout &getDataLayout() const {
165174
assert(dataLayout && "dataLayout must be set");
166175
return *dataLayout;
@@ -170,6 +179,8 @@ class CodeGenSpecifics {
170179
mlir::MLIRContext &context;
171180
llvm::Triple triple;
172181
KindMapping kindMap;
182+
llvm::StringRef targetCPU;
183+
mlir::LLVM::TargetFeaturesAttr targetFeatures;
173184
const mlir::DataLayout *dataLayout = nullptr;
174185
};
175186

flang/include/flang/Optimizer/Dialect/Support/FIRContext.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef FORTRAN_OPTIMIZER_SUPPORT_FIRCONTEXT_H
1818
#define FORTRAN_OPTIMIZER_SUPPORT_FIRCONTEXT_H
1919

20+
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
2021
#include "llvm/ADT/StringRef.h"
2122
#include "llvm/TargetParser/Triple.h"
2223

@@ -50,6 +51,19 @@ KindMapping getKindMapping(mlir::ModuleOp mod);
5051
/// If a ModuleOp cannot be reached, the function returns default KindMapping.
5152
KindMapping getKindMapping(mlir::Operation *op);
5253

54+
/// Set the target CPU for the module. `cpu` must not be deallocated while
55+
/// module `mod` is still live.
56+
void setTargetCPU(mlir::ModuleOp mod, llvm::StringRef cpu);
57+
58+
/// Get the target CPU string from the Module or return a null reference.
59+
llvm::StringRef getTargetCPU(mlir::ModuleOp mod);
60+
61+
/// Set the target features for the module.
62+
void setTargetFeatures(mlir::ModuleOp mod, llvm::StringRef features);
63+
64+
/// Get the target features from the Module.
65+
mlir::LLVM::TargetFeaturesAttr getTargetFeatures(mlir::ModuleOp mod);
66+
5367
/// Helper for determining the target from the host, etc. Tools may use this
5468
/// function to provide a consistent interpretation of the `--target=<string>`
5569
/// command-line option.

flang/lib/Frontend/FrontendActions.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,16 +285,14 @@ bool CodeGenAction::beginSourceFileAction() {
285285
ci.getSemanticsContext().defaultKinds();
286286
fir::KindMapping kindMap(mlirCtx.get(), llvm::ArrayRef<fir::KindTy>{
287287
fir::fromDefaultKinds(defKinds)});
288-
const llvm::DataLayout &dl = targetMachine.createDataLayout();
289-
290288
lower::LoweringBridge lb = Fortran::lower::LoweringBridge::create(
291289
*mlirCtx, ci.getSemanticsContext(), defKinds,
292290
ci.getSemanticsContext().intrinsics(),
293291
ci.getSemanticsContext().targetCharacteristics(),
294292
ci.getParsing().allCooked(), ci.getInvocation().getTargetOpts().triple,
295293
kindMap, ci.getInvocation().getLoweringOpts(),
296294
ci.getInvocation().getFrontendOpts().envDefaults,
297-
ci.getInvocation().getFrontendOpts().features, &dl);
295+
ci.getInvocation().getFrontendOpts().features, targetMachine);
298296

299297
// Fetch module from lb, so we can set
300298
mlirModule = std::make_unique<mlir::ModuleOp>(lb.getModule());

flang/lib/Lower/Bridge.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include "llvm/Support/ErrorHandling.h"
6565
#include "llvm/Support/FileSystem.h"
6666
#include "llvm/Support/Path.h"
67+
#include "llvm/Target/TargetMachine.h"
6768
#include <optional>
6869

6970
#define DEBUG_TYPE "flang-lower-bridge"
@@ -5092,7 +5093,7 @@ Fortran::lower::LoweringBridge::LoweringBridge(
50925093
const Fortran::lower::LoweringOptions &loweringOptions,
50935094
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
50945095
const Fortran::common::LanguageFeatureControl &languageFeatures,
5095-
const llvm::DataLayout *dataLayout)
5096+
const llvm::TargetMachine &targetMachine)
50965097
: semanticsContext{semanticsContext}, defaultKinds{defaultKinds},
50975098
intrinsics{intrinsics}, targetCharacteristics{targetCharacteristics},
50985099
cooked{&cooked}, context{context}, kindMap{kindMap},
@@ -5148,6 +5149,8 @@ Fortran::lower::LoweringBridge::LoweringBridge(
51485149
assert(module.get() && "module was not created");
51495150
fir::setTargetTriple(*module.get(), triple);
51505151
fir::setKindMapping(*module.get(), kindMap);
5151-
if (dataLayout)
5152-
fir::support::setMLIRDataLayout(*module.get(), *dataLayout);
5152+
fir::setTargetCPU(*module.get(), targetMachine.getTargetCPU());
5153+
fir::setTargetFeatures(*module.get(), targetMachine.getTargetFeatureString());
5154+
fir::support::setMLIRDataLayout(*module.get(),
5155+
targetMachine.createDataLayout());
51535156
}

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3879,6 +3879,12 @@ class FIRToLLVMLowering
38793879
fir::support::setMLIRDataLayout(mod, dl);
38803880
}
38813881

3882+
if (!forcedTargetCPU.empty())
3883+
fir::setTargetCPU(mod, forcedTargetCPU);
3884+
3885+
if (!forcedTargetFeatures.empty())
3886+
fir::setTargetFeatures(mod, forcedTargetFeatures);
3887+
38823888
// Run dynamic pass pipeline for converting Math dialect
38833889
// operations into other dialects (llvm, func, etc.).
38843890
// Some conversions of Math operations cannot be done

flang/lib/Optimizer/CodeGen/Target.cpp

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,51 +1057,57 @@ struct TargetLoongArch64 : public GenericTarget<TargetLoongArch64> {
10571057
// TODO: Add other targets to this file as needed.
10581058
std::unique_ptr<fir::CodeGenSpecifics>
10591059
fir::CodeGenSpecifics::get(mlir::MLIRContext *ctx, llvm::Triple &&trp,
1060-
KindMapping &&kindMap, const mlir::DataLayout &dl) {
1060+
KindMapping &&kindMap, llvm::StringRef targetCPU,
1061+
mlir::LLVM::TargetFeaturesAttr targetFeatures,
1062+
const mlir::DataLayout &dl) {
10611063
switch (trp.getArch()) {
10621064
default:
10631065
break;
10641066
case llvm::Triple::ArchType::x86:
10651067
if (trp.isOSWindows())
10661068
return std::make_unique<TargetI386Win>(ctx, std::move(trp),
1067-
std::move(kindMap), dl);
1069+
std::move(kindMap), targetCPU,
1070+
targetFeatures, dl);
10681071
else
10691072
return std::make_unique<TargetI386>(ctx, std::move(trp),
1070-
std::move(kindMap), dl);
1073+
std::move(kindMap), targetCPU,
1074+
targetFeatures, dl);
10711075
case llvm::Triple::ArchType::x86_64:
10721076
if (trp.isOSWindows())
10731077
return std::make_unique<TargetX86_64Win>(ctx, std::move(trp),
1074-
std::move(kindMap), dl);
1078+
std::move(kindMap), targetCPU,
1079+
targetFeatures, dl);
10751080
else
10761081
return std::make_unique<TargetX86_64>(ctx, std::move(trp),
1077-
std::move(kindMap), dl);
1082+
std::move(kindMap), targetCPU,
1083+
targetFeatures, dl);
10781084
case llvm::Triple::ArchType::aarch64:
1079-
return std::make_unique<TargetAArch64>(ctx, std::move(trp),
1080-
std::move(kindMap), dl);
1085+
return std::make_unique<TargetAArch64>(
1086+
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
10811087
case llvm::Triple::ArchType::ppc64:
1082-
return std::make_unique<TargetPPC64>(ctx, std::move(trp),
1083-
std::move(kindMap), dl);
1088+
return std::make_unique<TargetPPC64>(
1089+
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
10841090
case llvm::Triple::ArchType::ppc64le:
1085-
return std::make_unique<TargetPPC64le>(ctx, std::move(trp),
1086-
std::move(kindMap), dl);
1091+
return std::make_unique<TargetPPC64le>(
1092+
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
10871093
case llvm::Triple::ArchType::sparc:
1088-
return std::make_unique<TargetSparc>(ctx, std::move(trp),
1089-
std::move(kindMap), dl);
1094+
return std::make_unique<TargetSparc>(
1095+
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
10901096
case llvm::Triple::ArchType::sparcv9:
1091-
return std::make_unique<TargetSparcV9>(ctx, std::move(trp),
1092-
std::move(kindMap), dl);
1097+
return std::make_unique<TargetSparcV9>(
1098+
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
10931099
case llvm::Triple::ArchType::riscv64:
1094-
return std::make_unique<TargetRISCV64>(ctx, std::move(trp),
1095-
std::move(kindMap), dl);
1100+
return std::make_unique<TargetRISCV64>(
1101+
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
10961102
case llvm::Triple::ArchType::amdgcn:
1097-
return std::make_unique<TargetAMDGPU>(ctx, std::move(trp),
1098-
std::move(kindMap), dl);
1103+
return std::make_unique<TargetAMDGPU>(
1104+
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
10991105
case llvm::Triple::ArchType::nvptx64:
1100-
return std::make_unique<TargetNVPTX>(ctx, std::move(trp),
1101-
std::move(kindMap), dl);
1106+
return std::make_unique<TargetNVPTX>(
1107+
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
11021108
case llvm::Triple::ArchType::loongarch64:
1103-
return std::make_unique<TargetLoongArch64>(ctx, std::move(trp),
1104-
std::move(kindMap), dl);
1109+
return std::make_unique<TargetLoongArch64>(
1110+
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
11051111
}
11061112
TODO(mlir::UnknownLoc::get(ctx), "target not implemented");
11071113
}

flang/lib/Optimizer/CodeGen/TargetRewrite.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase<TargetRewrite> {
9090
if (!forcedTargetTriple.empty())
9191
fir::setTargetTriple(mod, forcedTargetTriple);
9292

93+
if (!forcedTargetCPU.empty())
94+
fir::setTargetCPU(mod, forcedTargetCPU);
95+
96+
if (!forcedTargetFeatures.empty())
97+
fir::setTargetFeatures(mod, forcedTargetFeatures);
98+
9399
// TargetRewrite will require querying the type storage sizes, if it was
94100
// not set already, create a DataLayoutSpec for the ModuleOp now.
95101
std::optional<mlir::DataLayout> dl =
@@ -102,9 +108,9 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase<TargetRewrite> {
102108
return;
103109
}
104110

105-
auto specifics =
106-
fir::CodeGenSpecifics::get(mod.getContext(), fir::getTargetTriple(mod),
107-
fir::getKindMapping(mod), *dl);
111+
auto specifics = fir::CodeGenSpecifics::get(
112+
mod.getContext(), fir::getTargetTriple(mod), fir::getKindMapping(mod),
113+
fir::getTargetCPU(mod), fir::getTargetFeatures(mod), *dl);
108114

109115
setMembers(specifics.get(), &rewriter, &*dl);
110116

@@ -666,8 +672,21 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase<TargetRewrite> {
666672
/// As the type signature is being changed, this must also update the
667673
/// function itself to use any new arguments, etc.
668674
mlir::LogicalResult convertTypes(mlir::ModuleOp mod) {
669-
for (auto fn : mod.getOps<mlir::func::FuncOp>())
675+
mlir::MLIRContext *ctx = mod->getContext();
676+
auto targetCPU = specifics->getTargetCPU();
677+
mlir::StringAttr targetCPUAttr =
678+
targetCPU.empty() ? nullptr : mlir::StringAttr::get(ctx, targetCPU);
679+
auto targetFeaturesAttr = specifics->getTargetFeatures();
680+
681+
for (auto fn : mod.getOps<mlir::func::FuncOp>()) {
682+
if (targetCPUAttr)
683+
fn->setAttr("target_cpu", targetCPUAttr);
684+
685+
if (targetFeaturesAttr)
686+
fn->setAttr("target_features", targetFeaturesAttr);
687+
670688
convertSignature(fn);
689+
}
671690
return mlir::success();
672691
}
673692

flang/lib/Optimizer/CodeGen/TypeConverter.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ LLVMTypeConverter::LLVMTypeConverter(mlir::ModuleOp module, bool applyTBAA,
3232
const mlir::DataLayout &dl)
3333
: mlir::LLVMTypeConverter(module.getContext()),
3434
kindMapping(getKindMapping(module)),
35-
specifics(CodeGenSpecifics::get(module.getContext(),
36-
getTargetTriple(module),
37-
getKindMapping(module), dl)),
35+
specifics(CodeGenSpecifics::get(
36+
module.getContext(), getTargetTriple(module), getKindMapping(module),
37+
getTargetCPU(module), getTargetFeatures(module), dl)),
3838
tbaaBuilder(std::make_unique<TBAABuilder>(module->getContext(), applyTBAA,
3939
forceUnifiedTBAATree)) {
4040
LLVM_DEBUG(llvm::dbgs() << "FIR type converter\n");

flang/lib/Optimizer/Dialect/Support/FIRContext.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,42 @@ fir::KindMapping fir::getKindMapping(mlir::Operation *op) {
6060
return getKindMapping(moduleOp);
6161
}
6262

63+
static constexpr const char *targetCpuName = "fir.target_cpu";
64+
65+
void fir::setTargetCPU(mlir::ModuleOp mod, llvm::StringRef cpu) {
66+
if (cpu.empty())
67+
return;
68+
69+
auto *ctx = mod.getContext();
70+
mod->setAttr(targetCpuName, mlir::StringAttr::get(ctx, cpu));
71+
}
72+
73+
llvm::StringRef fir::getTargetCPU(mlir::ModuleOp mod) {
74+
if (auto attr = mod->getAttrOfType<mlir::StringAttr>(targetCpuName))
75+
return attr.getValue();
76+
77+
return {};
78+
}
79+
80+
static constexpr const char *targetFeaturesName = "fir.target_features";
81+
82+
void fir::setTargetFeatures(mlir::ModuleOp mod, llvm::StringRef features) {
83+
if (features.empty())
84+
return;
85+
86+
auto *ctx = mod.getContext();
87+
mod->setAttr(targetFeaturesName,
88+
mlir::LLVM::TargetFeaturesAttr::get(ctx, features));
89+
}
90+
91+
mlir::LLVM::TargetFeaturesAttr fir::getTargetFeatures(mlir::ModuleOp mod) {
92+
if (auto attr = mod->getAttrOfType<mlir::LLVM::TargetFeaturesAttr>(
93+
targetFeaturesName))
94+
return attr;
95+
96+
return {};
97+
}
98+
6399
std::string fir::determineTargetTriple(llvm::StringRef triple) {
64100
// Treat "" or "default" as stand-ins for the default machine.
65101
if (triple.empty() || triple == "default")

flang/test/Driver/save-mlir-temps.f90

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@
5151
! Content to check from the MLIR outputs
5252
!--------------------------
5353
! MLIR-FIR-NOT: llvm.func
54-
! MLIR-FIR: func.func @{{.*}}main(){{.*}}{
54+
! MLIR-FIR: func.func @{{.*}}main(){{.*}}
5555

56-
! MLIR-FIR-NOT: func.func
57-
! MLIR-LLVMIR: llvm.func @{{.*}}main(){{.*}}{
56+
! MLIR-LLVMIR-NOT: func.func
57+
! MLIR-LLVMIR: llvm.func @{{.*}}main(){{.*}}
5858

5959
end program

0 commit comments

Comments
 (0)