Overnight testing showed a small number of cases where constant
synthesis was doing something dumb. Specifically generating more
instructions than the number of bits set in the constant.
It was a minor goof in the recent bseti code. In the code to first
figure out what bits LUI could set, I included one bit outside the space
LUI operates. For some dumb reason I kept thinking in terms of 11 low
bits belonging to addi, but it's actually 12 bits. The net is what we
thought should be a single LUI for costing turned into LUI+ADDI.
I didn't let the test run to completion, but over the course of 12 hours
it found 9 cases. Given we know that the triggers all have 0x800 set, I
bet we could likely find more, but I doubt it's that critical to cover
every possible constant that regressed.
This has run in my tester (rv64gc, rv32gcv), but I'll wait for the CI
tester as it covers the bitmanip extensions much better.
Jeff
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 9c98b1da035..049f8f8cb9f 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -921,12 +921,12 @@ riscv_build_integer_1 (struct riscv_integer_op
codes[RISCV_MAX_INTEGER_OPS],
/* First handle any bits set by LUI. Be careful of the
SImode sign bit!. */
- if (value & 0x7ffff800)
+ if (value & 0x7ffff000)
{
alt_codes[i].code = (i == 0 ? UNKNOWN : IOR);
- alt_codes[i].value = value & 0x7ffff800;
+ alt_codes[i].value = value & 0x7ffff000;
alt_codes[i].use_uw = false;
- value &= ~0x7ffff800;
+ value &= ~0x7ffff000;
i++;
}
diff --git a/gcc/testsuite/gcc.target/riscv/synthesis-4.c
b/gcc/testsuite/gcc.target/riscv/synthesis-4.c
new file mode 100644
index 00000000000..328a55b9e6e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/synthesis-4.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target rv64 } */
+/* We aggressively skip as we really just need to test the basic synthesis
+ which shouldn't vary based on the optimization level. -O1 seems to work
+ and eliminates the usual sources of extraneous dead code that would throw
+ off the counts. */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-O2" "-O3" "-Os" "-Oz" "-flto" } }
*/
+/* { dg-options "-march=rv64gc_zba_zbb_zbs" } */
+
+/* Rather than test for a specific synthesis of all these constants or
+ having thousands of tests each testing one variant, we just test the
+ total number of instructions.
+
+ This isn't expected to change much and any change is worthy of a look. */
+/* { dg-final { scan-assembler-times
"\\t(add|addi|bseti|li|ret|sh1add|sh2add|sh3add|slli)" 45 } } */
+
+
+unsigned long foo_0x60000400000800(void) { return 0x60000400000800UL; }
+
+unsigned long foo_0xc0000400000800(void) { return 0xc0000400000800UL; }
+
+unsigned long foo_0x180000400000800(void) { return 0x180000400000800UL; }
+
+unsigned long foo_0x300000400000800(void) { return 0x300000400000800UL; }
+
+unsigned long foo_0x600000400000800(void) { return 0x600000400000800UL; }
+
+unsigned long foo_0xc00000400000800(void) { return 0xc00000400000800UL; }
+
+unsigned long foo_0x1800000400000800(void) { return 0x1800000400000800UL; }
+
+unsigned long foo_0x3000000400000800(void) { return 0x3000000400000800UL; }
+
+unsigned long foo_0x6000000400000800(void) { return 0x6000000400000800UL; }