Skip to content

[Flang][Lower] Attach target_cpu and target_features attributes to MLIR functions #78289

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 30, 2024
Merged
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
8 changes: 4 additions & 4 deletions flang/include/flang/Lower/Bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include <set>

namespace llvm {
class DataLayout;
class TargetMachine;
} // namespace llvm

namespace Fortran {
Expand Down Expand Up @@ -65,11 +65,11 @@ class LoweringBridge {
const Fortran::lower::LoweringOptions &loweringOptions,
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
const Fortran::common::LanguageFeatureControl &languageFeatures,
const llvm::DataLayout *dataLayout = nullptr) {
const llvm::TargetMachine &targetMachine) {
return LoweringBridge(ctx, semanticsContext, defaultKinds, intrinsics,
targetCharacteristics, allCooked, triple, kindMap,
loweringOptions, envDefaults, languageFeatures,
dataLayout);
targetMachine);
}

//===--------------------------------------------------------------------===//
Expand Down Expand Up @@ -148,7 +148,7 @@ class LoweringBridge {
const Fortran::lower::LoweringOptions &loweringOptions,
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
const Fortran::common::LanguageFeatureControl &languageFeatures,
const llvm::DataLayout *dataLayout);
const llvm::TargetMachine &targetMachine);
LoweringBridge() = delete;
LoweringBridge(const LoweringBridge &) = delete;

