Jeff Law <jeffreya...@gmail.com> writes:
> On 12/30/24 3:02 PM, Richard Sandiford wrote:
>
>> 
>> So it seems like it's a bit of a mess :(
>> 
>> If we do try to fix combine, I think something like the attached
>> would fit within the current scheme.  It is a pure shift-for-shift
>> transformation, avoiding any extensions.
>> 
>> Will think more about it, but wanted to get the above stream of
>> consciousness out before I finish for the day :)
> So your approach in simplify-rtx ended up much cleaner than mine; unless 
> there's some objection from you, I'd like to go with it.  Obviously I'll 
> run it through the usual testing cycles first ;-)

Yeah, that's fine with me.  Reading it back, I realised that we should
probably also check for an in-range shift value, fixed below.

Richard


diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index dda8fc689e7..c478bd060fc 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -4494,6 +4494,60 @@ simplify_context::simplify_binary_operation_1 (rtx_code 
code,
            return simplify_gen_binary (code, mode, op0,
                                        gen_int_shift_amount (mode, val));
        }
+
+      /* Simplify:
+
+          (code:M1
+            (subreg:M1
+              ([al]shiftrt:M2
+                (subreg:M2
+                  (ashift:M1 X C1))
+                C2))
+            C3)
+
+        to:
+
+          (code:M1
+            ([al]shiftrt:M1
+              (ashift:M1 X C1+N)
+              C2+N)
+            C3)
+
+        where M1 is N bits wider than M2.  Optimizing the (subreg:M1 ...)
+        directly would be arithmetically correct, but restricting the
+        simplification to shifts by constants is more conservative,
+        since it is more likely to lead to further simplifications.  */
+      if (is_a<scalar_int_mode> (mode, &int_mode)
+         && paradoxical_subreg_p (op0)
+         && is_a<scalar_int_mode> (GET_MODE (SUBREG_REG (op0)), &inner_mode)
+         && (GET_CODE (SUBREG_REG (op0)) == ASHIFTRT
+             || GET_CODE (SUBREG_REG (op0)) == LSHIFTRT)
+         && CONST_INT_P (op1))
+       {
+         auto xcode = GET_CODE (SUBREG_REG (op0));
+         rtx xop0 = XEXP (SUBREG_REG (op0), 0);
+         rtx xop1 = XEXP (SUBREG_REG (op0), 1);
+         if (SUBREG_P (xop0)
+             && GET_MODE (SUBREG_REG (xop0)) == mode
+             && GET_CODE (SUBREG_REG (xop0)) == ASHIFT
+             && CONST_INT_P (xop1)
+             && UINTVAL (xop1) < GET_MODE_PRECISION (inner_mode))
+           {
+             rtx yop0 = XEXP (SUBREG_REG (xop0), 0);
+             rtx yop1 = XEXP (SUBREG_REG (xop0), 1);
+             if (CONST_INT_P (yop1)
+                 && UINTVAL (yop1) < GET_MODE_PRECISION (inner_mode))
+               {
+                 auto bias = (GET_MODE_BITSIZE (int_mode)
+                              - GET_MODE_BITSIZE (inner_mode));
+                 tem = simplify_gen_binary (ASHIFT, mode, yop0,
+                                            GEN_INT (INTVAL (yop1) + bias));
+                 tem = simplify_gen_binary (xcode, mode, tem,
+                                            GEN_INT (INTVAL (xop1) + bias));
+                 return simplify_gen_binary (code, mode, tem, op1);
+               }
+           }
+       }
       break;
 
     case SS_ASHIFT:
-- 
2.25.1

Reply via email to