https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126398

            Bug ID: 126398
           Summary: Missed optimization in byte swapping
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kargl at gcc dot gnu.org
  Target Milestone: ---

I'm not sure if this is a Fortran front end issue, a tree optimization issue,
or may be a target issue.  I choose tree-optimization.  Feel free to change
to an appropriate category.

The discussion

https://fortran-lang.discourse.group/t/fits-io-in-fortran/11006

reveals an issue in code generation for byte swapping with gfortran.
Consider two functions that swap the bytes in a double precision
quantity:

  elemental function le_to_be(x) result(y)
     use, intrinsic :: iso_fortran_env, only: int64, real64
     implicit none
     real(real64) y
     real(real64), intent(in) :: x
     integer(int64) i, j
     integer k
     i = transfer(x, i)
     j = 0
     do k = 0, 7
        call mvbits(i, 8*k, 8, j, 8*(7-k))
     end do
     y = transfer(j, y)
  end function le_to_be

  elemental function byteswap(x) result(y)
     use, intrinsic :: iso_fortran_env, only: int8, real64
     implicit none
     real(real64) y
     real(real64), intent(in) :: x
     integer(int8) bytes(8)
     bytes = transfer(x, bytes)
     y = transfer(bytes(8:1:-1), y)
  end function byteswap


Compiler explorer shows that x86-64 ifx 2025.3.2 generates

  le_to_be_:
        mov     rax, qword ptr [rdi]
        bswap   rax
        movq    xmm0, rax
        ret

  byteswap_:
        mov     rax, qword ptr [rdi]
        mov     qword ptr [rip + byteswap_$BYTES], rax
        bswap   rax
        movq    xmm0, rax
        ret

Compiler explore shows that x86-64 gfortran -O3 -march=znver5 generates

  "le_to_be_":
        mov     rdx, QWORD PTR [rdi]
        movabs  rcx, 71776119061217280
        movabs  rsi, 280375465082880
        mov     rax, rdx
        sal     rax, 40
        and     rax, rcx
        mov     rcx, rdx
        sal     rcx, 56
        or      rax, rcx
        mov     rcx, rdx
        sal     rcx, 24
        and     rcx, rsi
        movabs  rsi, 1095216660480
        or      rax, rcx
        mov     rcx, rdx
        sal     rcx, 8
        and     rcx, rsi
        or      rax, rcx
        mov     rcx, rdx
        shr     rcx, 8
        and     ecx, 4278190080
        or      rax, rcx
        mov     rcx, rdx
        shr     rcx, 24
        and     ecx, 16711680
        or      rax, rcx
        mov     rcx, rdx
        shr     rcx, 40
        shr     rdx, 56
        and     ecx, 65280
        or      rax, rcx
        or      rax, rdx
        vmovq   xmm0, rax
        ret
  "byteswap_":
        push    rbp
        movabs  rax, 1103806595072
        mov     rbp, rsp
        push    rbx
        and     rsp, -64
        sub     rsp, 192
        vmovq   xmm0, QWORD PTR [rdi]
        vmovdqa ymm1, YMMWORD PTR .LC0[rip]
        lea     rbx, [rsp+64]
        mov     QWORD PTR [rsp+152], rax
        mov     QWORD PTR [rsp+136], 0
        mov     QWORD PTR [rsp+144], 1
        mov     QWORD PTR [rsp+128], rbx
        lea     rdi, [rsp+128]
        vpshufb xmm0, xmm0, XMMWORD PTR .LC1[rip]
        vmovdqa YMMWORD PTR [rsp+160], ymm1
        vmovq   QWORD PTR [rsp+64], xmm0
        vzeroupper
        call    "_gfortran_internal_pack"
        vmovsd  xmm0, QWORD PTR [rax]
        cmp     rax, rbx
        je      .L3
        mov     rdi, rax
        vmovsd  QWORD PTR [rsp+56], xmm0
        call    "free"
        vmovsd  xmm0, QWORD PTR [rsp+56]
  .L3:
        mov     rbx, QWORD PTR [rbp-8]
        leave
        ret
  .LC0:
        .quad   1
        .quad   1
        .quad   0
        .quad   7
  .LC1:
        .byte   7
        .byte   6
        .byte   5
        .byte   4
        .byte   3
        .byte   2
        .byte   1
        .byte   0
        .byte   -128
        .byte   -128
        .byte   -128
        .byte   -128
        .byte   -128
        .byte   -128
        .byte   -128
        .byte   -128

Reply via email to