[flang-commits] [flang] [Flang][OpenMP][MLIR] Lowering of reduction, inreduction, nogroup and lastprivate clause to MLIR (PR #166751)
Kaviya Rajendiran via flang-commits
flang-commits at lists.llvm.org
Mon Nov 10 00:37:59 PST 2025
https://github.com/kaviya2510 updated https://github.com/llvm/llvm-project/pull/166751
>From 397edbf18ab97b63515c00a6f552bf6468c4579e Mon Sep 17 00:00:00 2001
From: Kaviya Rajendiran <kaviyara2000 at gmail.com>
Date: Thu, 6 Nov 2025 16:47:33 +0530
Subject: [PATCH 1/2] [Flang][OpenMP][MLIR] Lowering of reduction,inreduction,
nogroup and lastprivate clause to MLIR
---
flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 5 ++
flang/lib/Lower/OpenMP/ClauseProcessor.h | 1 +
.../lib/Lower/OpenMP/DataSharingProcessor.cpp | 3 +-
flang/lib/Lower/OpenMP/OpenMP.cpp | 30 +++++++----
.../OpenMP/Todo/taskloop-inreduction.f90 | 13 -----
.../Lower/OpenMP/Todo/taskloop-reduction.f90 | 13 -----
flang/test/Lower/OpenMP/taskloop.f90 | 52 +++++++++++++++++++
flang/test/Lower/taskloop-inreduction.f90 | 40 ++++++++++++++
flang/test/Lower/taskloop-reduction.f90 | 39 ++++++++++++++
9 files changed, 159 insertions(+), 37 deletions(-)
delete mode 100644 flang/test/Lower/OpenMP/Todo/taskloop-inreduction.f90
delete mode 100644 flang/test/Lower/OpenMP/Todo/taskloop-reduction.f90
create mode 100644 flang/test/Lower/taskloop-inreduction.f90
create mode 100644 flang/test/Lower/taskloop-reduction.f90
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 1c163e6de7e5a..872f31fe45cca 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -406,6 +406,11 @@ bool ClauseProcessor::processMergeable(
return markClauseOccurrence<omp::clause::Mergeable>(result.mergeable);
}
+bool ClauseProcessor::processNogroup(
+ mlir::omp::NogroupClauseOps &result) const {
+ return markClauseOccurrence<omp::clause::Nogroup>(result.nogroup);
+}
+
bool ClauseProcessor::processNowait(mlir::omp::NowaitClauseOps &result) const {
return markClauseOccurrence<omp::clause::Nowait>(result.nowait);
}
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h
index 6452e39b97551..d524b4ddc8ac4 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.h
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h
@@ -89,6 +89,7 @@ class ClauseProcessor {
bool processInclusive(mlir::Location currentLocation,
mlir::omp::InclusiveClauseOps &result) const;
bool processMergeable(mlir::omp::MergeableClauseOps &result) const;
+ bool processNogroup(mlir::omp::NogroupClauseOps &result) const;
bool processNowait(mlir::omp::NowaitClauseOps &result) const;
bool processNumTasks(lower::StatementContext &stmtCtx,
mlir::omp::NumTasksClauseOps &result) const;
diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
index 146a252b049ec..c5f7a0f710e8a 100644
--- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
@@ -342,7 +342,8 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) {
if (!hasLastPrivate)
return;
- if (mlir::isa<mlir::omp::WsloopOp>(op) || mlir::isa<mlir::omp::SimdOp>(op)) {
+ if (mlir::isa<mlir::omp::WsloopOp>(op) || mlir::isa<mlir::omp::SimdOp>(op) ||
+ mlir::isa<mlir::omp::TaskloopOp>(op)) {
mlir::omp::LoopRelatedClauseOps result;
llvm::SmallVector<const semantics::Symbol *> iv;
collectLoopRelatedInfo(converter, converter.getCurrentLocation(), eval,
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index ad456d89bc432..cb006211cc208 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -1763,21 +1763,24 @@ static void genTaskgroupClauses(
cp.processTaskReduction(loc, clauseOps, taskReductionSyms);
}
-static void genTaskloopClauses(lower::AbstractConverter &converter,
- semantics::SemanticsContext &semaCtx,
- lower::StatementContext &stmtCtx,
- const List<Clause> &clauses, mlir::Location loc,
- mlir::omp::TaskloopOperands &clauseOps) {
+static void genTaskloopClauses(
+ lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
+ lower::StatementContext &stmtCtx, const List<Clause> &clauses,
+ mlir::Location loc, mlir::omp::TaskloopOperands &clauseOps,
+ llvm::SmallVectorImpl<const semantics::Symbol *> &reductionSyms,
+ llvm::SmallVectorImpl<const semantics::Symbol *> &inReductionSyms) {
ClauseProcessor cp(converter, semaCtx, clauses);
cp.processGrainsize(stmtCtx, clauseOps);
cp.processNumTasks(stmtCtx, clauseOps);
+ cp.processNogroup(clauseOps);
+ cp.processReduction(loc, clauseOps, reductionSyms);
+ cp.processInReduction(loc, clauseOps, inReductionSyms);
cp.processTODO<clause::Allocate, clause::Collapse, clause::Default,
- clause::Final, clause::If, clause::InReduction,
- clause::Lastprivate, clause::Mergeable, clause::Nogroup,
- clause::Priority, clause::Reduction, clause::Shared,
- clause::Untied>(loc, llvm::omp::Directive::OMPD_taskloop);
+ clause::Final, clause::If, clause::Mergeable, clause::Priority,
+ clause::Shared, clause::Untied>(
+ loc, llvm::omp::Directive::OMPD_taskloop);
}
static void genTaskwaitClauses(lower::AbstractConverter &converter,
@@ -2979,8 +2982,11 @@ static mlir::omp::TaskloopOp genStandaloneTaskloop(
lower::pft::Evaluation &eval, mlir::Location loc,
const ConstructQueue &queue, ConstructQueue::const_iterator item) {
mlir::omp::TaskloopOperands taskloopClauseOps;
+ llvm::SmallVector<const semantics::Symbol *> reductionSyms;
+ llvm::SmallVector<const semantics::Symbol *> inReductionSyms;
+
genTaskloopClauses(converter, semaCtx, stmtCtx, item->clauses, loc,
- taskloopClauseOps);
+ taskloopClauseOps, reductionSyms, inReductionSyms);
DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval,
/*shouldCollectPreDeterminedSymbols=*/true,
enableDelayedPrivatization, symTable);
@@ -2994,6 +3000,10 @@ static mlir::omp::TaskloopOp genStandaloneTaskloop(
EntryBlockArgs taskloopArgs;
taskloopArgs.priv.syms = dsp.getDelayedPrivSymbols();
taskloopArgs.priv.vars = taskloopClauseOps.privateVars;
+ taskloopArgs.reduction.syms = reductionSyms;
+ taskloopArgs.reduction.vars = taskloopClauseOps.reductionVars;
+ taskloopArgs.inReduction.syms = inReductionSyms;
+ taskloopArgs.inReduction.vars = taskloopClauseOps.inReductionVars;
auto taskLoopOp = genWrapperOp<mlir::omp::TaskloopOp>(
converter, loc, taskloopClauseOps, taskloopArgs);
diff --git a/flang/test/Lower/OpenMP/Todo/taskloop-inreduction.f90 b/flang/test/Lower/OpenMP/Todo/taskloop-inreduction.f90
deleted file mode 100644
index 8acc399a92abe..0000000000000
--- a/flang/test/Lower/OpenMP/Todo/taskloop-inreduction.f90
+++ /dev/null
@@ -1,13 +0,0 @@
-! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
-! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
-
-! CHECK: not yet implemented: Unhandled clause IN_REDUCTION in TASKLOOP construct
-subroutine omp_taskloop_inreduction()
- integer x
- x = 0
- !$omp taskloop in_reduction(+:x)
- do i = 1, 100
- x = x + 1
- end do
- !$omp end taskloop
-end subroutine omp_taskloop_inreduction
diff --git a/flang/test/Lower/OpenMP/Todo/taskloop-reduction.f90 b/flang/test/Lower/OpenMP/Todo/taskloop-reduction.f90
deleted file mode 100644
index 0c16bd227257f..0000000000000
--- a/flang/test/Lower/OpenMP/Todo/taskloop-reduction.f90
+++ /dev/null
@@ -1,13 +0,0 @@
-! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
-! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
-
-! CHECK: not yet implemented: Unhandled clause REDUCTION in TASKLOOP construct
-subroutine omp_taskloop_reduction()
- integer x
- x = 0
- !$omp taskloop reduction(+:x)
- do i = 1, 100
- x = x + 1
- end do
- !$omp end taskloop
-end subroutine omp_taskloop_reduction
diff --git a/flang/test/Lower/OpenMP/taskloop.f90 b/flang/test/Lower/OpenMP/taskloop.f90
index 79b0c20e176c0..f23fbe13a52a5 100644
--- a/flang/test/Lower/OpenMP/taskloop.f90
+++ b/flang/test/Lower/OpenMP/taskloop.f90
@@ -1,6 +1,15 @@
! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
+! CHECK-LABEL: omp.private
+! CHECK-SAME: {type = private} @[[LAST_PRIVATE_I:.*]] : i32
+
+! CHECK-LABEL: omp.private
+! CHECK-SAME: {type = private} @[[LAST_PRIVATE_X:.*]] : i32
+
+! CHECK-LABEL: omp.private
+! CHECK-SAME: {type = private} @[[QFOMP_TASKLOOP_NOGROUPEI_PRIVATE_I32:.*]] : i32
+
! CHECK-LABEL: omp.private
! CHECK-SAME: {type = private} @[[I_PRIVATE_TEST2:.*]] : i32
@@ -70,3 +79,46 @@ subroutine omp_taskloop_private
! CHECK: }
!$omp end taskloop
end subroutine omp_taskloop_private
+
+!===============================================================================
+! `nogroup` clause
+!===============================================================================
+
+subroutine omp_taskloop_nogroup()
+ ! CHECK: omp.taskloop nogroup
+ !$omp taskloop nogroup
+ do i = 1, 10
+ call foo()
+ end do
+ !$omp end taskloop
+end subroutine
+
+!===============================================================================
+! `lastprivate` clause
+!===============================================================================
+
+! CHECK-LABEL: func.func @_QPomp_taskloop_lastprivate
+! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_taskloop_lastprivateEi"}
+! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] {uniq_name = "_QFomp_taskloop_lastprivateEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[ALLOCA_X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFomp_taskloop_lastprivateEx"}
+! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ALLOCA_X]] {uniq_name = "_QFomp_taskloop_lastprivateEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+subroutine omp_taskloop_lastprivate()
+ integer x
+ x = 0
+ ! CHECK: omp.taskloop private(@[[LAST_PRIVATE_X]] %[[DECL_X]]#0 -> %[[ARG0]], @[[LAST_PRIVATE_I]] %[[DECL_I]]#0 -> %[[ARG1]] : !fir.ref<i32>, !fir.ref<i32>) {
+ !$omp taskloop lastprivate(x)
+ do i = 1, 100
+ ! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFomp_taskloop_lastprivateEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ ! CHECK: %[[LOAD_ARG0:.*]] = fir.load %[[DECL_ARG0]]#0 : !fir.ref<i32>
+ ! CHECK: %[[RES_ADD:.*]] = arith.addi %[[LOAD_ARG0]], %{{.*}} : i32
+ ! CHECK: hlfir.assign %[[RES_ADD]] to %[[DECL_ARG0]]#0 : i32, !fir.ref<i32>
+ x = x + 1
+ ! CHECK: %[[SELCT_RESULT:.*]] = arith.select %{{.*}}, %{{.*}}, %{{.*}} : i1
+ ! CHECK: fir.if %[[SELCT_RESULT]] {
+ ! CHECK: %[[LOADED_SUM:.*]] = fir.load %[[DECL_ARG0]]#0 : !fir.ref<i32>
+ ! CHECK: hlfir.assign %[[LOADED_SUM]] to %[[DECL_X]]#0 : i32, !fir.ref<i32>
+ ! CHECK: }
+ ! CHECK: omp.yield
+ end do
+ !$omp end taskloop
+end subroutine omp_taskloop_lastprivate
diff --git a/flang/test/Lower/taskloop-inreduction.f90 b/flang/test/Lower/taskloop-inreduction.f90
new file mode 100644
index 0000000000000..e7d3f96115fbd
--- /dev/null
+++ b/flang/test/Lower/taskloop-inreduction.f90
@@ -0,0 +1,40 @@
+! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
+
+! CHECK-LABEL: omp.private
+! CHECK-SAME: {type = private} @[[PRIVATE_I:.*]] : i32
+
+! CHECK-LABEL: omp.declare_reduction
+! CHECK-SAME: @[[ADD_RED_I32:.*]] : i32 init {
+! CHECK: ^bb0(%{{.*}}: i32):
+! CHECK: %[[C0_I32:.*]] = arith.constant 0 : i32
+! CHECK: omp.yield(%[[C0_I32]] : i32)
+! CHECK: } combiner {
+! CHECK: ^bb0(%{{.*}}: i32, %{{.*}}: i32):
+! CHECK: %[[RES:.*]] = arith.addi %{{.*}}, %{{.*}} : i32
+! CHECK: omp.yield(%[[RES]] : i32)
+! CHECK: }
+
+! CHECK-LABEL: func.func @_QPomp_taskloop_inreduction
+! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_taskloop_inreductionEi"}
+! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] {uniq_name = "_QFomp_taskloop_inreductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[ALLOCA_X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFomp_taskloop_inreductionEx"}
+! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ALLOCA_X]] {uniq_name = "_QFomp_taskloop_inreductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[INIT_X:.*]] = arith.constant 0 : i32
+! CHECK: hlfir.assign %[[INIT_X]] to %[[DECL_X]]#0 : i32, !fir.ref<i32>
+subroutine omp_taskloop_inreduction()
+ integer x
+ x = 0
+ ! CHECK: omp.taskloop in_reduction(@[[ADD_RED_I32]]
+ ! CHECK: %[[DECL_X]]#0 -> %[[ARG0:.*]] : !fir.ref<i32>) private(@[[PRIVATE_I]] %[[DECL_I]]#0 -> %[[ARG1:.*]] : !fir.ref<i32>) {
+ ! CHECK: %[[VAL_ARG1:.*]]:2 = hlfir.declare %[[ARG0]]
+ ! CHECK-SAME: {uniq_name = "_QFomp_taskloop_inreductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ !$omp taskloop in_reduction(+:x)
+ do i = 1, 100
+ ! CHECK: %[[X_VAL:.*]] = fir.load %[[VAL_ARG1]]#0 : !fir.ref<i32>
+ ! CHECK: %[[ADD_VAL:.*]] = arith.addi %[[X_VAL]], %{{.*}} : i32
+ x = x + 1
+ ! CHECK: hlfir.assign %[[ADD_VAL]] to %[[VAL_ARG1]]#0 : i32, !fir.ref<i32>
+ end do
+ !$omp end taskloop
+end subroutine omp_taskloop_inreduction
diff --git a/flang/test/Lower/taskloop-reduction.f90 b/flang/test/Lower/taskloop-reduction.f90
new file mode 100644
index 0000000000000..e45c0181bcc8b
--- /dev/null
+++ b/flang/test/Lower/taskloop-reduction.f90
@@ -0,0 +1,39 @@
+! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
+
+! CHECK-LABEL: omp.private
+! CHECK-SAME: {type = private} @[[PRIVATE_I:.*]] : i32
+
+! CHECK-LABEL: omp.declare_reduction
+! CHECK-SAME: @[[ADD_RED_I32:.*]] : i32 init {
+! CHECK: ^bb0(%{{.*}}: i32):
+! CHECK: %[[C0_I32:.*]] = arith.constant 0 : i32
+! CHECK: omp.yield(%[[C0_I32]] : i32)
+! CHECK: } combiner {
+! CHECK: ^bb0(%{{.*}}: i32, %{{.*}}: i32):
+! CHECK: %[[RES:.*]] = arith.addi %{{.*}}, %{{.*}} : i32
+! CHECK: omp.yield(%[[RES]] : i32)
+! CHECK: }
+
+! CHECK-LABEL: func.func @_QPomp_taskloop_reduction
+! CHECK: %[[ALLOCA_I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_taskloop_reductionEi"}
+! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %[[ALLOCA_I]] {uniq_name = "_QFomp_taskloop_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[ALLOCA_X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFomp_taskloop_reductionEx"}
+! CHECK: %[[DECL_X:.*]]:2 = hlfir.declare %[[ALLOCA_X]] {uniq_name = "_QFomp_taskloop_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[INIT_X:.*]] = arith.constant 0 : i32
+! CHECK: hlfir.assign %[[INIT_X]] to %[[DECL_X]]#0 : i32, !fir.ref<i32>
+subroutine omp_taskloop_reduction()
+ integer x
+ x = 0
+ ! CHECK: omp.taskloop private(@[[PRIVATE_I]]
+ ! CHECK-SAME: %[[DECL_I]]#0 -> %[[ARG0:.*]] : !fir.ref<i32>) reduction(@[[ADD_RED_I32]] %[[DECL_X]]#0 -> %[[ARG1:.*]] : !fir.ref<i32>) {
+ ! CHECK: %[[VAL_ARG1:.*]]:2 = hlfir.declare %[[ARG1]]
+ !$omp taskloop reduction(+:x)
+ do i = 1, 100
+ ! CHECK: %[[X_VAL:.*]] = fir.load %[[VAL_ARG1]]#0 : !fir.ref<i32>
+ ! CHECK: %[[ADD_VAL:.*]] = arith.addi %[[X_VAL]], %{{.*}} : i32
+ x = x + 1
+ ! CHECK: hlfir.assign %[[ADD_VAL]] to %[[VAL_ARG1]]#0 : i32, !fir.ref<i32>
+ end do
+ !$omp end taskloop
+end subroutine omp_taskloop_reduction
>From 78c24063a89d441f03e2efaf9da51970add3a032 Mon Sep 17 00:00:00 2001
From: Kaviya Rajendiran <kaviyara2000 at gmail.com>
Date: Mon, 10 Nov 2025 13:12:01 +0530
Subject: [PATCH 2/2] [Flang][OpenMP][MLIR]Updated the error message for
lastprivate clause
---
flang/lib/Lower/OpenMP/DataSharingProcessor.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
index c5f7a0f710e8a..83c2eda0a2dc7 100644
--- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
@@ -409,7 +409,7 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) {
} else {
TODO(converter.getCurrentLocation(),
"lastprivate clause in constructs other than "
- "simd/worksharing-loop");
+ "simd/worksharing-loop/taskloop");
}
}
More information about the flang-commits
mailing list