Skip to content

Commit ab5ff15

Browse files
committed
[mlir][openacc] Translate ExitDataop to LLVM IR
Translate ExitDataOp with delete and copyout operands to runtime call. This is done in a similar way as D101504. Reviewed By: kiranchandramohan Differential Revision: https://reviews.llvm.org/D102381
1 parent 8854b27 commit ab5ff15

File tree

2 files changed

+153
-34
lines changed

2 files changed

+153
-34
lines changed

mlir/lib/Target/LLVMIR/Dialect/OpenACC/OpenACCToLLVMIRTranslation.cpp

Lines changed: 92 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ using OpenACCIRBuilder = llvm::OpenMPIRBuilder;
3636
static constexpr uint64_t createFlag = 0;
3737
/// 1 = to/copyin
3838
static constexpr uint64_t copyinFlag = 1;
39+
/// 2 = from/copyout
40+
static constexpr uint64_t copyoutFlag = 2;
41+
/// 8 = delete
42+
static constexpr uint64_t deleteFlag = 8;
43+
3944
/// Default value for the device id
4045
static constexpr int64_t defaultDevice = -1;
4146

@@ -57,10 +62,10 @@ static llvm::Constant *createSourceLocStrFromLocation(Location loc,
5762
}
5863

5964
/// Create the location struct from the operation location information.
60-
static llvm::Value *createSourceLocationInfo(acc::EnterDataOp &op,
61-
OpenACCIRBuilder &builder) {
62-
auto loc = op.getLoc();
63-
auto funcOp = op.getOperation()->getParentOfType<LLVM::LLVMFuncOp>();
65+
static llvm::Value *createSourceLocationInfo(OpenACCIRBuilder &builder,
66+
Operation *op) {
67+
auto loc = op->getLoc();
68+
auto funcOp = op->getParentOfType<LLVM::LLVMFuncOp>();
6469
StringRef funcName = funcOp ? funcOp.getName() : "unknown";
6570
llvm::Constant *locStr =
6671
createSourceLocStrFromLocation(loc, builder, funcName);
@@ -81,10 +86,16 @@ static llvm::Constant *createMappingInformation(Location loc,
8186

8287
/// Return the runtime function used to lower the given operation.
8388
static llvm::Function *getAssociatedFunction(OpenACCIRBuilder &builder,
84-
Operation &op) {
85-
if (isa<acc::EnterDataOp>(op))
86-
return builder.getOrCreateRuntimeFunctionPtr(
87-
llvm::omp::OMPRTL___tgt_target_data_begin_mapper);
89+
Operation *op) {
90+
return llvm::TypeSwitch<Operation *, llvm::Function *>(op)
91+
.Case([&](acc::EnterDataOp) {
92+
return builder.getOrCreateRuntimeFunctionPtr(
93+
llvm::omp::OMPRTL___tgt_target_data_begin_mapper);
94+
})
95+
.Case([&](acc::ExitDataOp) {
96+
return builder.getOrCreateRuntimeFunctionPtr(
97+
llvm::omp::OMPRTL___tgt_target_data_end_mapper);
98+
});
8899
llvm_unreachable("Unknown OpenACC operation");
89100
}
90101

@@ -105,7 +116,7 @@ static llvm::Value *getSizeInBytes(llvm::IRBuilderBase &builder,
105116
/// to populate the future functions arguments.
106117
static LogicalResult
107118
processOperands(llvm::IRBuilderBase &builder,
108-
LLVM::ModuleTranslation &moduleTranslation, Operation &op,
119+
LLVM::ModuleTranslation &moduleTranslation, Operation *op,
109120
ValueRange operands, unsigned totalNbOperand,
110121
uint64_t operandFlag, SmallVector<uint64_t> &flags,
111122
SmallVector<llvm::Constant *> &names, unsigned &index,
@@ -137,7 +148,7 @@ processOperands(llvm::IRBuilderBase &builder,
137148
dataPtr = dataValue;
138149
dataSize = getSizeInBytes(builder, dataValue);
139150
} else {
140-
return op.emitOpError()
151+
return op->emitOpError()
141152
<< "Data operand must be legalized before translation."
142153
<< "Unsupported type: " << data.getType();
143154
}
@@ -171,28 +182,81 @@ processOperands(llvm::IRBuilderBase &builder,
171182
return success();
172183
}
173184

185+
/// Process data operands from acc::EnterDataOp
186+
static LogicalResult
187+
processDataOperands(llvm::IRBuilderBase &builder,
188+
LLVM::ModuleTranslation &moduleTranslation,
189+
acc::EnterDataOp op, SmallVector<uint64_t> &flags,
190+
SmallVector<llvm::Constant *> &names, unsigned &index,
191+
llvm::AllocaInst *argsBase, llvm::AllocaInst *args,
192+
llvm::AllocaInst *argSizes) {
193+
// TODO add `create_zero` and `attach` operands
194+
195+
// Create operands are handled as `alloc` call.
196+
if (failed(processOperands(builder, moduleTranslation, op,
197+
op.createOperands(), op.getNumDataOperands(),
198+
createFlag, flags, names, index, argsBase, args,
199+
argSizes)))
200+
return failure();
201+
202+
// Copyin operands are handled as `to` call.
203+
if (failed(processOperands(builder, moduleTranslation, op,
204+
op.copyinOperands(), op.getNumDataOperands(),
205+
copyinFlag, flags, names, index, argsBase, args,
206+
argSizes)))
207+
return failure();
208+
209+
return success();
210+
}
211+
212+
/// Process data operands from acc::ExitDataOp
213+
static LogicalResult
214+
processDataOperands(llvm::IRBuilderBase &builder,
215+
LLVM::ModuleTranslation &moduleTranslation,
216+
acc::ExitDataOp op, SmallVector<uint64_t> &flags,
217+
SmallVector<llvm::Constant *> &names, unsigned &index,
218+
llvm::AllocaInst *argsBase, llvm::AllocaInst *args,
219+
llvm::AllocaInst *argSizes) {
220+
// TODO add `detach` operands
221+
222+
// Delete operands are handled as `delete` call.
223+
if (failed(processOperands(builder, moduleTranslation, op,
224+
op.deleteOperands(), op.getNumDataOperands(),
225+
deleteFlag, flags, names, index, argsBase, args,
226+
argSizes)))
227+
return failure();
228+
229+
// Copyout operands are handled as `from` call.
230+
if (failed(processOperands(builder, moduleTranslation, op,
231+
op.copyoutOperands(), op.getNumDataOperands(),
232+
copyoutFlag, flags, names, index, argsBase, args,
233+
argSizes)))
234+
return failure();
235+
236+
return success();
237+
}
238+
174239
//===----------------------------------------------------------------------===//
175240
// Conversion functions
176241
//===----------------------------------------------------------------------===//
177242

178-
/// Converts an OpenACC enter_data operartion into LLVM IR.
243+
/// Converts an OpenACC standalone data operation into LLVM IR.
244+
template <typename OpTy>
179245
static LogicalResult
180-
convertEnterDataOp(Operation &op, llvm::IRBuilderBase &builder,
181-
LLVM::ModuleTranslation &moduleTranslation) {
182-
auto enterDataOp = cast<acc::EnterDataOp>(op);
183-
auto enclosingFuncOp = op.getParentOfType<LLVM::LLVMFuncOp>();
246+
convertStandaloneDataOp(OpTy &op, llvm::IRBuilderBase &builder,
247+
LLVM::ModuleTranslation &moduleTranslation) {
248+
auto enclosingFuncOp =
249+
op.getOperation()->template getParentOfType<LLVM::LLVMFuncOp>();
184250
llvm::Function *enclosingFunction =
185251
moduleTranslation.lookupFunction(enclosingFuncOp.getName());
186252

187253
OpenACCIRBuilder *accBuilder = moduleTranslation.getOpenMPBuilder();
188254

189-
auto *srcLocInfo = createSourceLocationInfo(enterDataOp, *accBuilder);
255+
auto *srcLocInfo = createSourceLocationInfo(*accBuilder, op);
190256
auto *mapperFunc = getAssociatedFunction(*accBuilder, op);
191257

192258
// Number of arguments in the enter_data operation.
193-
// TODO include create_zero and attach operands.
194-
unsigned totalNbOperand =
195-
enterDataOp.createOperands().size() + enterDataOp.copyinOperands().size();
259+
unsigned totalNbOperand = op.getNumDataOperands();
196260

197261
// TODO could be moved to OpenXXIRBuilder?
198262
llvm::LLVMContext &ctx = builder.getContext();
@@ -214,18 +278,8 @@ convertEnterDataOp(Operation &op, llvm::IRBuilderBase &builder,
214278
SmallVector<llvm::Constant *> names;
215279
unsigned index = 0;
216280

217-
// Create operands are handled as `alloc` call.
218-
if (failed(processOperands(builder, moduleTranslation, op,
219-
enterDataOp.createOperands(), totalNbOperand,
220-
createFlag, flags, names, index, argsBase, args,
221-
argSizes)))
222-
return failure();
223-
224-
// Copyin operands are handled as `to` call.
225-
if (failed(processOperands(builder, moduleTranslation, op,
226-
enterDataOp.copyinOperands(), totalNbOperand,
227-
copyinFlag, flags, names, index, argsBase, args,
228-
argSizes)))
281+
if (failed(processDataOperands(builder, moduleTranslation, op, flags, names,
282+
index, argsBase, args, argSizes)))
229283
return failure();
230284

231285
llvm::GlobalVariable *maptypes =
@@ -282,8 +336,13 @@ LogicalResult OpenACCDialectLLVMIRTranslationInterface::convertOperation(
282336
LLVM::ModuleTranslation &moduleTranslation) const {
283337

284338
return llvm::TypeSwitch<Operation *, LogicalResult>(op)
285-
.Case([&](acc::EnterDataOp) {
286-
return convertEnterDataOp(*op, builder, moduleTranslation);
339+
.Case([&](acc::EnterDataOp enterDataOp) {
340+
return convertStandaloneDataOp<acc::EnterDataOp>(enterDataOp, builder,
341+
moduleTranslation);
342+
})
343+
.Case([&](acc::ExitDataOp exitDataOp) {
344+
return convertStandaloneDataOp<acc::ExitDataOp>(exitDataOp, builder,
345+
moduleTranslation);
287346
})
288347
.Default([&](Operation *op) {
289348
return op->emitError("unsupported OpenACC operation: ")

mlir/test/Target/LLVMIR/openacc-llvm.mlir

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
1+
// RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s
22

33
llvm.func @testenterdataop(%arg0: !llvm.ptr<f32>, %arg1: !llvm.ptr<f32>, %arg2: i64, %arg3: i64, %arg4: i64, %arg5: !llvm.ptr<f32>) {
44
%0 = llvm.mlir.undef : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
@@ -63,3 +63,63 @@ llvm.func @testenterdataop(%arg0: !llvm.ptr<f32>, %arg1: !llvm.ptr<f32>, %arg2:
6363
// CHECK: call void @__tgt_target_data_begin_mapper(%struct.ident_t* [[LOCGLOBAL]], i64 -1, i32 2, i8** [[ARGBASE_ALLOCA_GEP]], i8** [[ARG_ALLOCA_GEP]], i64* [[SIZE_ALLOCA_GEP]], i64* getelementptr inbounds ([{{[0-9]*}} x i64], [{{[0-9]*}} x i64]* [[MAPTYPES]], i32 0, i32 0), i8** getelementptr inbounds ([{{[0-9]*}} x i8*], [{{[0-9]*}} x i8*]* [[MAPNAMES]], i32 0, i32 0), i8** null)
6464

6565
// CHECK: declare void @__tgt_target_data_begin_mapper(%struct.ident_t*, i64, i32, i8**, i8**, i64*, i64*, i8**, i8**) #0
66+
67+
// -----
68+
69+
70+
llvm.func @testexitdataop(%arg0: !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, %arg1: !llvm.ptr<f32>) {
71+
%0 = llvm.mlir.constant(10 : index) : i64
72+
%1 = llvm.mlir.null : !llvm.ptr<f32>
73+
%2 = llvm.getelementptr %1[%0] : (!llvm.ptr<f32>, i64) -> !llvm.ptr<f32>
74+
%3 = llvm.ptrtoint %2 : !llvm.ptr<f32> to i64
75+
%4 = llvm.extractvalue %arg0[1] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
76+
%5 = llvm.mlir.undef : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>
77+
%6 = llvm.insertvalue %arg0, %5[0] : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>
78+
%7 = llvm.insertvalue %4, %6[1] : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>
79+
%8 = llvm.insertvalue %3, %7[2] : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>
80+
acc.exit_data copyout(%arg1 : !llvm.ptr<f32>) delete(%8 : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>)
81+
llvm.return
82+
}
83+
84+
// CHECK: %struct.ident_t = type { i32, i32, i32, i32, i8* }
85+
86+
// CHECK: [[LOCSTR:@.*]] = private unnamed_addr constant [{{[0-9]*}} x i8] c";{{.*}};testexitdataop;{{[0-9]*}};{{[0-9]*}};;\00", align 1
87+
// CHECK: [[LOCGLOBAL:@.*]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([{{[0-9]*}} x i8], [{{[0-9]*}} x i8]* [[LOCSTR]], i32 0, i32 0) }, align 8
88+
// CHECK: [[MAPNAME1:@.*]] = private unnamed_addr constant [{{[0-9]*}} x i8] c";{{.*}};unknown;{{[0-9]*}};{{[0-9]*}};;\00", align 1
89+
// CHECK: [[MAPNAME2:@.*]] = private unnamed_addr constant [{{[0-9]*}} x i8] c";{{.*}};unknown;{{[0-9]*}};{{[0-9]*}};;\00", align 1
90+
// CHECK: [[MAPTYPES:@.*]] = private unnamed_addr constant [{{[0-9]*}} x i64] [i64 8, i64 2]
91+
// CHECK: [[MAPNAMES:@.*]] = private constant [{{[0-9]*}} x i8*] [i8* getelementptr inbounds ([{{[0-9]*}} x i8], [{{[0-9]*}} x i8]* [[MAPNAME1]], i32 0, i32 0), i8* getelementptr inbounds ([{{[0-9]*}} x i8], [{{[0-9]*}} x i8]* [[MAPNAME2]], i32 0, i32 0)]
92+
93+
// CHECK: define void @testexitdataop({ float*, float*, i64, [1 x i64], [1 x i64] } %{{.*}}, float* [[SIMPLEPTR:%.*]])
94+
// CHECK: [[ARGBASE_ALLOCA:%.*]] = alloca [{{[0-9]*}} x i8*], align 8
95+
// CHECK: [[ARG_ALLOCA:%.*]] = alloca [{{[0-9]*}} x i8*], align 8
96+
// CHECK: [[SIZE_ALLOCA:%.*]] = alloca [{{[0-9]*}} x i64], align 8
97+
98+
// CHECK: [[ARGBASE:%.*]] = extractvalue %openacc_data %{{.*}}, 0
99+
// CHECK: [[ARG:%.*]] = extractvalue %openacc_data %{{.*}}, 1
100+
// CHECK: [[ARGSIZE:%.*]] = extractvalue %openacc_data %{{.*}}, 2
101+
// CHECK: [[ARGBASEGEP:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[ARGBASE_ALLOCA]], i32 0, i32 0
102+
// CHECK: [[ARGBASEGEPCAST:%.*]] = bitcast i8** [[ARGBASEGEP]] to { float*, float*, i64, [1 x i64], [1 x i64] }*
103+
// CHECK: store { float*, float*, i64, [1 x i64], [1 x i64] } [[ARGBASE]], { float*, float*, i64, [1 x i64], [1 x i64] }* [[ARGBASEGEPCAST]], align 8
104+
// CHECK: [[ARGGEP:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[ARG_ALLOCA]], i32 0, i32 0
105+
// CHECK: [[ARGGEPCAST:%.*]] = bitcast i8** [[ARGGEP]] to float**
106+
// CHECK: store float* [[ARG]], float** [[ARGGEPCAST]], align 8
107+
// CHECK: [[SIZEGEP:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[SIZE_ALLOCA]], i32 0, i32 0
108+
// CHECK: store i64 [[ARGSIZE]], i64* [[SIZEGEP]], align 4
109+
110+
// CHECK: [[ARGBASEGEP:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[ARGBASE_ALLOCA]], i32 0, i32 1
111+
// CHECK: [[ARGBASEGEPCAST:%.*]] = bitcast i8** [[ARGBASEGEP]] to float**
112+
// CHECK: store float* [[SIMPLEPTR]], float** [[ARGBASEGEPCAST]], align 8
113+
// CHECK: [[ARGGEP:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[ARG_ALLOCA]], i32 0, i32 1
114+
// CHECK: [[ARGGEPCAST:%.*]] = bitcast i8** [[ARGGEP]] to float**
115+
// CHECK: store float* [[SIMPLEPTR]], float** [[ARGGEPCAST]], align 8
116+
// CHECK: [[SIZEGEP:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[SIZE_ALLOCA]], i32 0, i32 1
117+
// CHECK: store i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64* [[SIZEGEP]], align 4
118+
119+
// CHECK: [[ARGBASE_ALLOCA_GEP:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[ARGBASE_ALLOCA]], i32 0, i32 0
120+
// CHECK: [[ARG_ALLOCA_GEP:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[ARG_ALLOCA]], i32 0, i32 0
121+
// CHECK: [[SIZE_ALLOCA_GEP:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[SIZE_ALLOCA]], i32 0, i32 0
122+
123+
// CHECK: call void @__tgt_target_data_end_mapper(%struct.ident_t* [[LOCGLOBAL]], i64 -1, i32 2, i8** [[ARGBASE_ALLOCA_GEP]], i8** [[ARG_ALLOCA_GEP]], i64* [[SIZE_ALLOCA_GEP]], i64* getelementptr inbounds ([{{[0-9]*}} x i64], [{{[0-9]*}} x i64]* [[MAPTYPES]], i32 0, i32 0), i8** getelementptr inbounds ([{{[0-9]*}} x i8*], [{{[0-9]*}} x i8*]* [[MAPNAMES]], i32 0, i32 0), i8** null)
124+
125+
// CHECK: declare void @__tgt_target_data_end_mapper(%struct.ident_t*, i64, i32, i8**, i8**, i64*, i64*, i8**, i8**) #0

0 commit comments

Comments
 (0)