Skip to content

Commit f9c7a9d

Browse files
committed
[flang][OpenMP] Support target ... nowait
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 `taret` (without `nowait`) as `task ... if(0)`; similar to what clang does.
1 parent 06eb10d commit f9c7a9d

File tree

5 files changed

+103
-65
lines changed

5 files changed

+103
-65
lines changed

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

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2875,16 +2875,15 @@ 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+
InsertPointTy createTarget(
2879+
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, TargetBodyGenCallbackTy BodyGenCB,
2885+
TargetGenArgAccessorsCallbackTy ArgAccessorFuncCB,
2886+
SmallVector<DependData> Dependencies = {}, bool HasNowait = false);
28882887

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

llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp

Lines changed: 31 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,14 @@ 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.
69936996
Function *TaskAllocFn =
6994-
getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_task_alloc);
6997+
!HasNoWait ? getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_omp_task_alloc)
6998+
: getOrCreateRuntimeFunctionPtr(
6999+
OMPRTL___kmpc_omp_target_task_alloc);
69957000

69967001
// Arguments - `loc_ref` (Ident) and `gtid` (ThreadID)
69977002
// call.
@@ -7032,10 +7037,18 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitTargetTask(
70327037
// Emit the @__kmpc_omp_task_alloc runtime call
70337038
// The runtime call returns a pointer to an area where the task captured
70347039
// 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});
7040+
CallInst *TaskData = nullptr;
7041+
7042+
SmallVector<llvm::Value *> TaskAllocArgs = {
7043+
/*loc_ref=*/Ident, /*gtid=*/ThreadID,
7044+
/*flags=*/Flags,
7045+
/*sizeof_task=*/TaskSize, /*sizeof_shared=*/SharedsSize,
7046+
/*task_func=*/ProxyFn};
7047+
7048+
if (HasNoWait)
7049+
TaskAllocArgs.push_back(DeviceID);
7050+
7051+
TaskData = Builder.CreateCall(TaskAllocFn, TaskAllocArgs);
70397052

70407053
if (HasShareds) {
70417054
Value *Shareds = StaleCI->getArgOperand(1);
@@ -7118,13 +7131,14 @@ void OpenMPIRBuilder::emitOffloadingArraysAndArgs(
71187131
emitOffloadingArraysArgument(Builder, RTArgs, Info, ForEndCall);
71197132
}
71207133

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 = {}) {
7134+
static void
7135+
emitTargetCall(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder,
7136+
OpenMPIRBuilder::InsertPointTy AllocaIP, Function *OutlinedFn,
7137+
Constant *OutlinedFnID, ArrayRef<int32_t> NumTeams,
7138+
ArrayRef<int32_t> NumThreads, SmallVectorImpl<Value *> &Args,
7139+
OpenMPIRBuilder::GenMapInfoCallbackTy GenMapInfoCB,
7140+
SmallVector<llvm::OpenMPIRBuilder::DependData> Dependencies = {},
7141+
bool HasNoWait = false) {
71287142
// Generate a function call to the host fallback implementation of the target
71297143
// region. This is called by the host when no offload entry was generated for
71307144
// the target region and when the offloading call fails at runtime.
@@ -7135,7 +7149,6 @@ static void emitTargetCall(
71357149
return Builder.saveIP();
71367150
};
71377151

7138-
bool HasNoWait = false;
71397152
bool HasDependencies = Dependencies.size() > 0;
71407153
bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
71417154

@@ -7211,7 +7224,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createTarget(
72117224
SmallVectorImpl<Value *> &Args, GenMapInfoCallbackTy GenMapInfoCB,
72127225
OpenMPIRBuilder::TargetBodyGenCallbackTy CBFunc,
72137226
OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy ArgAccessorFuncCB,
7214-
SmallVector<DependData> Dependencies) {
7227+
SmallVector<DependData> Dependencies, bool HasNowait) {
72157228

72167229
if (!updateToLocation(Loc))
72177230
return InsertPointTy();
@@ -7232,7 +7245,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createTarget(
72327245
// that represents the target region. Do that now.
72337246
if (!Config.isTargetDevice())
72347247
emitTargetCall(*this, Builder, AllocaIP, OutlinedFn, OutlinedFnID, NumTeams,
7235-
NumThreads, Args, GenMapInfoCB, Dependencies);
7248+
NumThreads, Args, GenMapInfoCB, Dependencies, HasNowait);
72367249
return Builder.saveIP();
72377250
}
72387251

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

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

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

35743569
// Remap access operations to declare target reference pointers for the
35753570
// 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)