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

            Bug ID: 127976
           Summary: [14/15/16 Regression] ICE in
                    simplify_binary_operation_1 (VEC_CONCAT) during
                    combine on aarch64 since 8968e92cc65e
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: zeno490 at gmail dot com
  Target Milestone: ---

Created attachment 65882
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65882&action=edit
repro file

[Note that this was generated by Claude]

GCC 14.1 to 16.2 crash on aarch64 at -O1 and -O2 with the testcase below.
GCC 12.5, GCC 13.4, and trunk (17.0.0 20261005) compile it. Clang 22 also
compiles it.

The failing assert is the operand size check of the VEC_CONCAT case in
simplify_binary_operation_1:

    gcc_assert (known_eq (GET_MODE_SIZE (op0_mode)
                          + GET_MODE_SIZE (op1_mode),
                          GET_MODE_SIZE (mode)));

(simplify-rtx.cc:5378 in 16.2.0, :5108 in 15.2.0, :4821 in 14.3.0, :4793 in
14.1.0)

The cause appears to be the VEC_CONCAT fold that 8968e92cc65e
("simplify-rtx: Simplify VEC_CONCAT of SUBREG and VEC_CONCAT from same vector")
added:

    /* (vec_concat:
         (subreg_lowpart:N OP)
         (vec_select:N OP P))  -->  OP when P selects the high half
        of the OP.  */
    ...
      return XEXP (trueop1, 0);

The fold does not check that the mode of OP is the result mode. In the failing
combine
attempt, insn 24 is:

    (vec_concat:V2SF (subreg:SF (reg:V4SF 101) 0)
                     (vec_select:SF (reg:V4SF 101) (parallel [(const_int 1)])))

The fold returns (reg:V4SF 101), a 16-byte value, for the V2SF result. The
outer
vec_concat:V4SF from vcombine_f32 (insn 28) then gets a 16-byte operand and an
8-byte operand, and the assert fails.

On trunk, b085ae4b49b4 (PR target/48609, 2026-08-25) replaced this fold with a
fold
that checks known_eq (GET_MODE_SIZE (GET_MODE (base0)), GET_MODE_SIZE (mode)).
That commit is an x86 optimization, so it is not on the release branches.
A smaller fix for the branches can be to add GET_MODE (XEXP (trueop1, 0)) ==
mode
to the condition of the old fold. (Not tested.)

Testcase (gcc_ice.c):

#include <arm_neon.h>

int run(float threshold)
{
        const float32x4_t values[] = {
                { 0.0F, 0.0F, 0.0F, 1.0F },
                { -0.701057315F, 0.0922959521F, -0.430459321F, 0.560985446F },
                { -0.597238779F, -0.565758348F, -0.0560427159F, 0.565758348F },
        };

        int all_ok = 1;
        for (int i = 0; i < 3; ++i)
        {
                const float32x2_t lo = vset_lane_f32(vgetq_lane_f32(values[i],
1), vmov_n_f32(vgetq_lane_f32(values[i], 0)), 1);
                const float32x2_t hi = vset_lane_f32(vgetq_lane_f32(values[i],
2), vdup_n_f32(0.0F), 0);
                const uint32x4_t mask = vcleq_f32(vabsq_f32(vcombine_f32(lo,
hi)), vdupq_n_f32(threshold));
                all_ok &= vminvq_u32(mask) != 0;
        }
        return all_ok;
}

Command line:

    gcc -O2 -c gcc_ice.c

Output:

during RTL pass: combine
gcc_ice.c: In function 'run':
gcc_ice.c:21:1: internal compiler error: in simplify_binary_operation_1, at
simplify-rtx.cc:5378
   21 | }
      | ^
0x1e1564f diagnostics::context::diagnostic_impl(rich_location*,
diagnostics::metadata const*, diagnostics::option_id, char const*,
std::__va_list*, diagnostics::kind)
        ???:0
0x1e0e833 internal_error(char const*, ...)
        ???:0
0x80e5d3 fancy_abort(char const*, int, char const*)
        ???:0
0xe745ff simplify_context::simplify_binary_operation_1(rtx_code, machine_mode,
rtx_def*, rtx_def*, rtx_def*, rtx_def*)
        ???:0
0xe74893 simplify_context::simplify_binary_operation(rtx_code, machine_mode,
rtx_def*, rtx_def*)
        ???:0

The last combine attempt in -fdump-rtl-combine-details:

Trying 22, 24 -> 28:
   22: r131:SF=vec_select(r101:V4SF,parallel)
   24: r132:V2SF=vec_concat(r101:V4SF#0,r131:SF)
      REG_DEAD r131:SF
   28: r128:V4SF=vec_concat(r132:V2SF,r134:V2SF)
      REG_DEAD r134:V2SF
      REG_DEAD r132:V2SF

gcc -v:

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/aarch64-linux-gnu/16.2.0/lto-wrapper
Target: aarch64-linux-gnu
Configured with: /usr/src/gcc/configure --build=aarch64-linux-gnu
--disable-multilib --enable-languages=c,c++,fortran,go
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 16.2.0 (GCC)

(The official gcc:16 Docker image. The other versions: the Ubuntu 26.04 arm64
packages
for 14.3.0 and 15.2.0, and Compiler Explorer for 12.x, 13.x, 14.1.0, 15.1.0,
16.1.0, and trunk.)

Found in: the unit tests of the Realtime Math library
(https://github.com/nfrechette/rtm).

Reply via email to