Files
clang-p2996/flang/test/Lower/do_loop_unstructured.f90
jeanPerier f35f863a88 [flang][NFC] Use hlfir=false and flang-deprecated-no-hlfir in legacy tests (#71957)
Patch 2/3 of the transition step 1 described in

https://discourse.llvm.org/t/rfc-enabling-the-hlfir-lowering-by-default/72778/7.

All the modified tests are still here since coverage for the direct
lowering to FIR was still needed while it was default. Some already have
an HLFIR version, some have not and will need to be ported in step 2
described in the RFC.

Note that another 147 lit tests use -emit-fir/-emit-llvm outputs but do
not need a flag since the HLFIR/no HLFIR output is the same for what is
being tested.
2023-11-13 09:14:05 +01:00

229 lines
12 KiB
Fortran

! RUN: bbc -emit-fir -hlfir=false -o - %s | FileCheck %s
! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -o - %s | FileCheck %s
! Tests for unstructured loops.
! Test a simple unstructured loop. Test for the existence of,
! -> The initialization of the trip-count and loop-variable
! -> The branch to the body or the exit inside the header
! -> The increment of the trip-count and the loop-variable inside the body
subroutine simple_unstructured()
integer :: i
do i=1,100
goto 404
404 continue
end do
end subroutine
! CHECK-LABEL: simple_unstructured
! CHECK: %[[TRIP_VAR_REF:.*]] = fir.alloca i32
! CHECK: %[[LOOP_VAR_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_unstructuredEi"}
! CHECK: %[[ONE:.*]] = arith.constant 1 : i32
! CHECK: %[[HUNDRED:.*]] = arith.constant 100 : i32
! CHECK: %[[STEP_ONE:.*]] = arith.constant 1 : i32
! CHECK: %[[TMP1:.*]] = arith.subi %[[HUNDRED]], %[[ONE]] : i32
! CHECK: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[STEP_ONE]] : i32
! CHECK: %[[TRIP_COUNT:.*]] = arith.divsi %[[TMP2]], %[[STEP_ONE]] : i32
! CHECK: fir.store %[[TRIP_COUNT]] to %[[TRIP_VAR_REF]] : !fir.ref<i32>
! CHECK: fir.store %[[ONE]] to %[[LOOP_VAR_REF]] : !fir.ref<i32>
! CHECK: cf.br ^[[HEADER:.*]]
! CHECK: ^[[HEADER]]:
! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref<i32>
! CHECK: %[[ZERO:.*]] = arith.constant 0 : i32
! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32
! CHECK: cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]]
! CHECK: ^[[BODY]]:
! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref<i32>
! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32
! CHECK: %[[TRIP_VAR_NEXT:.*]] = arith.subi %[[TRIP_VAR]], %[[ONE_1]] : i32
! CHECK: fir.store %[[TRIP_VAR_NEXT]] to %[[TRIP_VAR_REF]] : !fir.ref<i32>
! CHECK: %[[LOOP_VAR:.*]] = fir.load %[[LOOP_VAR_REF]] : !fir.ref<i32>
! CHECK: %[[STEP_ONE_2:.*]] = arith.constant 1 : i32
! CHECK: %[[LOOP_VAR_NEXT:.*]] = arith.addi %[[LOOP_VAR]], %[[STEP_ONE_2]] : i32
! CHECK: fir.store %[[LOOP_VAR_NEXT]] to %[[LOOP_VAR_REF]] : !fir.ref<i32>
! CHECK: cf.br ^[[HEADER]]
! CHECK: ^[[EXIT]]:
! CHECK: return
! Test an unstructured loop with a step. Mostly similar to the previous one.
! Only difference is a non-unit step.
subroutine simple_unstructured_with_step()
integer :: i
do i=1,100,2
goto 404
404 continue
end do
end subroutine
! CHECK-LABEL: simple_unstructured_with_step
! CHECK: %[[TRIP_VAR_REF:.*]] = fir.alloca i32
! CHECK: %[[LOOP_VAR_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_unstructured_with_stepEi"}
! CHECK: %[[ONE:.*]] = arith.constant 1 : i32
! CHECK: %[[HUNDRED:.*]] = arith.constant 100 : i32
! CHECK: %[[STEP:.*]] = arith.constant 2 : i32
! CHECK: %[[TMP1:.*]] = arith.subi %[[HUNDRED]], %[[ONE]] : i32
! CHECK: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[STEP]] : i32
! CHECK: %[[TRIP_COUNT:.*]] = arith.divsi %[[TMP2]], %[[STEP]] : i32
! CHECK: fir.store %[[TRIP_COUNT]] to %[[TRIP_VAR_REF]] : !fir.ref<i32>
! CHECK: fir.store %[[ONE]] to %[[LOOP_VAR_REF]] : !fir.ref<i32>
! CHECK: cf.br ^[[HEADER:.*]]
! CHECK: ^[[HEADER]]:
! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref<i32>
! CHECK: %[[ZERO:.*]] = arith.constant 0 : i32
! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32
! CHECK: cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]]
! CHECK: ^[[BODY]]:
! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref<i32>
! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32
! CHECK: %[[TRIP_VAR_NEXT:.*]] = arith.subi %[[TRIP_VAR]], %[[ONE_1]] : i32
! CHECK: fir.store %[[TRIP_VAR_NEXT]] to %[[TRIP_VAR_REF]] : !fir.ref<i32>
! CHECK: %[[LOOP_VAR:.*]] = fir.load %[[LOOP_VAR_REF]] : !fir.ref<i32>
! CHECK: %[[STEP_2:.*]] = arith.constant 2 : i32
! CHECK: %[[LOOP_VAR_NEXT:.*]] = arith.addi %[[LOOP_VAR]], %[[STEP_2]] : i32
! CHECK: fir.store %[[LOOP_VAR_NEXT]] to %[[LOOP_VAR_REF]] : !fir.ref<i32>
! CHECK: cf.br ^[[HEADER]]
! CHECK: ^[[EXIT]]:
! CHECK: return
! Test a three nested unstructured loop. Three nesting is the basic case where
! we have loops that are neither innermost or outermost.
subroutine nested_unstructured()
integer :: i, j, k
do i=1,100
do j=1,200
do k=1,300
goto 404
404 continue
end do
end do
end do
end subroutine
! CHECK-LABEL: nested_unstructured
! CHECK: %[[TRIP_VAR_K_REF:.*]] = fir.alloca i32
! CHECK: %[[TRIP_VAR_J_REF:.*]] = fir.alloca i32
! CHECK: %[[TRIP_VAR_I_REF:.*]] = fir.alloca i32
! CHECK: %[[LOOP_VAR_I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFnested_unstructuredEi"}
! CHECK: %[[LOOP_VAR_J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFnested_unstructuredEj"}
! CHECK: %[[LOOP_VAR_K_REF:.*]] = fir.alloca i32 {bindc_name = "k", uniq_name = "_QFnested_unstructuredEk"}
! CHECK: %[[I_START:.*]] = arith.constant 1 : i32
! CHECK: %[[I_END:.*]] = arith.constant 100 : i32
! CHECK: %[[I_STEP:.*]] = arith.constant 1 : i32
! CHECK: %[[TMP1:.*]] = arith.subi %[[I_END]], %[[I_START]] : i32
! CHECK: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[I_STEP]] : i32
! CHECK: %[[TRIP_COUNT_I:.*]] = arith.divsi %[[TMP2]], %[[I_STEP]] : i32
! CHECK: fir.store %[[TRIP_COUNT_I]] to %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: fir.store %[[I_START]] to %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: cf.br ^[[HEADER_I:.*]]
! CHECK: ^[[HEADER_I]]:
! CHECK: %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: %[[ZERO_1:.*]] = arith.constant 0 : i32
! CHECK: %[[COND_I:.*]] = arith.cmpi sgt, %[[TRIP_VAR_I]], %[[ZERO_1]] : i32
! CHECK: cf.cond_br %[[COND_I]], ^[[BODY_I:.*]], ^[[EXIT_I:.*]]
! CHECK: ^[[BODY_I]]:
! CHECK: %[[J_START:.*]] = arith.constant 1 : i32
! CHECK: %[[J_END:.*]] = arith.constant 200 : i32
! CHECK: %[[J_STEP:.*]] = arith.constant 1 : i32
! CHECK: %[[TMP3:.*]] = arith.subi %[[J_END]], %[[J_START]] : i32
! CHECK: %[[TMP4:.*]] = arith.addi %[[TMP3]], %[[J_STEP]] : i32
! CHECK: %[[TRIP_COUNT_J:.*]] = arith.divsi %[[TMP4]], %[[J_STEP]] : i32
! CHECK: fir.store %[[TRIP_COUNT_J]] to %[[TRIP_VAR_J_REF]] : !fir.ref<i32>
! CHECK: fir.store %[[J_START]] to %[[LOOP_VAR_J_REF]] : !fir.ref<i32>
! CHECK: cf.br ^[[HEADER_J:.*]]
! CHECK: ^[[HEADER_J]]:
! CHECK: %[[TRIP_VAR_J:.*]] = fir.load %[[TRIP_VAR_J_REF]] : !fir.ref<i32>
! CHECK: %[[ZERO_2:.*]] = arith.constant 0 : i32
! CHECK: %[[COND_J:.*]] = arith.cmpi sgt, %[[TRIP_VAR_J]], %[[ZERO_2]] : i32
! CHECK: cf.cond_br %[[COND_J]], ^[[BODY_J:.*]], ^[[EXIT_J:.*]]
! CHECK: ^[[BODY_J]]:
! CHECK: %[[K_START:.*]] = arith.constant 1 : i32
! CHECK: %[[K_END:.*]] = arith.constant 300 : i32
! CHECK: %[[K_STEP:.*]] = arith.constant 1 : i32
! CHECK: %[[TMP3:.*]] = arith.subi %[[K_END]], %[[K_START]] : i32
! CHECK: %[[TMP4:.*]] = arith.addi %[[TMP3]], %[[K_STEP]] : i32
! CHECK: %[[TRIP_COUNT_K:.*]] = arith.divsi %[[TMP4]], %[[K_STEP]] : i32
! CHECK: fir.store %[[TRIP_COUNT_K]] to %[[TRIP_VAR_K_REF]] : !fir.ref<i32>
! CHECK: fir.store %[[K_START]] to %[[LOOP_VAR_K_REF]] : !fir.ref<i32>
! CHECK: cf.br ^[[HEADER_K:.*]]
! CHECK: ^[[HEADER_K]]:
! CHECK: %[[TRIP_VAR_K:.*]] = fir.load %[[TRIP_VAR_K_REF]] : !fir.ref<i32>
! CHECK: %[[ZERO_2:.*]] = arith.constant 0 : i32
! CHECK: %[[COND_K:.*]] = arith.cmpi sgt, %[[TRIP_VAR_K]], %[[ZERO_2]] : i32
! CHECK: cf.cond_br %[[COND_K]], ^[[BODY_K:.*]], ^[[EXIT_K:.*]]
! CHECK: ^[[BODY_K]]:
! CHECK: %[[TRIP_VAR_K:.*]] = fir.load %[[TRIP_VAR_K_REF]] : !fir.ref<i32>
! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32
! CHECK: %[[TRIP_VAR_K_NEXT:.*]] = arith.subi %[[TRIP_VAR_K]], %[[ONE_1]] : i32
! CHECK: fir.store %[[TRIP_VAR_K_NEXT]] to %[[TRIP_VAR_K_REF]] : !fir.ref<i32>
! CHECK: %[[LOOP_VAR_K:.*]] = fir.load %[[LOOP_VAR_K_REF]] : !fir.ref<i32>
! CHECK: %[[K_STEP_2:.*]] = arith.constant 1 : i32
! CHECK: %[[LOOP_VAR_K_NEXT:.*]] = arith.addi %[[LOOP_VAR_K]], %[[K_STEP_2]] : i32
! CHECK: fir.store %[[LOOP_VAR_K_NEXT]] to %[[LOOP_VAR_K_REF]] : !fir.ref<i32>
! CHECK: cf.br ^[[HEADER_K]]
! CHECK: ^[[EXIT_K]]:
! CHECK: %[[TRIP_VAR_J:.*]] = fir.load %[[TRIP_VAR_J_REF]] : !fir.ref<i32>
! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32
! CHECK: %[[TRIP_VAR_J_NEXT:.*]] = arith.subi %[[TRIP_VAR_J]], %[[ONE_1]] : i32
! CHECK: fir.store %[[TRIP_VAR_J_NEXT]] to %[[TRIP_VAR_J_REF]] : !fir.ref<i32>
! CHECK: %[[LOOP_VAR_J:.*]] = fir.load %[[LOOP_VAR_J_REF]] : !fir.ref<i32>
! CHECK: %[[J_STEP_2:.*]] = arith.constant 1 : i32
! CHECK: %[[LOOP_VAR_J_NEXT:.*]] = arith.addi %[[LOOP_VAR_J]], %[[J_STEP_2]] : i32
! CHECK: fir.store %[[LOOP_VAR_J_NEXT]] to %[[LOOP_VAR_J_REF]] : !fir.ref<i32>
! CHECK: cf.br ^[[HEADER_J]]
! CHECK: ^[[EXIT_J]]:
! CHECK: %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32
! CHECK: %[[TRIP_VAR_I_NEXT:.*]] = arith.subi %[[TRIP_VAR_I]], %[[ONE_1]] : i32
! CHECK: fir.store %[[TRIP_VAR_I_NEXT]] to %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: %[[LOOP_VAR_I:.*]] = fir.load %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: %[[I_STEP_2:.*]] = arith.constant 1 : i32
! CHECK: %[[LOOP_VAR_I_NEXT:.*]] = arith.addi %[[LOOP_VAR_I]], %[[I_STEP_2]] : i32
! CHECK: fir.store %[[LOOP_VAR_I_NEXT]] to %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: cf.br ^[[HEADER_I]]
! CHECK: ^[[EXIT_I]]:
! CHECK: return
! Test the existence of a structured loop inside an unstructured loop.
! Only minimal checks are inserted for the structured loop.
subroutine nested_structured_in_unstructured()
integer :: i, j
do i=1,100
do j=1,100
end do
goto 404
404 continue
end do
end subroutine
! CHECK-LABEL: nested_structured_in_unstructured
! CHECK: %[[TRIP_VAR_I_REF:.*]] = fir.alloca i32
! CHECK: %[[LOOP_VAR_I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFnested_structured_in_unstructuredEi"}
! CHECK: %[[LOOP_VAR_J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFnested_structured_in_unstructuredEj"}
! CHECK: %[[I_START:.*]] = arith.constant 1 : i32
! CHECK: %[[I_END:.*]] = arith.constant 100 : i32
! CHECK: %[[I_STEP:.*]] = arith.constant 1 : i32
! CHECK: %[[TMP1:.*]] = arith.subi %[[I_END]], %[[I_START]] : i32
! CHECK: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[I_STEP]] : i32
! CHECK: %[[TRIP_COUNT:.*]] = arith.divsi %[[TMP2]], %[[I_STEP]] : i32
! CHECK: fir.store %[[TRIP_COUNT]] to %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: fir.store %[[I_START]] to %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: cf.br ^[[HEADER:.*]]
! CHECK: ^[[HEADER]]:
! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: %[[ZERO:.*]] = arith.constant 0 : i32
! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32
! CHECK: cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]]
! CHECK: ^[[BODY]]:
! CHECK: %{{.*}} = fir.do_loop %[[J_INDEX:[^ ]*]] =
! CHECK-SAME: %{{.*}} to %{{.*}} step %{{[^ ]*}}
! CHECK-SAME: iter_args(%[[J_IV:.*]] = %{{.*}}) -> (index, i32) {
! CHECK: fir.store %[[J_IV]] to %[[LOOP_VAR_J_REF]] : !fir.ref<i32>
! CHECK: }
! CHECK: %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: %[[C1_3:.*]] = arith.constant 1 : i32
! CHECK: %[[TRIP_VAR_I_NEXT:.*]] = arith.subi %[[TRIP_VAR_I]], %[[C1_3]] : i32
! CHECK: fir.store %[[TRIP_VAR_I_NEXT]] to %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: %[[LOOP_VAR_I:.*]] = fir.load %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: %[[I_STEP_2:.*]] = arith.constant 1 : i32
! CHECK: %[[LOOP_VAR_I_NEXT:.*]] = arith.addi %[[LOOP_VAR_I]], %[[I_STEP_2]] : i32
! CHECK: fir.store %[[LOOP_VAR_I_NEXT]] to %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
! CHECK: cf.br ^[[HEADER]]
! CHECK: ^[[EXIT]]:
! CHECK: return