From 5eb942e4c56de1ce7666a080900496d8c67b85b3 Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel Date: Tue, 24 Dec 2024 15:14:44 +0000 Subject: [PATCH] [Flang] Add a semantic check and LLVM Lowering support for UNTIED TASK Implementation details: The UNTIED clause is recognized by setting the flag=0 for the default case or performing logical OR to flag if other clauses are specified, and this flag is passed as an argument to the `__kmpc_omp_task_alloc` runtime call. --- flang/lib/Lower/OpenMP/OpenMP.cpp | 1 + flang/lib/Semantics/check-omp-structure.cpp | 33 +++++++++++++++++++ flang/test/Lower/OpenMP/Todo/task_untied.f90 | 13 -------- flang/test/Lower/OpenMP/task.f90 | 17 ++++++++++ flang/test/Semantics/OpenMP/task-united01.f90 | 28 ++++++++++++++++ .../OpenMP/OpenMPToLLVMIRTranslation.cpp | 5 ++- mlir/test/Target/LLVMIR/openmp-llvm.mlir | 12 +++++++ mlir/test/Target/LLVMIR/openmp-todo.mlir | 24 +++++++------- 8 files changed, 108 insertions(+), 25 deletions(-) delete mode 100644 flang/test/Lower/OpenMP/Todo/task_untied.f90 create mode 100644 flang/test/Semantics/OpenMP/task-united01.f90 diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index b07e89d201d198..4de5ecf187a4cb 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -2867,6 +2867,7 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, !std::holds_alternative(clause.u) && !std::holds_alternative(clause.u) && !std::holds_alternative(clause.u) && + !std::holds_alternative(clause.u) && !std::holds_alternative(clause.u) && !std::holds_alternative(clause.u)) { std::string name = diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 95b962f5daf57c..5fbe8f8a577cfd 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -213,6 +213,29 @@ class AssociatedLoopChecker { std::map constructNamesAndLevels_; }; +// `OmpDesignatorChecker` is used to check if the designator +// can appear within the OpenMP construct +class OmpDesignatorChecker { +public: + OmpDesignatorChecker(SemanticsContext &context) : context_{context} {} + + template bool Pre(const T &) { return true; } + template void Post(const T &) {} + + bool Pre(const parser::Name &name) { + if (name.symbol->test(Symbol::Flag::OmpThreadprivate)) { + // OpenMP 5.2: 5.2 threadprivate directive restriction + context_.Say(name.source, + "A THREADPRIVATE variable `%s` cannot appear in a UNTIED TASK region"_err_en_US, + name.source); + } + return true; + } + +private: + SemanticsContext &context_; +}; + bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) { unsigned version{context_.langOptions().OpenMPVersion}; DirectiveContext &dirCtx = GetContext(); @@ -1164,6 +1187,16 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { HasInvalidWorksharingNesting( beginDir.source, llvm::omp::nestedWorkshareErrSet); break; + case llvm::omp::Directive::OMPD_task: { + const auto &clauses{std::get(beginBlockDir.t)}; + for (const auto &clause : clauses.v) { + if (std::get_if(&clause.u)) { + OmpDesignatorChecker ompDesignatorChecker{context_}; + parser::Walk(block, ompDesignatorChecker); + } + } + break; + } default: break; } diff --git a/flang/test/Lower/OpenMP/Todo/task_untied.f90 b/flang/test/Lower/OpenMP/Todo/task_untied.f90 deleted file mode 100644 index 87d242ba3e9d21..00000000000000 --- a/flang/test/Lower/OpenMP/Todo/task_untied.f90 +++ /dev/null @@ -1,13 +0,0 @@ -! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s -! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s - -!=============================================================================== -! `untied` clause -!=============================================================================== - -! CHECK: not yet implemented: UNTIED clause is not implemented yet -subroutine omp_task_untied() - !$omp task untied - call foo() - !$omp end task -end subroutine omp_task_untied diff --git a/flang/test/Lower/OpenMP/task.f90 b/flang/test/Lower/OpenMP/task.f90 index 6e525a044b011e..a8cc16c540c9c8 100644 --- a/flang/test/Lower/OpenMP/task.f90 +++ b/flang/test/Lower/OpenMP/task.f90 @@ -235,6 +235,10 @@ subroutine task_multiple_clauses() !$omp end task end subroutine task_multiple_clauses +!=============================================================================== +! `mergeable` clause +!=============================================================================== + subroutine task_mergeable() !CHECK: omp.task mergeable { !CHECK: omp.terminator @@ -242,3 +246,16 @@ subroutine task_mergeable() !$omp task mergeable !$omp end task end subroutine + +!=============================================================================== +! `untied` clause +!=============================================================================== + +!CHECK-LABEL: func.func @_QPomp_task_untied() { +subroutine omp_task_untied() + !CHECK: omp.task untied { + !$omp task untied + call foo() + !CHECK: omp.terminator + !$omp end task +end subroutine omp_task_untied diff --git a/flang/test/Semantics/OpenMP/task-united01.f90 b/flang/test/Semantics/OpenMP/task-united01.f90 new file mode 100644 index 00000000000000..11227c0e919aa5 --- /dev/null +++ b/flang/test/Semantics/OpenMP/task-united01.f90 @@ -0,0 +1,28 @@ +! RUN: %python %S/../test_errors.py %s %flang %openmp_flags +! +! OpenMP 5.2: 5.2 threadprivate directive restriction + +subroutine task_united01() + integer, save :: var_01, var_02(2) + real :: var_03 + common /c/ var_03 + + !$omp threadprivate(var_01, var_02) + !$omp threadprivate(/c/) + + !$omp task untied + !ERROR: A THREADPRIVATE variable `var_01` cannot appear in a UNTIED TASK region + var_01 = 10 + !ERROR: A THREADPRIVATE variable `var_02` cannot appear in a UNTIED TASK region + !ERROR: A THREADPRIVATE variable `var_01` cannot appear in a UNTIED TASK region + var_02(1) = sum([var_01, 20]) + !$omp end task + + !$omp task untied + !ERROR: A THREADPRIVATE variable `var_02` cannot appear in a UNTIED TASK region + !ERROR: A THREADPRIVATE variable `var_02` cannot appear in a UNTIED TASK region + var_02(2) = product(var_02) + !ERROR: A THREADPRIVATE variable `var_03` cannot appear in a UNTIED TASK region + var_03 = 3.14 + !$omp end task +end subroutine task_united01 diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index 060113c4123241..d591c98a5497f8 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -258,7 +258,6 @@ static LogicalResult checkImplementationStatus(Operation &op) { checkAllocate(op, result); checkInReduction(op, result); checkPriority(op, result); - checkUntied(op, result); }) .Case([&](omp::TaskgroupOp op) { checkAllocate(op, result); @@ -268,6 +267,10 @@ static LogicalResult checkImplementationStatus(Operation &op) { checkDepend(op, result); checkNowait(op, result); }) + .Case([&](omp::TaskloopOp op) { + // TODO: Add other clauses check + checkUntied(op, result); + }) .Case([&](omp::WsloopOp op) { checkAllocate(op, result); checkLinear(op, result); diff --git a/mlir/test/Target/LLVMIR/openmp-llvm.mlir b/mlir/test/Target/LLVMIR/openmp-llvm.mlir index 5f8bdf8afdf783..8903bf283b5c75 100644 --- a/mlir/test/Target/LLVMIR/openmp-llvm.mlir +++ b/mlir/test/Target/LLVMIR/openmp-llvm.mlir @@ -3020,6 +3020,18 @@ module attributes {omp.is_target_device = true} { // ----- +llvm.func @omp_task_untied() { + // The third argument is 0: which signifies the united task + // CHECK: {{.*}} = call ptr @__kmpc_omp_task_alloc(ptr @1, i32 %{{.*}}, i32 0, + // CHECK-SAME: i64 40, i64 0, ptr @{{.*}}) + omp.task untied { + omp.terminator + } + llvm.return +} + +// ----- + // Third argument is 5: essentially (4 || 1) // signifying this task is TIED and MERGEABLE diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir index 8f3e466cfbbeb6..8ae795ec1ec6b0 100644 --- a/mlir/test/Target/LLVMIR/openmp-todo.mlir +++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir @@ -440,17 +440,6 @@ llvm.func @task_priority(%x : i32) { // ----- -llvm.func @task_untied() { - // expected-error@below {{not yet implemented: Unhandled clause untied in omp.task operation}} - // expected-error@below {{LLVM Translation failed for operation: omp.task}} - omp.task untied { - omp.terminator - } - llvm.return -} - -// ----- - llvm.func @taskgroup_allocate(%x : !llvm.ptr) { // expected-error@below {{not yet implemented: Unhandled clause allocate in omp.taskgroup operation}} // expected-error@below {{LLVM Translation failed for operation: omp.taskgroup}} @@ -503,6 +492,19 @@ llvm.func @taskloop(%lb : i32, %ub : i32, %step : i32) { // ----- +llvm.func @taskloop_untied(%lb : i32, %ub : i32, %step : i32) { + // expected-error@below {{not yet implemented: omp.taskloop}} + // expected-error@below {{LLVM Translation failed for operation: omp.taskloop}} + omp.taskloop untied { + omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) { + omp.yield + } + } + llvm.return +} + +// ----- + llvm.func @taskwait_depend(%x: !llvm.ptr) { // expected-error@below {{not yet implemented: Unhandled clause depend in omp.taskwait operation}} // expected-error@below {{LLVM Translation failed for operation: omp.taskwait}}