aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorJeff Law <jlaw@ventanamicro.com>2024-05-26 17:54:51 -0600
committerJeff Law <jlaw@ventanamicro.com>2024-05-26 17:54:51 -0600
commit3a915d6ad5fc3e0fadd14e54515b48b1d655c5a4 (patch)
treea6e60335c71a5888c373943041374e717631a8cb /gcc/config
parenta06df6644a4403bb63b0ab68532ea67b938d8baf (diff)
downloadgcc-3a915d6ad5fc3e0fadd14e54515b48b1d655c5a4.zip
gcc-3a915d6ad5fc3e0fadd14e54515b48b1d655c5a4.tar.gz
gcc-3a915d6ad5fc3e0fadd14e54515b48b1d655c5a4.tar.bz2
[to-be-committed] [RISC-V] Try inverting for constant synthesis
So there's another class of constants we're failing to synthesize well. Specifically those where we can invert our original constant C into C' and C' takes at least 2 fewer instructions to synthesize than C. In that case we can initially generate C', then use xori with the constant -1 to flip all the bits resulting in our target constant. I've only seen this trigger when the final synthesis is li+srli+xori. The original synthesis took on various 4 or 5 instruction forms. Most of the methods we use to improve constant synthesis are in riscv_build_integer_1. I originally tried to put this code in there. But that'll end up with infinite recursion due to some other ADDI related code which wants to flip bits and try synthesis. So this was put into riscv_build_integer and recurses into riscv_build_integer. This isn't unprecedented, just a bit different than most of the other synthesis implementation bits. This doesn't depend on any extensions. So it should help any rv64 system. gcc/ * config/riscv/riscv.cc (riscv_build_integer_one): Verify there are no bits left to set in the constant when generating bseti. (riscv_built_integer): Synthesize ~value and if it's cheap use it with a trailing xori with -1. gcc/testsuite * gcc.target/riscv/synthesis-8.c: New test.
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/riscv/riscv.cc27
1 files changed, 26 insertions, 1 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 0ebdd69..401ddc9 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1022,7 +1022,7 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
/* If LUI+ADDI+BSETI resulted in a more efficient
sequence, then use it. */
- if (i < cost)
+ if (value == 0 && i < cost)
{
memcpy (codes, alt_codes, sizeof (alt_codes));
cost = i;
@@ -1074,6 +1074,31 @@ riscv_build_integer (struct riscv_integer_op *codes, HOST_WIDE_INT value,
}
}
+ /* See if we can generate the inverted constant, then use
+ not to get the desired constant.
+
+ This can't be in riscv_build_integer_1 as it'll mutually
+ recurse with another case in there. And it has to recurse
+ into riscv_build_integer so we get the trailing 0s case
+ above. */
+ if (cost > 2 && value < 0)
+ {
+ struct riscv_integer_op alt_codes[RISCV_MAX_INTEGER_OPS];
+ int alt_cost;
+
+ HOST_WIDE_INT nval = ~value;
+ alt_cost = 1 + riscv_build_integer (alt_codes, nval, mode);
+ if (alt_cost < cost)
+ {
+ alt_codes[alt_cost - 1].code = XOR;
+ alt_codes[alt_cost - 1].value = -1;
+ alt_codes[alt_cost - 1].use_uw = false;
+ memcpy (codes, alt_codes, sizeof (alt_codes));
+ cost = alt_cost;
+ }
+ }
+
+
if (!TARGET_64BIT
&& (value > INT32_MAX || value < INT32_MIN))
{