diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -33,6 +33,23 @@ let assemblyFormat = "attr-dict"; } +//===----------------------------------------------------------------------===// +// 2.13.7 flush Construct +//===----------------------------------------------------------------------===// +def FlushOp : OpenMP_Op<"flush"> { + let summary = "flush construct"; + let description = [{ + The flush construct executes the OpenMP flush operation. This operation + makes a thread’s temporary view of memory consistent with memory and + enforces an order on the memory operations of the variables explicitly + specified or implied. + }]; + + let arguments = (ins Variadic:$varList); + + let assemblyFormat = "attr-dict ($varList^ `:` type($varList))?"; +} + def TaskwaitOp : OpenMP_Op<"taskwait"> { let summary = "taskwait construct"; let description = [{ 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 @@ -317,6 +317,9 @@ ompBuilder = std::make_unique(*llvmModule); ompBuilder->initialize(); } + // flush Construct: !$omp flush [(list)] + // flush with a list is treated same as a flush without a list by ignoring + // the list. return llvm::TypeSwitch(&opInst) .Case([&](omp::BarrierOp) { ompBuilder->CreateBarrier(builder.saveIP(), llvm::omp::OMPD_barrier); @@ -330,6 +333,10 @@ ompBuilder->CreateTaskyield(builder.saveIP()); return success(); }) + .Case([&](omp::FlushOp) { + ompBuilder->CreateFlush(builder.saveIP()); + return success(); + }) .Default([&](Operation *inst) { return inst->emitError("unsupported OpenMP operation: ") << inst->getName(); diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir --- a/mlir/test/Dialect/OpenMP/ops.mlir +++ b/mlir/test/Dialect/OpenMP/ops.mlir @@ -17,3 +17,19 @@ omp.taskyield return } + +func @omp_flush(%data_var : memref) -> () { + // Test without data var + // CHECK: omp.flush + omp.flush + + // Test with one data var + // CHECK: omp.flush + "omp.flush"(%data_var) : (memref) -> () + + // Test with two data var + // CHECK: omp.flush + "omp.flush"(%data_var, %data_var): (memref, memref) -> () + + return +} 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 @@ -1,7 +1,7 @@ // RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s -// CHECK-LABEL: define void @empty() -llvm.func @empty() { +// CHECK-LABEL: define void @empty(i32 %0) +llvm.func @empty(%arg0: !llvm.i32) { // 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 @@ -14,6 +14,12 @@ // 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 + // CHECK: call void @__kmpc_flush(%struct.ident_t* @{{[0-9]+}} + omp.flush + + // CHECK: call void @__kmpc_flush(%struct.ident_t* @{{[0-9]+}} + omp.flush %arg0, %arg0 : !llvm.i32, !llvm.i32 + + // CHECK-NEXT: ret void llvm.return }