222 changes: 157 additions & 65 deletions llvm/include/llvm/Support/GenericDomTreeConstruction.h

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions llvm/lib/IR/Dominators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,9 @@ template void llvm::DomTreeBuilder::DeleteEdge<DomTreeBuilder::BBPostDomTree>(
DomTreeBuilder::BBPostDomTree &DT, BasicBlock *From, BasicBlock *To);

template void llvm::DomTreeBuilder::ApplyUpdates<DomTreeBuilder::BBDomTree>(
DomTreeBuilder::BBDomTree &DT, DomTreeBuilder::BBDomTreeGraphDiff &);
DomTreeBuilder::BBDomTree &DT, DomTreeBuilder::BBUpdates);
template void llvm::DomTreeBuilder::ApplyUpdates<DomTreeBuilder::BBPostDomTree>(
DomTreeBuilder::BBPostDomTree &DT,
DomTreeBuilder::BBPostDomTreeGraphDiff &);
DomTreeBuilder::BBPostDomTree &DT, DomTreeBuilder::BBUpdates);

template bool llvm::DomTreeBuilder::Verify<DomTreeBuilder::BBDomTree>(
const DomTreeBuilder::BBDomTree &DT,
Expand Down
23 changes: 21 additions & 2 deletions mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,27 @@ def BarrierOp : OpenMP_Op<"barrier"> {
the construct appears.
}];

let parser = [{ return success(); }];
let printer = [{ p << getOperationName(); }];
let assemblyFormat = "attr-dict";
}

def TaskwaitOp : OpenMP_Op<"taskwait"> {
let summary = "taskwait construct";
let description = [{
The taskwait construct specifies a wait on the completion of child tasks
of the current task.
}];

let assemblyFormat = "attr-dict";
}

def TaskyieldOp : OpenMP_Op<"taskyield"> {
let summary = "taskyield construct";
let description = [{
The taskyield construct specifies that the current task can be suspended
in favor of execution of a different task.
}];

let assemblyFormat = "attr-dict";
}

#endif // OPENMP_OPS
2 changes: 2 additions & 0 deletions mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class ModuleTranslation {

virtual LogicalResult convertOperation(Operation &op,
llvm::IRBuilder<> &builder);
virtual LogicalResult convertOmpOperation(Operation &op,
llvm::IRBuilder<> &builder);
static std::unique_ptr<llvm::Module> prepareLLVMModule(Operation *m);

/// A helper to look up remapped operands in the value remapping table.
Expand Down
41 changes: 30 additions & 11 deletions mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "mlir/Target/LLVMIR/ModuleTranslation.h"

#include "DebugTranslation.h"
#include "mlir/ADT/TypeSwitch.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/IR/Attributes.h"
Expand Down Expand Up @@ -306,6 +307,34 @@ ModuleTranslation::ModuleTranslation(Operation *module,
}
ModuleTranslation::~ModuleTranslation() {}

/// Given an OpenMP MLIR operation, create the corresponding LLVM IR
/// (including OpenMP runtime calls).
LogicalResult
ModuleTranslation::convertOmpOperation(Operation &opInst,
llvm::IRBuilder<> &builder) {
if (!ompBuilder) {
ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
ompBuilder->initialize();
}
return mlir::TypeSwitch<Operation *, LogicalResult>(&opInst)
.Case([&](omp::BarrierOp) {
ompBuilder->CreateBarrier(builder.saveIP(), llvm::omp::OMPD_barrier);
return success();
})
.Case([&](omp::TaskwaitOp) {
ompBuilder->CreateTaskwait(builder.saveIP());
return success();
})
.Case([&](omp::TaskyieldOp) {
ompBuilder->CreateTaskyield(builder.saveIP());
return success();
})
.Default([&](Operation *inst) {
return inst->emitError("unsupported OpenMP operation: ")
<< inst->getName();
});
}

/// Given a single MLIR operation, create the corresponding LLVM IR operation
/// using the `builder`. LLVM IR Builder does not have a generic interface so
/// this has to be a long chain of `if`s calling different functions with a
Expand Down Expand Up @@ -415,17 +444,7 @@ LogicalResult ModuleTranslation::convertOperation(Operation &opInst,
}

if (opInst.getDialect() == ompDialect) {
if (!ompBuilder) {
ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
ompBuilder->initialize();
}

if (isa<omp::BarrierOp>(opInst)) {
ompBuilder->CreateBarrier(builder.saveIP(), llvm::omp::OMPD_barrier);
return success();
}
return opInst.emitError("unsupported OpenMP operation: ")
<< opInst.getName();
return convertOmpOperation(opInst, builder);
}

return opInst.emitError("unsupported or non-LLVM operation: ")
Expand Down
12 changes: 12 additions & 0 deletions mlir/test/Dialect/OpenMP/ops.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,15 @@ func @omp_barrier() -> () {
omp.barrier
return
}

func @omp_taskwait() -> () {
// CHECK: omp.taskwait
omp.taskwait
return
}

func @omp_taskyield() -> () {
// CHECK: omp.taskyield
omp.taskyield
return
}
15 changes: 12 additions & 3 deletions mlir/test/Target/openmp-llvm.mlir
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s

// CHECK-LABEL: define void @empty()
// CHECK: [[OMP_THREAD:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}})
// CHECK-NEXT: call void @__kmpc_barrier(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD]])
// CHECK-NEXT: ret void
llvm.func @empty() {
// CHECK: [[OMP_THREAD:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}})
// CHECK-NEXT: call void @__kmpc_barrier(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD]])
omp.barrier

// CHECK: [[OMP_THREAD1:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}})
// CHECK-NEXT: [[RET_VAL:%.*]] = call i32 @__kmpc_omp_taskwait(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD1]])
omp.taskwait

// CHECK: [[OMP_THREAD2:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}})
// CHECK-NEXT: [[RET_VAL:%.*]] = call i32 @__kmpc_omp_taskyield(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD2]], i32 0)
omp.taskyield

// CHECK-NEXT: ret void
llvm.return
}