forked from OSchip/llvm-project
[MLIR,OpenMP] Added support for lowering MasterOp to LLVMIR
Some Ops in OMP dialect have regions associated with them i.e `ParallelOp` `MasterOp`. Lowering of these regions involves interfacing with `OMPIRBuilder` using callbacks, yet there still exist opportunities for sharing common code in between. This patch factors out common code into a separate function and adds support for lowering `MasterOp` using that. Lowering of `ParallelOp` is also modified appropriately. Reviewed By: ftynse Differential Revision: https://reviews.llvm.org/D87247
This commit is contained in:
parent
5755522b5a
commit
c11d868a39
|
@ -91,7 +91,15 @@ protected:
|
|||
llvm::IRBuilder<> &builder);
|
||||
virtual LogicalResult convertOmpParallel(Operation &op,
|
||||
llvm::IRBuilder<> &builder);
|
||||
|
||||
virtual LogicalResult convertOmpMaster(Operation &op,
|
||||
llvm::IRBuilder<> &builder);
|
||||
void convertOmpOpRegions(Region ®ion,
|
||||
DenseMap<Value, llvm::Value *> &valueMapping,
|
||||
DenseMap<Block *, llvm::BasicBlock *> &blockMapping,
|
||||
llvm::Instruction *codeGenIPBBTI,
|
||||
llvm::BasicBlock &continuationIP,
|
||||
llvm::IRBuilder<> &builder,
|
||||
LogicalResult &bodyGenStatus);
|
||||
/// Converts the type from MLIR LLVM dialect to LLVM.
|
||||
llvm::Type *convertType(LLVMType type);
|
||||
|
||||
|
|
|
@ -385,6 +385,9 @@ LogicalResult
|
|||
ModuleTranslation::convertOmpParallel(Operation &opInst,
|
||||
llvm::IRBuilder<> &builder) {
|
||||
using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
|
||||
// TODO: support error propagation in OpenMPIRBuilder and use it instead of
|
||||
// relying on captured variables.
|
||||
LogicalResult bodyGenStatus = success();
|
||||
|
||||
auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
|
||||
llvm::BasicBlock &continuationIP) {
|
||||
|
@ -402,31 +405,10 @@ ModuleTranslation::convertOmpParallel(Operation &opInst,
|
|||
blockMapping[&bb] = llvmBB;
|
||||
}
|
||||
|
||||
// Then, convert blocks one by one in topological order to ensure
|
||||
// defs are converted before uses.
|
||||
llvm::SetVector<Block *> blocks = topologicalSort(region);
|
||||
for (auto indexedBB : llvm::enumerate(blocks)) {
|
||||
Block *bb = indexedBB.value();
|
||||
llvm::BasicBlock *curLLVMBB = blockMapping[bb];
|
||||
if (bb->isEntryBlock()) {
|
||||
assert(codeGenIPBBTI->getNumSuccessors() == 1 &&
|
||||
"OpenMPIRBuilder provided entry block has multiple successors");
|
||||
assert(codeGenIPBBTI->getSuccessor(0) == &continuationIP &&
|
||||
"ContinuationIP is not the successor of OpenMPIRBuilder "
|
||||
"provided entry block");
|
||||
codeGenIPBBTI->setSuccessor(0, curLLVMBB);
|
||||
}
|
||||
|
||||
// TODO: Error not returned up the hierarchy
|
||||
if (failed(convertBlock(*bb, /*ignoreArguments=*/indexedBB.index() == 0)))
|
||||
return;
|
||||
}
|
||||
|
||||
convertOmpOpRegions(region, valueMapping, blockMapping, codeGenIPBBTI,
|
||||
continuationIP, builder, bodyGenStatus);
|
||||
ompContinuationIPStack.pop_back();
|
||||
|
||||
// Finally, after all blocks have been traversed and values mapped,
|
||||
// connect the PHI nodes to the results of preceding blocks.
|
||||
connectPHINodes(region, valueMapping, blockMapping);
|
||||
};
|
||||
|
||||
// TODO: Perform appropriate actions according to the data-sharing
|
||||
|
@ -459,12 +441,79 @@ ModuleTranslation::convertOmpParallel(Operation &opInst,
|
|||
// entry or the alloca insertion point as provided by the body callback
|
||||
// above.
|
||||
llvm::OpenMPIRBuilder::InsertPointTy allocaIP(builder.saveIP());
|
||||
if (failed(bodyGenStatus))
|
||||
return failure();
|
||||
builder.restoreIP(
|
||||
ompBuilder->createParallel(builder, allocaIP, bodyGenCB, privCB, finiCB,
|
||||
ifCond, numThreads, pbKind, isCancellable));
|
||||
return success();
|
||||
}
|
||||
|
||||
void ModuleTranslation::convertOmpOpRegions(
|
||||
Region ®ion, DenseMap<Value, llvm::Value *> &valueMapping,
|
||||
DenseMap<Block *, llvm::BasicBlock *> &blockMapping,
|
||||
llvm::Instruction *codeGenIPBBTI, llvm::BasicBlock &continuationIP,
|
||||
llvm::IRBuilder<> &builder, LogicalResult &bodyGenStatus) {
|
||||
// Convert blocks one by one in topological order to ensure
|
||||
// defs are converted before uses.
|
||||
llvm::SetVector<Block *> blocks = topologicalSort(region);
|
||||
for (auto indexedBB : llvm::enumerate(blocks)) {
|
||||
Block *bb = indexedBB.value();
|
||||
llvm::BasicBlock *curLLVMBB = blockMapping[bb];
|
||||
if (bb->isEntryBlock()) {
|
||||
assert(codeGenIPBBTI->getNumSuccessors() == 1 &&
|
||||
"OpenMPIRBuilder provided entry block has multiple successors");
|
||||
assert(codeGenIPBBTI->getSuccessor(0) == &continuationIP &&
|
||||
"ContinuationIP is not the successor of OpenMPIRBuilder "
|
||||
"provided entry block");
|
||||
codeGenIPBBTI->setSuccessor(0, curLLVMBB);
|
||||
}
|
||||
|
||||
if (failed(convertBlock(*bb, /*ignoreArguments=*/indexedBB.index() == 0))) {
|
||||
bodyGenStatus = failure();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
// TODO: support error propagation in OpenMPIRBuilder and use it instead of
|
||||
// relying on captured variables.
|
||||
LogicalResult bodyGenStatus = success();
|
||||
|
||||
auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
|
||||
llvm::BasicBlock &continuationIP) {
|
||||
llvm::LLVMContext &llvmContext = llvmModule->getContext();
|
||||
|
||||
llvm::BasicBlock *codeGenIPBB = codeGenIP.getBlock();
|
||||
llvm::Instruction *codeGenIPBBTI = codeGenIPBB->getTerminator();
|
||||
ompContinuationIPStack.push_back(&continuationIP);
|
||||
|
||||
// MasterOp has only `1` region associated with it.
|
||||
auto ®ion = cast<omp::MasterOp>(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, bodyGenStatus);
|
||||
ompContinuationIPStack.pop_back();
|
||||
};
|
||||
|
||||
// TODO: Perform finalization actions for variables. This has to be
|
||||
// called for variables which have destructors/finalizers.
|
||||
auto finiCB = [&](InsertPointTy codeGenIP) {};
|
||||
|
||||
builder.restoreIP(ompBuilder->createMaster(builder, bodyGenCB, finiCB));
|
||||
return success();
|
||||
}
|
||||
|
||||
/// Given an OpenMP MLIR operation, create the corresponding LLVM IR
|
||||
/// (including OpenMP runtime calls).
|
||||
LogicalResult
|
||||
|
@ -505,6 +554,7 @@ ModuleTranslation::convertOmpOperation(Operation &opInst,
|
|||
})
|
||||
.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();
|
||||
|
|
|
@ -264,3 +264,30 @@ llvm.func @test_omp_parallel_5() -> () {
|
|||
}
|
||||
llvm.return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define void @test_omp_master()
|
||||
llvm.func @test_omp_master() -> () {
|
||||
// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @{{.*}} to
|
||||
// CHECK: omp.par.region1:
|
||||
omp.parallel {
|
||||
omp.master {
|
||||
// CHECK: [[OMP_THREAD_3_4:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}})
|
||||
// CHECK: {{[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
|
||||
omp.terminator
|
||||
}
|
||||
omp.terminator
|
||||
}
|
||||
omp.parallel {
|
||||
omp.parallel {
|
||||
omp.master {
|
||||
omp.terminator
|
||||
}
|
||||
omp.terminator
|
||||
}
|
||||
omp.terminator
|
||||
}
|
||||
llvm.return
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue