-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Flang][OpenMP] Move array bounds tests to HLFIR lowering #67328
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
Conversation
@llvm/pr-subscribers-flang-fir-hlfir @llvm/pr-subscribers-flang-openmp ChangesThis is a copy of the test in flang/test/Lower/OpenMP/FIR/array-bounds.f90 The device test is crashing in the Early Outlining pass. Since this pass is going to be removed, will wait before the device part is updated. Full diff: https://github.com/llvm/llvm-project/pull/67328.diff 1 Files Affected:
diff --git a/flang/test/Lower/OpenMP/array-bounds.f90 b/flang/test/Lower/OpenMP/array-bounds.f90
new file mode 100644
index 000000000000000..597116ac66c3ba8
--- /dev/null
+++ b/flang/test/Lower/OpenMP/array-bounds.f90
@@ -0,0 +1,154 @@
+!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes HOST
+
+!DEVICE-LABEL: func.func @_QPread_write_section_omp_outline_0(
+!DEVICE-SAME: %[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<!fir.array<10xi32>>, %[[ARG2:.*]]: !fir.ref<!fir.array<10xi32>>) attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>, omp.outline_parent_name = "_QPread_write_section"} {
+!DEVICE: %[[C1:.*]] = arith.constant 1 : index
+!DEVICE: %[[C2:.*]] = arith.constant 4 : index
+!DEVICE: %[[C3:.*]] = arith.constant 1 : index
+!DEVICE: %[[C4:.*]] = arith.constant 1 : index
+!DEVICE: %[[BOUNDS0:.*]] = omp.bounds lower_bound(%[[C1]] : index) upper_bound(%[[C2]] : index) stride(%[[C4]] : index) start_idx(%[[C4]] : index)
+!DEVICE: %[[MAP0:.*]] = omp.map_info var_ptr(%[[ARG1]] : !fir.ref<!fir.array<10xi32>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_read(2:5)"}
+!DEVICE: %[[C5:.*]] = arith.constant 1 : index
+!DEVICE: %[[C6:.*]] = arith.constant 4 : index
+!DEVICE: %[[C7:.*]] = arith.constant 1 : index
+!DEVICE: %[[C8:.*]] = arith.constant 1 : index
+!DEVICE: %[[BOUNDS1:.*]] = omp.bounds lower_bound(%[[C5]] : index) upper_bound(%[[C6]] : index) stride(%[[C8]] : index) start_idx(%[[C8]] : index)
+!DEVICE: %[[MAP1:.*]] = omp.map_info var_ptr(%[[ARG2]] : !fir.ref<!fir.array<10xi32>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_write(2:5)"}
+!DEVICE: omp.target map_entries(%[[MAP0]], %[[MAP1]] : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) {
+
+!HOST-LABEL: func.func @_QPread_write_section() {
+!HOST: %0 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFread_write_sectionEi"}
+!HOST: %[[READ:.*]] = fir.address_of(@_QFread_write_sectionEsp_read) : !fir.ref<!fir.array<10xi32>>
+!HOST: %[[C10:.*]] = arith.constant 10 : index
+!HOST: %[[READ_SHAPE:.*]] = fir.shape %[[C10]] : (index) -> !fir.shape<1>
+!HOST: %[[READ_DECL:.*]]:2 = hlfir.declare %[[READ]](%[[READ_SHAPE]]) {uniq_name = "_QFread_write_sectionEsp_read"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>)
+!HOST: %[[WRITE:.*]] = fir.address_of(@_QFread_write_sectionEsp_write) : !fir.ref<!fir.array<10xi32>>
+!HOST: %[[C10:.*]] = arith.constant 10 : index
+!HOST: %[[WRITE_SHAPE:.*]] = fir.shape %[[C10]] : (index) -> !fir.shape<1>
+!HOST: %[[WRITE_DECL:.*]]:2 = hlfir.declare %[[WRITE]](%[[WRITE_SHAPE]]) {uniq_name = "_QFread_write_sectionEsp_write"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>)
+
+!HOST: %[[C1:.*]] = arith.constant 1 : index
+!HOST: %[[C2:.*]] = arith.constant 1 : index
+!HOST: %[[C3:.*]] = arith.constant 4 : index
+!HOST: %[[BOUNDS0:.*]] = omp.bounds lower_bound(%[[C2]] : index) upper_bound(%[[C3]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index)
+!HOST: %[[MAP0:.*]] = omp.map_info var_ptr(%[[READ_DECL]]#1 : !fir.ref<!fir.array<10xi32>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_read(2:5)"}
+!HOST: %[[C4:.*]] = arith.constant 1 : index
+!HOST: %[[C5:.*]] = arith.constant 1 : index
+!HOST: %[[C6:.*]] = arith.constant 4 : index
+!HOST: %[[BOUNDS1:.*]] = omp.bounds lower_bound(%[[C5]] : index) upper_bound(%[[C6]] : index) stride(%[[C4]] : index) start_idx(%[[C4]] : index)
+!HOST: %[[MAP1:.*]] = omp.map_info var_ptr(%[[WRITE_DECL]]#1 : !fir.ref<!fir.array<10xi32>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_write(2:5)"}
+!HOST: omp.target map_entries(%[[MAP0]], %[[MAP1]] : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) {
+
+subroutine read_write_section()
+ integer :: sp_read(10) = (/1,2,3,4,5,6,7,8,9,10/)
+ integer :: sp_write(10) = (/0,0,0,0,0,0,0,0,0,0/)
+
+!$omp target map(tofrom:sp_read(2:5)) map(tofrom:sp_write(2:5))
+ do i = 2, 5
+ sp_write(i) = sp_read(i)
+ end do
+!$omp end target
+end subroutine read_write_section
+
+
+module assumed_array_routines
+ contains
+!DEVICE-LABEL: func.func @_QMassumed_array_routinesPassumed_shape_array_omp_outline_0(
+!DEVICE-SAME: %[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>) attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>, omp.outline_parent_name = "_QMassumed_array_routinesPassumed_shape_array"} {
+!DEVICE: %[[C0:.*]] = arith.constant 1 : index
+!DEVICE: %[[C1:.*]] = arith.constant 4 : index
+!DEVICE: %[[C2:.*]] = arith.constant 0 : index
+!DEVICE: %[[C3:.*]]:3 = fir.box_dims %[[ARG1]], %[[C2]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
+!DEVICE: %[[C4:.*]] = arith.constant 1 : index
+!DEVICE: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C0]] : index) upper_bound(%[[C1]] : index) stride(%[[C3]]#2 : index) start_idx(%[[C4]] : index) {stride_in_bytes = true}
+!DEVICE: %[[ARGADDR:.*]] = fir.box_addr %[[ARG1]] : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
+!DEVICE: %[[MAP:.*]] = omp.map_info var_ptr(%[[ARGADDR]] : !fir.ref<!fir.array<?xi32>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
+!DEVICE: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<?xi32>>) {
+
+!HOST-LABEL: func.func @_QMassumed_array_routinesPassumed_shape_array(
+!HOST-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "arr_read_write"}) {
+!HOST: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]] {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QMassumed_array_routinesFassumed_shape_arrayEarr_read_write"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>)
+!HOST: %[[C0:.*]] = arith.constant 1 : index
+!HOST: %[[C1:.*]] = arith.constant 0 : index
+!HOST: %[[C2:.*]]:3 = fir.box_dims %[[ARG0_DECL]]#1, %[[C1]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
+!HOST: %[[C3:.*]] = arith.constant 1 : index
+!HOST: %[[C4:.*]] = arith.constant 4 : index
+!HOST: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C3]] : index) upper_bound(%[[C4]] : index) stride(%[[C2]]#2 : index) start_idx(%[[C0]] : index) {stride_in_bytes = true}
+!HOST: %[[ADDROF:.*]] = fir.box_addr %[[ARG0_DECL]]#1 : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
+!HOST: %[[MAP:.*]] = omp.map_info var_ptr(%[[ADDROF]] : !fir.ref<!fir.array<?xi32>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
+!HOST: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<?xi32>>) {
+ subroutine assumed_shape_array(arr_read_write)
+ integer, intent(inout) :: arr_read_write(:)
+
+ !$omp target map(tofrom:arr_read_write(2:5))
+ do i = 2, 5
+ arr_read_write(i) = i
+ end do
+ !$omp end target
+ end subroutine assumed_shape_array
+
+!DEVICE-LABEL: func.func @_QMassumed_array_routinesPassumed_size_array_omp_outline_0(
+!DEVICE-SAME: %[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<!fir.array<?xi32>>) attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>, omp.outline_parent_name = "_QMassumed_array_routinesPassumed_size_array"} {
+!DEVICE: %[[C0:.*]] = arith.constant 1 : index
+!DEVICE: %[[C1:.*]] = arith.constant 4 : index
+!DEVICE: %[[C2:.*]] = arith.constant 1 : index
+!DEVICE: %[[C3:.*]] = arith.constant 1 : index
+!DEVICE: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C0]] : index) upper_bound(%[[C1]] : index) stride(%[[C3]] : index) start_idx(%[[C3]] : index)
+!DEVICE: %[[MAP:.*]] = omp.map_info var_ptr(%[[ARG1]] : !fir.ref<!fir.array<?xi32>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
+!DEVICE: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<?xi32>>) {
+
+!HOST-LABEL: func.func @_QMassumed_array_routinesPassumed_size_array(
+!HOST-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "arr_read_write"}) {
+!HOST: %[[UNDEF:.*]] = fir.undefined index
+!HOST: %[[ARG0_SHAPE:.*]] = fir.shape %[[UNDEF]] : (index) -> !fir.shape<1>
+!HOST: %[[ARG0_DECL:.*]]:2 = hlfir.declare %[[ARG0]](%[[ARG0_SHAPE]]) {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QMassumed_array_routinesFassumed_size_arrayEarr_read_write"} : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>)
+!HOST: %[[ALLOCA:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QMassumed_array_routinesFassumed_size_arrayEi"}
+!HOST: %[[C0:.*]] = arith.constant 1 : index
+!HOST: %[[C1:.*]] = arith.constant 1 : index
+!HOST: %[[C2:.*]] = arith.constant 4 : index
+!HOST: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C1]] : index) upper_bound(%[[C2]] : index) stride(%[[C0]] : index) start_idx(%[[C0]] : index)
+!HOST: %[[MAP:.*]] = omp.map_info var_ptr(%[[ARG0_DECL]]#1 : !fir.ref<!fir.array<?xi32>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"}
+!HOST: omp.target map_entries(%[[MAP]] : !fir.ref<!fir.array<?xi32>>) {
+ subroutine assumed_size_array(arr_read_write)
+ integer, intent(inout) :: arr_read_write(*)
+
+ !$omp target map(tofrom:arr_read_write(2:5))
+ do i = 2, 5
+ arr_read_write(i) = i
+ end do
+ !$omp end target
+ end subroutine assumed_size_array
+ end module assumed_array_routines
+
+
+!HOST-LABEL:func.func @_QPcall_assumed_shape_and_size_array() {
+!HOST: %[[C20:.*]] = arith.constant 20 : index
+!HOST: %[[READ_WRITE:.*]] = fir.alloca !fir.array<20xi32> {bindc_name = "arr_read_write", uniq_name = "_QFcall_assumed_shape_and_size_arrayEarr_read_write"}
+!HOST: %[[SHAPE_READ_WRITE:.*]] = fir.shape %[[C20]] : (index) -> !fir.shape<1>
+!HOST: %[[READ_WRITE_DECL:.*]]:2 = hlfir.declare %[[READ_WRITE]](%[[SHAPE_READ_WRITE]]) {uniq_name = "_QFcall_assumed_shape_and_size_arrayEarr_read_write"} : (!fir.ref<!fir.array<20xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<20xi32>>, !fir.ref<!fir.array<20xi32>>)
+!HOST: %[[LB:.*]] = arith.constant 1 : index
+!HOST: %[[UB:.*]] = arith.constant 10 : index
+!HOST: %[[STEP:.*]] = arith.constant 1 : index
+!HOST: %[[SHAPE_VAL10:.*]] = arith.constant 10 : index
+!HOST: %[[SHAPE:.*]] = fir.shape %[[SHAPE_VAL10]] : (index) -> !fir.shape<1>
+!HOST: %[[READ_WRITE_DESIGNATE:.*]] = hlfir.designate %[[READ_WRITE_DECL]]#0 (%[[LB]]:%[[UB]]:%[[STEP]]) shape %[[SHAPE]] : (!fir.ref<!fir.array<20xi32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>>
+!HOST: %[[READ_WRITE_EMBOX:.*]] = fir.embox %[[READ_WRITE_DESIGNATE]](%[[SHAPE]]) : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<10xi32>>
+!HOST: %[[ARG0:.*]] = fir.convert %[[READ_WRITE_EMBOX]] : (!fir.box<!fir.array<10xi32>>) -> !fir.box<!fir.array<?xi32>>
+!HOST: fir.call @_QMassumed_array_routinesPassumed_shape_array(%[[ARG0]]) fastmath<contract> : (!fir.box<!fir.array<?xi32>>) -> ()
+!HOST: %[[LB:.*]] = arith.constant 10 : index
+!HOST: %[[UB:.*]] = arith.constant 20 : index
+!HOST: %[[STEP:.*]] = arith.constant 1 : index
+!HOST: %[[SHAPE_VAL11:.*]] = arith.constant 11 : index
+!HOST: %[[SHAPE:.*]] = fir.shape %[[SHAPE_VAL11]] : (index) -> !fir.shape<1>
+!HOST: %[[READ_WRITE_EMBOX:.*]] = hlfir.designate %[[READ_WRITE_DECL]]#0 (%[[LB]]:%[[UB]]:%[[STEP]]) shape %[[SHAPE]] : (!fir.ref<!fir.array<20xi32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<11xi32>>
+!HOST: %[[ARG1:.*]] = fir.convert %[[READ_WRITE_EMBOX]] : (!fir.ref<!fir.array<11xi32>>) -> !fir.ref<!fir.array<?xi32>>
+!HOST: fir.call @_QMassumed_array_routinesPassumed_size_array(%[[ARG1]]) fastmath<contract> : (!fir.ref<!fir.array<?xi32>>) -> ()
+!HOST: return
+!HOST:}
+
+subroutine call_assumed_shape_and_size_array
+ use assumed_array_routines
+ integer :: arr_read_write(20)
+ call assumed_shape_array(arr_read_write(1:10))
+ call assumed_size_array(arr_read_write(10:20))
+end subroutine call_assumed_shape_and_size_array
|
This is a copy of the test in flang/test/Lower/OpenMP/FIR/array-bounds.f90 The device test is crashing in the Early Outlining pass. Since this pass is going to be removed, will wait before the device part is updated.
2c4b2e1
to
3eb0ffe
Compare
For ease of review, split this into three commits:
|
This is the unfortunate part about that pass I think, at least from my experience so far, any new operations that are required for later lowering or for keeping consistency in the kernel related IR/map operations needs to be cloned over, or you can get verification errors at the end of the pass/lose information needed for later lowering. Doesn't really mesh well with the idea of integrating new MLIR dialects or operations easily sadly. Although, perhaps there's a way around this problem I did not consider. But it will be the hlfir.declare it needs taught to clone and remap to a block argument in this case or to completely elide and have directed to a block argument. I did not get a chance to test the device flow with HLFIR yet sadly, if the pass ends up staying around I can look into the device failure and check any other HLFIR related issues we currently have with the pass and update it and just generally maintain it as neccessary. But otherwise for now moving it and switching it to host only LGTM. |
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.
This LGTM, I'd love to keep the device test + command in the code inactive with a TODO, so updating it doesn't get forgotten by the way side, but I understand if that's a little messy and you'd rather not. I've added updating it to my TODO list whenever the outlining pass's fate has been decided.
This is a copy of the test in flang/test/Lower/OpenMP/FIR/array-bounds.f90 The device test is crashing in the Early Outlining pass. Since this pass is going to be removed, will wait before the device part is updated.