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