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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://gcc.gnu.org/bugzill
                   |                            |a/show_bug.cgi?id=126079
             Status|UNCONFIRMED                 |NEW
     Ever confirmed|0                           |1
   Last reconfirmed|                            |2026-11-04

--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Thomas Koenig from comment #0)
> This is on rocketlake.
> 
> The following code
> 
> subroutine foo (from_small, to_small, from_buf, to_buf)
>   implicit none
>   unsigned(8), value :: from_small, to_small
>   unsigned(1), dimension(41), intent(out) :: from_buf, to_buf
>   integer, parameter :: grpsz = 6, tabsz=729
>   integer :: i, k
>   unsigned(16), parameter :: base = 3u_16
>   integer, parameter :: n_grp = int(64 * log(2.0)/log(real(base)) / grpsz) !
> rounding down
>   integer, parameter :: halfsize = n_grp * grpsz
> 
>   unsigned(kind=1), dimension(0:grpsz-1,0:tabsz-1), parameter :: tab =
> reshape ([ &
>        ((mod(uint(k)/base**uint(i), base), i=0, grpsz-1), k=0, tabsz-1) &
>        ], shape = [grpsz,tabsz])
>   unsigned, parameter :: tabszu = uint(tabsz)
>   unsigned(8) :: from_rem, to_rem
>   do i=0, halfsize-1, grpsz
>      to_rem = mod(to_small, tabszu)
>      to_small = to_small / tabszu
>      from_rem = mod(from_small, tabszu)
>      from_small = mod(from_small, tabszu)
>      to_buf (i:i+grpsz-1) = tab(:,int(to_rem))
>      from_buf (i:i+grpsz-1) = tab(:,int(from_rem))
>   end do
> end subroutine foo
> 
> yields some weird assembly code with
> 
> gfortran -fverbose-asm -march=native -mtune=native -fmax-errors=1 -funsigned
> -S -O3 tst2.f90
> 
> (only weird parts copied):
> 
> # tst2.f90:21:      to_buf (i:i+grpsz-1) = tab(:,int(to_rem))
>       vmovd   %edx, %xmm0     # tab[_125], tmp377
>       movzbl  tab.0+2(%rbx), %edx     # tab[_94], tab[_94]
>       vpinsrb $1, tab.0+1(%rbx), %xmm0, %xmm0 #, tab[_102], tmp377, tmp378
>       vmovd   %edx, %xmm7     # tab[_94], tmp383
>       movzbl  tab.0+4(%rbx), %edx     # tab[_70], tab[_70]
>       vpinsrb $1, tab.0+3(%rbx), %xmm7, %xmm7 #, tab[_87], tmp383, tmp384
>       vmovd   %edx, %xmm3     # tab[_70], tmp389
>       movzbl  tab.0(%r11), %edx       # tab[_69], tab[_69]
>       vpinsrb $1, tab.0+5(%rbx), %xmm3, %xmm3 #, tab[_41], tmp389, tmp390
>       vpunpcklwd      %xmm7, %xmm0, %xmm0     # tmp384, tmp378, tmp423
>       vmovd   %edx, %xmm6     # tab[_69], tmp395
>       movzbl  tab.0+2(%r11), %edx     # tab[_133], tab[_133]
>       vpinsrb $1, tab.0+1(%r11), %xmm6, %xmm6 #, tab[_77], tmp395, tmp396
>       vmovd   %edx, %xmm1     # tab[_133], tmp401
>       movzbl  tab.0+4(%r11), %edx     # tab[_141], tab[_141]
>       vpinsrb $1, tab.0+3(%r11), %xmm1, %xmm1 #, tab[_137], tmp401, tmp402
>       vpunpcklwd      %xmm6, %xmm3, %xmm3     # tmp396, tmp390, tmp425
>       vmovd   %edx, %xmm5     # tab[_141], tmp407
>       vpunpckldq      %xmm3, %xmm0, %xmm0     # tmp425, tmp423, tmp431
>       vpinsrb $1, tab.0+5(%r11), %xmm5, %xmm5 #, tab[_145], tmp407, tmp408
>       movzbl  tab.0(%r10), %edx       # tab[_179], tab[_179]
>       vmovd   %edx, %xmm2     # tab[_179], tmp413
>       movzbl  tab.0+2(%r10), %edx     # tab[_187], tab[_187]
>       vpunpcklwd      %xmm5, %xmm1, %xmm1     # tmp408, tmp402, tmp427
>       vpinsrb $1, tab.0+1(%r10), %xmm2, %xmm2 #, tab[_183], tmp413, tmp414
>       vmovd   %edx, %xmm4     # tab[_187], tmp419
>       movzbl  tab.0+4(%r10), %edx     # tab[_195], tab[_195]
>       vpinsrb $1, tab.0+3(%r10), %xmm4, %xmm4 #, tab[_191], tmp419, tmp420
>       vpunpcklwd      %xmm4, %xmm2, %xmm2     # tmp420, tmp414, tmp429
>       vpunpckldq      %xmm2, %xmm1, %xmm1     # tmp429, tmp427, tmp433
>       vpunpcklqdq     %xmm1, %xmm0, %xmm0     # tmp433, tmp431, tmp435
>       vmovd   %edx, %xmm1     # tab[_195], tmp438
>       movzbl  tab.0(%r9), %edx        # tab[_233], tab[_233]
>       vpinsrb $1, tab.0+5(%r10), %xmm1, %xmm1 #, tab[_199], tmp438, tmp439
>       vmovd   %edx, %xmm8     # tab[_233], tmp444
>       movzbl  tab.0+2(%r9), %edx      # tab[_241], tab[_241]
>       vpinsrb $1, tab.0+1(%r9), %xmm8, %xmm8  #, tab[_237], tmp444, tmp445
>       vmovd   %edx, %xmm4     # tab[_241], tmp450
>       movzbl  tab.0+4(%r9), %edx      # tab[_249], tab[_249]
>       vpinsrb $1, tab.0+3(%r9), %xmm4, %xmm4  #, tab[_245], tmp450, tmp451
>       vpunpcklwd      %xmm8, %xmm1, %xmm1     # tmp445, tmp439, tmp484
>       vmovd   %edx, %xmm7     # tab[_249], tmp456
>       movzbl  tab.0(%r8), %edx        # tab[_287], tab[_287]
>       vpinsrb $1, tab.0+5(%r9), %xmm7, %xmm7  #, tab[_253], tmp456, tmp457
>       vmovd   %edx, %xmm2     # tab[_287], tmp462
>       movzbl  tab.0+2(%r8), %edx      # tab[_295], tab[_295]
>       vpinsrb $1, tab.0+1(%r8), %xmm2, %xmm2  #, tab[_291], tmp462, tmp463
>       vpunpcklwd      %xmm7, %xmm4, %xmm4     # tmp457, tmp451, tmp486
>       vmovd   %edx, %xmm6     # tab[_295], tmp468
>       movzbl  tab.0+4(%r8), %edx      # tab[_303], tab[_303]
>       vpunpckldq      %xmm4, %xmm1, %xmm1     # tmp486, tmp484, tmp492
>       vpinsrb $1, tab.0+3(%r8), %xmm6, %xmm6  #, tab[_299], tmp468, tmp469
>       vmovd   %edx, %xmm3     # tab[_303], tmp474
>       movzbl  tab.0(%rcx), %edx       # tab[_26], tab[_26]
>       vpinsrb $1, tab.0+5(%r8), %xmm3, %xmm3  #, tab[_307], tmp474, tmp475
>       vpunpcklwd      %xmm6, %xmm2, %xmm2     # tmp469, tmp463, tmp488
>       vmovd   %edx, %xmm5     # tab[_26], tmp480
> # tst2.f90:21:      to_buf (i:i+grpsz-1) = tab(:,int(to_rem))
>       movl    tab.0+2(%rcx), %edx     # MEM <vector(4) unsigned(kind=1)>
> [(unsigned(kind=1) *)vectp.12_206], vect__106.13_207
> # tst2.f90:21:      to_buf (i:i+grpsz-1) = tab(:,int(to_rem))
>       vpinsrb $1, tab.0+1(%rcx), %xmm5, %xmm5 #, tab[_95], tmp480, tmp481
> # tst2.f90:21:      to_buf (i:i+grpsz-1) = tab(:,int(to_rem))
>       movl    %edx, 31(%r14)  # vect__106.13_207, MEM <vector(4) 
> unsigned(kind=1)>
> [(unsigned(kind=1) *)to_buf_27(D) + 31B]
> # tst2.f90:21:      to_buf (i:i+grpsz-1) = tab(:,int(to_rem))
>       vpunpcklwd      %xmm5, %xmm3, %xmm3     # tmp481, tmp475, tmp490
>       vpunpckldq      %xmm3, %xmm2, %xmm2     # tmp490, tmp488, tmp494
> # tst2.f90:22:      from_buf (i:i+grpsz-1) = tab(:,int(from_rem))
>       vmovd   %r12d, %xmm3    # _4, tmp512
> # tst2.f90:21:      to_buf (i:i+grpsz-1) = tab(:,int(to_rem))
>       vpunpcklqdq     %xmm2, %xmm1, %xmm1     # tmp494, tmp492, tmp496
> # tst2.f90:22:      from_buf (i:i+grpsz-1) = tab(:,int(from_rem))
>       vpinsrb $1, tab.0+5(%rdi), %xmm3, %xmm3 #, tab[_2], tmp512, tmp513
> # tst2.f90:21:      to_buf (i:i+grpsz-1) = tab(:,int(to_rem))
>       vinserti32x4    $0x1, %xmm1, %ymm0, %ymm0       # tmp496, tmp435, _202
> # tst2.f90:22:      from_buf (i:i+grpsz-1) = tab(:,int(from_rem))
>       vmovd   %esi, %xmm1     # _14, tmp508
> # tst2.f90:22:      from_buf (i:i+grpsz-1) = tab(:,int(from_rem))
>       movl    -4(%rsp), %esi  # %sfp, MEM <vector(4) unsigned(kind=1)>
> [(unsigned(kind=1) *)vectp.19_218]
> # tst2.f90:21:      to_buf (i:i+grpsz-1) = tab(:,int(to_rem))
>       vmovdqu %ymm0, -1(%r14) # _202, MEM <vector(32) unsigned(kind=1)>
> [(unsigned(kind=1) *)to_buf_27(D) + -1B]
> # tst2.f90:22:      from_buf (i:i+grpsz-1) = tab(:,int(from_rem))
>       vmovd   %eax, %xmm0     # _34, tmp504
>       vpinsrb $1, tab.0+3(%rdi), %xmm1, %xmm1 #, tab[_8], tmp508, tmp509
>       vpinsrb $1, tab.0+1(%rdi), %xmm0, %xmm0 #, tab[_29], tmp504, tmp505
> # tst2.f90:22:      from_buf (i:i+grpsz-1) = tab(:,int(from_rem))
>       movl    %esi, 31(%r13)  # MEM <vector(4) unsigned(kind=1)> 
> [(unsigned(kind=1)
> *)vectp.19_218], MEM <vector(4) unsigned(kind=1)> [(unsigned(kind=1)
> *)from_buf_32(D) + 31B]
> # tst2.f90:22:      from_buf (i:i+grpsz-1) = tab(:,int(from_rem))
>       vpunpcklwd      %xmm1, %xmm0, %xmm2     # tmp509, tmp505, tmp535
>       vpunpcklwd      %xmm3, %xmm1, %xmm1     # tmp513, tmp509, tmp539
>       vpunpcklwd      %xmm0, %xmm3, %xmm0     # tmp505, tmp513, tmp537
>       vpunpckldq      %xmm0, %xmm2, %xmm3     # tmp537, tmp535, tmp543
>       vpunpckldq      %xmm2, %xmm1, %xmm2     # tmp535, tmp539, tmp545
>       vpunpckldq      %xmm1, %xmm0, %xmm0     # tmp539, tmp537, tmp588
>       vpunpcklqdq     %xmm2, %xmm3, %xmm2     # tmp545, tmp543, tmp547
>       vpunpcklqdq     %xmm3, %xmm0, %xmm0     # tmp543, tmp588, tmp592
>       vinserti32x4    $0x1, %xmm0, %ymm2, %ymm0       # tmp592, tmp547, _213
>       vmovdqu %ymm0, -1(%r13) # _213, MEM <vector(32) unsigned(kind=1)>
> [(unsigned(kind=1) *)from_buf_32(D) + -1B]
>       vzeroupper
> 
> The line
> 
>      to_buf (i:i+grpsz-1) = tab(:,int(to_rem))
> 
> is a six-byte contiguous copy, which should be done with a a four-byte and a
> two-byte load and subsequent store.

