Hi Yuao,

this relates to conditional expressions/arguments, but not
directly to your patch(es).

* * *

Short version: I wonder whether resolve_conditional should - if
gfc_init_expr_flag is false - optimize expressions like:
  (one < 0 ? x_min > 0 : one /= 1)
to
  .false.
instead of
  '(.false. ? xmin > 0 : .false.)'

As the original expression is not a const expression according
to the spec, we cannot always optimize it - as for, e.g.,
  logical, parameter :: cond = ...

Here, permitting the expression would be invalid as not being
constant according to the spec (not all primaries are constant)¹,
even though the expression will always be .false.

[¹ cf. '10.1.12  Constant expression' in F2023]

* * *

I think relying on gfc_init_expr_flag should be sufficient.
However, the possible trickier part is to ensure that we don't
optimize too early, i.e. we still want to have all diagnostic
like .NIL. in arguments etc.

* * *

Background: Some diagnostic checks and optimizations are done
relatively early during the resolution phase, i.e., having a
constant instead of an expression helps.

However, as most code probably has either all constant or
all non-constant expressions, this case should be relatively
rare; thus:

→ This is not of high priority.

* * *

Background:

The issue came up when I was constructing some odder testcases
for the patch in the thread
  [PATCH] OpenMP: Handle 'nothing' with collapse as intervening code [PR120180]
  https://gcc.gnu.org/pipermail/gcc-patches/2025-October/697868.html

Here, the problem is for code like:

  !$omp ... collapse(2)
  do i = ...
    !$omp metadirective when(cond : simd )
    do j = ...

the loops collapses fine is there is no 'omp simd' and it is
invalid if there is. - That hinges on the value of 'cond' and
if not known at compile time, GCC errs on the safe side and
outputs an error. - Thus, if we know that 'cond' is false, the
code can be permitted.

The linked-to patch is just about this case - albeit not for
conditional expressions but for constants.

* * *

Test case showing the "issue":

SUBROUTINE test4(x_min, x_max, y_min, y_max, vol_flux_x)
  IMPLICIT NONE
  INTEGER, INTENT(IN) :: x_min, x_max, y_min, y_max
  REAL(KIND=8), DIMENSION(x_min:x_max,y_min:y_max) :: vol_flux_x
  INTEGER :: j,k
  integer, parameter :: one = 1

  !$omp do collapse(2)
  DO k=y_min,y_max
   !$omp metadirective &
   !$omp&   when(user={condition((one < 0 ? x_min > 0 : one /= 1))}: simd)
    DO j=x_min,x_max
      vol_flux_x(j,k)=0.25_8
    ENDDO
  ENDDO
END SUBROUTINE test4

→ Yielding the error:

    8 |   !$omp do collapse(2)
      |                      1
Error: not enough DO loops for collapsed !$OMP DO (level 1) at (1)

* * *

For completeness, the simplification happens in
gfc_match_omp_context_selector as follows:

                 if (!gfc_resolve_expr (otp->expr)
                   || (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR
                       && otp->expr->ts.type != BT_LOGICAL)

as mentioned, that works fine - but yields the non-const expression
'(.false. ? x_min > 0 : .false.)'.

NOTE: The code above is actually bad in the sense that it
simplifies to early - during parsing - instead during resolution.
It shouldn't matter for the case being discussed, but there are
cases where it fails - hence, it will eventually have to be moved
to the resolution stage → https://gcc.gnu.org/PR122306

* * *

Thanks,

Tobias

Reply via email to