]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Make sure high bits of usadd operands is clean for non-Xmode [PR116278]
authorPan Li <pan2.li@intel.com>
Fri, 9 Aug 2024 02:26:32 +0000 (10:26 +0800)
committerPan Li <pan2.li@intel.com>
Sun, 18 Aug 2024 01:26:07 +0000 (09:26 +0800)
For QI/HImode of .SAT_ADD,  the operands may be sign-extended and the
high bits of Xmode may be all 1 which is not expected.  For example as
below code.

signed char b[1];
unsigned short c;
signed char *d = b;
int main() {
  b[0] = -40;
  c = ({ (unsigned short)d[0] < 0xFFF6 ? (unsigned short)d[0] : 0xFFF6; }) + 9;
  __builtin_printf("%d\n", c);
}

After expanding we have:

;; _6 = .SAT_ADD (_3, 9);
(insn 8 7 9 (set (reg:DI 143)
        (high:DI (symbol_ref:DI ("d") [flags 0x86]  <var_decl d>)))
     (nil))
(insn 9 8 10 (set (reg/f:DI 142)
        (mem/f/c:DI (lo_sum:DI (reg:DI 143)
                (symbol_ref:DI ("d") [flags 0x86]  <var_decl d>)) [1 d+0 S8 A64]))
     (nil))
(insn 10 9 11 (set (reg:HI 144 [ _3 ])
        (sign_extend:HI (mem:QI (reg/f:DI 142) [0 *d.0_1+0 S1 A8]))) "test.c":7:10 -1
     (nil))

The convert from signed char to unsigned short will have sign_extend rtl
as above.  And finally become the lb insn as below:

lb      a1,0(a5)   // a1 is -40, aka 0xffffffffffffffd8
lui     a0,0x1a
addi    a5,a1,9
slli    a5,a5,0x30
srli    a5,a5,0x30 // a5 is 65505
sltu    a1,a5,a1   // compare 65505 and 0xffffffffffffffd8 => TRUE

The sltu try to compare 65505 and 0xffffffffffffffd8 here,  but we
actually want to compare 65505 and 65496 (0xffd8).  Thus we need to
clean up the high bits to ensure this.

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

PR target/116278

gcc/ChangeLog:

* config/riscv/riscv.cc (riscv_gen_zero_extend_rtx): Add new
func impl to zero extend rtx.
(riscv_expand_usadd): Leverage above func to cleanup operands 0
and remove the special handing for SImode in RV64.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/sat_u_add-11.c: Adjust asm check body.
* gcc.target/riscv/sat_u_add-15.c: Ditto.
* gcc.target/riscv/sat_u_add-19.c: Ditto.
* gcc.target/riscv/sat_u_add-23.c: Ditto.
* gcc.target/riscv/sat_u_add-3.c: Ditto.
* gcc.target/riscv/sat_u_add-7.c: Ditto.
* gcc.target/riscv/sat_u_add_imm-11.c: Ditto.
* gcc.target/riscv/sat_u_add_imm-15.c: Ditto.
* gcc.target/riscv/sat_u_add_imm-3.c: Ditto.
* gcc.target/riscv/sat_u_add_imm-7.c: Ditto.
* gcc.target/riscv/pr116278-run-1.c: New test.
* gcc.target/riscv/pr116278-run-2.c: New test.

Signed-off-by: Pan Li <pan2.li@intel.com>
13 files changed:
gcc/config/riscv/riscv.cc
gcc/testsuite/gcc.target/riscv/pr116278-run-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/pr116278-run-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/sat_u_add-11.c
gcc/testsuite/gcc.target/riscv/sat_u_add-15.c
gcc/testsuite/gcc.target/riscv/sat_u_add-19.c
gcc/testsuite/gcc.target/riscv/sat_u_add-23.c
gcc/testsuite/gcc.target/riscv/sat_u_add-3.c
gcc/testsuite/gcc.target/riscv/sat_u_add-7.c
gcc/testsuite/gcc.target/riscv/sat_u_add_imm-11.c
gcc/testsuite/gcc.target/riscv/sat_u_add_imm-15.c
gcc/testsuite/gcc.target/riscv/sat_u_add_imm-3.c
gcc/testsuite/gcc.target/riscv/sat_u_add_imm-7.c

index c3877008d05c882406abee777a23901d1ee71938..f266c45ed4d9c5c7723335bc10ddb8c37326dca4 100644 (file)
@@ -11828,12 +11828,29 @@ riscv_get_raw_result_mode (int regno)
   return default_get_reg_raw_mode (regno);
 }
 
