aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/avr/avr.cc
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2024-12-02 12:31:18 +0100
committerGeorg-Johann Lay <avr@gjlay.de>2024-12-03 12:21:57 +0100
commitd203f4cb968a1dc45c7fcd1bf5d7cd485ca6f510 (patch)
treec77548e48242a5cffcf84f13787ab562d6d25286 /gcc/config/avr/avr.cc
parentd777d66cc168a5019dad8e60b075c82b6207f199 (diff)
downloadgcc-d203f4cb968a1dc45c7fcd1bf5d7cd485ca6f510.zip
gcc-d203f4cb968a1dc45c7fcd1bf5d7cd485ca6f510.tar.gz
gcc-d203f4cb968a1dc45c7fcd1bf5d7cd485ca6f510.tar.bz2
AVR: Tweak uin8_t << 6 and uint8_t >> 6 shifts.
Logic 8-bit shifts with an offset of 6 can be improved by supporting them as 3-operand operations. PR target/117726 gcc/ * config/avr/avr-passes.cc (avr_emit_shift): All 8-bit shifts with an offset of 6 have 3-operand alternatives. * config/avr/avr.cc (ashlqi3_out, lshrqi3_out) [case 6]: Implement as 3-operand insn. (avr_rtx_costs_1) [QImode, ASHIFT + LSHIFTRT]: Adjust costs for offset of 6. * config/avr/avr.md (*ashlqi3_split, *ashlqi3) (*lshrqi3_split, *lshrqi3): Add "r,r,C06" alternative.
Diffstat (limited to 'gcc/config/avr/avr.cc')
-rw-r--r--gcc/config/avr/avr.cc70
1 files changed, 57 insertions, 13 deletions
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 32028df..ccf9b05 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -6780,6 +6780,8 @@ ashlqi3_out (rtx_insn *insn, rtx operands[], int *plen)
{
if (CONST_INT_P (operands[2]))
{
+ int reg0 = REGNO (operands[0]);
+ int reg1 = REGNO (operands[1]);
bool ldreg_p = test_hard_reg_class (LD_REGS, operands[0]);
int offs = INTVAL (operands[2]);
@@ -6787,7 +6789,7 @@ ashlqi3_out (rtx_insn *insn, rtx operands[], int *plen)
*plen = 0;
if (offs <= 3
- || (offs <= 6 && ! ldreg_p))
+ || (offs <= 5 && ! ldreg_p))
{
for (int i = 0; i < offs; ++i)
avr_asm_len ("lsl %0", operands, plen, 1);
@@ -6814,10 +6816,28 @@ ashlqi3_out (rtx_insn *insn, rtx operands[], int *plen)
"lsl %0" CR_TAB
"andi %0,0xe0", operands, plen, 3);
case 6:
- return avr_asm_len ("swap %0" CR_TAB
- "lsl %0" CR_TAB
- "lsl %0" CR_TAB
- "andi %0,0xc0", operands, plen, 4);
+ if (ldreg_p && reg0 == reg1)
+ return avr_asm_len ("swap %0" CR_TAB
+ "lsl %0" CR_TAB
+ "lsl %0" CR_TAB
+ "andi %0,0xc0", operands, plen, 4);
+ if (ldreg_p && reg0 != reg1 && AVR_HAVE_MUL)
+ return avr_asm_len ("ldi %0,1<<6" CR_TAB
+ "mul %0,%1" CR_TAB
+ "mov %0,r0" CR_TAB
+ "clr __zero_reg__", operands, plen, 4);
+ return reg0 != reg1
+ ? avr_asm_len ("clr %0" CR_TAB
+ "bst %1,0" CR_TAB
+ "bld %0,6" CR_TAB
+ "bst %1,1" CR_TAB
+ "bld %0,7", operands, plen, 5)
+ : avr_asm_len ("lsl %0" CR_TAB
+ "lsl %0" CR_TAB
+ "lsl %0" CR_TAB
+ "lsl %0" CR_TAB
+ "lsl %0" CR_TAB
+ "lsl %0", operands, plen, 6);
case 7:
return avr_asm_len ("bst %1,0" CR_TAB
"clr %0" CR_TAB
@@ -7663,6 +7683,8 @@ lshrqi3_out (rtx_insn *insn, rtx operands[], int *plen)
{
if (CONST_INT_P (operands[2]))
{
+ int reg0 = REGNO (operands[0]);
+ int reg1 = REGNO (operands[1]);
bool ldreg_p = test_hard_reg_class (LD_REGS, operands[0]);
int offs = INTVAL (operands[2]);
@@ -7670,7 +7692,7 @@ lshrqi3_out (rtx_insn *insn, rtx operands[], int *plen)
*plen = 0;
if (offs <= 3
- || (offs <= 6 && ! ldreg_p))
+ || (offs <= 5 && ! ldreg_p))
{
for (int i = 0; i < offs; ++i)
avr_asm_len ("lsr %0", operands, plen, 1);
@@ -7697,10 +7719,28 @@ lshrqi3_out (rtx_insn *insn, rtx operands[], int *plen)
"lsr %0" CR_TAB
"andi %0,0x7", operands, plen, 3);
case 6:
- return avr_asm_len ("swap %0" CR_TAB
- "lsr %0" CR_TAB
- "lsr %0" CR_TAB
- "andi %0,0x3", operands, plen, 4);
+ if (ldreg_p && reg0 == reg1)
+ return avr_asm_len ("swap %0" CR_TAB
+ "lsr %0" CR_TAB
+ "lsr %0" CR_TAB
+ "andi %0,0x3", operands, plen, 4);
+ if (ldreg_p && reg0 != reg1 && AVR_HAVE_MUL)
+ return avr_asm_len ("ldi %0,1<<2" CR_TAB
+ "mul %0,%1" CR_TAB
+ "mov %0,r1" CR_TAB
+ "clr __zero_reg__", operands, plen, 4);
+ return reg0 != reg1
+ ? avr_asm_len ("clr %0" CR_TAB
+ "bst %1,6" CR_TAB
+ "bld %0,0" CR_TAB
+ "bst %1,7" CR_TAB
+ "bld %0,1", operands, plen, 5)
+ : avr_asm_len ("lsr %0" CR_TAB
+ "lsr %0" CR_TAB
+ "lsr %0" CR_TAB
+ "lsr %0" CR_TAB
+ "lsr %0" CR_TAB
+ "lsr %0", operands, plen, 6);
case 7:
return avr_asm_len ("bst %1,7" CR_TAB
"clr %0" CR_TAB
@@ -12528,7 +12568,9 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
{
if (val1 == 7)
*total = COSTS_N_INSNS (3);
- else if (val1 >= 0 && val1 <= 7)
+ else if (val1 == 6)
+ *total = COSTS_N_INSNS (5 - AVR_HAVE_MUL);
+ else if (val1 >= 0 && val1 <= 5)
*total = COSTS_N_INSNS (val1);
else
*total = COSTS_N_INSNS (1);
@@ -12688,7 +12730,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (4);
else if (val1 == 7)
*total = COSTS_N_INSNS (2);
- else if (val1 >= 0 && val1 <= 7)
+ else if (val1 >= 0 && val1 <= 5)
*total = COSTS_N_INSNS (val1);
else
*total = COSTS_N_INSNS (1);
@@ -12851,7 +12893,9 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
{
if (val1 == 7)
*total = COSTS_N_INSNS (3);
- else if (val1 >= 0 && val1 <= 7)
+ else if (val1 == 6)
+ *total = COSTS_N_INSNS (5 - AVR_HAVE_MUL);
+ else if (val1 >= 0 && val1 <= 5)
*total = COSTS_N_INSNS (val1);
else
*total = COSTS_N_INSNS (1);