diff options
author | Dimitar Dimitrov <dimitar@dinux.eu> | 2022-08-20 23:58:27 +0300 |
---|---|---|
committer | Dimitar Dimitrov <dimitar@dinux.eu> | 2022-08-22 22:29:10 +0300 |
commit | 990124c35cd60cd23e0b70fc84cfb75311e80276 (patch) | |
tree | 7fe10eacaf165e21eaa5acbd4da87a68b43bb398 /gcc/config/pru | |
parent | 151effa22106a81f5835bb2dab7b95130f8fe2ef (diff) | |
download | gcc-990124c35cd60cd23e0b70fc84cfb75311e80276.zip gcc-990124c35cd60cd23e0b70fc84cfb75311e80276.tar.gz gcc-990124c35cd60cd23e0b70fc84cfb75311e80276.tar.bz2 |
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_<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 <dimitar@dinux.eu>
Diffstat (limited to 'gcc/config/pru')
-rw-r--r-- | gcc/config/pru/pru.md | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md index 02e1135..144cd35 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_<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")]) |