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

--- Comment #3 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jeff Law <[email protected]>:

https://gcc.gnu.org/g:f864e4b54a13420f37dc3710aeb9f8a6f9e63b9c

commit r16-4207-gf864e4b54a13420f37dc3710aeb9f8a6f9e63b9c
Author: Jeff Law <[email protected]>
Date:   Fri Oct 3 08:41:53 2025 -0600

    [RISC-V][PR rtl-optimization/121937] Don't call neg_poly_int_rtx with a
vector mode

    Fun little bug.

    We're asked to simplify this:

    (vec_select:HI (if_then_else:V2HI (unspec:V2BI [
                    (const_vector:V2BI [
                            (const_int 0 [0])
                            (const_int 1 [0x1])
                        ])
                    (const_int 2 [0x2])
                    (const_int 0 [0]) repeated x3
                    (reg:SI 66 vl)
                    (reg:SI 67 vtype)
                ] UNSPEC_VPREDICATE)
            (const_vector:V2HI [
                    (const_int 0 [0])
                    (const_int -1 [0xffffffffffffffff])
                ])
            (const_vector:V2HI [
                    (const_int -1 [0xffffffffffffffff])
                    (const_int 0 [0])
                ]))
        (parallel [
                (const_int 0 [0])
            ]))

    That triggers some fairly obscure code in combine which realizes the arms
are
    STORE_FLAG_VALUE computabble.  So we ask for a simplified conditional of
the
    condition against (const_int 0):

    3610      return simplify_context ().simplify_gen_relational (code, mode,
op_mode,
    (gdb) p debug_rtx (op0)
    (unspec:V2BI [
            (const_vector:V2BI [
                    (const_int 0 [0])
                    (const_int 1 [0x1])
                ])
            (const_int 2 [0x2])
            (const_int 0 [0]) repeated x3
            (reg:SI 66 vl)
            (reg:SI 67 vtype)
        ] UNSPEC_VPREDICATE)
    $50 = void
    (gdb) p debug_rtx (op1)
    (const_int 0 [0])

    CODE will be EQ.  So that eventually we'll try that as a simplification
using
    MINUS with those two operands.

    That ultimately lands us in simplify_binary_operation_1 which (of course)
tries
    to simplify x - 0 to x.  But that fails because we test (const_int 0)
against
    CONST0_RTX (V2BI) which, of course, false.

    We then stumble down into this code:

          /* Don't let a relocatable value get a negative coeff.  */
          if (poly_int_rtx_p (op1) && GET_MODE (op0) != VOIDmode)
            return simplify_gen_binary (PLUS, mode,
                                        op0,
                                        neg_poly_int_rtx (mode, op1));

    Where MODE is V2BI.  That's not a scalar mode and we try to get the
precision
    of V2BI in the bowels of neg_poly_int_rtx, which looks like:

            return GET_MODE_PRECISION (as_a <scalar_mode> (x.second));

    Where x.second is the mode, V2BI.  Since V2BI is not a scalar mode it blows
up
    as seen in the BZ.

    The immediate and direct fix is to guard that code with a check that we've
got
    a scalar mode.

    I looked at passing a more suitable zero node as well as improving the
checks
    to simplify x - 0 -> x for this case.  While the RTL does simplify in the
    expected ways, nothing really comes out of the RTL simplification (ie, the
    final assembly code is the same).  So I decided against including those
hacks
    (they really didn't feel all that clean to me).  There's just not a
compelling
    reason for them.

    Anyway, bootstrapped and regression tested on x86_64.  Verified it fixes
the
    riscv fault and doesn't regress riscv64-elf and riscv32-elf. Bootstrap on
riscv
    native targets will fire up overnight.

            PR rtl-optimization/121937

    gcc/
            * simplify-rtx.cc (simplify_context::simplify_binary_operation_1):
Make
            sure we've got a scalar_int_mode before calling neg_poly_int_rtx.

    gcc/testsuite/
            * gcc.target/riscv/pr121937.c: New test.

Reply via email to