[COMMITTED] tree-optimization/102738 - Simplification for right shift.

Message ID 3182839e-32e7-dde6-c896-1b4400afda09@redhat.com
State Committed
Headers
Series [COMMITTED] tree-optimization/102738 - Simplification for right shift. |

Commit Message

Andrew MacLeod Oct. 14, 2021, 6:02 p.m. UTC
  As the PR observes, if the first operand of a right shift is 0 or -1, 
operand 2 doesn't matter and the result will be the same as op1, so it 
can be turned into a copy.

This patch checks for that condition and performs the operation in EVRP.

Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed.

Andrew
  

Comments

H.J. Lu Oct. 14, 2021, 11:42 p.m. UTC | #1
On Thu, Oct 14, 2021 at 11:06 AM Andrew MacLeod via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> As the PR observes, if the first operand of a right shift is 0 or -1,
> operand 2 doesn't matter and the result will be the same as op1, so it
> can be turned into a copy.
>
> This patch checks for that condition and performs the operation in EVRP.
>
> Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed.
>
> Andrew
>

/* PR tree-optimization/102738 */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+/* Remove arithmetic shift right when the LHS is known to be 0 or -1.  */
+
+int a1(__int128 f, int g)

Missing

/* { dg-do compile { target int128 } } */
  
Andrew MacLeod Oct. 15, 2021, 12:35 a.m. UTC | #2
On 10/14/21 7:42 PM, H.J. Lu wrote:
> On Thu, Oct 14, 2021 at 11:06 AM Andrew MacLeod via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
>> As the PR observes, if the first operand of a right shift is 0 or -1,
>> operand 2 doesn't matter and the result will be the same as op1, so it
>> can be turned into a copy.
>>
>> This patch checks for that condition and performs the operation in EVRP.
>>
>> Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed.
>>
>> Andrew
>>
> /* PR tree-optimization/102738 */
> +/* { dg-options "-O2 -fdump-tree-evrp" } */
> +
> +/* Remove arithmetic shift right when the LHS is known to be 0 or -1.  */
> +
> +int a1(__int128 f, int g)
>
> Missing
>
> /* { dg-do compile { target int128 } } */
>
>
Thanks..   Done.    Feel free to bypass me :-)

Andrew
  

Patch

commit f0b7d4cc49ddb1c2c7474cc3f61e260aa93a96c0
Author: Andrew MacLeod <amacleod@redhat.com>
Date:   Thu Oct 14 10:43:58 2021 -0400

    Simplification for right shift.
    
    When the first operand of a signed right shift is zero or negative one, the
    RHS doesn't matter and the shift can be converted to a copy.
    
            PR tree-optimization/102738
            gcc/
            * vr-values.c (simplify_using_ranges::simplify): Handle RSHIFT_EXPR.
    
            gcc/testsuite
            * gcc.dg/pr102738.c: New.

diff --git a/gcc/testsuite/gcc.dg/pr102738.c b/gcc/testsuite/gcc.dg/pr102738.c
new file mode 100644
index 00000000000..776fcecb27a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr102738.c
@@ -0,0 +1,48 @@ 
+/* PR tree-optimization/102738 */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+/* Remove arithmetic shift right when the LHS is known to be 0 or -1.  */
+
+int a1(__int128 f, int g)
+{
+     /* Leaves f >> 127.  */
+    return (f >> 127) >> g;
+}
+
+int a2(int f, int g)
+{
+     /* Leaves f >> 31.  */
+    return (f >> 31) >> g;
+}
+
+int a3(int f, int g)
+{
+    if (f == 0 || f == -1)
+      return f >> g;
+    __builtin_unreachable();
+}
+
+int a4(int f, int g)
+{
+    if (f == 0 || f == 1)
+      return (-f) >> g;
+    __builtin_unreachable();
+}
+
+int a5(int f, int g)
+{
+    if (f == 0 || f == 1)
+      return (f-1) >> g;
+    return 0;
+}
+
+int a6(int f, int g)
+{
+    if (f == 6 || f == 7)
+      return (f-7) >> g;
+    __builtin_unreachable();
+}
+
+/* { dg-final { scan-tree-dump-times " >> 127" 1 "evrp" } } */
+/* { dg-final { scan-tree-dump-times " >> 31" 1 "evrp" } } */
+/* { dg-final { scan-tree-dump-times " >> " 2 "evrp" } } */
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 9bf58f416f2..d0f7cb41bc8 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -4281,6 +4281,28 @@  simplify_using_ranges::simplify (gimple_stmt_iterator *gsi)
 	case MAX_EXPR:
 	  return simplify_min_or_max_using_ranges (gsi, stmt);
 
+	case RSHIFT_EXPR:
+	  {
+	    tree op0 = gimple_assign_rhs1 (stmt);
+	    tree type = TREE_TYPE (op0);
+	    int_range_max range;
+	    if (TYPE_SIGN (type) == SIGNED
+		&& query->range_of_expr (range, op0, stmt))
+	      {
+		unsigned prec = TYPE_PRECISION (TREE_TYPE (op0));
+		int_range<2> nzm1 (type, wi::minus_one (prec), wi::zero (prec),
+				   VR_ANTI_RANGE);
+		range.intersect (nzm1);
+		// If there are no ranges other than [-1, 0] remove the shift.
+		if (range.undefined_p ())
+		  {
+		    gimple_assign_set_rhs_from_tree (gsi, op0);
+		    return true;
+		  }
+		return false;
+	      }
+	    break;
+	  }
 	default:
 	  break;
 	}