[Flang][OpenMP][MLIR] Check for presence of Box type before emitting store in MapInfoFinalization pass (#135477)

Currently we don't check for the presence of descriptor/BoxTypes before
emitting stores which lower to memcpys, the issue with this is that
users can have optional arguments, where they don't provide an input,
making the argument effectively null. This can still be mapped and this
causes issues at the moment as we'll emit a memcpy for function
arguments to store to a local variable for certain edge cases, when we
perform this memcpy on a null input, we cause a segfault at runtime.

The fix to this is to simply create a branch around the store that
checks if the data we're copying from is actually present. If it is, we
proceed with the store, if it isn't we skip it.
This commit is contained in:
agozillon 2025-04-14 17:15:56 +02:00 committed by GitHub
parent 092b6e73e6
commit b2c9a58b8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 72 additions and 1 deletions

View File

@ -153,7 +153,15 @@ class MapInfoFinalizationPass
builder.setInsertionPointToStart(allocaBlock);
auto alloca = builder.create<fir::AllocaOp>(loc, descriptor.getType());
builder.restoreInsertionPoint(insPt);
builder.create<fir::StoreOp>(loc, descriptor, alloca);
// We should only emit a store if the passed in data is present, it is
// possible a user passes in no argument to an optional parameter, in which
// case we cannot store or we'll segfault on the emitted memcpy.
auto isPresent =
builder.create<fir::IsPresentOp>(loc, builder.getI1Type(), descriptor);
builder.genIfOp(loc, {}, isPresent, false)
.genThen(
[&]() { builder.create<fir::StoreOp>(loc, descriptor, alloca); })
.end();
return slot = alloca;
}

View File

@ -0,0 +1,27 @@
!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
module foo
implicit none
contains
subroutine test(I,A)
implicit none
real(4), optional, intent(inout) :: A(:)
integer(kind=4), intent(in) :: I
!$omp target data map(to: A) if (I>0)
!$omp end target data
end subroutine test
end module foo
! CHECK-LABEL: func.func @_QMfooPtest(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "i"},
! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a", fir.optional}) {
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.array<?xf32>>
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{.*}} {fortran_attrs = #fir.var_attrs<intent_inout, optional>, uniq_name = "_QMfooFtestEa"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
! CHECK: %{{.*}} = fir.is_present %{{.*}}#1 : (!fir.box<!fir.array<?xf32>>) -> i1
! CHECK: %{{.*}}:5 = fir.if %{{.*}}
! CHECK: %[[VAL_4:.*]] = fir.is_present %[[VAL_3]]#1 : (!fir.box<!fir.array<?xf32>>) -> i1
! CHECK: fir.if %[[VAL_4]] {
! CHECK: fir.store %[[VAL_3]]#1 to %[[VAL_2]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
! CHECK: }

View File

@ -0,0 +1,36 @@
! OpenMP offloading test that checks we do not cause a segfault when mapping
! optional function arguments (present or otherwise). No results requiring
! checking other than that the program compiles and runs to completion with no
! error.
! REQUIRES: flang, amdgpu
! RUN: %libomptarget-compile-fortran-run-and-check-generic
module foo
implicit none
contains
subroutine test(I,A)
implicit none
real(4), optional, intent(inout) :: A(:)
integer(kind=4), intent(in) :: I
!$omp target data map(to: A) if (I>0)
!$omp end target data
!$omp target enter data map(to:A) if (I>0)
!$omp target exit data map(from:A) if (I>0)
end subroutine test
end module foo
program main
use foo
implicit none
real :: array(10)
call test(0)
call test(1)
call test(0, array)
call test(1, array)
print *, "PASSED"
end program main
! CHECK: PASSED