+/* Generate a new rtx of Xmode based on the rtx and mode in define pattern.
+   The rtx x will be zero extended to Xmode if the mode is HI/QImode,  and
+   the new zero extended Xmode rtx will be returned.
+   Or the gen_lowpart rtx of Xmode will be returned.  */
+
+static rtx
+riscv_gen_zero_extend_rtx (rtx x, machine_mode mode)
+{
+  if (mode == Xmode)
+    return x;
+
+  rtx xmode_reg = gen_reg_rtx (Xmode);
+  riscv_emit_unary (ZERO_EXTEND, xmode_reg, x);
+
+  return xmode_reg;
+}
+
 /* Implements the unsigned saturation add standard name usadd for int mode.
 
    z = SAT_ADD(x, y).
    =>
    1. sum = x + y.
-   2. sum = truncate (sum) for QI and HI only.
+   2. sum = truncate (sum) for non-Xmode.
    3. lt = sum < x.
    4. lt = -lt.
    5. z = sum | lt.  */
@@ -11844,22 +11861,15 @@ riscv_expand_usadd (rtx dest, rtx x, rtx y)
   machine_mode mode = GET_MODE (dest);
   rtx xmode_sum = gen_reg_rtx (Xmode);
   rtx xmode_lt = gen_reg_rtx (Xmode);
-  rtx xmode_x = gen_lowpart (Xmode, x);
+  rtx xmode_x = riscv_gen_zero_extend_rtx (x, mode);
   rtx xmode_y = gen_lowpart (Xmode, y);
   rtx xmode_dest = gen_reg_rtx (Xmode);
 
   /* Step-1: sum = x + y  */
-  if (mode == SImode && mode != Xmode)
-    { /* Take addw to avoid the sum truncate.  */
-      rtx simode_sum = gen_reg_rtx (SImode);
-      riscv_emit_binary (PLUS, simode_sum, x, y);
-      emit_move_insn (xmode_sum, gen_lowpart (Xmode, simode_sum));
-    }
-  else
-    riscv_emit_binary (PLUS, xmode_sum, xmode_x, xmode_y);
+  riscv_emit_binary (PLUS, xmode_sum, xmode_x, xmode_y);
 
