Skip to content

Commit e4f3cb2

Browse files
committed
[flang][OpenMP] Support MLIR lowering of linear clause for omp.wsloop
1 parent fe56c8f commit e4f3cb2

File tree

5 files changed

+97
-4
lines changed

5 files changed

+97
-4
lines changed

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,40 @@ bool ClauseProcessor::processIsDevicePtr(
10601060
});
10611061
}
10621062

1063+
bool ClauseProcessor::processLinear(mlir::omp::LinearClauseOps &result) const {
1064+
lower::StatementContext stmtCtx;
1065+
return findRepeatableClause<
1066+
omp::clause::Linear>([&](const omp::clause::Linear &clause,
1067+
const parser::CharBlock &) {
1068+
auto &objects = std::get<omp::ObjectList>(clause.t);
1069+
for (const omp::Object &object : objects) {
1070+
semantics::Symbol *sym = object.sym();
1071+
const mlir::Value variable = converter.getSymbolAddress(*sym);
1072+
result.linearVars.push_back(variable);
1073+
}
1074+
if (objects.size()) {
1075+
if (auto &mod =
1076+
std::get<std::optional<omp::clause::Linear::StepComplexModifier>>(
1077+
clause.t)) {
1078+
mlir::Value operand =
1079+
fir::getBase(converter.genExprValue(toEvExpr(*mod), stmtCtx));
1080+
result.linearStepVars.append(objects.size(), operand);
1081+
} else if (std::get<std::optional<omp::clause::Linear::LinearModifier>>(
1082+
clause.t)) {
1083+
mlir::Location currentLocation = converter.getCurrentLocation();
1084+
TODO(currentLocation, "Linear modifiers not yet implemented");
1085+
} else {
1086+
// If nothing is present, add the default step of 1.
1087+
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
1088+
mlir::Location currentLocation = converter.getCurrentLocation();
1089+
mlir::Value operand = firOpBuilder.createIntegerConstant(
1090+
currentLocation, firOpBuilder.getI32Type(), 1);
1091+
result.linearStepVars.append(objects.size(), operand);
1092+
}
1093+
}
1094+
});
1095+
}
1096+
10631097
bool ClauseProcessor::processLink(
10641098
llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const {
10651099
return findRepeatableClause<omp::clause::Link>(

flang/lib/Lower/OpenMP/ClauseProcessor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ class ClauseProcessor {
122122
bool processIsDevicePtr(
123123
mlir::omp::IsDevicePtrClauseOps &result,
124124
llvm::SmallVectorImpl<const semantics::Symbol *> &isDeviceSyms) const;
125+
bool processLinear(mlir::omp::LinearClauseOps &result) const;
125126
bool
126127
processLink(llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const;
127128

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,14 +213,15 @@ void DataSharingProcessor::collectSymbolsForPrivatization() {
213213
// so, we won't need to explicitely handle block objects (or forget to do
214214
// so).
215215
for (auto *sym : explicitlyPrivatizedSymbols)
216-
allPrivatizedSymbols.insert(sym);
216+
if (!sym->test(Fortran::semantics::Symbol::Flag::OmpLinear))
217+
allPrivatizedSymbols.insert(sym);
217218
}
218219

219220
bool DataSharingProcessor::needBarrier() {
220221
// Emit implicit barrier to synchronize threads and avoid data races on
221222
// initialization of firstprivate variables and post-update of lastprivate
222223
// variables.
223-
// Emit implicit barrier for linear clause. Maybe on somewhere else.
224+
// Emit implicit barrier for linear clause in the OpenMPIRBuilder.
224225
for (const semantics::Symbol *sym : allPrivatizedSymbols) {
225226
if (sym->test(semantics::Symbol::Flag::OmpLastPrivate) &&
226227
(sym->test(semantics::Symbol::Flag::OmpFirstPrivate) ||

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,13 +1841,13 @@ static void genWsloopClauses(
18411841
llvm::SmallVectorImpl<const semantics::Symbol *> &reductionSyms) {
18421842
ClauseProcessor cp(converter, semaCtx, clauses);
18431843
cp.processNowait(clauseOps);
1844+
cp.processLinear(clauseOps);
18441845
cp.processOrder(clauseOps);
18451846
cp.processOrdered(clauseOps);
18461847
cp.processReduction(loc, clauseOps, reductionSyms);
18471848
cp.processSchedule(stmtCtx, clauseOps);
18481849

1849-
cp.processTODO<clause::Allocate, clause::Linear>(
1850-
loc, llvm::omp::Directive::OMPD_do);
1850+
cp.processTODO<clause::Allocate>(loc, llvm::omp::Directive::OMPD_do);
18511851
}
18521852

18531853
//===----------------------------------------------------------------------===//
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
! This test checks lowering of OpenMP DO Directive (Worksharing)
2+
! with linear clause
3+
4+
! RUN: %flang_fc1 -fopenmp -emit-hlfir %s -o - 2>&1 | FileCheck %s
5+
6+
!CHECK: %[[X_alloca:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_linearEx"}
7+
!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_alloca]] {uniq_name = "_QFsimple_linearEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
8+
!CHECK: %[[const:.*]] = arith.constant 1 : i32
9+
subroutine simple_linear
10+
implicit none
11+
integer :: x, y, i
12+
!CHECK: omp.wsloop linear(%[[X]]#0 = %[[const]] : !fir.ref<i32>) {{.*}}
13+
!$omp do linear(x)
14+
!CHECK: %[[LOAD:.*]] = fir.load %[[X]]#0 : !fir.ref<i32>
15+
!CHECK: %[[const:.*]] = arith.constant 2 : i32
16+
!CHECK: %[[RESULT:.*]] = arith.addi %[[LOAD]], %[[const]] : i32
17+
do i = 1, 10
18+
y = x + 2
19+
end do
20+
!$omp end do
21+
end subroutine
22+
23+
24+
!CHECK: %[[X_alloca:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFlinear_stepEx"}
25+
!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_alloca]] {uniq_name = "_QFlinear_stepEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
26+
subroutine linear_step
27+
implicit none
28+
integer :: x, y, i
29+
!CHECK: %[[const:.*]] = arith.constant 4 : i32
30+
!CHECK: omp.wsloop linear(%[[X]]#0 = %[[const]] : !fir.ref<i32>) {{.*}}
31+
!$omp do linear(x:4)
32+
!CHECK: %[[LOAD:.*]] = fir.load %[[X]]#0 : !fir.ref<i32>
33+
!CHECK: %[[const:.*]] = arith.constant 2 : i32
34+
!CHECK: %[[RESULT:.*]] = arith.addi %[[LOAD]], %[[const]] : i32
35+
do i = 1, 10
36+
y = x + 2
37+
end do
38+
!$omp end do
39+
end subroutine
40+
41+
!CHECK: %[[A_alloca:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFlinear_exprEa"}
42+
!CHECK: %[[A:.*]]:2 = hlfir.declare %[[A_alloca]] {uniq_name = "_QFlinear_exprEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
43+
!CHECK: %[[X_alloca:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFlinear_exprEx"}
44+
!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_alloca]] {uniq_name = "_QFlinear_exprEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
45+
subroutine linear_expr
46+
implicit none
47+
integer :: x, y, i, a
48+
!CHECK: %[[LOAD_A:.*]] = fir.load %[[A]]#0 : !fir.ref<i32>
49+
!CHECK: %[[const:.*]] = arith.constant 4 : i32
50+
!CHECK: %[[LINEAR_EXPR:.*]] = arith.addi %[[LOAD_A]], %[[const]] : i32
51+
!CHECK: omp.wsloop linear(%[[X]]#0 = %[[LINEAR_EXPR]] : !fir.ref<i32>) {{.*}}
52+
!$omp do linear(x:a+4)
53+
do i = 1, 10
54+
y = x + 2
55+
end do
56+
!$omp end do
57+
end subroutine

0 commit comments

Comments
 (0)