Skip to content

Commit b41b736

Browse files
authored
Re-apply: [flang][OpenMP] Support MLIR lowering of linear clause for omp.wsloop (llvm#139385) (llvm#3935)
This PR re-applies upstream PR llvm#139385 which was reverted previously. Ran flang-446525 and it passes.
1 parent 2093bb0 commit b41b736

File tree

10 files changed

+383
-17
lines changed

10 files changed

+383
-17
lines changed

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,40 @@ bool ClauseProcessor::processIsDevicePtr(
11431143
});
11441144
}
11451145

1146+
bool ClauseProcessor::processLinear(mlir::omp::LinearClauseOps &result) const {
1147+
lower::StatementContext stmtCtx;
1148+
return findRepeatableClause<
1149+
omp::clause::Linear>([&](const omp::clause::Linear &clause,
1150+
const parser::CharBlock &) {
1151+
auto &objects = std::get<omp::ObjectList>(clause.t);
1152+
for (const omp::Object &object : objects) {
1153+
semantics::Symbol *sym = object.sym();
1154+
const mlir::Value variable = converter.getSymbolAddress(*sym);
1155+
result.linearVars.push_back(variable);
1156+
}
1157+
if (objects.size()) {
1158+
if (auto &mod =
1159+
std::get<std::optional<omp::clause::Linear::StepComplexModifier>>(
1160+
clause.t)) {
1161+
mlir::Value operand =
1162+
fir::getBase(converter.genExprValue(toEvExpr(*mod), stmtCtx));
1163+
result.linearStepVars.append(objects.size(), operand);
1164+
} else if (std::get<std::optional<omp::clause::Linear::LinearModifier>>(
1165+
clause.t)) {
1166+
mlir::Location currentLocation = converter.getCurrentLocation();
1167+
TODO(currentLocation, "Linear modifiers not yet implemented");
1168+
} else {
1169+
// If nothing is present, add the default step of 1.
1170+
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
1171+
mlir::Location currentLocation = converter.getCurrentLocation();
1172+
mlir::Value operand = firOpBuilder.createIntegerConstant(
1173+
currentLocation, firOpBuilder.getI32Type(), 1);
1174+
result.linearStepVars.append(objects.size(), operand);
1175+
}
1176+
}
1177+
});
1178+
}
1179+
11461180
bool ClauseProcessor::processLink(
11471181
llvm::SmallVectorImpl<DeclareTargetCaptureInfo> &result) const {
11481182
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
@@ -127,6 +127,7 @@ class ClauseProcessor {
127127
bool processIsDevicePtr(
128128
mlir::omp::IsDevicePtrClauseOps &result,
129129
llvm::SmallVectorImpl<const semantics::Symbol *> &isDeviceSyms) const;
130+
bool processLinear(mlir::omp::LinearClauseOps &result) const;
130131
bool
131132
processLink(llvm::SmallVectorImpl<DeclareTargetCaptureInfo> &result) const;
132133

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ bool DataSharingProcessor::needBarrier() {
300300
// Emit implicit barrier to synchronize threads and avoid data races on
301301
// initialization of firstprivate variables and post-update of lastprivate
302302
// variables.
303-
// Emit implicit barrier for linear clause. Maybe on somewhere else.
303+
// Emit implicit barrier for linear clause in the OpenMPIRBuilder.
304304
for (const semantics::Symbol *sym : allPrivatizedSymbols) {
305305
if (sym->test(semantics::Symbol::Flag::OmpLastPrivate) &&
306306
(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
@@ -1847,13 +1847,13 @@ static void genWsloopClauses(
18471847
llvm::SmallVectorImpl<const semantics::Symbol *> &reductionSyms) {
18481848
ClauseProcessor cp(converter, semaCtx, clauses);
18491849
cp.processNowait(clauseOps);
1850+
cp.processLinear(clauseOps);
18501851
cp.processOrder(clauseOps);
18511852
cp.processOrdered(clauseOps);
18521853
cp.processReduction(loc, clauseOps, reductionSyms);
18531854
cp.processSchedule(stmtCtx, clauseOps);
18541855

1855-
cp.processTODO<clause::Allocate, clause::Linear>(
1856-
loc, llvm::omp::Directive::OMPD_do);
1856+
cp.processTODO<clause::Allocate>(loc, llvm::omp::Directive::OMPD_do);
18571857
}
18581858

18591859
//===----------------------------------------------------------------------===//
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

llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3764,6 +3764,9 @@ class CanonicalLoopInfo {
37643764
BasicBlock *Latch = nullptr;
37653765
BasicBlock *Exit = nullptr;
37663766

3767+
// Hold the MLIR value for the `lastiter` of the canonical loop.
3768+
Value *LastIter = nullptr;
3769+
37673770
/// Add the control blocks of this loop to \p BBs.
37683771
///
37693772
/// This does not include any block from the body, including the one returned
@@ -3796,6 +3799,18 @@ class CanonicalLoopInfo {
37963799
void mapIndVar(llvm::function_ref<Value *(Instruction *)> Updater);
37973800

37983801
public:
3802+
/// Sets the last iteration variable for this loop.
3803+
void setLastIter(Value *IterVar) { LastIter = std::move(IterVar); }
3804+
3805+
/// Returns the last iteration variable for this loop.
3806+
/// Certain use-cases (like translation of linear clause) may access
3807+
/// this variable even after a loop transformation. Hence, do not guard
3808+
/// this getter function by `isValid`. It is the responsibility of the
3809+
/// callee to ensure this functionality is not invoked by a non-outlined
3810+
/// CanonicalLoopInfo object (in which case, `setLastIter` will never be
3811+
/// invoked and `LastIter` will be by default `nullptr`).
3812+
Value *getLastIter() { return LastIter; }
3813+
37993814
/// Returns whether this object currently represents the IR of a loop. If
38003815
/// returning false, it may have been consumed by a loop transformation or not
38013816
/// been intialized. Do not use in this case;

llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4732,6 +4732,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::applyStaticWorkshareLoop(
47324732
Value *PLowerBound = Builder.CreateAlloca(IVTy, nullptr, "p.lowerbound");
47334733
Value *PUpperBound = Builder.CreateAlloca(IVTy, nullptr, "p.upperbound");
47344734
Value *PStride = Builder.CreateAlloca(IVTy, nullptr, "p.stride");
4735+
CLI->setLastIter(PLastIter);
47354736

47364737
// At the end of the preheader, prepare for calling the "init" function by
47374738
// storing the current loop bounds into the allocated space. A canonical loop
@@ -4840,6 +4841,7 @@ OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(DebugLoc DL,
48404841
Value *PUpperBound =
48414842
Builder.CreateAlloca(InternalIVTy, nullptr, "p.upperbound");
48424843
Value *PStride = Builder.CreateAlloca(InternalIVTy, nullptr, "p.stride");
4844+
CLI->setLastIter(PLastIter);
48434845

48444846
// Set up the source location value for the OpenMP runtime.
48454847
Builder.restoreIP(CLI->getPreheaderIP());
@@ -5325,6 +5327,7 @@ OpenMPIRBuilder::applyDynamicWorkshareLoop(DebugLoc DL, CanonicalLoopInfo *CLI,
53255327
Value *PLowerBound = Builder.CreateAlloca(IVTy, nullptr, "p.lowerbound");
53265328
Value *PUpperBound = Builder.CreateAlloca(IVTy, nullptr, "p.upperbound");
53275329
Value *PStride = Builder.CreateAlloca(IVTy, nullptr, "p.stride");
5330+
CLI->setLastIter(PLastIter);
53285331

53295332
// At the end of the preheader, prepare for calling the "init" function by
53305333
// storing the current loop bounds into the allocated space. A canonical loop

0 commit comments

Comments
 (0)