https://gcc.gnu.org/g:5a48079c15fda4863b02eb253e473c57a5105528

commit r15-7268-g5a48079c15fda4863b02eb253e473c57a5105528
Author: Pan Li <pan2...@intel.com>
Date:   Thu Jan 23 14:28:39 2025 +0800

    RISC-V: Fix incorrect code gen for scalar signed SAT_TRUNC [PR117688]
    
    This patch would like to fix the wroing code generation for the scalar
    signed SAT_TRUNC.  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 0xff7f(-129 for HImode) trunc to QImode, we actually
    want compare -129 to -128, but if there is no sign extend like lbu, we will
    compare 0xff7f to 0xffffffffffffff80(assum Xmode is DImode).  Thus, we have
    to sign extend 0xff(Qmode) to 0xffffffffffffff7f(assume Xmode is DImode)
    before compare 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_sstrunc): Leverage the helper
            riscv_extend_to_xmode_reg with SIGN_EXTEND.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/pr117688.h: Add test helper macros.
            * gcc.target/riscv/pr117688-trunc-run-1-s16-to-s8.c: New test.
            * gcc.target/riscv/pr117688-trunc-run-1-s32-to-s16.c: New test.
            * gcc.target/riscv/pr117688-trunc-run-1-s32-to-s8.c: New test.
            * gcc.target/riscv/pr117688-trunc-run-1-s64-to-s16.c: New test.
            * gcc.target/riscv/pr117688-trunc-run-1-s64-to-s32.c: New test.
            * gcc.target/riscv/pr117688-trunc-run-1-s64-to-s8.c: New test.
    
    Signed-off-by: Pan Li <pan2...@intel.com>

Diff:
---
 gcc/config/riscv/riscv.cc                          |  2 +-
 .../riscv/pr117688-trunc-run-1-s16-to-s8.c         |  6 ++++++
 .../riscv/pr117688-trunc-run-1-s32-to-s16.c        |  6 ++++++
 .../riscv/pr117688-trunc-run-1-s32-to-s8.c         |  6 ++++++
 .../riscv/pr117688-trunc-run-1-s64-to-s16.c        |  6 ++++++
 .../riscv/pr117688-trunc-run-1-s64-to-s32.c        |  6 ++++++
 .../riscv/pr117688-trunc-run-1-s64-to-s8.c         |  6 ++++++
 gcc/testsuite/gcc.target/riscv/pr117688.h          | 22 ++++++++++++++++++++++
 8 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 3b042e2817b8..439cc12f93d5 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -13031,7 +13031,7 @@ riscv_expand_sstrunc (rtx dest, rtx src)
   rtx xmode_narrow_min = gen_reg_rtx (Xmode);
   rtx xmode_lt = gen_reg_rtx (Xmode);
   rtx xmode_gt = gen_reg_rtx (Xmode);
-  rtx xmode_src = gen_lowpart (Xmode, src);
+  rtx xmode_src = riscv_extend_to_xmode_reg (src, GET_MODE (src), SIGN_EXTEND);
   rtx xmode_dest = gen_reg_rtx (Xmode);
   rtx xmode_mask = gen_reg_rtx (Xmode);
   rtx xmode_sat = gen_reg_rtx (Xmode);
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s16-to-s8.c 
b/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s16-to-s8.c
new file mode 100644
index 000000000000..df84615a25f9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s16-to-s8.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "pr117688.h"
+
+DEFINE_SIGNED_SAT_TRUNC_RUN(int16_t, int8_t, INT8_MIN, INT8_MAX)
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s32-to-s16.c 
b/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s32-to-s16.c
new file mode 100644
index 000000000000..1b0f860eb55e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s32-to-s16.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "pr117688.h"
+
+DEFINE_SIGNED_SAT_TRUNC_RUN(int32_t, int16_t, INT16_MIN, INT16_MAX)
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s32-to-s8.c 
b/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s32-to-s8.c
new file mode 100644
index 000000000000..e412a29df36a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s32-to-s8.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "pr117688.h"
+
+DEFINE_SIGNED_SAT_TRUNC_RUN(int32_t, int8_t, INT8_MIN, INT8_MAX)
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s64-to-s16.c 
b/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s64-to-s16.c
new file mode 100644
index 000000000000..234d33b18952
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s64-to-s16.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "pr117688.h"
+
+DEFINE_SIGNED_SAT_TRUNC_RUN(int64_t, int16_t, INT16_MIN, INT16_MAX)
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s64-to-s32.c 
b/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s64-to-s32.c
new file mode 100644
index 000000000000..5f9e7f589f05
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s64-to-s32.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "pr117688.h"
+
+DEFINE_SIGNED_SAT_TRUNC_RUN(int64_t, int32_t, INT32_MIN, INT32_MAX)
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s64-to-s8.c 
b/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s64-to-s8.c
new file mode 100644
index 000000000000..aae6be92e675
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr117688-trunc-run-1-s64-to-s8.c
@@ -0,0 +1,6 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "pr117688.h"
+
+DEFINE_SIGNED_SAT_TRUNC_RUN(int64_t, int8_t, INT8_MIN, INT8_MAX)
diff --git a/gcc/testsuite/gcc.target/riscv/pr117688.h 
b/gcc/testsuite/gcc.target/riscv/pr117688.h
index 3b734ce62ed2..7621021016a2 100644
--- a/gcc/testsuite/gcc.target/riscv/pr117688.h
+++ b/gcc/testsuite/gcc.target/riscv/pr117688.h
@@ -45,4 +45,26 @@
     return 0;                                               \
   }
 
+#define DEFINE_SIGNED_SAT_TRUNC_RUN(WT, NT, NT_MIN, NT_MAX) \
+  WT x;                                                     \
+  NT result;                                                \
+                                                            \
+  __attribute__ ((noipa)) void                              \
+  foo ()                                                    \
+  {                                                         \
+    NT trunc = (NT)x;                                       \
+    result = (WT)NT_MIN <= x && x <= (WT)NT_MAX             \
+       ? trunc                                              \
+       : x < 0 ? NT_MIN : NT_MAX;                           \
+  }                                                         \
+                                                            \
+  int main ()                                               \
+  {                                                         \
+    x = (WT)NT_MIN - 1 ;                                    \
+    foo();                                                  \
+    if (result != (NT)NT_MIN)                               \
+      __builtin_abort ();                                   \
+    return 0;                                               \
+  }
+
 #endif

Reply via email to