https://gcc.gnu.org/g:81aa9488321dea5ed1d55d0dfb1a72f362a1a24f

commit r15-7266-g81aa9488321dea5ed1d55d0dfb1a72f362a1a24f
Author: Pan Li <pan2...@intel.com>
Date:   Thu Jan 23 12:08:17 2025 +0800

    RISC-V: Fix incorrect code gen for scalar signed SAT_ADD [PR117688]
    
    This patch would like to fix the wroing code generation for the scalar
    signed SAT_ADD.  The input can be QI/HI/SI/DI while the alu like sub
    can only work on Xmode.  Unfortunately we don't have sub/add for
    non-Xmode like QImode in scalar, thus we need to sign extend to Xmode
    to ensure we have the correct value before ALU like add.  The gen_lowpart
    will generate something like lbu which has all zero for highest bits.
    
    For example, when 0xff(-1 for QImode) plus 0x2(1 for QImode), we actually
    want to -1 + 2 = 1, but if there is no sign extend like lbu, we will get
    0xff + 2 = 0x101 which is incorrect.  Thus, we have to sign extend 
0xff(Qmode)
    to 0xffffffffffffffff(assume XImode is DImode) before plus in Xmode.
    
    The below test suites are passed for this patch.
    * The rv64gcv fully regression test.
    
            PR target/117688
    
    gcc/ChangeLog:
    
            * config/riscv/riscv.cc (riscv_expand_ssadd): Leverage the helper
            riscv_extend_to_xmode_reg with SIGN_EXTEND.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/pr117688-add-run-1-s16.c: New test.
            * gcc.target/riscv/pr117688-add-run-1-s32.c: New test.
            * gcc.target/riscv/pr117688-add-run-1-s64.c: New test.
            * gcc.target/riscv/pr117688-add-run-1-s8.c: New test.
            * gcc.target/riscv/pr117688.h: New test.
    
    Signed-off-by: Pan Li <pan2...@intel.com>

Diff:
---
 gcc/config/riscv/riscv.cc                          |  4 ++--
 .../gcc.target/riscv/pr117688-add-run-1-s16.c      |  6 +++++
 .../gcc.target/riscv/pr117688-add-run-1-s32.c      |  6 +++++
 .../gcc.target/riscv/pr117688-add-run-1-s64.c      |  6 +++++
 .../gcc.target/riscv/pr117688-add-run-1-s8.c       |  6 +++++
 gcc/testsuite/gcc.target/riscv/pr117688.h          | 27 ++++++++++++++++++++++
 6 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 5ee53d01f51f..8ea31846e879 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -12816,8 +12816,8 @@ riscv_expand_ssadd (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_extend_to_xmode_reg (x, mode, SIGN_EXTEND);
+  rtx xmode_y = riscv_extend_to_xmode_reg (y, mode, SIGN_EXTEND);
   rtx xmode_sum = gen_reg_rtx (Xmode);
   rtx xmode_dest = gen_reg_rtx (Xmode);
   rtx xmode_xor_0 = gen_reg_rtx (Xmode);
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688-add-run-1-s16.c 
b/gcc/testsuite/gcc.target/riscv/pr117688-add-run-1-s16.c
new file mode 100644
index 000000000000..21ec107cbf10
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688-add-run-1-s16.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "pr117688.h"
+
+DEFINE_SIGNED_SAT_ADD_RUN(int16_t, INT16_MIN, INT16_MAX)
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688-add-run-1-s32.c 
b/gcc/testsuite/gcc.target/riscv/pr117688-add-run-1-s32.c
new file mode 100644
index 000000000000..1f197d1280b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688-add-run-1-s32.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "pr117688.h"
+
+DEFINE_SIGNED_SAT_ADD_RUN(int32_t, INT32_MIN, INT32_MAX)
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688-add-run-1-s64.c 
b/gcc/testsuite/gcc.target/riscv/pr117688-add-run-1-s64.c
new file mode 100644
index 000000000000..4903bc854d34
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688-add-run-1-s64.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "pr117688.h"
+
+DEFINE_SIGNED_SAT_ADD_RUN(int64_t, INT64_MIN, INT64_MAX)
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688-add-run-1-s8.c 
b/gcc/testsuite/gcc.target/riscv/pr117688-add-run-1-s8.c
new file mode 100644
index 000000000000..a9f2fe7f1920
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688-add-run-1-s8.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "pr117688.h"
+
+DEFINE_SIGNED_SAT_ADD_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 000000000000..1013a8a80128
--- /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_SIGNED_SAT_ADD_RUN(T, MIN, MAX)            \
+  T x, y, result;                                         \
+                                                          \
+  __attribute__ ((noipa)) void                            \
+  foo ()                                                  \
+  {                                                       \
+    T sum;                                                \
+    _Bool overflow = __builtin_add_overflow (x, y, &sum); \
+    result = overflow ? (x < 0 ? MIN : MAX) : sum;        \
+  }                                                       \
+                                                          \
+  int main ()                                             \
+  {                                                       \
+    x = MIN;                                              \
+    y = -0x1;                                             \
+    foo();                                                \
+    if (result != (T)MIN)                                 \
+      __builtin_abort ();                                 \
+    return 0;                                             \
+  }
+
+#endif

Reply via email to