Skip to content

[Flang][MLIR][OpenMP] Add support for target-cpu and target-features #75344

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

Closed
wants to merge 3 commits into from
Closed
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
14 changes: 7 additions & 7 deletions flang/include/flang/Lower/Bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
#include "mlir/IR/BuiltinOps.h"

namespace llvm {
class DataLayout;
} // namespace llvm
#include "llvm/Target/TargetMachine.h"

namespace Fortran {
namespace common {
Expand Down Expand Up @@ -64,11 +61,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 @@ -110,6 +107,8 @@ class LoweringBridge {
return languageFeatures;
}

const llvm::TargetMachine &getTargetMachine() const { return targetMachine; }

/// Create a folding context. Careful: this is very expensive.
Fortran::evaluate::FoldingContext createFoldingContext() const;

Expand Down Expand Up @@ -147,7 +146,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 All @@ -164,6 +163,7 @@ class LoweringBridge {
const Fortran::lower::LoweringOptions &loweringOptions;
const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults;
const Fortran::common::LanguageFeatureControl &languageFeatures;
const llvm::TargetMachine &targetMachine;
};

} // namespace lower
Expand Down
11 changes: 0 additions & 11 deletions flang/include/flang/Tools/CrossToolHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,17 +103,6 @@ void setOffloadModuleInterfaceAttributes(
}
}

// Shares assinging of the OpenMP OffloadModuleInterface and its TargetCPU
// attribute accross Flang tools (bbc/flang)
void setOffloadModuleInterfaceTargetAttribute(mlir::ModuleOp &module,
llvm::StringRef targetCPU, llvm::StringRef targetFeatures) {
// Should be registered by the OpenMPDialect
if (auto offloadMod = llvm::dyn_cast<mlir::omp::OffloadModuleInterface>(
module.getOperation())) {
offloadMod.setTarget(targetCPU, targetFeatures);
}
}

void setOpenMPVersionAttribute(mlir::ModuleOp &module, int64_t version) {
module.getOperation()->setAttr(
mlir::StringAttr::get(module.getContext(), llvm::Twine{"omp.version"}),
Expand Down
7 changes: 1 addition & 6 deletions flang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,16 +283,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 All @@ -301,9 +299,6 @@ bool CodeGenAction::beginSourceFileAction() {
Fortran::common::LanguageFeature::OpenMP)) {
setOffloadModuleInterfaceAttributes(*mlirModule,
ci.getInvocation().getLangOpts());
setOffloadModuleInterfaceTargetAttribute(
*mlirModule, targetMachine.getTargetCPU(),
targetMachine.getTargetFeatureString());
setOpenMPVersionAttribute(*mlirModule,
ci.getInvocation().getLangOpts().OpenMPVersion);
}
Expand Down
21 changes: 17 additions & 4 deletions flang/lib/Lower/Bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include "flang/Semantics/symbol.h"
#include "flang/Semantics/tools.h"
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Parser/Parser.h"
#include "mlir/Transforms/RegionUtils.h"
Expand Down Expand Up @@ -4326,6 +4327,18 @@ class FirConverter : public Fortran::lower::AbstractConverter {
assert(blockId == 0 && "invalid blockId");
assert(activeConstructStack.empty() && "invalid construct stack state");

// Set target_cpu and target_features attributes to be passed through to the
// llvm.func operation during lowering.
const llvm::TargetMachine &targetMachine = bridge.getTargetMachine();
if (auto targetCPU = targetMachine.getTargetCPU(); !targetCPU.empty())
func->setAttr("target_cpu",
mlir::StringAttr::get(func.getContext(), targetCPU));

if (auto targetFeatures = targetMachine.getTargetFeatureString();
!targetFeatures.empty())
func->setAttr("target_features", mlir::LLVM::TargetFeaturesAttr::get(
func.getContext(), targetFeatures));

// Manage floating point exception, halting mode, and rounding mode
// settings at function entry and exit.
if (!funit.isMainProgram())
Expand Down Expand Up @@ -5091,12 +5104,12 @@ 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},
loweringOptions{loweringOptions}, envDefaults{envDefaults},
languageFeatures{languageFeatures} {
languageFeatures{languageFeatures}, targetMachine{targetMachine} {
// Register the diagnostic handler.
context.getDiagEngine().registerHandler([](mlir::Diagnostic &diag) {
llvm::raw_ostream &os = llvm::errs();
Expand Down Expand Up @@ -5147,6 +5160,6 @@ 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::support::setMLIRDataLayout(*module.get(),
targetMachine.createDataLayout());
}
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
22 changes: 13 additions & 9 deletions flang/test/Lower/OpenMP/FIR/target_cpu_features.f90
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
!REQUIRES: amdgpu-registered-target, nvptx-registered-target
!RUN: %flang_fc1 -emit-fir -triple amdgcn-amd-amdhsa -target-cpu gfx908 -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s
!RUN: %flang_fc1 -emit-fir -triple amdgcn-amd-amdhsa -target-cpu gfx908 -fopenmp -fopenmp-is-target-device %s -o - | FileCheck --check-prefix=AMDGCN %s
!RUN: %flang_fc1 -emit-hlfir -triple nvptx64-nvidia-cuda -target-cpu sm_80 -fopenmp -fopenmp-is-target-device %s -o - | FileCheck --check-prefix=NVPTX %s


!===============================================================================
! Target_Enter Simple
!===============================================================================

!CHECK: omp.target = #omp.target<target_cpu = "gfx908",
!CHECK-SAME: target_features = "+16-bit-insts,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,
!CHECK-SAME: +dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,
!CHECK-SAME: +gfx8-insts,+gfx9-insts,+gws,+image-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,
!CHECK-SAME: +wavefrontsize64">
!NVPTX: omp.target = #omp.target<target_cpu = "sm_80", target_features = "+ptx61,+sm_80">
!CHECK-LABEL: func.func @_QPomp_target_simple()
!AMDGCN-LABEL: func.func @_QPomp_target_simple() attributes {
!AMDGCN-SAME: target_cpu = "gfx908"
!AMDGCN-SAME: target_features = #llvm.target_features<["+16-bit-insts", "+ci-insts",
!AMDGCN-SAME: "+dl-insts", "+dot1-insts", "+dot10-insts", "+dot2-insts", "+dot3-insts",
!AMDGCN-SAME: "+dot4-insts", "+dot5-insts", "+dot6-insts", "+dot7-insts", "+dpp",
!AMDGCN-SAME: "+gfx8-insts", "+gfx9-insts", "+gws", "+image-insts", "+mai-insts",
!AMDGCN-SAME: "+s-memrealtime", "+s-memtime-inst", "+wavefrontsize64"]>

!NVPTX-LABEL: func.func @_QPomp_target_simple() attributes {
!NVPTX-SAME: target_cpu = "sm_80"
!NVPTX-SAME: target_features = #llvm.target_features<["+ptx61", "+sm_80"]>

subroutine omp_target_simple
! Directive needed to prevent subroutine from being filtered out when
! compiling for the device.
!$omp declare target
end subroutine omp_target_simple

22 changes: 13 additions & 9 deletions flang/test/Lower/OpenMP/target_cpu_features.f90
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
!REQUIRES: amdgpu-registered-target, nvptx-registered-target
!RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -target-cpu gfx908 -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s
!RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -target-cpu gfx908 -fopenmp -fopenmp-is-target-device %s -o - | FileCheck --check-prefix=AMDGCN %s
!RUN: %flang_fc1 -emit-hlfir -triple nvptx64-nvidia-cuda -target-cpu sm_80 -fopenmp -fopenmp-is-target-device %s -o - | FileCheck --check-prefix=NVPTX %s

!===============================================================================
! Target_Enter Simple
!===============================================================================

!CHECK: omp.target = #omp.target<target_cpu = "gfx908",
!CHECK-SAME: target_features = "+16-bit-insts,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,
!CHECK-SAME: +dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,
!CHECK-SAME: +gfx8-insts,+gfx9-insts,+gws,+image-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,
!CHECK-SAME: +wavefrontsize64">
!NVPTX: omp.target = #omp.target<target_cpu = "sm_80", target_features = "+ptx61,+sm_80">
!CHECK-LABEL: func.func @_QPomp_target_simple()
!AMDGCN-LABEL: func.func @_QPomp_target_simple() attributes {
!AMDGCN-SAME: target_cpu = "gfx908"
!AMDGCN-SAME: target_features = #llvm.target_features<["+16-bit-insts", "+ci-insts",
!AMDGCN-SAME: "+dl-insts", "+dot1-insts", "+dot10-insts", "+dot2-insts", "+dot3-insts",
!AMDGCN-SAME: "+dot4-insts", "+dot5-insts", "+dot6-insts", "+dot7-insts", "+dpp",
!AMDGCN-SAME: "+gfx8-insts", "+gfx9-insts", "+gws", "+image-insts", "+mai-insts",
!AMDGCN-SAME: "+s-memrealtime", "+s-memtime-inst", "+wavefrontsize64"]>

!NVPTX-LABEL: func.func @_QPomp_target_simple() attributes {
!NVPTX-SAME: target_cpu = "sm_80"
!NVPTX-SAME: target_features = #llvm.target_features<["+ptx61", "+sm_80"]>

subroutine omp_target_simple
! Directive needed to prevent subroutine from being filtered out when
! compiling for the device.
!$omp declare target
end subroutine omp_target_simple

23 changes: 23 additions & 0 deletions flang/test/Lower/target-features-amdgcn.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
! REQUIRES: amdgpu-registered-target
! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s --check-prefixes=ALL,NONE
! RUN: %flang_fc1 -emit-fir -triple amdgcn-amd-amdhsa %s -o - | FileCheck %s --check-prefixes=ALL,TRIPLE
! RUN: %flang_fc1 -emit-fir -target-cpu gfx90a %s -o - | FileCheck %s --check-prefixes=ALL,CPU
! RUN: %flang_fc1 -emit-fir -triple amdgcn-amd-amdhsa -target-cpu gfx90a %s -o - | FileCheck %s --check-prefixes=ALL,BOTH

! ALL-LABEL: func.func @_QPfoo()

! NONE-NOT: target_cpu
! NONE-NOT: target_features

! TRIPLE-SAME: target_cpu = "generic-hsa"
! TRIPLE-NOT: target_features

! CPU-SAME: target_cpu = "gfx90a"
! CPU-NOT: target_features

! BOTH-SAME: target_cpu = "gfx90a"
! BOTH-SAME: target_features = #llvm.target_features<[
! BOTH-SAME: "+gfx90a-insts"
! BOTH-SAME: ]>
subroutine foo
end subroutine
21 changes: 21 additions & 0 deletions flang/test/Lower/target-features-x86_64.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
! REQUIRES: x86-registered-target
! RUN: %flang_fc1 -emit-fir -triple x86_64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefixes=ALL,NONE
! RUN: %flang_fc1 -emit-fir -triple x86_64-unknown-linux-gnu -target-cpu x86-64 %s -o - | FileCheck %s --check-prefixes=ALL,CPU
! RUN: %flang_fc1 -emit-fir -triple x86_64-unknown-linux-gnu -target-feature +sse %s -o - | FileCheck %s --check-prefixes=ALL,FEATURE
! RUN: %flang_fc1 -emit-fir -triple x86_64-unknown-linux-gnu -target-cpu x86-64 -target-feature +sse %s -o - | FileCheck %s --check-prefixes=ALL,BOTH

! ALL-LABEL: func.func @_QPfoo()

! NONE-NOT: target_cpu
! NONE-NOT: target_features

! CPU-SAME: target_cpu = "x86-64"
! CPU-NOT: target_features

! FEATURE-NOT: target_cpu
! FEATURE-SAME: target_features = #llvm.target_features<["+sse"]>

! BOTH-SAME: target_cpu = "x86-64"
! BOTH-SAME: target_features = #llvm.target_features<["+sse"]>
subroutine foo
end subroutine
3 changes: 1 addition & 2 deletions flang/tools/bbc/bbc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,6 @@ static mlir::LogicalResult convertFortranSourceToMLIR(
auto &defKinds = semanticsContext.defaultKinds();
fir::KindMapping kindMap(
&ctx, llvm::ArrayRef<fir::KindTy>{fir::fromDefaultKinds(defKinds)});
const llvm::DataLayout &dataLayout = targetMachine.createDataLayout();
std::string targetTriple = targetMachine.getTargetTriple().normalize();
// Use default lowering options for bbc.
Fortran::lower::LoweringOptions loweringOptions{};
Expand All @@ -336,7 +335,7 @@ static mlir::LogicalResult convertFortranSourceToMLIR(
ctx, semanticsContext, defKinds, semanticsContext.intrinsics(),
semanticsContext.targetCharacteristics(), parsing.allCooked(),
targetTriple, kindMap, loweringOptions, {},
semanticsContext.languageFeatures(), &dataLayout);
semanticsContext.languageFeatures(), targetMachine);
burnside.lower(parseTree, semanticsContext);
mlir::ModuleOp mlirModule = burnside.getModule();
if (enableOpenMP) {
Expand Down
1 change: 1 addition & 0 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -1418,6 +1418,7 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
OptionalAttr<I64Attr>:$alignment,
OptionalAttr<LLVM_VScaleRangeAttr>:$vscale_range,
OptionalAttr<FramePointerKindAttr>:$frame_pointer,
OptionalAttr<StrAttr>:$target_cpu,
OptionalAttr<LLVM_TargetFeaturesAttr>:$target_features
);

Expand Down
10 changes: 0 additions & 10 deletions mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,6 @@ def FlagsAttr : OpenMP_Attr<"Flags", "flags"> {
let assemblyFormat = "`<` struct(params) `>`";
}

def TargetAttr : OpenMP_Attr<"Target", "target"> {
let parameters = (ins
StringRefParameter<>:$target_cpu,
StringRefParameter<>:$target_features
);

let assemblyFormat = "`<` struct(params) `>`";
}


class OpenMP_Op<string mnemonic, list<Trait> traits = []> :
Op<OpenMP_Dialect, mnemonic, traits>;

Expand Down
28 changes: 0 additions & 28 deletions mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td
Original file line number Diff line number Diff line change
Expand Up @@ -204,34 +204,6 @@ def OffloadModuleInterface : OpInterface<"OffloadModuleInterface"> {
assumeTeamsOversubscription, assumeThreadsOversubscription,
assumeNoThreadState, assumeNoNestedParallelism, openmpDeviceVersion));
}]>,
InterfaceMethod<
/*description=*/[{
Get the Target attribute on the current module if it exists
and return the attribute, if it doesn't exist it returns a nullptr.
}],
/*retTy=*/"mlir::omp::TargetAttr",
/*methodName=*/"getTarget",
(ins), [{}], [{
if (Attribute flags = $_op->getAttr("omp.target"))
return ::llvm::dyn_cast_or_null<mlir::omp::TargetAttr>(flags);
return nullptr;
}]>,
InterfaceMethod<
/*description=*/[{
Set the attribute target on the current module with the
specified string arguments - name of cpu and corresponding features.
}],
/*retTy=*/"void",
/*methodName=*/"setTarget",
(ins "llvm::StringRef":$targetCPU,
"llvm::StringRef":$targetFeatures), [{}], [{
if (targetCPU.empty())
return;
$_op->setAttr(("omp." + mlir::omp::TargetAttr::getMnemonic()).str(),
mlir::omp::TargetAttr::get($_op->getContext(),
targetCPU.str(),
targetFeatures.str()));
}]>,
InterfaceMethod<
/*description=*/[{
Set a StringAttr on the current module containing the host IR file path. This
Expand Down
Loading