public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jeff Law <jlaw@ventanamicro.com>
To: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>
Subject: [committed] RISC-V: Use splitter to generate zicond in another case
Date: Tue, 29 Aug 2023 17:02:27 -0600	[thread overview]
Message-ID: <b1a33efe-c43a-f4f5-ea04-38e60e4f9c83@ventanamicro.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1500 bytes --]

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.

This was primarily Philipp's work under contract with Ventana.  I just 
rewrite the split bits in an if-then-else form and adjusted the 
testsuite for zicond instead of xventanacondops.

Pushed to the trunk,
Jeff


[-- Attachment #2: P --]
[-- Type: text/plain, Size: 4171 bytes --]

commit 94b950df6f8c46925799f642e5c44f42638f2b5e
Author: Philipp Tomsich <philipp.tomsich@vrull.eu>
Date:   Tue Aug 29 16:48:24 2023 -0600

    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>

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 @@ (define_insn "*czero.nez.<GPR:mode><X:mode>.opt2"
   "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 } } */

                 reply	other threads:[~2023-08-29 23:02 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b1a33efe-c43a-f4f5-ea04-38e60e4f9c83@ventanamicro.com \
    --to=jlaw@ventanamicro.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).