-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[flang][OpenMP][Lower] lower array subscripts for task depend #132994
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
| #include "Clauses.h" | ||
| #include "Utils.h" | ||
|
|
||
| #include "flang/Lower/ConvertExprToHLFIR.h" | ||
| #include "flang/Lower/PFTBuilder.h" | ||
| #include "flang/Parser/tools.h" | ||
| #include "flang/Semantics/tools.h" | ||
|
|
@@ -808,7 +809,21 @@ bool ClauseProcessor::processCopyprivate( | |
| return hasCopyPrivate; | ||
| } | ||
|
|
||
| bool ClauseProcessor::processDepend(mlir::omp::DependClauseOps &result) const { | ||
| template <typename T> | ||
| static bool isVectorSubscript(const evaluate::Expr<T> &expr) { | ||
| if (std::optional<evaluate::DataRef> dataRef{evaluate::ExtractDataRef(expr)}) | ||
| if (const auto *arrayRef = std::get_if<evaluate::ArrayRef>(&dataRef->u)) | ||
| for (const evaluate::Subscript &subscript : arrayRef->subscript()) | ||
| if (std::holds_alternative<evaluate::IndirectSubscriptIntegerExpr>( | ||
| subscript.u)) | ||
| if (subscript.Rank() > 0) | ||
| return true; | ||
| return false; | ||
| } | ||
|
|
||
| bool ClauseProcessor::processDepend(lower::SymMap &symMap, | ||
| lower::StatementContext &stmtCtx, | ||
| mlir::omp::DependClauseOps &result) const { | ||
| auto process = [&](const omp::clause::Depend &clause, | ||
| const parser::CharBlock &) { | ||
| using Depend = omp::clause::Depend; | ||
|
|
@@ -830,18 +845,38 @@ bool ClauseProcessor::processDepend(mlir::omp::DependClauseOps &result) const { | |
|
|
||
| for (const omp::Object &object : objects) { | ||
| assert(object.ref() && "Expecting designator"); | ||
| mlir::Value dependVar; | ||
|
|
||
| if (evaluate::ExtractSubstring(*object.ref())) { | ||
| TODO(converter.getCurrentLocation(), | ||
| "substring not supported for task depend"); | ||
| } else if (evaluate::IsArrayElement(*object.ref())) { | ||
| TODO(converter.getCurrentLocation(), | ||
| "array sections not supported for task depend"); | ||
| // Array Section | ||
| SomeExpr expr = *object.ref(); | ||
| if (isVectorSubscript(expr)) | ||
| TODO(converter.getCurrentLocation(), | ||
| "Vector subscripted array section for task dependency"); | ||
|
|
||
| hlfir::EntityWithAttributes entity = convertExprToHLFIR( | ||
| converter.getCurrentLocation(), converter, expr, symMap, stmtCtx); | ||
| dependVar = entity.getBase(); | ||
| } else { | ||
| semantics::Symbol *sym = object.sym(); | ||
| dependVar = converter.getSymbolAddress(*sym); | ||
| } | ||
|
|
||
| semantics::Symbol *sym = object.sym(); | ||
| const mlir::Value variable = converter.getSymbolAddress(*sym); | ||
| result.dependVars.push_back(variable); | ||
| // The openmp dialect doesn't know what to do with boxes (and it would | ||
| // break layering to teach it about them). The dependency variable can be | ||
| // a box because it was an array section or because the original symbol | ||
| // was mapped to a box. | ||
| // Getting the address of the box data is okay because all the runtime | ||
| // ultimately cares about is the base address of the array. | ||
| if (fir::isa_box_type(dependVar.getType())) { | ||
|
||
| fir::FirOpBuilder &builder = converter.getFirOpBuilder(); | ||
| dependVar = builder.create<fir::BoxAddrOp>( | ||
| converter.getCurrentLocation(), dependVar); | ||
| } | ||
| result.dependVars.push_back(dependVar); | ||
| } | ||
| }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1669,15 +1669,15 @@ static void genSingleClauses(lower::AbstractConverter &converter, | |
|
|
||
| static void genTargetClauses( | ||
| lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, | ||
| lower::StatementContext &stmtCtx, lower::pft::Evaluation &eval, | ||
| const List<Clause> &clauses, mlir::Location loc, | ||
| mlir::omp::TargetOperands &clauseOps, | ||
| lower::SymMap &symTable, lower::StatementContext &stmtCtx, | ||
| lower::pft::Evaluation &eval, const List<Clause> &clauses, | ||
| mlir::Location loc, mlir::omp::TargetOperands &clauseOps, | ||
| llvm::SmallVectorImpl<const semantics::Symbol *> &hasDeviceAddrSyms, | ||
| llvm::SmallVectorImpl<const semantics::Symbol *> &isDevicePtrSyms, | ||
| llvm::SmallVectorImpl<const semantics::Symbol *> &mapSyms) { | ||
| ClauseProcessor cp(converter, semaCtx, clauses); | ||
| cp.processBare(clauseOps); | ||
| cp.processDepend(clauseOps); | ||
| cp.processDepend(symTable, stmtCtx, clauseOps); | ||
| cp.processDevice(stmtCtx, clauseOps); | ||
| cp.processHasDeviceAddr(stmtCtx, clauseOps, hasDeviceAddrSyms); | ||
| if (!hostEvalInfo.empty()) { | ||
|
|
@@ -1728,11 +1728,12 @@ static void genTargetDataClauses( | |
|
|
||
| static void genTargetEnterExitUpdateDataClauses( | ||
| lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, | ||
| lower::StatementContext &stmtCtx, const List<Clause> &clauses, | ||
| mlir::Location loc, llvm::omp::Directive directive, | ||
| lower::SymMap &symTable, lower::StatementContext &stmtCtx, | ||
| const List<Clause> &clauses, mlir::Location loc, | ||
| llvm::omp::Directive directive, | ||
| mlir::omp::TargetEnterExitUpdateDataOperands &clauseOps) { | ||
| ClauseProcessor cp(converter, semaCtx, clauses); | ||
| cp.processDepend(clauseOps); | ||
| cp.processDepend(symTable, stmtCtx, clauseOps); | ||
| cp.processDevice(stmtCtx, clauseOps); | ||
| cp.processIf(directive, clauseOps); | ||
|
|
||
|
|
@@ -1746,12 +1747,13 @@ static void genTargetEnterExitUpdateDataClauses( | |
|
|
||
| static void genTaskClauses(lower::AbstractConverter &converter, | ||
| semantics::SemanticsContext &semaCtx, | ||
| lower::SymMap &symTable, | ||
| lower::StatementContext &stmtCtx, | ||
| const List<Clause> &clauses, mlir::Location loc, | ||
| mlir::omp::TaskOperands &clauseOps) { | ||
| ClauseProcessor cp(converter, semaCtx, clauses); | ||
| cp.processAllocate(clauseOps); | ||
| cp.processDepend(clauseOps); | ||
| cp.processDepend(symTable, stmtCtx, clauseOps); | ||
| cp.processFinal(stmtCtx, clauseOps); | ||
| cp.processIf(llvm::omp::Directive::OMPD_task, clauseOps); | ||
| cp.processMergeable(clauseOps); | ||
|
|
@@ -2194,8 +2196,8 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable, | |
| mlir::omp::TargetOperands clauseOps; | ||
| llvm::SmallVector<const semantics::Symbol *> mapSyms, isDevicePtrSyms, | ||
| hasDeviceAddrSyms; | ||
| genTargetClauses(converter, semaCtx, stmtCtx, eval, item->clauses, loc, | ||
| clauseOps, hasDeviceAddrSyms, isDevicePtrSyms, mapSyms); | ||
| genTargetClauses(converter, semaCtx, symTable, stmtCtx, eval, item->clauses, | ||
| loc, clauseOps, hasDeviceAddrSyms, isDevicePtrSyms, mapSyms); | ||
|
|
||
| DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval, | ||
| /*shouldCollectPreDeterminedSymbols=*/ | ||
|
|
@@ -2415,7 +2417,7 @@ static OpTy genTargetEnterExitUpdateDataOp( | |
| } | ||
|
|
||
| mlir::omp::TargetEnterExitUpdateDataOperands clauseOps; | ||
| genTargetEnterExitUpdateDataClauses(converter, semaCtx, stmtCtx, | ||
| genTargetEnterExitUpdateDataClauses(converter, semaCtx, symTable, stmtCtx, | ||
| item->clauses, loc, directive, clauseOps); | ||
|
|
||
| return firOpBuilder.create<OpTy>(loc, clauseOps); | ||
|
|
@@ -2428,7 +2430,8 @@ genTaskOp(lower::AbstractConverter &converter, lower::SymMap &symTable, | |
| ConstructQueue::const_iterator item) { | ||
| lower::StatementContext stmtCtx; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While working on the next patch in this series I've noticed that this I have a proof of concept fix which I will finish off on Monday.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am trying to understand the problem here. This
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's discuss this on the PR for this change. Hopefully the example will make it clearer: #133891 (comment) |
||
| mlir::omp::TaskOperands clauseOps; | ||
| genTaskClauses(converter, semaCtx, stmtCtx, item->clauses, loc, clauseOps); | ||
| genTaskClauses(converter, semaCtx, symTable, stmtCtx, item->clauses, loc, | ||
| clauseOps); | ||
|
|
||
| if (!enableDelayedPrivatization) | ||
| return genOpWithBody<mlir::omp::TaskOp>( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| ! RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s | ||
| ! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s | ||
|
|
||
| ! CHECK: Vector subscripted array section for task dependency | ||
| subroutine vectorSubscriptArraySection(array, indices) | ||
| integer :: array(:) | ||
| integer :: indices(:) | ||
|
|
||
| !$omp task depend (in: array(indices)) | ||
| !$omp end task | ||
| end subroutine |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| ! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s | ||
|
|
||
| subroutine knownShape(array) | ||
| integer :: array(10) | ||
|
|
||
| !$omp task depend(in: array(2:8)) | ||
| !$omp end task | ||
| end subroutine | ||
|
|
||
| ! CHECK-LABEL: func.func @_QPknownshape( | ||
| ! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "array"}) { | ||
| ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope | ||
| ! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index | ||
| ! CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> | ||
| ! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) dummy_scope %[[VAL_1]] {uniq_name = "_QFknownshapeEarray"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) | ||
| ! CHECK: %[[VAL_5:.*]] = arith.constant 2 : index | ||
| ! CHECK: %[[VAL_6:.*]] = arith.constant 8 : index | ||
| ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : index | ||
| ! CHECK: %[[VAL_8:.*]] = arith.constant 7 : index | ||
| ! CHECK: %[[VAL_9:.*]] = fir.shape %[[VAL_8]] : (index) -> !fir.shape<1> | ||
| ! CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_5]]:%[[VAL_6]]:%[[VAL_7]]) shape %[[VAL_9]] : (!fir.ref<!fir.array<10xi32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<7xi32>> | ||
| ! CHECK: omp.task depend(taskdependin -> %[[VAL_10]] : !fir.ref<!fir.array<7xi32>>) { | ||
| ! CHECK: omp.terminator | ||
| ! CHECK: } | ||
| ! CHECK: return | ||
| ! CHECK: } | ||
|
|
||
|
|
||
| subroutine assumedShape(array) | ||
| integer :: array(:) | ||
|
|
||
| !$omp task depend(in: array(2:8:2)) | ||
| !$omp end task | ||
| end subroutine | ||
|
|
||
| ! CHECK-LABEL: func.func @_QPassumedshape( | ||
| ! CHECK-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "array"}) { | ||
| ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope | ||
| ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFassumedshapeEarray"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) | ||
| ! CHECK: %[[VAL_3:.*]] = arith.constant 2 : index | ||
| ! CHECK: %[[VAL_4:.*]] = arith.constant 8 : index | ||
| ! CHECK: %[[VAL_5:.*]] = arith.constant 2 : index | ||
| ! CHECK: %[[VAL_6:.*]] = arith.constant 4 : index | ||
| ! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> | ||
| ! CHECK: %[[VAL_8:.*]] = hlfir.designate %[[VAL_2]]#0 (%[[VAL_3]]:%[[VAL_4]]:%[[VAL_5]]) shape %[[VAL_7]] : (!fir.box<!fir.array<?xi32>>, index, index, index, !fir.shape<1>) -> !fir.box<!fir.array<4xi32>> | ||
| ! CHECK: %[[VAL_9:.*]] = fir.box_addr %[[VAL_8]] : (!fir.box<!fir.array<4xi32>>) -> !fir.ref<!fir.array<4xi32>> | ||
| ! CHECK: omp.task depend(taskdependin -> %[[VAL_9]] : !fir.ref<!fir.array<4xi32>>) { | ||
| ! CHECK: omp.terminator | ||
| ! CHECK: } | ||
| ! CHECK: return | ||
| ! CHECK: } |
Uh oh!
There was an error while loading. Please reload this page.