[flang-commits] [flang] ebec5e5 - [flang][OpenMP] Lowering critical construct
Shraiysh Vaishay via flang-commits
flang-commits at lists.llvm.org
Tue Mar 22 03:56:30 PDT 2022
Author: Shraiysh Vaishay
Date: 2022-03-22T16:26:18+05:30
New Revision: ebec5e5c8f120ab97f4f05a68e4753508349ad3c
URL: https://github.com/llvm/llvm-project/commit/ebec5e5c8f120ab97f4f05a68e4753508349ad3c
DIFF: https://github.com/llvm/llvm-project/commit/ebec5e5c8f120ab97f4f05a68e4753508349ad3c.diff
LOG: [flang][OpenMP] Lowering critical construct
This patch adds translation from PFT to FIR for critical construct.
This is part of the upstreaming effort from the fir-dev branch in [1].
[1] https://github.com/flang-compiler/f18-llvm-project
Co-authored-by: kiranchandramohan <kiranchandramohan at gmail.com>
Reviewed By: kiranchandramohan
Differential Revision: https://reviews.llvm.org/D122218
Added:
flang/test/Lower/OpenMP/critical.f90
Modified:
flang/lib/Lower/OpenMP.cpp
flang/lib/Semantics/resolve-directives.cpp
Removed:
################################################################################
diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp
index 70c01f2a309c5..7c8072d03179f 100644
--- a/flang/lib/Lower/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP.cpp
@@ -202,6 +202,49 @@ genOMP(Fortran::lower::AbstractConverter &converter,
}
}
+static void
+genOMP(Fortran::lower::AbstractConverter &converter,
+ Fortran::lower::pft::Evaluation &eval,
+ const Fortran::parser::OpenMPCriticalConstruct &criticalConstruct) {
+ fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
+ mlir::Location currentLocation = converter.getCurrentLocation();
+ std::string name;
+ const Fortran::parser::OmpCriticalDirective &cd =
+ std::get<Fortran::parser::OmpCriticalDirective>(criticalConstruct.t);
+ if (std::get<std::optional<Fortran::parser::Name>>(cd.t).has_value()) {
+ name =
+ std::get<std::optional<Fortran::parser::Name>>(cd.t).value().ToString();
+ }
+
+ uint64_t hint = 0;
+ const auto &clauseList = std::get<Fortran::parser::OmpClauseList>(cd.t);
+ for (const Fortran::parser::OmpClause &clause : clauseList.v)
+ if (auto hintClause =
+ std::get_if<Fortran::parser::OmpClause::Hint>(&clause.u)) {
+ const auto *expr = Fortran::semantics::GetExpr(hintClause->v);
+ hint = *Fortran::evaluate::ToInt64(*expr);
+ break;
+ }
+
+ mlir::omp::CriticalOp criticalOp = [&]() {
+ if (name.empty()) {
+ return firOpBuilder.create<mlir::omp::CriticalOp>(currentLocation,
+ FlatSymbolRefAttr());
+ } else {
+ mlir::ModuleOp module = firOpBuilder.getModule();
+ mlir::OpBuilder modBuilder(module.getBodyRegion());
+ auto global = module.lookupSymbol<mlir::omp::CriticalDeclareOp>(name);
+ if (!global)
+ global = modBuilder.create<mlir::omp::CriticalDeclareOp>(
+ currentLocation, name, hint);
+ return firOpBuilder.create<mlir::omp::CriticalOp>(
+ currentLocation, mlir::FlatSymbolRefAttr::get(
+ firOpBuilder.getContext(), global.sym_name()));
+ }
+ }();
+ createBodyOfOp<omp::CriticalOp>(criticalOp, firOpBuilder, currentLocation);
+}
+
void Fortran::lower::genOpenMPConstruct(
Fortran::lower::AbstractConverter &converter,
Fortran::lower::pft::Evaluation &eval,
@@ -239,7 +282,7 @@ void Fortran::lower::genOpenMPConstruct(
},
[&](const Fortran::parser::OpenMPCriticalConstruct
&criticalConstruct) {
- TODO(converter.getCurrentLocation(), "OpenMPCriticalConstruct");
+ genOMP(converter, eval, criticalConstruct);
},
},
ompConstruct.u);
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 3a3701459efb5..f6e9ae9f2c5ec 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -293,8 +293,6 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
bool Pre(const parser::OpenMPBlockConstruct &);
void Post(const parser::OpenMPBlockConstruct &);
- bool Pre(const parser::OmpCriticalDirective &x);
- bool Pre(const parser::OmpEndCriticalDirective &x);
void Post(const parser::OmpBeginBlockDirective &) {
GetContext().withinConstruct = true;
@@ -313,7 +311,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
bool Pre(const parser::OpenMPSectionsConstruct &);
void Post(const parser::OpenMPSectionsConstruct &) { PopContext(); }
- bool Pre(const parser::OpenMPCriticalConstruct &);
+ bool Pre(const parser::OpenMPCriticalConstruct &critical);
void Post(const parser::OpenMPCriticalConstruct &) { PopContext(); }
bool Pre(const parser::OpenMPDeclareSimdConstruct &x) {
@@ -1376,28 +1374,21 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPSectionsConstruct &x) {
return true;
}
-bool OmpAttributeVisitor::Pre(const parser::OmpCriticalDirective &x) {
- const auto &name{std::get<std::optional<parser::Name>>(x.t)};
- if (name) {
- ResolveOmpName(*name, Symbol::Flag::OmpCriticalLock);
+bool OmpAttributeVisitor::Pre(const parser::OpenMPCriticalConstruct &x) {
+ const auto &beginCriticalDir{std::get<parser::OmpCriticalDirective>(x.t)};
+ const auto &endCriticalDir{std::get<parser::OmpEndCriticalDirective>(x.t)};
+ PushContext(beginCriticalDir.source, llvm::omp::Directive::OMPD_critical);
+ if (const auto &criticalName{
+ std::get<std::optional<parser::Name>>(beginCriticalDir.t)}) {
+ ResolveOmpName(*criticalName, Symbol::Flag::OmpCriticalLock);
}
- return true;
-}
-
-bool OmpAttributeVisitor::Pre(const parser::OmpEndCriticalDirective &x) {
- const auto &name{std::get<std::optional<parser::Name>>(x.t)};
- if (name) {
- ResolveOmpName(*name, Symbol::Flag::OmpCriticalLock);
+ if (const auto &endCriticalName{
+ std::get<std::optional<parser::Name>>(endCriticalDir.t)}) {
+ ResolveOmpName(*endCriticalName, Symbol::Flag::OmpCriticalLock);
}
return true;
}
-bool OmpAttributeVisitor::Pre(const parser::OpenMPCriticalConstruct &x) {
- const auto &criticalDir{std::get<parser::OmpCriticalDirective>(x.t)};
- PushContext(criticalDir.source, llvm::omp::Directive::OMPD_critical);
- return true;
-}
-
bool OmpAttributeVisitor::Pre(const parser::OpenMPThreadprivate &x) {
PushContext(x.source, llvm::omp::Directive::OMPD_threadprivate);
const auto &list{std::get<parser::OmpObjectList>(x.t)};
@@ -1515,13 +1506,11 @@ void OmpAttributeVisitor::ResolveOmpName(
AddToContextObjectWithDSA(*resolvedSymbol, ompFlag);
}
}
- } else if (ompFlagsRequireNewSymbol.test(ompFlag)) {
- const auto pair{GetContext().scope.try_emplace(
- name.source, Attrs{}, ObjectEntityDetails{})};
+ } else if (ompFlag == Symbol::Flag::OmpCriticalLock) {
+ const auto pair{
+ GetContext().scope.try_emplace(name.source, Attrs{}, UnknownDetails{})};
CHECK(pair.second);
name.symbol = &pair.first->second.get();
- } else {
- DIE("OpenMP Name resolution failed");
}
}
diff --git a/flang/test/Lower/OpenMP/critical.f90 b/flang/test/Lower/OpenMP/critical.f90
new file mode 100644
index 0000000000000..4c052040a318c
--- /dev/null
+++ b/flang/test/Lower/OpenMP/critical.f90
@@ -0,0 +1,41 @@
+!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s --check-prefix="FIRDialect"
+!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | fir-opt --fir-to-llvm-ir | FileCheck %s --check-prefix="LLVMDialect"
+!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | fir-opt --fir-to-llvm-ir | tco | FileCheck %s --check-prefix="LLVMIR"
+
+subroutine omp_critical()
+ use omp_lib
+ integer :: x, y
+!FIRDialect: omp.critical.declare @help hint(contended)
+!LLVMDialect: omp.critical.declare @help hint(contended)
+!FIRDialect: omp.critical(@help)
+!LLVMDialect: omp.critical(@help)
+!LLVMIR: call void @__kmpc_critical_with_hint({{.*}}, {{.*}}, {{.*}} @{{.*}}help.var, i32 2)
+!$OMP CRITICAL(help) HINT(omp_lock_hint_contended)
+ x = x + y
+!FIRDialect: omp.terminator
+!LLVMDialect: omp.terminator
+!LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}help.var)
+!$OMP END CRITICAL(help)
+
+! Test that the same name can be used again
+! Also test with the zero hint expression
+!FIRDialect: omp.critical(@help)
+!LLVMDialect: omp.critical(@help)
+!LLVMIR: call void @__kmpc_critical_with_hint({{.*}}, {{.*}}, {{.*}} @{{.*}}help.var, i32 2)
+!$OMP CRITICAL(help) HINT(omp_lock_hint_none)
+ x = x - y
+!FIRDialect: omp.terminator
+!LLVMDialect: omp.terminator
+!LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}help.var)
+!$OMP END CRITICAL(help)
+
+!FIRDialect: omp.critical
+!LLVMDialect: omp.critical
+!LLVMIR: call void @__kmpc_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}_.var)
+!$OMP CRITICAL
+ y = x + y
+!FIRDialect: omp.terminator
+!LLVMDialect: omp.terminator
+!LLVMIR: call void @__kmpc_end_critical({{.*}}, {{.*}}, {{.*}} @{{.*}}_.var)
+!$OMP END CRITICAL
+end subroutine omp_critical
More information about the flang-commits
mailing list