]> git.ipfire.org Git - thirdparty/gcc.git/commit
[RISC-V][PR rtl-optimization/121937] Don't call neg_poly_int_rtx with a vector mode
authorJeff Law <jlaw@ventanamicro.com>
Fri, 3 Oct 2025 14:41:53 +0000 (08:41 -0600)
committerJeff Law <jlaw@ventanamicro.com>
Fri, 3 Oct 2025 14:43:14 +0000 (08:43 -0600)
commitf864e4b54a13420f37dc3710aeb9f8a6f9e63b9c
tree727dde5dbb8ca119333b473cdaf10be3db39b7ac
parente9ba0f896efd1ef4f713923304e95eb3b2490f54
[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.
gcc/simplify-rtx.cc
gcc/testsuite/gcc.target/riscv/pr121937.c [new file with mode: 0644]