-
Notifications
You must be signed in to change notification settings - Fork 14k
[flang][OpenMP] Map ByRef if size/alignment exceed that of a pointer #130832
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flang][OpenMP] Map ByRef if size/alignment exceed that of a pointer #130832
Conversation
Improve the check for whether a type can be passed by copy. Currently, passing by copy is done via the OMP_MAP_LITERAL mapping, which can only transfer as much data as can be contained in a pointer representation.
@llvm/pr-subscribers-offload @llvm/pr-subscribers-flang-fir-hlfir Author: Krzysztof Parzyszek (kparzysz) ChangesImprove the check for whether a type can be passed by copy. Currently, passing by copy is done via the OMP_MAP_LITERAL mapping, which can only transfer as much data as can be contained in a pointer representation. Full diff: https://github.com/llvm/llvm-project/pull/130832.diff 2 Files Affected:
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 77786742b3e13..651ed3055f203 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2192,6 +2192,24 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
/*useDelayedPrivatization=*/true, symTable);
dsp.processStep1(&clauseOps);
+ // Check if a value of type `type` be passed to the kernel by value.
+ // All kernel parameters are of pointer type, so if the value can be
+ // represented inside of a pointer, then it can be passed by value.
+ auto isLiteralType = [&](mlir::Type type) {
+ if (!fir::isa_trivial(type) && !fir::isa_char(type))
+ return false;
+
+ const mlir::DataLayout &dl = firOpBuilder.getDataLayout();
+ mlir::Type ptrTy =
+ mlir::LLVM::LLVMPointerType::get(&converter.getMLIRContext());
+ uint64_t ptrSize = dl.getTypeSize(ptrTy);
+ uint64_t ptrAlign = dl.getTypePreferredAlignment(ptrTy);
+
+ auto [size, align] = fir::getTypeSizeAndAlignmentOrCrash(
+ loc, type, dl, converter.getKindMap());
+ return size <= ptrSize && align <= ptrAlign;
+ };
+
// 5.8.1 Implicit Data-Mapping Attribute Rules
// The following code follows the implicit data-mapping rules to map all the
// symbols used inside the region that do not have explicit data-environment
@@ -2268,7 +2286,7 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
}
- } else if (fir::isa_trivial(eleType) || fir::isa_char(eleType)) {
+ } else if (isLiteralType(eleType)) {
captureKind = mlir::omp::VariableCaptureKind::ByCopy;
} else if (!fir::isa_builtin_cptr_type(eleType)) {
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
diff --git a/flang/test/Lower/OpenMP/target-map-complex.f90 b/flang/test/Lower/OpenMP/target-map-complex.f90
new file mode 100644
index 0000000000000..c15a10e4804dd
--- /dev/null
+++ b/flang/test/Lower/OpenMP/target-map-complex.f90
@@ -0,0 +1,33 @@
+!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+! Check that the complex*4 is passed by value. but complex*8 is passed by
+! reference
+
+!CHECK-LABEL: func.func @_QMmPbar()
+!CHECK: %[[V0:[0-9]+]]:2 = hlfir.declare {{.*}} (!fir.ref<complex<f64>>) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>)
+!CHECK: %[[V1:[0-9]+]]:2 = hlfir.declare {{.*}} (!fir.ref<complex<f32>>) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>)
+!CHECK: %[[V2:[0-9]+]] = omp.map.info var_ptr(%[[V1]]#1 : !fir.ref<complex<f32>>, complex<f32>) {{.*}} capture(ByCopy)
+!CHECK: %[[V3:[0-9]+]] = omp.map.info var_ptr(%[[V0]]#1 : !fir.ref<complex<f64>>, complex<f64>) {{.*}} capture(ByRef)
+!CHECK: omp.target map_entries(%[[V2]] -> {{.*}}, %[[V3]] -> {{.*}} : !fir.ref<complex<f32>>, !fir.ref<complex<f64>>)
+
+module m
+ implicit none
+ complex(kind=4) :: cfval = (24, 25)
+ complex(kind=8) :: cdval = (28, 29)
+ interface
+ subroutine foo(x, y)
+ complex(kind=4) :: x
+ complex(kind=8) :: y
+ !$omp declare target
+ end
+ end interface
+
+contains
+
+subroutine bar()
+!$omp target
+ call foo(cfval, cdval)
+!$omp end target
+end
+
+end module
|
@llvm/pr-subscribers-flang-openmp Author: Krzysztof Parzyszek (kparzysz) ChangesImprove the check for whether a type can be passed by copy. Currently, passing by copy is done via the OMP_MAP_LITERAL mapping, which can only transfer as much data as can be contained in a pointer representation. Full diff: https://github.com/llvm/llvm-project/pull/130832.diff 2 Files Affected:
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 77786742b3e13..651ed3055f203 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2192,6 +2192,24 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
/*useDelayedPrivatization=*/true, symTable);
dsp.processStep1(&clauseOps);
+ // Check if a value of type `type` be passed to the kernel by value.
+ // All kernel parameters are of pointer type, so if the value can be
+ // represented inside of a pointer, then it can be passed by value.
+ auto isLiteralType = [&](mlir::Type type) {
+ if (!fir::isa_trivial(type) && !fir::isa_char(type))
+ return false;
+
+ const mlir::DataLayout &dl = firOpBuilder.getDataLayout();
+ mlir::Type ptrTy =
+ mlir::LLVM::LLVMPointerType::get(&converter.getMLIRContext());
+ uint64_t ptrSize = dl.getTypeSize(ptrTy);
+ uint64_t ptrAlign = dl.getTypePreferredAlignment(ptrTy);
+
+ auto [size, align] = fir::getTypeSizeAndAlignmentOrCrash(
+ loc, type, dl, converter.getKindMap());
+ return size <= ptrSize && align <= ptrAlign;
+ };
+
// 5.8.1 Implicit Data-Mapping Attribute Rules
// The following code follows the implicit data-mapping rules to map all the
// symbols used inside the region that do not have explicit data-environment
@@ -2268,7 +2286,7 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
}
- } else if (fir::isa_trivial(eleType) || fir::isa_char(eleType)) {
+ } else if (isLiteralType(eleType)) {
captureKind = mlir::omp::VariableCaptureKind::ByCopy;
} else if (!fir::isa_builtin_cptr_type(eleType)) {
mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
diff --git a/flang/test/Lower/OpenMP/target-map-complex.f90 b/flang/test/Lower/OpenMP/target-map-complex.f90
new file mode 100644
index 0000000000000..c15a10e4804dd
--- /dev/null
+++ b/flang/test/Lower/OpenMP/target-map-complex.f90
@@ -0,0 +1,33 @@
+!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+! Check that the complex*4 is passed by value. but complex*8 is passed by
+! reference
+
+!CHECK-LABEL: func.func @_QMmPbar()
+!CHECK: %[[V0:[0-9]+]]:2 = hlfir.declare {{.*}} (!fir.ref<complex<f64>>) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>)
+!CHECK: %[[V1:[0-9]+]]:2 = hlfir.declare {{.*}} (!fir.ref<complex<f32>>) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>)
+!CHECK: %[[V2:[0-9]+]] = omp.map.info var_ptr(%[[V1]]#1 : !fir.ref<complex<f32>>, complex<f32>) {{.*}} capture(ByCopy)
+!CHECK: %[[V3:[0-9]+]] = omp.map.info var_ptr(%[[V0]]#1 : !fir.ref<complex<f64>>, complex<f64>) {{.*}} capture(ByRef)
+!CHECK: omp.target map_entries(%[[V2]] -> {{.*}}, %[[V3]] -> {{.*}} : !fir.ref<complex<f32>>, !fir.ref<complex<f64>>)
+
+module m
+ implicit none
+ complex(kind=4) :: cfval = (24, 25)
+ complex(kind=8) :: cdval = (28, 29)
+ interface
+ subroutine foo(x, y)
+ complex(kind=4) :: x
+ complex(kind=8) :: y
+ !$omp declare target
+ end
+ end interface
+
+contains
+
+subroutine bar()
+!$omp target
+ call foo(cfval, cdval)
+!$omp end target
+end
+
+end module
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, might be worth having an offload test checking that we can't writeback to implicitly captured larger literal types, I highly doubt this change would allow that, but always good to be certain and helps to have another test for the future incase some other change does something weird :-)
Make sure they are not TOFROM.
…lvm#130832) Improve the check for whether a type can be passed by copy. Currently, passing by copy is done via the OMP_MAP_LITERAL mapping, which can only transfer as much data as can be contained in a pointer representation.
Improve the check for whether a type can be passed by copy. Currently, passing by copy is done via the OMP_MAP_LITERAL mapping, which can only transfer as much data as can be contained in a pointer representation.