public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-4690] Constant fold/simplify SS_ASHIFT and US_ASHIFT in simplify-rtx.c
@ 2021-10-25 15:18 Roger Sayle
  0 siblings, 0 replies; only message in thread
From: Roger Sayle @ 2021-10-25 15:18 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:c49f389e3dee9f00ffc74de6a8770cd55dc12880

commit r12-4690-gc49f389e3dee9f00ffc74de6a8770cd55dc12880
Author: Roger Sayle <roger@nextmovesoftware.com>
Date:   Mon Oct 25 16:16:11 2021 +0100

    Constant fold/simplify SS_ASHIFT and US_ASHIFT in simplify-rtx.c
    
    This patch adds compile-time evaluation of signed saturating left shift
    (SS_ASHIFT) and unsigned saturating left shift (US_ASHIFT) to simplify-rtx's
    simplify_const_binary_operation.  US_ASHIFT saturates to the maximum
    unsigned value on overflow (which occurs when the shift is greater than
    the leading zero count), while SS_ASHIFT saturates on overflow to the
    maximum signed value for positive arguments, and the minimum signed value
    for negative arguments (which occurs when the shift count is greater than
    the number of leading redundant sign bits, clrsb).  This suggests
    some additional simplifications that this patch implements in
    simplify_binary_operation_1; us_ashift:HI of 0xffff remains 0xffff
    (much like any ashift of 0x0000 remains 0x0000), and ss_ashift:HI of
    0x7fff remains 0x7ffff, and of 0x8000 remains 0x8000.
    
    Conveniently the bfin backend provides instructions/built-ins that allow
    this functionality to be tested.  The two functions below
    
    short stest_sat_max() { return __builtin_bfin_shl_fr1x16(10000,8); }
    short stest_sat_min() { return __builtin_bfin_shl_fr1x16(-10000,8); }
    
    previously on bfin-elf with -O2 generated:
    
    _stest_sat_max:
            nop;
            nop;
            R0 = 10000 (X);
            R0 = R0 << 8 (V,S);
            rts;
    
    _stest_sat_min:
            nop;
            nop;
            R0 = -10000 (X);
            R0 = R0 << 8 (V,S);
            rts;
    
    With this patch, bfin-elf now generates:
    
    _stest_sat_max:
            nop;
            nop;
            nop;
            R0 = 32767 (X);
            rts;
    
    _stest_sat_min:
            nop;
            nop;
            nop;
            R0 = -32768 (X);
            rts;
    
    2021-10-25  Roger Sayle  <roger@nextmovesoftware.com>
    
    gcc/ChangeLog
            * simplify-rtx.c (simplify_binary_operation_1) [SS_ASHIFT]: Simplify
            shifts of the mode's smin_value and smax_value when the bit count
            operand doesn't have side-effects.
            [US_ASHIFT]: Likewise, simplify shifts of the mode's umax_value
            when the bit count operand doesn't have side-effects.
            (simplify_const_binary_operation) [SS_ASHIFT, US_ASHIFT]: Perform
            compile-time evaluation of saturating left shifts with constant
            arguments.
    
    gcc/testsuite/ChangeLog
            * gcc.target/bfin/ssashift-1.c: New test case.

Diff:
---
 gcc/simplify-rtx.c                         | 38 +++++++++++++++++++++-
 gcc/testsuite/gcc.target/bfin/ssashift-1.c | 52 ++++++++++++++++++++++++++++++
 2 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 2bb18fb5065..bbbd6b74942 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -4064,9 +4064,25 @@ simplify_context::simplify_binary_operation_1 (rtx_code code,
 	}
       break;
 
-    case ASHIFT:
     case SS_ASHIFT:
+      if (CONST_INT_P (trueop0)
+	  && HWI_COMPUTABLE_MODE_P (mode)
+	  && (UINTVAL (trueop0) == (GET_MODE_MASK (mode) >> 1)
+	      || mode_signbit_p (mode, trueop0))
+	  && ! side_effects_p (op1))
+	return op0;
+      goto simplify_ashift;
+
     case US_ASHIFT:
+      if (CONST_INT_P (trueop0)
+	  && HWI_COMPUTABLE_MODE_P (mode)
+	  && UINTVAL (trueop0) == GET_MODE_MASK (mode)
+	  && ! side_effects_p (op1))
+	return op0;
+      /* FALLTHRU */
+
+    case ASHIFT:
+simplify_ashift:
       if (trueop1 == CONST0_RTX (mode))
 	return op0;
       if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1))
@@ -5004,6 +5020,8 @@ simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
 	case LSHIFTRT:
 	case ASHIFTRT:
 	case ASHIFT:
+	case SS_ASHIFT:
+	case US_ASHIFT:
 	  {
 	    wide_int wop1 = pop1;
 	    if (SHIFT_COUNT_TRUNCATED)
@@ -5025,6 +5043,24 @@ simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
 		result = wi::lshift (pop0, wop1);
 		break;
 
+	      case SS_ASHIFT:
+		if (wi::leu_p (wop1, wi::clrsb (pop0)))
+		  result = wi::lshift (pop0, wop1);
+		else if (wi::neg_p (pop0))
+		  result = wi::min_value (int_mode, SIGNED);
+		else
+		  result = wi::max_value (int_mode, SIGNED);
+		break;
+
+	      case US_ASHIFT:
+		if (wi::eq_p (pop0, 0))
+		  result = pop0;
+		else if (wi::leu_p (wop1, wi::clz (pop0)))
+		  result = wi::lshift (pop0, wop1);
+		else
+		  result = wi::max_value (int_mode, UNSIGNED);
+		break;
+
 	      default:
 		gcc_unreachable ();
 	      }
diff --git a/gcc/testsuite/gcc.target/bfin/ssashift-1.c b/gcc/testsuite/gcc.target/bfin/ssashift-1.c
new file mode 100644
index 00000000000..aba90a68f0b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bfin/ssashift-1.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int test_ok_pos()
+{
+  int x = 100;
+  return __builtin_bfin_shl_fr1x32(x,24);
+}
+
+int test_ok_neg()
+{
+  int x = -100;
+  return __builtin_bfin_shl_fr1x32(x,24);
+}
+
+int test_sat_max()
+{
+  int x = 10000;
+  return __builtin_bfin_shl_fr1x32(x,24);
+}
+
+int test_sat_min()
+{
+  int x = -10000;
+  return __builtin_bfin_shl_fr1x32(x,24);
+}
+
+short stest_ok_pos()
+{
+  short x = 100;
+  return __builtin_bfin_shl_fr1x16(x,8);
+}
+
+short stest_ok_neg()
+{
+  short x = -100;
+  return __builtin_bfin_shl_fr1x16(x,8);
+}
+
+short stest_sat_max()
+{
+  short x = 10000;
+  return __builtin_bfin_shl_fr1x16(x,8);
+}
+
+short stest_sat_min()
+{
+  short x = -10000;
+  return __builtin_bfin_shl_fr1x16(x,8);
+}
+/* { dg-final { scan-assembler-not "\\(S\\)" } } */
+/* { dg-final { scan-assembler-not "\\(V,S\\)" } } */


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-10-25 15:18 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-25 15:18 [gcc r12-4690] Constant fold/simplify SS_ASHIFT and US_ASHIFT in simplify-rtx.c Roger Sayle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).