Skip to content

[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

Merged
merged 3 commits into from
Oct 3, 2023

Conversation

kiranchandramohan
Copy link
Contributor

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.

@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir flang:openmp labels Sep 25, 2023
@llvmbot
Copy link
Member

llvmbot commented Sep 25, 2023

@llvm/pr-subscribers-flang-fir-hlfir

@llvm/pr-subscribers-flang-openmp

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/67328.diff

1 Files Affected:

  • (added) flang/test/Lower/OpenMP/array-bounds.f90 (+154)
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.
@kiranchandramohan
Copy link
Contributor Author

For ease of review, split this into three commits:

  1. Copies the test
  2. Removes device test (since it is crashing in the outline pass and also the pass is scheduled for removal).
  3. Makes changes in test for HLFIR.

@agozillon
Copy link
Contributor

agozillon commented Sep 26, 2023

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.

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.

Copy link
Contributor

@agozillon agozillon left a 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.

@kiranchandramohan kiranchandramohan merged commit 54be730 into llvm:main Oct 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:fir-hlfir flang:openmp flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants