diff mbox series

Constant fold SS_NEG and SS_ABS in simplify-rtx.c

Message ID 001101d7c337$1db55680$59200380$@nextmovesoftware.com
State New
Headers show
Series Constant fold SS_NEG and SS_ABS in simplify-rtx.c | expand

Commit Message

Roger Sayle Oct. 17, 2021, 9:12 a.m. UTC
This simple patch performs compile-time constant folding of
signed saturating negation and signed saturating absolute value
in the RTL optimizers.  Normally in two's complement arithmetic
the lowest representable signed value overflows on negation,
with these saturating operators they "saturate" to the maximum
representable signed value, so SS_NEG:QI -128 is 127, and
SS_ABS:HI -32768 is 32767.

On bfin-elf, the following two short functions:

short foo()
{
  short t = -32768;
  short r = __builtin_bfin_negate_fr1x16(t);
  return r;
}

int bar()
{
  int t = -2147483648;
  int r = __builtin_bfin_abs_fr1x32(t);
  return r;
}

currently compile to:
_foo:   nop;
        nop;
        R0 = -32768 (X);
        R0 = -R0 (V);
        rts;

_bar:   nop;
        R0 = -1 (X);
        R0 <<= 31;
        R0 = abs R0;
        rts;

but with this middle-end patch now compile to:

_foo:   nop;
        nop;
        nop;
        R0 = 32767 (X);
        rts;

_bar:   nop;
        nop;
        R0 = -1 (X);
        R0.H = 32767;
        rts;


This patch has been tested on x86_64-pc-linux-gnu with "make bootstrap"
and "make -k check" with no new failures.  Ok for mainline?


2021-10-17  Roger Sayle  <roger@nextmovesoftware.com>

gcc/ChangeLog
	* simplify-rtx.c (simplify_const_unary_operation) [SS_NEG, SS_ABS]:
	Evalute SS_NEG and SS_ABS of a constant argument.

gcc/testsuite/ChangeLog
	* gcc.target/bfin/ssabs.c: New test case.
	* gcc.target/bfin/ssneg.c: New test case.


Thanks in advance,
Roger
--

/* { dg-do compile } */
/* { dg-options "-O2" } */

int foo()
{
  int t = -2147483648;
  int r = __builtin_bfin_abs_fr1x32(t);
  return r;
}

/* { dg-final { scan-assembler "32767" } } */
/* { dg-do compile } */
/* { dg-options "-O2" } */

short foo()
{
  short t = -32768;
  short r = __builtin_bfin_negate_fr1x16(t);
  return r;
}

/* { dg-final { scan-assembler "32767" } } */

Comments

Jeff Law Oct. 17, 2021, 4:18 p.m. UTC | #1
On 10/17/2021 3:12 AM, Roger Sayle wrote:
> This simple patch performs compile-time constant folding of
> signed saturating negation and signed saturating absolute value
> in the RTL optimizers.  Normally in two's complement arithmetic
> the lowest representable signed value overflows on negation,
> with these saturating operators they "saturate" to the maximum
> representable signed value, so SS_NEG:QI -128 is 127, and
> SS_ABS:HI -32768 is 32767.
>
> On bfin-elf, the following two short functions:
>
> short foo()
> {
>    short t = -32768;
>    short r = __builtin_bfin_negate_fr1x16(t);
>    return r;
> }
>
> int bar()
> {
>    int t = -2147483648;
>    int r = __builtin_bfin_abs_fr1x32(t);
>    return r;
> }
>
> currently compile to:
> _foo:   nop;
>          nop;
>          R0 = -32768 (X);
>          R0 = -R0 (V);
>          rts;
>
> _bar:   nop;
>          R0 = -1 (X);
>          R0 <<= 31;
>          R0 = abs R0;
>          rts;
>
> but with this middle-end patch now compile to:
>
> _foo:   nop;
>          nop;
>          nop;
>          R0 = 32767 (X);
>          rts;
>
> _bar:   nop;
>          nop;
>          R0 = -1 (X);
>          R0.H = 32767;
>          rts;
>
>
> This patch has been tested on x86_64-pc-linux-gnu with "make bootstrap"
> and "make -k check" with no new failures.  Ok for mainline?
>
>
> 2021-10-17  Roger Sayle  <roger@nextmovesoftware.com>
>
> gcc/ChangeLog
> 	* simplify-rtx.c (simplify_const_unary_operation) [SS_NEG, SS_ABS]:
> 	Evalute SS_NEG and SS_ABS of a constant argument.
>
> gcc/testsuite/ChangeLog
> 	* gcc.target/bfin/ssabs.c: New test case.
> 	* gcc.target/bfin/ssneg.c: New test case.
OK.

Jeff
diff mbox series

Patch

diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index e4fae0b..2bb18fb 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -2026,6 +2026,20 @@  simplify_const_unary_operation (enum rtx_code code, machine_mode mode,
 	  result = wide_int::from (op0, width, SIGNED);
 	  break;
 
+	case SS_NEG:
+	  if (wi::only_sign_bit_p (op0))
+	    result = wi::max_value (GET_MODE_PRECISION (imode), SIGNED);
+	  else
+	    result = wi::neg (op0);
+	  break;
+
+	case SS_ABS:
+	  if (wi::only_sign_bit_p (op0))
+	    result = wi::max_value (GET_MODE_PRECISION (imode), SIGNED);
+	  else
+	    result = wi::abs (op0);
+	  break;
+
 	case SQRT:
 	default:
 	  return 0;