Currently logical operations (AND, OR, EQV, NEQV) are implemented in terms of fir.convert from fir.logical to i1 + arith op on i1, and fir.convert to fir.logical.
This was done with the intent to avoid adding operations in FIR. But this is actually doing an early implementation of the logical operation because the fir.convert are forcing a canonicalization of the LOGICAL representation (introducing a compare to zero on the inputs and a zero extension on the output) that makes it harder to deal with reductions and/or to map the operation to atomic primitives.
The main motivation for this change is to making the IR for the following implicit reduction code easier to analyze and work with:
subroutine reduce_logical(r,a)
logical :: r, a(32)
!$acc kernels
do i = 1, 32
r = r .and. a(i)
enddo
!$acc end kernels
end
Currently generates inside the loops for the acc kernel:
%10 = fir.load %5 : !fir.ref<!fir.logical<4>>
%11 = fir.load %4 : !fir.ref<i32>
%12 = fir.convert %11 : (i32) -> i64
%13 = fir.array_coor %2(%1) %12 : (!fir.ref<!fir.array<32x!fir.logical<4>>>, !fir.shape<1>, i64) -> !fir.ref<!fir.logical<4>>
%14 = fir.load %13 : !fir.ref<!fir.logical<4>>
%15 = fir.convert %10 : (!fir.logical<4>) -> i1
%16 = fir.convert %14 : (!fir.logical<4>) -> i1
%17 = arith.andi %15, %16 : i1
%18 = fir.convert %17 : (i1) -> !fir.logical<4>
fir.store %18 to %5 : !fir.ref<!fir.logical<4>>
The extra converts are making the identification and transformation of the operation harder, especially because they cannot simply be ignored as they are sometimes inserted when converting logical to/from INTEGER where they must be applied.
Hence, I propose adding 4 simple pure operation for LOGICAL AND/OR/EQV/NEQV that would be generated when at least one of the operand is a logical variable and would make detection and transformation of logical reduction in OpenACC (and probably OpenMP) easier.
Here is the pull request that goes with this RFC.