From: Dimitar Dimitrov Date: Sat, 20 Aug 2022 20:58:27 +0000 (+0300) Subject: pru: Optimize 64-bit logical operations X-Git-Tag: basepoints/gcc-14~5065 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=990124c35cd60cd23e0b70fc84cfb75311e80276;p=thirdparty%2Fgcc.git pru: Optimize 64-bit logical operations The earlyclobber in the pattern yields inefficient code due to unnecessarily generated moves. Optimize by removing the earlyclobber for two special alternatives: - If OP2 is a small constant integer. - If the logical bit operation has only two operands. gcc/ChangeLog: * config/pru/pru.md (pru_di3): New alternative for two operands but without earlyclobber. gcc/testsuite/ChangeLog: * gcc.target/pru/bitop-di.c: New test. Signed-off-by: Dimitar Dimitrov --- diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md index 02e11350a4dc..144cd35d8098 100644 --- a/gcc/config/pru/pru.md +++ b/gcc/config/pru/pru.md @@ -786,15 +786,42 @@ operands[2] = force_reg (DImode, operands[2]); }) +;; 64-bit pattern for logical operations. (define_insn "pru_di3" - [(set (match_operand:DI 0 "register_operand" "=&r,&r") + [(set (match_operand:DI 0 "register_operand" "=r,&r,r") (LOGICAL_BITOP:DI - (match_operand:DI 1 "register_operand" "%r,r") - (match_operand:DI 2 "reg_or_ubyte_operand" "r,I")))] + (match_operand:DI 1 "register_operand" "%0,r,r") + (match_operand:DI 2 "reg_or_ubyte_operand" "r,r,I")))] "" - "@ - \\t%F0, %F1, %F2\;\\t%N0, %N1, %N2 - \\t%F0, %F1, %2\;\\t%N0, %N1, 0" +{ + switch (which_alternative) + { + case 0: + if (REGNO (operands[0]) == (REGNO (operands[2]) + 4)) + return "\\t%N0, %N0, %N2\;" + "\\t%F0, %F0, %F2"; + else + return "\\t%F0, %F0, %F2\;" + "\\t%N0, %N0, %N2"; + case 1: + /* With the three-register variant there is no way to handle the case + when OP0 overlaps both OP1 and OP2. Example: + OP0_lo == OP1_hi + OP0_hi == OP2_lo + Hence this variant's OP0 must be marked as an earlyclobber. */ + return "\\t%F0, %F1, %F2\;" + "\\t%N0, %N1, %N2"; + case 2: + if (REGNO (operands[0]) == (REGNO (operands[1]) + 4)) + return "\\t%N0, %N1, 0\;" + "\\t%F0, %F1, %2"; + else + return "\\t%F0, %F1, %2\;" + "\\t%N0, %N1, 0"; + default: + gcc_unreachable (); + } +} [(set_attr "type" "alu") (set_attr "length" "8")]) diff --git a/gcc/testsuite/gcc.target/pru/bitop-di.c b/gcc/testsuite/gcc.target/pru/bitop-di.c new file mode 100644 index 000000000000..4290cdbc759f --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/bitop-di.c @@ -0,0 +1,25 @@ +/* 64-bit logical bit operations. */ + +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +unsigned long long +test_xor_di (unsigned long long val1, unsigned long long val2) +{ + /* { dg-final { scan-assembler "xor\\tr14, r14, r16" } } */ + return val1 ^ val2; +} + +unsigned long long +test_and_di (unsigned long long val1, unsigned long long val2) +{ + /* { dg-final { scan-assembler "and\\tr14, r14, r16" } } */ + return val1 & val2; +} + +unsigned long long +test_ior_di (unsigned long long val1, unsigned long long val2) +{ + /* { dg-final { scan-assembler "or\\tr14, r14, r16" } } */ + return val1 | val2; +}