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 @@ -786,6 +786,59 @@ return success(); } +llvm::AtomicOrdering convertAtomicOrdering(Optional AOAttr) { + if (!AOAttr.hasValue()) + return llvm::AtomicOrdering::Monotonic; // Default Memory Ordering + + llvm::AtomicOrdering AO = llvm::AtomicOrdering::Monotonic; + StringRef AOString = AOAttr.getValue(); + if (AOString == "seq_cst") + AO = llvm::AtomicOrdering::SequentiallyConsistent; + else if (AOString == "acq_rel") + AO = llvm::AtomicOrdering::AcquireRelease; + else if (AOString == "acquire") + AO = llvm::AtomicOrdering::Acquire; + else if (AOString == "release") + AO = llvm::AtomicOrdering::Release; + else if (AOString == "relaxed") + AO = llvm::AtomicOrdering::Monotonic; + return AO; +} + +static LogicalResult +convertOmpAtomicRead(Operation &opInst, llvm::IRBuilderBase &builder, + LLVM::ModuleTranslation &moduleTranslation) { + + auto readOp = cast(opInst); + llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder(); + + // Set up the source location value for OpenMP runtime. + llvm::DISubprogram *subprogram = + builder.GetInsertBlock()->getParent()->getSubprogram(); + const llvm::DILocation *diLoc = + moduleTranslation.translateLoc(opInst.getLoc(), subprogram); + llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder.saveIP(), + llvm::DebugLoc(diLoc)); + llvm::AtomicOrdering AO = convertAtomicOrdering(readOp.memory_order()); + llvm::Value *address = moduleTranslation.lookupValue(readOp.address()); + llvm::OpenMPIRBuilder::InsertPointTy currentIP = builder.saveIP(); + + // Insert alloca for result + llvm::OpenMPIRBuilder::InsertPointTy allocaIP = + findAllocaInsertPoint(builder, moduleTranslation); + builder.restoreIP(allocaIP); + llvm::Value *v = builder.CreateAlloca( + moduleTranslation.convertType(readOp.getResult().getType())); + moduleTranslation.mapValue(readOp.getResult(), v); + + // Restore the IP and insert Atomic Read + builder.restoreIP(currentIP); + llvm::OpenMPIRBuilder::AtomicOpValue V = {v, false, false}; + llvm::OpenMPIRBuilder::AtomicOpValue X = {address, false, false}; + builder.restoreIP(ompBuilder->createAtomicRead(ompLoc, X, V, AO)); + return success(); +} + /// Converts an OpenMP reduction operation using OpenMPIRBuilder. Expects the /// mapping between reduction variables and their private equivalents to have /// been stored on the ModuleTranslation stack. Currently only supports @@ -907,6 +960,9 @@ .Case([&](omp::WsLoopOp) { return convertOmpWsLoop(*op, builder, moduleTranslation); }) + .Case([&](omp::AtomicReadOp) { + return convertOmpAtomicRead(*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 @@ -706,3 +706,33 @@ llvm.return } + +// ----- + +// CHECK-LABEL: @omp_atomic_read +// CHECK-SAME: (i32* %[[ARG0:.*]]) +llvm.func @omp_atomic_read(%arg0 : !llvm.ptr) -> () { + // CHECK: %{{.*}} = alloca i32, align 4 + // CHECK: %{{.*}} = alloca i32, align 4 + // CHECK: %{{.*}} = alloca i32, align 4 + // CHECK: %{{.*}} = alloca i32, align 4 + + // CHECK: %[[X1:.*]] = load atomic i32, i32* %[[ARG0]] monotonic, align 4 + // CHECK: store i32 %[[X1]], i32* %{{.*}}, align 4 + %x1 = omp.atomic.read %arg0 : !llvm.ptr -> i32 + + // CHECK: %[[X2:.*]] = load atomic i32, i32* %[[ARG0]] seq_cst, align 4 + // CHECK: call void @__kmpc_flush(%{{.*}}) + // CHECK: store i32 %[[X2]], i32* %{{.*}}, align 4 + %x2 = omp.atomic.read %arg0 memory_order(seq_cst) : !llvm.ptr -> i32 + + // CHECK: %[[X3:.*]] = load atomic i32, i32* %[[ARG0]] acquire, align 4 + // CHECK: call void @__kmpc_flush(%{{.*}}) + // CHECK: store i32 %[[X3]], i32* %{{.*}}, align 4 + %x3 = omp.atomic.read %arg0 memory_order(acquire) : !llvm.ptr -> i32 + + // CHECK: %[[X4:.*]] = load atomic i32, i32* %[[ARG0]] monotonic, align 4 + // CHECK: store i32 %[[X4]], i32* %{{.*}}, align 4 + %x4 = omp.atomic.read %arg0 memory_order(relaxed) : !llvm.ptr -> i32 + llvm.return +} \ No newline at end of file