diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp index e94d570b57122..ffc84781f77ff 100644 --- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -15,11 +15,13 @@ #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/LLVMIR/LLVMTypes.h" #include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.h" +#include "mlir/Dialect/OpenMP/OpenMPClauseOperands.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/DialectImplementation.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/OperationSupport.h" +#include "mlir/IR/SymbolTable.h" #include "mlir/Interfaces/FoldInterfaces.h" #include "llvm/ADT/ArrayRef.h" @@ -2640,6 +2642,23 @@ LogicalResult SimdOp::verify() { return emitError() << "'omp.composite' attribute present in non-composite wrapper"; + // Firstprivate is not allowed for SIMD in the standard. Check that none of + // the private decls are for firstprivate. + std::optional privateSyms = getPrivateSyms(); + if (privateSyms) { + for (const Attribute &sym : *privateSyms) { + auto symRef = cast(sym); + omp::PrivateClauseOp privatizer = + SymbolTable::lookupNearestSymbolFrom( + getOperation(), symRef); + if (!privatizer) + return emitError() << "Cannot find privatizer '" << symRef << "'"; + if (privatizer.getDataSharingType() == + DataSharingClauseType::FirstPrivate) + return emitError() << "FIRSTPRIVATE cannot be used with SIMD"; + } + } + return success(); } diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index 7b07243c5f843..b3eb1ab1832c1 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -2894,7 +2894,8 @@ convertOmpSimd(Operation &opInst, llvm::IRBuilderBase &builder, .failed()) return failure(); - // TODO: no call to copyFirstPrivateVars? + // No call to copyFirstPrivateVars because FIRSTPRIVATE is not allowed for + // SIMD. assert(afterAllocas.get()->getSinglePredecessor()); if (failed(initReductionVars(simdOp, reductionArgs, builder, diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir index 060b3cd2455a0..7608ad57c7967 100644 --- a/mlir/test/Dialect/OpenMP/invalid.mlir +++ b/mlir/test/Dialect/OpenMP/invalid.mlir @@ -480,6 +480,39 @@ func.func @omp_simd_pretty_simdlen_safelen(%lb : index, %ub : index, %step : ind // ----- +func.func @omp_simd_bad_privatizer(%lb : index, %ub : index, %step : index) { + %0 = llvm.mlir.constant(1 : i64) : i64 + %1 = llvm.alloca %0 x i32 : (i64) -> !llvm.ptr + // expected-error @below {{Cannot find privatizer '@not_defined'}} + omp.simd private(@not_defined %1 -> %arg0 : !llvm.ptr) { + omp.loop_nest (%arg2) : index = (%lb) to (%ub) inclusive step (%step) { + omp.yield + } + } +} + +// ----- + +omp.private {type = firstprivate} @_QFEp_firstprivate_i32 : i32 copy { +^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr): + %0 = llvm.load %arg0 : !llvm.ptr -> i32 + llvm.store %0, %arg1 : i32, !llvm.ptr + omp.yield(%arg1 : !llvm.ptr) +} +func.func @omp_simd_firstprivate(%lb : index, %ub : index, %step : index) { + %0 = llvm.mlir.constant(1 : i64) : i64 + %1 = llvm.alloca %0 x i32 : (i64) -> !llvm.ptr + // expected-error @below {{FIRSTPRIVATE cannot be used with SIMD}} + omp.simd private(@_QFEp_firstprivate_i32 %1 -> %arg0 : !llvm.ptr) { + omp.loop_nest (%arg2) : index = (%lb) to (%ub) inclusive step (%step) { + omp.yield + } + } + llvm.return +} + +// ----- + // expected-error @below {{op expects alloc region to yield a value of the reduction type}} omp.declare_reduction @add_f32 : f32 alloc {