[patch,avr] Slightly better memory accesses on avr_tiny

2016-07-19 Thread Georg-Johann Lay
This patch tries to improve the bloated code we are currently generating for 
AVR_TINY.  It's mostly about printing the memory loads and stores and more 
usage of reg_unused_after to print shorter instruction sequences in some cases.


Ok for trunk?

I also played around with PLUS in legitimate_address_p and legitimize_address 
and got better code, but the problem with such changes is that almost all tests 
for such small devices are failing and no reasonable portion of the testsuite 
will pass.


I don't even know if anybody is using avr_tiny + avr-gcc or if users are 
resorting to assembler.


Johann


gcc/
(avr_legitimize_address) [AVR_TINY]: Force constant addresses
outside [0,0xc0] into a register.
(avr_out_movhi_r_mr_reg_no_disp_tiny): Pass insn.  And handle
cases where the base address register is unused after.
(avr_out_movhi_r_mr_reg_disp_tiny): Same.
(avr_out_movhi_mr_r_reg_disp_tiny): Same.
(avr_out_store_psi_reg_disp_tiny): Same.

gcc/testsuite/
* gcc.target/avr/torture/get-mem.c: New test.
* gcc.target/avr/torture/set-mem.c: New test.
Index: config/avr/avr.c
===
--- config/avr/avr.c	(revision 238425)
+++ config/avr/avr.c	(working copy)
@@ -1922,6 +1922,16 @@ avr_legitimize_address (rtx x, rtx oldx,
 
   x = oldx;
 
+  if (AVR_TINY)
+{
+  if (CONSTANT_ADDRESS_P (x)
+  && !(CONST_INT_P (x)
+   && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode
+{
+  x = force_reg (Pmode, x);
+}
+}
+
   if (GET_CODE (oldx) == PLUS
   && REG_P (XEXP (oldx, 0)))
 {
@@ -3510,7 +3520,7 @@ out_movqi_r_mr (rtx_insn *insn, rtx op[]
 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
 
 static const char*
-avr_out_movhi_r_mr_reg_no_disp_tiny (rtx op[], int *plen)
+avr_out_movhi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
 {
   rtx dest = op[0];
   rtx src = op[1];
@@ -3524,17 +3534,20 @@ avr_out_movhi_r_mr_reg_no_disp_tiny (rtx
 			"ld %B0,%1"  CR_TAB
 			"mov %A0,__tmp_reg__", op, plen, -3);
 
-  return avr_asm_len ("ld %A0,%1" CR_TAB
-  TINY_ADIW (%E1, %F1, 1) CR_TAB
-  "ld %B0,%1" CR_TAB
-  TINY_SBIW (%E1, %F1, 1), op, plen, -6);
+  avr_asm_len ("ld %A0,%1+"  CR_TAB
+   "ld %B0,%1", op, plen, -2);
+
+  if (!reg_unused_after (insn, base))
+avr_asm_len (TINY_SBIW (%E1, %F1, 1), op, plen, 2);
+
+  return "";
 }
 
 
 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
 
 static const char*
-avr_out_movhi_r_mr_reg_disp_tiny (rtx op[], int *plen)
+avr_out_movhi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
 {
   rtx dest = op[0];
   rtx src = op[1];
@@ -3552,10 +3565,14 @@ avr_out_movhi_r_mr_reg_disp_tiny (rtx op
 }
   else
 {
-  return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
-  "ld %A0,%b1+" CR_TAB
-  "ld %B0,%b1"  CR_TAB
-  TINY_SBIW (%I1, %J1, %o1+1), op, plen, -6);
+  avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
+   "ld %A0,%b1+" CR_TAB
+   "ld %B0,%b1", op, plen, -4);
+
+  if (!reg_unused_after (insn, XEXP (base, 0)))
+avr_asm_len (TINY_SBIW (%I1, %J1, %o1+1), op, plen, 2);
+
+  return "";
 }
 }
 
@@ -3603,7 +3620,7 @@ out_movhi_r_mr (rtx_insn *insn, rtx op[]
   if (reg_base > 0)
 {
   if (AVR_TINY)
-return avr_out_movhi_r_mr_reg_no_disp_tiny (op, plen);
+return avr_out_movhi_r_mr_reg_no_disp_tiny (insn, op, plen);
 
   if (reg_dest == reg_base) /* R = (R) */
 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
@@ -3628,7 +3645,7 @@ out_movhi_r_mr (rtx_insn *insn, rtx op[]
   int reg_base = true_regnum (XEXP (base, 0));
 
   if (AVR_TINY)
-return avr_out_movhi_r_mr_reg_disp_tiny (op, plen);
+return avr_out_movhi_r_mr_reg_disp_tiny (insn, op, plen);
 
   if (disp > MAX_LD_OFFSET (GET_MODE (src)))
 {
@@ -4377,8 +4394,8 @@ avr_out_load_psi_reg_no_disp_tiny (rtx_i
 		   "ld %B0,%1+"  CR_TAB
 		   "ld %C0,%1", op, plen, -3);
 
-  if (reg_dest != reg_base - 2 &&
-  !reg_unused_after (insn, base))
+  if (reg_dest != reg_base - 2
+  && !reg_unused_after (insn, base))
 {
   avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
 }
@@ -4408,13 +4425,13 @@ avr_out_load_psi_reg_disp_tiny (rtx_insn
   else
 {
   avr_asm_len (TINY_ADIW (%I1, %J1, %o1)   CR_TAB
-  "ld %A0,%b1+"  CR_TAB
-  "ld %B0,%b1+"  CR_TAB
-  "ld %C0,%b1", op, plen, -5);
+   "ld %A0,%b1+"   CR_TAB
+   "ld %B0,%b1+"   CR_TAB

Re: [patch,avr] Slightly better memory accesses on avr_tiny

2016-07-19 Thread Denis Chertykov
2016-07-19 13:31 GMT+03:00 Georg-Johann Lay :
> This patch tries to improve the bloated code we are currently generating for
> AVR_TINY.  It's mostly about printing the memory loads and stores and more
> usage of reg_unused_after to print shorter instruction sequences in some
> cases.
>
> Ok for trunk?
>
> I also played around with PLUS in legitimate_address_p and
> legitimize_address and got better code, but the problem with such changes is
> that almost all tests for such small devices are failing and no reasonable
> portion of the testsuite will pass.
>
> I don't even know if anybody is using avr_tiny + avr-gcc or if users are
> resorting to assembler.
>

Keep Calm and Carry On
;-)

> Johann
>
>
> gcc/
> (avr_legitimize_address) [AVR_TINY]: Force constant addresses
> outside [0,0xc0] into a register.
> (avr_out_movhi_r_mr_reg_no_disp_tiny): Pass insn.  And handle
> cases where the base address register is unused after.
> (avr_out_movhi_r_mr_reg_disp_tiny): Same.
> (avr_out_movhi_mr_r_reg_disp_tiny): Same.
> (avr_out_store_psi_reg_disp_tiny): Same.
>
> gcc/testsuite/
> * gcc.target/avr/torture/get-mem.c: New test.
> * gcc.target/avr/torture/set-mem.c: New test.

Approved.