https://gcc.gnu.org/g:077f16b249346b560169cf89849779272327a2da
commit r15-1969-g077f16b249346b560169cf89849779272327a2da Author: Georg-Johann Lay <a...@gjlay.de> Date: Thu Jul 11 13:08:19 2024 +0200 AVR: Tidy up subtract-and-zero_extend insns. There are these insns that subtract and zero-extend where the subtrahend is zero-extended to the mode of the minuend. This patch uses one insn (and split) with mode iterators instead of spelling out each variant individually. This has the additional benefit that u32 - u24 is also supported, which previously wasn't. gcc/ * config/avr/avr-protos.h (avr_out_minus): New prototype. * config/avr/avr.cc (avr_out_minus): New function. * config/avr/avr.md (*sub<HISI:mode>3.zero_extend.<QIPSI:mode>) (*sub<HISI:mode>3.zero_extend.<QIPSI:mode>_split): New insns. (*subpsi3_zero_extend.qi_split): Remove isns_and_split. (*subpsi3_zero_extend.hi_split): Remove insn_and_split. (*subhi3_zero_extend1_split): Remove insn_and_split. (*subsi3_zero_extend_split): Remove insn_and_split. (*subsi3_zero_extend.hi_split): Remove insn_and_split. (*subpsi3_zero_extend.qi): Remove insn. (*subpsi3_zero_extend.hi): Remove insn. (*subhi3_zero_extend1): Remove insn. (*subsi3_zero_extend): Remove insn. (*subsi3_zero_extend.hi): Remove insn. gcc/testsuite/ * gcc.target/avr/torture/sub-zerox.c: New test. Diff: --- gcc/config/avr/avr-protos.h | 1 + gcc/config/avr/avr.cc | 32 +++++- gcc/config/avr/avr.md | 122 +++++------------------ gcc/testsuite/gcc.target/avr/torture/sub-zerox.c | 15 +++ 4 files changed, 73 insertions(+), 97 deletions(-) diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h index dc23cfbf461c..6e02161759ca 100644 --- a/gcc/config/avr/avr-protos.h +++ b/gcc/config/avr/avr-protos.h @@ -95,6 +95,7 @@ extern void avr_output_addr_vec (rtx_insn*, rtx); extern const char *avr_out_sbxx_branch (rtx_insn *insn, rtx operands[]); extern const char* avr_out_bitop (rtx, rtx*, int*); extern const char* avr_out_plus (rtx, rtx*, int* =NULL, bool =true); +extern const char* avr_out_minus (rtx*); extern const char* avr_out_round (rtx_insn *, rtx*, int* =NULL); extern const char* avr_out_addto_sp (rtx*, int*); extern const char* avr_out_xload (rtx_insn *, rtx*, int*); diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index d299fceb7824..4a7cbd0e7bc6 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -8843,6 +8843,36 @@ lshrsi3_out (rtx_insn *insn, rtx operands[], int *len) } +/* Output subtraction of integer registers XOP[0] and XOP[2] and return "" + + XOP[0] = XOP[0] - XOP[2] + + where the mode of XOP[0] is in { HI, PSI, SI }, and the mode of + XOP[2] is in { QI, HI, PSI }. When the mode of XOP[0] is larger + than the mode of XOP[2], then the latter is zero-extended on the fly. + The number of instructions will be the mode size of XOP[0]. */ + +const char * +avr_out_minus (rtx *xop) +{ + int n_bytes0 = GET_MODE_SIZE (GET_MODE (xop[0])); + int n_bytes2 = GET_MODE_SIZE (GET_MODE (xop[2])); + + output_asm_insn ("sub %0,%2", xop); + + for (int i = 1; i < n_bytes0; ++i) + { + rtx op[2]; + op[0] = all_regs_rtx[i + REGNO (xop[0])]; + op[1] = (i < n_bytes2) ? all_regs_rtx[i + REGNO (xop[2])] : zero_reg_rtx; + + output_asm_insn ("sbc %0,%1", op); + } + + return ""; +} + + /* Output addition of register XOP[0] and compile time constant XOP[2]. INSN is a single_set insn or an insn pattern. CODE == PLUS: perform addition by using ADD instructions or @@ -12717,7 +12747,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code, *total = COSTS_N_INSNS (2); return true; } - // *sub<mode>3_zero_extend1 + // *sub<HISI:mode>3.zero_extend.<QIPSI:mode> if (REG_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND) { diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 2783b8c986f1..8c3e55a91ee0 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -2030,47 +2030,6 @@ "sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2" [(set_attr "length" "3")]) -(define_insn_and_split "*subpsi3_zero_extend.qi_split" - [(set (match_operand:PSI 0 "register_operand" "=r") - (minus:PSI (match_operand:SI 1 "register_operand" "0") - (zero_extend:PSI (match_operand:QI 2 "register_operand" "r"))))] - "" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 0) - (minus:PSI (match_dup 1) - (zero_extend:PSI (match_dup 2)))) - (clobber (reg:CC REG_CC))])]) - -(define_insn "*subpsi3_zero_extend.qi" - [(set (match_operand:PSI 0 "register_operand" "=r") - (minus:PSI (match_operand:SI 1 "register_operand" "0") - (zero_extend:PSI (match_operand:QI 2 "register_operand" "r")))) - (clobber (reg:CC REG_CC))] - "reload_completed" - "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__" - [(set_attr "length" "3")]) - -(define_insn_and_split "*subpsi3_zero_extend.hi_split" - [(set (match_operand:PSI 0 "register_operand" "=r") - (minus:PSI (match_operand:PSI 1 "register_operand" "0") - (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))] - "" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 0) - (minus:PSI (match_dup 1) - (zero_extend:PSI (match_dup 2)))) - (clobber (reg:CC REG_CC))])]) - -(define_insn "*subpsi3_zero_extend.hi" - [(set (match_operand:PSI 0 "register_operand" "=r") - (minus:PSI (match_operand:PSI 1 "register_operand" "0") - (zero_extend:PSI (match_operand:HI 2 "register_operand" "r")))) - (clobber (reg:CC REG_CC))] - "reload_completed" - "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__" - [(set_attr "length" "3")]) (define_insn_and_split "*subpsi3_sign_extend.hi_split" [(set (match_operand:PSI 0 "register_operand" "=r") @@ -2154,26 +2113,6 @@ } [(set_attr "adjust_len" "plus")]) -(define_insn_and_split "*subhi3_zero_extend1_split" - [(set (match_operand:HI 0 "register_operand" "=r") - (minus:HI (match_operand:HI 1 "register_operand" "0") - (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))] - "" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 0) - (minus:HI (match_dup 1) - (zero_extend:HI (match_dup 2)))) - (clobber (reg:CC REG_CC))])]) - -(define_insn "*subhi3_zero_extend1" - [(set (match_operand:HI 0 "register_operand" "=r") - (minus:HI (match_operand:HI 1 "register_operand" "0") - (zero_extend:HI (match_operand:QI 2 "register_operand" "r")))) - (clobber (reg:CC REG_CC))] - "reload_completed" - "sub %A0,%2\;sbc %B0,__zero_reg__" - [(set_attr "length" "2")]) (define_insn_and_split "*subhi3.sign_extend2_split" [(set (match_operand:HI 0 "register_operand" "=r") @@ -2231,48 +2170,39 @@ } [(set_attr "adjust_len" "plus")]) -(define_insn_and_split "*subsi3_zero_extend_split" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "register_operand" "0") - (zero_extend:SI (match_operand:QI 2 "register_operand" "r"))))] - "" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 0) - (minus:SI (match_dup 1) - (zero_extend:SI (match_dup 2)))) - (clobber (reg:CC REG_CC))])]) -(define_insn "*subsi3_zero_extend" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "register_operand" "0") - (zero_extend:SI (match_operand:QI 2 "register_operand" "r")))) - (clobber (reg:CC REG_CC))] - "reload_completed" - "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__" - [(set_attr "length" "4") - ]) - -(define_insn_and_split "*subsi3_zero_extend.hi_split" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "register_operand" "0") - (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))] - "" +;; "*subhi3.zero_extend.qi_split" +;; "*subpsi3.zero_extend.qi_split" "*subpsi3.zero_extend.hi_split" +;; "*subsi3.zero_extend.qi_split" "*subsi3.zero_extend.hi_split" +;; "*subsi3.zero_extend.psi_split" +(define_insn_and_split "*sub<HISI:mode>3.zero_extend.<QIPSI:mode>_split" + [(set (match_operand:HISI 0 "register_operand" "=r") + (minus:HISI (match_operand:HISI 1 "register_operand" "0") + (zero_extend:HISI (match_operand:QIPSI 2 "register_operand" "r"))))] + "GET_MODE_SIZE (<HISI:MODE>mode) > GET_MODE_SIZE (<QIPSI:MODE>mode)" "#" "&& reload_completed" [(parallel [(set (match_dup 0) - (minus:SI (match_dup 1) - (zero_extend:SI (match_dup 2)))) + (minus:HISI (match_dup 1) + (zero_extend:HISI (match_dup 2)))) (clobber (reg:CC REG_CC))])]) -(define_insn "*subsi3_zero_extend.hi" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "register_operand" "0") - (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))) +;; "*subhi3.zero_extend.qi" +;; "*subpsi3.zero_extend.qi" "*subpsi3.zero_extend.hi" +;; "*subsi3.zero_extend.qi" "*subsi3.zero_extend.hi" +;; "*subsi3.zero_extend.psi" +(define_insn "*sub<HISI:mode>3.zero_extend.<QIPSI:mode>" + [(set (match_operand:HISI 0 "register_operand" "=r") + (minus:HISI (match_operand:HISI 1 "register_operand" "0") + (zero_extend:HISI (match_operand:QIPSI 2 "register_operand" "r")))) (clobber (reg:CC REG_CC))] - "reload_completed" - "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__" - [(set_attr "length" "4")]) + "reload_completed + && GET_MODE_SIZE (<HISI:MODE>mode) > GET_MODE_SIZE (<QIPSI:MODE>mode)" + { + return avr_out_minus (operands); + } + [(set_attr "length" "<HISI:SIZE>")]) + ;****************************************************************************** ; mul diff --git a/gcc/testsuite/gcc.target/avr/torture/sub-zerox.c b/gcc/testsuite/gcc.target/avr/torture/sub-zerox.c new file mode 100644 index 000000000000..435fc7065f0f --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/sub-zerox.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ + +typedef __UINT8_TYPE__ u8; +typedef __UINT16_TYPE__ u16; +typedef __uint24 u24; +typedef __UINT32_TYPE__ u32; + +u32 sub_32_8 (u32 a, u8 b) { return a - b; } +u32 sub_32_16 (u32 a, u16 b) { return a - b; } +u32 sub_32_24 (u32 a, u24 b) { return a - b; } + +u24 sub_24_8 (u24 a, u8 b) { return a - b; } +u24 sub_24_16 (u24 a, u16 b) { return a - b; } + +u16 sub_16_8 (u16 a, u8 b) { return a - b; }