[RISC-V] Use shNadd for constant synthesis
commitdbbd059b49edc936769737204f5c270d8d6ff553
authorJeff Law <jlaw@ventanamicro.com>
Fri, 10 May 2024 19:49:44 +0000 (10 13:49 -0600)
committerJeff Law <jlaw@ventanamicro.com>
Fri, 10 May 2024 19:50:52 +0000 (10 13:50 -0600)
treefaa01dcb08dd35ed844d05b5519ac9ba09bec201
parentf5a8cdc1ef5d6aa2de60849c23658ac5298df7bb
[RISC-V] Use shNadd for constant synthesis

So here's the next idiom to improve constant synthesis.

The basic idea here is to try and use shNadd to generate the constant when profitable.

Let's take 0x300000801.  Right now that generates:

        li      a0,3145728
        addi    a0,a0,1
        slli    a0,a0,12
        addi    a0,a0,-2047

But we can do better.  The constant is evenly divisible by 9 resulting in
0x55555639 which doesn't look terribly interesting.  But that constant can be
generated with two instructions, then we can use a sh3add to multiply it by 9.
So the updated sequence looks like:

        li      a0,1431654400
        addi    a0,a0,1593
        sh3add  a0,a0,a0

This doesn't trigger a whole lot, but I haven't really set up a test to explore
the most likely space where this might be useful.  The tests were found
exploring a different class of constant synthesis problems.

If you were to dive into the before/after you'd see that the shNadd interacts
quite nicely with the recent bseti work.   The joys of recursion.

Probably the most controversial thing in here is using the "FMA" opcode to
stand in for when we want to use shNadd.  Essentially when we synthesize a
constant we generate a series of RTL opcodes and constants for emission by
another routine.   We don't really have a way to say we want a shift-add.  But
you can think of shift-add as a limited form of multiply-accumulate.  It's a
bit of a stretch, but not crazy bad IMHO.

Other approaches would be to store our own enum rather than an RTL opcode.  Or
store an actual generator function rather than any kind of opcode.

It wouldn't take much pushback over (ab)using FMA in this manner to get me to
use our own enums rather than RTL opcodes for this stuff.

gcc/

* config/riscv/riscv.cc (riscv_build_integer_1): Recognize cases where
we can use shNadd to improve constant synthesis.
(riscv_move_integer): Handle code generation for shNadd.

gcc/testsuite
* gcc.target/riscv/synthesis-1.c: Also count shNadd instructions.
* gcc.target/riscv/synthesis-3.c: New test.
gcc/config/riscv/riscv.cc
gcc/testsuite/gcc.target/riscv/synthesis-1.c
gcc/testsuite/gcc.target/riscv/synthesis-3.c [new file with mode: 0644]