diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -637,6 +637,25 @@ return bodyGenStatus; } +/// Converts an OpenMP single construct into LLVM IR using OpenMPIRBuilder. +static LogicalResult +convertOmpSingle(omp::SingleOp &singleOp, llvm::IRBuilderBase &builder, + LLVM::ModuleTranslation &moduleTranslation) { + using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; + llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder); + LogicalResult bodyGenStatus = success(); + auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP, + llvm::BasicBlock &continuationBB) { + convertOmpOpRegions(singleOp.region(), "omp.single.region", + *codegenIP.getBlock(), continuationBB, builder, + moduleTranslation, bodyGenStatus); + }; + auto finiCB = [&](InsertPointTy codeGenIP) {}; + builder.restoreIP(moduleTranslation.getOpenMPBuilder()->createSingle( + ompLoc, bodyCB, finiCB, /*DidIt=*/nullptr)); + return bodyGenStatus; +} + /// Converts an OpenMP workshare loop into LLVM IR using OpenMPIRBuilder. static LogicalResult convertOmpWsLoop(Operation &opInst, llvm::IRBuilderBase &builder, @@ -1355,6 +1374,9 @@ .Case([&](omp::SectionsOp) { return convertOmpSections(*op, builder, moduleTranslation); }) + .Case([&](omp::SingleOp op) { + return convertOmpSingle(op, builder, moduleTranslation); + }) .Case([](auto op) { // `yield` and `terminator` can be just omitted. The block structure diff --git a/mlir/test/Target/LLVMIR/openmp-llvm.mlir b/mlir/test/Target/LLVMIR/openmp-llvm.mlir --- a/mlir/test/Target/LLVMIR/openmp-llvm.mlir +++ b/mlir/test/Target/LLVMIR/openmp-llvm.mlir @@ -1822,3 +1822,21 @@ } llvm.return } + +// ----- + +// CHECK-LABEL: @single +// CHECK-SAME: (i32 %[[x:.*]], i32 %[[y:.*]], i32* %[[zaddr:.*]]) +llvm.func @single(%x: i32, %y: i32, %zaddr: !llvm.ptr) { + // CHECK: call i32 @__kmpc_single + omp.single { + // CHECK: %[[z:.*]] = add i32 %[[x]], %[[y]] + %z = llvm.add %x, %y : i32 + // CHECK: store i32 %[[z]], i32* %[[zaddr]] + llvm.store %z, %zaddr : !llvm.ptr + // CHECK: call void @__kmpc_end_single + omp.terminator + } + // CHECK: ret void + llvm.return +}