https://gcc.gnu.org/g:939362411d0903542647dae0eff82db10a3ad78a
commit r15-5599-g939362411d0903542647dae0eff82db10a3ad78a Author: Georg-Johann Lay <a...@gjlay.de> Date: Thu Nov 21 22:59:14 2024 +0100 AVR: target/117726 - Tweak ashiftrt:SI and lshiftrt:SI insns. This patch is similar to r15-5569 (tweak ashift:SI) but for ashiftrt and lshiftrt codes. It splits constant shift offsets > 16 into a 3-operand byte shift and a 2-operand residual bit shift. Moreover, some of the constraint alternatives have been promoted to 3-operand alternatives regardless of options. For example, ashift:HI and lshiftrt:HI can support 3 operands for offsets 9...12 without any overhead. Apart from that, it's a bit of code clean up for 2-byte and 4-byte shift insns: Use one RTL peephole with any_shift code iterator instead of 3 individual peepholes. It also removes some useless split insns; presumably introduced during the cc0 -> CCmode work. PR target/117726 gcc/ * config/avr/avr-passes.cc (avr_split_shift): Also handle ASHIFTRT and LSHIFTRT codes for 4-byte shifts. (constr_split_shift4): New code_attr. (avr_emit_shift): Adjust to new shift capabilities. * config/avr/predicates.md (scratch_or_d_register_operand): rename to scratch_or_dreg_operand. * config/avr/avr.md: Same. (define_peephole2): Write the RTL scratch peephole for 2-byte and 4-byte shifts that generates *sh*<mode>3_const insns using code iterator any_shift. (*ashlhi3_const_split, *ashrhi3_const_split, *ashrhi3_const_split) (*lshrsi3_const_split, *lshrhi3_const_split): Remove useless split insns. (define_split) [avropt_split_bit_shift]: Add splitters for 4-byte ASHIFTRT and LSHIFTRT insns using avr_split_shift(). (ashrsi3, *ashrsi3, *ashrsi3_const): Add "r,0,C4a" and "r,r,C4a" constraint alternatives depending on 2op, 3op. (lshrsi3, *lshrsi3, *lshrsi3_const): Add "r,0,C4r" and "r,r,C4r" constraint alternatives depending on 2op, 3op. Add "r,r,C15". (lshrhi3, *lshrhi3, *lshrhi3_const, ashlhi3, *ashlhi3) (*ashlhi3_const): Add "r,r,C7c" alternative. (ashrpsi, *ashrpsi3): Add "r,r,C22" alternative. (ashlqi, *ashlqi): Turn C06 alternative into "r,r,C06". * config/avr/constraints.md (C14, C22, C30, C7c): New constraints. * config/avr/avr.cc (ashlhi3_out, lshrhi3_out) [case 7, 9, 10, 11, 12]: Support as 3-operand insn. (lshrsi3_out) [case 15]: Same. (ashrsi3_out) [case 30]: Same. (ashrhi3_out) [case 14]: Same. (ashrqi3_out) [case 6]: Same. (avr_out_ashrpsi3) [case 22]: Same. * config/avr/avr.h: Fix comment typo. * doc/invoke.texi (AVR Options) <-msplit-bit-shift>: Document. Diff: --- gcc/config/avr/avr-passes.cc | 95 +++++++++-- gcc/config/avr/avr.cc | 174 ++++++++++++++++---- gcc/config/avr/avr.h | 7 +- gcc/config/avr/avr.md | 371 ++++++++++++++++-------------------------- gcc/config/avr/constraints.md | 20 +++ gcc/config/avr/predicates.md | 2 +- gcc/doc/invoke.texi | 11 +- 7 files changed, 395 insertions(+), 285 deletions(-) diff --git a/gcc/config/avr/avr-passes.cc b/gcc/config/avr/avr-passes.cc index 57c3fed1e410..bd249b70e8d6 100644 --- a/gcc/config/avr/avr-passes.cc +++ b/gcc/config/avr/avr-passes.cc @@ -43,6 +43,7 @@ #include "context.h" #include "tree-pass.h" #include "insn-attr.h" +#include "tm-constrs.h" #define CONST_INT_OR_FIXED_P(X) (CONST_INT_P (X) || CONST_FIXED_P (X)) @@ -2412,6 +2413,7 @@ bbinfo_t::find_plies (int len, const insninfo_t &ii, const memento_t &memo0) bool profitable = (cost < SCALE * fpd->max_ply_cost || (bbinfo_t::try_split_any_p + && fpd->solution.n_plies == 0 && cost / SCALE <= fpd->max_ply_cost && cost / SCALE == fpd->movmode_cost)); if (! profitable) @@ -4840,37 +4842,54 @@ avr_shift_is_3op () LSHIFTRT, ASHIFT } into a byte shift and a residual bit shift. */ bool -avr_split_shift_p (int n_bytes, int offset, rtx_code) +avr_split_shift_p (int n_bytes, int offset, rtx_code code) { gcc_assert (n_bytes == 4); - return (avr_shift_is_3op () - && offset % 8 != 0 && IN_RANGE (offset, 17, 30)); + if (avr_shift_is_3op () + && offset % 8 != 0) + return select<bool>() + : code == ASHIFT ? IN_RANGE (offset, 17, 30) + : code == ASHIFTRT ? IN_RANGE (offset, 9, 29) + : code == LSHIFTRT ? IN_RANGE (offset, 9, 30) && offset != 15 + : bad_case<bool> (); + + return false; } +/* Emit a DEST = SRC <code> OFF shift of QImode, HImode or PSImode. + SCRATCH is a QImode d-register, scratch:QI, or NULL_RTX. */ + static void avr_emit_shift (rtx_code code, rtx dest, rtx src, int off, rtx scratch) { - machine_mode mode = GET_MODE (dest); + const machine_mode mode = GET_MODE (dest); + rtx xoff = GEN_INT (off); + bool is_3op = (off % 8 == 0 + || off == GET_MODE_BITSIZE (mode) - 1 + || (code == ASHIFTRT && off == GET_MODE_BITSIZE (mode) - 2) + || (mode == HImode + && (code == ASHIFT || code == LSHIFTRT) + && satisfies_constraint_C7c (xoff) /* 7...12 */)); rtx shift; - if (off == GET_MODE_BITSIZE (mode) - 1) + if (is_3op) { - shift = gen_rtx_fmt_ee (code, mode, src, GEN_INT (off)); + shift = gen_rtx_fmt_ee (code, mode, src, xoff); } else { if (REGNO (dest) != REGNO (src)) emit_valid_move_clobbercc (dest, src); - shift = gen_rtx_fmt_ee (code, mode, dest, GEN_INT (off)); + shift = gen_rtx_fmt_ee (code, mode, dest, xoff); } emit_valid_move_clobbercc (dest, shift, scratch); } -/* Worker for define_split that run when -msplit-bit-shift is on. +/* Worker for define_split that runs when -msplit-bit-shift is on. Split a shift of code CODE into a 3op byte shift and a residual bit shift. Return 'true' when a split has been performed and insns have been emitted. Otherwise, return 'false'. */ @@ -4887,25 +4906,73 @@ avr_split_shift (rtx xop[], rtx scratch, rtx_code code) if (code == ASHIFT) { - if (ioff >= 25) + if (IN_RANGE (ioff, 25, 30)) { rtx dst8 = avr_byte (dest, 3); rtx src8 = avr_byte (src, 0); - avr_emit_shift (code, dst8, src8, ioff % 8, NULL_RTX); + avr_emit_shift (code, dst8, src8, ioff - 24, NULL_RTX); emit_valid_move_clobbercc (avr_byte (dest, 2), const0_rtx); emit_valid_move_clobbercc (avr_word (dest, 0), const0_rtx); return true; } - else if (ioff >= 17) + else if (IN_RANGE (ioff, 17, 23)) { rtx dst16 = avr_word (dest, 2); rtx src16 = avr_word (src, 0); - avr_emit_shift (code, dst16, src16, ioff % 16, scratch); + avr_emit_shift (code, dst16, src16, ioff - 16, scratch); emit_valid_move_clobbercc (avr_word (dest, 0), const0_rtx); return true; } - else - gcc_unreachable (); + } + else if (code == ASHIFTRT + || code == LSHIFTRT) + { + if (IN_RANGE (ioff, 25, 30)) + { + rtx dst8 = avr_byte (dest, 0); + rtx src8 = avr_byte (src, 3); + avr_emit_shift (code, dst8, src8, ioff - 24, NULL_RTX); + if (code == ASHIFTRT) + { + rtx signs = avr_byte (dest, 1); + avr_emit_shift (code, signs, src8, 7, NULL_RTX); + emit_valid_move_clobbercc (avr_byte (dest, 2), signs); + emit_valid_move_clobbercc (avr_byte (dest, 3), signs); + } + else + { + emit_valid_move_clobbercc (avr_byte (dest, 1), const0_rtx); + emit_valid_move_clobbercc (avr_word (dest, 2), const0_rtx); + } + return true; + } + else if (IN_RANGE (ioff, 17, 23)) + { + rtx dst16 = avr_word (dest, 0); + rtx src16 = avr_word (src, 2); + avr_emit_shift (code, dst16, src16, ioff - 16, scratch); + if (code == ASHIFTRT) + { + rtx msb = avr_byte (src, 3); + rtx signs = avr_byte (dest, 2); + avr_emit_shift (code, signs, msb, 7, NULL_RTX); + emit_valid_move_clobbercc (avr_byte (dest, 3), signs); + } + else + emit_valid_move_clobbercc (avr_word (dest, 2), const0_rtx); + + return true; + } + else if (IN_RANGE (ioff, 9, 15)) + { + avr_emit_shift (code, dest, src, 8, NULL_RTX); + rtx dst24 = avr_chunk (PSImode, dest, 0); + rtx src24 = avr_chunk (PSImode, dest, 0); + if (! scratch) + scratch = gen_rtx_SCRATCH (QImode); + avr_emit_shift (code, dst24, src24, ioff - 8, scratch); + return true; + } } else gcc_unreachable (); diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index cc13dae9bfea..64d7795f37cc 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -6809,6 +6809,7 @@ ashlhi3_out (rtx_insn *insn, rtx operands[], int *plen) && XVECLEN (PATTERN (insn), 0) == 3 && REG_P (operands[3])); bool ldi_ok = test_hard_reg_class (LD_REGS, operands[0]); + bool reg1_unused_after = reg_unused_after (insn, operands[1]); if (plen) *plen = 0; @@ -6878,43 +6879,50 @@ ashlhi3_out (rtx_insn *insn, rtx operands[], int *plen) "mov %B0,%A0" CR_TAB "mov %A0,__tmp_reg__", operands, plen, 9); case 7: - return avr_asm_len ("lsr %B0" CR_TAB - "mov %B0,%A0" CR_TAB - "clr %A0" CR_TAB - "ror %B0" CR_TAB - "ror %A0", operands, plen, 5); + return reg1_unused_after + ? avr_asm_len ("lsr %B1" CR_TAB + "mov %B0,%A1" CR_TAB + "clr %A0" CR_TAB + "ror %B0" CR_TAB + "ror %A0", operands, plen, 5) + : avr_asm_len ("bst %B1,0" CR_TAB + "mov %B0,%A1" CR_TAB + "clr %A0" CR_TAB + "ror %B0" CR_TAB + "ror %A0" CR_TAB + "bld %B0,7", operands, plen, 6); case 8: return avr_asm_len ("mov %B0,%A1" CR_TAB "clr %A0", operands, plen, 2); case 9: - return avr_asm_len ("mov %B0,%A0" CR_TAB + return avr_asm_len ("mov %B0,%A1" CR_TAB "clr %A0" CR_TAB "lsl %B0", operands, plen, 3); case 10: - return avr_asm_len ("mov %B0,%A0" CR_TAB + return avr_asm_len ("mov %B0,%A1" CR_TAB "clr %A0" CR_TAB "lsl %B0" CR_TAB "lsl %B0", operands, plen, 4); case 11: - return avr_asm_len ("mov %B0,%A0" CR_TAB + return avr_asm_len ("mov %B0,%A1" CR_TAB "clr %A0" CR_TAB "lsl %B0" CR_TAB "lsl %B0" CR_TAB "lsl %B0", operands, plen, 5); case 12: if (ldi_ok) - return avr_asm_len ("mov %B0,%A0" CR_TAB + return avr_asm_len ("mov %B0,%A1" CR_TAB "clr %A0" CR_TAB "swap %B0" CR_TAB "andi %B0,0xf0", operands, plen, 4); if (scratch) - return avr_asm_len ("mov %B0,%A0" CR_TAB + return avr_asm_len ("mov %B0,%A1" CR_TAB "clr %A0" CR_TAB "swap %B0" CR_TAB "ldi %3,0xf0" CR_TAB "and %B0,%3", operands, plen, 5); - return avr_asm_len ("mov %B0,%A0" CR_TAB + return avr_asm_len ("mov %B0,%A1" CR_TAB "clr %A0" CR_TAB "lsl %B0" CR_TAB "lsl %B0" CR_TAB @@ -7164,6 +7172,7 @@ ashrqi3_out (rtx_insn *insn, rtx operands[], int *plen) *plen = 0; const int offs = INTVAL (operands[2]); + bool reg1_unused_after = reg_unused_after (insn, operands[1]); if (IN_RANGE (offs, 0, 5)) { @@ -7173,10 +7182,16 @@ ashrqi3_out (rtx_insn *insn, rtx operands[], int *plen) } else if (offs == 6) { - return avr_asm_len ("bst %0,6" CR_TAB - "lsl %0" CR_TAB - "sbc %0,%0" CR_TAB - "bld %0,0", operands, plen, 4); + return reg1_unused_after + ? avr_asm_len ("bst %1,6" CR_TAB + "lsl %1" CR_TAB + "sbc %0,%0" CR_TAB + "bld %0,0", operands, plen, 4) + : avr_asm_len ("mov %0,%1" CR_TAB + "bst %0,6" CR_TAB + "lsl %0" CR_TAB + "sbc %0,%0" CR_TAB + "bld %0,0", operands, plen, 5); } else if (offs >= 7) { @@ -7210,6 +7225,7 @@ ashrhi3_out (rtx_insn *insn, rtx operands[], int *plen) && XVECLEN (PATTERN (insn), 0) == 3 && REG_P (operands[3])); bool ldi_ok = test_hard_reg_class (LD_REGS, operands[0]); + bool reg1_unused_after = reg_unused_after (insn, operands[1]); if (plen) *plen = 0; @@ -7312,11 +7328,18 @@ ashrhi3_out (rtx_insn *insn, rtx operands[], int *plen) "asr %A0" CR_TAB "asr %A0", operands, plen, 8); case 14: - return avr_asm_len ("lsl %B0" CR_TAB - "sbc %A0,%A0" CR_TAB - "lsl %B0" CR_TAB - "mov %B0,%A0" CR_TAB - "rol %A0", operands, plen, 5); + return reg1_unused_after + ? avr_asm_len ("bst %B1,6" CR_TAB + "lsl %B1" CR_TAB + "sbc %B0,%B0" CR_TAB + "sbc %A0,%A0" CR_TAB + "bld %A0,0", operands, plen, 5) + : avr_asm_len ("mov %B0,%B1" CR_TAB + "bst %B0,6" CR_TAB + "lsl %B0" CR_TAB + "sbc %B0,%B0" CR_TAB + "sbc %A0,%A0" CR_TAB + "bld %A0,0", operands, plen, 6); default: if (INTVAL (operands[2]) < 16) break; @@ -7357,6 +7380,8 @@ avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen) if (plen) *plen = 0; + bool reg1_unused_after = reg_unused_after (insn, op[1]); + switch (INTVAL (op[2])) { case 8: @@ -7378,6 +7403,22 @@ avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen) "sbrc %A0,7" CR_TAB "com %B0" CR_TAB "mov %C0,%B0", op, plen, 4); + case 22: + { + rtx xop[2] = { op[0], op[1] }; + if (! reg1_unused_after) + { + avr_asm_len ("mov %C0,%C1", xop, plen, 1); + xop[1] = xop[0]; + } + return avr_asm_len ("bst %C1,6" CR_TAB + "lsl %C1" CR_TAB + "sbc %C0,%C0" CR_TAB + "sbc %B0,%B0" CR_TAB + "sbc %A0,%A0" CR_TAB + "bld %A0,0", xop, plen, 6); + } + default: if (INTVAL (op[2]) < 24) break; @@ -7387,7 +7428,7 @@ avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen) case 23: { rtx xop[2] = { op[0], op[1] }; - if (! reg_unused_after (insn, xop[1])) + if (! reg1_unused_after) { avr_asm_len ("mov %C0,%C1", xop, plen, 1); xop[1] = xop[0]; @@ -7419,6 +7460,7 @@ ashrsi3_out (rtx_insn *insn, rtx operands[], int *plen) int reg0 = true_regnum (operands[0]); int reg1 = true_regnum (operands[1]); + bool reg1_unused_after = reg_unused_after (insn, operands[1]); switch (INTVAL (operands[2])) { @@ -7461,6 +7503,26 @@ ashrsi3_out (rtx_insn *insn, rtx operands[], int *plen) "com %D0" CR_TAB "mov %B0,%D0" CR_TAB "mov %C0,%D0", operands, plen, 6); + case 30: + { + rtx xop[2] = { operands[0], operands[1] }; + if (! reg1_unused_after) + { + avr_asm_len ("mov %D0,%D1", xop, plen, 1); + xop[1] = xop[0]; + } + avr_asm_len ("bst %D1,6" CR_TAB + "lsl %D1" CR_TAB + "sbc %A0,%A0" CR_TAB + "sbc %B0,%B0", xop, plen, 4); + return AVR_HAVE_MOVW + ? avr_asm_len ("movw %C0,%A0" CR_TAB + "bld %A0,0", xop, plen, 2) + : avr_asm_len ("mov %C0,%A0" CR_TAB + "mov %D0,%A0" CR_TAB + "bld %A0,0", xop, plen, 3); + } + default: if (INTVAL (operands[2]) < 32) break; @@ -7470,7 +7532,7 @@ ashrsi3_out (rtx_insn *insn, rtx operands[], int *plen) case 31: { rtx xop[2] = { operands[0], operands[1] }; - if (! reg_unused_after (insn, xop[1])) + if (! reg1_unused_after) { avr_asm_len ("mov %D0,%D1", xop, plen, 1); xop[1] = xop[0]; @@ -7566,6 +7628,7 @@ lshrhi3_out (rtx_insn *insn, rtx operands[], int *plen) && XVECLEN (PATTERN (insn), 0) == 3 && REG_P (operands[3])); bool ldi_ok = test_hard_reg_class (LD_REGS, operands[0]); + bool reg1_unused_after = reg_unused_after (insn, operands[1]); if (plen) *plen = 0; @@ -7635,42 +7698,49 @@ lshrhi3_out (rtx_insn *insn, rtx operands[], int *plen) "mov %A0,%B0" CR_TAB "mov %B0,__tmp_reg__", operands, plen, 9); case 7: - return avr_asm_len ("lsl %A0" CR_TAB - "mov %A0,%B0" CR_TAB - "rol %A0" CR_TAB - "sbc %B0,%B0" CR_TAB - "neg %B0", operands, plen, 5); + return reg1_unused_after + ? avr_asm_len ("lsl %A1" CR_TAB + "mov %A0,%B1" CR_TAB + "rol %A0" CR_TAB + "sbc %B0,%B0" CR_TAB + "neg %B0", operands, plen, 5) + : avr_asm_len ("bst %A1,7" CR_TAB + "mov %A0,%B1" CR_TAB + "rol %A0" CR_TAB + "sbc %B0,%B0" CR_TAB + "neg %B0" CR_TAB + "bld %A0,0", operands, plen, 6); case 8: return avr_asm_len ("mov %A0,%B1" CR_TAB "clr %B0", operands, plen, 2); case 9: - return avr_asm_len ("mov %A0,%B0" CR_TAB + return avr_asm_len ("mov %A0,%B1" CR_TAB "clr %B0" CR_TAB "lsr %A0", operands, plen, 3); case 10: - return avr_asm_len ("mov %A0,%B0" CR_TAB + return avr_asm_len ("mov %A0,%B1" CR_TAB "clr %B0" CR_TAB "lsr %A0" CR_TAB "lsr %A0", operands, plen, 4); case 11: - return avr_asm_len ("mov %A0,%B0" CR_TAB + return avr_asm_len ("mov %A0,%B1" CR_TAB "clr %B0" CR_TAB "lsr %A0" CR_TAB "lsr %A0" CR_TAB "lsr %A0", operands, plen, 5); case 12: if (ldi_ok) - return avr_asm_len ("mov %A0,%B0" CR_TAB + return avr_asm_len ("mov %A0,%B1" CR_TAB "clr %B0" CR_TAB "swap %A0" CR_TAB "andi %A0,0x0f", operands, plen, 4); return scratch - ? avr_asm_len ("mov %A0,%B0" CR_TAB + ? avr_asm_len ("mov %A0,%B1" CR_TAB "clr %B0" CR_TAB "swap %A0" CR_TAB "ldi %3,0x0f" CR_TAB "and %A0,%3", operands, plen, 5) - : avr_asm_len ("mov %A0,%B0" CR_TAB + : avr_asm_len ("mov %A0,%B1" CR_TAB "clr %B0" CR_TAB "lsr %A0" CR_TAB "lsr %A0" CR_TAB @@ -7816,6 +7886,7 @@ lshrsi3_out (rtx_insn *insn, rtx operands[], int *plen) { int reg0 = true_regnum (operands[0]); int reg1 = true_regnum (operands[1]); + bool reg1_unused_after_p = reg_unused_after (insn, operands[1]); if (plen) *plen = 0; @@ -7844,6 +7915,30 @@ lshrsi3_out (rtx_insn *insn, rtx operands[], int *plen) "mov %C0,%D1" CR_TAB "mov %B0,%C1" CR_TAB "mov %A0,%B1", operands, plen, 4); + case 15: + avr_asm_len (reg1_unused_after_p + ? "lsl %B1" + : "bst %B1,7", operands, plen, 1); + if (reg0 != reg1 + 2) + { + if (AVR_HAVE_MOVW) + avr_asm_len ("movw %A0,%C1", operands, plen, 1); + else + avr_asm_len ("mov %A0,%C1" CR_TAB + "mov %B0,%D1", operands, plen, 2); + } + return reg1_unused_after_p + ? avr_asm_len ("clr %D0" CR_TAB + "clr %C0" CR_TAB + "rol %A0" CR_TAB + "rol %B0" CR_TAB + "rol %C0", operands, plen, 5) + : avr_asm_len ("clr %D0" CR_TAB + "clr %C0" CR_TAB + "lsl %A0" CR_TAB + "rol %B0" CR_TAB + "rol %C0" CR_TAB + "bld %A0,0", operands, plen, 6); case 16: if (reg0 == reg1 + 2) return avr_asm_len ("clr %C0" CR_TAB @@ -12556,6 +12651,9 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code, case 8: *total = COSTS_N_INSNS (5); break; + case 22: + *total = COSTS_N_INSNS (6); + break; case 23: *total = COSTS_N_INSNS (4); break; @@ -12589,6 +12687,9 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code, case 2: *total = COSTS_N_INSNS (!speed ? 7 : 8); break; + case 30: + *total = COSTS_N_INSNS (7 - AVR_HAVE_MOVW); + break; case 31: *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5); break; @@ -12723,8 +12824,13 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code, case 2: *total = COSTS_N_INSNS (!speed ? 7 : 8); break; - case 8: + case 15: + *total = COSTS_N_INSNS (8 - AVR_HAVE_MOVW); + break; case 16: + *total = COSTS_N_INSNS (4 - AVR_HAVE_MOVW); + break; + case 8: case 24: *total = COSTS_N_INSNS (4); break; diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index 2432cd615378..ac12af689380 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -611,10 +611,11 @@ struct GTY(()) machine_function __builtin_return_address. */ bool use_L__stack_usage; - /* Counts how many times the execute() method of the avr-fuse-add + /* Counts how many times the execute() method of the avr-fuse-add pass has been invoked. The count is even increased when the optimization - itself is not run. This purpose of this variable is to provide - information about where in the pass sequence we are. */ + itself is not run. The purpose of this variable is to provide + information about where in the pass sequence we are. + It is used in insn / split conditons. */ int n_avr_fuse_add_executed; }; diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 59e327fe7272..346847fa7d6e 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -5148,10 +5148,13 @@ [(set_attr "length" "5,0,1,2,3,4,6,9") (set_attr "adjust_len" "ashlqi")]) +;; "ashlhi3" +;; "ashlhq3" "ashluhq3" +;; "ashlha3" "ashluha3" (define_insn_and_split "ashl<mode>3" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r ,r,r,r") - (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r ,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O C15,K,n,Qm")))] + [(set (match_operand:ALL2 0 "register_operand" "=r,r ,r ,r,r") + (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0 ,r ,0,0") + (match_operand:QI 2 "nop_general_operand" "r,LPK,O C7c C15,n,Qm")))] "" "#" "&& reload_completed" @@ -5160,16 +5163,19 @@ (match_dup 2))) (clobber (reg:CC REG_CC))])]) +;; "*ashlhi3" +;; "*ashlhq3" "*ashluhq3" +;; "*ashlha3" "*ashluha3" (define_insn "*ashl<mode>3" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r ,r,r,r") - (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r ,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O C15,K,n,Qm"))) + [(set (match_operand:ALL2 0 "register_operand" "=r,r ,r ,r,r") + (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0 ,r ,0,0") + (match_operand:QI 2 "nop_general_operand" "r,LPK,O C7c C15,n,Qm"))) (clobber (reg:CC REG_CC))] "reload_completed" { return ashlhi3_out (insn, operands, NULL); } - [(set_attr "length" "6,0,2,3,4,10,10") + [(set_attr "length" "10") (set_attr "adjust_len" "ashlhi")]) @@ -5342,69 +5348,61 @@ operands[2] = avr_to_int_mode (operands[0]); }) -(define_peephole2 +(define_peephole2 ; *ashlhi3_const *ashrhi3_const *lshrhi3_const [(match_scratch:QI 3 "d") - (parallel [(set (match_operand:ALL2 0 "register_operand" "") - (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC REG_CC))])] + (parallel [(set (match_operand:ALL2 0 "register_operand") + (any_shift:ALL2 (match_operand:ALL2 1 "register_operand") + (match_operand:QI 2 "const_int_operand"))) + (clobber (reg:CC REG_CC))]) + ;; Don't allow $3 to overlap with $0. + (match_dup 3)] "" [(parallel [(set (match_dup 0) - (ashift:ALL2 (match_dup 1) - (match_dup 2))) + (any_shift:ALL2 (match_dup 1) + (match_dup 2))) (clobber (match_dup 3)) (clobber (reg:CC REG_CC))])]) ;; "*ashlhi3_const" ;; "*ashlhq3_const" "*ashluhq3_const" ;; "*ashlha3_const" "*ashluha3_const" -(define_insn_and_split "*ashl<mode>3_const_split" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r ,r,r") - (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r ,0,0") - (match_operand:QI 2 "const_int_operand" "L,P,O C15,K,n"))) - (clobber (match_scratch:QI 3 "=X,X,X ,X,&d"))] - "reload_completed" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 0) - (ashift:ALL2 (match_dup 1) - (match_dup 2))) - (clobber (match_dup 3)) - (clobber (reg:CC REG_CC))])]) - (define_insn "*ashl<mode>3_const" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r ,r,r") - (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r ,0,0") - (match_operand:QI 2 "const_int_operand" "L,P,O C15,K,n"))) - (clobber (match_scratch:QI 3 "=X,X,X ,X,&d")) + [(set (match_operand:ALL2 0 "register_operand" "=r ,r ,r") + (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0 ,r ,0") + (match_operand:QI 2 "const_int_operand" "LPK,O C7c C15,n"))) + (clobber (match_scratch:QI 3 "=X ,X ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { return ashlhi3_out (insn, operands, NULL); } - [(set_attr "length" "0,2,2,4,10") + [(set_attr "length" "10") (set_attr "adjust_len" "ashlhi")]) +(define_code_attr constr_split_shift4 + [(ashift "C4l") + (ashiftrt "C4a") + (lshiftrt "C4r")]) ;; Split shift into a byte shift and a residual bit shift (without scratch) (define_split [(parallel [(set (match_operand:ALL4 0 "register_operand") - (ashift:ALL4 (match_operand:ALL4 1 "register_operand") - (match_operand:QI 2 "const_int_operand"))) + (any_shift:ALL4 (match_operand:ALL4 1 "register_operand") + (match_operand:QI 2 "const_int_operand"))) (clobber (reg:CC REG_CC))])] "avropt_split_bit_shift && n_avr_fuse_add_executed >= 1 - && satisfies_constraint_C4l (operands[2])" + && satisfies_constraint_<constr_split_shift4> (operands[2])" [(parallel [(set (match_dup 0) - (ashift:ALL4 (match_dup 1) - (match_dup 3))) + (any_shift:ALL4 (match_dup 1) + (match_dup 3))) (clobber (reg:CC REG_CC))]) (parallel [(set (match_dup 0) - (ashift:ALL4 (match_dup 0) - (match_dup 4))) + (any_shift:ALL4 (match_dup 0) + (match_dup 4))) (clobber (reg:CC REG_CC))])] { - if (avr_split_shift (operands, NULL_RTX, ASHIFT)) + if (avr_split_shift (operands, NULL_RTX, <CODE>)) DONE; else if (REGNO (operands[0]) == REGNO (operands[1])) FAIL; @@ -5416,24 +5414,24 @@ ;; Split shift into a byte shift and a residual bit shift (with scratch) (define_split [(parallel [(set (match_operand:ALL4 0 "register_operand") - (ashift:ALL4 (match_operand:ALL4 1 "register_operand") - (match_operand:QI 2 "const_int_operand"))) - (clobber (match_operand:QI 3 "scratch_or_d_register_operand")) + (any_shift:ALL4 (match_operand:ALL4 1 "register_operand") + (match_operand:QI 2 "const_int_operand"))) + (clobber (match_operand:QI 3 "scratch_or_dreg_operand")) (clobber (reg:CC REG_CC))])] "avropt_split_bit_shift && n_avr_fuse_add_executed >= 1 - && satisfies_constraint_C4l (operands[2])" + && satisfies_constraint_<constr_split_shift4> (operands[2])" [(parallel [(set (match_dup 0) - (ashift:ALL4 (match_dup 1) - (match_dup 4))) + (any_shift:ALL4 (match_dup 1) + (match_dup 4))) (clobber (reg:CC REG_CC))]) (parallel [(set (match_dup 0) - (ashift:ALL4 (match_dup 0) - (match_dup 5))) + (any_shift:ALL4 (match_dup 0) + (match_dup 5))) (clobber (match_dup 3)) (clobber (reg:CC REG_CC))])] { - if (avr_split_shift (operands, operands[3], ASHIFT)) + if (avr_split_shift (operands, operands[3], <CODE>)) DONE; else if (REGNO (operands[0]) == REGNO (operands[1])) FAIL; @@ -5443,27 +5441,31 @@ }) -(define_peephole2 +;; Endow 4-byte shift with a scratch if available. +(define_peephole2 ; *ashrsi3_const *lshrsi3_const *ashlsi3_const [(match_scratch:QI 3 "d") - (parallel [(set (match_operand:ALL4 0 "register_operand" "") - (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) + (parallel [(set (match_operand:ALL4 0 "register_operand") + (any_shift:ALL4 (match_operand:ALL4 1 "register_operand") + (match_operand:QI 2 "const_int_operand"))) (clobber (reg:CC REG_CC))]) ;; $3 must not overlap with the output of the insn above. (match_dup 3)] "" [(parallel [(set (match_dup 0) - (ashift:ALL4 (match_dup 1) - (match_dup 2))) + (any_shift:ALL4 (match_dup 1) + (match_dup 2))) (clobber (match_dup 3)) (clobber (reg:CC REG_CC))])]) +;; "*ashlsi3_const" +;; "*ashlsq3_const" "*ashlusq3_const" +;; "*ashlsa3_const" "*ashlusa3_const" (define_insn "*ashl<mode>3_const" - [(set (match_operand:ALL4 0 "register_operand" "=r ,r ,r ,r ,r") - (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0 ,r ,0 ,r ,0") - (match_operand:QI 2 "const_int_operand" "LP,O C15 C31,C4l,C4l,n"))) - (clobber (match_operand:QI 3 "scratch_or_d_register_operand" "=X ,X ,&d ,&d ,&d")) + [(set (match_operand:ALL4 0 "register_operand" "=r ,r ,r ,r ,r") + (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0 ,r ,0 ,r ,0") + (match_operand:QI 2 "const_int_operand" "LP,O C15 C31,C4l,C4l,n"))) + (clobber (match_operand:QI 3 "scratch_or_dreg_operand" "=X ,X ,&d ,&d ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { @@ -5532,9 +5534,9 @@ ;; "ashrqi3" ;; "ashrqq3" "ashruqq3" (define_insn_and_split "ashr<mode>3" - [(set (match_operand:ALL1 0 "register_operand" "=r,r,r,r,r ,r ,r ,r") - (ashiftrt:ALL1 (match_operand:ALL1 1 "register_operand" "0,0,0,0,0 ,0 ,r ,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,K,C03 C04 C05,C06,C07,Qm")))] + [(set (match_operand:ALL1 0 "register_operand" "=r,r ,r ,r") + (ashiftrt:ALL1 (match_operand:ALL1 1 "register_operand" "0,0 ,r ,0") + (match_operand:QI 2 "nop_general_operand" "r,LPK C03 C04 C05,C06 C07,Qm")))] "" "#" "&& reload_completed" @@ -5544,24 +5546,24 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*ashr<mode>3" - [(set (match_operand:ALL1 0 "register_operand" "=r,r,r,r,r ,r ,r ,r") - (ashiftrt:ALL1 (match_operand:ALL1 1 "register_operand" "0,0,0,0,0 ,0 ,r ,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,K,C03 C04 C05,C06,C07,Qm"))) + [(set (match_operand:ALL1 0 "register_operand" "=r,r ,r ,r") + (ashiftrt:ALL1 (match_operand:ALL1 1 "register_operand" "0,0 ,r ,0") + (match_operand:QI 2 "nop_general_operand" "r,LPK C03 C04 C05,C06 C07,Qm"))) (clobber (reg:CC REG_CC))] "reload_completed" { return ashrqi3_out (insn, operands, NULL); } - [(set_attr "length" "5,0,1,2,5,4,3,9") + [(set_attr "length" "9") (set_attr "adjust_len" "ashrqi")]) ;; "ashrhi3" ;; "ashrhq3" "ashruhq3" ;; "ashrha3" "ashruha3" (define_insn_and_split "ashr<mode>3" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r ,r,r,r") - (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r ,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O C15,K,n,Qm")))] + [(set (match_operand:ALL2 0 "register_operand" "=r,r ,r ,r,r") + (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0 ,r ,0,0") + (match_operand:QI 2 "nop_general_operand" "r,LPK,O C14 C15,n,Qm")))] "" "#" "&& reload_completed" @@ -5570,23 +5572,26 @@ (match_dup 2))) (clobber (reg:CC REG_CC))])]) +;; "*ashrhi3" +;; "*ashrhq3" "*ashruhq3" +;; "*ashrha3" "*ashruha3" (define_insn "*ashr<mode>3" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r ,r,r,r") - (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r ,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O C15,K,n,Qm"))) + [(set (match_operand:ALL2 0 "register_operand" "=r,r ,r ,r,r") + (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0 ,r ,0,0") + (match_operand:QI 2 "nop_general_operand" "r,LPK,O C14 C15,n,Qm"))) (clobber (reg:CC REG_CC))] "reload_completed" { return ashrhi3_out (insn, operands, NULL); } - [(set_attr "length" "6,0,2,5,4,10,10") + [(set_attr "length" "10") (set_attr "adjust_len" "ashrhi")]) (define_insn_and_split "ashrpsi3" - [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r ,r") - (ashiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0,0,r ,0") - (match_operand:QI 2 "nonmemory_operand" "r,P,K,O C23,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,X ,&d"))] + [(set (match_operand:PSI 0 "register_operand" "=r,r ,r ,r") + (ashiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0 ,r ,0") + (match_operand:QI 2 "nonmemory_operand" "r,PK,O C22 C23,n"))) + (clobber (match_scratch:QI 3 "=X,X ,X ,&d"))] "" "#" "&& reload_completed" @@ -5597,10 +5602,10 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*ashrpsi3" - [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r ,r") - (ashiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0,0,r ,0") - (match_operand:QI 2 "nonmemory_operand" "r,P,K,O C23,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,X ,&d")) + [(set (match_operand:PSI 0 "register_operand" "=r,r ,r ,r") + (ashiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0 ,r ,0") + (match_operand:QI 2 "nonmemory_operand" "r,PK,O C22 C23,n"))) + (clobber (match_scratch:QI 3 "=X,X ,X ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { @@ -5612,115 +5617,65 @@ ;; "ashrsq3" "ashrusq3" ;; "ashrsa3" "ashrusa3" (define_insn_and_split "ashr<mode>3" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r ,r,r,r") - (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r ,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O C31,K,n,Qm")))] + [(set (match_operand:ALL4 0 "register_operand" "=r,r ,r ,r ,r ,r,r") + (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0 ,r ,0 ,r ,0,0") + (match_operand:QI 2 "nop_general_operand" "r,LPK,O C30 C31,C4a,C4a,n,Qm")))] "" "#" "&& reload_completed" [(parallel [(set (match_dup 0) (ashiftrt:ALL4 (match_dup 1) (match_dup 2))) - (clobber (reg:CC REG_CC))])]) + (clobber (reg:CC REG_CC))])] + "" + [(set_attr "isa" "*,*,*,2op,3op,*,*")]) (define_insn "*ashr<mode>3" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r ,r,r,r") - (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r ,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O C31,K,n,Qm"))) + [(set (match_operand:ALL4 0 "register_operand" "=r,r ,r ,r ,r ,r,r") + (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0 ,r ,0 ,r ,0,0") + (match_operand:QI 2 "nop_general_operand" "r,LPK,O C30 C31,C4a,C4a,n,Qm"))) (clobber (reg:CC REG_CC))] "reload_completed" { return ashrsi3_out (insn, operands, NULL); } - [(set_attr "length" "8,0,4,6,8,10,12") + [(set_attr "isa" "*,*,*,2op,3op,*,*") + (set_attr "length" "12") (set_attr "adjust_len" "ashrsi")]) -;; Optimize if a scratch register from LD_REGS happens to be available. - -(define_peephole2 - [(match_scratch:QI 3 "d") - (parallel [(set (match_operand:ALL2 0 "register_operand" "") - (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC REG_CC))])] - "" - [(parallel [(set (match_dup 0) - (ashiftrt:ALL2 (match_dup 1) - (match_dup 2))) - (clobber (match_dup 3)) - (clobber (reg:CC REG_CC))])]) ;; "*ashrhi3_const" ;; "*ashrhq3_const" "*ashruhq3_const" ;; "*ashrha3_const" "*ashruha3_const" -(define_insn_and_split "*ashr<mode>3_const_split" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r ,r,r") - (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r ,0,0") - (match_operand:QI 2 "const_int_operand" "L,P,O C15,K,n"))) - (clobber (match_scratch:QI 3 "=X,X,X ,X,&d"))] - "reload_completed" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 0) - (ashiftrt:ALL2 (match_dup 1) - (match_dup 2))) - (clobber (match_dup 3)) - (clobber (reg:CC REG_CC))])]) - (define_insn "*ashr<mode>3_const" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r ,r,r") - (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r ,0,0") - (match_operand:QI 2 "const_int_operand" "L,P,O C15,K,n"))) - (clobber (match_scratch:QI 3 "=X,X,X ,X,&d")) + [(set (match_operand:ALL2 0 "register_operand" "=r ,r ,r") + (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0 ,r ,0") + (match_operand:QI 2 "const_int_operand" "LPK,O C14 C15,n"))) + (clobber (match_scratch:QI 3 "=X ,X ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { return ashrhi3_out (insn, operands, NULL); } - [(set_attr "length" "0,2,4,4,10") + [(set_attr "length" "10") (set_attr "adjust_len" "ashrhi")]) -(define_peephole2 - [(match_scratch:QI 3 "d") - (parallel [(set (match_operand:ALL4 0 "register_operand" "") - (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC REG_CC))])] - "" - [(parallel [(set (match_dup 0) - (ashiftrt:ALL4 (match_dup 1) - (match_dup 2))) - (clobber (match_dup 3)) - (clobber (reg:CC REG_CC))])]) ;; "*ashrsi3_const" ;; "*ashrsq3_const" "*ashrusq3_const" ;; "*ashrsa3_const" "*ashrusa3_const" -(define_insn_and_split "*ashr<mode>3_const_split" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r ,r") - (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r ,0") - (match_operand:QI 2 "const_int_operand" "L,P,O C31,n"))) - (clobber (match_scratch:QI 3 "=X,X,X ,&d"))] - "reload_completed" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 0) - (ashiftrt:ALL4 (match_dup 1) - (match_dup 2))) - (clobber (match_dup 3)) - (clobber (reg:CC REG_CC))])]) - (define_insn "*ashr<mode>3_const" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r ,r") - (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r ,0") - (match_operand:QI 2 "const_int_operand" "L,P,O C31,n"))) - (clobber (match_scratch:QI 3 "=X,X,X ,&d")) + [(set (match_operand:ALL4 0 "register_operand" "=r ,r ,r ,r ,r") + (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0 ,r ,0 ,r ,0") + (match_operand:QI 2 "const_int_operand" "LP,O C30 C31,C4a,C4a,n"))) + (clobber (match_operand:QI 3 "scratch_or_dreg_operand" "=X ,X ,&d ,&d ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { return ashrsi3_out (insn, operands, NULL); } - [(set_attr "length" "0,4,4,10") + [(set_attr "isa" "*,*,2op,3op,*") + (set_attr "length" "10") (set_attr "adjust_len" "ashrsi")]) ;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> @@ -5802,9 +5757,9 @@ ;; "lshrhq3" "lshruhq3" ;; "lshrha3" "lshruha3" (define_insn_and_split "lshr<mode>3" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r ,r,r,r") - (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r,r ,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O,C15,K,n,Qm")))] + [(set (match_operand:ALL2 0 "register_operand" "=r,r ,r ,r,r") + (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0 ,r ,0,0") + (match_operand:QI 2 "nop_general_operand" "r,LPK,O C7c C15,n,Qm")))] "" "#" "&& reload_completed" @@ -5814,9 +5769,9 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*lshr<mode>3" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r ,r,r,r") - (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r,r ,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O,C15,K,n,Qm"))) + [(set (match_operand:ALL2 0 "register_operand" "=r,r ,r ,r,r") + (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0 ,r ,0,0") + (match_operand:QI 2 "nop_general_operand" "r,LPK,O C7c C15,n,Qm"))) (clobber (reg:CC REG_CC))] "reload_completed" { @@ -5854,27 +5809,30 @@ ;; "lshrsq3" "lshrusq3" ;; "lshrsa3" "lshrusa3" (define_insn_and_split "lshr<mode>3" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r,r,r ,r,r") - (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r,0,r ,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,C31,n,Qm")))] + [(set (match_operand:ALL4 0 "register_operand" "=r,r ,r ,r ,r ,r,r") + (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0 ,r ,0 ,r ,0,0") + (match_operand:QI 2 "nop_general_operand" "r,LPK,O C15 C31,C4r,C4r,n,Qm")))] "" "#" "&& reload_completed" [(parallel [(set (match_dup 0) (lshiftrt:ALL4 (match_dup 1) (match_dup 2))) - (clobber (reg:CC REG_CC))])]) + (clobber (reg:CC REG_CC))])] + "" + [(set_attr "isa" "*,*,*,2op,3op,*,*")]) (define_insn "*lshr<mode>3" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r,r,r ,r,r") - (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r,0,r ,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,C31,n,Qm"))) + [(set (match_operand:ALL4 0 "register_operand" "=r,r ,r ,r ,r ,r,r") + (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0 ,r ,0 ,r ,0,0") + (match_operand:QI 2 "nop_general_operand" "r,LPK,O C15 C31,C4r,C4r,n,Qm"))) (clobber (reg:CC REG_CC))] "reload_completed" { return lshrsi3_out (insn, operands, NULL); } - [(set_attr "adjust_len" "lshrsi")]) + [(set_attr "isa" "*,*,*,2op,3op,*,*") + (set_attr "adjust_len" "lshrsi")]) ;; Optimize if a scratch register from LD_REGS happens to be available. @@ -5933,41 +5891,15 @@ operands[2] = avr_to_int_mode (operands[0]); }) -(define_peephole2 ; "*lshrhi3_const" - [(match_scratch:QI 3 "d") - (parallel [(set (match_operand:ALL2 0 "register_operand" "") - (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC REG_CC))])] - "" - [(parallel [(set (match_dup 0) - (lshiftrt:ALL2 (match_dup 1) - (match_dup 2))) - (clobber (match_dup 3)) - (clobber (reg:CC REG_CC))])]) ;; "*lshrhi3_const" ;; "*lshrhq3_const" "*lshruhq3_const" ;; "*lshrha3_const" "*lshruha3_const" -(define_insn_and_split "*lshr<mode>3_const_split" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r ,r,r") - (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r,r ,0,0") - (match_operand:QI 2 "const_int_operand" "L,P,O,C15,K,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,X ,X,&d"))] - "reload_completed" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 0) - (lshiftrt:ALL2 (match_dup 1) - (match_dup 2))) - (clobber (match_dup 3)) - (clobber (reg:CC REG_CC))])]) - (define_insn "*lshr<mode>3_const" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r ,r,r") - (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r,r ,0,0") - (match_operand:QI 2 "const_int_operand" "L,P,O,C15,K,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,X ,X,&d")) + [(set (match_operand:ALL2 0 "register_operand" "=r ,r ,r") + (lshiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0 ,r ,0") + (match_operand:QI 2 "const_int_operand" "LPK,O C7c C15,n"))) + (clobber (match_scratch:QI 3 "=X ,X ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { @@ -5975,47 +5907,22 @@ } [(set_attr "adjust_len" "lshrhi")]) -(define_peephole2 ; "*lshrsi3_const" - [(match_scratch:QI 3 "d") - (parallel [(set (match_operand:ALL4 0 "register_operand" "") - (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC REG_CC))])] - "" - [(parallel [(set (match_dup 0) - (lshiftrt:ALL4 (match_dup 1) - (match_dup 2))) - (clobber (match_dup 3)) - (clobber (reg:CC REG_CC))])]) ;; "*lshrsi3_const" ;; "*lshrsq3_const" "*lshrusq3_const" ;; "*lshrsa3_const" "*lshrusa3_const" -(define_insn_and_split "*lshr<mode>3_const_split" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r ,r") - (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r,r ,0") - (match_operand:QI 2 "const_int_operand" "L,P,O,C31,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,X ,&d"))] - "reload_completed" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 0) - (lshiftrt:ALL4 (match_dup 1) - (match_dup 2))) - (clobber (match_dup 3)) - (clobber (reg:CC REG_CC))])]) - (define_insn "*lshr<mode>3_const" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r ,r") - (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r,r ,0") - (match_operand:QI 2 "const_int_operand" "L,P,O,C31,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,X ,&d")) + [(set (match_operand:ALL4 0 "register_operand" "=r ,r ,r ,r ,r") + (lshiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0 ,r ,0 ,r ,0") + (match_operand:QI 2 "const_int_operand" "LP,O C15 C31,C4r,C4r,n"))) + (clobber (match_operand:QI 3 "scratch_or_dreg_operand" "=X ,X ,&d ,&d ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { return lshrsi3_out (insn, operands, NULL); } - [(set_attr "adjust_len" "lshrsi")]) + [(set_attr "isa" "*,*,2op,3op,*") + (set_attr "adjust_len" "lshrsi")]) ;; abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) abs(x) ;; abs @@ -7099,7 +7006,7 @@ [(parallel [(set (match_operand:HISI 0 "register_operand") (plus:HISI (match_dup 0) (match_operand:HISI 1 "nonmemory_operand"))) - (clobber (match_operand:QI 3 "scratch_or_d_register_operand")) + (clobber (match_operand:QI 3 "scratch_or_dreg_operand")) (clobber (reg:CC REG_CC))]) (parallel [(set (reg:CC REG_CC) (compare:CC (match_dup 0) @@ -8167,7 +8074,7 @@ (parallel [(set (reg:CC REG_CC) (compare:CC (match_dup 0) (const_int -1))) - (clobber (match_operand:QI 1 "scratch_or_d_register_operand"))]) + (clobber (match_operand:QI 1 "scratch_or_dreg_operand"))]) (set (pc) (if_then_else (eqne (reg:CC REG_CC) (const_int 0)) @@ -8247,7 +8154,7 @@ (parallel [(set (reg:CC REG_CC) (compare:CC (match_dup 0) (const_int -1))) - (clobber (match_operand:QI 1 "scratch_or_d_register_operand"))]) + (clobber (match_operand:QI 1 "scratch_or_dreg_operand"))]) (set (pc) (if_then_else (eqne (reg:CC REG_CC) (const_int 0)) diff --git a/gcc/config/avr/constraints.md b/gcc/config/avr/constraints.md index a362f31e30b8..22bb4575089f 100644 --- a/gcc/config/avr/constraints.md +++ b/gcc/config/avr/constraints.md @@ -133,16 +133,36 @@ (and (match_code "const_int") (match_test "ival == 7"))) +(define_constraint "C7c" + "Constant integer the range 7 @dots{} 12." + (and (match_code "const_int") + (match_test "IN_RANGE (ival, 7, 12)"))) + +(define_constraint "C14" + "Constant integer 14." + (and (match_code "const_int") + (match_test "ival == 14"))) + (define_constraint "C15" "Constant integer 15." (and (match_code "const_int") (match_test "ival == 15"))) +(define_constraint "C22" + "Constant integer 22." + (and (match_code "const_int") + (match_test "ival == 22"))) + (define_constraint "C23" "Constant integer 23." (and (match_code "const_int") (match_test "ival == 23"))) +(define_constraint "C30" + "Constant integer 30." + (and (match_code "const_int") + (match_test "ival == 30"))) + (define_constraint "C31" "Constant integer 31." (and (match_code "const_int") diff --git a/gcc/config/avr/predicates.md b/gcc/config/avr/predicates.md index d852f1c9e084..a28c63a6478f 100644 --- a/gcc/config/avr/predicates.md +++ b/gcc/config/avr/predicates.md @@ -27,7 +27,7 @@ (and (match_code "reg") (match_test "REGNO (op) >= 16 && REGNO (op) <= 31"))) -(define_predicate "scratch_or_d_register_operand" +(define_predicate "scratch_or_dreg_operand" (ior (match_operand 0 "d_register_operand") (and (match_code ("scratch")) (match_operand 0 "scratch_operand")))) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index a8662efb5cb2..44f0fd297b29 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -905,7 +905,7 @@ Objective-C and Objective-C++ Dialects}. -mdouble=@var{bits} -mlong-double=@var{bits} -mn_flash=@var{size} -mno-interrupts -mmain-is-OS_task -mrelax -mrmw -mstrict-X -mtiny-stack --mrodata-in-ram -mfract-convert-truncate +-mrodata-in-ram -mfract-convert-truncate -msplit-bit-shift -mshort-calls -mskip-bug -nodevicelib -nodevicespecs -Waddr-space-convert -Wmisspelled-isr} @@ -24252,6 +24252,15 @@ ld @var{Rn}, X ; @var{Rn} = *X sbiw r26, const ; X -= const @end example +@opindex msplit-bit-shift +@item -msplit-bit-shift +Split multi-byte shifts into a shift with a byte offset and a residual +shift with a non-byte offset. This optimization is turned on per default +for @option{-O2} and higher, including @option{-Os} but excluding +@option{-Oz}. To date, only 4-byte shifts with a shift offset of +at least 17 are split. Splitting of shifts with an offset that is +a multiple of 8 is controlled by @option{-mfuse-move}. + @opindex mtiny-stack @item -mtiny-stack Only change the lower 8@tie{}bits of the stack pointer.