From 94dff03f67fad1f9c526bb915bb21a4deb19d638 Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Mon, 18 Oct 2021 11:51:07 +0100 Subject: [PATCH] Constant fold SS_NEG and SS_ABS in simplify-rtx.c 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; 2021-10-18 Roger Sayle 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. --- gcc/simplify-rtx.c | 14 ++++++++++++++ gcc/testsuite/gcc.target/bfin/ssabs.c | 11 +++++++++++ gcc/testsuite/gcc.target/bfin/ssneg.c | 11 +++++++++++ 3 files changed, 36 insertions(+) create mode 100644 gcc/testsuite/gcc.target/bfin/ssabs.c create mode 100644 gcc/testsuite/gcc.target/bfin/ssneg.c diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index e4fae0b3e57f..2bb18fb50654 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; diff --git a/gcc/testsuite/gcc.target/bfin/ssabs.c b/gcc/testsuite/gcc.target/bfin/ssabs.c new file mode 100644 index 000000000000..e9d8bae62fdb --- /dev/null +++ b/gcc/testsuite/gcc.target/bfin/ssabs.c @@ -0,0 +1,11 @@ +/* { 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" } } */ diff --git a/gcc/testsuite/gcc.target/bfin/ssneg.c b/gcc/testsuite/gcc.target/bfin/ssneg.c new file mode 100644 index 000000000000..44ad7edbba46 --- /dev/null +++ b/gcc/testsuite/gcc.target/bfin/ssneg.c @@ -0,0 +1,11 @@ +/* { 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" } } */ -- 2.47.3