From 32d29982c745581195dde8c21741d611827fe434 Mon Sep 17 00:00:00 2001
From: Kyrylo Tkachov <ktkachov@nvidia.com>
Date: Wed, 9 Oct 2024 09:39:55 -0700
Subject: [PATCH 1/2] PR 117048: simplify-rtx: Extend (x << C1) | (X >> C2) -->
 ROTATE transformation to vector operands

In the testcase from patch [2/2] we want to match a vector rotate operate from
an IOR of left and right shifts by immediate.  simplify-rtx has code for just
that but it looks like it's prepared to do handle only scalar operands.
In practice most of the code works for vector modes as well except the shift
amounts are checked to be CONST_INT rather than vector constants that we have
here.  This is easily extended by using unwrap_const_vec_duplicate to extract
the repeating constant shift amount.  With this change combine now tries
matching the simpler and expected:
(set (reg:V2DI 119 [ _14 ])
    (rotate:V2DI (xor:V2DI (reg:V2DI 114 [ vect__1.12_16 ])
            (reg:V2DI 116 [ *m1_01_8(D) ]))
        (const_vector:V2DI [
                (const_int 32 [0x20]) repeated x2
            ])))
instead of the previous:
(set (reg:V2DI 119 [ _14 ])
    (ior:V2DI (ashift:V2DI (xor:V2DI (reg:V2DI 114 [ vect__1.12_16 ])
                (reg:V2DI 116 [ *m1_01_8(D) ]))
            (const_vector:V2DI [
                    (const_int 32 [0x20]) repeated x2
                ]))
        (lshiftrt:V2DI (xor:V2DI (reg:V2DI 114 [ vect__1.12_16 ])
                (reg:V2DI 116 [ *m1_01_8(D) ]))
            (const_vector:V2DI [
                    (const_int 32 [0x20]) repeated x2
                ]))))

To actually fix the PR the aarch64 backend needs some adjustment as well
which is done in patch [2/2], which adds the testcase as well.

Bootstrapped and tested on aarch64-none-linux-gnu.

Signed-off-by: Kyrylo Tkachov <ktkachov@nvidia.com>

	PR target/117048
	* simplify-rtx.cc (simplify_context::simplify_binary_operation_1):
	Handle vector constants in (x << C1) | (x >> C2) -> ROTATE
	simplification.
---
 gcc/simplify-rtx.cc | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index e8e60404ef6..dc0d192dd21 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -3477,12 +3477,16 @@ simplify_context::simplify_binary_operation_1 (rtx_code code,
 	}
 
       if (GET_CODE (opleft) == ASHIFT && GET_CODE (opright) == LSHIFTRT
-          && rtx_equal_p (XEXP (opleft, 0), XEXP (opright, 0))
-          && CONST_INT_P (XEXP (opleft, 1))
-          && CONST_INT_P (XEXP (opright, 1))
-          && (INTVAL (XEXP (opleft, 1)) + INTVAL (XEXP (opright, 1))
-	      == GET_MODE_UNIT_PRECISION (mode)))
-        return gen_rtx_ROTATE (mode, XEXP (opright, 0), XEXP (opleft, 1));
+	  && rtx_equal_p (XEXP (opleft, 0), XEXP (opright, 0)))
+	{
+	  rtx leftcst = unwrap_const_vec_duplicate (XEXP (opleft, 1));
+	  rtx rightcst = unwrap_const_vec_duplicate (XEXP (opright, 1));
+
+	  if (CONST_INT_P (leftcst) && CONST_INT_P (rightcst)
+	      && (INTVAL (leftcst) + INTVAL (rightcst)
+		  == GET_MODE_UNIT_PRECISION (mode)))
+	    return gen_rtx_ROTATE (mode, XEXP (opright, 0), XEXP (opleft, 1));
+	}
 
       /* Same, but for ashift that has been "simplified" to a wider mode
         by simplify_shift_const.  */
-- 
2.44.0

