aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2024-11-21 22:59:14 +0100
committerGeorg-Johann Lay <avr@gjlay.de>2024-11-22 21:47:31 +0100
commit939362411d0903542647dae0eff82db10a3ad78a (patch)
treecc2aae35ca73adb781400b49ed5203e55537140d /gcc
parent84a335eb4f9641a471184d86900609dd97215218 (diff)
downloadgcc-939362411d0903542647dae0eff82db10a3ad78a.zip
gcc-939362411d0903542647dae0eff82db10a3ad78a.tar.gz
gcc-939362411d0903542647dae0eff82db10a3ad78a.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/avr/avr-passes.cc95
-rw-r--r--gcc/config/avr/avr.cc174
-rw-r--r--gcc/config/avr/avr.h7
-rw-r--r--gcc/config/avr/avr.md371
-rw-r--r--gcc/config/avr/constraints.md20
-rw-r--r--gcc/config/avr/predicates.md2
-rw-r--r--gcc/doc/invoke.texi11
7 files changed, 395 insertions, 285 deletions
diff --git a/gcc/config/avr/avr-passes.cc b/gcc/config/avr/avr-passes.cc
index 57c3fed..bd249b7 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 cc13dae..64d7795f 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 2432cd6..ac12af6 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 59e327f..346847f 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 a362f31..22bb457 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 d852f1c..a28c63a 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 a8662ef..44f0fd2 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.