diff --git a/flang/test/Transforms/loop-versioning.fir b/flang/test/Transforms/loop-versioning.fir --- a/flang/test/Transforms/loop-versioning.fir +++ b/flang/test/Transforms/loop-versioning.fir @@ -112,4 +112,171 @@ // CHECK: %[[COORD:.*]] = fir.coordinate_of %[[ARG0]], {{.*}} // CHECK: %{{.*}} = fir.load %[[COORD]] +// ----- + +// RUN: fir-opt --loop-versioning %s | FileCheck %s + +// Check that "no result" from a versioned loop works correctly +// This code was the basis for this, but `read` is replaced with a function called Func +// subroutine test3(x, y) +// integer :: y(:) +// integer :: x(:) +// read(*,*) x(y) +// end subroutine + + func.func @test3(%arg0: !fir.box> {fir.bindc_name = "x"}, %arg1: !fir.box> {fir.bindc_name = "y"}) { + %c0 = arith.constant 0 : index + %3:3 = fir.box_dims %arg1, %c0 : (!fir.box>, index) -> (index, index, index) + %c1 = arith.constant 1 : index + %4 = fir.slice %c1, %3#1, %c1 : (index, index, index) -> !fir.slice<1> + %c1_0 = arith.constant 1 : index + %c0_1 = arith.constant 0 : index + %5 = arith.subi %3#1, %c1_0 : index + fir.do_loop %arg2 = %c0_1 to %5 step %c1_0 { + %7 = fir.coordinate_of %arg1, %arg2 : (!fir.box>, index) -> !fir.ref + %8 = fir.load %7 : !fir.ref + %9 = fir.convert %8 : (i32) -> index + %10 = fir.array_coor %arg0 [%4] %9 : (!fir.box>, !fir.slice<1>, index) -> !fir.ref + %12 = fir.call @Func(%10) fastmath : (!fir.ref) -> i1 + } + return + } + func.func private @Func(!fir.ref, !fir.ref) -> i1 + +// CHECK-LABEL: func.func @test3( +// CHECK-SAME: %[[X:.*]]: !fir.box> {{.*}}, +// CHECK-SAME: %[[Y:.*]]: !fir.box> {{.*}}) { +// Look for arith.subi to locate the correct part of code. +// CHECK: {{.*}} arith.subi {{.*}} +// CHECK: %[[ZERO:.*]] = arith.constant 0 : index +// CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[Y]], %[[ZERO]] +// CHECK: %[[FOUR:.*]] = arith.constant 4 : index +// CHECK: %[[COMP:.*]] = arith.cmpi eq, %[[DIMS]]#2, %[[FOUR]] : index +// CHECK: fir.if %[[COMP]] { +// CHECK: %[[CONV:.*]] = fir.convert %[[Y]] : {{.*}} +// CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[CONV]] : {{.*}} +// CHECK: fir.do_loop %[[INDEX:.*]] = {{.*}} +// CHECK: %[[IND_PLUS_1:.*]] = arith.addi %{{.*}}, %[[INDEX]] +// CHECK: %[[YADDR:.*]] = fir.coordinate_of %[[BOX_ADDR]], %[[IND_PLUS_1]] +// CHECK: %[[YINT:.*]] = fir.load %[[YADDR]] : {{.*}} +// CHECK: %[[YINDEX:.*]] = fir.convert %[[YINT]] +// CHECK: %[[XADDR:.*]] = fir.array_coor %[[X]] [%{{.*}}] %[[YINDEX]] +// CHECK: fir.call @Func(%[[XADDR]]) +// CHECK-NEXT: } +// CHECK-NEXT: } else { +// CHECK: fir.do_loop %[[INDEX2:.*]] = {{.*}} +// CHECK: %[[YADDR2:.*]] = fir.coordinate_of %[[Y]], %[[INDEX2]] +// CHECK: %[[YINT2:.*]] = fir.load %[[YADDR2]] : {{.*}} +// CHECK: %[[YINDEX2:.*]] = fir.convert %[[YINT2]] +// CHECK: %[[XADDR2:.*]] = fir.array_coor %[[X]] [%{{.*}}] %[[YINDEX2]] +// CHECK: fir.call @Func(%[[XADDR2]]) +// CHECK-NEXT: } + + +// ---- + +// Test array initialization. +// +// This code has been modified to simplify it - removing the realloc generated to grow +// the constructed +//subroutine test4(a, b, n1, m1) +// real :: a(:) +// real :: b(:,:) +// +// a = [ ((b(i,j), j=1,n1,m1), i=1,n1,m1) ] +//end subroutine test4 + + func.func @test4(%arg0: !fir.box> {fir.bindc_name = "a"}, %arg1: !fir.box> {fir.bindc_name = "b"}, %arg2: !fir.ref {fir.bindc_name = "n1"}, %arg3: !fir.ref {fir.bindc_name = "m1"}) { + %0 = fir.alloca index {bindc_name = ".buff.pos"} + %1 = fir.alloca index {bindc_name = ".buff.size"} + %c0 = arith.constant 0 : index + %2:3 = fir.box_dims %arg0, %c0 : (!fir.box>, index) -> (index, index, index) + %3 = fir.array_load %arg0 : (!fir.box>) -> !fir.array + %c0_0 = arith.constant 0 : index + fir.store %c0_0 to %0 : !fir.ref + %c32 = arith.constant 32 : index + %4 = fir.allocmem f32, %c32 + fir.store %c32 to %1 : !fir.ref + %c1_i64 = arith.constant 1 : i64 + %5 = fir.convert %c1_i64 : (i64) -> index + %6 = fir.load %arg2 : !fir.ref + %7 = fir.convert %6 : (i32) -> i64 + %8 = fir.convert %7 : (i64) -> index + %9 = fir.load %arg3 : !fir.ref + %10 = fir.convert %9 : (i32) -> i64 + %11 = fir.convert %10 : (i64) -> index + %12 = fir.do_loop %arg4 = %5 to %8 step %11 iter_args(%arg5 = %4) -> (!fir.heap) { + %c1_i64_2 = arith.constant 1 : i64 + %19 = fir.convert %c1_i64_2 : (i64) -> index + %20 = fir.load %arg2 : !fir.ref + %21 = fir.convert %20 : (i32) -> i64 + %22 = fir.convert %21 : (i64) -> index + %23 = fir.load %arg3 : !fir.ref + %24 = fir.convert %23 : (i32) -> i64 + %25 = fir.convert %24 : (i64) -> index + %26 = fir.do_loop %arg6 = %19 to %22 step %25 iter_args(%arg7 = %arg5) -> (!fir.heap) { + %27 = fir.convert %arg4 : (index) -> i32 + %28 = fir.convert %27 : (i32) -> i64 + %c1_i64_3 = arith.constant 1 : i64 + %29 = arith.subi %28, %c1_i64_3 : i64 + %30 = fir.convert %arg6 : (index) -> i32 + %31 = fir.convert %30 : (i32) -> i64 + %c1_i64_4 = arith.constant 1 : i64 + %32 = arith.subi %31, %c1_i64_4 : i64 + %33 = fir.coordinate_of %arg1, %29, %32 : (!fir.box>, i64, i64) -> !fir.ref + %34 = fir.load %33 : !fir.ref + %c1_5 = arith.constant 1 : index + %35 = fir.zero_bits !fir.ref> + %36 = fir.coordinate_of %35, %c1_5 : (!fir.ref>, index) -> !fir.ref + %37 = fir.convert %36 : (!fir.ref) -> index + %38 = fir.load %0 : !fir.ref + %39 = fir.load %1 : !fir.ref + %c1_6 = arith.constant 1 : index + %40 = arith.addi %38, %c1_6 : index + + fir.store %40 to %0 : !fir.ref + fir.result %arg7 : !fir.heap + } + fir.result %26 : !fir.heap + } + %13 = fir.convert %12 : (!fir.heap) -> !fir.heap> + %14 = fir.load %0 : !fir.ref + %15 = fir.shape %14 : (index) -> !fir.shape<1> + %16 = fir.array_load %13(%15) : (!fir.heap>, !fir.shape<1>) -> !fir.array + %c1 = arith.constant 1 : index + %c0_1 = arith.constant 0 : index + %17 = arith.subi %2#1, %c1 : index + %18 = fir.do_loop %arg4 = %c0_1 to %17 step %c1 unordered iter_args(%arg5 = %3) -> (!fir.array) { + %19 = fir.array_fetch %16, %arg4 : (!fir.array, index) -> f32 + %20 = fir.array_update %arg5, %19, %arg4 : (!fir.array, f32, index) -> !fir.array + fir.result %20 : !fir.array + } + fir.array_merge_store %3, %18 to %arg0 : !fir.array, !fir.array, !fir.box> + fir.freemem %13 : !fir.heap> + return + } + +// CHECK: func.func @test4( +// CHECK-SAME: %[[A:.*]]: !fir.box> +// CHECK-SAME: %[[B:.*]]: !fir.box> +// CHECK-SAME: %[[N1:.*]]: !fir.ref {{.*}}, +// CHECK-SAME: %[[M1:.*]]: !fir.ref {{.*}}) { +// CHECK: fir.do_loop +// CHECL: %[[FOUR:.*]] = arith.constant 4 : index +// CHECK: %[[COMP:.*]] = arith.cmpi {{.*}}, %[[FOUR]] +// CHECK: fir.if %[[COMP]] -> {{.*}} { +// CHECK: %[[CONV:.*]] = fir.convert %[[B]] : +// CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[CONV]] +// CHECK: %[[RES:.*]] = fir.do_loop {{.*}} { +// CHECK: %[[ADDR:.*]] = fir.coordinate_of %[[BOX_ADDR]], %{{.*}} +// CHECK: %45 = fir.load %[[ADDR]] : !fir.ref +// CHECK: } +// CHECK: fir.result %[[RES]] : {{.*}} +// CHECK: } else { +// CHECK: %[[RES2:.*]] = fir.do_loop +// CHECK: %{{.*}} = fir.coordinate_of %[[B]], %{{.*}} +// CHECK: } +// CHECK: fir.result %[[RES2]] +// CHECK: } + } // End module