123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- From 1b1f5be20e41f14041f0ac3ec295fc114f6e3b86 Mon Sep 17 00:00:00 2001
- From: Philipp Tomsich <philipp.tomsich@vrull.eu>
- Date: Tue, 29 Aug 2023 16:48:24 -0600
- Subject: [PATCH 14/30] RISC-V: Use splitter to generate zicond in another case
- So in analyzing Ventana's internal tree against the trunk it became apparent
- that the current zicond code is missing a case that helps coremark's bitwise
- CRC implementation.
- Here's a minimized testcase:
- long xor1(long crc, long poly)
- {
- if (crc & 1)
- crc ^= poly;
- return crc;
- }
- ie, it's just a conditional xor.
- We generate this:
- andi a5,a0,1
- neg a5,a5
- and a5,a5,a1
- xor a0,a5,a0
- ret
- But we should instead generate:
- andi a5,a0,1
- czero.eqz a5,a1,a5
- xor a0,a5,a0
- ret
- Combine wants to generate:
- Trying 7, 8 -> 9:
- 7: r140:DI=r137:DI&0x1
- 8: r141:DI=-r140:DI
- REG_DEAD r140:DI
- 9: r142:DI=r141:DI&r144:DI
- REG_DEAD r144:DI
- REG_DEAD r141:DI
- Failed to match this instruction:
- (set (reg:DI 142)
- (and:DI (sign_extract:DI (reg/v:DI 137 [ crc ])
- (const_int 1 [0x1])
- (const_int 0 [0]))
- (reg:DI 144)))
- A splitter can rewrite the above into a suitable if-then-else construct and
- squeeze an instruction out of that pesky CRC loop. Sadly it doesn't really
- help anything else.
- The patch includes two variants. One that uses ZBS, the other uses an ANDI
- logical to produce the input condition.
- gcc/
- * config/riscv/zicond.md: New splitters to rewrite single bit
- sign extension as the condition to a czero in the desired form.
- gcc/testsuite
- * gcc.target/riscv/zicond-xor-01.c: New test.
- Co-authored-by: Jeff Law <jlaw@ventanamicro.com>
- ---
- gcc/config/riscv/zicond.md | 31 +++++++++++++++++++
- .../gcc.target/riscv/zicond-xor-01.c | 14 +++++++++
- 2 files changed, 45 insertions(+)
- create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-xor-01.c
- diff --git a/gcc/config/riscv/zicond.md b/gcc/config/riscv/zicond.md
- index 25f21d33487..4619220ef8a 100644
- --- a/gcc/config/riscv/zicond.md
- +++ b/gcc/config/riscv/zicond.md
- @@ -62,3 +62,34 @@
- "TARGET_ZICOND && rtx_equal_p (operands[1], operands[3])"
- "czero.nez\t%0,%2,%1"
- )
- +
- +;; Combine creates this form in some cases (particularly the coremark
- +;; CRC loop.
- +(define_split
- + [(set (match_operand:X 0 "register_operand")
- + (and:X (sign_extract:X (match_operand:X 1 "register_operand")
- + (const_int 1)
- + (match_operand 2 "immediate_operand"))
- + (match_operand:X 3 "register_operand")))
- + (clobber (match_operand:X 4 "register_operand"))]
- + "TARGET_ZICOND && TARGET_ZBS"
- + [(set (match_dup 4) (zero_extract:X (match_dup 1) (const_int 1) (match_dup 2)))
- + (set (match_dup 0) (if_then_else:X (eq:X (match_dup 4) (const_int 0))
- + (const_int 0)
- + (match_dup 3)))])
- +
- +(define_split
- + [(set (match_operand:X 0 "register_operand")
- + (and:X (sign_extract:X (match_operand:X 1 "register_operand")
- + (const_int 1)
- + (match_operand 2 "immediate_operand"))
- + (match_operand:X 3 "register_operand")))
- + (clobber (match_operand:X 4 "register_operand"))]
- + "TARGET_ZICOND && !TARGET_ZBS && (UINTVAL (operands[2]) < 11)"
- + [(set (match_dup 4) (and:X (match_dup 1) (match_dup 2)))
- + (set (match_dup 0) (if_then_else:X (eq:X (match_dup 4) (const_int 0))
- + (const_int 0)
- + (match_dup 3)))]
- +{
- + operands[2] = GEN_INT (1 << UINTVAL(operands[2]));
- +})
- diff --git a/gcc/testsuite/gcc.target/riscv/zicond-xor-01.c b/gcc/testsuite/gcc.target/riscv/zicond-xor-01.c
- new file mode 100644
- index 00000000000..8362ffaf5ab
- --- /dev/null
- +++ b/gcc/testsuite/gcc.target/riscv/zicond-xor-01.c
- @@ -0,0 +1,14 @@
- +/* { dg-do compile } */
- +/* { dg-options "-march=rv64gc_zicond -mabi=lp64" } */
- +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */
- +
- +long xor1(long crc, long poly)
- +{
- + if (crc & 1)
- + crc ^= poly;
- +
- + return crc;
- +}
- +
- +/* { dg-final { scan-assembler-times "czero.eqz\t" 1 } } */
- +/* { dg-final { scan-assembler-times "xor\t" 1 } } */
- --
- 2.25.1
|