Skip to content

Commit

Permalink
[Flang] Add a semantic check and LLVM Lowering support for UNTIED TASK
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Thirumalai-Shaktivel committed Dec 24, 2024
1 parent 334a576 commit 5eb942e
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 25 deletions.
1 change: 1 addition & 0 deletions flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2867,6 +2867,7 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
!std::holds_alternative<clause::UseDevicePtr>(clause.u) &&
!std::holds_alternative<clause::InReduction>(clause.u) &&
!std::holds_alternative<clause::Mergeable>(clause.u) &&
!std::holds_alternative<clause::Untied>(clause.u) &&
!std::holds_alternative<clause::TaskReduction>(clause.u) &&
!std::holds_alternative<clause::Detach>(clause.u)) {
std::string name =
Expand Down
33 changes: 33 additions & 0 deletions flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,29 @@ class AssociatedLoopChecker {
std::map<std::string, std::int64_t> constructNamesAndLevels_;
};

// `OmpDesignatorChecker` is used to check if the designator
// can appear within the OpenMP construct
class OmpDesignatorChecker {
public:
OmpDesignatorChecker(SemanticsContext &context) : context_{context} {}

template <typename T> bool Pre(const T &) { return true; }
template <typename T> 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();
Expand Down Expand Up @@ -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<parser::OmpClauseList>(beginBlockDir.t)};
for (const auto &clause : clauses.v) {
if (std::get_if<parser::OmpClause::Untied>(&clause.u)) {
OmpDesignatorChecker ompDesignatorChecker{context_};
parser::Walk(block, ompDesignatorChecker);
}
}
break;
}
default:
break;
}
Expand Down
13 changes: 0 additions & 13 deletions flang/test/Lower/OpenMP/Todo/task_untied.f90

This file was deleted.

17 changes: 17 additions & 0 deletions flang/test/Lower/OpenMP/task.f90
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,27 @@ subroutine task_multiple_clauses()
!$omp end task
end subroutine task_multiple_clauses

!===============================================================================
! `mergeable` clause
!===============================================================================

subroutine task_mergeable()
!CHECK: omp.task mergeable {
!CHECK: omp.terminator
!CHECK: }
!$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
28 changes: 28 additions & 0 deletions flang/test/Semantics/OpenMP/task-united01.f90
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
12 changes: 12 additions & 0 deletions mlir/test/Target/LLVMIR/openmp-llvm.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
24 changes: 13 additions & 11 deletions mlir/test/Target/LLVMIR/openmp-todo.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down Expand Up @@ -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}}
Expand Down

0 comments on commit 5eb942e

Please sign in to comment.