Skip to content

Commit d0d0380

Browse files
authored
[flang][OpenMP] Support target ... nowait (#111823)
Adds MLIR to LLVM lowering support for `target ... nowait`. This leverages the already existings code-gen patterns for `task` by treating `target ... nowait` as `task ... if(1)` and `target` (without `nowait`) as `task ... if(0)`; similar to what clang does.
1 parent a4367d2 commit d0d0380

File tree

5 files changed

+105
-65
lines changed

5 files changed

+105
-65
lines changed

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2875,16 +2875,16 @@ class OpenMPIRBuilder {
28752875
/// instructions for passed in target arguments where neccessary
28762876
/// \param Dependencies A vector of DependData objects that carry
28772877
// dependency information as passed in the depend clause
2878-
InsertPointTy
2879-
createTarget(const LocationDescription &Loc, bool IsOffloadEntry,
2880-
OpenMPIRBuilder::InsertPointTy AllocaIP,
2881-
OpenMPIRBuilder::InsertPointTy CodeGenIP,
2882-
TargetRegionEntryInfo &EntryInfo, ArrayRef<int32_t> NumTeams,
2883-
ArrayRef<int32_t> NumThreads, SmallVectorImpl<Value *> &Inputs,
2884-
GenMapInfoCallbackTy GenMapInfoCB,
2885-
TargetBodyGenCallbackTy BodyGenCB,
2886-
TargetGenArgAccessorsCallbackTy ArgAccessorFuncCB,
2887-
SmallVector<DependData> Dependencies = {});
2878+
// \param HasNowait Whether the target construct has a `nowait` clause or not.
2879+
InsertPointTy createTarget(
2880+
const LocationDescription &Loc, bool IsOffloadEntry,
2881+
OpenMPIRBuilder::InsertPointTy AllocaIP,
2882+
OpenMPIRBuilder::InsertPointTy CodeGenIP,
2883+
TargetRegionEntryInfo &EntryInfo, ArrayRef<int32_t> NumTeams,
2884+
ArrayRef<int32_t> NumThreads, SmallVectorImpl<Value *> &Inputs,
2885+
GenMapInfoCallbackTy GenMapInfoCB, TargetBodyGenCallbackTy BodyGenCB,
2886+
TargetGenArgAccessorsCallbackTy ArgAccessorFuncCB,
2887+
SmallVector<DependData> Dependencies = {}, bool HasNowait = false);
28882888

28892889
/// Returns __kmpc_for_static_init_* runtime function for the specified
28902890
/// size \a IVSize and sign \a IVSigned. Will create a distribute call

llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6968,8 +6968,8 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitTargetTask(
69686968
}
69696969

69706970
OI.ExitBB = Builder.saveIP().getBlock();
6971-
OI.PostOutlineCB = [this, ToBeDeleted, Dependencies,
6972-
HasNoWait](Function &OutlinedFn) mutable {
6971+
OI.PostOutlineCB = [this, ToBeDeleted, Dependencies, HasNoWait,
6972+
DeviceID](Function &OutlinedFn) mutable {
69736973
assert(OutlinedFn.getNumUses() == 1 &&
69746974
"there must be a single user for the outlined function");
69756975

@@ -6989,9 +6989,15 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitTargetTask(
69896989
getOrCreateSrcLocStr(LocationDescription(Builder), SrcLocStrSize);
69906990
Value *Ident = getOrCreateIdent(SrcLocStr, SrcLocStrSize);
69916991

6992-
// @__kmpc_omp_task_alloc
6992+
// @__kmpc_omp_task_alloc or @__kmpc_omp_target_task_alloc
6993+
//
6994+
// If `HasNoWait == true`, we call @__kmpc_omp_target_task_alloc to provide
6995+
// the DeviceID to the deferred task and also since
6996+
// @__kmpc_omp_target_task_alloc creates an untied/async task.
69936997
Function *TaskAllocFn =
6994-
getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_task_alloc);
6998+
!HasNoWait ? getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_task_alloc)
6999+
: getOrCreateRuntimeFunctionPtr(
7000+
OMPRTL___kmpc_omp_target_task_alloc);
69957001

69967002
// Arguments - `loc_ref` (Ident) and `gtid` (ThreadID)
69977003
// call.
@@ -7032,10 +7038,18 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitTargetTask(
70327038
// Emit the @__kmpc_omp_task_alloc runtime call
70337039
// The runtime call returns a pointer to an area where the task captured
70347040
// variables must be copied before the task is run (TaskData)
7035-
CallInst *TaskData = Builder.CreateCall(
7036-
TaskAllocFn, {/*loc_ref=*/Ident, /*gtid=*/ThreadID, /*flags=*/Flags,
7037-
/*sizeof_task=*/TaskSize, /*sizeof_shared=*/SharedsSize,
7038-
/*task_func=*/ProxyFn});
7041+
CallInst *TaskData = nullptr;
7042+
7043+
SmallVector<llvm::Value *> TaskAllocArgs = {
7044+
/*loc_ref=*/Ident, /*gtid=*/ThreadID,
7045+
/*flags=*/Flags,
7046+
/*sizeof_task=*/TaskSize, /*sizeof_shared=*/SharedsSize,
7047+
/*task_func=*/ProxyFn};
7048+
7049+
if (HasNoWait)
7050+
TaskAllocArgs.push_back(DeviceID);
7051+
7052+
TaskData = Builder.CreateCall(TaskAllocFn, TaskAllocArgs);
70397053

70407054
if (HasShareds) {
70417055
Value *Shareds = StaleCI->getArgOperand(1);
@@ -7118,13 +7132,14 @@ void OpenMPIRBuilder::emitOffloadingArraysAndArgs(
71187132
emitOffloadingArraysArgument(Builder, RTArgs, Info, ForEndCall);
71197133
}
71207134

7121-
static void emitTargetCall(
7122-
OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder,
7123-
OpenMPIRBuilder::InsertPointTy AllocaIP, Function *OutlinedFn,
7124-
Constant *OutlinedFnID, ArrayRef<int32_t> NumTeams,
7125-
ArrayRef<int32_t> NumThreads, SmallVectorImpl<Value *> &Args,
7126-
OpenMPIRBuilder::GenMapInfoCallbackTy GenMapInfoCB,
7127-
SmallVector<llvm::OpenMPIRBuilder::DependData> Dependencies = {}) {
7135+
static void
7136+
emitTargetCall(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder,
7137+
OpenMPIRBuilder::InsertPointTy AllocaIP, Function *OutlinedFn,
7138+
Constant *OutlinedFnID, ArrayRef<int32_t> NumTeams,
7139+
ArrayRef<int32_t> NumThreads, SmallVectorImpl<Value *> &Args,
7140+
OpenMPIRBuilder::GenMapInfoCallbackTy GenMapInfoCB,
7141+
SmallVector<llvm::OpenMPIRBuilder::DependData> Dependencies = {},
7142+
bool HasNoWait = false) {
71287143
// Generate a function call to the host fallback implementation of the target
71297144
// region. This is called by the host when no offload entry was generated for
71307145
// the target region and when the offloading call fails at runtime.
@@ -7135,7 +7150,6 @@ static void emitTargetCall(
71357150
return Builder.saveIP();
71367151
};
71377152

7138-
bool HasNoWait = false;
71397153
bool HasDependencies = Dependencies.size() > 0;
71407154
bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
71417155

@@ -7211,7 +7225,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createTarget(
72117225
SmallVectorImpl<Value *> &Args, GenMapInfoCallbackTy GenMapInfoCB,
72127226
OpenMPIRBuilder::TargetBodyGenCallbackTy CBFunc,
72137227
OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy ArgAccessorFuncCB,
7214-
SmallVector<DependData> Dependencies) {
7228+
SmallVector<DependData> Dependencies, bool HasNowait) {
72157229

72167230
if (!updateToLocation(Loc))
72177231
return InsertPointTy();
@@ -7232,7 +7246,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createTarget(
72327246
// that represents the target region. Do that now.
72337247
if (!Config.isTargetDevice())
72347248
emitTargetCall(*this, Builder, AllocaIP, OutlinedFn, OutlinedFnID, NumTeams,
7235-
NumThreads, Args, GenMapInfoCB, Dependencies);
7249+
NumThreads, Args, GenMapInfoCB, Dependencies, HasNowait);
72367250
return Builder.saveIP();
72377251
}
72387252

mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3241,11 +3241,6 @@ static bool targetOpSupported(Operation &opInst) {
32413241
return false;
32423242
}
32433243

3244-
if (targetOp.getNowait()) {
3245-
opInst.emitError("Nowait clause not yet supported");
3246-
return false;
3247-
}
3248-
32493244
if (!targetOp.getAllocateVars().empty() ||
32503245
!targetOp.getAllocatorVars().empty()) {
32513246
opInst.emitError("Allocate clause not yet supported");
@@ -3567,7 +3562,7 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
35673562
builder.restoreIP(moduleTranslation.getOpenMPBuilder()->createTarget(
35683563
ompLoc, isOffloadEntry, allocaIP, builder.saveIP(), entryInfo,
35693564
defaultValTeams, defaultValThreads, kernelInput, genMapInfoCB, bodyCB,
3570-
argAccessorCB, dds));
3565+
argAccessorCB, dds, targetOp.getNowait()));
35713566

35723567
// Remap access operations to declare target reference pointers for the
35733568
// device, essentially generating extra loadop's as necessary
Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,31 @@
1-
// RUN: not mlir-translate -mlir-to-llvmir -split-input-file %s 2>&1 | FileCheck %s
1+
// RUN: mlir-translate -mlir-to-llvmir %s 2>&1 | FileCheck %s
22

3-
llvm.func @_QPopenmp_target_data_update() {
4-
%0 = llvm.mlir.constant(1 : i64) : i64
5-
%1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr
6-
%2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
3+
// Set a dummy target triple to enable target region outlining.
4+
module attributes {omp.target_triples = ["dummy-target-triple"]} {
5+
llvm.func @_QPfoo() {
6+
%0 = llvm.mlir.constant(1 : i64) : i64
7+
%1 = llvm.alloca %0 x i32 : (i64) -> !llvm.ptr
8+
%2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(implicit) capture(ByCopy) -> !llvm.ptr
9+
omp.target nowait map_entries(%2 -> %arg0 : !llvm.ptr) {
10+
%3 = llvm.mlir.constant(2 : i32) : i32
11+
llvm.store %3, %arg0 : i32, !llvm.ptr
12+
omp.terminator
13+
}
14+
llvm.return
15+
}
716

8-
// CHECK: error: `nowait` is not supported yet
9-
omp.target_update map_entries(%2 : !llvm.ptr) nowait
10-
11-
llvm.return
12-
}
13-
14-
// -----
15-
16-
llvm.func @_QPopenmp_target_data_enter() {
17-
%0 = llvm.mlir.constant(1 : i64) : i64
18-
%1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr
19-
%2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
20-
21-
// CHECK: error: `nowait` is not supported yet
22-
omp.target_enter_data map_entries(%2 : !llvm.ptr) nowait
23-
24-
llvm.return
25-
}
2617

18+
// CHECK: define void @_QPfoo() {
2719

28-
// -----
20+
// CHECK: %[[TASK:.*]] = call ptr @__kmpc_omp_target_task_alloc
21+
// CHECK-SAME: (ptr @{{.*}}, i32 %{{.*}}, i32 {{.*}}, i64 {{.*}}, i64 {{.*}}, ptr
22+
// CHECK-SAME: @[[TASK_PROXY_FUNC:.*]], i64 {{.*}})
2923

30-
llvm.func @_QPopenmp_target_data_exit() {
31-
%0 = llvm.mlir.constant(1 : i64) : i64
32-
%1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr
33-
%2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
24+
// CHECK: call i32 @__kmpc_omp_task(ptr {{.*}}, i32 %{{.*}}, ptr %[[TASK]])
25+
// CHECK: }
3426

35-
// CHECK: error: `nowait` is not supported yet
36-
omp.target_exit_data map_entries(%2 : !llvm.ptr) nowait
3727

38-
llvm.return
28+
// CHECK: define internal void @[[TASK_PROXY_FUNC]](i32 %{{.*}}, ptr %{{.*}}) {
29+
// CHECK: call void @_QPfoo..omp_par(i32 %{{.*}}, ptr %{{.*}})
30+
// CHECK: }
3931
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: not mlir-translate -mlir-to-llvmir -split-input-file %s 2>&1 | FileCheck %s
2+
3+
llvm.func @_QPopenmp_target_data_update() {
4+
%0 = llvm.mlir.constant(1 : i64) : i64
5+
%1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr
6+
%2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
7+
8+
// CHECK: error: `nowait` is not supported yet
9+
omp.target_update map_entries(%2 : !llvm.ptr) nowait
10+
11+
llvm.return
12+
}
13+
14+
// -----
15+
16+
llvm.func @_QPopenmp_target_data_enter() {
17+
%0 = llvm.mlir.constant(1 : i64) : i64
18+
%1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr
19+
%2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
20+
21+
// CHECK: error: `nowait` is not supported yet
22+
omp.target_enter_data map_entries(%2 : !llvm.ptr) nowait
23+
24+
llvm.return
25+
}
26+
27+
28+
// -----
29+
30+
llvm.func @_QPopenmp_target_data_exit() {
31+
%0 = llvm.mlir.constant(1 : i64) : i64
32+
%1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr
33+
%2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
34+
35+
// CHECK: error: `nowait` is not supported yet
36+
omp.target_exit_data map_entries(%2 : !llvm.ptr) nowait
37+
38+
llvm.return
39+
}

0 commit comments

Comments
 (0)