Skip to content

Commit 096ee4e

Browse files
authored
[Flang][OpenMP] Implement "promotion" of use_device_ptr non-cptr arguments to use_device_addr (#82834)
This effectively implements some now deprecated OpenMP functionality that some applications (most notably at the moment GenASiS) unfortunately depend on (deprecated in specification version 5.2): "If a list item in a use_device_ptr clause is not of type C_PTR, the behavior is as if the list item appeared in a use_device_addr clause. Support for such list items in a use_device_ptr clause is deprecated." This PR downgrades the hard-error to a deprecated warning and "promotes" the above cases by simply moving the offending operands from the use_device_ptr value list to the back of the use_device_addr list (and moves the related symbols, locs and types that form the BlockArgs correspondingly) and then the generation of the target data construct proceeds as normal.
1 parent 59ff907 commit 096ee4e

File tree

4 files changed

+140
-2
lines changed

4 files changed

+140
-2
lines changed

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,58 @@ genTaskGroupOp(Fortran::lower::AbstractConverter &converter,
798798
/*task_reductions=*/nullptr, allocateOperands, allocatorOperands);
799799
}
800800

801+
// This helper function implements the functionality of "promoting"
802+
// non-CPTR arguments of use_device_ptr to use_device_addr
803+
// arguments (automagic conversion of use_device_ptr ->
804+
// use_device_addr in these cases). The way we do so currently is
805+
// through the shuffling of operands from the devicePtrOperands to
806+
// deviceAddrOperands where neccesary and re-organizing the types,
807+
// locations and symbols to maintain the correct ordering of ptr/addr
808+
// input -> BlockArg.
809+
//
810+
// This effectively implements some deprecated OpenMP functionality
811+
// that some legacy applications unfortunately depend on
812+
// (deprecated in specification version 5.2):
813+
//
814+
// "If a list item in a use_device_ptr clause is not of type C_PTR,
815+
// the behavior is as if the list item appeared in a use_device_addr
816+
// clause. Support for such list items in a use_device_ptr clause
817+
// is deprecated."
818+
static void promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr(
819+
llvm::SmallVector<mlir::Value> &devicePtrOperands,
820+
llvm::SmallVector<mlir::Value> &deviceAddrOperands,
821+
llvm::SmallVector<mlir::Type> &useDeviceTypes,
822+
llvm::SmallVector<mlir::Location> &useDeviceLocs,
823+
llvm::SmallVector<const Fortran::semantics::Symbol *> &useDeviceSymbols) {
824+
auto moveElementToBack = [](size_t idx, auto &vector) {
825+
auto *iter = std::next(vector.begin(), idx);
826+
vector.push_back(*iter);
827+
vector.erase(iter);
828+
};
829+
830+
// Iterate over our use_device_ptr list and shift all non-cptr arguments into
831+
// use_device_addr.
832+
for (auto *it = devicePtrOperands.begin(); it != devicePtrOperands.end();) {
833+
if (!fir::isa_builtin_cptr_type(fir::unwrapRefType(it->getType()))) {
834+
deviceAddrOperands.push_back(*it);
835+
// We have to shuffle the symbols around as well, to maintain
836+
// the correct Input -> BlockArg for use_device_ptr/use_device_addr.
837+
// NOTE: However, as map's do not seem to be included currently
838+
// this isn't as pertinent, but we must try to maintain for
839+
// future alterations. I believe the reason they are not currently
840+
// is that the BlockArg assign/lowering needs to be extended
841+
// to a greater set of types.
842+
auto idx = std::distance(devicePtrOperands.begin(), it);
843+
moveElementToBack(idx, useDeviceTypes);
844+
moveElementToBack(idx, useDeviceLocs);
845+
moveElementToBack(idx, useDeviceSymbols);
846+
it = devicePtrOperands.erase(it);
847+
continue;
848+
}
849+
++it;
850+
}
851+
}
852+
801853
static mlir::omp::DataOp
802854
genDataOp(Fortran::lower::AbstractConverter &converter,
803855
Fortran::semantics::SemanticsContext &semaCtx,
@@ -820,6 +872,20 @@ genDataOp(Fortran::lower::AbstractConverter &converter,
820872
useDeviceSymbols);
821873
cp.processUseDeviceAddr(deviceAddrOperands, useDeviceTypes, useDeviceLocs,
822874
useDeviceSymbols);
875+
// This function implements the deprecated functionality of use_device_ptr
876+
// that allows users to provide non-CPTR arguments to it with the caveat
877+
// that the compiler will treat them as use_device_addr. A lot of legacy
878+
// code may still depend on this functionality, so we should support it
879+
// in some manner. We do so currently by simply shifting non-cptr operands
880+
// from the use_device_ptr list into the front of the use_device_addr list
881+
// whilst maintaining the ordering of useDeviceLocs, useDeviceSymbols and
882+
// useDeviceTypes to use_device_ptr/use_device_addr input for BlockArg
883+
// ordering.
884+
// TODO: Perhaps create a user provideable compiler option that will
885+
// re-introduce a hard-error rather than a warning in these cases.
886+
promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr(
887+
devicePtrOperands, deviceAddrOperands, useDeviceTypes, useDeviceLocs,
888+
useDeviceSymbols);
823889
cp.processMap(currentLocation, llvm::omp::Directive::OMPD_target_data,
824890
stmtCtx, mapOperands);
825891

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2948,7 +2948,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) {
29482948
if (name->symbol) {
29492949
if (!(IsBuiltinCPtr(*(name->symbol)))) {
29502950
context_.Say(itr->second->source,
2951-
"'%s' in USE_DEVICE_PTR clause must be of type C_PTR"_err_en_US,
2951+
"Use of non-C_PTR type '%s' in USE_DEVICE_PTR is deprecated, use USE_DEVICE_ADDR instead"_warn_en_US,
29522952
name->ToString());
29532953
} else {
29542954
useDevicePtrNameList.push_back(*name);
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
2+
!RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s
3+
4+
! This tests primary goal is to check the promotion of
5+
! non-CPTR arguments from use_device_ptr to
6+
! use_device_addr works, without breaking any
7+
! functionality
8+
9+
!CHECK: func.func @{{.*}}only_use_device_ptr()
10+
!CHECK: omp.target_data use_device_ptr(%{{.*}} : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) use_device_addr(%{{.*}}, %{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) {
11+
!CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>):
12+
subroutine only_use_device_ptr
13+
use iso_c_binding
14+
integer, pointer, dimension(:) :: array
15+
real, pointer :: pa(:)
16+
type(c_ptr) :: cptr
17+
18+
!$omp target data use_device_ptr(pa, cptr, array)
19+
!$omp end target data
20+
end subroutine
21+
22+
!CHECK: func.func @{{.*}}mix_use_device_ptr_and_addr()
23+
!CHECK: omp.target_data use_device_ptr({{.*}} : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) use_device_addr(%{{.*}}, %{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) {
24+
!CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>):
25+
subroutine mix_use_device_ptr_and_addr
26+
use iso_c_binding
27+
integer, pointer, dimension(:) :: array
28+
real, pointer :: pa(:)
29+
type(c_ptr) :: cptr
30+
31+
!$omp target data use_device_ptr(pa, cptr) use_device_addr(array)
32+
!$omp end target data
33+
end subroutine
34+
35+
!CHECK: func.func @{{.*}}only_use_device_addr()
36+
!CHECK: omp.target_data use_device_addr(%{{.*}}, %{{.*}}, %{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) {
37+
!CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, %{{.*}}: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>):
38+
subroutine only_use_device_addr
39+
use iso_c_binding
40+
integer, pointer, dimension(:) :: array
41+
real, pointer :: pa(:)
42+
type(c_ptr) :: cptr
43+
44+
!$omp target data use_device_addr(pa, cptr, array)
45+
!$omp end target data
46+
end subroutine
47+
48+
!CHECK: func.func @{{.*}}mix_use_device_ptr_and_addr_and_map()
49+
!CHECK: omp.target_data map_entries(%{{.*}}, %{{.*}} : !fir.ref<i32>, !fir.ref<i32>) use_device_ptr(%{{.*}} : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) use_device_addr(%{{.*}}, %{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) {
50+
!CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>):
51+
subroutine mix_use_device_ptr_and_addr_and_map
52+
use iso_c_binding
53+
integer :: i, j
54+
integer, pointer, dimension(:) :: array
55+
real, pointer :: pa(:)
56+
type(c_ptr) :: cptr
57+
58+
!$omp target data use_device_ptr(pa, cptr) use_device_addr(array) map(tofrom: i, j)
59+
!$omp end target data
60+
end subroutine
61+
62+
!CHECK: func.func @{{.*}}only_use_map()
63+
!CHECK: omp.target_data map_entries(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) {
64+
subroutine only_use_map
65+
use iso_c_binding
66+
integer, pointer, dimension(:) :: array
67+
real, pointer :: pa(:)
68+
type(c_ptr) :: cptr
69+
70+
!$omp target data map(pa, cptr, array)
71+
!$omp end target data
72+
end subroutine

flang/test/Semantics/OpenMP/use_device_ptr1.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ subroutine omp_target_data
2727
a = arrayB
2828
!$omp end target data
2929

30-
!ERROR: 'a' in USE_DEVICE_PTR clause must be of type C_PTR
30+
!WARNING: Use of non-C_PTR type 'a' in USE_DEVICE_PTR is deprecated, use USE_DEVICE_ADDR instead
3131
!$omp target data map(tofrom: a) use_device_ptr(a)
3232
a = 2
3333
!$omp end target data

0 commit comments

Comments
 (0)