[flang][OpenMP] use attribute for delayed privatization barrier (#140092)

Fixes #136357

The barrier needs to go between the copying into firstprivate variables
and the initialization call for the OpenMP construct (e.g. wsloop).
There is no way of expressing this in MLIR because for delayed
privatization that is all implicit (added in MLIR->LLVMIR conversion).

The previous approach put the barrier immediately before the wsloop (or
similar). For delayed privatization, the firstprivate copy code would
then be inserted after that, opening the possibility for the race
observed in the bug report.

This patch solves the issue by instead setting an attribute on the mlir
operation, which will instruct openmp dialect to llvm ir conversion to
insert a barrier in the correct place.
This commit is contained in:
Tom Eccles
2025-05-22 15:25:53 +01:00
committed by GitHub
parent b048f3f8d7
commit e9cba3c8ed
5 changed files with 16 additions and 9 deletions

View File

@@ -62,7 +62,7 @@ void DataSharingProcessor::processStep1(
privatize(clauseOps);
insertBarrier();
insertBarrier(clauseOps);
}
void DataSharingProcessor::processStep2(mlir::Operation *op, bool isLoop) {
@@ -231,9 +231,18 @@ bool DataSharingProcessor::needBarrier() {
return false;
}
void DataSharingProcessor::insertBarrier() {
if (needBarrier())
void DataSharingProcessor::insertBarrier(
mlir::omp::PrivateClauseOps *clauseOps) {
if (!needBarrier())
return;
if (useDelayedPrivatization) {
if (clauseOps)
clauseOps->privateNeedsBarrier =
mlir::UnitAttr::get(&converter.getMLIRContext());
} else {
firOpBuilder.create<mlir::omp::BarrierOp>(converter.getCurrentLocation());
}
}
void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) {

View File

@@ -100,7 +100,7 @@ private:
const omp::ObjectList &objects,
llvm::SetVector<const semantics::Symbol *> &symbolSet);
void collectSymbolsForPrivatization();
void insertBarrier();
void insertBarrier(mlir::omp::PrivateClauseOps *clauseOps);
void collectDefaultSymbols();
void collectImplicitSymbols();
void collectPreDeterminedSymbols();

View File

@@ -8,7 +8,7 @@
! CHECK: fir.store %[[VAL_2]] to %[[VAL_0]] : !fir.ref<!fir.box<!fir.heap<i32>>>
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = {{.*}}<allocatable>, uniq_name = "_QFEa"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>)
! CHECK: omp.parallel {
! CHECK: omp.wsloop private(@{{.*}} %{{.*}} -> %{{.*}}, @{{.*}} %{{.*}} -> %[[VAL_17:.*]] : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<i32>) {
! CHECK: omp.wsloop private(@{{.*}} %{{.*}} -> %{{.*}}, @{{.*}} %{{.*}} -> %[[VAL_17:.*]] : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<i32>) private_barrier {
! CHECK: omp.loop_nest
! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = {{.*}}<allocatable>, uniq_name = "_QFEa"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>)
! CHECK: %[[VAL_18:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)

View File

@@ -226,8 +226,7 @@ end subroutine
! Firstprivate update
!CHECK-NEXT: omp.barrier
!CHECK: omp.wsloop private(@{{.*}} %{{.*}}#0 -> %[[CLONE1:.*]], @{{.*}} %{{.*}}#0 -> %[[IV:.*]] : !fir.ref<i32>, !fir.ref<i32>) {
!CHECK: omp.wsloop private(@{{.*}} %{{.*}}#0 -> %[[CLONE1:.*]], @{{.*}} %{{.*}}#0 -> %[[IV:.*]] : !fir.ref<i32>, !fir.ref<i32>) private_barrier {
!CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} {
!CHECK: %[[CLONE1_DECL:.*]]:2 = hlfir.declare %[[CLONE1]] {uniq_name = "_QFfirstpriv_lastpriv_int2Earg1"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)

View File

@@ -20,8 +20,7 @@ end subroutine
! CHECK: func.func @{{.*}}first_and_lastprivate()
! CHECK: %[[ORIG_VAR_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "{{.*}}Evar"}
! CHECK: omp.parallel {
! CHECK: omp.barrier
! CHECK: omp.wsloop private(@{{.*}}var_firstprivate_i32 {{.*}}) {
! CHECK: omp.wsloop private(@{{.*}}var_firstprivate_i32 {{.*}}) private_barrier {
! CHECK: omp.loop_nest {{.*}} {
! CHECK: %[[PRIV_VAR_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "{{.*}}Evar"}
! CHECK: fir.if %{{.*}} {