-  /* Step-1.1: truncate sum for HI and QI as we have no insn for add QI/HI.  */
-  if (mode == HImode || mode == QImode)
+  /* Step-1.1: truncate sum for non-Xmode for overflow check.  */
+  if (mode != Xmode)
     {
       int shift_bits = GET_MODE_BITSIZE (Xmode)
        - GET_MODE_BITSIZE (mode).to_constant ();
diff --git a/gcc/testsuite/gcc.target/riscv/pr116278-run-1.c b/gcc/testsuite/gcc.target/riscv/pr116278-run-1.c
new file mode 100644 (file)
index 0000000..d3812bd
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-options "-O2 -fdump-rtl-expand-details" } */
+
+#include <stdint-gcc.h>
+
+int8_t b[1];
+int8_t *d = b;
+int32_t c;
+
+int main() {
+  b[0] = -40;
+  uint16_t t = (uint16_t)d[0];
+
+  c = (t < 0xFFF6 ? t : 0xFFF6) + 9;
+
+  if (c != 65505)
+    __builtin_abort ();
+}
+
+/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/pr116278-run-2.c b/gcc/testsuite/gcc.target/riscv/pr116278-run-2.c
new file mode 100644 (file)
index 0000000..669cd4f
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-options "-O2 -fdump-rtl-expand-details" } */
+
+#include <stdint-gcc.h>
+
+int16_t b[1];
+int16_t *d = b;
+int64_t c;
+
+int main() {
+  b[0] = -40;
+  uint32_t t = (uint32_t)d[0];
+
+  c = (t < 0xFFFFFFF6u ? t : 0xFFFFFFF6u) + 9;
+
+  if (c != 4294967265)
+    __builtin_abort ();
+}
+
+/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */
index b6dc779b212ae89ec56edfeecbea7372e0696c55..e248aeafa8ef9a9c5db6dd56a687b3cda010f98e 100644 (file)
@@ -6,7 +6,11 @@
 
 /*
 ** sat_u_add_uint32_t_fmt_3:
-** addw\s+[atx][0-9]+,\s*a0,\s*a1
+** slli\s+[atx][0-9]+,\s*a0,\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
+** add\s+[atx][0-9]+,\s*a0,\s*a1
+** slli\s+[atx][0-9]+,\s*[atx][0-9],\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
 ** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
 ** neg\s+[atx][0-9]+,\s*[atx][0-9]+
 ** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
index 27de543159dd638b7282a3cd442b6286dfff3e86..bb8b991a84eeba87eee0e6d72e65c1f735ae2225 100644 (file)
@@ -6,7 +6,11 @@
 
 /*
 ** sat_u_add_uint32_t_fmt_4:
-** addw\s+[atx][0-9]+,\s*a0,\s*a1
+** slli\s+[atx][0-9]+,\s*a0,\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
+** add\s+[atx][0-9]+,\s*a0,\s*a1
+** slli\s+[atx][0-9]+,\s*[atx][0-9],\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
 ** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
 ** neg\s+[atx][0-9]+,\s*[atx][0-9]+
 ** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
index 491909165dc94ccff32ceb672412fe82994e9681..7e4ae12f2f511e9993d098373183b2ddd261eaaa 100644 (file)
@@ -6,7 +6,11 @@
 
 /*
 ** sat_u_add_uint32_t_fmt_5:
-** addw\s+[atx][0-9]+,\s*a0,\s*a1
+** slli\s+[atx][0-9]+,\s*a0,\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
+** add\s+[atx][0-9]+,\s*a0,\s*a1
+** slli\s+[atx][0-9]+,\s*[atx][0-9],\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
 ** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
 ** neg\s+[atx][0-9]+,\s*[atx][0-9]+
 ** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
index 3b82bdffb59b1e8dd8e260c4f4f1a3932d071d6a..49bbb74a401e07387968f452eed833b6d17053c1 100644 (file)
@@ -6,7 +6,11 @@
 
 /*
 ** sat_u_add_uint32_t_fmt_6:
-** addw\s+[atx][0-9]+,\s*a0,\s*a1
+** slli\s+[atx][0-9]+,\s*a0,\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
+** add\s+[atx][0-9]+,\s*a0,\s*a1
+** slli\s+[atx][0-9]+,\s*[atx][0-9],\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
 ** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
 ** neg\s+[atx][0-9]+,\s*[atx][0-9]+
 ** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
index 12347c607bd4ae5ae46fed2a539cbfcd683b7aa7..cd15dc964503435c764edf1878f187c000bcd6ed 100644 (file)
@@ -6,7 +6,11 @@
 
 /*
 ** sat_u_add_uint32_t_fmt_1:
-** addw\s+[atx][0-9]+,\s*a0,\s*a1
+** slli\s+[atx][0-9]+,\s*a0,\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
+** add\s+[atx][0-9]+,\s*a0,\s*a1
+** slli\s+[atx][0-9]+,\s*[atx][0-9],\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
 ** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
 ** neg\s+[atx][0-9]+,\s*[atx][0-9]+
 ** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
index fe9dcd4f8065071d3520fea8393d8ca1ed08c779..a0b79b15ac4a8711ed00185144419ba2fe3e29a1 100644 (file)
@@ -6,7 +6,11 @@
 
 /*
 ** sat_u_add_uint32_t_fmt_2:
-** addw\s+[atx][0-9]+,\s*a0,\s*a1
+** slli\s+[atx][0-9]+,\s*a0,\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
+** add\s+[atx][0-9]+,\s*a0,\s*a1
+** slli\s+[atx][0-9]+,\s*[atx][0-9],\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
 ** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
 ** neg\s+[atx][0-9]+,\s*[atx][0-9]+
 ** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
index f30e2405a0d0389301702f0c93ab4dc6a4aac2b6..43f34b5f3c98bcd3d85c9d5d365c7400e0b9e556 100644 (file)
@@ -6,7 +6,11 @@
 
 /*
 ** sat_u_add_imm7_uint32_t_fmt_3:
-** addiw\s+[atx][0-9]+,\s*a0,\s*7
+** slli\s+[atx][0-9]+,\s*a0,\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
+** addi\s+[atx][0-9]+,\s*a0,\s*7
+** slli\s+[atx][0-9]+,\s*[atx][0-9],\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
 ** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
 ** neg\s+[atx][0-9]+,\s*[atx][0-9]+
 ** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
index 3918d215658430408e40ededf5f7c25e9e969fae..eeea574bba223a0abb8965d75223d96596c09bb2 100644 (file)
@@ -6,7 +6,11 @@
 
 /*
 ** sat_u_add_imm7_uint32_t_fmt_4:
-** addiw\s+[atx][0-9]+,\s*a0,\s*7
+** slli\s+[atx][0-9]+,\s*a0,\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
+** addi\s+[atx][0-9]+,\s*a0,\s*7
+** slli\s+[atx][0-9]+,\s*[atx][0-9],\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
 ** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
 ** neg\s+[atx][0-9]+,\s*[atx][0-9]+
 ** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
index 21cc903c78eca924e2a1876b6d50db2a7c6979a5..6283168b46d4a9284f32646bc0831662fcef4913 100644 (file)
@@ -6,7 +6,11 @@
 
 /*
 ** sat_u_add_imm7_uint32_t_fmt_1:
-** addiw\s+[atx][0-9]+,\s*a0,\s*7
+** slli\s+[atx][0-9]+,\s*a0,\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
+** addi\s+[atx][0-9]+,\s*a0,\s*7
+** slli\s+[atx][0-9]+,\s*[atx][0-9],\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
 ** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
 ** neg\s+[atx][0-9]+,\s*[atx][0-9]+
 ** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
index 044b821f7b5d6db72140a93cacbcee49c56c9c54..9008d2f946a56787d0901240d9e410ee503c6a4a 100644 (file)
@@ -6,7 +6,11 @@
 
 /*
 ** sat_u_add_imm7_uint32_t_fmt_2:
-** addiw\s+[atx][0-9]+,\s*a0,\s*7
+** slli\s+[atx][0-9]+,\s*a0,\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
+** addi\s+[atx][0-9]+,\s*a0,\s*7
+** slli\s+[atx][0-9]+,\s*[atx][0-9],\s*32
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*32
 ** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
 ** neg\s+[atx][0-9]+,\s*[atx][0-9]+
 ** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+