diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h --- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h @@ -91,7 +91,14 @@ llvm::IRBuilder<> &builder); virtual LogicalResult convertOmpParallel(Operation &op, llvm::IRBuilder<> &builder); - + virtual LogicalResult convertOmpMaster(Operation &op, + llvm::IRBuilder<> &builder); + void convertOmpOpRegions(Region ®ion, + DenseMap &valueMapping, + DenseMap &blockMapping, + llvm::Instruction *codeGenIPBBTI, + llvm::BasicBlock &continuationIP, + llvm::IRBuilder<> &builder); /// Converts the type from MLIR LLVM dialect to LLVM. llvm::Type *convertType(LLVMType type); diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -407,31 +407,8 @@ blockMapping[&bb] = llvmBB; } - // Then, convert blocks one by one in topological order to ensure - // defs are converted before uses. - llvm::SetVector blocks = topologicalSort(region); - for (auto indexedBB : llvm::enumerate(blocks)) { - Block *bb = indexedBB.value(); - llvm::BasicBlock *curLLVMBB = blockMapping[bb]; - if (bb->isEntryBlock()) - codeGenIPBBTI->setSuccessor(0, curLLVMBB); - - // TODO: Error not returned up the hierarchy - if (failed(convertBlock(*bb, /*ignoreArguments=*/indexedBB.index() == 0))) - return; - - // If this block has the terminator then add a jump to - // continuation bb - for (auto &op : *bb) { - if (isa(op)) { - builder.SetInsertPoint(curLLVMBB); - builder.CreateBr(&continuationIP); - } - } - } - // Finally, after all blocks have been traversed and values mapped, - // connect the PHI nodes to the results of preceding blocks. - connectPHINodes(region, valueMapping, blockMapping); + convertOmpOpRegions(region, valueMapping, blockMapping, codeGenIPBBTI, + continuationIP, builder); }; // TODO: Perform appropriate actions according to the data-sharing @@ -470,6 +447,70 @@ return success(); } +void ModuleTranslation::convertOmpOpRegions( + Region ®ion, DenseMap &valueMapping, + DenseMap &blockMapping, + llvm::Instruction *codeGenIPBBTI, llvm::BasicBlock &continuationIP, + llvm::IRBuilder<> &builder) { + // Convert blocks one by one in topological order to ensure + // defs are converted before uses. + llvm::SetVector blocks = topologicalSort(region); + for (auto indexedBB : llvm::enumerate(blocks)) { + Block *bb = indexedBB.value(); + llvm::BasicBlock *curLLVMBB = blockMapping[bb]; + if (bb->isEntryBlock()) + codeGenIPBBTI->setSuccessor(0, curLLVMBB); + + // TODO: Error not returned up the hierarchy + if (failed(convertBlock(*bb, /*ignoreArguments=*/indexedBB.index() == 0))) + return; + + // If this block has the terminator then add a jump to + // continuation bb + for (auto &op : *bb) { + if (isa(op)) { + builder.SetInsertPoint(curLLVMBB); + builder.CreateBr(&continuationIP); + } + } + } + // Finally, after all blocks have been traversed and values mapped, + // connect the PHI nodes to the results of preceding blocks. + connectPHINodes(region, valueMapping, blockMapping); +} + +LogicalResult ModuleTranslation::convertOmpMaster(Operation &opInst, + llvm::IRBuilder<> &builder) { + using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; + + auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP, + llvm::BasicBlock &continuationIP) { + llvm::LLVMContext &llvmContext = llvmModule->getContext(); + + llvm::BasicBlock *codeGenIPBB = codeGenIP.getBlock(); + llvm::Instruction *codeGenIPBBTI = codeGenIPBB->getTerminator(); + + builder.SetInsertPoint(codeGenIPBB); + // MasterOp has only `1` region associated with it. + auto ®ion = cast(opInst).getRegion(); + for (auto &bb : region) { + auto *llvmBB = llvm::BasicBlock::Create( + llvmContext, "omp.master.region", codeGenIP.getBlock()->getParent()); + blockMapping[&bb] = llvmBB; + } + convertOmpOpRegions(region, valueMapping, blockMapping, codeGenIPBBTI, + continuationIP, builder); + }; + + // TODO: Perform finalization actions for variables. This has to be + // called for variables which have destructors/finalizers. + auto finiCB = [&](InsertPointTy codeGenIP) {}; + + llvm::OpenMPIRBuilder::InsertPointTy allocaIP(builder.saveIP()); + builder.restoreIP(ompBuilder->CreateMaster(builder, bodyGenCB, finiCB)); + return success(); +} + /// Given an OpenMP MLIR operation, create the corresponding LLVM IR /// (including OpenMP runtime calls). LogicalResult @@ -507,6 +548,7 @@ .Case([&](omp::TerminatorOp) { return success(); }) .Case( [&](omp::ParallelOp) { return convertOmpParallel(opInst, builder); }) + .Case([&](omp::MasterOp) { return convertOmpMaster(opInst, builder); }) .Default([&](Operation *inst) { return inst->emitError("unsupported OpenMP operation: ") << inst->getName(); diff --git a/mlir/test/Target/openmp-llvm.mlir b/mlir/test/Target/openmp-llvm.mlir --- a/mlir/test/Target/openmp-llvm.mlir +++ b/mlir/test/Target/openmp-llvm.mlir @@ -202,7 +202,19 @@ llvm.return } - // CHECK: define internal void @[[OMP_OUTLINED_FN_3_3]] // CHECK: define internal void @[[OMP_OUTLINED_FN_3_2]] // CHECK: define internal void @[[OMP_OUTLINED_FN_3_1]] + +// CHECK-LABEL: define void @test_omp_master() +// CHECK: [[OMP_THREAD_3_4:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}}) +// CHECK-NEXT: {{[0-9]+}} = call i32 @__kmpc_master(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD_3_4]]) +// CHECK: omp.master.region +// CHECK: call void @__kmpc_end_master(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD_3_4]]) +// CHECK: br label %omp_region.end +llvm.func @test_omp_master() -> () { + "omp.master" ()({ + omp.terminator + }):()->() + llvm.return +}