Index: flang/include/flang/Lower/Bridge.h =================================================================== --- flang/include/flang/Lower/Bridge.h +++ flang/include/flang/Lower/Bridge.h @@ -40,6 +40,15 @@ namespace lower { +struct Attribute { + std::string attribute; + std::optional attributeVal; + Attribute(llvm::StringRef attribute) + : attribute{attribute.str()}, attributeVal{} {}; + Attribute(llvm::StringRef attribute, llvm::StringRef attributeVal) + : attribute{attribute.str()}, attributeVal{attributeVal.str()} {}; +}; + //===----------------------------------------------------------------------===// // Lowering bridge //===----------------------------------------------------------------------===// @@ -57,11 +66,12 @@ const Fortran::evaluate::TargetCharacteristics &targetCharacteristics, const Fortran::parser::AllCookedSources &allCooked, llvm::StringRef triple, fir::KindMapping &kindMap, + const llvm::SmallVector &llvmFuncAttributes, const Fortran::lower::LoweringOptions &loweringOptions, const std::vector &envDefaults) { return LoweringBridge(ctx, semanticsContext, defaultKinds, intrinsics, targetCharacteristics, allCooked, triple, kindMap, - loweringOptions, envDefaults); + llvmFuncAttributes, loweringOptions, envDefaults); } //===--------------------------------------------------------------------===// @@ -131,6 +141,7 @@ const Fortran::evaluate::TargetCharacteristics &targetCharacteristics, const Fortran::parser::AllCookedSources &cooked, llvm::StringRef triple, fir::KindMapping &kindMap, + const llvm::SmallVector &funcAttributes, const Fortran::lower::LoweringOptions &loweringOptions, const std::vector &envDefaults); LoweringBridge() = delete; @@ -145,6 +156,7 @@ mlir::MLIRContext &context; std::unique_ptr module; fir::KindMapping &kindMap; + const llvm::SmallVector &funcAttributes; const Fortran::lower::LoweringOptions &loweringOptions; const std::vector &envDefaults; }; Index: flang/lib/Frontend/FrontendActions.cpp =================================================================== --- flang/lib/Frontend/FrontendActions.cpp +++ flang/lib/Frontend/FrontendActions.cpp @@ -260,6 +260,18 @@ if (!res) return res; + llvm::SmallVector loweringAttributes; + if (!setUpTargetMachine()) + return false; + + if (!tm->getTargetCPU().empty()) { + lower::Attribute attr("target-cpu", tm->getTargetCPU()); + loweringAttributes.push_back(attr); + } + if (!tm->getTargetFeatureString().empty()) { + lower::Attribute attr("target-features", tm->getTargetFeatureString()); + loweringAttributes.push_back(attr); + } // Create a LoweringBridge const common::IntrinsicTypeDefaultKinds &defKinds = ci.getInvocation().getSemanticsContext().defaultKinds(); @@ -270,14 +282,12 @@ ci.getInvocation().getSemanticsContext().intrinsics(), ci.getInvocation().getSemanticsContext().targetCharacteristics(), ci.getParsing().allCooked(), ci.getInvocation().getTargetOpts().triple, - kindMap, ci.getInvocation().getLoweringOpts(), + kindMap, loweringAttributes, ci.getInvocation().getLoweringOpts(), ci.getInvocation().getFrontendOpts().envDefaults); // 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)) { Index: flang/lib/Lower/Bridge.cpp =================================================================== --- flang/lib/Lower/Bridge.cpp +++ flang/lib/Lower/Bridge.cpp @@ -270,7 +270,8 @@ virtual ~FirConverter() = default; /// Convert the PFT to FIR. - void run(Fortran::lower::pft::Program &pft) { + void run(Fortran::lower::pft::Program &pft, + const llvm::SmallVector &funcAttributes) { // Preliminary translation pass. // - Lower common blocks from the PFT common block list that contains a @@ -308,14 +309,17 @@ // Primary translation pass. for (Fortran::lower::pft::Program::Units &u : pft.getUnits()) { - std::visit( - Fortran::common::visitors{ - [&](Fortran::lower::pft::FunctionLikeUnit &f) { lowerFunc(f); }, - [&](Fortran::lower::pft::ModuleLikeUnit &m) { lowerMod(m); }, - [&](Fortran::lower::pft::BlockDataUnit &b) {}, - [&](Fortran::lower::pft::CompilerDirectiveUnit &d) {}, - }, - u); + std::visit(Fortran::common::visitors{ + [&](Fortran::lower::pft::FunctionLikeUnit &f) { + lowerFunc(f, funcAttributes); + }, + [&](Fortran::lower::pft::ModuleLikeUnit &m) { + lowerMod(m, funcAttributes); + }, + [&](Fortran::lower::pft::BlockDataUnit &b) {}, + [&](Fortran::lower::pft::CompilerDirectiveUnit &d) {}, + }, + u); } /// Once all the code has been translated, create runtime type info @@ -3529,7 +3533,9 @@ } /// Start translation of a function. - void startNewFunction(Fortran::lower::pft::FunctionLikeUnit &funit) { + void startNewFunction( + Fortran::lower::pft::FunctionLikeUnit &funit, + const llvm::SmallVector &funcAttributes) { assert(!builder && "expected nullptr"); bridge.fctCtx().pushScope(); const Fortran::semantics::Scope &scope = funit.getScope(); @@ -3547,6 +3553,21 @@ assert(activeConstructStack.empty() && "invalid construct stack state"); mapDummiesAndResults(funit, callee); + mlir::Attribute passthroughAttr = func->getAttr("passthrough"); + if (!passthroughAttr) { + llvm::SmallVector passthroughAttrsVec; + for (const auto &attr : funcAttributes) { + if (attr.attributeVal) { + passthroughAttrsVec.push_back( + builder->getStrArrayAttr({attr.attribute, *attr.attributeVal})); + } else { + passthroughAttrsVec.push_back(builder->getStringAttr(attr.attribute)); + } + } + if (!passthroughAttrsVec.empty()) + func->setAttr(builder->getStringAttr("passthrough"), + builder->getArrayAttr(passthroughAttrsVec)); + } // Map host associated symbols from parent procedure if any. if (funit.parentHasHostAssoc()) @@ -3787,19 +3808,22 @@ } /// Lower a procedure (nest). - void lowerFunc(Fortran::lower::pft::FunctionLikeUnit &funit) { + void lowerFunc( + Fortran::lower::pft::FunctionLikeUnit &funit, + const llvm::SmallVector &funcAttributes) { setCurrentPosition(funit.getStartingSourceLoc()); for (int entryIndex = 0, last = funit.entryPointList.size(); entryIndex < last; ++entryIndex) { funit.setActiveEntry(entryIndex); - startNewFunction(funit); // the entry point for lowering this procedure + startNewFunction( + funit, funcAttributes); // the entry point for lowering this procedure for (Fortran::lower::pft::Evaluation &eval : funit.evaluationList) genFIR(eval); endNewFunction(funit); } funit.setActiveEntry(0); for (Fortran::lower::pft::FunctionLikeUnit &f : funit.nestedFunctions) - lowerFunc(f); // internal procedure + lowerFunc(f, funcAttributes); // internal procedure } /// Lower module variable definitions to fir::globalOp and OpenMP/OpenACC @@ -3822,9 +3846,11 @@ } /// Lower functions contained in a module. - void lowerMod(Fortran::lower::pft::ModuleLikeUnit &mod) { + void + lowerMod(Fortran::lower::pft::ModuleLikeUnit &mod, + const llvm::SmallVector &funcAttributes) { for (Fortran::lower::pft::FunctionLikeUnit &f : mod.nestedFunctions) - lowerFunc(f); + lowerFunc(f, funcAttributes); } void setCurrentPosition(const Fortran::parser::CharBlock &position) { @@ -4115,7 +4141,7 @@ if (dumpBeforeFir) Fortran::lower::dumpPFT(llvm::errs(), *pft); FirConverter converter{*this}; - converter.run(*pft); + converter.run(*pft, funcAttributes); } void Fortran::lower::LoweringBridge::parseSourceFile(llvm::SourceMgr &srcMgr) { @@ -4133,12 +4159,14 @@ const Fortran::evaluate::TargetCharacteristics &targetCharacteristics, const Fortran::parser::AllCookedSources &cooked, llvm::StringRef triple, fir::KindMapping &kindMap, + const llvm::SmallVector &funcAttributes, const Fortran::lower::LoweringOptions &loweringOptions, const std::vector &envDefaults) : semanticsContext{semanticsContext}, defaultKinds{defaultKinds}, intrinsics{intrinsics}, targetCharacteristics{targetCharacteristics}, cooked{&cooked}, context{context}, kindMap{kindMap}, - loweringOptions{loweringOptions}, envDefaults{envDefaults} { + funcAttributes{funcAttributes}, loweringOptions{loweringOptions}, + envDefaults{envDefaults} { // Register the diagnostic handler. context.getDiagEngine().registerHandler([](mlir::Diagnostic &diag) { llvm::raw_ostream &os = llvm::errs(); Index: flang/test/Driver/save-mlir-temps.f90 =================================================================== --- flang/test/Driver/save-mlir-temps.f90 +++ flang/test/Driver/save-mlir-temps.f90 @@ -50,9 +50,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: llvm.func @{{.*}}main() end program Index: flang/test/Lower/OpenMP/target_cpu_features.f90 =================================================================== --- flang/test/Lower/OpenMP/target_cpu_features.f90 +++ flang/test/Lower/OpenMP/target_cpu_features.f90 @@ -10,7 +10,7 @@ !CHECK-SAME: +16-bit-insts,+s-memrealtime,+dot6-insts,+dl-insts,+wavefrontsize64, !CHECK-SAME: +gfx9-insts,+gfx8-insts,+ci-insts,+dot10-insts,+dot7-insts, !CHECK-SAME: +dot1-insts,+dot5-insts,+mai-insts,+dpp,+dot2-insts"> -!CHECK-LABEL: func.func @_QPomp_target_simple() { +!CHECK-LABEL: func.func @_QPomp_target_simple() subroutine omp_target_simple end subroutine omp_target_simple Index: flang/test/Lower/passthrough_attributes.f90 =================================================================== --- /dev/null +++ flang/test/Lower/passthrough_attributes.f90 @@ -0,0 +1,22 @@ +! REQUIRES: x86-registered-target + +!RUN: %flang_fc1 -emit-fir -triple x86_64-unknown-linux-gnu %s -o - | FileCheck %s -check-prefix=CHECK-X86 + +!RUN: %flang_fc1 -emit-fir -triple x86_64-unknown-linux-gnu -target-cpu znver4 %s -o - | FileCheck %s -check-prefix=CHECK-ZEN4 + +!RUN: %flang_fc1 -emit-fir -triple x86_64-unknown-linux-gnu -target-cpu znver4 -target-feature +mmx %s -o - | FileCheck %s -check-prefix=CHECK-ZEN4-MMX + +subroutine test_passthrough +end subroutine + +!CHECK-X86: func.func @_QPtest_passthrough() { +!CHECK-ZEN4: func.func @_QPtest_passthrough() attributes {passthrough = +!CHECK-ZEN4-SAME: target-cpu +!CHECK-ZEN4-SAME: znver4 +!CHECK-ZEN4-NOT: mmx +!CHECK-ZEN4-MMX: func.func @_QPtest_passthrough() attributes {passthrough = +!CHECK-ZEN4-MMX-SAME: target-cpu +!CHECK-ZEN4-MMX-SAME: znver4 +!CHECK-ZEN4-MMX-SAME: target-features +!CHECK-ZEN4-MMX-SAME: mmx + Index: flang/tools/bbc/bbc.cpp =================================================================== --- flang/tools/bbc/bbc.cpp +++ flang/tools/bbc/bbc.cpp @@ -273,7 +273,7 @@ auto burnside = Fortran::lower::LoweringBridge::create( ctx, semanticsContext, defKinds, semanticsContext.intrinsics(), semanticsContext.targetCharacteristics(), parsing.allCooked(), "", - kindMap, loweringOptions, {}); + kindMap, {}, loweringOptions, {}); burnside.lower(parseTree, semanticsContext); mlir::ModuleOp mlirModule = burnside.getModule(); if (enableOpenMP) {