diff options
author | Pan Li <pan2.li@intel.com> | 2024-08-09 10:26:32 +0800 |
---|---|---|
committer | Pan Li <pan2.li@intel.com> | 2024-08-18 09:26:07 +0800 |
commit | e8f31f4f58f0fcf1716fc1d9ee003fbcdda600c3 (patch) | |
tree | ce500f3a59775b8e79b1772b63f983d7e1b50b09 /gcc | |
parent | 8d0efcf5581abf2560701f4143a0c2ccb261d1f7 (diff) | |
download | gcc-e8f31f4f58f0fcf1716fc1d9ee003fbcdda600c3.zip gcc-e8f31f4f58f0fcf1716fc1d9ee003fbcdda600c3.tar.gz gcc-e8f31f4f58f0fcf1716fc1d9ee003fbcdda600c3.tar.bz2 |
RISC-V: Make sure high bits of usadd operands is clean for non-Xmode [PR116278]
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>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/riscv/riscv.cc | 34 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/pr116278-run-1.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/pr116278-run-2.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/sat_u_add-11.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/sat_u_add-15.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/sat_u_add-19.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/sat_u_add-23.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/sat_u_add-3.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/sat_u_add-7.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/sat_u_add_imm-11.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/sat_u_add_imm-15.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/sat_u_add_imm-3.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/sat_u_add_imm-7.c | 6 |
13 files changed, 112 insertions, 22 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index c387700..f266c45 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -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 index 0000000..d3812bd --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr116278-run-1.c @@ -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 index 0000000..669cd4f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr116278-run-2.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-11.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-11.c index b6dc779..e248aea 100644 --- a/gcc/testsuite/gcc.target/riscv/sat_u_add-11.c +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-11.c @@ -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]+ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-15.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-15.c index 27de543..bb8b991 100644 --- a/gcc/testsuite/gcc.target/riscv/sat_u_add-15.c +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-15.c @@ -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]+ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-19.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-19.c index 4919091..7e4ae12 100644 --- a/gcc/testsuite/gcc.target/riscv/sat_u_add-19.c +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-19.c @@ -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]+ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-23.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-23.c index 3b82bdf..49bbb74 100644 --- a/gcc/testsuite/gcc.target/riscv/sat_u_add-23.c +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-23.c @@ -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]+ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-3.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-3.c index 12347c6..cd15dc9 100644 --- a/gcc/testsuite/gcc.target/riscv/sat_u_add-3.c +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-3.c @@ -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]+ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-7.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-7.c index fe9dcd4..a0b79b1 100644 --- a/gcc/testsuite/gcc.target/riscv/sat_u_add-7.c +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-7.c @@ -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]+ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-11.c b/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-11.c index f30e240..43f34b5 100644 --- a/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-11.c +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-11.c @@ -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]+ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-15.c b/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-15.c index 3918d21..eeea574 100644 --- a/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-15.c +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-15.c @@ -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]+ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-3.c b/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-3.c index 21cc903..6283168 100644 --- a/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-3.c +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-3.c @@ -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]+ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-7.c b/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-7.c index 044b821..9008d2f 100644 --- a/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-7.c +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add_imm-7.c @@ -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]+ |