On Tue, 2025-01-21 at 22:14 +0800, Xi Ruoyao wrote:
> On Tue, 2025-01-21 at 21:52 +0800, Xi Ruoyao wrote:
> > > struct Pair { unsigned long a, b; };
> > > 
> > > struct Pair
> > > test (struct Pair p, long x, long y)
> > > {
> > >   p.a &= 0xffffffff;
> > >   p.a <<= 2;
> > >   p.a += x;
> > >   p.b &= 0xffffffff;
> > >   p.b <<= 2;
> > >   p.b += x;
> > >   return p;
> > > }
> > > 
> > > in GCC 13 the result is:
> > > 
> > >   or      $r12,$r4,$r0
> > 
> > Hmm, this strange move is caused by "&" in bstrpick_alsl_paired.  Is it
> > really needed for the fusion?
> 
> Never mind, it's needed or a = ((a & 0xffffffff) << 1) + a will blow up.
> Stupid I.
> 
> > >   bstrpick.d      $r4,$r12,31,0
> > >   alsl.d  $r4,$r4,$r6,2
> > >   or      $r12,$r5,$r0
> > >   bstrpick.d      $r5,$r12,31,0
> > >   alsl.d  $r5,$r5,$r6,2
> > >   jr      $r1

This fixes the test case and forces to emit alsl.d for (a & 0xffffffff)
<< [1234]:

diff --git a/gcc/config/loongarch/loongarch.md 
b/gcc/config/loongarch/loongarch.md
index 10197b9d9d5..7b5b77c56ac 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -3134,8 +3134,50 @@ (define_insn_and_split "<optab>_shift_reverse<X:mode>"
                                       <MODE>mode)"
   "#"
   "&& true"
+  [(set (match_dup 0) (ashift:X (match_dup 0) (match_dup 2)))]
+  {
+    operands[3] = loongarch_reassoc_shift_bitwise (<is_and>,
+                                                  operands[2],
+                                                  operands[3],
+                                                  <MODE>mode);
+
+    if (ins_zero_bitmask_operand (operands[3], <MODE>mode))
+      {
+       gcc_checking_assert (<is_and>);
+       emit_move_insn (operands[0], operands[1]);
+       operands[1] = operands[0];              
+      }
+
+    emit_insn (gen_<optab><mode>3 (operands[0], operands[1], operands[3]));
+
+    if (<is_and>
+       && TARGET_64BIT
+       && si_mask_operand (operands[3], DImode)
+       && const_immalsl_operand (operands[2], SImode))
+      {
+       /* Special case for bstrpick.d + alsl.d fusion
+          TODO: TARGET_SCHED_MACRO_FUSION_PAIR_P */
+       emit_insn (gen_alsldi3 (operands[0], operands[0],
+                               operands[2], gen_rtx_REG (DImode, 0)));
+       DONE;
+      }
+  })
+
+(define_insn_and_split "<optab>_alsl_reverse<X:mode>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+       (plus:X
+         (any_bitwise:X
+           (ashift:X (match_operand:X  1 "register_operand" "r")
+                     (match_operand:SI 2 "const_immalsl_operand" "i"))
+           (match_operand:X 3 "const_int_operand" "i"))
+         (match_operand:X 4 "register_operand" "r")))]
+  "loongarch_reassoc_shift_bitwise (<is_and>, operands[2], operands[3],
+                                   <MODE>mode)"
+  "#"
+  "&& true"
   [(set (match_dup 0) (any_bitwise:X (match_dup 1) (match_dup 3)))
-   (set (match_dup 0) (ashift:X (match_dup 0) (match_dup 2)))]
+   (set (match_dup 0) (plus:X (ashift:X (match_dup 0) (match_dup 2))
+                             (match_dup 4)))]
   {
     operands[3] = loongarch_reassoc_shift_bitwise (<is_and>,
                                                   operands[2],

I guess it'll work combined with TARGET_SCHED_MACRO_FUSION_PAIR_P
implemented.


-- 
Xi Ruoyao <xry...@xry111.site>
School of Aerospace Science and Technology, Xidian University

Reply via email to