Expand Down
8 changes: 8 additions & 0 deletions flang/include/flang/Optimizer/CodeGen/CGPasses.td
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ def FIRToLLVMLowering : Pass<"fir-to-llvm-ir", "mlir::ModuleOp"> {
"Override module's target triple.">,
Option<"forcedDataLayout", "datalayout", "std::string", /*default=*/"",
"Override module's data layout.">,
Option<"forcedTargetCPU", "target-cpu", "std::string", /*default=*/"",
"Override module's target CPU.">,
Option<"forcedTargetFeatures", "target-features", "std::string",
/*default=*/"", "Override module's target features.">,
Option<"applyTBAA", "apply-tbaa", "bool", /*default=*/"false",
"Attach TBAA tags to memory accessing operations.">
];
Expand Down Expand Up @@ -60,6 +64,10 @@ def TargetRewritePass : Pass<"target-rewrite", "mlir::ModuleOp"> {
let options = [
Option<"forcedTargetTriple", "target", "std::string", /*default=*/"",
"Override module's target triple.">,
Option<"forcedTargetCPU", "target-cpu", "std::string", /*default=*/"",
"Override module's target CPU.">,
Option<"forcedTargetFeatures", "target-features", "std::string",
/*default=*/"", "Override module's target features.">,
Option<"noCharacterConversion", "no-character-conversion",
"bool", /*default=*/"false",
"Disable target-specific conversion of CHARACTER.">,
Expand Down
23 changes: 17 additions & 6 deletions flang/include/flang/Optimizer/CodeGen/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/IR/BuiltinTypes.h"
#include "llvm/TargetParser/Triple.h"
#include <memory>
Expand Down Expand Up @@ -70,17 +71,19 @@ class CodeGenSpecifics {
using TypeAndAttr = std::tuple<mlir::Type, Attributes>;
using Marshalling = std::vector<TypeAndAttr>;

static std::unique_ptr<CodeGenSpecifics> get(mlir::MLIRContext *ctx,
llvm::Triple &&trp,
KindMapping &&kindMap,
const mlir::DataLayout &dl);
static std::unique_ptr<CodeGenSpecifics>
get(mlir::MLIRContext *ctx, llvm::Triple &&trp, KindMapping &&kindMap,
llvm::StringRef targetCPU, mlir::LLVM::TargetFeaturesAttr targetFeatures,
const mlir::DataLayout &dl);

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

CodeGenSpecifics(mlir::MLIRContext *ctx, llvm::Triple &&trp,
KindMapping &&kindMap, const mlir::DataLayout &dl)
KindMapping &&kindMap, llvm::StringRef targetCPU,
mlir::LLVM::TargetFeaturesAttr targetFeatures,
const mlir::DataLayout &dl)
: context{*ctx}, triple{std::move(trp)}, kindMap{std::move(kindMap)},
dataLayout{&dl} {}
targetCPU{targetCPU}, targetFeatures{targetFeatures}, dataLayout{&dl} {}
CodeGenSpecifics() = delete;
virtual ~CodeGenSpecifics() {}

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

llvm::StringRef getTargetCPU() const { return targetCPU; }

mlir::LLVM::TargetFeaturesAttr getTargetFeatures() const {
return targetFeatures;
}

const mlir::DataLayout &getDataLayout() const {
assert(dataLayout && "dataLayout must be set");
return *dataLayout;
Expand All @@ -170,6 +179,8 @@ class CodeGenSpecifics {
mlir::MLIRContext &context;
llvm::Triple triple;
KindMapping kindMap;
llvm::StringRef targetCPU;
mlir::LLVM::TargetFeaturesAttr targetFeatures;
const mlir::DataLayout *dataLayout = nullptr;
};

Expand Down
14 changes: 14 additions & 0 deletions flang/include/flang/Optimizer/Dialect/Support/FIRContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef FORTRAN_OPTIMIZER_SUPPORT_FIRCONTEXT_H
#define FORTRAN_OPTIMIZER_SUPPORT_FIRCONTEXT_H

#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/TargetParser/Triple.h"

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

/// Set the target CPU for the module. `cpu` must not be deallocated while
/// module `mod` is still live.
void setTargetCPU(mlir::ModuleOp mod, llvm::StringRef cpu);

/// Get the target CPU string from the Module or return a null reference.
llvm::StringRef getTargetCPU(mlir::ModuleOp mod);

/// Set the target features for the module.
void setTargetFeatures(mlir::ModuleOp mod, llvm::StringRef features);

/// Get the target features from the Module.
mlir::LLVM::TargetFeaturesAttr getTargetFeatures(mlir::ModuleOp mod);

/// Helper for determining the target from the host, etc. Tools may use this
/// function to provide a consistent interpretation of the `--target=<string>`
/// command-line option.
Expand Down
4 changes: 1 addition & 3 deletions flang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,16 +285,14 @@ bool CodeGenAction::beginSourceFileAction() {
ci.getSemanticsContext().defaultKinds();
fir::KindMapping kindMap(mlirCtx.get(), llvm::ArrayRef<fir::KindTy>{
fir::fromDefaultKinds(defKinds)});
const llvm::DataLayout &dl = targetMachine.createDataLayout();

lower::LoweringBridge lb = Fortran::lower::LoweringBridge::create(
*mlirCtx, ci.getSemanticsContext(), defKinds,
ci.getSemanticsContext().intrinsics(),
ci.getSemanticsContext().targetCharacteristics(),
ci.getParsing().allCooked(), ci.getInvocation().getTargetOpts().triple,
kindMap, ci.getInvocation().getLoweringOpts(),
ci.getInvocation().getFrontendOpts().envDefaults,
ci.getInvocation().getFrontendOpts().features, &dl);
ci.getInvocation().getFrontendOpts().features, targetMachine);

// Fetch module from lb, so we can set
mlirModule = std::make_unique<mlir::ModuleOp>(lb.getModule());
Expand Down
9 changes: 6 additions & 3 deletions flang/lib/Lower/Bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Target/TargetMachine.h"
#include <optional>

#define DEBUG_TYPE "flang-lower-bridge"
Expand Down Expand Up @@ -5092,7 +5093,7 @@ Fortran::lower::LoweringBridge::LoweringBridge(
const Fortran::lower::LoweringOptions &loweringOptions,
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
const Fortran::common::LanguageFeatureControl &languageFeatures,
const llvm::DataLayout *dataLayout)
const llvm::TargetMachine &targetMachine)
: semanticsContext{semanticsContext}, defaultKinds{defaultKinds},
intrinsics{intrinsics}, targetCharacteristics{targetCharacteristics},
cooked{&cooked}, context{context}, kindMap{kindMap},
Expand Down Expand Up @@ -5148,6 +5149,8 @@ Fortran::lower::LoweringBridge::LoweringBridge(
assert(module.get() && "module was not created");
fir::setTargetTriple(*module.get(), triple);
fir::setKindMapping(*module.get(), kindMap);
if (dataLayout)
fir::support::setMLIRDataLayout(*module.get(), *dataLayout);
fir::setTargetCPU(*module.get(), targetMachine.getTargetCPU());
fir::setTargetFeatures(*module.get(), targetMachine.getTargetFeatureString());
fir::support::setMLIRDataLayout(*module.get(),
targetMachine.createDataLayout());
}
6 changes: 6 additions & 0 deletions flang/lib/Optimizer/CodeGen/CodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3879,6 +3879,12 @@ class FIRToLLVMLowering
fir::support::setMLIRDataLayout(mod, dl);
}

if (!forcedTargetCPU.empty())
fir::setTargetCPU(mod, forcedTargetCPU);

if (!forcedTargetFeatures.empty())
fir::setTargetFeatures(mod, forcedTargetFeatures);

// Run dynamic pass pipeline for converting Math dialect
// operations into other dialects (llvm, func, etc.).
// Some conversions of Math operations cannot be done
Expand Down
52 changes: 29 additions & 23 deletions flang/lib/Optimizer/CodeGen/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1057,51 +1057,57 @@ struct TargetLoongArch64 : public GenericTarget<TargetLoongArch64> {
// TODO: Add other targets to this file as needed.
std::unique_ptr<fir::CodeGenSpecifics>
fir::CodeGenSpecifics::get(mlir::MLIRContext *ctx, llvm::Triple &&trp,
KindMapping &&kindMap, const mlir::DataLayout &dl) {
KindMapping &&kindMap, llvm::StringRef targetCPU,
mlir::LLVM::TargetFeaturesAttr targetFeatures,
const mlir::DataLayout &dl) {
switch (trp.getArch()) {
default:
break;
case llvm::Triple::ArchType::x86:
if (trp.isOSWindows())
return std::make_unique<TargetI386Win>(ctx, std::move(trp),
std::move(kindMap), dl);
std::move(kindMap), targetCPU,
targetFeatures, dl);
else
return std::make_unique<TargetI386>(ctx, std::move(trp),
std::move(kindMap), dl);
std::move(kindMap), targetCPU,
targetFeatures, dl);
case llvm::Triple::ArchType::x86_64:
if (trp.isOSWindows())
return std::make_unique<TargetX86_64Win>(ctx, std::move(trp),
std::move(kindMap), dl);
std::move(kindMap), targetCPU,
targetFeatures, dl);
else
return std::make_unique<TargetX86_64>(ctx, std::move(trp),
std::move(kindMap), dl);
std::move(kindMap), targetCPU,
targetFeatures, dl);
case llvm::Triple::ArchType::aarch64:
return std::make_unique<TargetAArch64>(ctx, std::move(trp),
std::move(kindMap), dl);
return std::make_unique<TargetAArch64>(
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
case llvm::Triple::ArchType::ppc64:
return std::make_unique<TargetPPC64>(ctx, std::move(trp),
std::move(kindMap), dl);
return std::make_unique<TargetPPC64>(
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
case llvm::Triple::ArchType::ppc64le:
return std::make_unique<TargetPPC64le>(ctx, std::move(trp),
std::move(kindMap), dl);
return std::make_unique<TargetPPC64le>(
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
case llvm::Triple::ArchType::sparc:
return std::make_unique<TargetSparc>(ctx, std::move(trp),
std::move(kindMap), dl);
return std::make_unique<TargetSparc>(
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
case llvm::Triple::ArchType::sparcv9:
return std::make_unique<TargetSparcV9>(ctx, std::move(trp),
std::move(kindMap), dl);
return std::make_unique<TargetSparcV9>(
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
case llvm::Triple::ArchType::riscv64:
return std::make_unique<TargetRISCV64>(ctx, std::move(trp),
std::move(kindMap), dl);
return std::make_unique<TargetRISCV64>(
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
case llvm::Triple::ArchType::amdgcn:
return std::make_unique<TargetAMDGPU>(ctx, std::move(trp),
std::move(kindMap), dl);
return std::make_unique<TargetAMDGPU>(
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
case llvm::Triple::ArchType::nvptx64:
return std::make_unique<TargetNVPTX>(ctx, std::move(trp),
std::move(kindMap), dl);
return std::make_unique<TargetNVPTX>(
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
case llvm::Triple::ArchType::loongarch64:
return std::make_unique<TargetLoongArch64>(ctx, std::move(trp),
std::move(kindMap), dl);
return std::make_unique<TargetLoongArch64>(
ctx, std::move(trp), std::move(kindMap), targetCPU, targetFeatures, dl);
}
TODO(mlir::UnknownLoc::get(ctx), "target not implemented");
}
27 changes: 23 additions & 4 deletions flang/lib/Optimizer/CodeGen/TargetRewrite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase<TargetRewrite> {
if (!forcedTargetTriple.empty())
fir::setTargetTriple(mod, forcedTargetTriple);

if (!forcedTargetCPU.empty())
fir::setTargetCPU(mod, forcedTargetCPU);

if (!forcedTargetFeatures.empty())
fir::setTargetFeatures(mod, forcedTargetFeatures);

// TargetRewrite will require querying the type storage sizes, if it was
// not set already, create a DataLayoutSpec for the ModuleOp now.
std::optional<mlir::DataLayout> dl =
Expand All @@ -102,9 +108,9 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase<TargetRewrite> {
return;
}

auto specifics =
fir::CodeGenSpecifics::get(mod.getContext(), fir::getTargetTriple(mod),
fir::getKindMapping(mod), *dl);
auto specifics = fir::CodeGenSpecifics::get(
mod.getContext(), fir::getTargetTriple(mod), fir::getKindMapping(mod),
fir::getTargetCPU(mod), fir::getTargetFeatures(mod), *dl);

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

Expand Down Expand Up @@ -666,8 +672,21 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase<TargetRewrite> {
/// As the type signature is being changed, this must also update the
/// function itself to use any new arguments, etc.
mlir::LogicalResult convertTypes(mlir::ModuleOp mod) {
for (auto fn : mod.getOps<mlir::func::FuncOp>())
mlir::MLIRContext *ctx = mod->getContext();
auto targetCPU = specifics->getTargetCPU();
mlir::StringAttr targetCPUAttr =
targetCPU.empty() ? nullptr : mlir::StringAttr::get(ctx, targetCPU);
auto targetFeaturesAttr = specifics->getTargetFeatures();

for (auto fn : mod.getOps<mlir::func::FuncOp>()) {
if (targetCPUAttr)
fn->setAttr("target_cpu", targetCPUAttr);

if (targetFeaturesAttr)
fn->setAttr("target_features", targetFeaturesAttr);

convertSignature(fn);
}
return mlir::success();
}

Expand Down
6 changes: 3 additions & 3 deletions flang/lib/Optimizer/CodeGen/TypeConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ LLVMTypeConverter::LLVMTypeConverter(mlir::ModuleOp module, bool applyTBAA,
const mlir::DataLayout &dl)
: mlir::LLVMTypeConverter(module.getContext()),
kindMapping(getKindMapping(module)),
specifics(CodeGenSpecifics::get(module.getContext(),
getTargetTriple(module),
getKindMapping(module), dl)),
specifics(CodeGenSpecifics::get(
module.getContext(), getTargetTriple(module), getKindMapping(module),
getTargetCPU(module), getTargetFeatures(module), dl)),
tbaaBuilder(std::make_unique<TBAABuilder>(module->getContext(), applyTBAA,
forceUnifiedTBAATree)) {
LLVM_DEBUG(llvm::dbgs() << "FIR type converter\n");
Expand Down
36 changes: 36 additions & 0 deletions flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,42 @@ fir::KindMapping fir::getKindMapping(mlir::Operation *op) {
return getKindMapping(moduleOp);
}

static constexpr const char *targetCpuName = "fir.target_cpu";

void fir::setTargetCPU(mlir::ModuleOp mod, llvm::StringRef cpu) {
if (cpu.empty())
return;

auto *ctx = mod.getContext();
mod->setAttr(targetCpuName, mlir::StringAttr::get(ctx, cpu));
}

llvm::StringRef fir::getTargetCPU(mlir::ModuleOp mod) {
if (auto attr = mod->getAttrOfType<mlir::StringAttr>(targetCpuName))
return attr.getValue();

return {};
}

static constexpr const char *targetFeaturesName = "fir.target_features";

void fir::setTargetFeatures(mlir::ModuleOp mod, llvm::StringRef features) {
if (features.empty())
return;

auto *ctx = mod.getContext();
mod->setAttr(targetFeaturesName,
mlir::LLVM::TargetFeaturesAttr::get(ctx, features));
}

mlir::LLVM::TargetFeaturesAttr fir::getTargetFeatures(mlir::ModuleOp mod) {
if (auto attr = mod->getAttrOfType<mlir::LLVM::TargetFeaturesAttr>(
targetFeaturesName))
return attr;

return {};
}

std::string fir::determineTargetTriple(llvm::StringRef triple) {
// Treat "" or "default" as stand-ins for the default machine.
if (triple.empty() || triple == "default")
Expand Down
6 changes: 3 additions & 3 deletions flang/test/Driver/save-mlir-temps.f90
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@
! Content to check from the MLIR outputs
!--------------------------
! MLIR-FIR-NOT: llvm.func
! MLIR-FIR: func.func @{{.*}}main(){{.*}}{
! MLIR-FIR: func.func @{{.*}}main(){{.*}}

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

end program
Loading