blob: 0725f50c17343fdf18d1a525ce7c3bd513efc206 [file] [edit]
! RUN: bbc -emit-hlfir --wrap-unstructured-constructs-in-execute-region %s -o - | FileCheck %s
! An unstructured IF inside a DO is self-contained, so isUnstructured does
! not propagate to the DO. The DO lowers as fir.do_loop and the IF's blocks
! are wrapped in an scf.execute_region inside its body.
subroutine wrapped_unstructured(n, a)
integer :: n, i
real :: a(n)
do i = 1, n
if (a(i) > 0.0) stop
a(i) = real(i)
end do
end subroutine
! CHECK-LABEL: func.func @_QPwrapped_unstructured
! CHECK: fir.do_loop
! CHECK: scf.execute_region no_inline {
! CHECK: cf.cond_br
! CHECK: fir.call @_FortranAStopStatement
! CHECK: fir.unreachable
! CHECK: scf.yield
! CHECK: }
! Unstructured DO with a GOTO targeting a label outside the construct that
! is reachable on a path distinct from the loop's natural exit: not wrapped.
! The GOTO jumps past the post-loop store directly to label 99, so the
! loop body has an outgoing edge that is neither another loop block nor the
! construct exit. The wrap pass bails out and the CFG stays flat.
subroutine not_wrapped_outer_label(n, a)
integer :: n, i
real :: a(n)
do i = 1, n
if (a(i) > 0.0) goto 99
a(i) = real(i)
end do
a(1) = -1.0
99 continue
end subroutine
! CHECK-LABEL: func.func @_QPnot_wrapped_outer_label
! CHECK-NOT: scf.execute_region
! CHECK: cf.cond_br
! CHECK: return
! Multiway branch (computed GO TO) inside a DO with a target that escapes
! the loop: not wrapped. Only the first target of a computed GO TO used to
! be considered by the wrappability check, so an escaping non-first label
! (99 below) was invisible and the DO was wrapped; the resulting
! scf.execute_region contained a fir.select whose successor lived outside
! the region, tripping MLIR's op verifier.
subroutine not_wrapped_computed_goto_exit(sel, a)
integer :: sel, a, i
do i = 1, 10
go to (10, 99), sel
10 end do
a = -1
99 continue
end subroutine
! CHECK-LABEL: func.func @_QPnot_wrapped_computed_goto_exit
! CHECK-NOT: scf.execute_region
! CHECK: fir.select
! CHECK: return
! Same shape via an arithmetic IF. Arithmetic IF has three label targets;
! only the first was recorded on the source Evaluation, so a non-first
! escape target (99) was again invisible to the wrappability check.
subroutine not_wrapped_arithmetic_if_exit(x, a)
integer :: a, i
real :: x
do i = 1, 10
if (x) 10, 10, 99
10 end do
a = -1
99 continue
end subroutine
! CHECK-LABEL: func.func @_QPnot_wrapped_arithmetic_if_exit
! CHECK-NOT: scf.execute_region
! CHECK: cf.cond_br
! CHECK: return
! Assigned GO TO with no explicit label list inside a DO: not wrapped.
! The set of runtime targets for `go to k` is the union of every label
! ASSIGN'd to k, but analyzeBranches only sees ASSIGNs earlier than the
! goto in program order. Here the escaping label 99 is added by a later
! ASSIGN and would be invisible to the escape check, so wrappability bails
! out for any listless assigned GO TO regardless of the currently recorded
! targets.
subroutine not_wrapped_assigned_goto_no_list(a)
integer :: a, i, k
assign 10 to k
do i = 1, 10
go to k
assign 99 to k
10 end do
a = -1
99 continue
end subroutine
! CHECK-LABEL: func.func @_QPnot_wrapped_assigned_goto_no_list
! CHECK-NOT: scf.execute_region
! CHECK: return
! A plain, structured DO with no early exits: lowered as fir.do_loop,
! never reaches the wrap path (the loop is not unstructured at all).
subroutine structured(n, a)
integer :: n, i
real :: a(n)
do i = 1, n
a(i) = real(i)
end do
end subroutine
! CHECK-LABEL: func.func @_QPstructured
! CHECK-NOT: scf.execute_region
! CHECK: fir.do_loop
! CHECK: return
! Nested DOs whose only unstructuredness comes from a self-contained IF.
! Both DOs lower as fir.do_loop; only the IF is wrapped in scf.execute_region
! at the innermost level.
subroutine outer_structured_inner_wrapped(n, a)
integer :: n, i, j
real :: a(n)
do i = 1, n
do j = 1, n
if (a(j) > 0.0) stop
a(j) = real(i + j)
end do
end do
end subroutine
! CHECK-LABEL: func.func @_QPouter_structured_inner_wrapped
! CHECK: fir.do_loop
! CHECK: fir.do_loop
! CHECK: scf.execute_region no_inline {
! CHECK: cf.cond_br
! CHECK: fir.call @_FortranAStopStatement
! CHECK: fir.unreachable
! CHECK: scf.yield
! CHECK: }
! Structured outer DO containing an unstructured inner DO (the inner DO has
! an EXIT that targets its own construct exit). isUnstructured does not
! propagate from the inner DO to the outer DO, so the outer lowers as
! fir.do_loop. The inner DO's blocks would otherwise have nowhere to live
! inside the outer's single-block region, so the pre-wrap path creates an
! scf.execute_region around the inner DO's CFG.
subroutine outer_fir_do_loop_inner_unstructured_do(n, a)
integer :: n, i, j
real :: a(n)
do i = 1, n
do j = 1, n
if (a(j) > 0.0) exit
end do
end do
end subroutine
! CHECK-LABEL: func.func @_QPouter_fir_do_loop_inner_unstructured_do
! CHECK: fir.do_loop
! CHECK: scf.execute_region no_inline {
! CHECK: cf.br
! CHECK: cf.cond_br
! CHECK: cf.cond_br
! CHECK: scf.yield
! CHECK: }