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

            Bug ID: 127897
           Summary: [12/13/14/15/16/17 Regression] x86: set1 vector
                    constants built with 2-3 instructions instead of a
                    memory operand
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mathemagician.ut at gmail dot com
  Target Milestone: ---

The generated code is correct, but vector constants of equal elements that
GCC 11 and clang use as a memory operand are now built with extra
instructions.

pr.c:

#include <immintrin.h>
__m128 f(__m128 x) { return _mm_add_ps(_mm_mul_ps(x, _mm_set1_ps(1.5f)),
_mm_set1_ps(0.25f)); }
__m128i g(__m128i x) { return _mm_add_epi32(_mm_mullo_epi32(x,
_mm_set1_epi32(12345)), _mm_set1_epi32(678)); }

$ gcc -O2 -march=x86-64-v2 -S pr.c

GCC 11.5.0 and clang 19.1.7:

f:      mulps   .LC0(%rip), %xmm0
        addps   .LC1(%rip), %xmm0
g:      pmulld  .LC2(%rip), %xmm0
        paddd   .LC3(%rip), %xmm0

GCC 16.2.0 and trunk (r17-5005):

f:      movss   .LC1(%rip), %xmm1
        shufps  $0, %xmm1, %xmm1
        mulps   %xmm1, %xmm0
        movss   .LC3(%rip), %xmm1
        shufps  $0, %xmm1, %xmm1
        addps   %xmm1, %xmm0
g:      movl    $12345, %eax
        movdqa  %xmm0, %xmm1
        movd    %eax, %xmm0
        movl    $678, %eax
        pshufd  $0, %xmm0, %xmm0
        pmulld  %xmm1, %xmm0
        movd    %eax, %xmm1
        pshufd  $0, %xmm1, %xmm1
        paddd   %xmm1, %xmm0

f is affected since GCC 12, g since GCC 14. Same at -O3 and with any -mtune
tried. With AVX or AVX2, 32-bit integer constants (g, _mm256_set1_epi32) are
built in a general register since GCC 12; clang uses a memory operand or
vpbroadcastd from memory.

-mtune-ctrl=^inter_unit_moves_to_vec restores g but not f.
-mtune-ctrl=^prefer_bcst_from_integer (PR123631) loads g's constants with
movd + pshufd from memory, still two instructions each; f is unchanged.

Caused by (each checked by building cc1 at the revision and its parent):

  r12-2463-ga6291d88d5b6c1: ix86_broadcast_from_constant accepts float modes
    on any target, so f becomes movss + shufps when there is no AVX.
  r14-6534-gbe0ff0866a6f07 (PR112992): removes the TARGET_AVX/TARGET_AVX2
    check from ix86_broadcast_from_constant. The commit targets 32-byte
    vectors without AVX2, but 16-byte integer vectors are now also built
    in a general register with only SSE (g).
  r12-1958-gedafb35bdadf30, r12-7530-gb1a741a0304178: the same for integer
    vectors with AVX and AVX2.

Known to work: 11.5.0
Known to fail: 12.5.0, 13.3.0, 14.2.0, 15.3.0, 16.2.0, 17.0.0
See also: PR112992, PR123631
Host/Target: x86_64-pc-linux-gnu

Reply via email to