[mlir][OpenMP] Don't allow firstprivate for simd (#146734)

This is not allowed by the openmp standard.
This commit is contained in:
Tom Eccles
2025-07-04 12:15:07 +01:00
committed by GitHub
parent 3099b7eb5d
commit ea5ee2e743
3 changed files with 54 additions and 1 deletions

View File

@@ -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<ArrayAttr> privateSyms = getPrivateSyms();
if (privateSyms) {
for (const Attribute &sym : *privateSyms) {
auto symRef = cast<SymbolRefAttr>(sym);
omp::PrivateClauseOp privatizer =
SymbolTable::lookupNearestSymbolFrom<omp::PrivateClauseOp>(
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();
}

View File

@@ -2899,7 +2899,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,

View File

@@ -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 {