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.
Regression tested on pru-unknown-elf, committed to mainline. gcc/ChangeLog: * config/pru/pru.md (pru_<code>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 <dimi...@dinux.eu> --- gcc/config/pru/pru.md | 39 +++++++++++++++++++++---- gcc/testsuite/gcc.target/pru/bitop-di.c | 25 ++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/pru/bitop-di.c diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md index 02e11350a4d..144cd35d809 100644 --- a/gcc/config/pru/pru.md +++ b/gcc/config/pru/pru.md @@ -786,15 +786,42 @@ (define_expand "<code>di3" operands[2] = force_reg (DImode, operands[2]); }) +;; 64-bit pattern for logical operations. (define_insn "pru_<code>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")))] "" - "@ - <logical_bitop_asm>\\t%F0, %F1, %F2\;<logical_bitop_asm>\\t%N0, %N1, %N2 - <logical_bitop_asm>\\t%F0, %F1, %2\;<logical_bitop_asm>\\t%N0, %N1, 0" +{ + switch (which_alternative) + { + case 0: + if (REGNO (operands[0]) == (REGNO (operands[2]) + 4)) + return "<logical_bitop_asm>\\t%N0, %N0, %N2\;" + "<logical_bitop_asm>\\t%F0, %F0, %F2"; + else + return "<logical_bitop_asm>\\t%F0, %F0, %F2\;" + "<logical_bitop_asm>\\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 "<logical_bitop_asm>\\t%F0, %F1, %F2\;" + "<logical_bitop_asm>\\t%N0, %N1, %N2"; + case 2: + if (REGNO (operands[0]) == (REGNO (operands[1]) + 4)) + return "<logical_bitop_asm>\\t%N0, %N1, 0\;" + "<logical_bitop_asm>\\t%F0, %F1, %2"; + else + return "<logical_bitop_asm>\\t%F0, %F1, %2\;" + "<logical_bitop_asm>\\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 00000000000..4290cdbc759 --- /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; +} -- 2.37.2