From: Pan Li <pan2...@intel.com>

This patch would like to fix the wroing code generation for the scalar
signed SAT_SUB.  The input can be QI/HI/SI/DI while the alu like sub
can only work on Xmode, thus we need to make sure the value of input
are well signed-extended at first.  But the gen_lowpart will generate
something like lbu which will perform the zero extended.

The below test suites are passed for this patch.
* The rv64gcv fully regression test.

Note we also notice some refinement like to support const_int for input
or similar issue for ssadd and/or sstruct.  But we would like to fix
it by another patch(es).

        PR target/117688

gcc/ChangeLog:

        * config/riscv/riscv.cc (riscv_gen_sign_extend_rtx): Add new func
        to make sure the op is signed extended to Xmode.
        (riscv_expand_sssub): Leverage above func to perform sign extend
        if not Xmode.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/pr117688-run-1-s16.c: New test.
        * gcc.target/riscv/pr117688-run-1-s32.c: New test.
        * gcc.target/riscv/pr117688-run-1-s8.c: New test.
        * gcc.target/riscv/pr117688.h: New test.

Signed-off-by: Pan Li <pan2...@intel.com>
---
 gcc/config/riscv/riscv.cc                     | 28 +++++++++++++++++--
 .../gcc.target/riscv/pr117688-run-1-s16.c     |  6 ++++
 .../gcc.target/riscv/pr117688-run-1-s32.c     |  6 ++++
 .../gcc.target/riscv/pr117688-run-1-s8.c      |  6 ++++
 gcc/testsuite/gcc.target/riscv/pr117688.h     | 27 ++++++++++++++++++
 5 files changed, 71 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/pr117688-run-1-s16.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/pr117688-run-1-s32.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/pr117688-run-1-s8.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/pr117688.h

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index f5e672bb7f5..e38a246f669 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -12693,6 +12693,30 @@ riscv_gen_zero_extend_rtx (rtx x, machine_mode mode)
   return xmode_reg;
 }
 
+/* Generate a REG rtx of Xmode from the given rtx and mode.
+   The rtx x can be REG (QI/HI/SI/DI).
+   The machine_mode mode is the original mode from define pattern.
+
+   If rtx is REG and Xmode, the RTX x will be returned directly.
+
+   If rtx is REG and non-Xmode, the sign extended to new REG of Xmode will be
+   returned.
+
+   Then the underlying expanding can perform the code generation based on
+   the REG rtx of Xmode, instead of taking care of these in expand func.  */
+
+static rtx
+riscv_gen_sign_extend_rtx (rtx x, machine_mode mode)
+{
+  if (mode == Xmode)
+    return x;
+
+  rtx xmode_reg = gen_reg_rtx (Xmode);
+  riscv_emit_unary (SIGN_EXTEND, xmode_reg, x);
+
+  return xmode_reg;
+}
+
 /* Implements the unsigned saturation add standard name usadd for int mode.
 
    z = SAT_ADD(x, y).
@@ -12892,8 +12916,8 @@ riscv_expand_sssub (rtx dest, rtx x, rtx y)
   machine_mode mode = GET_MODE (dest);
   unsigned bitsize = GET_MODE_BITSIZE (mode).to_constant ();
   rtx shift_bits = GEN_INT (bitsize - 1);
-  rtx xmode_x = gen_lowpart (Xmode, x);
-  rtx xmode_y = gen_lowpart (Xmode, y);
+  rtx xmode_x = riscv_gen_sign_extend_rtx (x, mode);
+  rtx xmode_y = riscv_gen_sign_extend_rtx (y, mode);
   rtx xmode_minus = gen_reg_rtx (Xmode);
   rtx xmode_xor_0 = gen_reg_rtx (Xmode);
   rtx xmode_xor_1 = gen_reg_rtx (Xmode);
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688-run-1-s16.c 
b/gcc/testsuite/gcc.target/riscv/pr117688-run-1-s16.c
new file mode 100644
index 00000000000..b63f00e100b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688-run-1-s16.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "pr117688.h"
+
+DEFINE_PR117688_RUN(int16_t, INT16_MIN, INT16_MAX)
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688-run-1-s32.c 
b/gcc/testsuite/gcc.target/riscv/pr117688-run-1-s32.c
new file mode 100644
index 00000000000..852285aa882
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688-run-1-s32.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "pr117688.h"
+
+DEFINE_PR117688_RUN(int32_t, INT32_MIN, INT32_MAX)
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688-run-1-s8.c 
b/gcc/testsuite/gcc.target/riscv/pr117688-run-1-s8.c
new file mode 100644
index 00000000000..1e4914ebc40
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688-run-1-s8.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "pr117688.h"
+
+DEFINE_PR117688_RUN(int8_t, INT8_MIN, INT8_MAX)
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688.h 
b/gcc/testsuite/gcc.target/riscv/pr117688.h
new file mode 100644
index 00000000000..97c67837ebf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688.h
@@ -0,0 +1,27 @@
+#ifndef HAVE_DEFINED_PR117688_H
+#define HAVE_DEFINED_PR117688_H
+
+#include <stdint.h>
+
+#define DEFINE_PR117688_RUN(T, MIN, MAX)                    \
+  T x, y, result;                                           \
+                                                            \
+  __attribute__ ((noipa)) void                              \
+  foo ()                                                    \
+  {                                                         \
+    T minus;                                                \
+    _Bool overflow = __builtin_sub_overflow (x, y, &minus); \
+    result = overflow ? (x < 0 ? MIN : MAX) : minus;        \
+  }                                                         \
+                                                            \
+  int main ()                                               \
+  {                                                         \
+    x = MIN;                                                \
+    y = 0x1;                                                \
+    foo();                                                  \
+    if (result != (T)MIN)                                   \
+      __builtin_abort ();                                   \
+    return 0;                                               \
+  }
+
+#endif
-- 
2.43.0

Reply via email to