The vectorizer does exactly that.  The code you quite is from the
vectorization of

     from_buf (i:i+grpsz-1) = tab(:,int(from_rem))

after completely unrolling the loop:

t.f90:21:46: optimized: basic block part vectorized using 4 byte vectors
t.f90:21:46: optimized: basic block part vectorized using 2 byte vectors
t.f90:21:46: optimized: basic block part vectorized using 4 byte vectors
t.f90:21:46: optimized: basic block part vectorized using 2 byte vectors
t.f90:21:46: optimized: basic block part vectorized using 4 byte vectors
t.f90:21:46: optimized: basic block part vectorized using 2 byte vectors
t.f90:21:46: optimized: basic block part vectorized using 4 byte vectors
t.f90:21:46: optimized: basic block part vectorized using 2 byte vectors
t.f90:21:46: optimized: basic block part vectorized using 4 byte vectors
t.f90:21:46: optimized: basic block part vectorized using 2 byte vectors
t.f90:21:46: optimized: basic block part vectorized using 4 byte vectors
t.f90:21:46: optimized: basic block part vectorized using 2 byte vectors
t.f90:22:50: optimized: basic block part vectorized using 32 byte vectors
t.f90:22:50: optimized: basic block part vectorized using 4 byte vectors

for the earlier block we split the store group because the loads are
from different interleaving chains (aliasing issue likely), where the
latter block is successfully handled with a repeating load permutation
but then

t.f90:22:50: note:   ==> examining statement: _34 = tab[_37];
t.f90:22:50: missed:   BB vectorization with gaps at the end of a load is not
supported
t.f90:22:50: missed:   not vectorized: relevant stmt not supported: _34 =
tab[_37];
t.f90:22:50: note:   Building vector operands of 0x282b4070 from scalars
instead

and that costs OK.  This late failure isn't handled via splitting the
graph.

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

Reply via email to