[to-be-committed][RISC-V] Generate nearby constant, then adjust to our final desired constant
Next step in constant synthesis work. For some cases it can be advantageous to generate a constant near our target, then do a final addi to fully synthesize C. The idea is that while our target C may require N instructions to synthesize, C' may only require N-2 (or fewer) instructions. Thus there's budget to adjust C' into C ending up with a better sequence than if we tried to generate C directly. So as an example: > unsigned long foo_0xfffff7fe7ffff7ff(void) { return 0xfffff7fe7ffff7ffUL; } This is currently 5 instructions on the trunk: > li a0,-4096 > addi a0,a0,2047 > bclri a0,a0,31 > bclri a0,a0,32 > bclri a0,a0,43 But we can do better by first synthesizing 0xfffff7fe7ffff800 which is just 3 instructions. Then we can subtract 1 from the result. That gives us this sequence: > li a0,-16789504 > slli a0,a0,19 > addi a0,a0,-2048 > addi a0,a0,-1 These cases are relatively easy to find once you know what you're looking for. I kept the full set found by the testing code yesterday, mostly because some of them show different patterns for generating C', thus showing generality in the overall synthesis implementation. While all these tests have 0x7ff in their low bits. That's just an artifact to the test script. The methodology will work for a variety of other cases. gcc/ * config/riscv/riscv.cc (riscv_build_integer_1): Try generating a nearby simpler constant, then using a final addi to set low bits properly. gcc/testsuite * gcc.target/riscv/synthesis-7.c: New test.
This commit is contained in:
parent
87463737b9
commit
95660223c4
2 changed files with 1551 additions and 0 deletions
|
@ -963,6 +963,26 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
|
|||
}
|
||||
}
|
||||
|
||||
/* We might be able to generate a constant close to our target
|
||||
then a final ADDI to get the desired constant. */
|
||||
if (cost > 2
|
||||
&& (value & 0xfff) != 0
|
||||
&& (value & 0x1800) == 0x1000)
|
||||
{
|
||||
HOST_WIDE_INT adjustment = -(0x800 - (value & 0xfff));
|
||||
alt_cost = 1 + riscv_build_integer_1 (alt_codes,
|
||||
value - adjustment, mode);
|
||||
|
||||
if (alt_cost < cost)
|
||||
{
|
||||
alt_codes[alt_cost - 1].code = PLUS;
|
||||
alt_codes[alt_cost - 1].value = adjustment;
|
||||
alt_codes[alt_cost - 1].use_uw = false;
|
||||
memcpy (codes, alt_codes, sizeof (alt_codes));
|
||||
cost = alt_cost;
|
||||
}
|
||||
}
|
||||
|
||||
/* Final cases, particularly focused on bseti. */
|
||||
if (cost > 2 && TARGET_ZBS)
|
||||
{
|
||||
|
|
1531
gcc/testsuite/gcc.target/riscv/synthesis-7.c
Normal file
1531
gcc/testsuite/gcc.target/riscv/synthesis-7.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue