Skip to content

Commit e2ad554

Browse files
[Flang][mlir] - Translation of delayed privatization for deferred target-tasks (#155348)
This PR adds support for translation of the private clause on deferred target tasks - that is `omp.target` operations with the `nowait` clause. An offloading call for a deferred target-task is not blocking - the offloading (target-generating) host task continues its execution after issuing the offloading call. Therefore, the key problem we need to solve is to ensure that the data needed for private variables to be initialized in the target task persists even after the host task has completed. We do this in a new pass called `PrepareForOMPOffloadPrivatizationPass`. For a privatized variable that needs its host counterpart for initialization (such as the shape of the data from the descriptor when an allocatable is privatized or the value of the data when an allocatable is firstprivatized), - the pass allocates memory on the heap. - it then initializes this memory by using the `init` and `copy` (for firstprivate) regions of the corresponding `omp::PrivateClauseOp`. - Finally the memory allocated on the heap is freed using the `dealloc` region of the same `omp::PrivateClauseOp` instance. This step is not straightforward though, because we cannot simply free the memory that's going to be used by another thread without any synchronization. So, for deallocation, we create a `omp.task` after the `omp.target` and synchronize the two with a dummy dependency (using the `depend` clause). In this newly created `omp.task` we do the deallocation.
1 parent 866879f commit e2ad554

File tree

16 files changed

+888
-27
lines changed

16 files changed

+888
-27
lines changed

flang/include/flang/Optimizer/Passes/Pipelines.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
2323
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
2424
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
25+
#include "mlir/Dialect/OpenMP/Transforms/Passes.h"
2526
#include "mlir/Pass/PassManager.h"
2627
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
2728
#include "mlir/Transforms/Passes.h"

flang/lib/Optimizer/Passes/Pipelines.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,12 @@ void createMLIRToLLVMPassPipeline(mlir::PassManager &pm,
426426

427427
// Add codegen pass pipeline.
428428
fir::createDefaultFIRCodeGenPassPipeline(pm, config, inputFilename);
429+
430+
// Run a pass to prepare for translation of delayed privatization in the
431+
// context of deferred target tasks.
432+
addPassConditionally(pm, disableFirToLlvmIr, [&]() {
433+
return mlir::omp::createPrepareForOMPOffloadPrivatizationPass();
434+
});
429435
}
430436

431437
} // namespace fir

flang/test/Fir/basic-program.fir

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,5 @@ func.func @_QQmain() {
161161
// PASSES-NEXT: LowerNontemporalPass
162162
// PASSES-NEXT: FIRToLLVMLowering
163163
// PASSES-NEXT: ReconcileUnrealizedCasts
164+
// PASSES-NEXT: PrepareForOMPOffloadPrivatizationPass
164165
// PASSES-NEXT: LLVMIRLoweringPass

mlir/include/mlir/Dialect/OpenMP/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
add_subdirectory(Transforms)
2+
13
set(LLVM_TARGET_DEFINITIONS ${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend/OpenMP/OMP.td)
24
mlir_tablegen(OmpCommon.td --gen-directive-decl --directives-dialect=OpenMP)
35
add_mlir_dialect_tablegen_target(omp_common_td)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
set(LLVM_TARGET_DEFINITIONS Passes.td)
2+
mlir_tablegen(Passes.h.inc -gen-pass-decls -name OpenMP)
3+
add_public_tablegen_target(MLIROpenMPPassIncGen)
4+
5+
add_mlir_doc(Passes OpenMPPasses ./ -gen-pass-doc)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===- Passes.h - OpenMP Pass Construction and Registration -----*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef MLIR_DIALECT_OPENMP_TRANSFORMS_PASSES_H
10+
#define MLIR_DIALECT_OPENMP_TRANSFORMS_PASSES_H
11+
12+
#include "mlir/Pass/Pass.h"
13+
14+
namespace mlir {
15+
16+
namespace omp {
17+
18+
/// Generate the code for registering conversion passes.
19+
#define GEN_PASS_DECL
20+
#define GEN_PASS_REGISTRATION
21+
#include "mlir/Dialect/OpenMP/Transforms/Passes.h.inc"
22+
23+
} // namespace omp
24+
} // namespace mlir
25+
26+
#endif // MLIR_DIALECT_LLVMIR_TRANSFORMS_PASSES_H
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===-- Passes.td - OpenMP pass definition file ------------*- tablegen -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef MLIR_DIALECT_OPENMP_TRANSFORMS_PASSES
10+
#define MLIR_DIALECT_OPENMP_TRANSFORMS_PASSES
11+
12+
include "mlir/Pass/PassBase.td"
13+
14+
def PrepareForOMPOffloadPrivatizationPass : Pass<"omp-offload-privatization-prepare", "ModuleOp"> {
15+
let summary = "Prepare OpenMP maps for privatization for deferred target tasks";
16+
let description = [{
17+
When generating LLVMIR for privatized variables in an OpenMP offloading directive (eg. omp::TargetOp)
18+
that creates a deferred target task (when the nowait clause is used), we need to copy the privatized
19+
variable out of the stack of the generating task and into the heap so that the deferred target task
20+
can still access it. However, if such a privatized variable is also mapped, typically the case for
21+
allocatables, then the corresponding `omp::MapInfoOp` needs to be fixed up to map the new heap-allocated
22+
variable and not the original variable.
23+
}];
24+
let dependentDialects = ["LLVM::LLVMDialect"];
25+
}
26+
#endif // MLIR_DIALECT_OPENMP_TRANSFORMS_PASSES

mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ add_mlir_dialect_library(MLIRLLVMIRTransforms
1818
MLIRPass
1919
MLIRTransforms
2020
MLIRNVVMDialect
21+
MLIROpenMPDialect
2122
)

mlir/lib/Dialect/OpenMP/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
add_subdirectory(Transforms)
2+
13
add_mlir_dialect_library(MLIROpenMPDialect
24
IR/OpenMPDialect.cpp
35

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
add_mlir_dialect_library(MLIROpenMPTransforms
2+
OpenMPOffloadPrivatizationPrepare.cpp
3+
4+
DEPENDS
5+
MLIROpenMPPassIncGen
6+
7+
LINK_LIBS PUBLIC
8+
MLIRIR
9+
MLIRFuncDialect
10+
MLIRLLVMDialect
11+
MLIROpenMPDialect
12+
MLIRPass
13+
MLIRTransforms
14+
)

0 commit comments

Comments
 (0)