public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-4376] RISC-V: Avoid redundant sign-extension for SImode SGE, SGEU, SLE, SLEU
@ 2022-11-28 19:37 Maciej W. Rozycki
  0 siblings, 0 replies; only message in thread
From: Maciej W. Rozycki @ 2022-11-28 19:37 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:868fc62791b6b0f10484cc6fa15f81911418e605

commit r13-4376-g868fc62791b6b0f10484cc6fa15f81911418e605
Author: Maciej W. Rozycki <macro@embecosm.com>
Date:   Mon Nov 28 19:36:15 2022 +0000

    RISC-V: Avoid redundant sign-extension for SImode SGE, SGEU, SLE, SLEU
    
    We produce inefficient code for some synthesized SImode conditional set
    operations (i.e. ones that are not directly implemented in hardware) on
    RV64.  For example a piece of C code like this:
    
    int
    sleu (unsigned int x, unsigned int y)
    {
      return x <= y;
    }
    
    gets compiled (at `-O2') to this:
    
    sleu:
            sgtu    a0,a0,a1        # 9     [c=4 l=4]  *sgtu_disi
            xori    a0,a0,1         # 10    [c=4 l=4]  *xorsi3_internal/1
            andi    a0,a0,1         # 16    [c=4 l=4]  anddi3/1
            ret                     # 25    [c=0 l=4]  simple_return
    
    or (at `-O1') to this:
    
    sleu:
            sgtu    a0,a0,a1        # 9     [c=4 l=4]  *sgtu_disi
            xori    a0,a0,1         # 10    [c=4 l=4]  *xorsi3_internal/1
            sext.w  a0,a0           # 16    [c=4 l=4]  extendsidi2/0
            ret                     # 24    [c=0 l=4]  simple_return
    
    This is because the middle end expands a SLEU operation missing from
    RISC-V hardware into a sequence of a SImode SGTU operation followed by
    an explicit SImode XORI operation with immediate 1.  And while the SGTU
    machine instruction (alias SLTU with the input operands swapped) gives a
    properly sign-extended 32-bit result which is valid both as a SImode or
    a DImode operand the middle end does not see that through a SImode XORI
    operation, because we tell the middle end that the RISC-V target (unlike
    MIPS) may hold values in DImode integer registers that are valid for
    SImode operations even if not properly sign-extended.
    
    However the RISC-V psABI requires that 32-bit function arguments and
    results passed in 64-bit integer registers be properly sign-extended, so
    this is explicitly done at the conclusion of the function.
    
    Fix this by making the backend use a sequence of a DImode SGTU operation
    followed by a SImode SEQZ operation instead.  The latter operation is
    known by the middle end to produce a properly sign-extended 32-bit
    result and therefore combine gets rid of the sign-extension operation
    that follows and actually folds it into the very same XORI machine
    operation resulting in:
    
    sleu:
            sgtu    a0,a0,a1        # 9     [c=4 l=4]  *sgtu_didi
            xori    a0,a0,1         # 16    [c=4 l=4]  xordi3/1
            ret                     # 25    [c=0 l=4]  simple_return
    
    instead (although the SEQZ alias SLTIU against immediate 1 machine
    instruction would equally do and is actually retained at `-O0').  This
    is handled analogously for the remaining synthesized operations of this
    kind, i.e. `SLE', `SGEU', and `SGE'.
    
            gcc/
            * config/riscv/riscv.cc (riscv_emit_int_order_test): Use EQ 0
            rather that XOR 1 for LE and LEU operations.
    
            gcc/testsuite/
            * gcc.target/riscv/sge.c: New test.
            * gcc.target/riscv/sgeu.c: New test.
            * gcc.target/riscv/sle.c: New test.
            * gcc.target/riscv/sleu.c: New test.

Diff:
---
 gcc/config/riscv/riscv.cc             |  4 ++--
 gcc/testsuite/gcc.target/riscv/sge.c  | 12 ++++++++++++
 gcc/testsuite/gcc.target/riscv/sgeu.c | 12 ++++++++++++
 gcc/testsuite/gcc.target/riscv/sle.c  | 12 ++++++++++++
 gcc/testsuite/gcc.target/riscv/sleu.c | 12 ++++++++++++
 5 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 74612a701b0..ab02a81e152 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3004,9 +3004,9 @@ riscv_emit_int_order_test (enum rtx_code code, bool *invert_ptr,
 	}
       else if (invert_ptr == 0)
 	{
-	  rtx inv_target = riscv_force_binary (GET_MODE (target),
+	  rtx inv_target = riscv_force_binary (word_mode,
 					       inv_code, cmp0, cmp1);
-	  riscv_emit_binary (XOR, target, inv_target, const1_rtx);
+	  riscv_emit_binary (EQ, target, inv_target, const0_rtx);
 	}
       else
 	{
diff --git a/gcc/testsuite/gcc.target/riscv/sge.c b/gcc/testsuite/gcc.target/riscv/sge.c
new file mode 100644
index 00000000000..5f7e7ae82db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sge.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target rv64 } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+int
+sge (int x, int y)
+{
+  return x >= y;
+}
+
+/* { dg-final { scan-assembler "\\sxori\\sa0,a0,1\n\\sret\n" } } */
+/* { dg-final { scan-assembler-not "andi|sext\\.w" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sgeu.c b/gcc/testsuite/gcc.target/riscv/sgeu.c
new file mode 100644
index 00000000000..234b9aa52bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sgeu.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target rv64 } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+int
+sgeu (unsigned int x, unsigned int y)
+{
+  return x >= y;
+}
+
+/* { dg-final { scan-assembler "\\sxori\\sa0,a0,1\n\\sret\n" } } */
+/* { dg-final { scan-assembler-not "andi|sext\\.w" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sle.c b/gcc/testsuite/gcc.target/riscv/sle.c
new file mode 100644
index 00000000000..3259c191598
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sle.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target rv64 } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+int
+sle (int x, int y)
+{
+  return x <= y;
+}
+
+/* { dg-final { scan-assembler "\\sxori\\sa0,a0,1\n\\sret\n" } } */
+/* { dg-final { scan-assembler-not "andi|sext\\.w" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sleu.c b/gcc/testsuite/gcc.target/riscv/sleu.c
new file mode 100644
index 00000000000..301b8c32eb7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sleu.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target rv64 } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+int
+sleu (unsigned int x, unsigned int y)
+{
+  return x <= y;
+}
+
+/* { dg-final { scan-assembler "\\sxori\\sa0,a0,1\n\\sret\n" } } */
+/* { dg-final { scan-assembler-not "andi|sext\\.w" } } */

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-11-28 19:37 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-28 19:37 [gcc r13-4376] RISC-V: Avoid redundant sign-extension for SImode SGE, SGEU, SLE, SLEU Maciej W. Rozycki

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).