[flang-commits] [flang] d333b38 - [flang][NFC] Add tests for array-value-copy pass with array with pointers

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Mon Apr 4 01:45:55 PDT 2022


Author: Valentin Clement
Date: 2022-04-04T10:45:45+02:00
New Revision: d333b382701e9ba7c72dc893f3bf5f9a702879b5

URL: https://github.com/llvm/llvm-project/commit/d333b382701e9ba7c72dc893f3bf5f9a702879b5
DIFF: https://github.com/llvm/llvm-project/commit/d333b382701e9ba7c72dc893f3bf5f9a702879b5.diff

LOG: [flang][NFC] Add tests for array-value-copy pass with array with pointers

This patch adds tests for the array-value-copy pass with array assignment
involving Fortran pointers.

This patch is part of the upstreaming effort from fir-dev branch.

Reviewed By: schweitz

Differential Revision: https://reviews.llvm.org/D122878

Added: 
    flang/test/Fir/array-copies-pointers.fir

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/flang/test/Fir/array-copies-pointers.fir b/flang/test/Fir/array-copies-pointers.fir
new file mode 100644
index 0000000000000..8d93e303ca036
--- /dev/null
+++ b/flang/test/Fir/array-copies-pointers.fir
@@ -0,0 +1,170 @@
+// Test array-copy-value pass (copy elision) with array assignment
+// involving Fortran pointers. Focus in only on wether copy ellision
+// is made or not.
+// RUN: fir-opt %s --array-value-copy -split-input-file | FileCheck %s
+
+// Test `pointer(:) = array(:)`
+// TODO: array should have target attribute.
+// CHECK-LABEL: func @maybe_overlap
+// CHECK: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>
+// CHECK: fir.do_loop
+// CHECK: fir.do_loop
+// CHECK: fir.do_loop
+// CHECK: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>
+func @maybe_overlap(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>>) {
+  %c100 = arith.constant 100 : index
+  %c99 = arith.constant 99 : index
+  %c1 = arith.constant 1 : index
+  %c0 = arith.constant 0 : index
+  %0 = fir.alloca f32
+  %1 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
+  %3 = fir.array_load %arg1(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
+  %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %2) -> (!fir.array<100xf32>) {
+    %5 = fir.array_fetch %3, %arg2 : (!fir.array<100xf32>, index) -> f32
+    %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
+    fir.result %6 : !fir.array<100xf32>
+  }
+  fir.array_merge_store %2, %4 to %arg0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ptr<!fir.array<100xf32>>
+  return
+}
+
+// -----
+
+// Test `pointer(:) = pointer(:)`
+// CHECK-LABEL: func @no_overlap
+// CHECK-NOT: fir.allocmem
+// CHECK:     fir.do_loop
+// CHECK:       fir.array_coor
+// CHECK:       fir.array_coor
+// CHECK:       fir.store
+func @no_overlap(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>>) {
+  %c100 = arith.constant 100 : index
+  %c99 = arith.constant 99 : index
+  %c1 = arith.constant 1 : index
+  %c0 = arith.constant 0 : index
+  %0 = fir.alloca f32
+  %1 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
+  %3 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %2) -> (!fir.array<100xf32>) {
+    %4 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32
+    %5 = fir.array_update %arg3, %4, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
+    fir.result %5 : !fir.array<100xf32>
+  }
+  fir.array_merge_store %2, %3 to %arg0 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ptr<!fir.array<100xf32>>
+  return
+}
+
+// -----
+
+// Test `array(:) = pointer(:)`
+// TODO: array should have target attribute.
+// CHECK-LABEL: func @maybe_overlap_2
+// CHECK: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>
+// CHECK: fir.do_loop
+// CHECK: fir.do_loop
+// CHECK: fir.do_loop
+// CHECK: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>
+func @maybe_overlap_2(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ref<!fir.array<100xf32>>) {
+  %c100 = arith.constant 100 : index
+  %c99 = arith.constant 99 : index
+  %c1 = arith.constant 1 : index
+  %c0 = arith.constant 0 : index
+  %0 = fir.alloca f32
+  %1 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
+  %3 = fir.array_load %arg1(%1) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
+  %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<100xf32>) {
+    %5 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32
+    %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
+    fir.result %6 : !fir.array<100xf32>
+  }
+  fir.array_merge_store %3, %4 to %arg1 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ref<!fir.array<100xf32>>
+  return
+}
+
+// -----
+
+// Test `pointer1(:) = pointer2(:)`
+// CHECK-LABEL: func @maybe_overlap_3
+// CHECK: %[[ALLOC:.*]] = fir.allocmem !fir.array<100xf32>
+// CHECK: fir.do_loop
+// CHECK: fir.do_loop
+// CHECK: fir.do_loop
+// CHECK: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<100xf32>>
+func @maybe_overlap_3(%arg0: !fir.ptr<!fir.array<100xf32>>, %arg1: !fir.ptr<!fir.array<100xf32>>) {
+  %c100 = arith.constant 100 : index
+  %c99 = arith.constant 99 : index
+  %c1 = arith.constant 1 : index
+  %c0 = arith.constant 0 : index
+  %0 = fir.alloca f32
+  %1 = fir.shape %c100 : (index) -> !fir.shape<1>
+  %2 = fir.array_load %arg0(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
+  %3 = fir.array_load %arg1(%1) : (!fir.ptr<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
+  %4 = fir.do_loop %arg2 = %c0 to %c99 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<100xf32>) {
+    %5 = fir.array_fetch %2, %arg2 : (!fir.array<100xf32>, index) -> f32
+    %6 = fir.array_update %arg3, %5, %arg2 : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
+    fir.result %6 : !fir.array<100xf32>
+  }
+  fir.array_merge_store %3, %4 to %arg1 : !fir.array<100xf32>, !fir.array<100xf32>, !fir.ptr<!fir.array<100xf32>>
+  return
+}
+
+// -----
+
+// Test derived_target(:)%i = integer_pointer(:)
+// The integer pointer may be aliasing the derived target component.
+// CHECK-LABEL: func @derived_whose_component_may_be_aliased
+// CHECK: %[[ALLOC:.*]] = fir.allocmem !fir.array<4x!fir.type<some_type{i:i32}>>
+// CHECK-COUNT-3: fir.do_loop
+// CHECK: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<4x!fir.type<some_type{i:i32}>>>
+func @derived_whose_component_may_be_aliased(%arg0: !fir.box<!fir.array<4x!fir.type<some_type{i:i32}>>> {fir.target}, %arg1: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) {
+  %c4 = arith.constant 4 : index
+  %0 = fir.field_index i, !fir.type<some_type{i:i32}>
+  %c1 = arith.constant 1 : index
+  %1 = fir.slice %c1, %c4, %c1 path %0 : (index, index, index, !fir.field) -> !fir.slice<1>
+  %2 = fir.array_load %arg0 [%1] : (!fir.box<!fir.array<4x!fir.type<some_type{i:i32}>>>, !fir.slice<1>) -> !fir.array<4xi32>
+  %3 = fir.load %arg1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
+  %c0 = arith.constant 0 : index
+  %4:3 = fir.box_dims %3, %c0 : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, index) -> (index, index, index)
+  %5 = fir.shift %4#0 : (index) -> !fir.shift<1>
+  %6 = fir.array_load %3(%5) : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, !fir.shift<1>) -> !fir.array<?xi32>
+  %7 = arith.subi %c4, %c1 : index
+  %8 = fir.do_loop %arg2 = %c0 to %7 step %c1 unordered iter_args(%arg3 = %2) -> (!fir.array<4xi32>) {
+    %9 = fir.array_fetch %6, %arg2 : (!fir.array<?xi32>, index) -> i32
+    %10 = fir.array_update %arg3, %9, %arg2 : (!fir.array<4xi32>, i32, index) -> !fir.array<4xi32>
+    fir.result %10 : !fir.array<4xi32>
+  }
+  fir.array_merge_store %2, %8 to %arg0[%1] : !fir.array<4xi32>, !fir.array<4xi32>, !fir.box<!fir.array<4x!fir.type<some_type{i:i32}>>>, !fir.slice<1>
+  return
+}
+
+// -----
+
+// Test real_target = complex_target(:)%re
+// The real pointer may be aliasing the complex real part.
+// CHECK-LABEL: func @complex_real_aliasing
+// CHECK: %[[ALLOC:.*]] = fir.allocmem !fir.array<?xf32>
+// CHECK-COUNT-3: fir.do_loop
+// CHECK: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<?xf32>>
+func @complex_real_aliasing(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, %arg1: !fir.ref<!fir.array<4x!fir.complex<4>>> {fir.target}) {
+  %c4 = arith.constant 4 : index
+  %0 = fir.load %arg0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+  %c0 = arith.constant 0 : index
+  %1:3 = fir.box_dims %0, %c0 : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
+  %2 = fir.shift %1#0 : (index) -> !fir.shift<1>
+  %3 = fir.array_load %0(%2) : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>) -> !fir.array<?xf32>
+  %c0_i32 = arith.constant 0 : i32
+  %4 = fir.shape %c4 : (index) -> !fir.shape<1>
+  %c1 = arith.constant 1 : index
+  %5 = fir.slice %c1, %c4, %c1 path %c0_i32 : (index, index, index, i32) -> !fir.slice<1>
+  %6 = fir.array_load %arg1(%4) [%5] : (!fir.ref<!fir.array<4x!fir.complex<4>>>, !fir.shape<1>, !fir.slice<1>) -> !fir.array<4xf32>
+  %7 = arith.subi %c4, %c1 : index
+  %8 = fir.do_loop %arg2 = %c0 to %7 step %c1 unordered iter_args(%arg3 = %3) -> (!fir.array<?xf32>) {
+    %9 = fir.array_fetch %6, %arg2 : (!fir.array<4xf32>, index) -> f32
+    %10 = fir.array_update %arg3, %9, %arg2 : (!fir.array<?xf32>, f32, index) -> !fir.array<?xf32>
+    fir.result %10 : !fir.array<?xf32>
+  }
+  fir.array_merge_store %3, %8 to %0 : !fir.array<?xf32>, !fir.array<?xf32>, !fir.box<!fir.ptr<!fir.array<?xf32>>>
+  return
+}


        


More information about the flang-commits mailing list