Index: flang/include/flang/Tools/CrossToolHelpers.h =================================================================== --- flang/include/flang/Tools/CrossToolHelpers.h +++ flang/include/flang/Tools/CrossToolHelpers.h @@ -27,4 +27,15 @@ } } +// 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( + module.getOperation())) { + offloadMod.setTarget(targetCPU, targetFeatures); + } +} + #endif // FORTRAN_TOOLS_CROSS_TOOL_HELPERS_H Index: flang/lib/Frontend/FrontendActions.cpp =================================================================== --- flang/lib/Frontend/FrontendActions.cpp +++ flang/lib/Frontend/FrontendActions.cpp @@ -276,14 +276,17 @@ // Fetch module from lb, so we can set mlirModule = std::make_unique(lb.getModule()); + if (!setUpTargetMachine()) + return false; + if (ci.getInvocation().getFrontendOpts().features.IsEnabled( Fortran::common::LanguageFeature::OpenMP)) { setOffloadModuleInterfaceAttributes( *mlirModule, ci.getInvocation().getLangOpts().OpenMPIsDevice); + setOffloadModuleInterfaceTargetAttribute(*mlirModule, tm->getTargetCPU(), + tm->getTargetFeatureString()); } - if (!setUpTargetMachine()) - return false; const llvm::DataLayout &dl = tm->createDataLayout(); setMLIRDataLayout(*mlirModule, dl); Index: flang/test/Lower/OpenMP/target_cpu_features.f90 =================================================================== --- /dev/null +++ flang/test/Lower/OpenMP/target_cpu_features.f90 @@ -0,0 +1,16 @@ +!REQUIRES: amdgpu-registered-target +!RUN: %flang_fc1 -emit-fir -triple amdgcn-amd-amdhsa -target-cpu gfx908 -fopenmp %s -o - | FileCheck %s + +!=============================================================================== +! Target_Enter Simple +!=============================================================================== + +!CHECK: omp.target = #omp.target +!CHECK-LABEL: func.func @_QPomp_target_simple() { +subroutine omp_target_simple +end subroutine omp_target_simple + Index: mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td =================================================================== --- mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -68,6 +68,16 @@ 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 traits = []> : Op; Index: mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td =================================================================== --- mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td +++ mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td @@ -59,10 +59,10 @@ InterfaceMethod< /*description=*/[{ Set the attribute IsDeviceAttr on the current module with the - specified boolean argument. + specified boolean argument. }], /*retTy=*/"void", - /*methodName=*/"setIsDevice", + /*methodName=*/"setIsDevice", (ins "bool":$isDevice), [{}], [{ $_op->setAttr( mlir::StringAttr::get($_op->getContext(), llvm::Twine{"omp.is_device"}), @@ -74,7 +74,7 @@ its value, if it doesn't exit it returns false by default. }], /*retTy=*/"bool", - /*methodName=*/"getIsDevice", + /*methodName=*/"getIsDevice", (ins), [{}], [{ if (Attribute isDevice = $_op->getAttr("omp.is_device")) if (isDevice.isa()) @@ -110,6 +110,34 @@ assumeTeamsOversubscription, assumeThreadsOversubscription, assumeNoThreadState, assumeNoNestedParallelism)); }]>, + InterfaceMethod< + /*description=*/[{ + Get the Target attribute on the current module if it exists + and return the attribute, if it doesn't exit it returns a nullptr + }], + /*retTy=*/"mlir::omp::TargetAttr", + /*methodName=*/"getTarget", + (ins), [{}], [{ + if (Attribute flags = $_op->getAttr("omp.target")) + return flags.dyn_cast_or_null(); + return nullptr; + }]>, + InterfaceMethod< + /*description=*/[{ + Set the attribute target on the current module with the + specified string arguments - name of cpu and corresponind 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())); + }]>, ]; }