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