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