[gcc r14-9389] AVR: Add an insn combine pattern for offset computation.

2024-03-08 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:40209cb15a3f2af8233ee887dc960992f358ad86

commit r14-9389-g40209cb15a3f2af8233ee887dc960992f358ad86
Author: Georg-Johann Lay 
Date:   Fri Mar 8 13:29:13 2024 +0100

AVR: Add an insn combine pattern for offset computation.

Computing  uint16_t += 2 * uint8_t  can occur when an offset
into a 16-bit array is computed.  Without this pattern is costs
six instructions: A move (1), a zero-extend (1), a shift (2) and
an addition (2).  With this pattern it costs 4.

gcc/
* config/avr/avr.md (*addhi3_zero_extend.ashift1): New pattern.
* config/avr/avr.cc (avr_rtx_costs_1) [PLUS]: Compute its cost.

Diff:
---
 gcc/config/avr/avr.cc | 11 +++
 gcc/config/avr/avr.md | 33 +
 2 files changed, 44 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index b87ae6a256d..1fa4b557f5d 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -12513,6 +12513,17 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int 
outer_code,
   return true;
 
 case PLUS:
+  // uint16_t += 2 * uint8_t;
+  if (mode == HImode
+ && GET_CODE (XEXP (x, 0)) == ASHIFT
+ && REG_P (XEXP (x, 1))
+ && XEXP (XEXP (x, 0), 1) == const1_rtx
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND)
+   {
+ *total = COSTS_N_INSNS (4);
+ return true;
+   }
+
   if (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
  && REG_P (XEXP (x, 1)))
{
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index bc8a59c956c..52b6cff4a8b 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -1630,6 +1630,39 @@
   "subi %A0,%n2\;sbc %B0,%B0"
   [(set_attr "length" "2")])
 
+
+;; Occurs when computing offsets into 16-bit arrays.
+;; Saves up to 2 instructions.
+(define_insn_and_split "*addhi3_zero_extend.ashift1.split"
+  [(set (match_operand:HI 0 "register_operand" 
   "=r")
+(plus:HI (ashift:HI (zero_extend:HI (match_operand:QI 1 
"register_operand" "r"))
+(const_int 1))
+ (match_operand:HI 2 "register_operand"
"0")))]
+  ""
+  "#"
+  "&& reload_completed"
+  [(parallel [(set (match_dup 0)
+   (plus:HI (ashift:HI (zero_extend:HI (match_dup 1))
+   (const_int 1))
+(match_dup 2)))
+  (clobber (reg:CC REG_CC))])])
+
+(define_insn "*addhi3_zero_extend.ashift1"
+  [(set (match_operand:HI 0 "register_operand" 
   "=r")
+(plus:HI (ashift:HI (zero_extend:HI (match_operand:QI 1 
"register_operand" "r"))
+(const_int 1))
+ (match_operand:HI 2 "register_operand"
"0")))
+   (clobber (reg:CC REG_CC))]
+  "reload_completed"
+  {
+return reg_overlap_mentioned_p (operands[1], operands[0])
+  ? "mov __tmp_reg__,%1\;add %A0,__tmp_reg__\;adc %B0,__zero_reg__\;add 
%A0,__tmp_reg__\;adc %B0,__zero_reg__"
+  : "add %A0,%1\;adc %B0,__zero_reg__\;add %A0,%1\;adc %B0,__zero_reg__";
+  }
+  [(set (attr "length")
+(symbol_ref ("4 + reg_overlap_mentioned_p (operands[1], 
operands[0])")))])
+
+
 (define_insn_and_split "*usum_widenqihi3_split"
   [(set (match_operand:HI 0 "register_operand"  "=r")
 (plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand"  "0"))


[gcc r15-207] AVR: ipa/92606 - Don't optimize PROGMEM data against non-PROGMEM.

2024-05-06 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:08e752e72363ae7fd5a5fcb70913a0f7b240387b

commit r15-207-g08e752e72363ae7fd5a5fcb70913a0f7b240387b
Author: Georg-Johann Lay 
Date:   Fri May 3 18:47:50 2024 +0200

AVR: ipa/92606 - Don't optimize PROGMEM data against non-PROGMEM.

ipa/92606: Inter-procedural analysis optimizes data across
address-spaces and PROGMEM.  As of v14, the PROGMEM part is
still not fixed (and there is still no target hook as proposed
in PR92932).  Just disable respective bogus optimization.

PR ipa/92606
gcc/
* config/avr/avr.cc (avr_option_override): Set
flag_ipa_icf_variables = 0.
gcc/testsuite/
* gcc.target/avr/torture/pr92606.c: New test.

Diff:
---
 gcc/config/avr/avr.cc  |  6 +++
 gcc/testsuite/gcc.target/avr/torture/pr92606.c | 57 ++
 2 files changed, 63 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 510e4cea19f..74924ab0565 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -1140,6 +1140,12 @@ avr_option_override (void)
   if (targetm.addr_space.zero_address_valid (ADDR_SPACE_GENERIC))
 flag_delete_null_pointer_checks = 0;
 
+  /* PR ipa/92606: Inter-procedural analysis optimizes data across
+ address-spaces and PROGMEM.  As of v14, the PROGMEM part is
+ still not fixed (and there is still no target hook as proposed
+ in PR92932).  Just disable respective bogus optimization.  */
+  flag_ipa_icf_variables = 0;
+
   if (flag_pic == 1)
 warning (OPT_fpic, "%<-fpic%> is not supported");
   if (flag_pic == 2)
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr92606.c 
b/gcc/testsuite/gcc.target/avr/torture/pr92606.c
new file mode 100644
index 000..cc07128c73b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr92606.c
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
+
+typedef uint32_t T;
+
+#define NI __attribute__((noinline,noclone))
+
+
+#ifndef __AVR_TINY__
+#define read_u32(X) \
+(__extension__( \
+{   \
+uint16_t __addr16 = (uint16_t)(X);  \
+uint32_t __result;  \
+__asm__ __volatile__ ("lpm %A0, Z+" "\n\t"  \
+  "lpm %B0, Z+" "\n\t"  \
+  "lpm %C0, Z+" "\n\t"  \
+  "lpm %D0, Z" "\n\t"   \
+  : "=r" (__result), "+z" (__addr16));  \
+__result;   \
+}))
+#else
+NI uint32_t read_u32 (const uint32_t *p)
+{
+   return *p;
+}
+#endif
+
+static const __attribute((progmem)) T xyz_prog[] = { 123, 123, 123 };
+T xyz[] = { 123, 123, 123 };
+volatile int x = 0;
+
+NI void prf (T f)
+{
+if (f != 123)
+__builtin_abort();
+}
+
+NI void func_progmem()
+{
+prf (read_u32 (&xyz_prog[0]));
+}
+
+NI void func_ram()
+{
+prf (xyz[x]);
+}
+
+int main (void)
+{
+func_progmem();
+func_ram();
+
+   return 0;
+}


[gcc r13-8699] AVR: ipa/92606 - Don't optimize PROGMEM data against non-PROGMEM.

2024-05-06 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:287293786d541217e7bf47cab6b8fb522ae9156a

commit r13-8699-g287293786d541217e7bf47cab6b8fb522ae9156a
Author: Georg-Johann Lay 
Date:   Fri May 3 18:47:50 2024 +0200

AVR: ipa/92606 - Don't optimize PROGMEM data against non-PROGMEM.

ipa/92606: Inter-procedural analysis optimizes data across
address-spaces and PROGMEM.  As of v14, the PROGMEM part is
still not fixed (and there is still no target hook as proposed
in PR92932).  Just disable respective bogus optimization.

PR ipa/92606
gcc/
* config/avr/avr.cc (avr_option_override): Set
flag_ipa_icf_variables = 0.
gcc/testsuite/
* gcc.target/avr/torture/pr92606.c: New test.

(cherry picked from commit 08e752e72363ae7fd5a5fcb70913a0f7b240387b)

Diff:
---
 gcc/config/avr/avr.cc  |  6 +++
 gcc/testsuite/gcc.target/avr/torture/pr92606.c | 57 ++
 2 files changed, 63 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index f8c4eb327a2..a5c628134b4 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -1112,6 +1112,12 @@ avr_option_override (void)
   if (targetm.addr_space.zero_address_valid (ADDR_SPACE_GENERIC))
 flag_delete_null_pointer_checks = 0;
 
+  /* PR ipa/92606: Inter-procedural analysis optimizes data across
+ address-spaces and PROGMEM.  As of v14, the PROGMEM part is
+ still not fixed (and there is still no target hook as proposed
+ in PR92932).  Just disable respective bogus optimization.  */
+  flag_ipa_icf_variables = 0;
+
   if (flag_pic == 1)
 warning (OPT_fpic, "%<-fpic%> is not supported");
   if (flag_pic == 2)
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr92606.c 
b/gcc/testsuite/gcc.target/avr/torture/pr92606.c
new file mode 100644
index 000..cc07128c73b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr92606.c
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
+
+typedef uint32_t T;
+
+#define NI __attribute__((noinline,noclone))
+
+
+#ifndef __AVR_TINY__
+#define read_u32(X) \
+(__extension__( \
+{   \
+uint16_t __addr16 = (uint16_t)(X);  \
+uint32_t __result;  \
+__asm__ __volatile__ ("lpm %A0, Z+" "\n\t"  \
+  "lpm %B0, Z+" "\n\t"  \
+  "lpm %C0, Z+" "\n\t"  \
+  "lpm %D0, Z" "\n\t"   \
+  : "=r" (__result), "+z" (__addr16));  \
+__result;   \
+}))
+#else
+NI uint32_t read_u32 (const uint32_t *p)
+{
+   return *p;
+}
+#endif
+
+static const __attribute((progmem)) T xyz_prog[] = { 123, 123, 123 };
+T xyz[] = { 123, 123, 123 };
+volatile int x = 0;
+
+NI void prf (T f)
+{
+if (f != 123)
+__builtin_abort();
+}
+
+NI void func_progmem()
+{
+prf (read_u32 (&xyz_prog[0]));
+}
+
+NI void func_ram()
+{
+prf (xyz[x]);
+}
+
+int main (void)
+{
+func_progmem();
+func_ram();
+
+   return 0;
+}


[gcc r14-10175] AVR: ipa/92606 - Don't optimize PROGMEM data against non-PROGMEM.

2024-05-07 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:c6141ad24f73cf1771e33c7d7edf1d80d8df70b8

commit r14-10175-gc6141ad24f73cf1771e33c7d7edf1d80d8df70b8
Author: Georg-Johann Lay 
Date:   Fri May 3 18:47:50 2024 +0200

AVR: ipa/92606 - Don't optimize PROGMEM data against non-PROGMEM.

ipa/92606: Inter-procedural analysis optimizes data across
address-spaces and PROGMEM.  As of v14, the PROGMEM part is
still not fixed (and there is still no target hook as proposed
in PR92932).  Just disable respective bogus optimization.

PR ipa/92606
gcc/
* config/avr/avr.cc (avr_option_override): Set
flag_ipa_icf_variables = 0.
gcc/testsuite/
* gcc.target/avr/torture/pr92606.c: New test.

(cherry picked from commit 08e752e72363ae7fd5a5fcb70913a0f7b240387b)

Diff:
---
 gcc/config/avr/avr.cc  |  6 +++
 gcc/testsuite/gcc.target/avr/torture/pr92606.c | 57 ++
 2 files changed, 63 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 510e4cea19f..74924ab0565 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -1140,6 +1140,12 @@ avr_option_override (void)
   if (targetm.addr_space.zero_address_valid (ADDR_SPACE_GENERIC))
 flag_delete_null_pointer_checks = 0;
 
+  /* PR ipa/92606: Inter-procedural analysis optimizes data across
+ address-spaces and PROGMEM.  As of v14, the PROGMEM part is
+ still not fixed (and there is still no target hook as proposed
+ in PR92932).  Just disable respective bogus optimization.  */
+  flag_ipa_icf_variables = 0;
+
   if (flag_pic == 1)
 warning (OPT_fpic, "%<-fpic%> is not supported");
   if (flag_pic == 2)
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr92606.c 
b/gcc/testsuite/gcc.target/avr/torture/pr92606.c
new file mode 100644
index 000..cc07128c73b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr92606.c
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
+
+typedef uint32_t T;
+
+#define NI __attribute__((noinline,noclone))
+
+
+#ifndef __AVR_TINY__
+#define read_u32(X) \
+(__extension__( \
+{   \
+uint16_t __addr16 = (uint16_t)(X);  \
+uint32_t __result;  \
+__asm__ __volatile__ ("lpm %A0, Z+" "\n\t"  \
+  "lpm %B0, Z+" "\n\t"  \
+  "lpm %C0, Z+" "\n\t"  \
+  "lpm %D0, Z" "\n\t"   \
+  : "=r" (__result), "+z" (__addr16));  \
+__result;   \
+}))
+#else
+NI uint32_t read_u32 (const uint32_t *p)
+{
+   return *p;
+}
+#endif
+
+static const __attribute((progmem)) T xyz_prog[] = { 123, 123, 123 };
+T xyz[] = { 123, 123, 123 };
+volatile int x = 0;
+
+NI void prf (T f)
+{
+if (f != 123)
+__builtin_abort();
+}
+
+NI void func_progmem()
+{
+prf (read_u32 (&xyz_prog[0]));
+}
+
+NI void func_ram()
+{
+prf (xyz[x]);
+}
+
+int main (void)
+{
+func_progmem();
+func_ram();
+
+   return 0;
+}


[gcc r12-10418] AVR: ipa/92606 - Don't optimize PROGMEM data against non-PROGMEM.

2024-05-07 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:231728b6dd7684e031f2a05e7e43bab54b7f2c5e

commit r12-10418-g231728b6dd7684e031f2a05e7e43bab54b7f2c5e
Author: Georg-Johann Lay 
Date:   Fri May 3 18:47:50 2024 +0200

AVR: ipa/92606 - Don't optimize PROGMEM data against non-PROGMEM.

ipa/92606: Inter-procedural analysis optimizes data across
address-spaces and PROGMEM.  As of v14, the PROGMEM part is
still not fixed (and there is still no target hook as proposed
in PR92932).  Just disable respective bogus optimization.

PR ipa/92606
gcc/
* config/avr/avr.cc (avr_option_override): Set
flag_ipa_icf_variables = 0.
gcc/testsuite/
* gcc.target/avr/torture/pr92606.c: New test.

(cherry picked from commit 08e752e72363ae7fd5a5fcb70913a0f7b240387b)

Diff:
---
 gcc/config/avr/avr.cc  | 10 +
 gcc/testsuite/gcc.target/avr/torture/pr92606.c | 57 ++
 2 files changed, 67 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 1905ac5790c..bc15017c61c 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -1095,6 +1095,16 @@ avr_option_override (void)
   flag_omit_frame_pointer = 0;
 }
 
+  /* Disable flag_delete_null_pointer_checks if zero is a valid address. */
+  if (targetm.addr_space.zero_address_valid (ADDR_SPACE_GENERIC))
+flag_delete_null_pointer_checks = 0;
+
+  /* PR ipa/92606: Inter-procedural analysis optimizes data across
+ address-spaces and PROGMEM.  As of v14, the PROGMEM part is
+ still not fixed (and there is still no target hook as proposed
+ in PR92932).  Just disable respective bogus optimization.  */
+  flag_ipa_icf_variables = 0;
+
   if (flag_pic == 1)
 warning (OPT_fpic, "%<-fpic%> is not supported");
   if (flag_pic == 2)
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr92606.c 
b/gcc/testsuite/gcc.target/avr/torture/pr92606.c
new file mode 100644
index 000..cc07128c73b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr92606.c
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
+
+typedef uint32_t T;
+
+#define NI __attribute__((noinline,noclone))
+
+
+#ifndef __AVR_TINY__
+#define read_u32(X) \
+(__extension__( \
+{   \
+uint16_t __addr16 = (uint16_t)(X);  \
+uint32_t __result;  \
+__asm__ __volatile__ ("lpm %A0, Z+" "\n\t"  \
+  "lpm %B0, Z+" "\n\t"  \
+  "lpm %C0, Z+" "\n\t"  \
+  "lpm %D0, Z" "\n\t"   \
+  : "=r" (__result), "+z" (__addr16));  \
+__result;   \
+}))
+#else
+NI uint32_t read_u32 (const uint32_t *p)
+{
+   return *p;
+}
+#endif
+
+static const __attribute((progmem)) T xyz_prog[] = { 123, 123, 123 };
+T xyz[] = { 123, 123, 123 };
+volatile int x = 0;
+
+NI void prf (T f)
+{
+if (f != 123)
+__builtin_abort();
+}
+
+NI void func_progmem()
+{
+prf (read_u32 (&xyz_prog[0]));
+}
+
+NI void func_ram()
+{
+prf (xyz[x]);
+}
+
+int main (void)
+{
+func_progmem();
+func_ram();
+
+   return 0;
+}


[gcc r12-10419] AVR: Backport device support from v13.3.

2024-05-07 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:ef10d72003f87ab2d88c852da75d407c0c990e99

commit r12-10419-gef10d72003f87ab2d88c852da75d407c0c990e99
Author: Georg-Johann Lay 
Date:   Tue May 7 14:00:43 2024 +0200

AVR: Backport device support from v13.3.

gcc/
* config/avr/avr-mcus.def: Add new MCUs (copy from gcc-13).
* doc/avr-mmcu.texi: Rebuild.

Diff:
---
 gcc/config/avr/avr-mcus.def | 79 +++--
 gcc/doc/avr-mmcu.texi   | 10 +++---
 2 files changed, 82 insertions(+), 7 deletions(-)

diff --git a/gcc/config/avr/avr-mcus.def b/gcc/config/avr/avr-mcus.def
index db28d9b1b0a..876fecd8aa1 100644
--- a/gcc/config/avr/avr-mcus.def
+++ b/gcc/config/avr/avr-mcus.def
@@ -166,12 +166,15 @@ AVR_MCU ("at90pwm3b",ARCH_AVR4, AVR_ISA_NONE,  
"__AVR_AT90PWM3B__",
 AVR_MCU ("at90pwm81",ARCH_AVR4, AVR_ISA_NONE,  "__AVR_AT90PWM81__",
0x0100, 0x0, 0x2000, 0)
 /* Enhanced, > 8K, <= 64K.  */
 AVR_MCU ("avr5", ARCH_AVR5, AVR_ISA_NONE, NULL,
0x0060, 0x0, 0x4000, 0)
-AVR_MCU ("ata5702m322",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5702M322__",   
0x0200, 0x0, 0x1, 0)
+AVR_MCU ("ata5700m322",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5700M322__",   
0x0200, 0x8000, 0x1, 0)
+AVR_MCU ("ata5702m322",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5702M322__",   
0x0200, 0x8000, 0x1, 0)
 AVR_MCU ("ata5782",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5782__",   
0x0200, 0x8000, 0xd000, 0)
+AVR_MCU ("ata5787",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5787__",   
0x0200, 0x8000, 0xd200, 0)
 AVR_MCU ("ata5790",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5790__",   
0x0100, 0x0, 0x4000, 0)
 AVR_MCU ("ata5790n", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5790N__",  
0x0100, 0x0, 0x4000, 0)
 AVR_MCU ("ata5791",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5791__",   
0x0100, 0x0, 0x4000, 0)
 AVR_MCU ("ata5831",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5831__",   
0x0200, 0x8000, 0xd000, 0)
+AVR_MCU ("ata5835",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5835__",   
0x0200, 0x8000, 0xd200, 0)
 AVR_MCU ("ata6613c", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA6613C__",  
0x0100, 0x0, 0x4000, 0)
 AVR_MCU ("ata6614q", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA6614Q__",  
0x0100, 0x0, 0x8000, 0)
 AVR_MCU ("ata8210",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA8210__",   
0x0200, 0x8000, 0xd000, 0)
@@ -291,7 +294,7 @@ AVR_MCU ("atmega2560",   ARCH_AVR6, AVR_ISA_NONE, 
"__AVR_ATmega2560__",
 AVR_MCU ("atmega2561",   ARCH_AVR6, AVR_ISA_NONE, "__AVR_ATmega2561__",
0x0200, 0x0, 0x4, 0)
 AVR_MCU ("atmega256rfr2",ARCH_AVR6, AVR_ISA_NONE, "__AVR_ATmega256RFR2__", 
0x0200, 0x0, 0x4, 0)
 AVR_MCU ("atmega2564rfr2",   ARCH_AVR6, AVR_ISA_NONE, 
"__AVR_ATmega2564RFR2__",0x0200, 0x0, 0x4, 0)
-/* Xmega, 16K <= Flash < 64K, RAM <= 64K */
+/* Xmega, 16K <= Flash <= 64K, RAM <= 64K */
 AVR_MCU ("avrxmega2",ARCH_AVRXMEGA2, AVR_ISA_NONE, NULL,   
0x2000, 0x0, 0x9000, 0)
 AVR_MCU ("atxmega8e5",   ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_ATxmega8E5__",   0x2000, 0x0, 0x2800, 0)
 AVR_MCU ("atxmega16a4",  ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_ATxmega16A4__",  0x2000, 0x0, 0x5000, 0)
@@ -306,6 +309,23 @@ AVR_MCU ("atxmega16c4",  ARCH_AVRXMEGA2, AVR_ISA_RMW,  
"__AVR_ATxmega16C4__"
 AVR_MCU ("atxmega32a4u", ARCH_AVRXMEGA2, AVR_ISA_RMW,  
"__AVR_ATxmega32A4U__", 0x2000, 0x0, 0x9000, 0)
 AVR_MCU ("atxmega32c4",  ARCH_AVRXMEGA2, AVR_ISA_RMW,  
"__AVR_ATxmega32C4__",  0x2000, 0x0, 0x9000, 0)
 AVR_MCU ("atxmega32e5",  ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_ATxmega32E5__",  0x2000, 0x0, 0x9000, 0)
+AVR_MCU ("avr64da28",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DA28__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64da32",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DA32__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64da48",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DA48__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64da64",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DA64__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64db28",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DB28__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64db32",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DB32__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64db48",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DB48__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64db64",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DB64__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64dd14",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DD14__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64dd20",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DD20__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64dd28",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DD28__",0x6000, 0x0, 0x1, 0)
+A

[gcc r15-286] AVR: target/114835 - Tweak popcountqi2

2024-05-07 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:8d2c93fcfe1afc5291bbbe162c3b7ad5764f6d8d

commit r15-286-g8d2c93fcfe1afc5291bbbe162c3b7ad5764f6d8d
Author: Wolfgang Hospital 
Date:   Tue May 7 16:24:39 2024 +0200

AVR: target/114835 - Tweak popcountqi2

libgcc/
PR target/114835
* config/avr/lib1funcs.S (__popcountqi2): Use code that
is one instruction shorter / faster.

Diff:
---
 libgcc/config/avr/lib1funcs.S | 30 +++---
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index af4d7d97016..4ac31fa104e 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -3050,21 +3050,21 @@ ENDF __popcountdi2
 ;; r24 = popcount8 (r24)
 ;; clobbers: __tmp_reg__
 DEFUN __popcountqi2
-mov  __tmp_reg__, r24
-andi r24, 1
-lsr  __tmp_reg__
-lsr  __tmp_reg__
-adc  r24, __zero_reg__
-lsr  __tmp_reg__
-adc  r24, __zero_reg__
-lsr  __tmp_reg__
-adc  r24, __zero_reg__
-lsr  __tmp_reg__
-adc  r24, __zero_reg__
-lsr  __tmp_reg__
-adc  r24, __zero_reg__
-lsr  __tmp_reg__
-adc  r24, __tmp_reg__
+mov  __tmp_reg__, r24; oeoeoeoe
+andi r24, 0xAA   ; o0o0o0o0
+lsr  r24 ; 0o0o0o0o
+;; Four values 0, 1 or 2: # bits set o+e
+sub  __tmp_reg__, r24; 44332211
+mov  r24, __tmp_reg__; 44332211
+andi r24, 0x33   ; 00330011
+eor  __tmp_reg__, r24; 44002200
+lsr  __tmp_reg__ ; 04400220
+lsr  __tmp_reg__ ; 00440022
+add  r24, __tmp_reg__; 04210421
+mov  __tmp_reg__, r24; h421l421
+swap __tmp_reg__ ; l421h421
+add  r24, __tmp_reg__; 84218421
+andi r24, 0xf; 8421 /17
 ret
 ENDF __popcountqi2
 #endif /* defined (L_popcountqi2) */


[gcc r15-317] AVR: target/114975 - Add combine-pattern for __popcountqi2.

2024-05-08 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:c8f4bbb824fafecf021a802324cd79e64b03b947

commit r15-317-gc8f4bbb824fafecf021a802324cd79e64b03b947
Author: Georg-Johann Lay 
Date:   Tue May 7 19:39:55 2024 +0200

AVR: target/114975 - Add combine-pattern for __popcountqi2.

PR target/114975
gcc/
* config/avr/avr.md: Add combine pattern for
8-bit popcount detection.

gcc/testsuite/
* gcc.target/avr/pr114975-popcount.c: New test.

Diff:
---
 gcc/config/avr/avr.md| 13 +
 gcc/testsuite/gcc.target/avr/pr114975-popcount.c | 17 +
 2 files changed, 30 insertions(+)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 97f42be7729c..36fe384828f9 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -8527,6 +8527,19 @@
 operands[2] = gen_reg_rtx (HImode);
   })
 
+(define_insn_and_split "*popcounthi2.split8"
+  [(set (reg:HI 24)
+(zero_extend:HI (popcount:QI (match_operand:QI 0 
"register_operand"]
+  "! reload_completed"
+  { gcc_unreachable(); }
+  "&& 1"
+  [(set (reg:QI 24)
+(match_dup 0))
+   (set (reg:QI 24)
+(popcount:QI (reg:QI 24)))
+   (set (reg:QI 25)
+(const_int 0))])
+
 (define_insn_and_split "*popcounthi2.libgcc_split"
   [(set (reg:HI 24)
 (popcount:HI (reg:HI 24)))]
diff --git a/gcc/testsuite/gcc.target/avr/pr114975-popcount.c 
b/gcc/testsuite/gcc.target/avr/pr114975-popcount.c
new file mode 100644
index ..87eb56b56c5a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr114975-popcount.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Os" } */
+
+typedef __UINT8_TYPE__ uint8_t;
+
+uint8_t use_pop1 (int y, uint8_t x)
+{
+return 1 + __builtin_popcount (x);
+}
+
+uint8_t use_pop2 (uint8_t x)
+{
+   x += 1;
+return 1 - __builtin_popcount (x);
+}
+
+/* { dg-final { scan-assembler-times "__popcountqi2" 2 } } */


[gcc r15-318] AVR: target/114975 - Add combine-pattern for __parityqi2.

2024-05-08 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:41bc359c322d45ec1adfb51f7a45c7ef02ce6ca9

commit r15-318-g41bc359c322d45ec1adfb51f7a45c7ef02ce6ca9
Author: Georg-Johann Lay 
Date:   Tue May 7 19:42:30 2024 +0200

AVR: target/114975 - Add combine-pattern for __parityqi2.

PR target/114975
gcc/
* config/avr/avr.md: Add combine pattern for
8-bit parity detection.

gcc/testsuite/
* gcc.target/avr/pr114975-parity.c: New test.

Diff:
---
 gcc/config/avr/avr.md  | 17 -
 gcc/testsuite/gcc.target/avr/pr114975-parity.c | 17 +
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 36fe384828f9..d4fcff46123b 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -8418,7 +8418,22 @@
(set (match_dup 0)
 (reg:HI 24))])
 
-(define_insn_and_split "*parityqihi2"
+(define_insn_and_split "*parityqihi2.1"
+  [(set (match_operand:HI 0 "register_operand""=r")
+(zero_extend:HI
+ (parity:QI (match_operand:QI 1 "register_operand" "r"
+   (clobber (reg:HI 24))]
+  "!reload_completed"
+  { gcc_unreachable(); }
+  "&& 1"
+  [(set (reg:QI 24)
+(match_dup 1))
+   (set (reg:HI 24)
+(zero_extend:HI (parity:QI (reg:QI 24
+   (set (match_dup 0)
+(reg:HI 24))])
+
+(define_insn_and_split "*parityqihi2.2"
   [(set (match_operand:HI 0 "register_operand"   "=r")
 (parity:HI (match_operand:QI 1 "register_operand" "r")))
(clobber (reg:HI 24))]
diff --git a/gcc/testsuite/gcc.target/avr/pr114975-parity.c 
b/gcc/testsuite/gcc.target/avr/pr114975-parity.c
new file mode 100644
index ..767ced0a464d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr114975-parity.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Os" } */
+
+typedef __UINT8_TYPE__ uint8_t;
+
+uint8_t use_pary1 (int y, uint8_t x)
+{
+return 1 + __builtin_parity (x);
+}
+
+uint8_t use_pary2 (uint8_t x)
+{
+   x += 1;
+return 1 - __builtin_parity (x);
+}
+
+/* { dg-final { scan-assembler-times "__parityqi2" 2 } } */


[gcc r15-331] AVR: target/114981 - Support __builtin_powi[l] / __powidf2.

2024-05-08 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:de4eea7d7ea86e54843507c68d6672eca9d8c7bb

commit r15-331-gde4eea7d7ea86e54843507c68d6672eca9d8c7bb
Author: Georg-Johann Lay 
Date:   Wed May 8 17:56:05 2024 +0200

AVR: target/114981 - Support __builtin_powi[l] / __powidf2.

This supports __powidf2 by means of a double wrapper for already
existing f7_powi (renamed to __f7_powi by f7-renames.h).
It tweaks the implementation so that it does not perform trivial
multiplications with 1.0 any more, but instead uses a move.
It also fixes the last statement of f7_powi, which was wrong.
Notice that f7_powi was unused until now.

PR target/114981
libgcc/config/avr/libf7/
* libf7-common.mk (F7_ASM_PARTS): Add D_powi
* libf7-asm.sx (F7MOD_D_powi_, __powidf2): New module and function.
* libf7.c (f7_powi): Fix last (wrong) statement.
Tweak trivial multiplications with 1.0.

gcc/testsuite/
* gcc.target/avr/pr114981-powil.c: New test.

Diff:
---
 gcc/testsuite/gcc.target/avr/pr114981-powil.c | 33 +++
 libgcc/config/avr/libf7/libf7-asm.sx  | 12 ++
 libgcc/config/avr/libf7/libf7-common.mk   |  2 +-
 libgcc/config/avr/libf7/libf7.c   | 29 +--
 4 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/gcc/testsuite/gcc.target/avr/pr114981-powil.c 
b/gcc/testsuite/gcc.target/avr/pr114981-powil.c
new file mode 100644
index ..70f8e796c654
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr114981-powil.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-Os" } */
+
+const long double vals[] =
+  {
+0.0625L, -0.125L, 0.25L, -0.5L,
+1.0L,
+-2.0L, 4.0L, -8.0L, 16.0L
+  };
+
+#define ARRAY_SIZE(X) ((int) (sizeof(X) / sizeof(*X)))
+
+__attribute__((noinline,noclone))
+void test1 (long double x)
+{
+  int i;
+
+  for (i = 0; i < ARRAY_SIZE (vals); ++i)
+{
+  long double val0 = vals[i];
+  long double val1 = __builtin_powil (x, i - 4);
+  __asm ("" : "+r" (val0));
+
+  if (val0 != val1)
+   __builtin_exit (__LINE__);
+}
+}
+
+int main (void)
+{
+  test1 (-2.0L);
+  return 0;
+}
diff --git a/libgcc/config/avr/libf7/libf7-asm.sx 
b/libgcc/config/avr/libf7/libf7-asm.sx
index 1ab91270cb2b..1f8f60ab2826 100644
--- a/libgcc/config/avr/libf7/libf7-asm.sx
+++ b/libgcc/config/avr/libf7/libf7-asm.sx
@@ -1877,4 +1877,16 @@ ENDF call_ddd
 
 #include "f7-wraps.h"
 
+;;; Some additional, singular wraps that don't match any pattern.
+
+;; double __powidf2 (double, int)  ; __builtin_powi
+#ifdef F7MOD_D_powi_
+_DEFUN __powidf2
+.global F7_NAME(powi)
+ldi ZH, hi8(gs(F7_NAME(powi)))
+ldi ZL, lo8(gs(F7_NAME(powi)))
+F7jmp   call_ddx
+_ENDF __powidf2
+#endif /* F7MOD_D_powi_ */
+
 #endif /* !AVR_TINY */
diff --git a/libgcc/config/avr/libf7/libf7-common.mk 
b/libgcc/config/avr/libf7/libf7-common.mk
index d541b48ff3ca..5d411071c8e4 100644
--- a/libgcc/config/avr/libf7/libf7-common.mk
+++ b/libgcc/config/avr/libf7/libf7-common.mk
@@ -22,7 +22,7 @@ F7_ASM_PARTS += addsub_mant_scaled store load
 F7_ASM_PARTS += to_integer to_unsigned clz normalize_with_carry normalize
 F7_ASM_PARTS += store_expo sqrt16 sqrt_approx div
 
-F7_ASM_PARTS += D_class D_fma
+F7_ASM_PARTS += D_class D_fma D_powi
 F7_ASM_PARTS += D_isnan D_isinf D_isfinite D_signbit D_copysign D_neg D_fabs
 
 F7_ASM_PARTS += call_dd call_ddd
diff --git a/libgcc/config/avr/libf7/libf7.c b/libgcc/config/avr/libf7/libf7.c
index 369dbe241039..375becb854c1 100644
--- a/libgcc/config/avr/libf7/libf7.c
+++ b/libgcc/config/avr/libf7/libf7.c
@@ -1752,20 +1752,33 @@ void f7_powi (f7_t *cc, const f7_t *aa, int ii)
 {
   uint16_t u16 = ii;
   f7_t xx27, *xx2 = &xx27;
+  bool cc_is_one = true;
+  bool expo_is_neg = false;
 
   if (ii < 0)
-u16 = -u16;
+{
+  u16 = -u16;
+  expo_is_neg = true;
+}
 
   f7_copy (xx2, aa);
 
-  f7_set_u16 (cc, 1);
-
   while (1)
 {
   if (u16 & 1)
-   f7_Imul (cc, xx2);
+   {
+ if (cc_is_one)
+   {
+ // C *= X2 simplifies to C = X2.
+ f7_copy (cc, xx2);
+ cc_is_one = false;
+   }
+ else
+   f7_Imul (cc, xx2);
+   }
 
-  if (! f7_is_nonzero (cc))
+  if (! cc_is_one
+ && ! f7_is_nonzero (cc))
break;
 
   u16 >>= 1;
@@ -1774,8 +1787,10 @@ void f7_powi (f7_t *cc, const f7_t *aa, int ii)
   f7_Isquare (xx2);
 }
 
-  if (ii < 0)
-f7_div1 (xx2, aa);
+  if (cc_is_one)
+f7_set_u16 (cc, 1);
+  else if (expo_is_neg)
+f7_div1 (cc, cc);
 }
 #endif // F7MOD_powi_


[gcc r13-8736] AVR: target/114981 - Support __builtin_powi[l] / __powidf2.

2024-05-09 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:adba85bb63a45d7d668501c11bdf9772cc00b7b8

commit r13-8736-gadba85bb63a45d7d668501c11bdf9772cc00b7b8
Author: Georg-Johann Lay 
Date:   Wed May 8 17:56:05 2024 +0200

AVR: target/114981 - Support __builtin_powi[l] / __powidf2.

This supports __powidf2 by means of a double wrapper for already
existing f7_powi (renamed to __f7_powi by f7-renames.h).
It tweaks the implementation so that it does not perform trivial
multiplications with 1.0 any more, but instead uses a move.
It also fixes the last statement of f7_powi, which was wrong.
Notice that f7_powi was unused until now.

PR target/114981
libgcc/config/avr/libf7/
* libf7-common.mk (F7_ASM_PARTS): Add D_powi
* libf7-asm.sx (F7MOD_D_powi_, __powidf2): New module and function.
* libf7.c (f7_powi): Fix last (wrong) statement.
Tweak trivial multiplications with 1.0.

gcc/testsuite/
* gcc.target/avr/pr114981-powil.c: New test.

(cherry picked from commit de4eea7d7ea86e54843507c68d6672eca9d8c7bb)

Diff:
---
 gcc/testsuite/gcc.target/avr/pr114981-powil.c | 33 +++
 libgcc/config/avr/libf7/libf7-asm.sx  | 12 ++
 libgcc/config/avr/libf7/libf7-common.mk   |  2 +-
 libgcc/config/avr/libf7/libf7.c   | 29 +--
 4 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/gcc/testsuite/gcc.target/avr/pr114981-powil.c 
b/gcc/testsuite/gcc.target/avr/pr114981-powil.c
new file mode 100644
index ..70f8e796c654
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr114981-powil.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-Os" } */
+
+const long double vals[] =
+  {
+0.0625L, -0.125L, 0.25L, -0.5L,
+1.0L,
+-2.0L, 4.0L, -8.0L, 16.0L
+  };
+
+#define ARRAY_SIZE(X) ((int) (sizeof(X) / sizeof(*X)))
+
+__attribute__((noinline,noclone))
+void test1 (long double x)
+{
+  int i;
+
+  for (i = 0; i < ARRAY_SIZE (vals); ++i)
+{
+  long double val0 = vals[i];
+  long double val1 = __builtin_powil (x, i - 4);
+  __asm ("" : "+r" (val0));
+
+  if (val0 != val1)
+   __builtin_exit (__LINE__);
+}
+}
+
+int main (void)
+{
+  test1 (-2.0L);
+  return 0;
+}
diff --git a/libgcc/config/avr/libf7/libf7-asm.sx 
b/libgcc/config/avr/libf7/libf7-asm.sx
index b00f75994964..df315d35c73e 100644
--- a/libgcc/config/avr/libf7/libf7-asm.sx
+++ b/libgcc/config/avr/libf7/libf7-asm.sx
@@ -1877,4 +1877,16 @@ ENDF call_ddd
 
 #include "f7-wraps.h"
 
+;;; Some additional, singular wraps that don't match any pattern.
+
+;; double __powidf2 (double, int)  ; __builtin_powi
+#ifdef F7MOD_D_powi_
+_DEFUN __powidf2
+.global F7_NAME(powi)
+ldi ZH, hi8(gs(F7_NAME(powi)))
+ldi ZL, lo8(gs(F7_NAME(powi)))
+F7jmp   call_ddx
+_ENDF __powidf2
+#endif /* F7MOD_D_powi_ */
+
 #endif /* !AVR_TINY */
diff --git a/libgcc/config/avr/libf7/libf7-common.mk 
b/libgcc/config/avr/libf7/libf7-common.mk
index d541b48ff3ca..5d411071c8e4 100644
--- a/libgcc/config/avr/libf7/libf7-common.mk
+++ b/libgcc/config/avr/libf7/libf7-common.mk
@@ -22,7 +22,7 @@ F7_ASM_PARTS += addsub_mant_scaled store load
 F7_ASM_PARTS += to_integer to_unsigned clz normalize_with_carry normalize
 F7_ASM_PARTS += store_expo sqrt16 sqrt_approx div
 
-F7_ASM_PARTS += D_class D_fma
+F7_ASM_PARTS += D_class D_fma D_powi
 F7_ASM_PARTS += D_isnan D_isinf D_isfinite D_signbit D_copysign D_neg D_fabs
 
 F7_ASM_PARTS += call_dd call_ddd
diff --git a/libgcc/config/avr/libf7/libf7.c b/libgcc/config/avr/libf7/libf7.c
index fd7059d6c65a..a769f311d958 100644
--- a/libgcc/config/avr/libf7/libf7.c
+++ b/libgcc/config/avr/libf7/libf7.c
@@ -1749,20 +1749,33 @@ void f7_powi (f7_t *cc, const f7_t *aa, int ii)
 {
   uint16_t u16 = ii;
   f7_t xx27, *xx2 = &xx27;
+  bool cc_is_one = true;
+  bool expo_is_neg = false;
 
   if (ii < 0)
-u16 = -u16;
+{
+  u16 = -u16;
+  expo_is_neg = true;
+}
 
   f7_copy (xx2, aa);
 
-  f7_set_u16 (cc, 1);
-
   while (1)
 {
   if (u16 & 1)
-   f7_Imul (cc, xx2);
+   {
+ if (cc_is_one)
+   {
+ // C *= X2 simplifies to C = X2.
+ f7_copy (cc, xx2);
+ cc_is_one = false;
+   }
+ else
+   f7_Imul (cc, xx2);
+   }
 
-  if (! f7_is_nonzero (cc))
+  if (! cc_is_one
+ && ! f7_is_nonzero (cc))
break;
 
   u16 >>= 1;
@@ -1771,8 +1784,10 @@ void f7_powi (f7_t *cc, const f7_t *aa, int ii)
   f7_Isquare (xx2);
 }
 
-  if (ii < 0)
-f7_div1 (xx2, aa);
+  if (cc_is_one)
+f7_set_u16 (cc, 1);
+  else if (expo_is_neg)
+f7_div1 (cc, cc);
 }
 #endif // F7MOD_powi_


[gcc r14-10186] AVR: target/114981 - Support __builtin_powi[l] / __powidf2.

2024-05-09 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:a9e313ed38775b3ffee650d5396419ce3e6ea389

commit r14-10186-ga9e313ed38775b3ffee650d5396419ce3e6ea389
Author: Georg-Johann Lay 
Date:   Wed May 8 17:56:05 2024 +0200

AVR: target/114981 - Support __builtin_powi[l] / __powidf2.

This supports __powidf2 by means of a double wrapper for already
existing f7_powi (renamed to __f7_powi by f7-renames.h).
It tweaks the implementation so that it does not perform trivial
multiplications with 1.0 any more, but instead uses a move.
It also fixes the last statement of f7_powi, which was wrong.
Notice that f7_powi was unused until now.

PR target/114981
libgcc/config/avr/libf7/
* libf7-common.mk (F7_ASM_PARTS): Add D_powi
* libf7-asm.sx (F7MOD_D_powi_, __powidf2): New module and function.
* libf7.c (f7_powi): Fix last (wrong) statement.
Tweak trivial multiplications with 1.0.

gcc/testsuite/
* gcc.target/avr/pr114981-powil.c: New test.

(cherry picked from commit de4eea7d7ea86e54843507c68d6672eca9d8c7bb)

Diff:
---
 gcc/testsuite/gcc.target/avr/pr114981-powil.c | 33 +++
 libgcc/config/avr/libf7/libf7-asm.sx  | 12 ++
 libgcc/config/avr/libf7/libf7-common.mk   |  2 +-
 libgcc/config/avr/libf7/libf7.c   | 29 +--
 4 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/gcc/testsuite/gcc.target/avr/pr114981-powil.c 
b/gcc/testsuite/gcc.target/avr/pr114981-powil.c
new file mode 100644
index ..70f8e796c654
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr114981-powil.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-Os" } */
+
+const long double vals[] =
+  {
+0.0625L, -0.125L, 0.25L, -0.5L,
+1.0L,
+-2.0L, 4.0L, -8.0L, 16.0L
+  };
+
+#define ARRAY_SIZE(X) ((int) (sizeof(X) / sizeof(*X)))
+
+__attribute__((noinline,noclone))
+void test1 (long double x)
+{
+  int i;
+
+  for (i = 0; i < ARRAY_SIZE (vals); ++i)
+{
+  long double val0 = vals[i];
+  long double val1 = __builtin_powil (x, i - 4);
+  __asm ("" : "+r" (val0));
+
+  if (val0 != val1)
+   __builtin_exit (__LINE__);
+}
+}
+
+int main (void)
+{
+  test1 (-2.0L);
+  return 0;
+}
diff --git a/libgcc/config/avr/libf7/libf7-asm.sx 
b/libgcc/config/avr/libf7/libf7-asm.sx
index 1ab91270cb2b..1f8f60ab2826 100644
--- a/libgcc/config/avr/libf7/libf7-asm.sx
+++ b/libgcc/config/avr/libf7/libf7-asm.sx
@@ -1877,4 +1877,16 @@ ENDF call_ddd
 
 #include "f7-wraps.h"
 
+;;; Some additional, singular wraps that don't match any pattern.
+
+;; double __powidf2 (double, int)  ; __builtin_powi
+#ifdef F7MOD_D_powi_
+_DEFUN __powidf2
+.global F7_NAME(powi)
+ldi ZH, hi8(gs(F7_NAME(powi)))
+ldi ZL, lo8(gs(F7_NAME(powi)))
+F7jmp   call_ddx
+_ENDF __powidf2
+#endif /* F7MOD_D_powi_ */
+
 #endif /* !AVR_TINY */
diff --git a/libgcc/config/avr/libf7/libf7-common.mk 
b/libgcc/config/avr/libf7/libf7-common.mk
index d541b48ff3ca..5d411071c8e4 100644
--- a/libgcc/config/avr/libf7/libf7-common.mk
+++ b/libgcc/config/avr/libf7/libf7-common.mk
@@ -22,7 +22,7 @@ F7_ASM_PARTS += addsub_mant_scaled store load
 F7_ASM_PARTS += to_integer to_unsigned clz normalize_with_carry normalize
 F7_ASM_PARTS += store_expo sqrt16 sqrt_approx div
 
-F7_ASM_PARTS += D_class D_fma
+F7_ASM_PARTS += D_class D_fma D_powi
 F7_ASM_PARTS += D_isnan D_isinf D_isfinite D_signbit D_copysign D_neg D_fabs
 
 F7_ASM_PARTS += call_dd call_ddd
diff --git a/libgcc/config/avr/libf7/libf7.c b/libgcc/config/avr/libf7/libf7.c
index 369dbe241039..375becb854c1 100644
--- a/libgcc/config/avr/libf7/libf7.c
+++ b/libgcc/config/avr/libf7/libf7.c
@@ -1752,20 +1752,33 @@ void f7_powi (f7_t *cc, const f7_t *aa, int ii)
 {
   uint16_t u16 = ii;
   f7_t xx27, *xx2 = &xx27;
+  bool cc_is_one = true;
+  bool expo_is_neg = false;
 
   if (ii < 0)
-u16 = -u16;
+{
+  u16 = -u16;
+  expo_is_neg = true;
+}
 
   f7_copy (xx2, aa);
 
-  f7_set_u16 (cc, 1);
-
   while (1)
 {
   if (u16 & 1)
-   f7_Imul (cc, xx2);
+   {
+ if (cc_is_one)
+   {
+ // C *= X2 simplifies to C = X2.
+ f7_copy (cc, xx2);
+ cc_is_one = false;
+   }
+ else
+   f7_Imul (cc, xx2);
+   }
 
-  if (! f7_is_nonzero (cc))
+  if (! cc_is_one
+ && ! f7_is_nonzero (cc))
break;
 
   u16 >>= 1;
@@ -1774,8 +1787,10 @@ void f7_powi (f7_t *cc, const f7_t *aa, int ii)
   f7_Isquare (xx2);
 }
 
-  if (ii < 0)
-f7_div1 (xx2, aa);
+  if (cc_is_one)
+f7_set_u16 (cc, 1);
+  else if (expo_is_neg)
+f7_div1 (cc, cc);
 }
 #endif // F7MOD_powi_


[gcc r14-10188] AVR: target/114975 - Add combine-pattern for __parityqi2.

2024-05-09 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:bbb76ac0a06ae3a469f2acc2d5d63e63160bd9e5

commit r14-10188-gbbb76ac0a06ae3a469f2acc2d5d63e63160bd9e5
Author: Georg-Johann Lay 
Date:   Tue May 7 19:42:30 2024 +0200

AVR: target/114975 - Add combine-pattern for __parityqi2.

PR target/114975
gcc/
* config/avr/avr.md: Add combine pattern for
8-bit parity detection.

gcc/testsuite/
* gcc.target/avr/pr114975-parity.c: New test.

(cherry picked from commit 41bc359c322d45ec1adfb51f7a45c7ef02ce6ca9)

Diff:
---
 gcc/config/avr/avr.md  | 17 -
 gcc/testsuite/gcc.target/avr/pr114975-parity.c | 17 +
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 36fe384828f9..d4fcff46123b 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -8418,7 +8418,22 @@
(set (match_dup 0)
 (reg:HI 24))])
 
-(define_insn_and_split "*parityqihi2"
+(define_insn_and_split "*parityqihi2.1"
+  [(set (match_operand:HI 0 "register_operand""=r")
+(zero_extend:HI
+ (parity:QI (match_operand:QI 1 "register_operand" "r"
+   (clobber (reg:HI 24))]
+  "!reload_completed"
+  { gcc_unreachable(); }
+  "&& 1"
+  [(set (reg:QI 24)
+(match_dup 1))
+   (set (reg:HI 24)
+(zero_extend:HI (parity:QI (reg:QI 24
+   (set (match_dup 0)
+(reg:HI 24))])
+
+(define_insn_and_split "*parityqihi2.2"
   [(set (match_operand:HI 0 "register_operand"   "=r")
 (parity:HI (match_operand:QI 1 "register_operand" "r")))
(clobber (reg:HI 24))]
diff --git a/gcc/testsuite/gcc.target/avr/pr114975-parity.c 
b/gcc/testsuite/gcc.target/avr/pr114975-parity.c
new file mode 100644
index ..767ced0a464d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr114975-parity.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Os" } */
+
+typedef __UINT8_TYPE__ uint8_t;
+
+uint8_t use_pary1 (int y, uint8_t x)
+{
+return 1 + __builtin_parity (x);
+}
+
+uint8_t use_pary2 (uint8_t x)
+{
+   x += 1;
+return 1 - __builtin_parity (x);
+}
+
+/* { dg-final { scan-assembler-times "__parityqi2" 2 } } */


[gcc r14-10187] AVR: target/114975 - Add combine-pattern for __popcountqi2.

2024-05-09 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:4ef09dd8ce8866e4f64dd918890c97a67af8fd15

commit r14-10187-g4ef09dd8ce8866e4f64dd918890c97a67af8fd15
Author: Georg-Johann Lay 
Date:   Tue May 7 19:39:55 2024 +0200

AVR: target/114975 - Add combine-pattern for __popcountqi2.

PR target/114975
gcc/
* config/avr/avr.md: Add combine pattern for
8-bit popcount detection.

gcc/testsuite/
* gcc.target/avr/pr114975-popcount.c: New test.

(cherry picked from commit c8f4bbb824fafecf021a802324cd79e64b03b947)

Diff:
---
 gcc/config/avr/avr.md| 13 +
 gcc/testsuite/gcc.target/avr/pr114975-popcount.c | 17 +
 2 files changed, 30 insertions(+)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 97f42be7729c..36fe384828f9 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -8527,6 +8527,19 @@
 operands[2] = gen_reg_rtx (HImode);
   })
 
+(define_insn_and_split "*popcounthi2.split8"
+  [(set (reg:HI 24)
+(zero_extend:HI (popcount:QI (match_operand:QI 0 
"register_operand"]
+  "! reload_completed"
+  { gcc_unreachable(); }
+  "&& 1"
+  [(set (reg:QI 24)
+(match_dup 0))
+   (set (reg:QI 24)
+(popcount:QI (reg:QI 24)))
+   (set (reg:QI 25)
+(const_int 0))])
+
 (define_insn_and_split "*popcounthi2.libgcc_split"
   [(set (reg:HI 24)
 (popcount:HI (reg:HI 24)))]
diff --git a/gcc/testsuite/gcc.target/avr/pr114975-popcount.c 
b/gcc/testsuite/gcc.target/avr/pr114975-popcount.c
new file mode 100644
index ..87eb56b56c5a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr114975-popcount.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Os" } */
+
+typedef __UINT8_TYPE__ uint8_t;
+
+uint8_t use_pop1 (int y, uint8_t x)
+{
+return 1 + __builtin_popcount (x);
+}
+
+uint8_t use_pop2 (uint8_t x)
+{
+   x += 1;
+return 1 - __builtin_popcount (x);
+}
+
+/* { dg-final { scan-assembler-times "__popcountqi2" 2 } } */


[gcc r15-360] AVR: target/114981 - Tweak __builtin_powif / __powisf2

2024-05-10 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:af64af69c3cc85dbe00c520651a54850bf5cadc1

commit r15-360-gaf64af69c3cc85dbe00c520651a54850bf5cadc1
Author: Georg-Johann Lay 
Date:   Wed May 8 17:52:56 2024 +0200

AVR: target/114981 - Tweak __builtin_powif / __powisf2

Implement __powisf2 in assembly.

PR target/114981
libgcc/
* config/avr/t-avr (LIB2FUNCS_EXCLUDE): Add _powisf2.
(LIB1ASMFUNCS) [!avrtiny]: Add _powif.
* config/avr/lib1funcs.S (mov4): New .macro.
(L_powif, __powisf2) [!avrtiny]: New module and function.

gcc/testsuite/
* gcc.target/avr/pr114981-powif.c: New test.

Diff:
---
 gcc/testsuite/gcc.target/avr/pr114981-powif.c |  33 ++
 libgcc/config/avr/lib1funcs.S | 154 ++
 libgcc/config/avr/t-avr   |   4 +-
 3 files changed, 190 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.target/avr/pr114981-powif.c 
b/gcc/testsuite/gcc.target/avr/pr114981-powif.c
new file mode 100644
index ..191dcc61e6d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr114981-powif.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-Os" } */
+
+const float vals[] =
+  {
+0.0625f, -0.125f, 0.25f, -0.5f,
+1.0f,
+-2.0f, 4.0f, -8.0f, 16.0f
+  };
+
+#define ARRAY_SIZE(X) ((int) (sizeof(X) / sizeof(*X)))
+
+__attribute__((noinline,noclone))
+void test1 (float x)
+{
+  int i;
+
+  for (i = 0; i < ARRAY_SIZE (vals); ++i)
+{
+  float val0 = vals[i];
+  float val1 = __builtin_powif (x, i - 4);
+  __asm ("" : "+r" (val0));
+
+  if (val0 != val1)
+   __builtin_exit (__LINE__);
+}
+}
+
+int main (void)
+{
+  test1 (-2.0f);
+  return 0;
+}
diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index 4ac31fa104e3..04a4eb01ab43 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -80,6 +80,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #endif
 .endm
 
+.macro mov4  r_dest, r_src
+wmov \r_dest,   \r_src
+wmov \r_dest+2, \r_src+2
+.endm
+
 #if defined (__AVR_HAVE_JMP_CALL__)
 #define XCALL call
 #define XJMP  jmp
@@ -3312,4 +3317,153 @@ ENDF __fmul
 #undef C0
 #undef C1
 
+
+
+/**
+ * Floating-Point
+ **/
+
+#if defined (L_powif)
+#ifndef __AVR_TINY__
+
+;; float output and arg #1
+#define A0  22
+#define A1  A0 + 1
+#define A2  A0 + 2
+#define A3  A0 + 3
+
+;; float arg #2
+#define B0  18
+#define B1  B0 + 1
+#define B2  B0 + 2
+#define B3  B0 + 3
+
+;; float X: input and iterated squares
+#define X0  10
+#define X1  X0 + 1
+#define X2  X0 + 2
+#define X3  X0 + 3
+
+;; float Y: expand result
+#define Y0  14
+#define Y1  Y0 + 1
+#define Y2  Y0 + 2
+#define Y3  Y0 + 3
+
+;; .7 = Sign of I.
+;; .0 == 0  =>  Y = 1.0f implicitly.
+#define Flags   R9
+#define Y_set   0
+
+;;;  Integer exponent input.
+#define I0  28
+#define I1  I0+1
+
+#define ONE 0x3f80
+
+DEFUN __powisf2
+;; Save 11 Registers: R9...R17, R28, R29
+do_prologue_saves 11
+
+;; Fill local vars with input parameters.
+wmovI0, 20
+mov4X0, A0
+;; Save sign of exponent for later.
+mov Flags,  I1
+;; I := abs (I)
+tst I1
+brpl 1f
+NEG2I0
+1:
+;; Y := (I % 2) ? X : 1.0f
+;; (When we come from below, this is like SET, i.e. Flags.Y_set := 1).
+bst I0, 0
+;; Flags.Y_set = false means that we have to assume Y = 1.0f below.
+bld Flags,  Y_set
+2:  ;; We have A == X when we come from above.
+mov4Y0, A0
+
+.Loop:
+;; while (I >>= 1)
+lsr I1
+ror I0
+sbiwI0, 0
+breq .Loop_done
+
+;; X := X * X
+mov4A0, X0
+#ifdef __WITH_AVRLIBC__
+XCALL   squaref
+#else
+mov4B0, X0
+XCALL   __mulsf3
+#endif /* Have AVR-LibC? */
+mov4X0, A0
+
+;; if (I % 2 == 1)  Y := Y * X
+bst I0, 0
+brtc .Loop
+bst Flags, Y_set
+;; When Y is not set  =>  Y := Y * X = 1.0f * X (= A)
+;; Plus, we have to set Y_set = 1 (= I0.0)
+brtc 1b
+;; Y is already set: Y := X * Y (= A * Y)
+mov4B0, Y0
+XCALL   __mulsf3
+rjmp 2b
+
+;; End while
+.Loop_done:
+
+;; A := 1.0f
+ldi A3, hhi8(ONE)
+ldi A2, hlo8(ONE)
+ldi A1, hi8(ONE)
+ldi A0, lo8(ONE)
+
+;; When Y is still not set, the result is 1.0f (= A).
+bst Flags, Y_set
+brtc .Lret
+
+;; if (I was < 0) Y = 1.0f / Y
+tst Flags
+brmi 1f
+;; A := Y
+mov4A0, Y0
+rjmp .Lret
+1:  ;; A := 1 / Y = A / Y
+mov4B0, Y0
+XCALL   __divsf3
+
+.Lret:
+do_epilogue_restores 11
+ENDF __powisf2
+
+#undef A0
+#undef A1
+#undef A2
+#undef A3
+
+#undef B0
+#undef B1
+#undef B2
+#undef B3
+
+#undef X0
+#undef X1
+#

[gcc r14-10194] AVR: target/114981 - Tweak __builtin_powif / __powisf2

2024-05-10 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:fcdd723779f9ad9af9638e11ffe56786de2d02ce

commit r14-10194-gfcdd723779f9ad9af9638e11ffe56786de2d02ce
Author: Georg-Johann Lay 
Date:   Wed May 8 17:52:56 2024 +0200

AVR: target/114981 - Tweak __builtin_powif / __powisf2

Implement __powisf2 in assembly.

PR target/114981
libgcc/
* config/avr/t-avr (LIB2FUNCS_EXCLUDE): Add _powisf2.
(LIB1ASMFUNCS) [!avrtiny]: Add _powif.
* config/avr/lib1funcs.S (mov4): New .macro.
(L_powif, __powisf2) [!avrtiny]: New module and function.

gcc/testsuite/
* gcc.target/avr/pr114981-powif.c: New test.

(cherry picked from commit af64af69c3cc85dbe00c520651a54850bf5cadc1)

Diff:
---
 gcc/testsuite/gcc.target/avr/pr114981-powif.c |  33 ++
 libgcc/config/avr/lib1funcs.S | 154 ++
 libgcc/config/avr/t-avr   |   4 +-
 3 files changed, 190 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.target/avr/pr114981-powif.c 
b/gcc/testsuite/gcc.target/avr/pr114981-powif.c
new file mode 100644
index ..191dcc61e6d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr114981-powif.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-Os" } */
+
+const float vals[] =
+  {
+0.0625f, -0.125f, 0.25f, -0.5f,
+1.0f,
+-2.0f, 4.0f, -8.0f, 16.0f
+  };
+
+#define ARRAY_SIZE(X) ((int) (sizeof(X) / sizeof(*X)))
+
+__attribute__((noinline,noclone))
+void test1 (float x)
+{
+  int i;
+
+  for (i = 0; i < ARRAY_SIZE (vals); ++i)
+{
+  float val0 = vals[i];
+  float val1 = __builtin_powif (x, i - 4);
+  __asm ("" : "+r" (val0));
+
+  if (val0 != val1)
+   __builtin_exit (__LINE__);
+}
+}
+
+int main (void)
+{
+  test1 (-2.0f);
+  return 0;
+}
diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index af4d7d970169..a0854139a0a3 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -80,6 +80,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #endif
 .endm
 
+.macro mov4  r_dest, r_src
+wmov \r_dest,   \r_src
+wmov \r_dest+2, \r_src+2
+.endm
+
 #if defined (__AVR_HAVE_JMP_CALL__)
 #define XCALL call
 #define XJMP  jmp
@@ -3312,4 +3317,153 @@ ENDF __fmul
 #undef C0
 #undef C1
 
+
+
+/**
+ * Floating-Point
+ **/
+
+#if defined (L_powif)
+#ifndef __AVR_TINY__
+
+;; float output and arg #1
+#define A0  22
+#define A1  A0 + 1
+#define A2  A0 + 2
+#define A3  A0 + 3
+
+;; float arg #2
+#define B0  18
+#define B1  B0 + 1
+#define B2  B0 + 2
+#define B3  B0 + 3
+
+;; float X: input and iterated squares
+#define X0  10
+#define X1  X0 + 1
+#define X2  X0 + 2
+#define X3  X0 + 3
+
+;; float Y: expand result
+#define Y0  14
+#define Y1  Y0 + 1
+#define Y2  Y0 + 2
+#define Y3  Y0 + 3
+
+;; .7 = Sign of I.
+;; .0 == 0  =>  Y = 1.0f implicitly.
+#define Flags   R9
+#define Y_set   0
+
+;;;  Integer exponent input.
+#define I0  28
+#define I1  I0+1
+
+#define ONE 0x3f80
+
+DEFUN __powisf2
+;; Save 11 Registers: R9...R17, R28, R29
+do_prologue_saves 11
+
+;; Fill local vars with input parameters.
+wmovI0, 20
+mov4X0, A0
+;; Save sign of exponent for later.
+mov Flags,  I1
+;; I := abs (I)
+tst I1
+brpl 1f
+NEG2I0
+1:
+;; Y := (I % 2) ? X : 1.0f
+;; (When we come from below, this is like SET, i.e. Flags.Y_set := 1).
+bst I0, 0
+;; Flags.Y_set = false means that we have to assume Y = 1.0f below.
+bld Flags,  Y_set
+2:  ;; We have A == X when we come from above.
+mov4Y0, A0
+
+.Loop:
+;; while (I >>= 1)
+lsr I1
+ror I0
+sbiwI0, 0
+breq .Loop_done
+
+;; X := X * X
+mov4A0, X0
+#ifdef __WITH_AVRLIBC__
+XCALL   squaref
+#else
+mov4B0, X0
+XCALL   __mulsf3
+#endif /* Have AVR-LibC? */
+mov4X0, A0
+
+;; if (I % 2 == 1)  Y := Y * X
+bst I0, 0
+brtc .Loop
+bst Flags, Y_set
+;; When Y is not set  =>  Y := Y * X = 1.0f * X (= A)
+;; Plus, we have to set Y_set = 1 (= I0.0)
+brtc 1b
+;; Y is already set: Y := X * Y (= A * Y)
+mov4B0, Y0
+XCALL   __mulsf3
+rjmp 2b
+
+;; End while
+.Loop_done:
+
+;; A := 1.0f
+ldi A3, hhi8(ONE)
+ldi A2, hlo8(ONE)
+ldi A1, hi8(ONE)
+ldi A0, lo8(ONE)
+
+;; When Y is still not set, the result is 1.0f (= A).
+bst Flags, Y_set
+brtc .Lret
+
+;; if (I was < 0) Y = 1.0f / Y
+tst Flags
+brmi 1f
+;; A := Y
+mov4A0, Y0
+rjmp .Lret
+1:  ;; A := 1 / Y = A / Y
+mov4B0, Y0
+XCALL   __divsf3
+
+.Lret:
+do_epilogue_restores 11
+ENDF __powisf2
+
+#undef A0
+#undef A1
+#undef A2
+#u

[gcc r15-645] AVR: target/115065 - Tweak __clzhi2.

2024-05-18 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:988838da722dea09bd81ee9d49800a6f24980372

commit r15-645-g988838da722dea09bd81ee9d49800a6f24980372
Author: Wolfgang Hospital 
Date:   Sat May 18 15:02:51 2024 +0200

AVR: target/115065 - Tweak __clzhi2.

The libgcc implementation of __clzhi2 can be tweaked by
one cycle in some situations by re-arranging the instructions.
It also reduces the WCET by 1 cycle.

libgcc/
PR target/115065
* config/avr/lib1funcs.S (__clzhi2): Tweak.

Diff:
---
 libgcc/config/avr/lib1funcs.S | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index 04a4eb01ab43..d48b04747da8 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -2921,11 +2921,9 @@ DEFUN __clzhi2
 clr  r26
 tst  r25
 brne 1f
-subi r26, -8
 or   r25, r24
-brne 1f
-ldi  r24, 16
-ret
+breq 0f
+subi r26, -8
 1:  cpi  r25, 16
 brsh 3f
 subi r26, -3
@@ -2936,6 +2934,8 @@ DEFUN __clzhi2
 mov  r24, r26
 clr  r25
 ret
+0:  ldi  r24, 16
+ret
 ENDF __clzhi2
 #endif /* defined (L_clzhi2) */


[gcc r14-10217] AVR: target/115065 - Tweak __clzhi2.

2024-05-18 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:3b88dade7ff8a07fd0843ac1281e095cfd94453e

commit r14-10217-g3b88dade7ff8a07fd0843ac1281e095cfd94453e
Author: Wolfgang Hospital 
Date:   Sat May 18 15:02:51 2024 +0200

AVR: target/115065 - Tweak __clzhi2.

The libgcc implementation of __clzhi2 can be tweaked by
one cycle in some situations by re-arranging the instructions.
It also reduces the WCET by 1 cycle.

libgcc/
PR target/115065
* config/avr/lib1funcs.S (__clzhi2): Tweak.

(cherry picked from commit 988838da722dea09bd81ee9d49800a6f24980372)

Diff:
---
 libgcc/config/avr/lib1funcs.S | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index a0854139a0a3..1d04fed72644 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -2921,11 +2921,9 @@ DEFUN __clzhi2
 clr  r26
 tst  r25
 brne 1f
-subi r26, -8
 or   r25, r24
-brne 1f
-ldi  r24, 16
-ret
+breq 0f
+subi r26, -8
 1:  cpi  r25, 16
 brsh 3f
 subi r26, -3
@@ -2936,6 +2934,8 @@ DEFUN __clzhi2
 mov  r24, r26
 clr  r25
 ret
+0:  ldi  r24, 16
+ret
 ENDF __clzhi2
 #endif /* defined (L_clzhi2) */


[gcc r15-3659] AVR: Partially revert r15-3623.

2024-09-16 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:9f8e18213cbcfbadce56f7f531bd61fe4c7eab11

commit r15-3659-g9f8e18213cbcfbadce56f7f531bd61fe4c7eab11
Author: Georg-Johann Lay 
Date:   Sun Sep 15 20:37:48 2024 +0200

AVR: Partially revert r15-3623.

ADIW doesn't mix with CPC / SBIC because it's not only about
propagating the Z flag but also about carry.

gcc/
* config/avr/avr.cc (avr_out_compare): Don't mix ADIW with SBCI / 
CPC.

Diff:
---
 gcc/config/avr/avr.cc | 32 ++--
 1 file changed, 10 insertions(+), 22 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 4cb51ea68dc7..5597f3ef74dc 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -6026,25 +6026,15 @@ avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
   if (n_bytes == 4
   && eqne_p
   && AVR_HAVE_ADIW
-  && REGNO (xreg) >= REG_22)
+  && REGNO (xreg) >= REG_22
+  && (xval == const0_rtx
+ || (IN_RANGE (avr_int16 (xval, 2), 0, 63)
+ && reg_unused_after (insn, xreg
 {
-  if (xval == const0_rtx)
-   return avr_asm_len ("sbiw %C0,0"   CR_TAB
-   "cpc %B0,__zero_reg__" CR_TAB
-   "cpc %A0,__zero_reg__", xop, plen, 3);
-
-  int16_t hi16 = avr_int16 (xval, 2);
-  if (reg_unused_after (insn, xreg)
- && (IN_RANGE (hi16, 0, 63)
- || (eqne_p
- && IN_RANGE (hi16, -63, -1
-   {
- rtx op[] = { xop[0], avr_word (xval, 2) };
- avr_asm_len (hi16 < 0 ? "adiw %C0,%n1" : "sbiw %C0,%1",
-  op, plen, 1);
- return avr_asm_len ("sbci %B0,hi8(%1)" CR_TAB
- "sbci %A0,lo8(%1)", xop, plen, 2);
-   }
+  xop[2] = avr_word (xval, 2);
+  return avr_asm_len ("sbiw %C0,%2"  CR_TAB
+ "sbci %B0,hi8(%1)" CR_TAB
+ "sbci %A0,lo8(%1)", xop, plen, 3);
 }
 
   bool changed[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -6078,12 +6068,10 @@ avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
 
  if (IN_RANGE (val16, -63, -1)
  && eqne_p
+ && n_bytes == 2
  && reg_unused_after (insn, xreg))
{
- avr_asm_len ("adiw %0,%n1", xop, plen, 1);
- changed[0] = changed[1] = true;
- i++;
- continue;
+ return avr_asm_len ("adiw %0,%n1", xop, plen, 1);
}
}


[gcc r15-3660] AVR: Tidy up enum and struct tags.

2024-09-16 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:8d402c307f289a4cc96fec36189864d7e3f37893

commit r15-3660-g8d402c307f289a4cc96fec36189864d7e3f37893
Author: Georg-Johann Lay 
Date:   Sat Sep 14 12:19:52 2024 +0200

AVR: Tidy up enum and struct tags.

Use "rtx_code" for RTX codes, not "enum rtx_code" and not "RTX_CODE".
Drop enum and struct tags if possible.

gcc/
* config/avr/avr.cc: Use rtx_code for RTX codes.
Drop enum and struct tags.
* config/avr/avr.md: Same.
* config/avr/avr-c.cc: Same.
* config/avr/avr-dimode.md: Same.
* config/avr/avr-passes.cc: Same.
* config/avr/avr-protos.h: Same.

Diff:
---
 gcc/config/avr/avr-c.cc  |  4 +-
 gcc/config/avr/avr-dimode.md |  6 +--
 gcc/config/avr/avr-passes.cc |  8 ++--
 gcc/config/avr/avr-protos.h  | 12 +++---
 gcc/config/avr/avr.cc| 96 ++--
 gcc/config/avr/avr.md|  8 ++--
 6 files changed, 67 insertions(+), 67 deletions(-)

diff --git a/gcc/config/avr/avr-c.cc b/gcc/config/avr/avr-c.cc
index 34c73c6bf552..81c91c383638 100644
--- a/gcc/config/avr/avr-c.cc
+++ b/gcc/config/avr/avr-c.cc
@@ -51,7 +51,7 @@ static tree
 avr_resolve_overloaded_builtin (unsigned int iloc, tree fndecl, void *vargs)
 {
   tree type0, type1, fold = NULL_TREE;
-  enum avr_builtin_id id = AVR_BUILTIN_COUNT;
+  avr_builtin_id id = AVR_BUILTIN_COUNT;
   location_t loc = (location_t) iloc;
   vec &args = * (vec*) vargs;
 
@@ -291,7 +291,7 @@ avr_toupper (char *up, const char *lo)
 /* Worker function for TARGET_CPU_CPP_BUILTINS.  */
 
 void
-avr_cpu_cpp_builtins (struct cpp_reader *pfile)
+avr_cpu_cpp_builtins (cpp_reader *pfile)
 {
   builtin_define_std ("AVR");
 
diff --git a/gcc/config/avr/avr-dimode.md b/gcc/config/avr/avr-dimode.md
index e6284ced45df..593372187832 100644
--- a/gcc/config/avr/avr-dimode.md
+++ b/gcc/config/avr/avr-dimode.md
@@ -459,11 +459,11 @@
   (label_ref (match_operand 3))
   (pc)))]
   "avr_have_dimode"
-   {
+  {
 int icode = (int) GET_CODE (operands[0]);
 
 targetm.canonicalize_comparison (&icode, &operands[1], &operands[2], 
false);
-operands[0] = gen_rtx_fmt_ee ((enum rtx_code) icode,
+operands[0] = gen_rtx_fmt_ee ((rtx_code) icode,
   VOIDmode, operands[1], operands[2]);
 
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -488,7 +488,7 @@
 emit_jump_insn (gen_cbranch_2_split (operands[0], operands[3]));
   }
 DONE;
-   })
+  })
 
 (define_insn_and_split "cbranch_2_split"
   [(set (pc)
diff --git a/gcc/config/avr/avr-passes.cc b/gcc/config/avr/avr-passes.cc
index 95b8e9a7529b..ad913ddd4afc 100644
--- a/gcc/config/avr/avr-passes.cc
+++ b/gcc/config/avr/avr-passes.cc
@@ -813,7 +813,7 @@ avr_optimize_casesi (rtx_insn *insns[5], rtx *xop)
 
   // How the original switch value was extended to SImode; this is
   // SIGN_EXTEND or ZERO_EXTEND.
-  enum rtx_code code = GET_CODE (xop[9]);
+  rtx_code code = GET_CODE (xop[9]);
 
   // Lower index, upper index (plus one) and range of case calues.
   HOST_WIDE_INT low_idx = -INTVAL (xop[1]);
@@ -1078,7 +1078,7 @@ public:
   {
 rtx reg_or_0, mem, addr, addr_reg;
 int addr_regno;
-enum rtx_code addr_code;
+rtx_code addr_code;
 machine_mode mode;
 addr_space_t addr_space;
 bool store_p, volatile_p;
@@ -1744,7 +1744,7 @@ avr_split_fake_addressing_move (rtx_insn * /*insn*/, rtx 
*xop)
 
   machine_mode mode = GET_MODE (mem);
   rtx base, addr = XEXP (mem, 0);
-  enum rtx_code addr_code = GET_CODE (addr);
+  rtx_code addr_code = GET_CODE (addr);
 
   if (REG_P (reg_or_0)
   && reg_overlap_mentioned_p (reg_or_0, addr))
@@ -1784,7 +1784,7 @@ avr_split_fake_addressing_move (rtx_insn * /*insn*/, rtx 
*xop)
mem_volatile_p = true;
 }
 
-  enum rtx_code new_code = UNKNOWN;
+  rtx_code new_code = UNKNOWN;
   HOST_WIDE_INT add = 0, sub = 0;
   int msize = GET_MODE_SIZE (mode);
 
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 71c110c791ff..c8aa7c72df73 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -20,7 +20,7 @@
 
 
 extern int avr_function_arg_regno_p (int r);
-extern void avr_cpu_cpp_builtins (struct cpp_reader * pfile);
+extern void avr_cpu_cpp_builtins (cpp_reader * pfile);
 extern enum reg_class avr_regno_reg_class (int r);
 extern void asm_globalize_label (FILE *file, const char *name);
 extern void avr_adjust_reg_alloc_order (void);
@@ -66,7 +66,7 @@ extern const char *avr_out_plus_set_N (rtx*, int*);
 extern const char *avr_out_op8_set_ZN (rtx_code, rtx*, int*);
 extern int avr_len_op8_set_ZN (rtx_code, rtx*);
 extern bool avr_op8_ZN_operator (rtx);
-extern const char *avr_out_cmp_ext (rtx*, enum rtx_code, int*);
+extern const char *avr_out_cmp_ext (rtx*, rtx_code, int*);
 
 extern const char *ashlqi3_out (rtx_insn *insn, rtx operands[], int *len);
 extern const char *ashlhi3_out (rtx_insn *in

[gcc r15-3664] AVR: Tweak >= and < compares with consts that are 0 mod 256.

2024-09-16 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:7fb1117310def905f8d151196b8655247dff68ee

commit r15-3664-g7fb1117310def905f8d151196b8655247dff68ee
Author: Georg-Johann Lay 
Date:   Sun Sep 15 16:58:09 2024 +0200

AVR: Tweak >= and < compares with consts that are 0 mod 256.

The >= and < comparisons may skip comparing the lower bytes when
the according bytes of the constant are all zeros.  For example,

uint16 >= 0x1200

is true iff

hi8 (uint16) >= hi8 (0x1200)

and similar for uint16 < 0x1200.  Some comparisons against constants
that are an integral power of 256 where already handled in the split
preparation.  That code has been outsourced to new avr_maybe_cmp_lsr()
which may change the operands such that the resulting insns become
a comparison of the high bytes against 0 plus a EQ / NE branch.
For example,

uint32 >= 0x1

can be rewritten as

(uint32 >> 16) != 0.

The according asm output is performed by new avr_out_cmp_lsr().

gcc/
* config/avr/avr-protos.h (avr_out_cmp_lsr, avr_maybe_cmp_lsr): New.
* config/avr/avr.cc (avr_maybe_cmp_lsr, avr_out_cmp_lsr): New 
functions.
(avr_out_compare) [GEU, LTU]: Start output at byte CTZ(xval) / 8.
(avr_adjust_insn_length) [ADJUST_LEN_CMP_LSR]: Handle case.
* config/avr/avr.md (adjust_len) : New attr value.
(*cmp_lsr): New define_insn_and_split.
(cbranch4_insn): When splitting, run avr_maybe_cmp_lsr()
which may map the operands to *cmp_lsr.
gcc/testsuite/
* gcc.target/avr/torture/cmp-lsr-i32.c: New test.
* gcc.target/avr/torture/cmp-lsr-u16.c: New test.
* gcc.target/avr/torture/cmp-lsr-u24.c: New test.
* gcc.target/avr/torture/cmp-lsr-u32.c: New test.
* gcc.target/avr/torture/cmp-lsr-u64.c: New test.

Diff:
---
 gcc/config/avr/avr-protos.h|   3 +-
 gcc/config/avr/avr.cc  | 147 +++--
 gcc/config/avr/avr.md  |  70 ++
 gcc/testsuite/gcc.target/avr/torture/cmp-lsr-i32.c |  82 
 gcc/testsuite/gcc.target/avr/torture/cmp-lsr-u16.c |  73 ++
 gcc/testsuite/gcc.target/avr/torture/cmp-lsr-u24.c |  76 +++
 gcc/testsuite/gcc.target/avr/torture/cmp-lsr-u32.c |  78 +++
 gcc/testsuite/gcc.target/avr/torture/cmp-lsr-u64.c |  84 
 8 files changed, 572 insertions(+), 41 deletions(-)

diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index c8aa7c72df73..96708eb4db58 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -115,7 +115,8 @@ extern const char* output_reload_inhi (rtx*, rtx, int*);
 extern const char* output_reload_insisf (rtx*, rtx, int*);
 extern const char* avr_out_reload_inpsi (rtx*, rtx, int*);
 extern const char* avr_out_lpm (rtx_insn *, rtx*, int*);
-extern void avr_notice_update_cc (rtx body, rtx_insn *insn);
+extern const char* avr_out_cmp_lsr (rtx_insn *, rtx*, int*);
+extern void avr_maybe_cmp_lsr (rtx *);
 extern int reg_unused_after (rtx_insn *insn, rtx reg);
 extern int avr_jump_mode (rtx x, rtx_insn *insn, int = 0);
 extern int test_hard_reg_class (enum reg_class rclass, rtx x);
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index cf17be043763..c0bf1320fdd9 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -5943,6 +5943,118 @@ avr_canonicalize_comparison (int *icode, rtx *op0, rtx 
*op1, bool op0_fixed)
 }
 
 
+/* Try to turn a GEU or LTU comparison of register XOP[1] into an
+   NE / EQ comparison of the higher bytes of XOP[1] against 0.
+   XOP[1] has scalar int or scalar fixed-point mode of 2, 3 or 4 bytes.
+   XOP[2] is a compile-time constant, and XOP[0] = XOP[1]  XOP[2]
+   is the comparison operator.  XOP[3] is the branch label, and XOP[4]
+   is a QImode scratch operand.
+  When XOP[1] (viewed as a CONST_INT) is an integral power of 256,
+   then a GTU or LTU comparison can be turned into a NE or EQ comparison
+   of the high bytes against zero.  For example, the C code
+
+   if (x >= 1)
+ ccc = 0;
+
+   where x is an unsigned _Accum may be compiled as:
+
+   or r24,r25   ;  *cmpsi_lsr
+   breq .L1 ;  branch
+   sts ccc,__zero_reg__ ;  movqi_insn
+ .L1:
+
+   In the case of success, the operands will be such that they comprise
+   a *cmp_lsr insn, where mode is HI, PSI or SI, and XOP[0] will be
+   a NE or EQ branch condition.  Otherwise, XOP[] is unchanged.  */
+
+void
+avr_maybe_cmp_lsr (rtx *xop)
+{
+  rtx_code comp = GET_CODE (xop[0]);
+
+  if ((comp == GEU || comp == LTU)
+  && (CONST_INT_P (xop[2]) || CONST_FIXED_P (xop[2])))
+{
+  rtx xreg = avr_to_int_mode (xop[1]);
+  rtx xval = avr_to_int_mode (xop[2]);
+  machine_mode imode = GET_MODE (xreg);
+  auto uval = UINTVAL (xval) & GE

[gcc r15-3667] AVR: Update weblinks to AVR-LibC.

2024-09-16 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:f5448384a2134f32c8733b401440da11bfe69252

commit r15-3667-gf5448384a2134f32c8733b401440da11bfe69252
Author: Georg-Johann Lay 
Date:   Mon Sep 16 17:23:00 2024 +0200

AVR: Update weblinks to AVR-LibC.

AVR-LibC has moved to GitHub, adjust web links:
https://github.com/avrdudes/avr-libc (project)
https://avrdudes.github.io/avr-libc/avr-libc-user-manual (wwwdocs)

gcc/
* doc/invoke.texi (AVR Options): Update AVR-LibC weblink from
nongnu.org to https://github.com/avrdudes/avr-libc
* doc/extend.texi (AVR Named Address Spaces): Same.
(AVR Function Attributes): Same.
* doc/install.texi (Cross-Compiler-Specific Options, AVR): Same.

Diff:
---
 gcc/doc/extend.texi  | 6 +++---
 gcc/doc/install.texi | 5 +++--
 gcc/doc/invoke.texi  | 4 ++--
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 2d795ba7e599..c95df8456344 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1593,7 +1593,7 @@ locates data in flash but
 accesses to these data read from generic address space, i.e.@:
 from RAM,
 so that you need special accessors like @code{pgm_read_byte}
-from @w{@uref{https://www.nongnu.org/avr-libc/user-manual/,AVR-LibC}}
+from 
@w{@uref{https://avrdudes.github.io/avr-libc/avr-libc-user-manual/,AVR-LibC}}
 together with attribute @code{progmem}.
 
 @noindent
@@ -5181,7 +5181,7 @@ globally enable interrupts.
 
 The recommended way to use these attributes is by means of the
 @code{ISR} macro provided by @code{avr/interrupt.h} from
-@w{@uref{https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html,,AVR-LibC}}:
+@w{@uref{https://avrdudes.github.io/avr-libc/avr-libc-user-manual/group__avr__interrupts.html,,AVR-LibC}}:
 @example
 #include 
 
@@ -5219,7 +5219,7 @@ static void my_handler (void)
 Notice that the handler function needs not to be externally visible.
 The recommended way to use these attributes is by means of the
 @code{ISR_N} macro provided by @code{avr/interrupt.h} from
-@w{@uref{https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html,,AVR-LibC}}:
+@w{@uref{https://avrdudes.github.io/avr-libc/avr-libc-user-manual/group__avr__interrupts.html,,AVR-LibC}}:
 
 @example
 #include 
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 62a611045985..1ca0f14b44d1 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -2688,8 +2688,9 @@ omitted from @file{libgcc.a} on the assumption that it 
will be provided by
 
 @end html
 @item --with-avrlibc
-Only supported for the AVR target. Specifies that @samp{AVR-Libc} is
-being used as the target C@tie{} library.  This causes float support
+Only supported for the AVR target. Specifies that
+@uref{https://github.com/avrdudes/avr-libc/,,AVR-LibC}
+is being used as the target C@tie{} library.  This causes float support
 functions like @code{__addsf3} to be omitted from @file{libgcc.a} on
 the assumption that it will be provided by @file{libm.a}.  For more
 technical details, cf. @uref{https://gcc.gnu.org/PR54461,,PR54461}.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index a6cd5111d47c..511b8c8d3111 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -24053,7 +24053,7 @@ a device library @code{lib@var{mcu}.a} and a
 @uref{https://gcc.gnu.org/wiki/avr-gcc#spec-files,device-specs} file
 @code{specs-@var{mcu}}. Only the latter is provided by the compiler
 according the supported @code{@var{mcu}}s below.  The rest is supported
-by @w{@uref{https://www.nongnu.org/avr-libc/,AVR-LibC}}, or by means of
+by @w{@uref{https://github.com/avrdudes/avr-libc/,AVR-LibC}}, or by means of
 @uref{https://gcc.gnu.org/wiki/avr-gcc#atpack,@code{atpack}} files
 from the hardware manufacturer.
 
@@ -24289,7 +24289,7 @@ points to.
 The startup code from libgcc never sets @code{EIND}.
 Notice that startup code is a blend of code from libgcc and AVR-LibC.
 For the impact of AVR-LibC on @code{EIND}, see the
-@w{@uref{https://www.nongnu.org/avr-libc/user-manual/,AVR-LibC user manual}}.
+@w{@uref{https://avrdudes.github.io/avr-libc/avr-libc-user-manual/,AVR-LibC 
user manual}}.
 
 @item
 It is legitimate for user-specific startup code to set up @code{EIND}


[gcc r15-2963] AVR: target/116390 - Fix an avrtiny asm out template.

2024-08-17 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:4065d163151b07b274241377e71dad028576db88

commit r15-2963-g4065d163151b07b274241377e71dad028576db88
Author: Georg-Johann Lay 
Date:   Sat Aug 17 12:49:42 2024 +0200

AVR: target/116390 - Fix an avrtiny asm out template.

PR target/116390
gcc/
* config/avr/avr.cc (avr_out_movsi_mr_r_reg_disp_tiny): Fix
output templates for the reg_base == reg_src and
reg_src == reg_base - 2 cases.
gcc/testsuite/
* gcc.target/avr/torture/pr116390.c: New test.

Diff:
---
 gcc/config/avr/avr.cc   | 30 +--
 gcc/testsuite/gcc.target/avr/torture/pr116390.c | 71 +
 2 files changed, 86 insertions(+), 15 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 8d59a6babed..8c19bcb34a6 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -5638,33 +5638,33 @@ avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
   rtx src = op[1];
   rtx base = XEXP (dest, 0);
   int reg_base = REGNO (XEXP (base, 0));
-  int reg_src =true_regnum (src);
+  int reg_src = true_regnum (src);
 
   if (reg_base == reg_src)
 {
   *l = 11;
-  return ("mov __tmp_reg__,%A2"CR_TAB
- "mov __zero_reg__,%B2"   CR_TAB
+  return ("mov __tmp_reg__,%A1"CR_TAB
+ "mov __zero_reg__,%B1"   CR_TAB
  TINY_ADIW (%I0, %J0, %o0)CR_TAB
  "st %b0+,__tmp_reg__"CR_TAB
  "st %b0+,__zero_reg__"   CR_TAB
- "st %b0+,%C2"CR_TAB
- "st %b0,%D2" CR_TAB
+ "st %b0+,%C1"CR_TAB
+ "st %b0,%D1" CR_TAB
  "clr __zero_reg__"   CR_TAB
  TINY_SBIW (%I0, %J0, %o0+3));
 }
   else if (reg_src == reg_base - 2)
 {
-  *l = 11;
-  return ("mov __tmp_reg__,%C2" CR_TAB
- "mov __zero_reg__,%D2"CR_TAB
- TINY_ADIW (%I0, %J0, %o0) CR_TAB
- "st %b0+,%A0" CR_TAB
- "st %b0+,%B0" CR_TAB
- "st %b0+,__tmp_reg__" CR_TAB
- "st %b0,__zero_reg__" CR_TAB
- "clr __zero_reg__"CR_TAB
- TINY_SBIW (%I0, %J0, %o0+3));
+  // This awkward case can occur when ext-dce turns zero-extend:SI(HI)
+  // into a paradoxical subreg, which register allocation may turn into
+  // something like *(R28:HI + 7) = R26:SI.  There is actually no need
+  // to store the upper 2 bytes of R26:SI as they are unused rubbish.
+  // See PR116390.
+  *l = 6;
+  return (TINY_ADIW (%I0, %J0, %o0) CR_TAB
+ "st %b0+,%A1" CR_TAB
+ "st %b0,%B1"  CR_TAB
+ TINY_SBIW (%I0, %J0, %o0+1));
 }
   *l = 8;
   return (TINY_ADIW (%I0, %J0, %o0) CR_TAB
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr116390.c 
b/gcc/testsuite/gcc.target/avr/torture/pr116390.c
new file mode 100644
index 000..70c1ad62936
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr116390.c
@@ -0,0 +1,71 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99" } */
+
+typedef struct
+{
+int i;
+} MyStruct;
+
+void f_ic (int, char);
+void f_pi (char const *, int);
+void f_iic (int, int, char);
+
+const MyStruct *f_rms (void);
+
+char *f_rcp (void);
+int f_ri (void);
+
+void badFoo (void)
+{
+const MyStruct* ps = f_rms ();
+const char* pc = f_rcp ();
+
+unsigned n1 = f_rcp () - pc;
+
+if (n1)
+{
+long n2 = n1 - ps->i;
+if (n2 > 0)
+{
+if (f_ri ())
+n2 = n1;
+
+if (f_ri ())
+{
+f_iic (1, 2 * n2, ' ');
+}
+else
+f_pi (pc, n2);
+}
+if (ps->i > 0)
+{
+if (n2 >= 0)
+f_pi (pc + n2, ps->i);
+else
+{
+f_ic (n2, ' ');
+}
+}
+
+const int which = f_ri ();
+switch (which)
+{
+case 1:
+if (f_ri ())
+f_rcp ()[1] = ' ';
+break;
+
+case 2:
+f_pi (f_rcp (), 1);
+break;
+
+case 3:
+if (f_ri () && n1 < 0)
+f_ic (n1, ' ');
+else
+f_rcp ()[1] = ' ';
+break;
+
+}
+}
+}


[gcc r14-10597] AVR: target/116390 - Fix an avrtiny asm out template.

2024-08-17 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:f3d9c120a1959c5b094001516c1e5cb4ba6f4080

commit r14-10597-gf3d9c120a1959c5b094001516c1e5cb4ba6f4080
Author: Georg-Johann Lay 
Date:   Sat Aug 17 12:49:42 2024 +0200

AVR: target/116390 - Fix an avrtiny asm out template.

PR target/116390
gcc/
* config/avr/avr.cc (avr_out_movsi_mr_r_reg_disp_tiny): Fix
output templates for the reg_base == reg_src and
reg_src == reg_base - 2 cases.
gcc/testsuite/
* gcc.target/avr/torture/pr116390.c: New test.

(cherry picked from commit 4065d163151b07b274241377e71dad028576db88)

Diff:
---
 gcc/config/avr/avr.cc   | 30 +--
 gcc/testsuite/gcc.target/avr/torture/pr116390.c | 71 +
 2 files changed, 86 insertions(+), 15 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 71929b28160..3c1a0bf707f 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -5501,33 +5501,33 @@ avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
   rtx src = op[1];
   rtx base = XEXP (dest, 0);
   int reg_base = REGNO (XEXP (base, 0));
-  int reg_src =true_regnum (src);
+  int reg_src = true_regnum (src);
 
   if (reg_base == reg_src)
 {
   *l = 11;
-  return ("mov __tmp_reg__,%A2"CR_TAB
- "mov __zero_reg__,%B2"   CR_TAB
+  return ("mov __tmp_reg__,%A1"CR_TAB
+ "mov __zero_reg__,%B1"   CR_TAB
  TINY_ADIW (%I0, %J0, %o0)CR_TAB
  "st %b0+,__tmp_reg__"CR_TAB
  "st %b0+,__zero_reg__"   CR_TAB
- "st %b0+,%C2"CR_TAB
- "st %b0,%D2" CR_TAB
+ "st %b0+,%C1"CR_TAB
+ "st %b0,%D1" CR_TAB
  "clr __zero_reg__"   CR_TAB
  TINY_SBIW (%I0, %J0, %o0+3));
 }
   else if (reg_src == reg_base - 2)
 {
-  *l = 11;
-  return ("mov __tmp_reg__,%C2" CR_TAB
- "mov __zero_reg__,%D2"CR_TAB
- TINY_ADIW (%I0, %J0, %o0) CR_TAB
- "st %b0+,%A0" CR_TAB
- "st %b0+,%B0" CR_TAB
- "st %b0+,__tmp_reg__" CR_TAB
- "st %b0,__zero_reg__" CR_TAB
- "clr __zero_reg__"CR_TAB
- TINY_SBIW (%I0, %J0, %o0+3));
+  // This awkward case can occur when ext-dce turns zero-extend:SI(HI)
+  // into a paradoxical subreg, which register allocation may turn into
+  // something like *(R28:HI + 7) = R26:SI.  There is actually no need
+  // to store the upper 2 bytes of R26:SI as they are unused rubbish.
+  // See PR116390.
+  *l = 6;
+  return (TINY_ADIW (%I0, %J0, %o0) CR_TAB
+ "st %b0+,%A1" CR_TAB
+ "st %b0,%B1"  CR_TAB
+ TINY_SBIW (%I0, %J0, %o0+1));
 }
   *l = 8;
   return (TINY_ADIW (%I0, %J0, %o0) CR_TAB
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr116390.c 
b/gcc/testsuite/gcc.target/avr/torture/pr116390.c
new file mode 100644
index 000..70c1ad62936
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr116390.c
@@ -0,0 +1,71 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99" } */
+
+typedef struct
+{
+int i;
+} MyStruct;
+
+void f_ic (int, char);
+void f_pi (char const *, int);
+void f_iic (int, int, char);
+
+const MyStruct *f_rms (void);
+
+char *f_rcp (void);
+int f_ri (void);
+
+void badFoo (void)
+{
+const MyStruct* ps = f_rms ();
+const char* pc = f_rcp ();
+
+unsigned n1 = f_rcp () - pc;
+
+if (n1)
+{
+long n2 = n1 - ps->i;
+if (n2 > 0)
+{
+if (f_ri ())
+n2 = n1;
+
+if (f_ri ())
+{
+f_iic (1, 2 * n2, ' ');
+}
+else
+f_pi (pc, n2);
+}
+if (ps->i > 0)
+{
+if (n2 >= 0)
+f_pi (pc + n2, ps->i);
+else
+{
+f_ic (n2, ' ');
+}
+}
+
+const int which = f_ri ();
+switch (which)
+{
+case 1:
+if (f_ri ())
+f_rcp ()[1] = ' ';
+break;
+
+case 2:
+f_pi (f_rcp (), 1);
+break;
+
+case 3:
+if (f_ri () && n1 < 0)
+f_ic (n1, ' ');
+else
+f_rcp ()[1] = ' ';
+break;
+
+}
+}
+}


[gcc r15-2982] AVR: target/116407 - Fix linker error "relocation truncated to fit".

2024-08-18 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:dfb2e8caa85d1059a0ab8ed4f19568c04c9f13a4

commit r15-2982-gdfb2e8caa85d1059a0ab8ed4f19568c04c9f13a4
Author: Georg-Johann Lay 
Date:   Sun Aug 18 15:00:55 2024 +0200

AVR: target/116407 - Fix linker error "relocation truncated to fit".

Some text peepholes output extra instructions prior to a branch
instruction and that increase the jump offset of backward branches.

PR target/116407
gcc/
* config/avr/avr-protos.h (avr_jump_mode): Add an int argument.
* config/avr/avr.cc (avr_jump_mode): Add an int argument to increase
the computed jump offset of backwards branches.
* config/avr/avr.md (*dec-and-branchhi!=-1, *dec-and-branchsi!=-1):
Increase the jump offset used by avr_jump_mode() as needed.
gcc/testsuite/
* gcc.target/avr/torture/pr116407-2.c: New test.
* gcc.target/avr/torture/pr116407-4.c: New test.

Diff:
---
 gcc/config/avr/avr-protos.h   |  2 +-
 gcc/config/avr/avr.cc | 11 +---
 gcc/config/avr/avr.md |  8 +++---
 gcc/testsuite/gcc.target/avr/torture/pr116407-2.c | 34 +++
 gcc/testsuite/gcc.target/avr/torture/pr116407-4.c | 34 +++
 5 files changed, 80 insertions(+), 9 deletions(-)

diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 7b666f17718..34298b976a7 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -115,7 +115,7 @@ extern const char* avr_out_reload_inpsi (rtx*, rtx, int*);
 extern const char* avr_out_lpm (rtx_insn *, rtx*, int*);
 extern void avr_notice_update_cc (rtx body, rtx_insn *insn);
 extern int reg_unused_after (rtx_insn *insn, rtx reg);
-extern int avr_jump_mode (rtx x, rtx_insn *insn);
+extern int avr_jump_mode (rtx x, rtx_insn *insn, int = 0);
 extern int test_hard_reg_class (enum reg_class rclass, rtx x);
 extern int jump_over_one_insn_p (rtx_insn *insn, rtx dest);
 
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 8c19bcb34a6..c520b98a178 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -4133,19 +4133,22 @@ avr_use_by_pieces_infrastructure_p (unsigned 
HOST_WIDE_INT size,
 /* Choose mode for jump insn:
1 - relative jump in range -63 <= x <= 62 ;
2 - relative jump in range -2046 <= x <= 2045 ;
-   3 - absolute jump (only for ATmega[16]03).  */
+   3 - absolute jump (only when we have JMP / CALL).
+
+   When jumping backwards, assume the jump offset is EXTRA words
+   bigger than inferred from insn addresses.  */
 
 int
-avr_jump_mode (rtx x, rtx_insn *insn)
+avr_jump_mode (rtx x, rtx_insn *insn, int extra)
 {
   int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
? XEXP (x, 0) : x));
   int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
   int jump_distance = cur_addr - dest_addr;
 
-  if (IN_RANGE (jump_distance, -63, 62))
+  if (IN_RANGE (jump_distance, -63, 62 - extra))
 return 1;
-  else if (IN_RANGE (jump_distance, -2046, 2045))
+  else if (IN_RANGE (jump_distance, -2046, 2045 - extra))
 return 2;
   else if (AVR_HAVE_JMP_CALL)
 return 3;
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 28841e40db1..8c4819a901f 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -7605,7 +7605,7 @@
"sbc %C0,__zero_reg__" CR_TAB
"sbc %D0,__zero_reg__", operands);
 
-int jump_mode = avr_jump_mode (operands[2], insn);
+int jump_mode = avr_jump_mode (operands[2], insn, 3 - avr_adiw_reg_p 
(operands[0]));
 const char *op = ((EQ == ) ^ (jump_mode == 1)) ? "brcc" : "brcs";
 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
 
@@ -7642,7 +7642,7 @@
   output_asm_insn ("subi %A0,1" CR_TAB
"sbc %B0,__zero_reg__", operands);
 
-int jump_mode = avr_jump_mode (operands[2], insn);
+int jump_mode = avr_jump_mode (operands[2], insn, 1 - avr_adiw_reg_p 
(operands[0]));
 const char *op = ((EQ == ) ^ (jump_mode == 1)) ? "brcc" : "brcs";
 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
 
@@ -7681,7 +7681,7 @@
   output_asm_insn ("subi %A0,1" CR_TAB
"sbc %B0,__zero_reg__", operands);
 
-int jump_mode = avr_jump_mode (operands[2], insn);
+int jump_mode = avr_jump_mode (operands[2], insn, 1 - avr_adiw_reg_p 
(operands[0]));
 const char *op = ((EQ == ) ^ (jump_mode == 1)) ? "brcc" : "brcs";
 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
 
@@ -7718,7 +7718,7 @@
  "sub %A0,%3" CR_TAB
  "sbc %B0,__zero_reg__", operands);
 
-int jump_mode = avr_jump_mode (operands[2], insn);
+int jump_mode = avr_jump_mode (operands[2], insn, 1 - avr_adiw_reg_p 
(operands[0]));
 const char *op = ((EQ == ) ^ (jump_mode == 1)) ? "brcc" : "brcs";
 operands[1] = gen_rtx_CONST_STRIN

[gcc r14-10599] AVR: target/116407 - Fix linker error "relocation truncated to fit".

2024-08-18 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:919c42bf4487a8f0cc584a3ca53784c381f19dfa

commit r14-10599-g919c42bf4487a8f0cc584a3ca53784c381f19dfa
Author: Georg-Johann Lay 
Date:   Sun Aug 18 15:00:55 2024 +0200

AVR: target/116407 - Fix linker error "relocation truncated to fit".

Some text peepholes output extra instructions prior to a branch
instruction and that increase the jump offset of backward branches.

PR target/116407
gcc/
* config/avr/avr-protos.h (avr_jump_mode): Add an int argument.
* config/avr/avr.cc (avr_jump_mode): Add an int argument to increase
the computed jump offset of backwards branches.
* config/avr/avr.md (*dec-and-branchhi!=-1, *dec-and-branchsi!=-1):
Increase the jump offset used by avr_jump_mode() as needed.
gcc/testsuite/
* gcc.target/avr/torture/pr116407-2.c: New test.
* gcc.target/avr/torture/pr116407-4.c: New test.

(cherry picked from commit dfb2e8caa85d1059a0ab8ed4f19568c04c9f13a4)

Diff:
---
 gcc/config/avr/avr-protos.h   |  2 +-
 gcc/config/avr/avr.cc | 11 +---
 gcc/config/avr/avr.md |  8 +++---
 gcc/testsuite/gcc.target/avr/torture/pr116407-2.c | 34 +++
 gcc/testsuite/gcc.target/avr/torture/pr116407-4.c | 34 +++
 5 files changed, 80 insertions(+), 9 deletions(-)

diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index dc23cfbf461..d918e2fce31 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -112,7 +112,7 @@ extern const char* avr_out_reload_inpsi (rtx*, rtx, int*);
 extern const char* avr_out_lpm (rtx_insn *, rtx*, int*);
 extern void avr_notice_update_cc (rtx body, rtx_insn *insn);
 extern int reg_unused_after (rtx_insn *insn, rtx reg);
-extern int avr_jump_mode (rtx x, rtx_insn *insn);
+extern int avr_jump_mode (rtx x, rtx_insn *insn, int = 0);
 extern int test_hard_reg_class (enum reg_class rclass, rtx x);
 extern int jump_over_one_insn_p (rtx_insn *insn, rtx dest);
 
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 3c1a0bf707f..c6f29fd48f9 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -3989,19 +3989,22 @@ avr_use_by_pieces_infrastructure_p (unsigned 
HOST_WIDE_INT size,
 /* Choose mode for jump insn:
1 - relative jump in range -63 <= x <= 62 ;
2 - relative jump in range -2046 <= x <= 2045 ;
-   3 - absolute jump (only for ATmega[16]03).  */
+   3 - absolute jump (only when we have JMP / CALL).
+
+   When jumping backwards, assume the jump offset is EXTRA words
+   bigger than inferred from insn addresses.  */
 
 int
-avr_jump_mode (rtx x, rtx_insn *insn)
+avr_jump_mode (rtx x, rtx_insn *insn, int extra)
 {
   int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
? XEXP (x, 0) : x));
   int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
   int jump_distance = cur_addr - dest_addr;
 
-  if (IN_RANGE (jump_distance, -63, 62))
+  if (IN_RANGE (jump_distance, -63, 62 - extra))
 return 1;
-  else if (IN_RANGE (jump_distance, -2046, 2045))
+  else if (IN_RANGE (jump_distance, -2046, 2045 - extra))
 return 2;
   else if (AVR_HAVE_JMP_CALL)
 return 3;
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 55de11079c3..9aaefcfcd64 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -7771,7 +7771,7 @@
"sbc %C0,__zero_reg__" CR_TAB
"sbc %D0,__zero_reg__", operands);
 
-int jump_mode = avr_jump_mode (operands[2], insn);
+int jump_mode = avr_jump_mode (operands[2], insn, 3 - avr_adiw_reg_p 
(operands[0]));
 const char *op = ((EQ == ) ^ (jump_mode == 1)) ? "brcc" : "brcs";
 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
 
@@ -7808,7 +7808,7 @@
   output_asm_insn ("subi %A0,1" CR_TAB
"sbc %B0,__zero_reg__", operands);
 
-int jump_mode = avr_jump_mode (operands[2], insn);
+int jump_mode = avr_jump_mode (operands[2], insn, 1 - avr_adiw_reg_p 
(operands[0]));
 const char *op = ((EQ == ) ^ (jump_mode == 1)) ? "brcc" : "brcs";
 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
 
@@ -7847,7 +7847,7 @@
   output_asm_insn ("subi %A0,1" CR_TAB
"sbc %B0,__zero_reg__", operands);
 
-int jump_mode = avr_jump_mode (operands[2], insn);
+int jump_mode = avr_jump_mode (operands[2], insn, 1 - avr_adiw_reg_p 
(operands[0]));
 const char *op = ((EQ == ) ^ (jump_mode == 1)) ? "brcc" : "brcs";
 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
 
@@ -7884,7 +7884,7 @@
  "sub %A0,%3" CR_TAB
  "sbc %B0,__zero_reg__", operands);
 
-int jump_mode = avr_jump_mode (operands[2], insn);
+int jump_mode = avr_jump_mode (operands[2], insn, 1 - avr_adiw_reg_p 
(operands[0]));
 const char *op = ((EQ == 

[gcc r13-8980] AVR: target/116407 - Fix linker error "relocation truncated to fit".

2024-08-18 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:58c8882ff5ba249ef4cfc99f3c3f8ada8810f75a

commit r13-8980-g58c8882ff5ba249ef4cfc99f3c3f8ada8810f75a
Author: Georg-Johann Lay 
Date:   Sun Aug 18 15:00:55 2024 +0200

AVR: target/116407 - Fix linker error "relocation truncated to fit".

Some text peepholes output extra instructions prior to a branch
instruction and that increase the jump offset of backward branches.

PR target/116407
gcc/
* config/avr/avr-protos.h (avr_jump_mode): Add an int argument.
* config/avr/avr.cc (avr_jump_mode): Add an int argument to increase
the computed jump offset of backwards branches.
* config/avr/avr.md (*dec-and-branchhi!=-1, *dec-and-branchsi!=-1):
Increase the jump offset used by avr_jump_mode() as needed.
gcc/testsuite/
* gcc.target/avr/torture/pr116407-2.c: New test.
* gcc.target/avr/torture/pr116407-4.c: New test.

(cherry picked from commit dfb2e8caa85d1059a0ab8ed4f19568c04c9f13a4)

Diff:
---
 gcc/config/avr/avr-protos.h   |  2 +-
 gcc/config/avr/avr.cc | 11 +---
 gcc/config/avr/avr.md | 24 ++--
 gcc/testsuite/gcc.target/avr/torture/pr116407-2.c | 34 +++
 gcc/testsuite/gcc.target/avr/torture/pr116407-4.c | 34 +++
 5 files changed, 84 insertions(+), 21 deletions(-)

diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index cf45a8c4499..27659bc8e15 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -108,7 +108,7 @@ extern const char* avr_out_lpm (rtx_insn *, rtx*, int*);
 extern void avr_notice_update_cc (rtx body, rtx_insn *insn);
 extern int reg_unused_after (rtx_insn *insn, rtx reg);
 extern int _reg_unused_after (rtx_insn *insn, rtx reg);
-extern int avr_jump_mode (rtx x, rtx_insn *insn);
+extern int avr_jump_mode (rtx x, rtx_insn *insn, int = 0);
 extern int test_hard_reg_class (enum reg_class rclass, rtx x);
 extern int jump_over_one_insn_p (rtx_insn *insn, rtx dest);
 
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 676ab2405db..f5e53aba708 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -3388,19 +3388,22 @@ avr_use_by_pieces_infrastructure_p (unsigned 
HOST_WIDE_INT size,
 /* Choose mode for jump insn:
1 - relative jump in range -63 <= x <= 62 ;
2 - relative jump in range -2046 <= x <= 2045 ;
-   3 - absolute jump (only for ATmega[16]03).  */
+   3 - absolute jump (only when we have JMP / CALL).
+
+   When jumping backwards, assume the jump offset is EXTRA words
+   bigger than inferred from insn addresses.  */
 
 int
-avr_jump_mode (rtx x, rtx_insn *insn)
+avr_jump_mode (rtx x, rtx_insn *insn, int extra)
 {
   int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
 ? XEXP (x, 0) : x));
   int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
   int jump_distance = cur_addr - dest_addr;
 
-  if (IN_RANGE (jump_distance, -63, 62))
+  if (IN_RANGE (jump_distance, -63, 62 - extra))
 return 1;
-  else if (IN_RANGE (jump_distance, -2046, 2045))
+  else if (IN_RANGE (jump_distance, -2046, 2045 - extra))
 return 2;
   else if (AVR_HAVE_JMP_CALL)
 return 3;
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index c8b5ccaf098..9bd6b9119ec 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -7625,8 +7625,6 @@
   (pc)))]
   "dead_or_set_regno_p (insn, REG_CC)"
   {
-const char *op;
-int jump_mode;
 if (avr_adiw_reg_p (operands[0]))
   output_asm_insn ("sbiw %0,1" CR_TAB
"sbc %C0,__zero_reg__" CR_TAB
@@ -7637,8 +7635,8 @@
"sbc %C0,__zero_reg__" CR_TAB
"sbc %D0,__zero_reg__", operands);
 
-jump_mode = avr_jump_mode (operands[2], insn);
-op = ((EQ == ) ^ (jump_mode == 1)) ? "brcc" : "brcs";
+int jump_mode = avr_jump_mode (operands[2], insn, 3 - avr_adiw_reg_p 
(operands[0]));
+const char *op = ((EQ == ) ^ (jump_mode == 1)) ? "brcc" : "brcs";
 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
 
 switch (jump_mode)
@@ -7668,16 +7666,14 @@
   (pc)))]
   "dead_or_set_regno_p (insn, REG_CC)"
   {
-const char *op;
-int jump_mode;
 if (avr_adiw_reg_p (operands[0]))
   output_asm_insn ("sbiw %0,1", operands);
 else
   output_asm_insn ("subi %A0,1" CR_TAB
"sbc %B0,__zero_reg__", operands);
 
-jump_mode = avr_jump_mode (operands[2], insn);
-op = ((EQ == ) ^ (jump_mode == 1)) ? "brcc" : "brcs";
+int jump_mode = avr_jump_mode (operands[2], insn, 1 - avr_adiw_reg_p 
(operands[0]));
+const char *op = ((EQ == ) ^ (jump_mode == 1)) ? "brcc" : "brcs";
 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
 
 switch (jump_mode)
@@ -7709,16 +7705,14 @@
  

[gcc r15-2983] AVR: ad target/116407 - Fix linker error "relocation truncated to fit".

2024-08-18 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:22acd3c4d18dbd4d4d39d7770145fe3ec36073f6

commit r15-2983-g22acd3c4d18dbd4d4d39d7770145fe3ec36073f6
Author: Georg-Johann Lay 
Date:   Sun Aug 18 17:07:15 2024 +0200

AVR: ad target/116407 - Fix linker error "relocation truncated to fit".

PR target/116407
gcc/
* config/avr/avr.md (*dec-and-branchhi!=-1.l.clobber):
Increase the additional jump offset to 2 words.

Diff:
---
 gcc/config/avr/avr.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 8c4819a901f..57f4a08c58c 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -7718,7 +7718,7 @@
  "sub %A0,%3" CR_TAB
  "sbc %B0,__zero_reg__", operands);
 
-int jump_mode = avr_jump_mode (operands[2], insn, 1 - avr_adiw_reg_p 
(operands[0]));
+int jump_mode = avr_jump_mode (operands[2], insn, 2);
 const char *op = ((EQ == ) ^ (jump_mode == 1)) ? "brcc" : "brcs";
 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);


[gcc r15-2984] AVR: Tweak 16-bit addition with const that didn't get a LD_REGS register.

2024-08-18 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:1ed1dd521b8104dd76d010aaf78f130b1832864e

commit r15-2984-g1ed1dd521b8104dd76d010aaf78f130b1832864e
Author: Georg-Johann Lay 
Date:   Sun Aug 18 18:26:16 2024 +0200

AVR: Tweak 16-bit addition with const that didn't get a LD_REGS register.

The 16-bit additions like addhi3 have two forms: One with a scratch:QI
and one without, where the latter is required because reload cannot
deal with a scratch when spill code pops a 16-bit addition.

Passes like combine and fwprop1 may come up with the non-scratch version,
which is sub-optimal in the case when the addition is performed in a
NO_LD_REGS register because the operands will be spilled to LD_REGS.
Having a scratch:QI at disposal can lead to better code with less spills.

gcc/
* config/avr/avr.md (*add3_split) [!reload_completed]:
Add a scratch:QI to 16-bit additions with constant.

Diff:
---
 gcc/config/avr/avr.md | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 57f4a08c58c..c10709ecef0 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -1724,12 +1724,28 @@
(match_operand:ALL2 2 "nonmemory_or_const_operand" "r,s,IJ 
YIJ,n Ynn")))]
   ""
   "#"
-  "&& reload_completed"
+  "&& 1"
   [(parallel [(set (match_dup 0)
(plus:ALL2 (match_dup 1)
   (match_dup 2)))
   (clobber (reg:CC REG_CC))])]
-  ""
+  {
+// Passes like combine and fwprop1 may remove the scratch from an
+// addhi3 insn.  Add the scratch again because having a QImode
+// scratch reg available is better than spilling the operands in
+// the case when we don't get a d-regs register.
+if (! reload_completed
+&& const_operand (operands[2], mode)
+&& ! stack_register_operand (operands[0], HImode)
+&& ! stack_register_operand (operands[1], HImode))
+  {
+emit (gen_add3_clobber (operands[0], operands[1], operands[2]));
+DONE;
+  }
+
+if (! reload_completed)
+  FAIL;
+  }
   [(set_attr "isa" "*,*,adiw,*")])
 
 ;; "*addhi3"


[gcc r14-10600] AVR: ad target/116407 - Fix linker error "relocation truncated to fit".

2024-08-18 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:c7257486630c419f0d140d558eaa20d183439811

commit r14-10600-gc7257486630c419f0d140d558eaa20d183439811
Author: Georg-Johann Lay 
Date:   Sun Aug 18 17:07:15 2024 +0200

AVR: ad target/116407 - Fix linker error "relocation truncated to fit".

PR target/116407
gcc/
* config/avr/avr.md (*dec-and-branchhi!=-1.l.clobber):
Increase the additional jump offset to 2 words.

(cherry picked from commit 22acd3c4d18dbd4d4d39d7770145fe3ec36073f6)

Diff:
---
 gcc/config/avr/avr.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 9aaefcfcd64..b7273fa19f6 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -7884,7 +7884,7 @@
  "sub %A0,%3" CR_TAB
  "sbc %B0,__zero_reg__", operands);
 
-int jump_mode = avr_jump_mode (operands[2], insn, 1 - avr_adiw_reg_p 
(operands[0]));
+int jump_mode = avr_jump_mode (operands[2], insn, 2);
 const char *op = ((EQ == ) ^ (jump_mode == 1)) ? "brcc" : "brcs";
 operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);


[gcc r15-3144] testsuite: Add dg-require-effective-target scheduling for some tests that set -fschedule-insns.

2024-08-24 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:ac826d2f5b1fcd6c9356d5c77a1a0ef927ae2701

commit r15-3144-gac826d2f5b1fcd6c9356d5c77a1a0ef927ae2701
Author: Georg-Johann Lay 
Date:   Sat Aug 24 10:23:39 2024 +0200

testsuite: Add dg-require-effective-target scheduling for some tests that 
set -fschedule-insns.

gcc/testsuite/
* gcc.dg/torture/pr115929-2.c: Add dg-require-effective-target 
scheduling.
* gcc.dg/torture/pr116343.c: Same.

Diff:
---
 gcc/testsuite/gcc.dg/torture/pr115929-2.c | 1 +
 gcc/testsuite/gcc.dg/torture/pr116343.c   | 1 +
 2 files changed, 2 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/torture/pr115929-2.c 
b/gcc/testsuite/gcc.dg/torture/pr115929-2.c
index c8473a74da6c..02496d54d798 100644
--- a/gcc/testsuite/gcc.dg/torture/pr115929-2.c
+++ b/gcc/testsuite/gcc.dg/torture/pr115929-2.c
@@ -1,4 +1,5 @@
 /* { dg-additional-options "-fschedule-insns" } */
+/* { dg-require-effective-target scheduling } */
 
 int a, b, c, d, e, f;
 int main() {
diff --git a/gcc/testsuite/gcc.dg/torture/pr116343.c 
b/gcc/testsuite/gcc.dg/torture/pr116343.c
index ad13f0fc21c1..287a09707ec4 100644
--- a/gcc/testsuite/gcc.dg/torture/pr116343.c
+++ b/gcc/testsuite/gcc.dg/torture/pr116343.c
@@ -1,4 +1,5 @@
 // { dg-additional-options "-fschedule-insns -fno-thread-jumps -fno-dce" }
+/* { dg-require-effective-target scheduling } */
 
 int a, b, c;
 volatile int d;


[gcc r15-3264] AVR: Overhaul the avr-ifelse RTL optimization pass.

2024-08-28 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:898f013e195fa828bb30ae6ba4ad50abbd804fbd

commit r15-3264-g898f013e195fa828bb30ae6ba4ad50abbd804fbd
Author: Georg-Johann Lay 
Date:   Fri Aug 23 11:34:43 2024 +0200

AVR: Overhaul the avr-ifelse RTL optimization pass.

Mini-pass avr-ifelse realizes optimizations that replace two cbranch
insns with one comparison and two branches.  This patch adds the
following improvements:

- The right operand of the comparisons may also be REGs.
  Formerly only CONST_INT was handled.

- The RTX code of the first comparison in no more restricted
  to (effectively) EQ.

- When the second cbranch is located in the fallthrough path
  of the first cbranch, then difficult (expensive) comparisons
  can always be avoided.  This may require to swap the branch
  targets.  (When the second cbranch is located after the target
  label of the first one, then getting rid of difficult branches
  would require to reorder blocks.)

- The code has been cleaned up:  avr_rest_of_handle_ifelse() now
  just scans the insn stream for optimization candidates.  The code
  that actually performs the transformation has been outsourced to
  the new function avr_optimize_2ifelse().

- The code to find a better representation for reg-const_int comparisons
  has been split into two parts:  First try to find codes such that the
  right-hand sides of the comparisons are the same (avr_2comparisons_rhs).
  When this succeeds then one comparison can serve two branches, and
  that function tries to get rid of difficult branches.  This is always
  possible when the second cbranch is located in the fallthrough path
  of the first one.

Some final notes on why we don't use compare-elim:  1) The two cbranch
insns may come with different scratch operands depending on the chosen
constraint alternatives.  There are cases where the outgoing comparison
requires a scratch but only one incoming cbranch has one.  2) Avoiding
difficult branches can be achieved by rewiring basic blocks.
compare-elim doesn't do that; it doesn't even know the costs of the
branch codes.  3)  avr_2comparisons_rhs() may de-canonicalize a
comparison to achieve its goal.  compare-elim doesn't know how to do
that.  4) There are more reasons, see for example the commit message
and discussion for PR115830.

avr_2comparisons_rhs tries to decompose the interval as given by some
[u]intN_t into three intervals using the new Ranges struct that
implemens set operations on finite unions of intervals.
Sadly, value-range.h is not well suited for that, and writing a
wrapper around it that avoids all corner case ICEs would be more
laborious than struct Ranges.

gcc/
* config/avr/avr.cc (INCLUDE_VECTOR): Define it.
(cfganal.h): Include it.
(Ranges): New struct.
(avr_2comparisons_rhs, avr_redundant_compare_regs)
(avr_strict_signed_p, avr_strict_unsigned_p): New static functions.
(avr_redundant_compare): Overhaul: Allow more cases.
(avr_optimize_2ifelse): New static function, outsourced from...
(avr_rest_of_handle_ifelse): ...this method.
gcc/testsuite/
* gcc.target/avr/torture/ifelse-c.h: New file.
* gcc.target/avr/torture/ifelse-d.h: New file.
* gcc.target/avr/torture/ifelse-q.h: New file.
* gcc.target/avr/torture/ifelse-r.h: New file.
* gcc.target/avr/torture/ifelse-c-i8.c: New test.
* gcc.target/avr/torture/ifelse-d-i8.c: New test.
* gcc.target/avr/torture/ifelse-q-i8.c: New test.
* gcc.target/avr/torture/ifelse-r-i8.c: New test.
* gcc.target/avr/torture/ifelse-c-i16.c: New test.
* gcc.target/avr/torture/ifelse-d-i16.c: New test.
* gcc.target/avr/torture/ifelse-q-i16.c: New test.
* gcc.target/avr/torture/ifelse-r-i16.c: New test.
* gcc.target/avr/torture/ifelse-c-u16.c: New test.
* gcc.target/avr/torture/ifelse-d-u16.c: New test.
* gcc.target/avr/torture/ifelse-q-u16.c: New test.
* gcc.target/avr/torture/ifelse-r-u16.c: New test.

Diff:
---
 gcc/config/avr/avr.cc  | 987 -
 .../gcc.target/avr/torture/ifelse-c-i16.c  |  12 +
 gcc/testsuite/gcc.target/avr/torture/ifelse-c-i8.c |  12 +
 .../gcc.target/avr/torture/ifelse-c-u16.c  |  12 +
 gcc/testsuite/gcc.target/avr/torture/ifelse-c.h|  99 +++
 .../gcc.target/avr/torture/ifelse-d-i16.c  |  12 +
 gcc/testsuite/gcc.target/avr/torture/ifelse-d-i8.c |  12 +
 .../gcc.target/avr/torture/ifelse-d-u16.c  |  12 +
 gcc/testsuite/gcc.target/avr/torture/ifelse-d.h|  82 ++
 .../gcc.target/avr/torture/ifelse-q-i16.c  |  12 +
 gcc/testsuite/gcc.target/avr/torture/ifelse-q-i8

[gcc r15-3286] AVR: target/115830 - Make better use of SREG.N and SREG.Z.

2024-08-29 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:07e5e054a1c579dec3e1ed2192992b2fea14ad40

commit r15-3286-g07e5e054a1c579dec3e1ed2192992b2fea14ad40
Author: Georg-Johann Lay 
Date:   Sun Aug 4 19:46:43 2024 +0200

AVR: target/115830 - Make better use of SREG.N and SREG.Z.

This patch adds new CC modes CCN and CCZN for operations that
set SREG.N, resp. SREG.Z and SREG.N.  Add peephole2 patterns
to generate new compute + branch insns that make use
of the Z and N flags.  Most of these patterns need their own
asm output routines that don't do all the micro-optimizations
that the ordinary outputs may perform, as the latter have no
requirement to set CC in a usable way.

We don't use cmpelim because it cannot provide scratch regs
(which peephole2 can), and some of the patterns require a
scratch reg, whereas the same operations that don't set REG_CC
don't require a scratch.  See the comments in avr.md for details.

The existing add.for.cc* patterns are simplified as they no
more cover QImode, which is handled in a separate QImode case.
Apart from that, it adds 3 patterns for subtractions and one
pattern for shift left, all for multi-byte cases (HI, PSI, SI).

The add.for.cc* patterns now use CC[Z]Nmode, instead of the
formerly abuse of CCmode.

PR target/115830
gcc/
* config/avr/avr-modes.def (CCN, CCZN): New CC_MODEs.
* config/avr/avr-protos.h (avr_cond_branch): New from
ret_cond_branch.
(avr_out_plus_set_N, avr_op8_ZN_operator, avr_cmp0_code)
(avr_out_op8_set_ZN, avr_len_op8_set_ZN): New protos.
(ccn_reg_rtx, cczn_reg_rtx): New declarations.
* config/avr/avr.cc (avr_cond_branch): New from ret_cond_branch.
(avr_cond_string): Add bool cc_overflow_unusable argument.
(avr_print_operand) ['L']: Like 'j' but overflow unusable.
['K']: Like 'k' but overflow unusable.
(avr_out_plus_set_ZN): Remove handling of QImode.
(avr_out_plus_set_N, avr_op8_ZN_operator, avr_cmp0_code)
(avr_out_op8_set_ZN, avr_len_op8_set_ZN): New functions.
(avr_adjust_insn_length) [ADJUST_LEN_ADD_SET_N]: Hande case.
(avr_class_max_nregs): All MODE_CCs occupy one hard reg.
(avr_hard_regno_nregs): Same.
(avr_hard_regno_mode_ok) [REG_CC]: Allow all MODE_CC.
(pass_manager.h, context.h, tree-pass.h): Include them.
(ccn_reg_rtx, cczn_reg_rtx): New GTY variables.
(avr_init_expanders): Initialize them.
(avr_option_override): Run peephole2 a second time.
* config/avr/avr.md (adjust_len) [add_set_N]: New attr value.
(ALLCC, HI_SI): New mode iterators.
(CCname): New mode attribute.
(eqnegtle, cmp_signed, op8_ZN): New code iterators.
(swap, SWAP): New code attributes.
(branch): Handle CCNmode and CCZNmode.  Assimilate...
(difficult_branch): ...this insn.
(p1m1): Remove.
(gen_add_for__): Adjust to CCNmode and CCZNmode. Use
HISI as mode iterator.  Extend peephole2s that produce them.
(*add.for.eqne.): Extend to *add.for.cc[z]n..
(*ashift.for.ccn.): New insn and peephole2 to make them.
(*sub.for.cczn., *sub-extend.for.cczn.):
New insns and peephole2s to make them.
(*op8.for.cczn.): New insn and peephole2 to make them.
* config/avr/predicates.md (const_1_to_3_operand)
(abs1_abs2_operand, signed_comparison_operator)
(op8_ZN_operator): New predicates.
gcc/testsuite/
* gcc.target/avr/pr115830-add.c: New test.
* gcc.target/avr/pr115830-add-c.c: New test.
* gcc.target/avr/pr115830-add-i.c: New test.
* gcc.target/avr/pr115830-and.c: New test.
* gcc.target/avr/pr115830-asl.c: New test.
* gcc.target/avr/pr115830-asr.c: New test.
* gcc.target/avr/pr115830-ior.c: New test.
* gcc.target/avr/pr115830-lsr.c: New test.
* gcc.target/avr/pr115830-asl32.c: New test.
* gcc.target/avr/pr115830-sub.c: New test.
* gcc.target/avr/pr115830-sub-ext.c: New test.

Diff:
---
 gcc/config/avr/avr-modes.def|   6 +
 gcc/config/avr/avr-protos.h |   8 +-
 gcc/config/avr/avr.cc   | 354 ++---
 gcc/config/avr/avr.md   | 671 +---
 gcc/config/avr/predicates.md|  31 ++
 gcc/testsuite/gcc.target/avr/pr115830-add-c.c   |  79 +++
 gcc/testsuite/gcc.target/avr/pr115830-add-i.c   | 103 
 gcc/testsuite/gcc.target/avr/pr115830-add.c |  76 +++
 gcc/testsuite/gcc.target/avr/pr115830-and.c |  67 +++
 gcc/testsuite/gcc.target/avr/pr115830-asl.c |  78 +++
 gcc/testsuite/gcc.target/avr/pr11583

[gcc r15-3329] AVR: Don't print a space after , when printing instructions.

2024-08-31 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:dc476e5f68ecc5acaf93677ce57b74bd01ce2d13

commit r15-3329-gdc476e5f68ecc5acaf93677ce57b74bd01ce2d13
Author: Georg-Johann Lay 
Date:   Sat Aug 31 10:58:12 2024 +0200

AVR: Don't print a space after , when printing instructions.

gcc/
* config/avr/avr.cc: Follow the convention to not add a space
after comma when printing instructions.

Diff:
---
 gcc/config/avr/avr.cc | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 614b361921a2..079db62695dc 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -4184,7 +4184,7 @@ avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx 
op[], int *l)
   /* "ld r26,-X" is undefined */
   if (reg_unused_after (insn, base))
{
- return *l = 7, ("mov __tmp_reg__, %B1"  CR_TAB
+ return *l = 7, ("mov __tmp_reg__,%B1"   CR_TAB
  "st %0,%A1" CR_TAB
  TINY_ADIW (%E0, %F0, 1) CR_TAB
  "st %0+,__tmp_reg__"CR_TAB
@@ -4193,7 +4193,7 @@ avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx 
op[], int *l)
}
   else
{
- return *l = 9, ("mov __tmp_reg__, %B1"  CR_TAB
+ return *l = 9, ("mov __tmp_reg__,%B1"   CR_TAB
  "st %0,%A1" CR_TAB
  TINY_ADIW (%E0, %F0, 1) CR_TAB
  "st %0+,__tmp_reg__"CR_TAB
@@ -4291,7 +4291,7 @@ out_movsi_mr_r (rtx_insn *insn, rtx op[], int *l)
 {
   if (io_address_operand (base, SImode))
{
- return *l=4,("out %i0, %A1"  CR_TAB
+ return *l=4,("out %i0,%A1"   CR_TAB
   "out %i0+1,%B1" CR_TAB
   "out %i0+2,%C1" CR_TAB
   "out %i0+3,%D1");
@@ -8230,7 +8230,7 @@ avr_out_plus_set_ZN (rtx *xop, int *plen)
   && IN_RANGE (INTVAL (xval), 1, 63))
 {
   // Add 16-bit value in [1..63] to a w register.
-  return avr_asm_len ("adiw %0, %1", xop, plen, 1);
+  return avr_asm_len ("adiw %0,%1", xop, plen, 1);
 }
 
   // Addition won't work; subtract the negative of XVAL instead.
@@ -8259,7 +8259,7 @@ avr_out_plus_set_ZN (rtx *xop, int *plen)
  if (IN_RANGE (INTVAL (op[1]), 0, 63))
{
  // SBIW can handle the lower 16 bits.
- avr_asm_len ("sbiw %0, %1", op, plen, 1);
+ avr_asm_len ("sbiw %0,%1", op, plen, 1);
 
  // Next byte has already been handled: Skip it.
  ++i;
@@ -8273,8 +8273,8 @@ avr_out_plus_set_ZN (rtx *xop, int *plen)
{
  // d-regs can subtract immediates.
  avr_asm_len (i == 0
-  ? "subi %0, %1"
-  : "sbci %0, %1", op, plen, 1);
+  ? "subi %0,%1"
+  : "sbci %0,%1", op, plen, 1);
}
   else
{
@@ -8283,8 +8283,8 @@ avr_out_plus_set_ZN (rtx *xop, int *plen)
{
  // Any register can subtract 0.
  avr_asm_len (i == 0
-  ? "sub %0, __zero_reg__"
-  : "sbc %0, __zero_reg__", op, plen, 1);
+  ? "sub %0,__zero_reg__"
+  : "sbc %0,__zero_reg__", op, plen, 1);
}
  else
{
@@ -8294,13 +8294,13 @@ avr_out_plus_set_ZN (rtx *xop, int *plen)
{
  // Load partial xval to QI clobber reg and memoize for later.
  gcc_assert (REG_P (op[2]));
- avr_asm_len ("ldi %2, %1", op, plen, 1);
+ avr_asm_len ("ldi %2,%1", op, plen, 1);
  clobber_val = val8;
}
 
  avr_asm_len (i == 0
-  ? "sub %0, %2"
-  : "sbc %0, %2", op, plen, 1);
+  ? "sub %0,%2"
+  : "sbc %0,%2", op, plen, 1);
}
}
 } // Loop bytes.


[gcc r15-3340] AVR: Run pass avr-fuse-add a second time after pass_cprop_hardreg.

2024-08-31 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:df89afbb7732bdf9f003af0020a46b6deb3c4eeb

commit r15-3340-gdf89afbb7732bdf9f003af0020a46b6deb3c4eeb
Author: Georg-Johann Lay 
Date:   Fri Aug 30 19:38:30 2024 +0200

AVR: Run pass avr-fuse-add a second time after pass_cprop_hardreg.

gcc/
* config/avr/avr-passes.cc (avr_pass_fuse_add) : Override.
* config/avr/avr-passes.def (avr_pass_fuse_add): Run again
after pass_cprop_hardreg.

Diff:
---
 gcc/config/avr/avr-passes.cc  |  7 +++
 gcc/config/avr/avr-passes.def | 21 +
 2 files changed, 28 insertions(+)

diff --git a/gcc/config/avr/avr-passes.cc b/gcc/config/avr/avr-passes.cc
index 58b132b64bec..8a71b57ada10 100644
--- a/gcc/config/avr/avr-passes.cc
+++ b/gcc/config/avr/avr-passes.cc
@@ -1026,6 +1026,13 @@ public:
 this->name = name;
   }
 
+  // Cloning is required because we are running one instance of the pass
+  // before peephole2. and a second one after cprop_hardreg.
+  opt_pass * clone () final override
+  {
+return make_avr_pass_fuse_add (m_ctxt);
+  }
+
   bool gate (function *) final override
   {
 return optimize && avr_fuse_add > 0;
diff --git a/gcc/config/avr/avr-passes.def b/gcc/config/avr/avr-passes.def
index 3be82e027101..cd89d6737276 100644
--- a/gcc/config/avr/avr-passes.def
+++ b/gcc/config/avr/avr-passes.def
@@ -26,6 +26,27 @@
 
 INSERT_PASS_BEFORE (pass_peephole2, 1, avr_pass_fuse_add);
 
+/* There are cases where avr-fuse-add doesn't find POST_INC cases because
+   the RTL code at that time is too long-winded, and moves registers back and
+   forth (which seems to be the same reason for why pass auto_inc_dec cannot
+   find POST_INC, either).  Some of that long-windedness is cleaned up very
+   late in pass cprop_hardreg, which opens up new opportunities to find post
+   increments.  An example is the following function from AVR-LibC's qsort:
+
+   void swapfunc (char *a, char *b, int n)
+   {
+   do
+   {
+   char tmp = *a;
+   *a++ = *b;
+   *b++ = tmp;
+   } while (--n > 0);
+   }
+
+   Hence, run avr-fuse-add twice; the second time after cprop_hardreg.  */
+
+INSERT_PASS_AFTER (pass_cprop_hardreg, 1, avr_pass_fuse_add);
+
 /* An analysis pass that runs prior to prologue / epilogue generation.
Computes cfun->machine->gasisr.maybe which is used in prologue and
epilogue generation provided -mgas-isr-prologues is on.  */


[gcc r15-3339] AVR: Tidy pass avr-fuse-add.

2024-08-31 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:60fc5501ddc77d496f1584532c29d209eea13734

commit r15-3339-g60fc5501ddc77d496f1584532c29d209eea13734
Author: Georg-Johann Lay 
Date:   Fri Aug 30 19:38:30 2024 +0200

AVR: Tidy pass avr-fuse-add.

gcc/
* config/avr/avr-protos.h (avr_split_tiny_move): Rename to
avr_split_fake_addressing_move.
* config/avr/avr-passes.def: Same.
* config/avr/avr-passes.cc: Same.
(avr_pass_data_fuse_add) : Set to TV_MACH_DEP.
* config/avr/avr.md (split-lpmx): Remove a define_split.  Such
splits are performed by avr_split_fake_addressing_move.

Diff:
---
 gcc/config/avr/avr-passes.cc  |  8 
 gcc/config/avr/avr-passes.def | 10 +-
 gcc/config/avr/avr-protos.h   |  2 +-
 gcc/config/avr/avr.md | 35 ++-
 4 files changed, 12 insertions(+), 43 deletions(-)

diff --git a/gcc/config/avr/avr-passes.cc b/gcc/config/avr/avr-passes.cc
index 8b018ff6a056..58b132b64bec 100644
--- a/gcc/config/avr/avr-passes.cc
+++ b/gcc/config/avr/avr-passes.cc
@@ -1009,7 +1009,7 @@ static const pass_data avr_pass_data_fuse_add =
   RTL_PASS,// type
   "",  // name (will be patched)
   OPTGROUP_NONE,// optinfo_flags
-  TV_DF_SCAN,  // tv_id
+  TV_MACH_DEP, // tv_id
   0,   // properties_required
   0,   // properties_provided
   0,   // properties_destroyed
@@ -1503,8 +1503,8 @@ avr_pass_fuse_add::fuse_mem_add (Mem_Insn &mem, Add_Insn 
&add)
- PLUS insn of that kind.
- Indirect loads and stores.
In almost all cases, combine opportunities arise from the preparation
-   done by `avr_split_tiny_move', but in some rare cases combinations are
-   found for the ordinary cores, too.
+   done by `avr_split_fake_addressing_move', but in some rare cases 
combinations
+   are found for the ordinary cores, too.
   As we consider at most one Mem insn per try, there may still be missed
optimizations like  POST_INC + PLUS + POST_INC  might be performed
as  PRE_DEC + PRE_DEC  for two adjacent locations.  */
@@ -1714,7 +1714,7 @@ public:
core's capabilities.  This sets the stage for pass .avr-fuse-add.  */
 
 bool
-avr_split_tiny_move (rtx_insn * /*insn*/, rtx *xop)
+avr_split_fake_addressing_move (rtx_insn * /*insn*/, rtx *xop)
 {
   bool store_p = false;
   rtx mem, reg_or_0;
diff --git a/gcc/config/avr/avr-passes.def b/gcc/config/avr/avr-passes.def
index 748260edaef6..3be82e027101 100644
--- a/gcc/config/avr/avr-passes.def
+++ b/gcc/config/avr/avr-passes.def
@@ -20,9 +20,9 @@
 /* A post reload optimization pass that fuses PLUS insns with CONST_INT
addend with a load or store insn to get POST_INC or PRE_DEC addressing.
It can also fuse two PLUSes to a single one, which may occur due to
-   splits from `avr_split_tiny_move'.  We do this in an own pass because
-   it can find more cases than peephole2, for example when there are
-   unrelated insns between the interesting ones.  */
+   splits from `avr_split_fake_addressing_move'.  We do this in an own
+   pass because it can find more cases than peephole2, for example when
+   there are unrelated insns between the interesting ones.  */
 
 INSERT_PASS_BEFORE (pass_peephole2, 1, avr_pass_fuse_add);
 
@@ -47,9 +47,9 @@ INSERT_PASS_BEFORE (pass_free_cfg, 1, 
avr_pass_recompute_notes);
tries to fix such situations by operating on the original mode.  This
reduces code size and register pressure.
 
-   The assertion is that the code generated by casesi is unaltered and a
+   The assertion is that the code generated by casesi is unaltered and
a sign-extend or zero-extend from QImode or HImode precedes the casesi
-   insns withaout any insns in between.  */
+   insns without any insns in between.  */
 
 INSERT_PASS_AFTER (pass_expand, 1, avr_pass_casesi);
 
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 289c80cab550..d6f4abbac669 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -179,7 +179,7 @@ extern rtl_opt_pass *make_avr_pass_casesi (gcc::context *);
 extern rtl_opt_pass *make_avr_pass_ifelse (gcc::context *);
 #ifdef RTX_CODE
 extern bool avr_casei_sequence_check_operands (rtx *xop);
-extern bool avr_split_tiny_move (rtx_insn *insn, rtx *operands);
+extern bool avr_split_fake_addressing_move (rtx_insn *insn, rtx *operands);
 #endif /* RTX_CODE */
 
 /* From avr-log.cc */
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index f477ac170ea2..520f1fe41a21 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -993,41 +993,10 @@
   (clobber (reg:CC REG_CC))])])
 
 
-;; For LPM loads from AS1 we split
-;;R = *Z
-;; to
-;;R = *Z++
-;;Z = Z - sizeof (R)
-;;
-;; so that the second instruction can be optimized out.
-
-(define_split ; "split-lpmx"
-  [(set (match_operand:HISI 0 "register_operand" "")
-(match_operand:HISI 1 "memory_operand" ""))]
-

[gcc r15-3512] AVR: lra/116321 - Add test case.

2024-09-06 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:e8378231bb88582274e641e57766da613fe067bd

commit r15-3512-ge8378231bb88582274e641e57766da613fe067bd
Author: Georg-Johann Lay 
Date:   Fri Sep 6 13:47:12 2024 +0200

AVR: lra/116321 - Add test case.

PR rtl-optimization/116321
gcc/testsuite/
* gcc.target/avr/torture/lra-pr116321.c: New test.

Diff:
---
 gcc/testsuite/gcc.target/avr/torture/lra-pr116321.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/gcc/testsuite/gcc.target/avr/torture/lra-pr116321.c 
b/gcc/testsuite/gcc.target/avr/torture/lra-pr116321.c
new file mode 100644
index 000..559db8d450a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/lra-pr116321.c
@@ -0,0 +1,20 @@
+/* { dg-additional-options -std=gnu99 } */
+
+#include 
+
+typedef __UINT64_TYPE__ T;
+
+#ifdef __FLASH
+T fun64_flash (const __flash T *p)
+{
+  return *p;
+}
+#endif
+
+#ifdef __MEMX
+T fun64_memx (const __memx T *p)
+{
+  return *p;
+}
+#endif
+


[gcc r15-3621] AVR: avr.cc - Reorder functions to require less forward decls.

2024-09-13 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:be59aaf13cea06a6dd01736d2c31d1c3bc2a60ee

commit r15-3621-gbe59aaf13cea06a6dd01736d2c31d1c3bc2a60ee
Author: Georg-Johann Lay 
Date:   Tue Sep 10 18:28:36 2024 +0200

AVR: avr.cc - Reorder functions to require less forward decls.

gcc/
* config/avr/avr.cc (avr_init_machine_status): Move code to...
(avr_option_override) : ...lambda.
(avr_insn_has_reg_unused_note_p): Move up.
(_reg_unused_after, reg_unused_after): Move up.
(output_reload_in_const): Move up.
(avr_c_mode_for_floating_type): Move down.

Diff:
---
 gcc/config/avr/avr.cc | 891 +-
 1 file changed, 439 insertions(+), 452 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 1f809d8e1e3b..f743261c6adf 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -153,16 +153,6 @@ static const char *out_movqi_mr_r (rtx_insn *, rtx[], int 
*);
 static const char *out_movhi_mr_r (rtx_insn *, rtx[], int *);
 static const char *out_movsi_mr_r (rtx_insn *, rtx[], int *);
 
-static int get_sequence_length (rtx_insn *insns);
-static int sequent_regs_live (void);
-static const char *ptrreg_to_str (int);
-static int avr_num_arg_regs (machine_mode, const_tree);
-static int avr_operand_rtx_cost (rtx, machine_mode, enum rtx_code,
-int, bool);
-static void output_reload_in_const (rtx *, rtx, int *, bool);
-static struct machine_function *avr_init_machine_status (void);
-static bool _reg_unused_after (rtx_insn *insn, rtx reg, bool look_at_insn);
-
 
 /* Prototypes for hook implementors if needed before their implementation.  */
 
@@ -456,7 +446,10 @@ avr_option_override (void)
   avr_addr.sp_l = 0x3D + avr_arch->sfr_offset;
   avr_addr.sp_h = avr_addr.sp_l + 1;
 
-  init_machine_status = avr_init_machine_status;
+  init_machine_status = []()
+  {
+return ggc_cleared_alloc ();
+  };
 
   avr_log_set_avr_log();
 
@@ -473,14 +466,6 @@ avr_option_override (void)
   }
 }
 
-/* Function to set up the backend function structure.  */
-
-static struct machine_function *
-avr_init_machine_status (void)
-{
-  return ggc_cleared_alloc ();
-}
-
 
 /* Implement `INIT_EXPANDERS'.  */
 /* The function works like a singleton.  */
@@ -1179,7 +1164,7 @@ sequent_regs_live (void)
 
 /* Obtain the length sequence of insns.  */
 
-int
+static int
 get_sequence_length (rtx_insn *insns)
 {
   int length = 0;
@@ -2933,6 +2918,7 @@ avr_init_cumulative_args (CUMULATIVE_ARGS *cum, tree 
fntype, rtx libname,
   cfun->machine->sibcall_fails = 0;
 }
 
+
 /* Returns the number of registers to allocate for a function argument.  */
 
 static int
@@ -3099,6 +3085,152 @@ avr_xload_libgcc_p (machine_mode mode)
 }
 
 
+/* Return true when INSN has a REG_UNUSED note for hard reg REG.
+   rtlanal.cc::find_reg_note() uses == to compare XEXP (link, 0)
+   therefore use a custom function.  */
+
+static bool
+avr_insn_has_reg_unused_note_p (rtx_insn *insn, rtx reg)
+{
+  for (rtx link = REG_NOTES (insn); link; link = XEXP (link, 1))
+if (REG_NOTE_KIND (link) == REG_UNUSED
+   && REG_P (XEXP (link, 0))
+   && REGNO (reg) >= REGNO (XEXP (link, 0))
+   && END_REGNO (reg) <= END_REGNO (XEXP (link, 0)))
+  return true;
+
+  return false;
+}
+
+
+/* A helper for the next function.
+   Return nonzero if REG is not used after INSN.
+   We assume REG is a reload reg, and therefore does
+   not live past labels.  It may live past calls or jumps though.  */
+
+static bool
+_reg_unused_after (rtx_insn *insn, rtx reg, bool look_at_insn)
+{
+  if (look_at_insn)
+{
+  /* If the reg is set by this instruction, then it is safe for our
+case.  Disregard the case where this is a store to memory, since
+we are checking a register used in the store address.  */
+  rtx set = single_set (insn);
+  if (set && !MEM_P (SET_DEST (set))
+ && reg_overlap_mentioned_p (reg, SET_DEST (set)))
+   return 1;
+
+  /* This case occurs when fuse-add introduced a POST_INC addressing,
+but the address register is unused after.  */
+  if (set)
+   {
+ rtx mem = MEM_P (SET_SRC (set)) ? SET_SRC (set) : SET_DEST (set);
+ if (MEM_P (mem)
+ && reg_overlap_mentioned_p (reg, XEXP (mem, 0))
+ && avr_insn_has_reg_unused_note_p (insn, reg))
+   return 1;
+   }
+}
+
+  while ((insn = NEXT_INSN (insn)))
+{
+  rtx set;
+  enum rtx_code code = GET_CODE (insn);
+
+#if 0
+  /* If this is a label that existed before reload, then the register
+if dead here.  However, if this is a label added by reorg, then
+the register may still be live here.  We can't tell the difference,
+so we just ignore labels completely.  */
+  if (code == CODE_LABEL)
+   return 1;
+  /* else */
+#endif
+
+  if (!INSN_P (insn))
+   continue;
+
+  if (code == JUMP_INSN)
+   r

[gcc r15-3622] AVR: Tweak 32-bit EQ and NE comparisons.

2024-09-13 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:1ec16778312a902592822cbda626241da68ea643

commit r15-3622-g1ec16778312a902592822cbda626241da68ea643
Author: Georg-Johann Lay 
Date:   Tue Sep 10 17:51:58 2024 +0200

AVR: Tweak 32-bit EQ and NE comparisons.

The order in which multi-byte EQ and NE comparisons are performing
the byte comparisons does not matter, and there are situations where
using SBIW on the high word can save an instruction.

gcc/
* config/avr/avr.cc (avr_out_compare): Tweak 32-bit EQ and NE
comparisons that can use SBIW for the hi16 part.

Diff:
---
 gcc/config/avr/avr.cc | 25 +
 1 file changed, 25 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index f743261c6adf..25220c3bc0c7 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -5990,6 +5990,31 @@ avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
}
 }
 
+  /* Comparisons == and != may change the order in which the sub-bytes are
+ being compared.  Start with the high 16 bits so we can use SBIW.  */
+
+  if (n_bytes == 4
+  && compare_eq_p (insn)
+  && AVR_HAVE_ADIW
+  && REGNO (xreg) >= REG_22)
+{
+  if (xval == const0_rtx)
+   return avr_asm_len ("sbiw %C0,0"   CR_TAB
+   "cpc %B0,__zero_reg__" CR_TAB
+   "cpc %A0,__zero_reg__", xop, plen, 3);
+
+  rtx xhi16 = simplify_gen_subreg (HImode, xval, mode, 2);
+  if (IN_RANGE (UINTVAL (xhi16) & GET_MODE_MASK (HImode), 0, 63)
+ && reg_unused_after (insn, xreg))
+   {
+ xop[1] = xhi16;
+ avr_asm_len ("sbiw %C0,%1", xop, plen, 1);
+ xop[1] = xval;
+ return avr_asm_len ("sbci %B0,hi8(%1)" CR_TAB
+ "sbci %A0,lo8(%1)", xop, plen, 2);
+   }
+}
+
   for (int i = 0; i < n_bytes; i++)
 {
   /* We compare byte-wise.  */


[gcc r15-3623] AVR: Rework avr_out_compare.

2024-09-13 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:494d3c3faaee0dbde696ea334f8e242ae85ae2b5

commit r15-3623-g494d3c3faaee0dbde696ea334f8e242ae85ae2b5
Author: Georg-Johann Lay 
Date:   Thu Sep 12 14:24:53 2024 +0200

AVR: Rework avr_out_compare.

16-bit comparisons like R25:24 == -1 are currently performed like
cpi R24, -1
cpc R25, R24
Similar is possible for wider modes.  ADIW can be used like SBIW when
the compare code is EQ or NE because such comparisons are just about
(propagating) the Z flag.  The patch adds helper functions like avr_byte()
that may be useful in other functions than avr_out_compare().
Use new convenient helper functions that may be useful in
other output functions, too.

For example, with the patch

R24:SI == -1 (unused after)
adiw r26,1
sbci r25,hi8(-1)
sbci r24,lo8(-1)

R18:SI == -1
cpi r18,-1
cpc r19,r18
cpc r20,r18
cpc r21,r18

Without the patch, we had:

R24:SI == -1 (unused after)
cpi r24,-1
sbci r25,-1
sbci r26,-1
sbci r27,-1

R18:SI == -1
cpi r18,-1
ldi r24,-1
cpc r19,r24
cpc r20,r24
cpc r21,r24

gcc/
* config/avr/avr.cc (avr_chunk, avr_byte, avr_word)
(avr_int8, avr_uint8, avr_int16): New helper functions.
(avr_out_compare): Overhaul.

Diff:
---
 gcc/config/avr/avr.cc | 175 ++
 1 file changed, 118 insertions(+), 57 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 25220c3bc0c7..b26716551fcf 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -247,6 +247,68 @@ avr_tolower (char *lo, const char *up)
 }
 
 
+/* Return chunk of mode MODE of X as an rtx.  N specifies the subreg
+   byte at which the chunk starts.  N must be an integral multiple
+   of the mode size.  */
+
+static rtx
+avr_chunk (machine_mode mode, rtx x, int n)
+{
+  gcc_assert (n % GET_MODE_SIZE (mode) == 0);
+  machine_mode xmode = GET_MODE (x) == VOIDmode ? DImode : GET_MODE (x);
+  return simplify_gen_subreg (mode, x, xmode, n);
+}
+
+
+/* Return the N-th byte of X as an rtx.  */
+
+static rtx
+avr_byte (rtx x, int n)
+{
+  return avr_chunk (QImode, x, n);
+}
+
+
+/* Return the sub-word of X starting at byte number N.  */
+
+static rtx
+avr_word (rtx x, int n)
+{
+  return avr_chunk (HImode, x, n);
+}
+
+
+/* Return the N-th byte of compile-time constant X as an int8_t.  */
+
+static int8_t
+avr_int8 (rtx x, int n)
+{
+  gcc_assert (CONST_INT_P (x) || CONST_FIXED_P (x) || CONST_DOUBLE_P (x));
+
+  return (int8_t) trunc_int_for_mode (INTVAL (avr_byte (x, n)), QImode);
+}
+
+/* Return the N-th byte of compile-time constant X as an uint8_t.  */
+
+static uint8_t
+avr_uint8 (rtx x, int n)
+{
+  return (uint8_t) avr_int8 (x, n);
+}
+
+
+/* Return the sub-word of compile-time constant X that starts
+   at byte N as an int16_t.  */
+
+static int16_t
+avr_int16 (rtx x, int n)
+{
+  gcc_assert (CONST_INT_P (x) || CONST_FIXED_P (x) || CONST_DOUBLE_P (x));
+
+  return (int16_t) trunc_int_for_mode (INTVAL (avr_word (x, n)), HImode);
+}
+
+
 /* Constraint helper function.  XVAL is a CONST_INT or a CONST_DOUBLE.
Return true if the least significant N_BYTES bytes of XVAL all have a
popcount in POP_MASK and false, otherwise.  POP_MASK represents a subset
@@ -5917,9 +5979,6 @@ avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
   xval = avr_to_int_mode (xop[1]);
 }
 
-  /* MODE of the comparison.  */
-  machine_mode mode = GET_MODE (xreg);
-
   gcc_assert (REG_P (xreg));
   gcc_assert ((CONST_INT_P (xval) && n_bytes <= 4)
  || (const_double_operand (xval, VOIDmode) && n_bytes == 8));
@@ -5927,13 +5986,15 @@ avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
   if (plen)
 *plen = 0;
 
+  const bool eqne_p = compare_eq_p (insn);
+
   /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
  against 0 by ORing the bytes.  This is one instruction shorter.
  Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
  and therefore don't use this.  */
 
-  if (!test_hard_reg_class (LD_REGS, xreg)
-  && compare_eq_p (insn)
+  if (eqne_p
+  && ! test_hard_reg_class (LD_REGS, xreg)
   && reg_unused_after (insn, xreg))
 {
   if (xval == const1_rtx)
@@ -5962,39 +6023,11 @@ avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
}
 }
 
-  /* Comparisons == -1 and != -1 of a d-register that's used after the
- comparison.  (If it's unused after we use CPI / SBCI or ADIW sequence
- from below.)  Instead of  CPI Rlo,-1 / LDI Rx,-1 / CPC Rhi,Rx  we can
- use  CPI Rlo,-1 / CPC Rhi,Rlo  which is 1 instruction shorter:
- If CPI is true then Rlo contains -1 and we can use Rlo instead of Rx
- when CPC'ing the high part.  If CPI is false then CPC cannot render
- the result to true.  This also wor

[gcc r15-3632] AVR: Use avr_byte instead of simplify_gen_subreg (QImode, ...

2024-09-13 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:b55f5e344c9b2f3667ef176e090c168e0add41f1

commit r15-3632-gb55f5e344c9b2f3667ef176e090c168e0add41f1
Author: Georg-Johann Lay 
Date:   Fri Sep 13 12:50:31 2024 +0200

AVR: Use avr_byte instead of simplify_gen_subreg (QImode, ...

There are many places where asm output functions have to look at
the constituent bytes and words of the operands.  The function of
choice was simplify_gen_subreg (mode, ...) which can be replaced
by the more handy avr_byte (rtx, byte_num).

gcc/
* config/avr/avr.cc: Use functions like avr_byte,
avr_word, avr_[u]int8/16 if convenient.
(avr_uint16): New function.

Diff:
---
 gcc/config/avr/avr.cc | 109 ++
 1 file changed, 47 insertions(+), 62 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index b26716551fcf..48d1d0e76465 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -308,6 +308,15 @@ avr_int16 (rtx x, int n)
   return (int16_t) trunc_int_for_mode (INTVAL (avr_word (x, n)), HImode);
 }
 
+/* Return the sub-word of compile-time constant X that starts
+   at byte N as an uint16_t.  */
+
+static uint16_t
+avr_uint16 (rtx x, int n)
+{
+  return (uint16_t) avr_int16 (x, n);
+}
+
 
 /* Constraint helper function.  XVAL is a CONST_INT or a CONST_DOUBLE.
Return true if the least significant N_BYTES bytes of XVAL all have a
@@ -317,15 +326,9 @@ avr_int16 (rtx x, int n)
 bool
 avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
 {
-  machine_mode mode = GET_MODE (xval);
-
-  if (VOIDmode == mode)
-mode = SImode;
-
   for (int i = 0; i < n_bytes; i++)
 {
-  rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
-  unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
+  unsigned int val8 = avr_uint8 (xval, i);
 
   if ((pop_mask & (1 << popcount_hwi (val8))) == 0)
return false;
@@ -342,15 +345,9 @@ avr_popcount_each_byte (rtx xval, int n_bytes, int 
pop_mask)
 bool
 avr_xor_noclobber_dconst (rtx xval, int n_bytes)
 {
-  machine_mode mode = GET_MODE (xval);
-
-  if (VOIDmode == mode)
-mode = SImode;
-
   for (int i = 0; i < n_bytes; ++i)
 {
-  rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
-  unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
+  unsigned int val8 = avr_uint8 (xval, i);
 
   if (val8 != 0 && val8 != 0xff && val8 != 0x80)
return false;
@@ -3414,7 +3411,7 @@ avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
 
   for (int i = 0; i < n_bytes; ++i)
{
- rtx reg = simplify_gen_subreg (QImode, dest, GET_MODE (dest), i);
+ rtx reg = avr_byte (dest, i);
 
  if (i > 0)
avr_asm_len ("adiw %2,1", xop, plen, 1);
@@ -3676,9 +3673,9 @@ output_reload_in_const (rtx *op, rtx clobber_reg, int 
*len, bool clear_p)
  but has some subregs that are in LD_REGS.  Use the MSB (REG:QI 17).  */
 
   if (REGNO (dest) < REG_16
-  && REGNO (dest) + GET_MODE_SIZE (mode) > REG_16)
+  && END_REGNO (dest) > REG_16)
 {
-  clobber_reg = all_regs_rtx[REGNO (dest) + n_bytes - 1];
+  clobber_reg = all_regs_rtx[END_REGNO (dest) - 1];
 }
 
   /* We might need a clobber reg but don't have one.  Look at the value to
@@ -3708,7 +3705,7 @@ output_reload_in_const (rtx *op, rtx clobber_reg, int 
*len, bool clear_p)
 
   /* Crop the n-th destination byte.  */
 
-  xdest[n] = simplify_gen_subreg (QImode, dest, mode, n);
+  xdest[n] = avr_byte (dest, n);
   int ldreg_p = test_hard_reg_class (LD_REGS, xdest[n]);
 
   if (!CONST_INT_P (src)
@@ -3734,7 +3731,7 @@ output_reload_in_const (rtx *op, rtx clobber_reg, int 
*len, bool clear_p)
 
   /* Crop the n-th source byte.  */
 
-  xval = simplify_gen_subreg (QImode, src, mode, n);
+  xval = avr_byte (src, n);
   ival[n] = INTVAL (xval);
 
   /* Look if we can reuse the low word by means of MOVW.  */
@@ -3743,12 +3740,12 @@ output_reload_in_const (rtx *op, rtx clobber_reg, int 
*len, bool clear_p)
  && n_bytes >= 4
  && AVR_HAVE_MOVW)
{
- rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
- rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2);
+ int lo16 = avr_int16 (src, 0);
+ int hi16 = avr_int16 (src, 2);
 
- if (INTVAL (lo16) == INTVAL (hi16))
+ if (lo16 == hi16)
{
- if (INTVAL (lo16) != 0 || !clear_p)
+ if (lo16 != 0 || ! clear_p)
avr_asm_len ("movw %C0,%A0", &op[0], len, 1);
 
  break;
@@ -6275,7 +6272,7 @@ avr_out_cmp_ext (rtx xop[], enum rtx_code code, int *plen)
 {
   // Sign-extend the high-byte of zreg to tmp_reg.
   int zmsb = GET_MODE_SIZE (zmode) - 1;
-  rtx xzmsb = simplify_gen_subreg (QImode, zreg, zmode, zmsb);
+  rtx xzmsb = avr_byte (zreg, zmsb);
 
   avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
  

[gcc r15-3634] AVR: Detect more skip opportunities.

2024-09-13 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:4ffca9966a9c43cedafe56d3ef8033182290f25b

commit r15-3634-g4ffca9966a9c43cedafe56d3ef8033182290f25b
Author: Georg-Johann Lay 
Date:   Fri Sep 13 18:06:57 2024 +0200

AVR: Detect more skip opportunities.

The transparent call insns like "*parityhi2.libgcc" output a single
[R]CALL instruction that can be skipped by the skip instructions.
Such insns have attribute "type" of "xcall" and can therefore
be easily recognized.  Same applies when "adjust_len" is "call".

gcc/
* config/avr/avr.cc (avr_2word_insn_p): Return true for
transparent calls: When insn attribute "type" is "xcall"
or when "adjust_len" is "call".

Diff:
---
 gcc/config/avr/avr.cc | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 48d1d0e76465..4cb51ea68dc7 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -12972,7 +12972,7 @@ test_hard_reg_class (enum reg_class rclass, rtx x)
 }
 
 
-/* Helper for jump_over_one_insn_p:  Test if INSN is a 2-word instruction
+/* Helper for `jump_over_one_insn_p':  Test if INSN is a 2-word instruction
and thus is suitable to be skipped by CPSE, SBRC, etc.  */
 
 static bool
@@ -12986,7 +12986,10 @@ avr_2word_insn_p (rtx_insn *insn)
   switch (INSN_CODE (insn))
 {
 default:
-  return false;
+  return (recog_memoized (insn) >= 0
+ // Transparent calls may be skipped.
+ && (get_attr_type (insn) == TYPE_XCALL
+ || get_attr_adjust_len (insn) == ADJUST_LEN_CALL));
 
 case CODE_FOR_movqi_insn:
 case CODE_FOR_movuqq_insn:


[gcc r15-3641] AVR: Use rtx code copysign.

2024-09-14 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:a900349485cc4753084527bf0234f173967979b0

commit r15-3641-ga900349485cc4753084527bf0234f173967979b0
Author: Georg-Johann Lay 
Date:   Sat Sep 14 10:12:54 2024 +0200

AVR: Use rtx code copysign.

gcc/
* config/avr/avr.md (UNSPEC_COPYSIGN): Remove define_enum.
(copysignsf3): Use copysign instead of UNSPEC_COPYSIGN.
Allow const_double for operand 2.

Diff:
---
 gcc/config/avr/avr.md | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 429f537b7d4f..2abf3c38d836 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -87,7 +87,6 @@
UNSPEC_FMUL
UNSPEC_FMULS
UNSPEC_FMULSU
-   UNSPEC_COPYSIGN
UNSPEC_INSERT_BITS
UNSPEC_ROUND
])
@@ -9272,12 +9271,18 @@
 ;; Copysign
 
 (define_insn "copysignsf3"
-  [(set (match_operand:SF 0 "register_operand" "=r")
-(unspec:SF [(match_operand:SF 1 "register_operand"  "0")
-(match_operand:SF 2 "register_operand"  "r")]
-   UNSPEC_COPYSIGN))]
+  [(set (match_operand:SF 0 "register_operand"  "=r")
+(copysign:SF (match_operand:SF 1 "register_operand"  "0")
+ (match_operand:SF 2 "nonmemory_operand" "rF")))]
   ""
-  "bst %D2,7\;bld %D0,7"
+  {
+if (const_double_operand (operands[2], SFmode))
+  {
+rtx xmsb = simplify_gen_subreg (QImode, operands[2], SFmode, 3);
+return INTVAL (xmsb) < 0 ? "set\;bld %D0,7" : "clt\;bld %D0,7";
+  }
+return "bst %D2,7\;bld %D0,7";
+  }
   [(set_attr "length" "2")])
 
 ;; Swap Bytes (change byte-endianness)


[gcc r15-1749] testsuite/52641 - Adjust some test cases to less capable platforms.

2024-07-01 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:90c558ef740d0b98892b6a7811c278eda8adeea3

commit r15-1749-g90c558ef740d0b98892b6a7811c278eda8adeea3
Author: Georg-Johann Lay 
Date:   Mon Jul 1 12:10:50 2024 +0200

testsuite/52641 - Adjust some test cases to less capable platforms.

PR testsuite/52641
gcc/testsuite/
* gcc.dg/analyzer/pr109577.c: Use __SIZE_TYPE__ instead of 
"unsigned long".
* gcc.dg/analyzer/pr93032-mztools-signed-char.c: Requires int32plus.
* gcc.dg/analyzer/pr93032-mztools-unsigned-char.c: Requires 
int32plus.
* gcc.dg/analyzer/putenv-1.c: Skip on avr.
* gcc.dg/torture/type-generic-1.c: Skip on avr.

Diff:
---
 gcc/testsuite/gcc.dg/analyzer/pr109577.c  | 8 
 gcc/testsuite/gcc.dg/analyzer/pr93032-mztools-signed-char.c   | 1 +
 gcc/testsuite/gcc.dg/analyzer/pr93032-mztools-unsigned-char.c | 1 +
 gcc/testsuite/gcc.dg/analyzer/putenv-1.c  | 1 +
 gcc/testsuite/gcc.dg/torture/type-generic-1.c | 1 +
 5 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/analyzer/pr109577.c 
b/gcc/testsuite/gcc.dg/analyzer/pr109577.c
index 74d1629f3c7..18417818b54 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr109577.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr109577.c
@@ -2,18 +2,18 @@
Therefore this test has been duplicated as
c-c++-common/analyzer/pr109577-noexcept.c  */
 
-void *malloc (unsigned long);
+void *malloc (__SIZE_TYPE__);
 
 double *
-unsafe (unsigned long n)
+unsafe (__SIZE_TYPE__ n)
 {
   return (double *) malloc (n * sizeof (double));
 }
 
 double *
-safer (unsigned long n)
+safer (__SIZE_TYPE__ n)
 {
-  unsigned long nbytes;
+  __SIZE_TYPE__ nbytes;
   if (__builtin_mul_overflow (n, sizeof (double), &nbytes))
 return 0;
   return (double *) malloc (nbytes); /* Exceptions enabled cause a leak here. 
*/
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools-signed-char.c 
b/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools-signed-char.c
index 45599e228b8..7a7320fca2b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools-signed-char.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools-signed-char.c
@@ -5,6 +5,7 @@
 
 /* { dg-do "compile" } */
 /* { dg-additional-options "-fsigned-char" } */
+/* { dg-require-effective-target int32plus } */
 
 /* TODO (PR analyzer/112528): remove need for this.  */
 /* { dg-additional-options "--param analyzer-max-enodes-per-program-point=40 
--param analyzer-bb-explosion-factor=10" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools-unsigned-char.c 
b/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools-unsigned-char.c
index a59fc49c2b3..10832757127 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools-unsigned-char.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr93032-mztools-unsigned-char.c
@@ -5,6 +5,7 @@
 
 /* { dg-do "compile" } */
 /* { dg-additional-options "-funsigned-char" } */
+/* { dg-require-effective-target int32plus } */
 
 /* TODO (PR analyzer/112528): remove need for this.  */
 /* { dg-additional-options "--param analyzer-max-enodes-per-program-point=40 
--param analyzer-bb-explosion-factor=10" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/putenv-1.c 
b/gcc/testsuite/gcc.dg/analyzer/putenv-1.c
index 5c4e08c68df..2be52f05033 100644
--- a/gcc/testsuite/gcc.dg/analyzer/putenv-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/putenv-1.c
@@ -1,5 +1,6 @@
 /* { dg-additional-options "-Wno-analyzer-null-argument" } */
 /* { dg-require-effective-target alloca } */
+/* { dg-skip-if "has no putenv" { "avr-*-*" } } */
 
 #include 
 #include 
diff --git a/gcc/testsuite/gcc.dg/torture/type-generic-1.c 
b/gcc/testsuite/gcc.dg/torture/type-generic-1.c
index b2aacd933f8..1dd0534a5fb 100644
--- a/gcc/testsuite/gcc.dg/torture/type-generic-1.c
+++ b/gcc/testsuite/gcc.dg/torture/type-generic-1.c
@@ -4,6 +4,7 @@
 /* { dg-do run } */
 /* { dg-require-effective-target inf } */
 /* { dg-skip-if "No subnormal support" { csky-*-* } { "-mhard-float" } } */
+/* { dg-skip-if "Not fully IEEE" { "avr-*-*" } } */
 /* { dg-options "-DUNSAFE" { target tic6x*-*-* visium-*-* nvptx-*-* } } */
 /* { dg-add-options ieee } */


[gcc r15-1750] AVR: target/88236, target/115726 - Fix __memx code generation.

2024-07-01 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:3d23abd3dd9c8c226ea302203b214b346f4fe8d7

commit r15-1750-g3d23abd3dd9c8c226ea302203b214b346f4fe8d7
Author: Georg-Johann Lay 
Date:   Mon Jul 1 12:31:01 2024 +0200

AVR: target/88236, target/115726 - Fix __memx code generation.

PR target/88236
PR target/115726
gcc/
* config/avr/avr.md (mov) [avr_mem_memx_p]: Expand in such a
way that the destination does not overlap with any hard register
clobbered / used by xload8qi_A resp. xload_A.
* config/avr/avr.cc (avr_out_xload): Avoid early-clobber
situation for Z by executing just one load when the output register
overlaps with Z.
gcc/testsuite/
* gcc.target/avr/torture/pr88236-pr115726.c: New test.

Diff:
---
 gcc/config/avr/avr.cc  |   8 +-
 gcc/config/avr/avr.md  |  18 +++-
 .../gcc.target/avr/torture/pr88236-pr115726.c  | 115 +
 3 files changed, 138 insertions(+), 3 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 61c325f2497..a110af62cd5 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -4686,7 +4686,13 @@ avr_out_xload (rtx_insn * /*insn*/, rtx *op, int *plen)
   xop[2] = lpm_addr_reg_rtx;
   xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
 
-  avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
+  if (plen)
+*plen = 0;
+
+  if (reg_overlap_mentioned_p (xop[3], lpm_addr_reg_rtx))
+avr_asm_len ("sbrs %1,7", xop, plen, 1);
+
+  avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, 1);
 
   avr_asm_len ("sbrc %1,7" CR_TAB
   "ld %3,%a2", xop, plen, 2);
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 75d35d5e14b..dabf4c0fc5a 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -735,12 +735,26 @@
 if (!REG_P (addr))
   src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr));
 
+rtx dest2 = reg_overlap_mentioned_p (dest, lpm_addr_reg_rtx)
+  ? gen_reg_rtx (mode)
+  : dest;
+
 if (!avr_xload_libgcc_p (mode))
   // No  here because gen_xload8_A only iterates over ALL1.
   // insn-emit does not depend on the mode, it's all about operands.
-  emit_insn (gen_xload8qi_A (dest, src));
+  emit_insn (gen_xload8qi_A (dest2, src));
 else
-  emit_insn (gen_xload_A (dest, src));
+  {
+rtx reg_22 = gen_rtx_REG (mode, REG_22);
+if (reg_overlap_mentioned_p (dest2, reg_22)
+|| reg_overlap_mentioned_p (dest2, all_regs_rtx[REG_21]))
+  dest2 = gen_reg_rtx (mode);
+
+emit_insn (gen_xload_A (dest2, src));
+  }
+
+if (dest2 != dest)
+  emit_move_insn (dest, dest2);
 
 DONE;
   }
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c 
b/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c
new file mode 100644
index 000..9fd5fd3b5f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c
@@ -0,0 +1,115 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-std=gnu99" } */
+
+const __flash char fvals8[] = { 1, 2, 3 };
+char rvals8[] = { 0, 2, 4 };
+
+const __flash int fvals16[] = { 1, 2, 3 };
+int rvals16[] = { 0, 2, 4 };
+
+__attribute__((noinline, noclone))
+char xload8_r30 (const __memx char *pc)
+{
+  register char c __asm ("r30");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+int xload16_r30 (const __memx int *pc)
+{
+  register int c __asm ("r30");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+char xload8_r22 (const __memx char *pc)
+{
+  register char c __asm ("r22");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+int xload16_r22 (const __memx int *pc)
+{
+  register int c __asm ("r22");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+int xload16_r20 (const __memx int *pc)
+{
+  register int c __asm ("r20");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+void test8 (void)
+{
+  char c;
+  for (int i = 0; i < 3; ++i)
+{
+  c = xload8_r30 (fvals8 + i);
+  if (c != 1 + i)
+   __builtin_exit (__LINE__);
+
+  c = xload8_r22 (fvals8 + i);
+  if (c != 1 + i)
+   __builtin_exit (__LINE__);
+
+  c = xload8_r30 (rvals8 + i);
+  if (c != 2 * i)
+   __builtin_exit (__LINE__);
+
+  c = xload8_r22 (rvals8 + i);
+  if (c != 2 * i)
+   __builtin_exit (__LINE__);
+}
+}
+
+void test16 (void)
+{
+  int c;
+  for (int i = 0; i < 3; ++i)
+{
+  c = xload16_r30 (fvals16 + i);
+  if (c != 1 + i)
+   __builtin_exit (__LINE__);
+
+  c = xload16_r22 (fvals16 + i);
+  if (c != 1 + i)
+   __builtin_exit (__LI

[gcc r14-10367] AVR: target/88236, target/115726 - Fix __memx code generation.

2024-07-01 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:7249b3cdc16ae85bcfeb63510b6e5cb7f4a43adb

commit r14-10367-g7249b3cdc16ae85bcfeb63510b6e5cb7f4a43adb
Author: Georg-Johann Lay 
Date:   Mon Jul 1 12:31:01 2024 +0200

AVR: target/88236, target/115726 - Fix __memx code generation.

PR target/88236
PR target/115726
gcc/
* config/avr/avr.md (mov) [avr_mem_memx_p]: Expand in such a
way that the destination does not overlap with any hard register
clobbered / used by xload8qi_A resp. xload_A.
* config/avr/avr.cc (avr_out_xload): Avoid early-clobber
situation for Z by executing just one load when the output register
overlaps with Z.
gcc/testsuite/
* gcc.target/avr/torture/pr88236-pr115726.c: New test.

(cherry picked from commit 3d23abd3dd9c8c226ea302203b214b346f4fe8d7)

Diff:
---
 gcc/config/avr/avr.cc  |   8 +-
 gcc/config/avr/avr.md  |  18 +++-
 .../gcc.target/avr/torture/pr88236-pr115726.c  | 115 +
 3 files changed, 138 insertions(+), 3 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 74924ab0565..e516c19322c 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -4686,7 +4686,13 @@ avr_out_xload (rtx_insn * /*insn*/, rtx *op, int *plen)
   xop[2] = lpm_addr_reg_rtx;
   xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
 
-  avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
+  if (plen)
+*plen = 0;
+
+  if (reg_overlap_mentioned_p (xop[3], lpm_addr_reg_rtx))
+avr_asm_len ("sbrs %1,7", xop, plen, 1);
+
+  avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, 1);
 
   avr_asm_len ("sbrc %1,7" CR_TAB
   "ld %3,%a2", xop, plen, 2);
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 75d35d5e14b..dabf4c0fc5a 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -735,12 +735,26 @@
 if (!REG_P (addr))
   src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr));
 
+rtx dest2 = reg_overlap_mentioned_p (dest, lpm_addr_reg_rtx)
+  ? gen_reg_rtx (mode)
+  : dest;
+
 if (!avr_xload_libgcc_p (mode))
   // No  here because gen_xload8_A only iterates over ALL1.
   // insn-emit does not depend on the mode, it's all about operands.
-  emit_insn (gen_xload8qi_A (dest, src));
+  emit_insn (gen_xload8qi_A (dest2, src));
 else
-  emit_insn (gen_xload_A (dest, src));
+  {
+rtx reg_22 = gen_rtx_REG (mode, REG_22);
+if (reg_overlap_mentioned_p (dest2, reg_22)
+|| reg_overlap_mentioned_p (dest2, all_regs_rtx[REG_21]))
+  dest2 = gen_reg_rtx (mode);
+
+emit_insn (gen_xload_A (dest2, src));
+  }
+
+if (dest2 != dest)
+  emit_move_insn (dest, dest2);
 
 DONE;
   }
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c 
b/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c
new file mode 100644
index 000..9fd5fd3b5f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c
@@ -0,0 +1,115 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-std=gnu99" } */
+
+const __flash char fvals8[] = { 1, 2, 3 };
+char rvals8[] = { 0, 2, 4 };
+
+const __flash int fvals16[] = { 1, 2, 3 };
+int rvals16[] = { 0, 2, 4 };
+
+__attribute__((noinline, noclone))
+char xload8_r30 (const __memx char *pc)
+{
+  register char c __asm ("r30");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+int xload16_r30 (const __memx int *pc)
+{
+  register int c __asm ("r30");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+char xload8_r22 (const __memx char *pc)
+{
+  register char c __asm ("r22");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+int xload16_r22 (const __memx int *pc)
+{
+  register int c __asm ("r22");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+int xload16_r20 (const __memx int *pc)
+{
+  register int c __asm ("r20");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+void test8 (void)
+{
+  char c;
+  for (int i = 0; i < 3; ++i)
+{
+  c = xload8_r30 (fvals8 + i);
+  if (c != 1 + i)
+   __builtin_exit (__LINE__);
+
+  c = xload8_r22 (fvals8 + i);
+  if (c != 1 + i)
+   __builtin_exit (__LINE__);
+
+  c = xload8_r30 (rvals8 + i);
+  if (c != 2 * i)
+   __builtin_exit (__LINE__);
+
+  c = xload8_r22 (rvals8 + i);
+  if (c != 2 * i)
+   __builtin_exit (__LINE__);
+}
+}
+
+void test16 (void)
+{
+  int c;
+  for (int i = 0; i < 3; ++i)
+{
+  c = xload16_r30 (fvals16 + i);
+  if (c != 1 + i)
+   __builtin_exit (__LINE__);
+
+  c =

[gcc r13-8882] AVR: target/88236, target/115726 - Fix __memx code generation.

2024-07-01 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:743575bfc6cfb3520047bddf969f880455d581b1

commit r13-8882-g743575bfc6cfb3520047bddf969f880455d581b1
Author: Georg-Johann Lay 
Date:   Mon Jul 1 12:31:01 2024 +0200

AVR: target/88236, target/115726 - Fix __memx code generation.

PR target/88236
PR target/115726
gcc/
* config/avr/avr.md (mov) [avr_mem_memx_p]: Expand in such a
way that the destination does not overlap with any hard register
clobbered / used by xload8qi_A resp. xload_A.
* config/avr/avr.cc (avr_out_xload): Avoid early-clobber
situation for Z by executing just one load when the output register
overlaps with Z.
gcc/testsuite/
* gcc.target/avr/torture/pr88236-pr115726.c: New test.

(cherry picked from commit 3d23abd3dd9c8c226ea302203b214b346f4fe8d7)

Diff:
---
 gcc/config/avr/avr.cc  |   8 +-
 gcc/config/avr/avr.md  |  18 +++-
 .../gcc.target/avr/torture/pr88236-pr115726.c  | 115 +
 3 files changed, 138 insertions(+), 3 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index a5c628134b4..36ad0f23162 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -4093,7 +4093,13 @@ avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, 
int *plen)
   xop[2] = lpm_addr_reg_rtx;
   xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
 
-  avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
+  if (plen)
+*plen = 0;
+
+  if (reg_overlap_mentioned_p (xop[3], lpm_addr_reg_rtx))
+avr_asm_len ("sbrs %1,7", xop, plen, 1);
+
+  avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, 1);
 
   avr_asm_len ("sbrc %1,7" CR_TAB
"ld %3,%a2", xop, plen, 2);
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 46f7812cea2..c8b5ccaf098 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -718,12 +718,26 @@
 if (!REG_P (addr))
   src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr));
 
+rtx dest2 = reg_overlap_mentioned_p (dest, lpm_addr_reg_rtx)
+  ? gen_reg_rtx (mode)
+  : dest;
+
 if (!avr_xload_libgcc_p (mode))
   /* ; No  here because gen_xload8_A only iterates over 
ALL1.
  ; insn-emit does not depend on the mode, it's all about operands. 
 */
-  emit_insn (gen_xload8qi_A (dest, src));
+  emit_insn (gen_xload8qi_A (dest2, src));
 else
-  emit_insn (gen_xload_A (dest, src));
+  {
+rtx reg_22 = gen_rtx_REG (mode, 22);
+if (reg_overlap_mentioned_p (dest2, reg_22)
+|| reg_overlap_mentioned_p (dest2, all_regs_rtx[21]))
+  dest2 = gen_reg_rtx (mode);
+
+emit_insn (gen_xload_A (dest2, src));
+  }
+
+if (dest2 != dest)
+  emit_move_insn (dest, dest2);
 
 DONE;
   }
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c 
b/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c
new file mode 100644
index 000..9fd5fd3b5f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c
@@ -0,0 +1,115 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-std=gnu99" } */
+
+const __flash char fvals8[] = { 1, 2, 3 };
+char rvals8[] = { 0, 2, 4 };
+
+const __flash int fvals16[] = { 1, 2, 3 };
+int rvals16[] = { 0, 2, 4 };
+
+__attribute__((noinline, noclone))
+char xload8_r30 (const __memx char *pc)
+{
+  register char c __asm ("r30");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+int xload16_r30 (const __memx int *pc)
+{
+  register int c __asm ("r30");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+char xload8_r22 (const __memx char *pc)
+{
+  register char c __asm ("r22");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+int xload16_r22 (const __memx int *pc)
+{
+  register int c __asm ("r22");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+int xload16_r20 (const __memx int *pc)
+{
+  register int c __asm ("r20");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+void test8 (void)
+{
+  char c;
+  for (int i = 0; i < 3; ++i)
+{
+  c = xload8_r30 (fvals8 + i);
+  if (c != 1 + i)
+   __builtin_exit (__LINE__);
+
+  c = xload8_r22 (fvals8 + i);
+  if (c != 1 + i)
+   __builtin_exit (__LINE__);
+
+  c = xload8_r30 (rvals8 + i);
+  if (c != 2 * i)
+   __builtin_exit (__LINE__);
+
+  c = xload8_r22 (rvals8 + i);
+  if (c != 2 * i)
+   __builtin_exit (__LINE__);
+}
+}
+
+void test16 (void)
+{
+  int c;
+  for (int i = 0; i < 3; ++i)
+{
+  c = xload16_r30 (fvals16 + i);
+  if (c != 1 + i)
+   __builtin_exit (__LINE__

[gcc r12-10591] AVR: target/88236, target/115726 - Fix __memx code generation.

2024-07-01 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:53305588cfbf74604bafcc27902e1eded5677ae6

commit r12-10591-g53305588cfbf74604bafcc27902e1eded5677ae6
Author: Georg-Johann Lay 
Date:   Mon Jul 1 12:31:01 2024 +0200

AVR: target/88236, target/115726 - Fix __memx code generation.

PR target/88236
PR target/115726
gcc/
* config/avr/avr.md (mov) [avr_mem_memx_p]: Expand in such a
way that the destination does not overlap with any hard register
clobbered / used by xload8qi_A resp. xload_A.
* config/avr/avr.cc (avr_out_xload): Avoid early-clobber
situation for Z by executing just one load when the output register
overlaps with Z.
gcc/testsuite/
* gcc.target/avr/torture/pr88236-pr115726.c: New test.

(cherry picked from commit 3d23abd3dd9c8c226ea302203b214b346f4fe8d7)

Diff:
---
 gcc/config/avr/avr.cc  |   8 +-
 gcc/config/avr/avr.md  |  18 +++-
 .../gcc.target/avr/torture/pr88236-pr115726.c  | 115 +
 3 files changed, 138 insertions(+), 3 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index bc15017c61c..ee033d3204d 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -4071,7 +4071,13 @@ avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, 
int *plen)
   xop[2] = lpm_addr_reg_rtx;
   xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
 
-  avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
+  if (plen)
+*plen = 0;
+
+  if (reg_overlap_mentioned_p (xop[3], lpm_addr_reg_rtx))
+avr_asm_len ("sbrs %1,7", xop, plen, 1);
+
+  avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, 1);
 
   avr_asm_len ("sbrc %1,7" CR_TAB
"ld %3,%a2", xop, plen, 2);
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index de029476908..f76249340b8 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -715,12 +715,26 @@
 if (!REG_P (addr))
   src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr));
 
+rtx dest2 = reg_overlap_mentioned_p (dest, lpm_addr_reg_rtx)
+  ? gen_reg_rtx (mode)
+  : dest;
+
 if (!avr_xload_libgcc_p (mode))
   /* ; No  here because gen_xload8_A only iterates over 
ALL1.
  ; insn-emit does not depend on the mode, it's all about operands. 
 */
-  emit_insn (gen_xload8qi_A (dest, src));
+  emit_insn (gen_xload8qi_A (dest2, src));
 else
-  emit_insn (gen_xload_A (dest, src));
+  {
+rtx reg_22 = gen_rtx_REG (mode, 22);
+if (reg_overlap_mentioned_p (dest2, reg_22)
+|| reg_overlap_mentioned_p (dest2, all_regs_rtx[21]))
+  dest2 = gen_reg_rtx (mode);
+
+emit_insn (gen_xload_A (dest2, src));
+  }
+
+if (dest2 != dest)
+  emit_move_insn (dest, dest2);
 
 DONE;
   }
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c 
b/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c
new file mode 100644
index 000..9fd5fd3b5f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c
@@ -0,0 +1,115 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options "-std=gnu99" } */
+
+const __flash char fvals8[] = { 1, 2, 3 };
+char rvals8[] = { 0, 2, 4 };
+
+const __flash int fvals16[] = { 1, 2, 3 };
+int rvals16[] = { 0, 2, 4 };
+
+__attribute__((noinline, noclone))
+char xload8_r30 (const __memx char *pc)
+{
+  register char c __asm ("r30");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+int xload16_r30 (const __memx int *pc)
+{
+  register int c __asm ("r30");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+char xload8_r22 (const __memx char *pc)
+{
+  register char c __asm ("r22");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+int xload16_r22 (const __memx int *pc)
+{
+  register int c __asm ("r22");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+__attribute__((noinline, noclone))
+int xload16_r20 (const __memx int *pc)
+{
+  register int c __asm ("r20");
+  c = *pc;
+  __asm (";;" : "+r" (c));
+  return c;
+}
+
+void test8 (void)
+{
+  char c;
+  for (int i = 0; i < 3; ++i)
+{
+  c = xload8_r30 (fvals8 + i);
+  if (c != 1 + i)
+   __builtin_exit (__LINE__);
+
+  c = xload8_r22 (fvals8 + i);
+  if (c != 1 + i)
+   __builtin_exit (__LINE__);
+
+  c = xload8_r30 (rvals8 + i);
+  if (c != 2 * i)
+   __builtin_exit (__LINE__);
+
+  c = xload8_r22 (rvals8 + i);
+  if (c != 2 * i)
+   __builtin_exit (__LINE__);
+}
+}
+
+void test16 (void)
+{
+  int c;
+  for (int i = 0; i < 3; ++i)
+{
+  c = xload16_r30 (fvals16 + i);
+  if (c != 1 + i)
+   __builtin_exit (__LINE_

[gcc r15-1810] AVR: target/98762 - Handle partial clobber in movqi output.

2024-07-03 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:e9fb6efa1cf542353fd44ddcbb5136344c463fd0

commit r15-1810-ge9fb6efa1cf542353fd44ddcbb5136344c463fd0
Author: Georg-Johann Lay 
Date:   Wed Jul 3 10:29:18 2024 +0200

AVR: target/98762 - Handle partial clobber in movqi output.

PR target/98762
gcc/
* config/avr/avr.cc (avr_out_movqi_r_mr_reg_disp_tiny): Properly
restore the base register when it is partially clobbered.
gcc/testsuite/
* gcc.target/avr/torture/pr98762.c: New test.

Diff:
---
 gcc/config/avr/avr.cc  | 27 +-
 gcc/testsuite/gcc.target/avr/torture/pr98762.c | 19 ++
 2 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index a110af62cd5..f048bf5fd41 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -4838,13 +4838,30 @@ avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx 
op[], int *plen)
   rtx dest = op[0];
   rtx src = op[1];
   rtx x = XEXP (src, 0);
+  rtx base = XEXP (x, 0);
 
-  avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
-  "ld %0,%b1" , op, plen, -3);
+  if (plen)
+*plen = 0;
 
-  if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
-  && !reg_unused_after (insn, XEXP (x, 0)))
-avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
+  if (!reg_overlap_mentioned_p (dest, base))
+{
+  avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
+  "ld %0,%b1", op, plen, 3);
+  if (!reg_unused_after (insn, base))
+   avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
+}
+  else
+{
+  // PR98762: The base register overlaps dest and is only partly clobbered.
+  rtx base2 = all_regs_rtx[1 ^ REGNO (dest)];
+
+  if (!reg_unused_after (insn, base2))
+   avr_asm_len ("mov __tmp_reg__,%0" , &base2, plen, 1);
+  avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
+  "ld %0,%b1", op, plen, 3);
+  if (!reg_unused_after (insn, base2))
+   avr_asm_len ("mov %0,__tmp_reg__" , &base2, plen, 1);
+}
 
   return "";
 }
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr98762.c 
b/gcc/testsuite/gcc.target/avr/torture/pr98762.c
new file mode 100644
index 000..c3ba7da69a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr98762.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-additional-options "-std=c99" } */
+
+long long acc = 0x1122334455667788;
+
+__attribute__((noinline,noclone))
+void addhi (short a)
+{
+  acc += (long long) a << 32;
+}
+
+int main (void)
+{
+  addhi (0x0304);
+  if (acc != 0x1122364855667788)
+__builtin_abort();
+
+  return 0;
+}


[gcc r14-10373] AVR: target/98762 - Handle partial clobber in movqi output.

2024-07-03 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:55744507abc5240fe1a59a6251f815a0d6217fe8

commit r14-10373-g55744507abc5240fe1a59a6251f815a0d6217fe8
Author: Georg-Johann Lay 
Date:   Wed Jul 3 10:29:18 2024 +0200

AVR: target/98762 - Handle partial clobber in movqi output.

PR target/98762
gcc/
* config/avr/avr.cc (avr_out_movqi_r_mr_reg_disp_tiny): Properly
restore the base register when it is partially clobbered.
gcc/testsuite/
* gcc.target/avr/torture/pr98762.c: New test.

(cherry picked from commit e9fb6efa1cf542353fd44ddcbb5136344c463fd0)

Diff:
---
 gcc/config/avr/avr.cc  | 27 +-
 gcc/testsuite/gcc.target/avr/torture/pr98762.c | 19 ++
 2 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index e516c19322c..b41592ff1a3 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -4838,13 +4838,30 @@ avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx 
op[], int *plen)
   rtx dest = op[0];
   rtx src = op[1];
   rtx x = XEXP (src, 0);
+  rtx base = XEXP (x, 0);
 
-  avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
-  "ld %0,%b1" , op, plen, -3);
+  if (plen)
+*plen = 0;
 
-  if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
-  && !reg_unused_after (insn, XEXP (x, 0)))
-avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
+  if (!reg_overlap_mentioned_p (dest, base))
+{
+  avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
+  "ld %0,%b1", op, plen, 3);
+  if (!reg_unused_after (insn, base))
+   avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
+}
+  else
+{
+  // PR98762: The base register overlaps dest and is only partly clobbered.
+  rtx base2 = all_regs_rtx[1 ^ REGNO (dest)];
+
+  if (!reg_unused_after (insn, base2))
+   avr_asm_len ("mov __tmp_reg__,%0" , &base2, plen, 1);
+  avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
+  "ld %0,%b1", op, plen, 3);
+  if (!reg_unused_after (insn, base2))
+   avr_asm_len ("mov %0,__tmp_reg__" , &base2, plen, 1);
+}
 
   return "";
 }
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr98762.c 
b/gcc/testsuite/gcc.target/avr/torture/pr98762.c
new file mode 100644
index 000..c3ba7da69a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr98762.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-additional-options "-std=c99" } */
+
+long long acc = 0x1122334455667788;
+
+__attribute__((noinline,noclone))
+void addhi (short a)
+{
+  acc += (long long) a << 32;
+}
+
+int main (void)
+{
+  addhi (0x0304);
+  if (acc != 0x1122364855667788)
+__builtin_abort();
+
+  return 0;
+}


[gcc r13-8887] AVR: target/98762 - Handle partial clobber in movqi output.

2024-07-03 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:ba9fef4bdea32ca5c121a1baba02450faf2b

commit r13-8887-gba9fef4bdea32ca5c121a1baba02450faf2b
Author: Georg-Johann Lay 
Date:   Wed Jul 3 10:29:18 2024 +0200

AVR: target/98762 - Handle partial clobber in movqi output.

PR target/98762
gcc/
* config/avr/avr.cc (avr_out_movqi_r_mr_reg_disp_tiny): Properly
restore the base register when it is partially clobbered.
gcc/testsuite/
* gcc.target/avr/torture/pr98762.c: New test.

(cherry picked from commit e9fb6efa1cf542353fd44ddcbb5136344c463fd0)

Diff:
---
 gcc/config/avr/avr.cc  | 27 +-
 gcc/testsuite/gcc.target/avr/torture/pr98762.c | 19 ++
 2 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 36ad0f23162..676ab2405db 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -4245,13 +4245,30 @@ avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx 
op[], int *plen)
   rtx dest = op[0];
   rtx src = op[1];
   rtx x = XEXP (src, 0);
+  rtx base = XEXP (x, 0);
 
-  avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
-   "ld %0,%b1" , op, plen, -3);
+  if (plen)
+*plen = 0;
 
-  if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
-  && !reg_unused_after (insn, XEXP (x, 0)))
-avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
+  if (!reg_overlap_mentioned_p (dest, base))
+{
+  avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
+  "ld %0,%b1", op, plen, 3);
+  if (!reg_unused_after (insn, base))
+   avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
+}
+  else
+{
+  // PR98762: The base register overlaps dest and is only partly clobbered.
+  rtx base2 = all_regs_rtx[1 ^ REGNO (dest)];
+
+  if (!reg_unused_after (insn, base2))
+   avr_asm_len ("mov __tmp_reg__,%0" , &base2, plen, 1);
+  avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
+  "ld %0,%b1", op, plen, 3);
+  if (!reg_unused_after (insn, base2))
+   avr_asm_len ("mov %0,__tmp_reg__" , &base2, plen, 1);
+}
 
   return "";
 }
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr98762.c 
b/gcc/testsuite/gcc.target/avr/torture/pr98762.c
new file mode 100644
index 000..c3ba7da69a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr98762.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-additional-options "-std=c99" } */
+
+long long acc = 0x1122334455667788;
+
+__attribute__((noinline,noclone))
+void addhi (short a)
+{
+  acc += (long long) a << 32;
+}
+
+int main (void)
+{
+  addhi (0x0304);
+  if (acc != 0x1122364855667788)
+__builtin_abort();
+
+  return 0;
+}


[gcc r12-10596] AVR: target/98762 - Handle partial clobber in movqi output.

2024-07-03 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:5f699cb08eed44a903393f601009e9c6d0b59c59

commit r12-10596-g5f699cb08eed44a903393f601009e9c6d0b59c59
Author: Georg-Johann Lay 
Date:   Wed Jul 3 10:29:18 2024 +0200

AVR: target/98762 - Handle partial clobber in movqi output.

PR target/98762
gcc/
* config/avr/avr.cc (avr_out_movqi_r_mr_reg_disp_tiny): Properly
restore the base register when it is partially clobbered.
gcc/testsuite/
* gcc.target/avr/torture/pr98762.c: New test.

(cherry picked from commit e9fb6efa1cf542353fd44ddcbb5136344c463fd0)

Diff:
---
 gcc/config/avr/avr.cc  | 27 +-
 gcc/testsuite/gcc.target/avr/torture/pr98762.c | 19 ++
 2 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index ee033d3204d..f355146f992 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -4223,13 +4223,30 @@ avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx 
op[], int *plen)
   rtx dest = op[0];
   rtx src = op[1];
   rtx x = XEXP (src, 0);
+  rtx base = XEXP (x, 0);
 
-  avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
-   "ld %0,%b1" , op, plen, -3);
+  if (plen)
+*plen = 0;
 
-  if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
-  && !reg_unused_after (insn, XEXP (x, 0)))
-avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
+  if (!reg_overlap_mentioned_p (dest, base))
+{
+  avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
+  "ld %0,%b1", op, plen, 3);
+  if (!reg_unused_after (insn, base))
+   avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
+}
+  else
+{
+  // PR98762: The base register overlaps dest and is only partly clobbered.
+  rtx base2 = all_regs_rtx[1 ^ REGNO (dest)];
+
+  if (!reg_unused_after (insn, base2))
+   avr_asm_len ("mov __tmp_reg__,%0" , &base2, plen, 1);
+  avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
+  "ld %0,%b1", op, plen, 3);
+  if (!reg_unused_after (insn, base2))
+   avr_asm_len ("mov %0,__tmp_reg__" , &base2, plen, 1);
+}
 
   return "";
 }
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr98762.c 
b/gcc/testsuite/gcc.target/avr/torture/pr98762.c
new file mode 100644
index 000..c3ba7da69a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr98762.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-additional-options "-std=c99" } */
+
+long long acc = 0x1122334455667788;
+
+__attribute__((noinline,noclone))
+void addhi (short a)
+{
+  acc += (long long) a << 32;
+}
+
+int main (void)
+{
+  addhi (0x0304);
+  if (acc != 0x1122364855667788)
+__builtin_abort();
+
+  return 0;
+}


[gcc r15-1860] AVR: target/87376 - Use nop_general_operand for DImode inputs.

2024-07-05 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:23a0935262d6817097406578b1c70563f424804b

commit r15-1860-g23a0935262d6817097406578b1c70563f424804b
Author: Georg-Johann Lay 
Date:   Fri Jul 5 13:22:12 2024 +0200

AVR: target/87376 - Use nop_general_operand for DImode inputs.

The avr-dimode.md expanders have code like  emit_move_insn(acc_a, 
operands[1])
where acc_a is a hard register and operands[1] might be a non-generic
address-space memory reference.  Such loads may clobber hard regs since
some of them are implemented as libgcc calls /and/ 64-moves are
expanded as eight byte-moves, so that acc_a or acc_b might be clobbered
by such a load.

This patch simply denies non-generic address-space references by using
nop_general_operand for all avr-dimode.md input predicates.
With the patch, all memory loads that require library calls are issued
before the expander codes from avr-dimode.md are run.

PR target/87376
gcc/
* config/avr/avr-dimode.md: Use "nop_general_operand" instead
of "general_operand" as predicate for all input operands.

gcc/testsuite/
* gcc.target/avr/torture/pr87376.c: New test.

Diff:
---
 gcc/config/avr/avr-dimode.md   | 26 +--
 gcc/testsuite/gcc.target/avr/torture/pr87376.c | 60 ++
 2 files changed, 73 insertions(+), 13 deletions(-)

diff --git a/gcc/config/avr/avr-dimode.md b/gcc/config/avr/avr-dimode.md
index 4b74e77e5e5..c357213e211 100644
--- a/gcc/config/avr/avr-dimode.md
+++ b/gcc/config/avr/avr-dimode.md
@@ -62,8 +62,8 @@
 ;; "addta3" "adduta3"
 (define_expand "add3"
   [(parallel [(match_operand:ALL8 0 "general_operand" "")
-  (match_operand:ALL8 1 "general_operand" "")
-  (match_operand:ALL8 2 "general_operand" "")])]
+  (match_operand:ALL8 1 "nop_general_operand")
+  (match_operand:ALL8 2 "nop_general_operand")])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -178,8 +178,8 @@
 ;; "subta3" "subuta3"
 (define_expand "sub3"
   [(parallel [(match_operand:ALL8 0 "general_operand" "")
-  (match_operand:ALL8 1 "general_operand" "")
-  (match_operand:ALL8 2 "general_operand" "")])]
+  (match_operand:ALL8 1 "nop_general_operand")
+  (match_operand:ALL8 2 "nop_general_operand")])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -259,8 +259,8 @@
 
 (define_expand "3"
   [(set (match_operand:ALL8S 0 "general_operand" "")
-(ss_addsub:ALL8S (match_operand:ALL8S 1 "general_operand" "")
- (match_operand:ALL8S 2 "general_operand" "")))]
+(ss_addsub:ALL8S (match_operand:ALL8S 1 "nop_general_operand")
+ (match_operand:ALL8S 2 "nop_general_operand")))]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -332,8 +332,8 @@
 
 (define_expand "3"
   [(set (match_operand:ALL8U 0 "general_operand" "")
-(us_addsub:ALL8U (match_operand:ALL8U 1 "general_operand" "")
- (match_operand:ALL8U 2 "general_operand" "")))]
+(us_addsub:ALL8U (match_operand:ALL8U 1 "nop_general_operand")
+ (match_operand:ALL8U 2 "nop_general_operand")))]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -405,7 +405,7 @@
 
 (define_expand "negdi2"
   [(parallel [(match_operand:DI 0 "general_operand" "")
-  (match_operand:DI 1 "general_operand" "")])]
+  (match_operand:DI 1 "nop_general_operand")])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (DImode, ACC_A);
@@ -602,8 +602,8 @@
 ;; "ashluta3"  "ashruta3"  "lshruta3"  "rotluta3"
 (define_expand "3"
   [(parallel [(match_operand:ALL8 0 "general_operand" "")
-  (di_shifts:ALL8 (match_operand:ALL8 1 "general_operand" "")
-  (match_operand:QI 2 "general_operand" ""))])]
+  (di_shifts:ALL8 (match_operand:ALL8 1 "nop_general_operand")
+  (match_operand:QI 2 "nop_general_operand"))])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -648,8 +648,8 @@
 ;; "mulsidi3"
 (define_expand "mulsidi3"
   [(parallel [(match_operand:DI 0 "register_operand" "")
-  (match_operand:SI 1 "general_operand" "")
-  (match_operand:SI 2 "general_operand" "")
+  (match_operand:SI 1 "nop_general_operand")
+  (match_operand:SI 2 "nop_general_operand")
   ;; Just to mention the iterator 
   (clobber (any_extend:SI (match_dup 1)))])]
   "avr_have_dimode
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr87376.c 
b/gcc/testsuite/gcc.target/avr/torture/pr87376.c
new file mode 100644
index 000..c31a4a9dda5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr87376.c
@@ -0,0 +1,60 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-opt

[gcc r14-10382] AVR: target/87376 - Use nop_general_operand for DImode inputs.

2024-07-05 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:9f5620aed3976716e20e13c285dade56578d5bab

commit r14-10382-g9f5620aed3976716e20e13c285dade56578d5bab
Author: Georg-Johann Lay 
Date:   Fri Jul 5 13:22:12 2024 +0200

AVR: target/87376 - Use nop_general_operand for DImode inputs.

The avr-dimode.md expanders have code like  emit_move_insn(acc_a, 
operands[1])
where acc_a is a hard register and operands[1] might be a non-generic
address-space memory reference.  Such loads may clobber hard regs since
some of them are implemented as libgcc calls /and/ 64-moves are
expanded as eight byte-moves, so that acc_a or acc_b might be clobbered
by such a load.

This patch simply denies non-generic address-space references by using
nop_general_operand for all avr-dimode.md input predicates.
With the patch, all memory loads that require library calls are issued
before the expander codes from avr-dimode.md are run.

PR target/87376
gcc/
* config/avr/avr-dimode.md: Use "nop_general_operand" instead
of "general_operand" as predicate for all input operands.

gcc/testsuite/
* gcc.target/avr/torture/pr87376.c: New test.

(cherry picked from commit 23a0935262d6817097406578b1c70563f424804b)

Diff:
---
 gcc/config/avr/avr-dimode.md   | 26 +--
 gcc/testsuite/gcc.target/avr/torture/pr87376.c | 60 ++
 2 files changed, 73 insertions(+), 13 deletions(-)

diff --git a/gcc/config/avr/avr-dimode.md b/gcc/config/avr/avr-dimode.md
index 4b74e77e5e5..c357213e211 100644
--- a/gcc/config/avr/avr-dimode.md
+++ b/gcc/config/avr/avr-dimode.md
@@ -62,8 +62,8 @@
 ;; "addta3" "adduta3"
 (define_expand "add3"
   [(parallel [(match_operand:ALL8 0 "general_operand" "")
-  (match_operand:ALL8 1 "general_operand" "")
-  (match_operand:ALL8 2 "general_operand" "")])]
+  (match_operand:ALL8 1 "nop_general_operand")
+  (match_operand:ALL8 2 "nop_general_operand")])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -178,8 +178,8 @@
 ;; "subta3" "subuta3"
 (define_expand "sub3"
   [(parallel [(match_operand:ALL8 0 "general_operand" "")
-  (match_operand:ALL8 1 "general_operand" "")
-  (match_operand:ALL8 2 "general_operand" "")])]
+  (match_operand:ALL8 1 "nop_general_operand")
+  (match_operand:ALL8 2 "nop_general_operand")])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -259,8 +259,8 @@
 
 (define_expand "3"
   [(set (match_operand:ALL8S 0 "general_operand" "")
-(ss_addsub:ALL8S (match_operand:ALL8S 1 "general_operand" "")
- (match_operand:ALL8S 2 "general_operand" "")))]
+(ss_addsub:ALL8S (match_operand:ALL8S 1 "nop_general_operand")
+ (match_operand:ALL8S 2 "nop_general_operand")))]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -332,8 +332,8 @@
 
 (define_expand "3"
   [(set (match_operand:ALL8U 0 "general_operand" "")
-(us_addsub:ALL8U (match_operand:ALL8U 1 "general_operand" "")
- (match_operand:ALL8U 2 "general_operand" "")))]
+(us_addsub:ALL8U (match_operand:ALL8U 1 "nop_general_operand")
+ (match_operand:ALL8U 2 "nop_general_operand")))]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -405,7 +405,7 @@
 
 (define_expand "negdi2"
   [(parallel [(match_operand:DI 0 "general_operand" "")
-  (match_operand:DI 1 "general_operand" "")])]
+  (match_operand:DI 1 "nop_general_operand")])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (DImode, ACC_A);
@@ -602,8 +602,8 @@
 ;; "ashluta3"  "ashruta3"  "lshruta3"  "rotluta3"
 (define_expand "3"
   [(parallel [(match_operand:ALL8 0 "general_operand" "")
-  (di_shifts:ALL8 (match_operand:ALL8 1 "general_operand" "")
-  (match_operand:QI 2 "general_operand" ""))])]
+  (di_shifts:ALL8 (match_operand:ALL8 1 "nop_general_operand")
+  (match_operand:QI 2 "nop_general_operand"))])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -648,8 +648,8 @@
 ;; "mulsidi3"
 (define_expand "mulsidi3"
   [(parallel [(match_operand:DI 0 "register_operand" "")
-  (match_operand:SI 1 "general_operand" "")
-  (match_operand:SI 2 "general_operand" "")
+  (match_operand:SI 1 "nop_general_operand")
+  (match_operand:SI 2 "nop_general_operand")
   ;; Just to mention the iterator 
   (clobber (any_extend:SI (match_dup 1)))])]
   "avr_have_dimode
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr87376.c 
b/gcc/testsuite/gcc.target/avr/torture/pr87376.c
new file mode 100644
index 000..c31a4a9dda5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr87376.c
@@ -0,0 

[gcc r13-8893] AVR: target/87376 - Use nop_general_operand for DImode inputs.

2024-07-05 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:4a49d212b54ab152737e3209b7f80af3a80966b8

commit r13-8893-g4a49d212b54ab152737e3209b7f80af3a80966b8
Author: Georg-Johann Lay 
Date:   Fri Jul 5 13:22:12 2024 +0200

AVR: target/87376 - Use nop_general_operand for DImode inputs.

The avr-dimode.md expanders have code like  emit_move_insn(acc_a, 
operands[1])
where acc_a is a hard register and operands[1] might be a non-generic
address-space memory reference.  Such loads may clobber hard regs since
some of them are implemented as libgcc calls /and/ 64-moves are
expanded as eight byte-moves, so that acc_a or acc_b might be clobbered
by such a load.

This patch simply denies non-generic address-space references by using
nop_general_operand for all avr-dimode.md input predicates.
With the patch, all memory loads that require library calls are issued
before the expander codes from avr-dimode.md are run.

PR target/87376
gcc/
* config/avr/avr-dimode.md: Use "nop_general_operand" instead
of "general_operand" as predicate for all input operands.

gcc/testsuite/
* gcc.target/avr/torture/pr87376.c: New test.

(cherry picked from commit 23a0935262d6817097406578b1c70563f424804b)

Diff:
---
 gcc/config/avr/avr-dimode.md   | 26 +--
 gcc/testsuite/gcc.target/avr/torture/pr87376.c | 60 ++
 2 files changed, 73 insertions(+), 13 deletions(-)

diff --git a/gcc/config/avr/avr-dimode.md b/gcc/config/avr/avr-dimode.md
index 91f0d395761..ba444be1b33 100644
--- a/gcc/config/avr/avr-dimode.md
+++ b/gcc/config/avr/avr-dimode.md
@@ -62,8 +62,8 @@
 ;; "addta3" "adduta3"
 (define_expand "add3"
   [(parallel [(match_operand:ALL8 0 "general_operand" "")
-  (match_operand:ALL8 1 "general_operand" "")
-  (match_operand:ALL8 2 "general_operand" "")])]
+  (match_operand:ALL8 1 "nop_general_operand")
+  (match_operand:ALL8 2 "nop_general_operand")])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -178,8 +178,8 @@
 ;; "subta3" "subuta3"
 (define_expand "sub3"
   [(parallel [(match_operand:ALL8 0 "general_operand" "")
-  (match_operand:ALL8 1 "general_operand" "")
-  (match_operand:ALL8 2 "general_operand" "")])]
+  (match_operand:ALL8 1 "nop_general_operand")
+  (match_operand:ALL8 2 "nop_general_operand")])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -259,8 +259,8 @@
 
 (define_expand "3"
   [(set (match_operand:ALL8S 0 "general_operand" "")
-(ss_addsub:ALL8S (match_operand:ALL8S 1 "general_operand" "")
- (match_operand:ALL8S 2 "general_operand" "")))]
+(ss_addsub:ALL8S (match_operand:ALL8S 1 "nop_general_operand")
+ (match_operand:ALL8S 2 "nop_general_operand")))]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -332,8 +332,8 @@
 
 (define_expand "3"
   [(set (match_operand:ALL8U 0 "general_operand" "")
-(us_addsub:ALL8U (match_operand:ALL8U 1 "general_operand" "")
- (match_operand:ALL8U 2 "general_operand" "")))]
+(us_addsub:ALL8U (match_operand:ALL8U 1 "nop_general_operand")
+ (match_operand:ALL8U 2 "nop_general_operand")))]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -405,7 +405,7 @@
 
 (define_expand "negdi2"
   [(parallel [(match_operand:DI 0 "general_operand" "")
-  (match_operand:DI 1 "general_operand" "")])]
+  (match_operand:DI 1 "nop_general_operand")])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (DImode, ACC_A);
@@ -602,8 +602,8 @@
 ;; "ashluta3"  "ashruta3"  "lshruta3"  "rotluta3"
 (define_expand "3"
   [(parallel [(match_operand:ALL8 0 "general_operand" "")
-  (di_shifts:ALL8 (match_operand:ALL8 1 "general_operand" "")
-  (match_operand:QI 2 "general_operand" ""))])]
+  (di_shifts:ALL8 (match_operand:ALL8 1 "nop_general_operand")
+  (match_operand:QI 2 "nop_general_operand"))])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -648,8 +648,8 @@
 ;; "mulsidi3"
 (define_expand "mulsidi3"
   [(parallel [(match_operand:DI 0 "register_operand" "")
-  (match_operand:SI 1 "general_operand" "")
-  (match_operand:SI 2 "general_operand" "")
+  (match_operand:SI 1 "nop_general_operand")
+  (match_operand:SI 2 "nop_general_operand")
   ;; Just to mention the iterator 
   (clobber (any_extend:SI (match_dup 1)))])]
   "avr_have_dimode
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr87376.c 
b/gcc/testsuite/gcc.target/avr/torture/pr87376.c
new file mode 100644
index 000..c31a4a9dda5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr87376.c
@@ -0,0 +

[gcc r12-10602] AVR: target/87376 - Use nop_general_operand for DImode inputs.

2024-07-05 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:5f4a60c43d5cd805add6529b4528c35893c283ae

commit r12-10602-g5f4a60c43d5cd805add6529b4528c35893c283ae
Author: Georg-Johann Lay 
Date:   Fri Jul 5 13:22:12 2024 +0200

AVR: target/87376 - Use nop_general_operand for DImode inputs.

The avr-dimode.md expanders have code like  emit_move_insn(acc_a, 
operands[1])
where acc_a is a hard register and operands[1] might be a non-generic
address-space memory reference.  Such loads may clobber hard regs since
some of them are implemented as libgcc calls /and/ 64-moves are
expanded as eight byte-moves, so that acc_a or acc_b might be clobbered
by such a load.

This patch simply denies non-generic address-space references by using
nop_general_operand for all avr-dimode.md input predicates.
With the patch, all memory loads that require library calls are issued
before the expander codes from avr-dimode.md are run.

PR target/87376
gcc/
* config/avr/avr-dimode.md: Use "nop_general_operand" instead
of "general_operand" as predicate for all input operands.

gcc/testsuite/
* gcc.target/avr/torture/pr87376.c: New test.

(cherry picked from commit 23a0935262d6817097406578b1c70563f424804b)

Diff:
---
 gcc/config/avr/avr-dimode.md   | 26 +--
 gcc/testsuite/gcc.target/avr/torture/pr87376.c | 60 ++
 2 files changed, 73 insertions(+), 13 deletions(-)

diff --git a/gcc/config/avr/avr-dimode.md b/gcc/config/avr/avr-dimode.md
index 28e97da0516..78a7a745d34 100644
--- a/gcc/config/avr/avr-dimode.md
+++ b/gcc/config/avr/avr-dimode.md
@@ -62,8 +62,8 @@
 ;; "addta3" "adduta3"
 (define_expand "add3"
   [(parallel [(match_operand:ALL8 0 "general_operand" "")
-  (match_operand:ALL8 1 "general_operand" "")
-  (match_operand:ALL8 2 "general_operand" "")])]
+  (match_operand:ALL8 1 "nop_general_operand")
+  (match_operand:ALL8 2 "nop_general_operand")])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -178,8 +178,8 @@
 ;; "subta3" "subuta3"
 (define_expand "sub3"
   [(parallel [(match_operand:ALL8 0 "general_operand" "")
-  (match_operand:ALL8 1 "general_operand" "")
-  (match_operand:ALL8 2 "general_operand" "")])]
+  (match_operand:ALL8 1 "nop_general_operand")
+  (match_operand:ALL8 2 "nop_general_operand")])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -259,8 +259,8 @@
 
 (define_expand "3"
   [(set (match_operand:ALL8S 0 "general_operand" "")
-(ss_addsub:ALL8S (match_operand:ALL8S 1 "general_operand" "")
- (match_operand:ALL8S 2 "general_operand" "")))]
+(ss_addsub:ALL8S (match_operand:ALL8S 1 "nop_general_operand")
+ (match_operand:ALL8S 2 "nop_general_operand")))]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -332,8 +332,8 @@
 
 (define_expand "3"
   [(set (match_operand:ALL8U 0 "general_operand" "")
-(us_addsub:ALL8U (match_operand:ALL8U 1 "general_operand" "")
- (match_operand:ALL8U 2 "general_operand" "")))]
+(us_addsub:ALL8U (match_operand:ALL8U 1 "nop_general_operand")
+ (match_operand:ALL8U 2 "nop_general_operand")))]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -405,7 +405,7 @@
 
 (define_expand "negdi2"
   [(parallel [(match_operand:DI 0 "general_operand" "")
-  (match_operand:DI 1 "general_operand" "")])]
+  (match_operand:DI 1 "nop_general_operand")])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (DImode, ACC_A);
@@ -602,8 +602,8 @@
 ;; "ashluta3"  "ashruta3"  "lshruta3"  "rotluta3"
 (define_expand "3"
   [(parallel [(match_operand:ALL8 0 "general_operand" "")
-  (di_shifts:ALL8 (match_operand:ALL8 1 "general_operand" "")
-  (match_operand:QI 2 "general_operand" ""))])]
+  (di_shifts:ALL8 (match_operand:ALL8 1 "nop_general_operand")
+  (match_operand:QI 2 "nop_general_operand"))])]
   "avr_have_dimode"
   {
 rtx acc_a = gen_rtx_REG (mode, ACC_A);
@@ -648,8 +648,8 @@
 ;; "mulsidi3"
 (define_expand "mulsidi3"
   [(parallel [(match_operand:DI 0 "register_operand" "")
-  (match_operand:SI 1 "general_operand" "")
-  (match_operand:SI 2 "general_operand" "")
+  (match_operand:SI 1 "nop_general_operand")
+  (match_operand:SI 2 "nop_general_operand")
   ;; Just to mention the iterator 
   (clobber (any_extend:SI (match_dup 1)))])]
   "avr_have_dimode
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr87376.c 
b/gcc/testsuite/gcc.target/avr/torture/pr87376.c
new file mode 100644
index 000..c31a4a9dda5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr87376.c
@@ -0,0 

[gcc r15-1871] AVR: Create more opportunities for -mfuse-add optimization.

2024-07-06 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:96559be74bfa355507472fc020c95c14587c227f

commit r15-1871-g96559be74bfa355507472fc020c95c14587c227f
Author: Georg-Johann Lay 
Date:   Fri Jul 5 23:49:43 2024 +0200

AVR: Create more opportunities for -mfuse-add optimization.

avr_split_tiny_move() was only run for AVR_TINY because it has no PLUS
addressing modes.  Same applies to the X register on ordinary cores, and
also to the Z register when used with [E]LPM.  For example, without this 
patch

long long addLL (long long *a, long long *b)
{
  return *a + *b;
}

compiles with "-mmcu=atmgea128 -Os -dp" to:

...
movw r26,r24 ;  80  [c=4 l=1]  *movhi/0
movw r30,r22 ;  81  [c=4 l=1]  *movhi/0
ld r18,X ;  82  [c=4 l=1]  movqi_insn/3
adiw r26,1   ;  83  [c=4 l=3]  movqi_insn/3
ld r19,X
sbiw r26,1
adiw r26,2   ;  84  [c=4 l=3]  movqi_insn/3
ld r20,X
sbiw r26,2
adiw r26,3   ;  85  [c=4 l=3]  movqi_insn/3
ld r21,X
sbiw r26,3
adiw r26,4   ;  86  [c=4 l=3]  movqi_insn/3
ld r22,X
sbiw r26,4
adiw r26,5   ;  87  [c=4 l=3]  movqi_insn/3
ld r23,X
sbiw r26,5
adiw r26,6   ;  88  [c=4 l=3]  movqi_insn/3
ld r24,X
sbiw r26,6
adiw r26,7   ;  89  [c=4 l=2]  movqi_insn/3
ld r25,X
ld r10,Z ;  90  [c=4 l=1]  movqi_insn/3
...

whereas with this patch it becomes:

...
movw r26,r24 ;  80  [c=4 l=1]  *movhi/0
movw r30,r22 ;  81  [c=4 l=1]  *movhi/0
ld r18,X+;  140 [c=4 l=1]  movqi_insn/3
ld r19,X+;  142 [c=4 l=1]  movqi_insn/3
ld r20,X+;  144 [c=4 l=1]  movqi_insn/3
ld r21,X+;  146 [c=4 l=1]  movqi_insn/3
ld r22,X+;  148 [c=4 l=1]  movqi_insn/3
ld r23,X+;  150 [c=4 l=1]  movqi_insn/3
ld r24,X+;  152 [c=4 l=1]  movqi_insn/3
ld r25,X ;  109 [c=4 l=1]  movqi_insn/3
ld r10,Z ;  111 [c=4 l=1]  movqi_insn/3
...

gcc/
* config/avr/avr.md: Also split with avr_split_tiny_move()
for non-AVR_TINY.
* config/avr/avr.cc (avr_split_tiny_move): Don't change memory
references with base regs that can do PLUS addressing.
(avr_out_lpm_no_lpmx) [POST_INC]: Don't output final ADIW when the
address register is unused after.
gcc/testsuite/
* gcc.target/avr/torture/fuse-add.c: New test.

Diff:
---
 gcc/config/avr/avr.cc   | 39 
 gcc/config/avr/avr.md   |  3 +-
 gcc/testsuite/gcc.target/avr/torture/fuse-add.c | 59 +
 3 files changed, 80 insertions(+), 21 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index f048bf5fd41..d299fceb782 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -4471,28 +4471,21 @@ avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int 
*plen)
   gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
  && n_bytes <= 4);
 
-  if (regno_dest == LPM_REGNO)
-   avr_asm_len ("%4lpm"  CR_TAB
-"adiw %2,1", xop, plen, 2);
-  else
-   avr_asm_len ("%4lpm"  CR_TAB
-"mov %A0,%3" CR_TAB
-"adiw %2,1", xop, plen, 3);
+  for (int i = 0; i < n_bytes; ++i)
+   {
+ rtx reg = simplify_gen_subreg (QImode, dest, GET_MODE (dest), i);
 
-  if (n_bytes >= 2)
-   avr_asm_len ("%4lpm"  CR_TAB
-"mov %B0,%3" CR_TAB
-"adiw %2,1", xop, plen, 3);
+ if (i > 0)
+   avr_asm_len ("adiw %2,1", xop, plen, 1);
 
-  if (n_bytes >= 3)
-   avr_asm_len ("%4lpm"  CR_TAB
-"mov %C0,%3" CR_TAB
-"adiw %2,1", xop, plen, 3);
+ avr_asm_len ("%4lpm", xop, plen, 1);
 
-  if (n_bytes >= 4)
-   avr_asm_len ("%4lpm"  CR_TAB
-"mov %D0,%3" CR_TAB
-"adiw %2,1", xop, plen, 3);
+ if (REGNO (reg) != LPM_REGNO)
+   avr_asm_len ("mov %0,r0", ®, plen, 1);
+   }
+
+  if (! _reg_unused_after (insn, xop[2], false))
+   avr_asm_len ("adiw %2,1", xop, plen, 1);
 
   break; /* POST_INC */
 
@@ -6685,6 +6678,14 @@ avr_split_tiny_move (rtx_insn * /*insn*/, rtx *xop)
   if (REGNO (base) > REG_Z)
 return false;
 
+  if (! AVR_TINY
+  // Only keep base registers that can't do PLUS addressing.
+  && ((REGNO (base) != REG_X
+  && ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (mem)))
+ || avr_load_libgcc_p (mem)
+ || avr_mem_memx_p (mem)))
+return false;
+
   bool volatile_p = MEM_VOLATILE_P (mem);
   bool mem_volatile_p = false;
   if (frame_pointer_needed
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.

[gcc r15-1873] testsuite/52641 - Fix more sloppy tests.

2024-07-06 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:bb16e3179e79e4307f1d834a02e63d0dfd817f67

commit r15-1873-gbb16e3179e79e4307f1d834a02e63d0dfd817f67
Author: Georg-Johann Lay 
Date:   Sat Jul 6 15:02:28 2024 +0200

testsuite/52641 - Fix more sloppy tests.

PR testsuite/52641
gcc/testsuite/
* gcc.dg/analyzer/torture/boxed-ptr-1.c: Requires size24plus.
* gcc.dg/analyzer/torture/pr102692.c: Use intptr_t instead of long.
* gcc.dg/ipa/pr102714.c: Use uintptr_t instead of unsigned long.
* gcc.dg/torture/pr115387-1.c: Same.
* gcc.dg/torture/pr113895-1.c : Same.
* gcc.dg/ipa/pr108007.c: Require int32plus.
* gcc.dg/ipa/pr109318.c: Same.
* gcc.dg/ipa/pr96040.c: Use size_t instead of unsigned long.
* gcc.dg/torture/pr113126.c: Use vectors of same dimension.
* gcc.dg/tree-ssa/builtin-sprintf-9.c: Requires double64.

* gcc.dg/spellcheck-inttypes.c [avr]: Avoid include of inttypes.h.
* gcc.dg/analyzer/torture/pr104159.c [avr]: Skip.
* gcc.dg/torture/pr84682-2.c [avr]: Skip.
* gcc.dg/wtr-conversion-1.c [avr]: Remove avr selector since
long double is a 64-bit type by now.

Diff:
---
 gcc/testsuite/gcc.dg/analyzer/torture/boxed-ptr-1.c | 1 +
 gcc/testsuite/gcc.dg/analyzer/torture/pr102692.c| 2 +-
 gcc/testsuite/gcc.dg/analyzer/torture/pr104159.c| 1 +
 gcc/testsuite/gcc.dg/ipa/pr102714.c | 6 +++---
 gcc/testsuite/gcc.dg/ipa/pr108007.c | 1 +
 gcc/testsuite/gcc.dg/ipa/pr109318.c | 1 +
 gcc/testsuite/gcc.dg/ipa/pr96040.c  | 4 ++--
 gcc/testsuite/gcc.dg/spellcheck-inttypes.c  | 7 +++
 gcc/testsuite/gcc.dg/torture/pr113126.c | 4 ++--
 gcc/testsuite/gcc.dg/torture/pr113895-1.c   | 1 +
 gcc/testsuite/gcc.dg/torture/pr115387-1.c   | 2 +-
 gcc/testsuite/gcc.dg/torture/pr84682-2.c| 1 +
 gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-9.c   | 1 +
 gcc/testsuite/gcc.dg/wtr-conversion-1.c | 4 ++--
 14 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/boxed-ptr-1.c 
b/gcc/testsuite/gcc.dg/analyzer/torture/boxed-ptr-1.c
index 5bc7151a798..e25d0c31ea5 100644
--- a/gcc/testsuite/gcc.dg/analyzer/torture/boxed-ptr-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/boxed-ptr-1.c
@@ -1,4 +1,5 @@
 /* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+/* { dg-require-effective-target size24plus } */
 
 #include 
 #include "../analyzer-decls.h"
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/pr102692.c 
b/gcc/testsuite/gcc.dg/analyzer/torture/pr102692.c
index a6c6bc47896..a1b3bfed047 100644
--- a/gcc/testsuite/gcc.dg/analyzer/torture/pr102692.c
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/pr102692.c
@@ -15,7 +15,7 @@ make_lisp_ptr (void *ptr, int type)
 static _Bool
 TAGGEDP (struct lisp *a, unsigned tag)
 {
-  return ! (((unsigned) (long) a - tag) & 7);
+  return ! (((unsigned) (__INTPTR_TYPE__) a - tag) & 7);
 }
 
 static _Bool
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/pr104159.c 
b/gcc/testsuite/gcc.dg/analyzer/torture/pr104159.c
index ad85d084b39..0c490bd39f2 100644
--- a/gcc/testsuite/gcc.dg/analyzer/torture/pr104159.c
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/pr104159.c
@@ -1,4 +1,5 @@
 /* { dg-additional-options "-Wno-analyzer-use-of-uninitialized-value 
-Wno-psabi" } */
+/* { dg-skip-if "incompatible types" { "avr-*-*" } } */
 
 typedef int __attribute__((__vector_size__(4))) T;
 typedef unsigned __attribute__((__vector_size__(4))) U;
diff --git a/gcc/testsuite/gcc.dg/ipa/pr102714.c 
b/gcc/testsuite/gcc.dg/ipa/pr102714.c
index 65dd86f5c15..8ab77a61d75 100644
--- a/gcc/testsuite/gcc.dg/ipa/pr102714.c
+++ b/gcc/testsuite/gcc.dg/ipa/pr102714.c
@@ -54,16 +54,16 @@ static inline __attribute__((__gnu_inline__)) 
__attribute__((__unused__)) __attr
 
 static inline __attribute__((__gnu_inline__)) __attribute__((__unused__)) 
__attribute__((no_instrument_function)) struct xa_node *entry_to_node(void *ptr)
 {
- return (void *)((unsigned long)ptr & ~2UL);
+ return (void *)((__UINTPTR_TYPE__)ptr & ~(__UINTPTR_TYPE__)2);
 }
 
 static inline __attribute__((__gnu_inline__)) __attribute__((__unused__)) 
__attribute__((no_instrument_function)) bool radix_tree_is_internal_node(void 
*ptr)
 {
- return ((unsigned long)ptr & 3UL) ==
+ return ((__UINTPTR_TYPE__)ptr & 3UL) ==
 2UL;
 }
 
-static inline __attribute__((__gnu_inline__)) __attribute__((__unused__)) 
__attribute__((no_instrument_function)) void *xa_mk_internal(unsigned long v)
+static inline __attribute__((__gnu_inline__)) __attribute__((__unused__)) 
__attribute__((no_instrument_function)) void *xa_mk_internal(__UINTPTR_TYPE__ v)
 {
  return (void *)((v << 2) | 2);
 }
diff --git a/gcc/testsuite/gcc.dg/ipa/pr108007.c 
b/gcc/testsuite/gcc.dg/ipa/pr108007.c
index 77fc95975cf..5bd1c350963 100644
--- a/gcc/testsuite/gc

[gcc r15-1969] AVR: Tidy up subtract-and-zero_extend insns.

2024-07-11 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:077f16b249346b560169cf89849779272327a2da

commit r15-1969-g077f16b249346b560169cf89849779272327a2da
Author: Georg-Johann Lay 
Date:   Thu Jul 11 13:08:19 2024 +0200

AVR: Tidy up subtract-and-zero_extend insns.

There are these insns that subtract and zero-extend where
the subtrahend is zero-extended to the mode of the minuend.
This patch uses one insn (and split) with mode iterators
instead of spelling out each variant individually.
This has the additional benefit that u32 - u24 is also supported,
which previously wasn't.

gcc/
* config/avr/avr-protos.h (avr_out_minus): New prototype.
* config/avr/avr.cc (avr_out_minus): New function.
* config/avr/avr.md (*sub3.zero_extend.)
(*sub3.zero_extend._split): New insns.
(*subpsi3_zero_extend.qi_split): Remove isns_and_split.
(*subpsi3_zero_extend.hi_split): Remove insn_and_split.
(*subhi3_zero_extend1_split): Remove insn_and_split.
(*subsi3_zero_extend_split): Remove insn_and_split.
(*subsi3_zero_extend.hi_split): Remove insn_and_split.
(*subpsi3_zero_extend.qi): Remove insn.
(*subpsi3_zero_extend.hi): Remove insn.
(*subhi3_zero_extend1): Remove insn.
(*subsi3_zero_extend): Remove insn.
(*subsi3_zero_extend.hi): Remove insn.
gcc/testsuite/
* gcc.target/avr/torture/sub-zerox.c: New test.

Diff:
---
 gcc/config/avr/avr-protos.h  |   1 +
 gcc/config/avr/avr.cc|  32 +-
 gcc/config/avr/avr.md| 122 +--
 gcc/testsuite/gcc.target/avr/torture/sub-zerox.c |  15 +++
 4 files changed, 73 insertions(+), 97 deletions(-)

diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index dc23cfbf461c..6e02161759ca 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -95,6 +95,7 @@ extern void avr_output_addr_vec (rtx_insn*, rtx);
 extern const char *avr_out_sbxx_branch (rtx_insn *insn, rtx operands[]);
 extern const char* avr_out_bitop (rtx, rtx*, int*);
 extern const char* avr_out_plus (rtx, rtx*, int* =NULL, bool =true);
+extern const char* avr_out_minus (rtx*);
 extern const char* avr_out_round (rtx_insn *, rtx*, int* =NULL);
 extern const char* avr_out_addto_sp (rtx*, int*);
 extern const char* avr_out_xload (rtx_insn *, rtx*, int*);
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index d299fceb7824..4a7cbd0e7bc6 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -8843,6 +8843,36 @@ lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
 }
 
 
+/* Output subtraction of integer registers XOP[0] and XOP[2] and return ""
+
+  XOP[0] = XOP[0] - XOP[2]
+
+   where the mode of XOP[0] is in { HI, PSI, SI }, and the mode of
+   XOP[2] is in { QI, HI, PSI }.  When the mode of XOP[0] is larger
+   than the mode of XOP[2], then the latter is zero-extended on the fly.
+   The number of instructions will be the mode size of XOP[0].  */
+
+const char *
+avr_out_minus (rtx *xop)
+{
+  int n_bytes0 = GET_MODE_SIZE (GET_MODE (xop[0]));
+  int n_bytes2 = GET_MODE_SIZE (GET_MODE (xop[2]));
+
+  output_asm_insn ("sub %0,%2", xop);
+
+  for (int i = 1; i < n_bytes0; ++i)
+{
+  rtx op[2];
+  op[0] = all_regs_rtx[i + REGNO (xop[0])];
+  op[1] = (i < n_bytes2) ? all_regs_rtx[i + REGNO (xop[2])] : zero_reg_rtx;
+
+  output_asm_insn ("sbc %0,%1", op);
+}
+
+  return "";
+}
+
+
 /* Output addition of register XOP[0] and compile time constant XOP[2].
INSN is a single_set insn or an insn pattern.
CODE == PLUS:  perform addition by using ADD instructions or
@@ -12717,7 +12747,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int 
outer_code,
  *total = COSTS_N_INSNS (2);
  return true;
}
-  // *sub3_zero_extend1
+  // *sub3.zero_extend.
   if (REG_P (XEXP (x, 0))
  && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
{
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 2783b8c986f1..8c3e55a91ee0 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -2030,47 +2030,6 @@
   "sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2"
   [(set_attr "length" "3")])
 
-(define_insn_and_split "*subpsi3_zero_extend.qi_split"
-  [(set (match_operand:PSI 0 "register_operand"   "=r")
-(minus:PSI (match_operand:SI 1 "register_operand"  "0")
-   (zero_extend:PSI (match_operand:QI 2 "register_operand" 
"r"]
-  ""
-  "#"
-  "&& reload_completed"
-  [(parallel [(set (match_dup 0)
-   (minus:PSI (match_dup 1)
-  (zero_extend:PSI (match_dup 2
-  (clobber (reg:CC REG_CC))])])
-
-(define_insn "*subpsi3_zero_extend.qi"
-  [(set (match_operand:PSI 0 "register_operand"   "=r")
-(minus:PSI (ma

[gcc r15-2040] AVR: avr-md - Simplify GET_MODE and GET_MODE_BITSIZE.

2024-07-15 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:8f87b3c5ecd47f6ac0d7407ae5d436a12fb169dd

commit r15-2040-g8f87b3c5ecd47f6ac0d7407ae5d436a12fb169dd
Author: Georg-Johann Lay 
Date:   Mon Jul 15 09:12:03 2024 +0200

AVR: avr-md - Simplify GET_MODE and GET_MODE_BITSIZE.

gcc/
* config/avr/avr.md: Simplify mode usage.
(GET_MODE_SIZE (mode)): Use  instead.
(GET_MODE_BITSIZE (mode) - 1): Use  instead.
(GET_MODE_MASK (QImode)): Use 0xff instead.
* config/avr/avr-fixed.md: Same.

Diff:
---
 gcc/config/avr/avr-fixed.md |  8 
 gcc/config/avr/avr.md   | 36 ++--
 2 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/gcc/config/avr/avr-fixed.md b/gcc/config/avr/avr-fixed.md
index ca0e254e314b..911b8b2cd67c 100644
--- a/gcc/config/avr/avr-fixed.md
+++ b/gcc/config/avr/avr-fixed.md
@@ -231,7 +231,7 @@
 (match_dup 2))]
   ""
   {
-operands[2] = gen_rtx_REG (mode, 26 - GET_MODE_SIZE (mode));
+operands[2] = gen_rtx_REG (mode, 26 - );
   })
 
 ;; "*ssneghq2"  "*ssnegha2"
@@ -651,7 +651,7 @@
   {
 if (CONST_INT_P (operands[2])
 && !(optimize_size
- && 4 == GET_MODE_SIZE (mode)))
+ && 4 == ))
   {
 emit_insn (gen_round3_const (operands[0], operands[1], 
operands[2]));
 DONE;
@@ -661,8 +661,8 @@
 const unsigned int regno_in[]  = { -1U, 22, 22, -1U, 18 };
 const unsigned int regno_out[] = { -1U, 24, 24, -1U, 22 };
 
-operands[3] = gen_rtx_REG (mode, regno_out[(size_t) GET_MODE_SIZE 
(mode)]);
-operands[4] = gen_rtx_REG (mode,  regno_in[(size_t) GET_MODE_SIZE 
(mode)]);
+operands[3] = gen_rtx_REG (mode, regno_out[(size_t) ]);
+operands[4] = gen_rtx_REG (mode,  regno_in[(size_t) ]);
 avr_fix_inputs (operands, 1 << 2, regmask (mode, REGNO 
(operands[4])));
 operands[5] = simplify_gen_subreg (QImode, force_reg (HImode, 
operands[2]), HImode, 0);
 // $2 is no more needed, but is referenced for expand.
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 8c3e55a91ee0..e67284421b64 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -556,7 +556,7 @@
&& REG_Z == REGNO (XEXP (operands[0], 0))
&& reload_completed"
   {
-operands[0] = GEN_INT (GET_MODE_SIZE (mode));
+operands[0] = GEN_INT ();
 return "%~call __load_%0";
   }
   [(set_attr "length" "1,2")
@@ -679,7 +679,7 @@
   "avr_xload_libgcc_p (mode)
&& reload_completed"
   {
-rtx x_bytes = GEN_INT (GET_MODE_SIZE (mode));
+rtx x_bytes = GEN_INT ();
 
 output_asm_insn ("%~call __xload_%0", &x_bytes);
 return "";
@@ -1023,7 +1023,7 @@
 operands[2] = replace_equiv_address (operands[1],
  gen_rtx_POST_INC (Pmode, addr));
 operands[3] = addr;
-operands[4] = gen_int_mode (-GET_MODE_SIZE (mode), HImode);
+operands[4] = gen_int_mode (-, HImode);
   })
 
 
@@ -4789,7 +4789,7 @@
   [(set (match_dup 2) (match_dup 3))
(set (match_dup 4) (match_dup 5))]
   {
-machine_mode mode_hi = 4 == GET_MODE_SIZE (mode) ? HImode : QImode;
+machine_mode mode_hi =  == 4 ? HImode : QImode;
 bool lo_first = REGNO (operands[0]) < REGNO (operands[1]);
 rtx dst_lo = simplify_gen_subreg (HImode, operands[0], mode, 0);
 rtx src_lo = simplify_gen_subreg (HImode, operands[1], mode, 0);
@@ -4833,7 +4833,7 @@
&& reload_completed"
   [(const_int 1)]
   {
-for (int i = 0; i < GET_MODE_SIZE (mode); i++)
+for (int i = 0; i < ; i++)
   {
 rtx dst = simplify_gen_subreg (QImode, operands[0], mode, i);
 rtx src = simplify_gen_subreg (QImode, operands[1], mode, i);
@@ -4962,7 +4962,7 @@
   operands[3] = gen_rtx_SCRATCH (QImode);
   }
 else if (offset == 1
- || offset == GET_MODE_BITSIZE (mode) -1)
+ || offset == )
   {
 // Support rotate left/right by 1.
 
@@ -5117,7 +5117,7 @@
(clobber (match_scratch: 3 "="))]
   "AVR_HAVE_MOVW
&& CONST_INT_P (operands[2])
-   && GET_MODE_SIZE (mode) % 2 == 0
+   &&  % 2 == 0
&& 0 == INTVAL (operands[2]) % 16"
   "#"
   "&& reload_completed"
@@ -5141,7 +5141,7 @@
   "CONST_INT_P (operands[2])
&& (8 == INTVAL (operands[2]) % 16
|| ((!AVR_HAVE_MOVW
-|| GET_MODE_SIZE (mode) % 2 != 0)
+||  % 2 != 0)
&& 0 == INTVAL (operands[2]) % 16))"
   "#"
   "&& reload_completed"
@@ -6658,7 +6658,7 @@
 (compare:CC (any_extend:HISI (match_operand:QIPSI 0 "register_operand" 
"r"))
 (match_operand:HISI 1 "register_operand" "r")))]
   "reload_completed
-   && GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode)"
+   &&  > "
   {
 return avr_out_cmp_ext (operands, , nullptr);
   }
@@ -6671,7 +6671,7 @@
 (compare:CC (match_operand:HISI 0 "register_operand" "r")
 (any_extend:HISI (match_operand:QIPSI 1 "register_operand" 
"r"]
   "reload_completed
-   && GET_MODE_SIZE (mode) > GE

[gcc r15-2064] AVR: Allow more combinations of XOR / IOR with byte-shifts.

2024-07-16 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:cca1229b85f2ad9422773fdb954d0924fa1cd350

commit r15-2064-gcca1229b85f2ad9422773fdb954d0924fa1cd350
Author: Georg-Johann Lay 
Date:   Tue Jul 16 15:17:23 2024 +0200

AVR: Allow more combinations of XOR / IOR with byte-shifts.

This patch takes some existing patterns that have QImode as one
input and uses a mode iterator to allow for more modes to match.
These insns are split after reload into *xorqi3 resp. *iorqi3 insn(s).

gcc/
* config/avr/avr-protos.h (avr_emit_xior_with_shift): New proto.
* config/avr/avr.cc (avr_emit_xior_with_shift): New function.
* config/avr/avr.md (any_lshift): New code iterator.
(*.): New insn-and-split.
(.0): Replaces...
(*qi.byte0): ...this one.
(*.): Replaces...
(*qi.byte1-3): ...this one.

Diff:
---
 gcc/config/avr/avr-protos.h |  1 +
 gcc/config/avr/avr.cc   | 52 ++
 gcc/config/avr/avr.md   | 78 +
 3 files changed, 104 insertions(+), 27 deletions(-)

diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 6e02161759ca..d3fa6c677232 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -88,6 +88,7 @@ extern rtx avr_to_int_mode (rtx);
 extern void avr_expand_prologue (void);
 extern void avr_expand_epilogue (bool);
 extern bool avr_emit_cpymemhi (rtx*);
+extern void avr_emit_xior_with_shift (rtx_insn*, rtx*, int);
 extern int avr_epilogue_uses (int regno);
 extern bool avr_split_tiny_move (rtx_insn *insn, rtx *operands);
 
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 4a7cbd0e7bc6..d2a08c60c3ad 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -9754,6 +9754,58 @@ avr_out_bitop (rtx insn, rtx *xop, int *plen)
 }
 
 
+/* Emit code for
+
+   XOP[0] = XOP[0]  (XOP[1]  BITOFF)
+
+   where XOP[0] and XOP[1] are hard registers with integer mode,
+is XOR or IOR, and  is LSHIFTRT or ASHIFT with a
+   non-negative shift offset BITOFF.  This function emits the operation
+   in terms of byte-wise operations in QImode.  */
+
+void
+avr_emit_xior_with_shift (rtx_insn *insn, rtx *xop, int bitoff)
+{
+  rtx src = SET_SRC (single_set (insn));
+  RTX_CODE xior = GET_CODE (src);
+  gcc_assert (xior == XOR || xior == IOR);
+  gcc_assert (bitoff % 8 == 0);
+
+  // Work out the shift offset in bytes; negative for shift right.
+  RTX_CODE shift = GET_CODE (XEXP (src, 0));
+  int byteoff = 0?0
+: shift == ASHIFT ? bitoff / 8
+: shift == LSHIFTRT ? -bitoff / 8
+// Not a shift but something like REG or ZERO_EXTEND:
+// Use xop[1] as is, without shifting it.
+: 0;
+
+  // Work out which hard REGNOs belong to the operands.
+  int size0 = GET_MODE_SIZE (GET_MODE (xop[0]));
+  int size1 = GET_MODE_SIZE (GET_MODE (xop[1]));
+  int regno0_lo = REGNO (xop[0]), regno0_hi = regno0_lo + size0 - 1;
+  int regno1_lo = REGNO (xop[1]), regno1_hi = regno1_lo + size1 - 1;
+  int regoff = regno0_lo - regno1_lo + byteoff;
+
+  // The order of insns matters in the rare case when xop[1] overlaps xop[0].
+  int beg = regoff > 0 ? regno1_hi : regno1_lo;
+  int end = regoff > 0 ? regno1_lo : regno1_hi;
+  int inc = regoff > 0 ? -1 : 1;
+
+  rtx (*gen)(rtx,rtx,rtx) = xior == XOR ? gen_xorqi3 : gen_iorqi3;
+
+  for (int i = beg; i != end + inc; i += inc)
+{
+  if (IN_RANGE (i + regoff, regno0_lo, regno0_hi))
+   {
+ rtx reg0 = all_regs_rtx[i + regoff];
+ rtx reg1 = all_regs_rtx[i];
+ emit_insn (gen (reg0, reg0, reg1));
+   }
+}
+}
+
+
 /* Output sign extension from XOP[1] to XOP[0] and return "".
If PLEN == NULL, print assembler instructions to perform the operation;
otherwise, set *PLEN to the length of the instruction sequence (in words)
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index e67284421b64..cf9541422a33 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -313,6 +313,7 @@
 (define_code_iterator any_extract [sign_extract zero_extract])
 (define_code_iterator any_shiftrt [lshiftrt ashiftrt])
 (define_code_iterator any_shift   [lshiftrt ashiftrt ashift])
+(define_code_iterator any_lshift  [lshiftrt ashift]) ; logic shift
 
 (define_code_iterator piaop [plus ior and])
 (define_code_iterator bitop [xor ior and])
@@ -9350,46 +9351,69 @@
   })
 
 
+;; "*iorsi.ashift""*iorpsi.ashift""*iorhi.ashift"
+;; "*xorsi.ashift""*xorpsi.ashift""*xorhi.ashift"
+;; "*iorsi.lshiftrt"  "*iorpsi.lshiftrt"  "*iorhi.lshiftrt"
+;; "*xorsi.lshiftrt"  "*xorpsi.lshiftrt"  "*xorhi.lshiftrt"
+(define_insn_and_split "*."
+  [(set (match_operand:HISI 0 "register_operand"   
"=r")
+(xior:HISI (any_lshift:HISI (match_operand:HISI 1 "register_operand"   
 "r")
+(match_operand:QI 3 
"const_8_16_24_operand" "n"))
+   (match_operand:HISI 2 "regis

[gcc r15-2068] AVR: Overhaul add and sub insns that extend one operand.

2024-07-16 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:a074780fce3751cbedc0307dd1967a5a7d8e5660

commit r15-2068-ga074780fce3751cbedc0307dd1967a5a7d8e5660
Author: Georg-Johann Lay 
Date:   Fri Jul 12 13:02:55 2024 +0200

AVR: Overhaul add and sub insns that extend one operand.

These are insns of the forms

  (set (regA:M)
   (plus:M (extend:M (regB:L))
   (regA:M)))
and

  (set (regA:M)
   (minus:M (regA:M)
(extend:M (regB:L

where "extend" may be a sign-extend or zero-extend,
and the integer modes are  SImode >= M > L >= QImode.

The existing patterns are now represented in terms of insns
with mode iterators and a code iterator over any_extend,
and these new insn support all valid combinations of M and L
(which previously was not the case).

gcc/
* config/avr/avr.cc (avr_out_minus): Assimilate into...
(avr_out_plus_ext): ...this new function.
(avr_adjust_insn_length) [ADJUST_LEN_PLUS_EXT]: Handle case.
(avr_rtx_costs_1) [PLUS, MINUS]: Adjust RTX costs.
* config/avr/avr.md (adjust_len) : Add new attribute 
value.
(*addpsi3_zero_extend.hi_split): Assimilate...
(*addpsi3_zero_extend.qi_split): Assimilate...
(*addsi3_zero_extend_split): Assimilate...
(*addsi3_zero_extend.hi_split): Assimilate...
(*addpsi3_sign_extend.hi_split): Assimilate...
(*addhi3.sign_extend1_split): Assimilate...
(*add3.._split): ...into this
new insn-and-split.
(*addpsi3_zero_extend.hi): Assimilate...
(*addpsi3_zero_extend.qi): Assimilate...
(*addsi3_zero_extend): Assimilate...
(*addsi3_zero_extend.hi): Assimilate...
(*addpsi3_sign_extend.hi): Assimilate...
(*addhi3.sign_extend1): Assimilate...
(*add3..): ...into this new insn.
(*subpsi3_sign_extend.hi_split): Assimilate...
(*subhi3.sign_extend2_split): Assimilate...
(*sub3.zero_extend._split): Assimilate...
(*sub3._split): ...into this new
insn-and-split.
(*subpsi3_sign_extend.hi): Assimilate...
(*subhi3.sign_extend2): Assimilate...
(*sub3.zero_extend.): Assimilate...
(*sub3..): ...into this new insn.
(*sub3.zero_extend.): Use avr_out_plus_ext
for asm out.
* config/avr/avr-protos.h (avr_out_minus): Remove.
(avr_out_plus_ext): New proto.
gcc/testsuite/
* gcc.target/avr/torture/add-extend.c: New test.
* gcc.target/avr/torture/sub-extend.c: New test.

Diff:
---
 gcc/config/avr/avr-protos.h   |   2 +-
 gcc/config/avr/avr.cc | 107 +++--
 gcc/config/avr/avr.md | 264 ++
 gcc/testsuite/gcc.target/avr/torture/add-extend.c | 109 +
 gcc/testsuite/gcc.target/avr/torture/sub-extend.c | 109 +
 5 files changed, 377 insertions(+), 214 deletions(-)

diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index d3fa6c677232..5fdb13057570 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -96,7 +96,7 @@ extern void avr_output_addr_vec (rtx_insn*, rtx);
 extern const char *avr_out_sbxx_branch (rtx_insn *insn, rtx operands[]);
 extern const char* avr_out_bitop (rtx, rtx*, int*);
 extern const char* avr_out_plus (rtx, rtx*, int* =NULL, bool =true);
-extern const char* avr_out_minus (rtx*);
+extern const char* avr_out_plus_ext (rtx_insn*, rtx*, int*);
 extern const char* avr_out_round (rtx_insn *, rtx*, int* =NULL);
 extern const char* avr_out_addto_sp (rtx*, int*);
 extern const char* avr_out_xload (rtx_insn *, rtx*, int*);
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index d2a08c60c3ad..5fc046a310e5 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -8843,30 +8843,90 @@ lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
 }
 
 
-/* Output subtraction of integer registers XOP[0] and XOP[2] and return ""
+/* Output addition of registers YOP[0] and YOP[1]
 
-  XOP[0] = XOP[0] - XOP[2]
+  YOP[0] += extend (YOP[1])
 
-   where the mode of XOP[0] is in { HI, PSI, SI }, and the mode of
-   XOP[2] is in { QI, HI, PSI }.  When the mode of XOP[0] is larger
-   than the mode of XOP[2], then the latter is zero-extended on the fly.
-   The number of instructions will be the mode size of XOP[0].  */
+   or subtraction of registers YOP[0] and YOP[2]
+
+  YOP[0] -= extend (YOP[2])
+
+   where the integer modes satisfy  SI >= YOP[0].mode > YOP[1/2].mode >= QI,
+   and the extension may be sign- or zero-extend.  Returns "".
+
+   If PLEN == NULL output the instructions.
+   If PLEN != NULL set *PLEN to the length of the sequence in words.  */
 
 const char *
-avr_out_minus (rtx *xop)
+avr_out_plus_ext (rtx_insn *ins

[gcc r15-2073] AVR: testsuite - Add noipa function attribute to noclone functions.

2024-07-16 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:f8b302c98378b54e09c5f20cd6f6197871311da2

commit r15-2073-gf8b302c98378b54e09c5f20cd6f6197871311da2
Author: Georg-Johann Lay 
Date:   Tue Jul 16 17:33:18 2024 +0200

AVR: testsuite - Add noipa function attribute to noclone functions.

Many functions under test have the noinline and noclone function
attributes attached so that no (constant) values are propagated
into the functions, so that we actually are testing what's supposed
to be tested.  In order to enforce that, noipa may also be required
when inter-procedural analysis / optimizations are on.

gcc/testsuite/
* gcc.target/avr/isr-test.h: Add noipa function attribute
to noclone functions.
* gcc.target/avr/pr114981-powif.c: Same.
* gcc.target/avr/pr114981-powil.c: Same.
* gcc.target/avr/pr71676-1.c: Same.
* gcc.target/avr/pr71676-2.c: Same.
* gcc.target/avr/pr71676-3.c: Same.
* gcc.target/avr/pr71676.c: Same.
* gcc.target/avr/torture/fix-types.h: Same.
* gcc.target/avr/torture/fuse-add.c: Same.
* gcc.target/avr/torture/get-mem.c: Same.
* gcc.target/avr/torture/insv-anyshift-hi.c: Same.
* gcc.target/avr/torture/insv-anyshift-si.c: Same.
* gcc.target/avr/torture/isr-02-call.c: Same.
* gcc.target/avr/torture/isr-03-fixed.c: Same.
* gcc.target/avr/torture/pr109650-1.c: Same.
* gcc.target/avr/torture/pr109650-2.c: Same.
* gcc.target/avr/torture/pr109907-1.c: Same.
* gcc.target/avr/torture/pr109907-2.c: Same.
* gcc.target/avr/torture/pr114132-2.c: Same.
* gcc.target/avr/torture/pr39633.c: Same.
* gcc.target/avr/torture/pr51782-1.c: Same.
* gcc.target/avr/torture/pr61055.c: Same.
* gcc.target/avr/torture/pr61443.c: Same.
* gcc.target/avr/torture/pr64331.c: Same.
* gcc.target/avr/torture/pr77326.c: Same.
* gcc.target/avr/torture/pr83729.c: Same.
* gcc.target/avr/torture/pr83801.c: Same.
* gcc.target/avr/torture/pr87376.c: Same.
* gcc.target/avr/torture/pr88236-pr115726.c: Same.
* gcc.target/avr/torture/pr92606.c: Same.
* gcc.target/avr/torture/pr98762.c: Same.
* gcc.target/avr/torture/sat-hr-plus-minus.c: Same.
* gcc.target/avr/torture/sat-k-plus-minus.c: Same.
* gcc.target/avr/torture/sat-llk-plus-minus.c: Same.
* gcc.target/avr/torture/sat-r-plus-minus.c: Same.
* gcc.target/avr/torture/sat-uhr-plus-minus.c: Same.
* gcc.target/avr/torture/sat-uk-plus-minus.c: Same.
* gcc.target/avr/torture/sat-ullk-plus-minus.c: Same.
* gcc.target/avr/torture/sat-ur-plus-minus.c: Same.
* gcc.target/avr/torture/set-mem.c: Same.
* gcc.target/avr/torture/tiny-progmem.c: Same.

Diff:
---
 gcc/testsuite/gcc.target/avr/isr-test.h|  6 ++--
 gcc/testsuite/gcc.target/avr/pr114981-powif.c  |  2 +-
 gcc/testsuite/gcc.target/avr/pr114981-powil.c  |  2 +-
 gcc/testsuite/gcc.target/avr/pr71676-1.c   | 32 +++---
 gcc/testsuite/gcc.target/avr/pr71676-2.c   |  2 +-
 gcc/testsuite/gcc.target/avr/pr71676-3.c   |  2 +-
 gcc/testsuite/gcc.target/avr/pr71676.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/fix-types.h   |  8 +++---
 gcc/testsuite/gcc.target/avr/torture/fuse-add.c|  4 +--
 gcc/testsuite/gcc.target/avr/torture/get-mem.c |  2 +-
 .../gcc.target/avr/torture/insv-anyshift-hi.c  |  6 ++--
 .../gcc.target/avr/torture/insv-anyshift-si.c  |  4 +--
 gcc/testsuite/gcc.target/avr/torture/isr-02-call.c |  2 +-
 .../gcc.target/avr/torture/isr-03-fixed.c  |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr109650-1.c  |  4 +--
 gcc/testsuite/gcc.target/avr/torture/pr109650-2.c  |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr109907-1.c  |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr109907-2.c  |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr114132-2.c  |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr39633.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr51782-1.c   |  8 +++---
 gcc/testsuite/gcc.target/avr/torture/pr61055.c |  8 +++---
 gcc/testsuite/gcc.target/avr/torture/pr61443.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr64331.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr77326.c |  4 +--
 gcc/testsuite/gcc.target/avr/torture/pr83729.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr83801.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr87376.c | 10 +++
 .../gcc.target/avr/torture/pr88236-pr115726.c  | 10 +++
 gcc/testsuite/gcc.target/avr/torture/pr92606.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr98762.c |  2 +-
 .../gcc.target/avr/torture/sat-hr-plus-minus.c | 16 +--
 

[gcc r15-2075] AVR: testsuite - Attribute ipa implies noinline and noclone.

2024-07-16 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:a3d1469c7c7e152fa7a5dbc95dbc6d1f3792bbd8

commit r15-2075-ga3d1469c7c7e152fa7a5dbc95dbc6d1f3792bbd8
Author: Georg-Johann Lay 
Date:   Tue Jul 16 19:53:24 2024 +0200

AVR: testsuite - Attribute ipa implies noinline and noclone.

gcc/testsuite/
* gcc.target/avr/isr-test.h: Attribute ipa implies noinline and 
noclone.
* gcc.target/avr/pr114981-powif.c: Same.
* gcc.target/avr/pr114981-powil.c: Same.
* gcc.target/avr/pr71676-1.c: Same.
* gcc.target/avr/pr71676-2.c: Same.
* gcc.target/avr/pr71676-3.c: Same.
* gcc.target/avr/pr71676.c: Same.
* gcc.target/avr/torture/add-extend.c: Same.
* gcc.target/avr/torture/fix-types.h: Same.
* gcc.target/avr/torture/fuse-add.c: Same.
* gcc.target/avr/torture/get-mem.c: Same.
* gcc.target/avr/torture/insv-anyshift-hi.c: Same.
* gcc.target/avr/torture/insv-anyshift-si.c: Same.
* gcc.target/avr/torture/isr-02-call.c: Same.
* gcc.target/avr/torture/isr-03-fixed.c: Same.
* gcc.target/avr/torture/pr109650-1.c: Same.
* gcc.target/avr/torture/pr109650-2.c: Same.
* gcc.target/avr/torture/pr109907-1.c: Same.
* gcc.target/avr/torture/pr109907-2.c: Same.
* gcc.target/avr/torture/pr114132-2.c: Same.
* gcc.target/avr/torture/pr39633.c: Same.
* gcc.target/avr/torture/pr51782-1.c: Same.
* gcc.target/avr/torture/pr61055.c: Same.
* gcc.target/avr/torture/pr61443.c: Same.
* gcc.target/avr/torture/pr64331.c: Same.
* gcc.target/avr/torture/pr77326.c: Same.
* gcc.target/avr/torture/pr83729.c: Same.
* gcc.target/avr/torture/pr83801.c: Same.
* gcc.target/avr/torture/pr87376.c: Same.
* gcc.target/avr/torture/pr88236-pr115726.c: Same.
* gcc.target/avr/torture/pr92606.c: Same.
* gcc.target/avr/torture/pr98762.c: Same.
* gcc.target/avr/torture/sat-hr-plus-minus.c: Same.
* gcc.target/avr/torture/sat-k-plus-minus.c: Same.
* gcc.target/avr/torture/sat-llk-plus-minus.c: Same.
* gcc.target/avr/torture/sat-r-plus-minus.c: Same.
* gcc.target/avr/torture/sat-uhr-plus-minus.c: Same.
* gcc.target/avr/torture/sat-uk-plus-minus.c: Same.
* gcc.target/avr/torture/sat-ullk-plus-minus.c: Same.
* gcc.target/avr/torture/sat-ur-plus-minus.c: Same.
* gcc.target/avr/torture/set-mem.c: Same.
* gcc.target/avr/torture/sub-extend.c: Same.
* gcc.target/avr/torture/tiny-progmem.c: Same.

Diff:
---
 gcc/testsuite/gcc.target/avr/isr-test.h|  6 ++--
 gcc/testsuite/gcc.target/avr/pr114981-powif.c  |  2 +-
 gcc/testsuite/gcc.target/avr/pr114981-powil.c  |  2 +-
 gcc/testsuite/gcc.target/avr/pr71676-1.c   | 32 +++---
 gcc/testsuite/gcc.target/avr/pr71676-2.c   |  2 +-
 gcc/testsuite/gcc.target/avr/pr71676-3.c   |  2 +-
 gcc/testsuite/gcc.target/avr/pr71676.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/add-extend.c  |  2 +-
 gcc/testsuite/gcc.target/avr/torture/fix-types.h   |  8 +++---
 gcc/testsuite/gcc.target/avr/torture/fuse-add.c|  4 +--
 gcc/testsuite/gcc.target/avr/torture/get-mem.c |  2 +-
 .../gcc.target/avr/torture/insv-anyshift-hi.c  |  6 ++--
 .../gcc.target/avr/torture/insv-anyshift-si.c  |  4 +--
 gcc/testsuite/gcc.target/avr/torture/isr-02-call.c |  2 +-
 .../gcc.target/avr/torture/isr-03-fixed.c  |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr109650-1.c  |  4 +--
 gcc/testsuite/gcc.target/avr/torture/pr109650-2.c  |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr109907-1.c  |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr109907-2.c  |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr114132-2.c  |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr39633.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr51782-1.c   |  8 +++---
 gcc/testsuite/gcc.target/avr/torture/pr61055.c |  8 +++---
 gcc/testsuite/gcc.target/avr/torture/pr61443.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr64331.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr77326.c |  4 +--
 gcc/testsuite/gcc.target/avr/torture/pr83729.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr83801.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr87376.c | 10 +++
 .../gcc.target/avr/torture/pr88236-pr115726.c  | 10 +++
 gcc/testsuite/gcc.target/avr/torture/pr92606.c |  2 +-
 gcc/testsuite/gcc.target/avr/torture/pr98762.c |  2 +-
 .../gcc.target/avr/torture/sat-hr-plus-minus.c | 16 +--
 .../gcc.target/avr/torture/sat-k-plus-minus.c  | 16 +--
 .../gcc.target/avr/torture/sat-llk-plus-minus.c| 16 +--
 .../gcc.target/avr/torture/sat-r-plus-minus.c  | 16 ++

[gcc r15-2102] AVR: target/90616 - Improve adding constants that are 0 mod 256.

2024-07-17 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:e21fef7da92ef36af1e1b020ae5f35ef4f3c3fce

commit r15-2102-ge21fef7da92ef36af1e1b020ae5f35ef4f3c3fce
Author: Georg-Johann Lay 
Date:   Thu Jul 4 12:08:34 2024 +0200

AVR: target/90616 - Improve adding constants that are 0 mod 256.

This patch introduces a new insn that works as an insn combine
pattern for

   (plus:HI (zero_extend:HI (reg:QI))
(const_0mod256_operannd:HI))

which requires at most 2 instructions.  When the input register operand
is already in HImode, the addhi3 printer only adds the hi8 part when
it sees a SYMBOL_REF or CONST aligned to at least 256 bytes.
(The CONST_INT case was already handled).

gcc/
PR target/90616
* config/avr/predicates.md (const_0mod256_operand): New predicate.
* config/avr/constraints.md (Cp8): New constraint.
* config/avr/avr.md (*aligned_add_symbol): New insn.
* config/avr/avr.cc (avr_out_plus_symbol) [HImode]:
When op2 is a multiple of 256, there is no need to add / subtract
the lo8 part.
(avr_rtx_costs_1) [PLUS && HImode]: Return expected costs for
new insn *aligned_add_symbol as it applies.

Diff:
---
 gcc/config/avr/avr.cc | 14 ++
 gcc/config/avr/avr.md | 14 ++
 gcc/config/avr/constraints.md |  5 +
 gcc/config/avr/predicates.md  | 14 ++
 4 files changed, 47 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 5fc046a310e5..b9064424ffec 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -9434,6 +9434,12 @@ avr_out_plus_symbol (rtx *xop, enum rtx_code code, int 
*plen)
 
   gcc_assert (mode == HImode || mode == PSImode);
 
+  if (mode == HImode
+  && const_0mod256_operand (xop[2], HImode))
+return avr_asm_len (PLUS == code
+   ? "subi %B0,hi8(-(%2))"
+   : "subi %B0,hi8(%2)", xop, plen, -1);
+
   avr_asm_len (PLUS == code
   ? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
   : "subi %A0,lo8(%2)"CR_TAB "sbci %B0,hi8(%2)",
@@ -12759,6 +12765,14 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int 
outer_code,
  *total = COSTS_N_INSNS (3);
  return true;
}
+  // *aligned_add_symbol
+  if (mode == HImode
+ && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+ && const_0mod256_operand (XEXP (x, 1), HImode))
+   {
+ *total = COSTS_N_INSNS (1.5);
+ return true;
+   }
 
   // *add3.zero_extend.
   // *addhi3_zero_extend
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 695ff87f0c26..16adb7b85d93 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -1617,6 +1617,20 @@
   "subi %A0,%n2\;sbc %B0,%B0"
   [(set_attr "length" "2")])
 
+;; PR90616: Adding symbols that are aligned to 256 bytes can
+;; save up to two instructions.
+(define_insn "*aligned_add_symbol"
+  [(set (match_operand:HI 0 "register_operand" "=d")
+(plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
+ (match_operand:HI 2 "const_0mod256_operand"
"Cp8")))]
+  ""
+  {
+return REGNO (operands[0]) == REGNO (operands[1])
+  ? "ldi %B0,hi8(%2)"
+  : "mov %A0,%1\;ldi %B0,hi8(%2)";
+  }
+  [(set (attr "length")
+(symbol_ref ("2 - (REGNO (operands[0]) == REGNO (operands[1]))")))])
 
 ;; Occurs when computing offsets into 16-bit arrays.
 ;; Saves up to 2 instructions.
diff --git a/gcc/config/avr/constraints.md b/gcc/config/avr/constraints.md
index b4e5525d1978..35448614aa7a 100644
--- a/gcc/config/avr/constraints.md
+++ b/gcc/config/avr/constraints.md
@@ -253,6 +253,11 @@
   (and (match_code "const_int")
(match_test "IN_RANGE (ival, -255, -1)")))
 
+(define_constraint "Cp8"
+  "A constant integer or symbolic operand that is at least .p2align 8."
+  (and (match_code "const_int,symbol_ref,const")
+   (match_test "const_0mod256_operand (op, HImode)")))
+
 ;; CONST_FIXED is no element of 'n' so cook our own.
 ;; "i" or "s" would match but because the insn uses iterators that cover
 ;; INT_MODE, "i" or "s" is not always possible.
diff --git a/gcc/config/avr/predicates.md b/gcc/config/avr/predicates.md
index 12013660ed17..5b49481ff0f3 100644
--- a/gcc/config/avr/predicates.md
+++ b/gcc/config/avr/predicates.md
@@ -171,6 +171,20 @@
 (define_predicate "symbol_ref_operand"
   (match_code "symbol_ref"))
 
+;; Returns true when OP is a SYMBOL_REF, CONST or CONST_INT that is
+;; a multiple of 256, i.e. lo8(OP) = 0.
+(define_predicate "const_0mod256_operand"
+  (ior (and (match_code "symbol_ref")
+(match_test "SYMBOL_REF_DECL (op)
+ && DECL_P (SYMBOL_REF_DECL (op))
+ && DECL_ALIGN (SYMBOL_REF_DECL (op)) >= 8 * 256"))
+   (and (match_code "const")
+(match_test "GET_CODE (XEXP (op, 0)) == P

[gcc r15-2158] AVR: Support new built-in function __builtin_avr_mask1.

2024-07-19 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:9116490c1b03dac18f10e42df03731a3aed0b4e9

commit r15-2158-g9116490c1b03dac18f10e42df03731a3aed0b4e9
Author: Georg-Johann Lay 
Date:   Fri Jul 19 18:22:26 2024 +0200

AVR: Support new built-in function __builtin_avr_mask1.

gcc/
* config/avr/builtins.def (MASK1): New DEF_BUILTIN.
* config/avr/avr.cc (avr_rtx_costs_1): Handle rtx costs for
expressions like __builtin_avr_mask1.
(avr_init_builtins) : New tree type.
(avr_expand_builtin) [AVR_BUILTIN_MASK1]: Diagnose unexpected forms.
(avr_fold_builtin) [AVR_BUILTIN_MASK1]: Handle case.
* config/avr/avr.md (gen_mask1): New expand helper.
(mask1_0x01_split, mask1_0x80_split, mask1_0xfe_split): New
insn-and-split.
(*mask1_0x01, *mask1_0x80, *mask1_0xfe): New insns.
* doc/extend.texi (AVR Built-in Functions) <__builtin_avr_mask1>:
Document new built-in function.
gcc/testsuite/
* gcc.target/avr/torture/builtin-mask1.c: New test.

Diff:
---
 gcc/config/avr/avr.cc  |  62 +
 gcc/config/avr/avr.md  | 138 +
 gcc/config/avr/builtins.def|   1 +
 gcc/doc/extend.texi|  17 +++
 .../gcc.target/avr/torture/builtin-mask1.c | 118 ++
 5 files changed, 336 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index b9064424ffec..e941730452e5 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -13135,6 +13135,16 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int 
outer_code,
   switch (mode)
{
case E_QImode:
+ if (speed
+ && XEXP (x, 0) == const1_rtx
+ && GET_CODE (XEXP (x, 1)) == AND)
+   {
+ // "*mask1_0x01"
+ // Leave the space costs alone as they are smaller than 7 here.
+ *total = COSTS_N_INSNS (7);
+ return true;
+   }
+
  if (!CONST_INT_P (XEXP (x, 1)))
{
  *total = COSTS_N_INSNS (!speed ? 4 : 17);
@@ -13308,6 +13318,15 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int 
outer_code,
  break;
 
case E_HImode:
+ if (CONST_INT_P (XEXP (x, 0))
+ && INTVAL (XEXP (x, 0)) == 128
+ && GET_CODE (XEXP (x, 1)) == AND)
+   {
+ // "*mask1_0x80"
+ *total = COSTS_N_INSNS (7);
+ return true;
+   }
+
  if (!CONST_INT_P (XEXP (x, 1)))
{
  *total = COSTS_N_INSNS (!speed ? 5 : 41);
@@ -15796,6 +15815,11 @@ avr_init_builtins (void)
 = build_function_type_list (unsigned_intQI_type_node,
unsigned_intQI_type_node,
NULL_TREE);
+  tree uintQI_ftype_uintQI_uintQI
+= build_function_type_list (unsigned_intQI_type_node,
+   unsigned_intQI_type_node,
+   unsigned_intQI_type_node,
+   NULL_TREE);
   tree uintHI_ftype_uintQI_uintQI
 = build_function_type_list (unsigned_intHI_type_node,
unsigned_intQI_type_node,
@@ -16080,6 +16104,22 @@ avr_expand_builtin (tree exp, rtx target, rtx 
/*subtarget*/,
return NULL_RTX;
   }
 
+case AVR_BUILTIN_MASK1:
+  {
+   arg0 = CALL_EXPR_ARG (exp, 0);
+   op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+   int ival = CONST_INT_P (op0) ? 0xff & INTVAL (op0) : 0;
+
+   if (ival != 0x01 && ival != 0x7f && ival != 0x80 && ival != 0xfe)
+ {
+   error ("%s expects a compile time integer constant of 0x01, "
+  "0x7f, 0x80 or 0xfe as first argument", bname);
+   return target;
+ }
+
+   break;
+  }
+
 case AVR_BUILTIN_INSERT_BITS:
   {
arg0 = CALL_EXPR_ARG (exp, 0);
@@ -16247,6 +16287,28 @@ avr_fold_builtin (tree fndecl, int /*n_args*/, tree 
*arg, bool /*ignore*/)
 
   return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]);
 
+case AVR_BUILTIN_MASK1:
+  {
+   tree tmask = arg[0];
+   tree toffs = arg[1];
+
+   if (TREE_CODE (tmask) == INTEGER_CST
+   && TREE_CODE (toffs) == INTEGER_CST)
+ {
+   switch (0xff & TREE_INT_CST_LOW (tmask))
+ {
+ case 0x01:
+ case 0xfe:
+   return fold_build2 (LROTATE_EXPR, val_type, arg[0], toffs);
+
+ case 0x80:
+ case 0x7f:
+   return fold_build2 (RROTATE_EXPR, val_type, arg[0], toffs);
+ }
+ }
+   break;
+  } // AVR_BUILTIN_MASK1
+
 case AVR_BUILTIN_INSERT_BITS:
   {
tree tbits = arg[1];
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 16adb7b85d93..91a306f25228 100644
--- a/gcc/config/avr/avr.md
+++ b

[gcc r14-9410] AVR: Add cost computation for some insn combine patterns.

2024-03-09 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:e8cc1f956b75a6bf74c5f5262ddced9451dcccac

commit r14-9410-ge8cc1f956b75a6bf74c5f5262ddced9451dcccac
Author: Georg-Johann Lay 
Date:   Sat Mar 9 10:00:44 2024 +0100

AVR: Add cost computation for some insn combine patterns.

gcc/
* config/avr/avr.cc (avr_rtx_costs_1) [PLUS]: Determine cost for
usum_widenqihi and add_zero_extend1.
[MINUS]: Determine costs for udiff_widenqihi, sub+zero_extend,
sub+sign_extend.
* config/avr/avr.md (*addhi3.sign_extend1, *subhi3.sign_extend2):
Compute exact insn lengths.
(*usum_widenqihi3): Allow input operands to commute.

Diff:
---
 gcc/config/avr/avr.cc | 40 +++-
 gcc/config/avr/avr.md | 20 ++--
 2 files changed, 49 insertions(+), 11 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 1fa4b557f5d..00fce8da15f 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -12524,10 +12524,25 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int 
outer_code,
  return true;
}
 
+  // *usum_widenqihi
+  if (mode == HImode
+ && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+ && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
+   {
+ *total = COSTS_N_INSNS (3);
+ return true;
+   }
+
   if (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
  && REG_P (XEXP (x, 1)))
{
- *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) - 1);
+ *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
+ return true;
+   }
+  if (REG_P (XEXP (x, 0))
+ && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
+   {
+ *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
  return true;
}
 
@@ -12610,6 +12625,29 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int 
outer_code,
   return true;
 
 case MINUS:
+  // *udiff_widenqihi
+  if (mode == HImode
+ && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+ && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
+   {
+ *total = COSTS_N_INSNS (2);
+ return true;
+   }
+  // *sub3_zero_extend1
+  if (REG_P (XEXP (x, 0))
+ && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
+   {
+ *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
+ return true;
+   }
+  // *sub3.sign_extend2
+  if (REG_P (XEXP (x, 0))
+ && GET_CODE (XEXP (x, 1)) == SIGN_EXTEND)
+   {
+ *total = COSTS_N_INSNS (2 + GET_MODE_SIZE (mode));
+ return true;
+   }
+
   if (AVR_HAVE_MUL
  && QImode == mode
  && register_operand (XEXP (x, 0), QImode)
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 52b6cff4a8b..59ec724f7da 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -1588,12 +1588,10 @@
   ""
   "#"
   "&& reload_completed"
-  [(parallel
-  [(set (match_dup 0)
-(plus:HI
-  (sign_extend:HI (match_dup 1))
-  (match_dup 2)))
-   (clobber (reg:CC REG_CC))])])
+  [(parallel [(set (match_dup 0)
+   (plus:HI (sign_extend:HI (match_dup 1))
+(match_dup 2)))
+  (clobber (reg:CC REG_CC))])])
 
 
 (define_insn "*addhi3.sign_extend1"
@@ -1607,7 +1605,8 @@
   ? "mov __tmp_reg__,%1\;add %A0,%1\;adc %B0,__zero_reg__\;sbrc 
__tmp_reg__,7\;dec %B0"
   : "add %A0,%1\;adc %B0,__zero_reg__\;sbrc %1,7\;dec %B0";
   }
-  [(set_attr "length" "5")])
+  [(set (attr "length")
+(symbol_ref ("4 + reg_overlap_mentioned_p (operands[0], 
operands[1])")))])
 
 (define_insn_and_split "*addhi3_zero_extend.const_split"
   [(set (match_operand:HI 0 "register_operand" "=d")
@@ -1665,7 +1664,7 @@
 
 (define_insn_and_split "*usum_widenqihi3_split"
   [(set (match_operand:HI 0 "register_operand"  "=r")
-(plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand"  "0"))
+(plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0"))
  (zero_extend:HI (match_operand:QI 2 "register_operand"  
"r"]
   ""
   "#"
@@ -1678,7 +1677,7 @@
 
 (define_insn "*usum_widenqihi3"
   [(set (match_operand:HI 0 "register_operand"  "=r")
-(plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand"  "0"))
+(plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0"))
  (zero_extend:HI (match_operand:QI 2 "register_operand"  
"r"
(clobber (reg:CC REG_CC))]
   "reload_completed"
@@ -2186,7 +2185,8 @@
   ? "mov __tmp_reg__,%2\;sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc 
__tmp_reg__,7\;inc %B0"
   : "sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc %2,7\;inc %B0";
   }
-  [(set_attr "length" "5")])
+  [(set (attr "length")
+(symbol_ref ("4 + reg_overlap_mentioned_p (operands[0], 
operands[2])")))])
 
 ;; "subsi3"
 ;; "subsq3" "subusq3"


[gcc r14-9413] AVR: Fix typos in comment, indentation glitches in avr.md.

2024-03-09 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:f5a805d82902fe2d6e0a7af8c0e6519f9d25a8f3

commit r14-9413-gf5a805d82902fe2d6e0a7af8c0e6519f9d25a8f3
Author: Georg-Johann Lay 
Date:   Sat Mar 9 13:07:17 2024 +0100

AVR: Fix typos in comment, indentation glitches in avr.md.

gcc/
* config/avr/avr.md: Fix typos in comment, indentation glitches
and some other nits.

Diff:
---
 gcc/config/avr/avr.md | 87 +--
 1 file changed, 43 insertions(+), 44 deletions(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 59ec724f7da..bc408633eb5 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -31,7 +31,7 @@
 ;;  j  Branch condition.
 ;;  k  Reverse branch condition.
 ;;..m..Constant Direct Data memory address.
-;;  i  Print the SFR address quivalent of a CONST_INT or a CONST_INT
+;;  i  Print the SFR address equivalent of a CONST_INT or a CONST_INT
 ;; RAM address.  The resulting address is suitable to be used in IN/OUT.
 ;;  o  Displacement for (mem (plus (reg) (const_int))) operands.
 ;;  p  POST_INC or PRE_DEC address as a pointer (X, Y, Z)
@@ -475,7 +475,7 @@
 //  (reg:HI 28)))
 //(set (mem:HI (post_dec:HI (reg:HI 32 SP))
 // (reg:HI **)))
- 
+
 emit_insn (gen_pushhi1_insn (operands[0]));
 DONE;
   }
@@ -540,7 +540,7 @@
   "#"
   "&& reload_completed"
   [(parallel [(set (reg:MOVMODE 22)
-(match_dup 0))
+   (match_dup 0))
   (clobber (reg:CC REG_CC))])]
   ""
   [(set_attr "isa" "rjmp,jmp")])
@@ -576,7 +576,7 @@
   [(clobber (const_int 0))]
   {
 // Split away the high part of the address.  GCC's register allocator
-// in not able to allocate segment registers and reload the resulting
+// is not able to allocate segment registers and reload the resulting
 // expressions.  Notice that no address register can hold a PSImode.
 
 rtx addr = XEXP (operands[1], 0);
@@ -614,14 +614,13 @@
 rtx reg_z = gen_rtx_REG (HImode, REG_Z);
 rtx addr_hi8 = simplify_gen_subreg (QImode, addr, PSImode, 2);
 addr_space_t as = MEM_ADDR_SPACE (operands[1]);
-rtx_insn *insn;
 
 // Split the address to R21:Z
 emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
 emit_move_insn (gen_rtx_REG (QImode, 21), addr_hi8);
 
 // Load with code from libgcc.
-insn = emit_insn (gen_xload__libgcc ());
+rtx_insn *insn = emit_insn (gen_xload__libgcc ());
 set_mem_addr_space (SET_SRC (single_set (insn)), as);
 
 // Move to destination.
@@ -1704,7 +1703,7 @@
   "reload_completed"
   "sub %A0,%2\;sbc %B0,%B0"
   [(set_attr "length" "2")])
-
+
 (define_insn_and_split "*addhi3_sp"
   [(set (match_operand:HI 1 "stack_register_operand"   "=q")
 (plus:HI (match_operand:HI 2 "stack_register_operand"   "q")
@@ -2169,8 +2168,8 @@
   "#"
   "&& reload_completed"
   [(parallel [(set (match_dup 0)
-  (minus:HI (match_dup 1)
-(sign_extend:HI (match_dup 2
+   (minus:HI (match_dup 1)
+ (sign_extend:HI (match_dup 2
   (clobber (reg:CC REG_CC))])])
 
 
@@ -2506,7 +2505,7 @@
   "&& reload_completed"
   [(parallel [(set (reg:HI 24)
(mult:HI (zero_extend:HI (reg:QI 22))
-   (zero_extend:HI (reg:QI 24
+(zero_extend:HI (reg:QI 24
   (clobber (reg:QI 21))
   (clobber (reg:HI 22))
   (clobber (reg:CC REG_CC))])])
@@ -2890,7 +2889,7 @@
 
 ;; Special case of a += 2*b as frequently seen with accesses to int arrays.
 ;; This is shorter, faster than MUL and has lower register pressure.
-
+;; See also "*addhi3_zero_extend.ashift1".
 (define_insn_and_split "*umaddqihi4.2"
   [(set (match_operand:HI 0 "register_operand" 
 "=r")
 (plus:HI (mult:HI (zero_extend:HI (match_operand:QI 1 
"register_operand" "r"))
@@ -3356,12 +3355,14 @@
? "mul %A1,%A1\;movw %0,r0\;mul %A1,%B1\;add %B0,r0\;add 
%B0,r0\;clr r1"
: "mul %A1,%A2\;movw %0,r0\;mul %A1,%B2\;add %B0,r0\;mul 
%B1,%A2\;add %B0,r0\;clr r1";
   }
-  [(set_attr "length" "7")])
+  [(set (attr "length")
+(symbol_ref ("7 - (REGNO (operands[1]) == REGNO (operands[2]))")))])
 
 (define_expand "mulhi3_call"
   [(set (reg:HI 24) (match_operand:HI 1 "register_operand" ""))
(set (reg:HI 22) (match_operand:HI 2 "register_operand" ""))
-   (parallel [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
+   (parallel [(set (reg:HI 24)
+   (mult:HI (reg:HI 24) (reg:HI 22)))
   (clobber (reg:HI 22))
   (clobber (reg:QI 21))])
(set (match_operand:HI 0 "register_operand" "")
@@ -3373,19 +3374,22 @@
 
 
 (define_insn_and_split "*mulhi3_call_split"
-  [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
+  [(set (reg:HI 2

[gcc r14-9514] avr.md - Tweak xor insn constraints.

2024-03-18 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:9361f19e081294b04e16ac2f6056b3b910f27ff4

commit r14-9514-g9361f19e081294b04e16ac2f6056b3b910f27ff4
Author: Georg-Johann Lay 
Date:   Mon Mar 18 08:50:02 2024 +0100

avr.md - Tweak xor insn constraints.

xor insn can handle some more values without the requirement of a
scratch register.  This patch adds a new constraint alternative for
such values.  The output function avr_out_bitop already handles
these cases, so no change is needed there.

gcc/
* config/avr/constraints.md (CX2, CX3, CX4): New constraints.
* config/avr/avr-protos.h (avr_xor_noclobber_dconst): New proto.
* config/avr/avr.cc (avr_xor_noclobber_dconst): New function.
* config/avr/avr.md (xorhi3, *xorhi3): Add "d,0,CX2,X" alternative.
(xorpsi3, *xorpsi3): Add "d,0,CX3,X" alternative.
(xorsi3, *xorsi3): Add "d,0,CX4,X" alternative.

Diff:
---
 gcc/config/avr/avr-protos.h   |  1 +
 gcc/config/avr/avr.cc | 25 ++
 gcc/config/avr/avr.md | 60 +--
 gcc/config/avr/constraints.md | 17 +++-
 4 files changed, 72 insertions(+), 31 deletions(-)

diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index bb680312117..dc23cfbf461 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -101,6 +101,7 @@ extern const char* avr_out_xload (rtx_insn *, rtx*, int*);
 extern const char* avr_out_cpymem (rtx_insn *, rtx*, int*);
 extern const char* avr_out_insert_bits (rtx*, int*);
 extern bool avr_popcount_each_byte (rtx, int, int);
+extern bool avr_xor_noclobber_dconst (rtx, int);
 extern bool avr_has_nibble_0xf (rtx);
 
 extern int extra_constraint_Q (rtx x);
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 00fce8da15f..12c59668b4c 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -281,6 +281,31 @@ avr_popcount_each_byte (rtx xval, int n_bytes, int 
pop_mask)
 }
 
 
+/* Constraint helper function.  XVAL is a CONST_INT.  Return true if we
+   can perform XOR without a clobber reg, provided the operation is on
+   a d-register.  This means each byte is in { 0, 0xff, 0x80 }.  */
+
+bool
+avr_xor_noclobber_dconst (rtx xval, int n_bytes)
+{
+  machine_mode mode = GET_MODE (xval);
+
+  if (VOIDmode == mode)
+mode = SImode;
+
+  for (int i = 0; i < n_bytes; ++i)
+{
+  rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
+  unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
+
+  if (val8 != 0 && val8 != 0xff && val8 != 0x80)
+   return false;
+}
+
+  return true;
+}
+
+
 /* Access some RTX as INT_MODE.  If X is a CONST_FIXED we can get
the bit representation of X by "casting" it to CONST_INT.  */
 
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index bc408633eb5..97f42be7729 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -4741,10 +4741,10 @@
   [(set_attr "length" "1")])
 
 (define_insn_and_split "xorhi3"
-  [(set (match_operand:HI 0 "register_operand"   "=??r,r  ,r")
-(xor:HI (match_operand:HI 1 "register_operand" "%0,0  ,0")
-(match_operand:HI 2 "nonmemory_operand" "r,Cx2,n")))
-   (clobber (match_scratch:QI 3"=X,X  ,&d"))]
+  [(set (match_operand:HI 0 "register_operand"   "=??r,r  ,d  ,r")
+(xor:HI (match_operand:HI 1 "register_operand" "%0,0  ,0  ,0")
+(match_operand:HI 2 "nonmemory_operand" "r,Cx2,CX2,n")))
+   (clobber (match_scratch:QI 3"=X,X  ,X  ,&d"))]
   ""
   "#"
   "&& reload_completed"
@@ -4755,10 +4755,10 @@
   (clobber (reg:CC REG_CC))])])
 
 (define_insn "*xorhi3"
-  [(set (match_operand:HI 0 "register_operand"   "=??r,r  ,r")
-(xor:HI (match_operand:HI 1 "register_operand" "%0,0  ,0")
-(match_operand:HI 2 "nonmemory_operand" "r,Cx2,n")))
-   (clobber (match_scratch:QI 3"=X,X  ,&d"))
+  [(set (match_operand:HI 0 "register_operand"   "=??r,r  ,d  ,r")
+(xor:HI (match_operand:HI 1 "register_operand" "%0,0  ,0  ,0")
+(match_operand:HI 2 "nonmemory_operand" "r,Cx2,CX2,n")))
+   (clobber (match_scratch:QI 3"=X,X  ,X  ,&d"))
(clobber (reg:CC REG_CC))]
   "reload_completed"
   {
@@ -4767,14 +4767,14 @@
 
 return avr_out_bitop (insn, operands, NULL);
   }
-  [(set_attr "length" "2,2,4")
-   (set_attr "adjust_len" "*,out_bitop,out_bitop")])
+  [(set_attr "length" "2,2,4,4")
+   (set_attr "adjust_len" "*,out_bitop,out_bitop,out_bitop")])
 
 (define_insn_and_split "xorpsi3"
-  [(set (match_operand:PSI 0 "register_operand""=??r,r  ,r")
-(xor:PSI (match_operand:PSI 1 "register_operand" "%0,0  ,0")
- (match_operand:PSI 2 "nonmemory_operand" "r,Cx3,n")))
-   (clobber (match_scratch:QI 3  "=X,X  ,&d"))]
+  [(set (match_operand:PSI 0 "register_

[gcc r14-9630] AVR: Adjust message for SIGNAL and INTERRUPT usage

2024-03-22 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:65b7d1862e11784a0ce67ab758e06dd8aa65b181

commit r14-9630-g65b7d1862e11784a0ce67ab758e06dd8aa65b181
Author: Georg-Johann Lay 
Date:   Fri Mar 22 17:29:21 2024 +0100

AVR: Adjust message for SIGNAL and INTERRUPT usage

gcc/
* config/avr/avr.cc (avr_set_current_function): Adjust diagnostic
for deprecated SIGNAL and INTERRUPT usage without respective header.

Diff:
---
 gcc/config/avr/avr.cc | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 12c59668b4c..4a5a921107b 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -1495,14 +1495,20 @@ avr_set_current_function (tree decl)
   // Common problem is using "ISR" without first including avr/interrupt.h.
   const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
   name = default_strip_name_encoding (name);
-  if (strcmp ("ISR", name) == 0
-  || strcmp ("INTERRUPT", name) == 0
-  || strcmp ("SIGNAL", name) == 0)
+  if (strcmp ("ISR", name) == 0)
 {
   warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved identifier"
  " in AVR-LibC.  Consider %<#include %>"
  " before using the %qs macro", name, name);
 }
+  if (strcmp ("INTERRUPT", name) == 0
+  || strcmp ("SIGNAL", name) == 0)
+{
+  warning_at (loc, OPT_Wmisspelled_isr, "%qs is a deprecated identifier"
+ " in AVR-LibC.  Consider %<#include %>"
+ " or %<#include %>"
+ " before using the %qs macro", name, name);
+}
 #endif // AVR-LibC naming conventions
 
   /* Don't print the above diagnostics more than once.  */


[gcc r14-9977] AVR: Add 8 more avrxmega3 MCUs.

2024-04-15 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:6e11bb451babfe47bb6b7ad42335019f2771a32e

commit r14-9977-g6e11bb451babfe47bb6b7ad42335019f2771a32e
Author: Georg-Johann Lay 
Date:   Mon Apr 15 19:23:32 2024 +0200

AVR: Add 8 more avrxmega3 MCUs.

gcc/
* config/avr/avr-mcus.def: Add: avr16du14, avr16du20, avr16du28,
avr16du32, avr32du14, avr32du20, avr32du28,  avr32du32.
* doc/avr-mmcu.texi: Rebuild.

Diff:
---
 gcc/config/avr/avr-mcus.def | 8 
 gcc/doc/avr-mmcu.texi   | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/gcc/config/avr/avr-mcus.def b/gcc/config/avr/avr-mcus.def
index 27812d441f7..068875a2c60 100644
--- a/gcc/config/avr/avr-mcus.def
+++ b/gcc/config/avr/avr-mcus.def
@@ -379,6 +379,10 @@ AVR_MCU ("avr16dd14",ARCH_AVRXMEGA3, AVR_ISA_NONE, 
 "__AVR_AVR16DD14__",
 AVR_MCU ("avr16dd20",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DD20__",   0x7800, 0x0, 0x4000, 0x8000)
 AVR_MCU ("avr16dd28",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DD28__",   0x7800, 0x0, 0x4000, 0x8000)
 AVR_MCU ("avr16dd32",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DD32__",   0x7800, 0x0, 0x4000, 0x8000)
+AVR_MCU ("avr16du14",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DU14__",   0x7800, 0x0, 0x4000, 0x8000)
+AVR_MCU ("avr16du20",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DU20__",   0x7800, 0x0, 0x4000, 0x8000)
+AVR_MCU ("avr16du28",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DU28__",   0x7800, 0x0, 0x4000, 0x8000)
+AVR_MCU ("avr16du32",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DU32__",   0x7800, 0x0, 0x4000, 0x8000)
 AVR_MCU ("avr32da28",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DA28__",   0x7000, 0x0, 0x8000, 0x8000)
 AVR_MCU ("avr32da32",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DA32__",   0x7000, 0x0, 0x8000, 0x8000)
 AVR_MCU ("avr32da48",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DA48__",   0x7000, 0x0, 0x8000, 0x8000)
@@ -389,6 +393,10 @@ AVR_MCU ("avr32dd14",ARCH_AVRXMEGA3, AVR_ISA_NONE, 
 "__AVR_AVR32DD14__",
 AVR_MCU ("avr32dd20",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DD20__",   0x7000, 0x0, 0x8000, 0x8000)
 AVR_MCU ("avr32dd28",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DD28__",   0x7000, 0x0, 0x8000, 0x8000)
 AVR_MCU ("avr32dd32",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DD32__",   0x7000, 0x0, 0x8000, 0x8000)
+AVR_MCU ("avr32du14",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DU14__",   0x7000, 0x0, 0x8000, 0x8000)
+AVR_MCU ("avr32du20",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DU20__",   0x7000, 0x0, 0x8000, 0x8000)
+AVR_MCU ("avr32du28",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DU28__",   0x7000, 0x0, 0x8000, 0x8000)
+AVR_MCU ("avr32du32",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DU32__",   0x7000, 0x0, 0x8000, 0x8000)
 AVR_MCU ("avr16eb14",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16EB14__",   0x7800, 0x0, 0x4000, 0x8000)
 AVR_MCU ("avr16eb20",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16EB20__",   0x7800, 0x0, 0x4000, 0x8000)
 AVR_MCU ("avr16eb28",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16EB28__",   0x7800, 0x0, 0x4000, 0x8000)
diff --git a/gcc/doc/avr-mmcu.texi b/gcc/doc/avr-mmcu.texi
index dcbf4ef7247..671e66e7ffb 100644
--- a/gcc/doc/avr-mmcu.texi
+++ b/gcc/doc/avr-mmcu.texi
@@ -54,7 +54,7 @@
 
 @item @anchor{avrxmega3}avrxmega3
 ``XMEGA'' devices with up to 64@tie{}KiB of combined program memory and RAM, 
and with program memory visible in the RAM address space.
-@*@var{mcu}@tie{}= @code{attiny202}, @code{attiny204}, @code{attiny212}, 
@code{attiny214}, @code{attiny402}, @code{attiny404}, @code{attiny406}, 
@code{attiny412}, @code{attiny414}, @code{attiny416}, @code{attiny416auto}, 
@code{attiny417}, @code{attiny424}, @code{attiny426}, @code{attiny427}, 
@code{attiny804}, @code{attiny806}, @code{attiny807}, @code{attiny814}, 
@code{attiny816}, @code{attiny817}, @code{attiny824}, @code{attiny826}, 
@code{attiny827}, @code{attiny1604}, @code{attiny1606}, @code{attiny1607}, 
@code{attiny1614}, @code{attiny1616}, @code{attiny1617}, @code{attiny1624}, 
@code{attiny1626}, @code{attiny1627}, @code{attiny3214}, @code{attiny3216}, 
@code{attiny3217}, @code{attiny3224}, @code{attiny3226}, @code{attiny3227}, 
@code{atmega808}, @code{atmega809}, @code{atmega1608}, @code{atmega1609}, 
@code{atmega3208}, @code{atmega3209}, @code{atmega4808}, @code{atmega4809}, 
@code{avr16dd14}, @code{avr16dd20}, @code{avr16dd28}, @code{avr16dd32}, 
@code{avr16ea28}, @code{avr16ea32},
  @code{avr16ea48}, @code{avr16eb14}, @code{avr16eb20}, @code{avr16eb28}, 
@code{avr16eb32}, @code{avr32da28}, @code{avr32da32}, @code{avr32da48}, 
@code{avr32db28}, @code{avr32db32}, @code{avr32db48}, @code{avr32dd14}, 
@code{avr32dd20}, @code{avr32dd28}, @code{avr32dd32}, @code{avr32ea28}, 
@code{avr32ea32}, @code{avr32ea48}.
+@*@var{mcu}@tie{}= @code{attiny202}, @code{attiny204}, @code{attiny212}, 
@code{atti

[gcc r13-8611] AVR: Add 8 more avrxmega3 MCUs.

2024-04-15 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:f585f8f9081ddecad63fa654297811e434613e6c

commit r13-8611-gf585f8f9081ddecad63fa654297811e434613e6c
Author: Georg-Johann Lay 
Date:   Mon Apr 15 19:23:32 2024 +0200

AVR: Add 8 more avrxmega3 MCUs.

gcc/
* config/avr/avr-mcus.def: Add: avr16du14, avr16du20, avr16du28,
avr16du32, avr32du14, avr32du20, avr32du28,  avr32du32.
* doc/avr-mmcu.texi: Rebuild.

(cherry picked from commit 6e11bb451babfe47bb6b7ad42335019f2771a32e)

Diff:
---
 gcc/config/avr/avr-mcus.def | 8 
 gcc/doc/avr-mmcu.texi   | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/gcc/config/avr/avr-mcus.def b/gcc/config/avr/avr-mcus.def
index 2e01281c900..d869f8720f2 100644
--- a/gcc/config/avr/avr-mcus.def
+++ b/gcc/config/avr/avr-mcus.def
@@ -379,6 +379,10 @@ AVR_MCU ("avr16dd14",ARCH_AVRXMEGA3, AVR_ISA_NONE, 
 "__AVR_AVR16DD14__",
 AVR_MCU ("avr16dd20",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DD20__",   0x7800, 0x0, 0x4000, 0x8000)
 AVR_MCU ("avr16dd28",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DD28__",   0x7800, 0x0, 0x4000, 0x8000)
 AVR_MCU ("avr16dd32",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DD32__",   0x7800, 0x0, 0x4000, 0x8000)
+AVR_MCU ("avr16du14",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DU14__",   0x7800, 0x0, 0x4000, 0x8000)
+AVR_MCU ("avr16du20",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DU20__",   0x7800, 0x0, 0x4000, 0x8000)
+AVR_MCU ("avr16du28",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DU28__",   0x7800, 0x0, 0x4000, 0x8000)
+AVR_MCU ("avr16du32",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16DU32__",   0x7800, 0x0, 0x4000, 0x8000)
 AVR_MCU ("avr32da28",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DA28__",   0x7000, 0x0, 0x8000, 0x8000)
 AVR_MCU ("avr32da32",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DA32__",   0x7000, 0x0, 0x8000, 0x8000)
 AVR_MCU ("avr32da48",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DA48__",   0x7000, 0x0, 0x8000, 0x8000)
@@ -389,6 +393,10 @@ AVR_MCU ("avr32dd14",ARCH_AVRXMEGA3, AVR_ISA_NONE, 
 "__AVR_AVR32DD14__",
 AVR_MCU ("avr32dd20",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DD20__",   0x7000, 0x0, 0x8000, 0x8000)
 AVR_MCU ("avr32dd28",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DD28__",   0x7000, 0x0, 0x8000, 0x8000)
 AVR_MCU ("avr32dd32",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DD32__",   0x7000, 0x0, 0x8000, 0x8000)
+AVR_MCU ("avr32du14",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DU14__",   0x7000, 0x0, 0x8000, 0x8000)
+AVR_MCU ("avr32du20",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DU20__",   0x7000, 0x0, 0x8000, 0x8000)
+AVR_MCU ("avr32du28",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DU28__",   0x7000, 0x0, 0x8000, 0x8000)
+AVR_MCU ("avr32du32",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR32DU32__",   0x7000, 0x0, 0x8000, 0x8000)
 AVR_MCU ("avr16eb14",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16EB14__",   0x7800, 0x0, 0x4000, 0x8000)
 AVR_MCU ("avr16eb20",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16EB20__",   0x7800, 0x0, 0x4000, 0x8000)
 AVR_MCU ("avr16eb28",ARCH_AVRXMEGA3, AVR_ISA_NONE,  
"__AVR_AVR16EB28__",   0x7800, 0x0, 0x4000, 0x8000)
diff --git a/gcc/doc/avr-mmcu.texi b/gcc/doc/avr-mmcu.texi
index 748243c296a..50c7d3fa94d 100644
--- a/gcc/doc/avr-mmcu.texi
+++ b/gcc/doc/avr-mmcu.texi
@@ -54,7 +54,7 @@
 
 @item avrxmega3
 ``XMEGA'' devices with up to 64@tie{}KiB of combined program memory and RAM, 
and with program memory visible in the RAM address space.
-@*@var{mcu}@tie{}= @code{attiny202}, @code{attiny204}, @code{attiny212}, 
@code{attiny214}, @code{attiny402}, @code{attiny404}, @code{attiny406}, 
@code{attiny412}, @code{attiny414}, @code{attiny416}, @code{attiny416auto}, 
@code{attiny417}, @code{attiny424}, @code{attiny426}, @code{attiny427}, 
@code{attiny804}, @code{attiny806}, @code{attiny807}, @code{attiny814}, 
@code{attiny816}, @code{attiny817}, @code{attiny824}, @code{attiny826}, 
@code{attiny827}, @code{attiny1604}, @code{attiny1606}, @code{attiny1607}, 
@code{attiny1614}, @code{attiny1616}, @code{attiny1617}, @code{attiny1624}, 
@code{attiny1626}, @code{attiny1627}, @code{attiny3214}, @code{attiny3216}, 
@code{attiny3217}, @code{attiny3224}, @code{attiny3226}, @code{attiny3227}, 
@code{atmega808}, @code{atmega809}, @code{atmega1608}, @code{atmega1609}, 
@code{atmega3208}, @code{atmega3209}, @code{atmega4808}, @code{atmega4809}, 
@code{avr16dd14}, @code{avr16dd20}, @code{avr16dd28}, @code{avr16dd32}, 
@code{avr16ea28}, @code{avr16ea32},
  @code{avr16ea48}, @code{avr16eb14}, @code{avr16eb20}, @code{avr16eb28}, 
@code{avr16eb32}, @code{avr32da28}, @code{avr32da32}, @code{avr32da48}, 
@code{avr32db28}, @code{avr32db32}, @code{avr32db48}, @code{avr32dd14}, 
@code{avr32dd20}, @code{avr32dd28}, @code{avr32dd32}, @code{avr32ea28}, 
@code{avr32ea32}, @code{avr32ea48}.
+@*@var{mcu}@tie{}= @code

[gcc r14-10003] AVR: target/114752 - Fix ICE on inline asm const 64-bit float operand

2024-04-17 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:909c6faf2c726178d115726e56304eac91cff6e9

commit r14-10003-g909c6faf2c726178d115726e56304eac91cff6e9
Author: Georg-Johann Lay 
Date:   Wed Apr 17 10:26:05 2024 +0200

AVR: target/114752 - Fix ICE on inline asm const 64-bit float operand

gcc/
PR target/114752
* config/avr/avr.cc (avr_print_operand) [CONST_DOUBLE_P]: Handle 
DFmode.

Diff:
---
 gcc/config/avr/avr.cc | 17 +
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 4a5a921107b..510e4cea19f 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -3932,11 +3932,20 @@ avr_print_operand (FILE *file, rtx x, int code)
 }
   else if (CONST_DOUBLE_P (x))
 {
-  long val;
-  if (GET_MODE (x) != SFmode)
+  if (GET_MODE (x) == SFmode)
+   {
+ long val;
+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
+ fprintf (file, "0x%lx", val);
+   }
+  else if (GET_MODE (x) == DFmode)
+   {
+ long l[2];
+ REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (x), l);
+ fprintf (file, "0x%lx%08lx", l[1] & 0x, l[0] & 0x);
+   }
+  else
fatal_insn ("internal compiler error.  Unknown mode:", x);
-  REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
-  fprintf (file, "0x%lx", val);
 }
   else if (GET_CODE (x) == CONST_STRING)
 fputs (XSTR (x, 0), file);


[gcc r13-8616] AVR: target/114752 - Fix ICE on inline asm const 64-bit float operand

2024-04-17 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:ca7d454804045a39d10a9b1f691a940aeacdf25b

commit r13-8616-gca7d454804045a39d10a9b1f691a940aeacdf25b
Author: Georg-Johann Lay 
Date:   Wed Apr 17 10:26:05 2024 +0200

AVR: target/114752 - Fix ICE on inline asm const 64-bit float operand

gcc/
PR target/114752
* config/avr/avr.cc (avr_print_operand) [CONST_DOUBLE_P]: Handle 
DFmode.

(cherry picked from commit 909c6faf2c726178d115726e56304eac91cff6e9)

Diff:
---
 gcc/config/avr/avr.cc | 19 ++-
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index d91fa51e78c..f8c4eb327a2 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -,11 +,20 @@ avr_print_operand (FILE *file, rtx x, int code)
 }
   else if (CONST_DOUBLE_P (x))
 {
-  long val;
-  if (GET_MODE (x) != SFmode)
-fatal_insn ("internal compiler error.  Unknown mode:", x);
-  REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
-  fprintf (file, "0x%lx", val);
+  if (GET_MODE (x) == SFmode)
+   {
+ long val;
+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
+ fprintf (file, "0x%lx", val);
+   }
+  else if (GET_MODE (x) == DFmode)
+   {
+ long l[2];
+ REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (x), l);
+ fprintf (file, "0x%lx%08lx", l[1] & 0x, l[0] & 0x);
+   }
+  else
+   fatal_insn ("internal compiler error.  Unknown mode:", x);
 }
   else if (GET_CODE (x) == CONST_STRING)
 fputs (XSTR (x, 0), file);


[gcc r14-10058] AVR: target/114794 - Tweak __udivmodqi4

2024-04-21 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:a44d16efa7a508f8b8f303417d0714c39f159725

commit r14-10058-ga44d16efa7a508f8b8f303417d0714c39f159725
Author: Georg-Johann Lay 
Date:   Sun Apr 21 14:33:50 2024 +0200

AVR: target/114794 - Tweak __udivmodqi4

libgcc/
PR target/114794
* config/avr/lib1funcs.S (__udivmodqi4): Tweak.

Diff:
---
 libgcc/config/avr/lib1funcs.S | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index 535510ab867..af4d7d97016 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -1339,9 +1339,9 @@ ENDF __umulsidi3
 
 #if defined (L_udivmodqi4)
 DEFUN __udivmodqi4
-   sub r_rem,r_rem ; clear remainder and carry
-   ldi r_cnt,9 ; init loop counter
-   rjmp__udivmodqi4_ep ; jump to entry point
+   clr r_rem   ; clear remainder
+   ldi r_cnt,8 ; init loop counter
+   lsl r_arg1  ; shift dividend
 __udivmodqi4_loop:
rol r_rem   ; shift dividend into remainder
cp  r_rem,r_arg2; compare remainder & divisor


[gcc r13-8638] AVR: target/114794 - Tweak __udivmodqi4

2024-04-21 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:7bd8428da72a0a1d3bef4e50be4b60b981ed540d

commit r13-8638-g7bd8428da72a0a1d3bef4e50be4b60b981ed540d
Author: Georg-Johann Lay 
Date:   Sun Apr 21 14:33:50 2024 +0200

AVR: target/114794 - Tweak __udivmodqi4

libgcc/
PR target/114794
* config/avr/lib1funcs.S (__udivmodqi4): Tweak.

(cherry picked from commit a44d16efa7a508f8b8f303417d0714c39f159725)

Diff:
---
 libgcc/config/avr/lib1funcs.S | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index 0870595111a..4ee651bf6ea 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -1339,9 +1339,9 @@ ENDF __umulsidi3
 
 #if defined (L_udivmodqi4)
 DEFUN __udivmodqi4
-   sub r_rem,r_rem ; clear remainder and carry
-   ldi r_cnt,9 ; init loop counter
-   rjmp__udivmodqi4_ep ; jump to entry point
+   clr r_rem   ; clear remainder
+   ldi r_cnt,8 ; init loop counter
+   lsl r_arg1  ; shift dividend
 __udivmodqi4_loop:
rol r_rem   ; shift dividend into remainder
cp  r_rem,r_arg2; compare remainder & divisor


[gcc r15-2367] AVR target 116056 - Support attribute signal(n), interrupt(n) and noblock.

2024-07-28 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:0f1de0c4ce6eb237128d8f6439c2434aded1f51a

commit r15-2367-g0f1de0c4ce6eb237128d8f6439c2434aded1f51a
Author: Georg-Johann Lay 
Date:   Wed Jul 24 08:37:43 2024 +0200

AVR target 116056 - Support attribute signal(n), interrupt(n) and noblock.

This patch adds support for arguments to the signal and interrupt
function attributes.  It allows to specify the ISR by means of the
associated IRQ number, in extension to the current attributes that
require to specify the ISR name like "__vector_1" as (assembly) name
for the function.  The new feature is more convenient, e.g. when the
ISR is implemented by a class method or in a namespace.  There is no
requirement that the ISR is externally visible.  The syntax is like:

__attribute__((signal(1, 2, ...), signal(3, 4, ...)))
[static] void isr_function (void)
{
// Code
}

Moreover, this patch adds support for the "noblock" function attribute
to let an ISR start with a SEI instruction.  Attribute "signal" together
with "noblock" behaves like "interrupt" but without imposing a specific
function name or visibility like "interrupt" does.

PR target/116056
gcc/
* config/avr/avr.h (machine_function) : New field.
* config/avr/avr-c.cc (avr_cpu_cpp_builtins) <__HAVE_SIGNAL_N__>: 
New
built-in macro.
* config/avr/avr.cc (avr_declare_function_name): New function.
(avr_attribute_table) : New function attribute>.
: Allow any number of args.
(avr_insert_attributes): Check validity of "signal" and "interrupt"
arguments.
(avr_foreach_function_attribute, avr_interrupt_signal_function)
(avr_isr_number, avr_asm_isr_alias, avr_handle_isr_attribute)
(avr_noblock_function_p): New static functions.
(avr_interrupt_function): New from avr_interrupt_function_p.
Adjust callers.
(avr_signal_function): New from avr_signal_function_p.
Adjust callers.
(avr_set_current_function): Only diagnose non-__vector ISR names
when "signal" or "interrupt" attribute has no args. Set
cfun->machine->is_noblock.  Warn about "noblock" in non-ISR 
functions.
(struct avr_fun_cookie): New.
(avr_expand_prologue, avr_asm_function_end_prologue): Handle 
"noblock".
* config/avr/elf.h (ASM_DECLARE_FUNCTION_NAME): New define.
* config/avr/avr-protos.h (avr_declare_function_name): New proto.
* doc/extend.texi (AVR Function Attributes): Document
signal(num) and interrupt(num).
* doc/invoke.texi (AVR Built-in Macros) <__HAVE_SIGNAL_N__>: 
Document.
gcc/testsuite/
* gcc.target/avr/torture/signal_n-1.c: New test.
* gcc.target/avr/torture/signal_n-2.c: New test.
* gcc.target/avr/torture/signal_n-3.c: New test.
* gcc.target/avr/torture/signal_n-4.cpp: New test.

Diff:
---
 gcc/config/avr/avr-c.cc|   4 +
 gcc/config/avr/avr-protos.h|   1 +
 gcc/config/avr/avr.cc  | 226 ++---
 gcc/config/avr/avr.h   |  18 +-
 gcc/config/avr/elf.h   |   4 +
 gcc/doc/extend.texi|  38 
 gcc/doc/invoke.texi|   7 +
 gcc/testsuite/gcc.target/avr/torture/signal_n-1.c  |  49 +
 gcc/testsuite/gcc.target/avr/torture/signal_n-2.c  |  32 +++
 gcc/testsuite/gcc.target/avr/torture/signal_n-3.c  |  13 ++
 .../gcc.target/avr/torture/signal_n-4.cpp  |  53 +
 11 files changed, 413 insertions(+), 32 deletions(-)

diff --git a/gcc/config/avr/avr-c.cc b/gcc/config/avr/avr-c.cc
index 5e7f759ed738..ca484f26132a 100644
--- a/gcc/config/avr/avr-c.cc
+++ b/gcc/config/avr/avr-c.cc
@@ -391,6 +391,10 @@ avr_cpu_cpp_builtins (struct cpp_reader *pfile)
   cpp_define (pfile, "__WITH_AVRLIBC__");
 #endif /* WITH_AVRLIBC */
 
+  // We support __attribute__((signal/interrupt (n1, n2, ...)[, noblock]))
+  cpp_define (pfile, "__HAVE_SIGNAL_N__");
+
+
   // From configure --with-libf7={|libgcc|math|math-symbols|yes|no}
 
 #ifdef WITH_LIBF7_LIBGCC
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 5fdb13057570..7b666f17718d 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -35,6 +35,7 @@ extern void avr_init_expanders (void);
 #ifdef TREE_CODE
 extern void avr_asm_output_aligned_decl_common (FILE*, tree, const char*, 
unsigned HOST_WIDE_INT, unsigned int, bool);
 extern void avr_asm_asm_output_aligned_bss (FILE *, tree, const char *, 
unsigned HOST_WIDE_INT, int, void (*) (FILE *, tree, const char *, unsigned 
HOST_WIDE_INT, int));
+extern void avr_declare_function_name (FILE *, const char *, tree);
 extern void asm_output_external (FI

[gcc r15-2382] AVR: avr.cc - Fix a typo in a diagnostic.

2024-07-29 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:3bc79863eb8483ab1a396e1d6131361a5195780f

commit r15-2382-g3bc79863eb8483ab1a396e1d6131361a5195780f
Author: Georg-Johann Lay 
Date:   Mon Jul 29 18:02:58 2024 +0200

AVR: avr.cc - Fix a typo in a diagnostic.

gcc/
* config/avr/avr.cc (avr_set_current_function): Fix typo in
error message.

Diff:
---
 gcc/config/avr/avr.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index dffb7e056bec..7229aac747bd 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -1540,7 +1540,7 @@ avr_set_current_function (tree decl)
{
  error_at (loc, "%qs function cannot have arguments", isr);
  if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
-   inform (loc, "method %qs has an inplicit % argument", name);
+   inform (loc, "method %qs has an implicit % argument", name);
}
 
   if (TREE_CODE (ret) != VOID_TYPE)


[gcc r15-2400] AVR: Propose to use attribute signal(n) via AVR-LibC's ISR_N.

2024-07-30 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:922083693136be9516b9f916fd5139f419f8

commit r15-2400-g922083693136be9516b9f916fd5139f419f8
Author: Georg-Johann Lay 
Date:   Tue Jul 30 09:16:02 2024 +0200

AVR: Propose to use attribute signal(n) via AVR-LibC's ISR_N.

gcc/
* doc/extend.texi (AVR Function Attributes): Propose to use
attribute signal(n) via AVR-LibC's ISR_N from avr/interrupt.h

Diff:
---
 gcc/doc/extend.texi | 30 +++---
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 927aa24ab635..48b27ff9f390 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -5147,22 +5147,38 @@ the attribute, rather than providing the ISR name 
itself as the function name:
 
 @example
 __attribute__((signal(1)))
-void my_handler (void)
+static void my_handler (void)
 @{
// Code for __vector_1
 @}
+@end example
 
-#include 
+Notice that the handler function needs not to be externally visible.
+The recommended way to use these attributes is by means of the
+@code{ISR_N} macro provided by @code{avr/interrupt.h} from
+@w{@uref{https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html,,AVR-LibC}}:
+
+@example
+#include 
 
-__attribute__((__signal__(PCINT0_vect_num, PCINT1_vect_num)))
-static void my_pcint0_1_handler (void)
+ISR_N (PCINT0_vect_num)
+static void my_pcint0_handler (void)
 @{
-   // Code for PCINT0 and PCINT1 (__vector_3 and __vector_4
-   // on ATmega328).
+   // Code
+@}
+
+ISR_N (ADC_vect_num, ISR_NOBLOCK)
+static void my_adc_handler (void)
+@{
+// Code
 @}
 @end example
 
-Notice that the handler function needs not to be externally visible.
+@code{ISR_N} can be specified more than once, in which case several
+interrupt vectors are pointing to the same handler function.  This
+is similar to the @code{ISR_ALIASOF} macro provided by AVR-LibC, but
+without the overhead introduced by @code{ISR_ALIASOF}.
+
 
 @cindex @code{noblock} function attribute, AVR
 @item noblock


[gcc r15-2474] AVR: Tweak register pressure for const_fixed compares against "M".

2024-08-01 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:d0504847970d89d5dd7bd689ca8f7bf82fedf522

commit r15-2474-gd0504847970d89d5dd7bd689ca8f7bf82fedf522
Author: Georg-Johann Lay 
Date:   Thu Aug 1 09:58:48 2024 +0200

AVR: Tweak register pressure for const_fixed compares against "M".

When comparing a 16-bit or 32-bit integer against a constant in
the range 0...0xff, constraint M is used because no scratch reg
is needed in that case.  Same can be done for fixed-point compares.

gcc/
* config/avr/constraints.md (YMM): New constraint.
* config/avr/avr.md (cmp3, *cmp3)
(cbranch4_insn): Allow YMM where M is allowed.

Diff:
---
 gcc/config/avr/avr.md | 28 ++--
 gcc/config/avr/constraints.md |  7 +++
 2 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 91a306f25228..02d0a4156513 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -6568,9 +6568,9 @@
 ;; "cmpha3" "cmpuha3"
 (define_insn "cmp3"
   [(set (reg:CC REG_CC)
-(compare:CC (match_operand:ALL2 0 "register_operand"  "!w  ,r  ,r,d ,r 
 ,d,r")
-(match_operand:ALL2 1 "nonmemory_operand"  "Y00,Y00,r,s ,s 
 ,M,n Ynn")))
-   (clobber (match_scratch:QI 2   "=X  ,X  
,X,&d,&d ,X,&d"))]
+(compare:CC (match_operand:ALL2 0 "register_operand"  "!w  ,r  ,r,d ,r 
,d,r")
+(match_operand:ALL2 1 "nonmemory_operand"  "Y00,Y00,r,s ,s 
,M YMM,n Ynn")))
+   (clobber (match_scratch:QI 2   "=X  ,X  
,X,&d,&d,X,&d"))]
   "reload_completed"
   {
 switch (which_alternative)
@@ -6635,9 +6635,9 @@
 ;; "*cmpsa" "*cmpusa"
 (define_insn "*cmp"
   [(set (reg:CC REG_CC)
-(compare:CC (match_operand:ALL4 0 "register_operand"  "r  ,r ,d,r ,r")
-(match_operand:ALL4 1 "nonmemory_operand" "Y00,r ,M,M ,n 
Ynn")))
-   (clobber (match_scratch:QI 2  "=X  ,X 
,X,&d,&d"))]
+(compare:CC (match_operand:ALL4 0 "register_operand"  "r  ,r ,d,r")
+(match_operand:ALL4 1 "nonmemory_operand" "Y00,r ,M YMM,n 
Ynn")))
+   (clobber (match_scratch:QI 2  "=X  ,X ,X
,&d"))]
   "reload_completed"
   {
 if (0 == which_alternative)
@@ -6647,8 +6647,8 @@
 
 return avr_out_compare (insn, operands, NULL);
   }
-  [(set_attr "length" "4,4,4,5,8")
-   (set_attr "adjust_len" "tstsi,*,compare,compare,compare")])
+  [(set_attr "length" "4,4,4,8")
+   (set_attr "adjust_len" "tstsi,*,compare,compare")])
 
 
 ;; A helper for avr_pass_ifelse::avr_rest_of_handle_ifelse().
@@ -6727,11 +6727,11 @@
   [(set (pc)
 (if_then_else
  (match_operator 0 "ordered_comparison_operator"
-   [(match_operand:ALL4 1 "register_operand"  "r  ,r,d,r ,r")
-(match_operand:ALL4 2 "nonmemory_operand" "Y00,r,M,M ,n Ynn")])
+   [(match_operand:ALL4 1 "register_operand"  "r  ,r,d ,r")
+(match_operand:ALL4 2 "nonmemory_operand" "Y00,r,M YMM ,n Ynn")])
  (label_ref (match_operand 3))
  (pc)))
-   (clobber (match_scratch:QI 4  "=X  ,X,X,&d,&d"))]
+   (clobber (match_scratch:QI 4  "=X  ,X,X ,&d"))]
""
"#"
"reload_completed"
@@ -6772,11 +6772,11 @@
   [(set (pc)
 (if_then_else
  (match_operator 0 "ordered_comparison_operator"
-   [(match_operand:ALL2 1 "register_operand" "!w  ,r  ,r,d ,r ,d,r")
-(match_operand:ALL2 2 "nonmemory_operand" "Y00,Y00,r,s ,s ,M,n 
Ynn")])
+   [(match_operand:ALL2 1 "register_operand" "!w  ,r  ,r,d ,r ,d
,r")
+(match_operand:ALL2 2 "nonmemory_operand" "Y00,Y00,r,s ,s ,M YMM,n 
Ynn")])
  (label_ref (match_operand 3))
  (pc)))
-   (clobber (match_scratch:QI 4  "=X  ,X  ,X,&d,&d,X,&d"))]
+   (clobber (match_scratch:QI 4  "=X  ,X  ,X,&d,&d,X
,&d"))]
""
"#"
"reload_completed"
diff --git a/gcc/config/avr/constraints.md b/gcc/config/avr/constraints.md
index 35448614aa7a..963e23a4d9ed 100644
--- a/gcc/config/avr/constraints.md
+++ b/gcc/config/avr/constraints.md
@@ -313,6 +313,13 @@
   (and (match_code "const_fixed")
(match_test "IN_RANGE (INTVAL (avr_to_int_mode (op)), -63, 63)")))
 
+;; Similar to "M", but for CONST_FIXED.
+
+(define_constraint "YMM"
+  "Fixed-point constant in the range 0 @dots{} 0xff when viewed as CONST_INT."
+  (and (match_code "const_fixed")
+   (match_test "IN_RANGE (INTVAL (avr_to_int_mode (op)), 0, 0xff)")))
+
 (define_constraint "Yil"
   "Memory in the lower half of the I/O space."
   (and (match_code "mem")


[gcc r15-2475] AVR: Tweak unsigned comparisons against 256 resp. 65536.

2024-08-01 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:3e4c47d1088417db599a0793a6d93707228e4f70

commit r15-2475-g3e4c47d1088417db599a0793a6d93707228e4f70
Author: Georg-Johann Lay 
Date:   Thu Aug 1 10:21:53 2024 +0200

AVR: Tweak unsigned comparisons against 256 resp. 65536.

u16 >= 256 can be performed by testing the hi8 part against 0.
u32 >= 65536 can be performed by testing the high word against 0.
The optimization is performed in split2 after register allocation
because the register allocator likely spills for subregs.

gcc/
* config/avr/avr.md (cbranch4_insn): Split to a test of the
high part against 0 if possible.

Diff:
---
 gcc/config/avr/avr.md | 36 ++--
 1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 02d0a4156513..fce5349bbe5f 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -6742,7 +6742,23 @@
  (if_then_else (match_op_dup 0
  [(reg:CC REG_CC) (const_int 0)])
(label_ref (match_dup 3))
-   (pc)))])
+   (pc)))]
+   {
+ // Unsigned >= 65536 and < 65536 can be performed by testing the
+ // high word against 0.
+ if ((GET_CODE (operands[0]) == LTU
+  || GET_CODE (operands[0]) == GEU)
+ && const_operand (operands[2], mode)
+ && INTVAL (avr_to_int_mode (operands[2])) == 65536)
+   {
+ // "cmphi3" of the high word against 0.
+ operands[0] = copy_rtx (operands[0]);
+ PUT_CODE (operands[0], GET_CODE (operands[0]) == GEU ? NE : EQ);
+ operands[1] = simplify_gen_subreg (HImode, operands[1], mode, 
2);
+ operands[2] = const0_rtx;
+ operands[4] = gen_rtx_SCRATCH (QImode);
+   }
+   })
 
 ;; "cbranchpsi4_insn"
 (define_insn_and_split "cbranchpsi4_insn"
@@ -6787,7 +6803,23 @@
  (if_then_else (match_op_dup 0
  [(reg:CC REG_CC) (const_int 0)])
(label_ref (match_dup 3))
-   (pc)))])
+   (pc)))]
+   {
+ // Unsigned >= 256 and < 256 can be performed by testing the
+ // high byte against 0.
+ if ((GET_CODE (operands[0]) == LTU
+  || GET_CODE (operands[0]) == GEU)
+ && const_operand (operands[2], mode)
+ && INTVAL (avr_to_int_mode (operands[2])) == 256)
+   {
+ rtx_code code = GET_CODE (operands[0]) == GEU ? NE : EQ;
+ rtx hi8 = simplify_gen_subreg (QImode, operands[1], mode, 1);
+ rtx cmp = gen_rtx_fmt_ee (code, VOIDmode, cc_reg_rtx, const0_rtx);
+ emit (gen_cmpqi3 (hi8, const0_rtx));
+ emit (gen_branch (operands[3], cmp));
+ DONE;
+   }
+   })
 
 ;; Combiner pattern to compare sign- or zero-extended register against
 ;; a wider register, like comparing uint8_t against uint16_t.


[gcc r15-2836] AVR: Improve POST_INC output in some rare cases.

2024-08-08 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:ef697f83917e6380e979c196b330ad8ad84b8ce0

commit r15-2836-gef697f83917e6380e979c196b330ad8ad84b8ce0
Author: Georg-Johann Lay 
Date:   Thu Aug 8 16:50:39 2024 +0200

AVR: Improve POST_INC output in some rare cases.

gcc/
* config/avr/avr.cc (avr_insn_has_reg_unused_note_p): New function.
(_reg_unused_after): Use it to recognize more cases.
(avr_out_lpm_no_lpmx) [POST_INC]: Use reg_unused_after.

Diff:
---
 gcc/config/avr/avr.cc | 32 +++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 7229aac747bd..0b3fd7a36d00 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -4621,7 +4621,7 @@ avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
avr_asm_len ("mov %0,r0", ®, plen, 1);
}
 
-  if (! _reg_unused_after (insn, xop[2], false))
+  if (! reg_unused_after (insn, xop[2]))
avr_asm_len ("adiw %2,1", xop, plen, 1);
 
   break; /* POST_INC */
@@ -11318,6 +11318,25 @@ avr_adjust_insn_length (rtx_insn *insn, int len)
   return len;
 }
 
+
+/* Return true when INSN has a REG_UNUSED note for hard reg REG.
+   rtlanal.cc::find_reg_note() uses == to compare XEXP (link, 0)
+   therefore use a custom function.  */
+
+static bool
+avr_insn_has_reg_unused_note_p (rtx_insn *insn, rtx reg)
+{
+  for (rtx link = REG_NOTES (insn); link; link = XEXP (link, 1))
+if (REG_NOTE_KIND (link) == REG_UNUSED
+   && REG_P (XEXP (link, 0))
+   && REGNO (reg) >= REGNO (XEXP (link, 0))
+   && END_REGNO (reg) <= END_REGNO (XEXP (link, 0)))
+  return true;
+
+  return false;
+}
+
+
 /* Return nonzero if register REG dead after INSN.  */
 
 int
@@ -11344,6 +11363,17 @@ _reg_unused_after (rtx_insn *insn, rtx reg, bool 
look_at_insn)
   if (set && !MEM_P (SET_DEST (set))
  && reg_overlap_mentioned_p (reg, SET_DEST (set)))
return 1;
+
+  /* This case occurs when fuse-add introduced a POST_INC addressing,
+but the address register is unused after.  */
+  if (set)
+   {
+ rtx mem = MEM_P (SET_SRC (set)) ? SET_SRC (set) : SET_DEST (set);
+ if (MEM_P (mem)
+ && reg_overlap_mentioned_p (reg, XEXP (mem, 0))
+ && avr_insn_has_reg_unused_note_p (insn, reg))
+   return 1;
+   }
 }
 
   while ((insn = NEXT_INSN (insn)))


[gcc r15-2837] AVR: Fix a typo in __builtin_avr_mask1 documentation.

2024-08-08 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:f6a41ebb5b45be22959afba2fa2b5cf42450378a

commit r15-2837-gf6a41ebb5b45be22959afba2fa2b5cf42450378a
Author: Georg-Johann Lay 
Date:   Thu Aug 8 16:54:52 2024 +0200

AVR: Fix a typo in __builtin_avr_mask1 documentation.

gcc/
* doc/extend.texi (AVR Built-in Functions) : Fix a typo.

Diff:
---
 gcc/doc/extend.texi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 89fe5db7aed0..ae1ada3cdf8e 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -17052,7 +17052,7 @@ __builtin_avr_insert_bits (0x01234567, bits, 0);
 @defbuiltin{uint8_t __builtin_avr_mask1 (uint8_t @var{mask}, uint8_t 
@var{offs})}
 Rotate the 8-bit constant value @var{mask} by an offset of @var{offs},
 where @var{mask} is in @{ 0x01, 0xfe, 0x7f, 0x80 @}.
-This built-in can be use as an alternative to 8-bit expressions like
+This built-in can be used as an alternative to 8-bit expressions like
 @code{1 << offs} when their computation consumes too much
 time, and @var{offs} is known to be in the range 0@dots{}7.
 @example


[gcc r15-2838] AVR: target/116295 - Fix unrecognizable insn with __flash read.

2024-08-08 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:c4d3dba253b49fb0e8e32109783f76453bc53653

commit r15-2838-gc4d3dba253b49fb0e8e32109783f76453bc53653
Author: Georg-Johann Lay 
Date:   Thu Aug 8 18:31:16 2024 +0200

AVR: target/116295 - Fix unrecognizable insn with __flash read.

Some loads from non-generic address-spaces are performed by
libgcc calls, and they don't have a POST_INC form.  Don't consider
such insns when running -mfuse-add.

 PR target/116295
gcc/
* config/avr/avr.cc (Mem_Insn::Mem_Insn): Don't consider MEMs
that are avr_mem_memx_p or avr_load_libgcc_p.

gcc/testsuite/
* gcc.target/avr/torture/pr116295.c: New test.

Diff:
---
 gcc/config/avr/avr.cc   |  4 
 gcc/testsuite/gcc.target/avr/torture/pr116295.c | 22 ++
 2 files changed, 26 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 0b3fd7a36d00..5cfd67a8e742 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -2121,6 +2121,10 @@ avr_pass_fuse_add::Mem_Insn::Mem_Insn (rtx_insn *insn)
   else
 return;
 
+  if (avr_mem_memx_p (mem)
+  || avr_load_libgcc_p (mem))
+return;
+
   addr = XEXP (mem, 0);
   addr_code = GET_CODE (addr);
 
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr116295.c 
b/gcc/testsuite/gcc.target/avr/torture/pr116295.c
new file mode 100644
index ..0b3d380ff147
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr116295.c
@@ -0,0 +1,22 @@
+/* { dg-do link } */
+/* { dg-additional-options "-std=gnu99" } */
+
+#ifdef __FLASH
+
+long val;
+
+__attribute__((used))
+const __flash long*
+load4_flash (const __flash long *p)
+{
+val += *p++;
+val += *p++;
+return p;
+}
+
+#endif
+
+int main (void)
+{
+   return 0;
+}


[gcc r14-10573] AVR: target/116295 - Fix unrecognizable insn with __flash read.

2024-08-08 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:9ca1d7a36abecee7da387ceb1c07d77eaad15927

commit r14-10573-g9ca1d7a36abecee7da387ceb1c07d77eaad15927
Author: Georg-Johann Lay 
Date:   Thu Aug 8 18:31:16 2024 +0200

AVR: target/116295 - Fix unrecognizable insn with __flash read.

Some loads from non-generic address-spaces are performed by
libgcc calls, and they don't have a POST_INC form.  Don't consider
such insns when running -mfuse-add.

PR target/116295
gcc/
* config/avr/avr.cc (Mem_Insn::Mem_Insn): Don't consider MEMs
that are avr_mem_memx_p or avr_load_libgcc_p.

gcc/testsuite/
* gcc.target/avr/torture/pr116295.c: New test.

(cherry picked from commit c4d3dba253b49fb0e8e32109783f76453bc53653)

Diff:
---
 gcc/config/avr/avr.cc   |  4 
 gcc/testsuite/gcc.target/avr/torture/pr116295.c | 22 ++
 2 files changed, 26 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index b41592ff1a32..71929b281605 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -2052,6 +2052,10 @@ avr_pass_fuse_add::Mem_Insn::Mem_Insn (rtx_insn *insn)
   else
 return;
 
+  if (avr_mem_memx_p (mem)
+  || avr_load_libgcc_p (mem))
+return;
+
   addr = XEXP (mem, 0);
   addr_code = GET_CODE (addr);
 
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr116295.c 
b/gcc/testsuite/gcc.target/avr/torture/pr116295.c
new file mode 100644
index ..0b3d380ff147
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr116295.c
@@ -0,0 +1,22 @@
+/* { dg-do link } */
+/* { dg-additional-options "-std=gnu99" } */
+
+#ifdef __FLASH
+
+long val;
+
+__attribute__((used))
+const __flash long*
+load4_flash (const __flash long *p)
+{
+val += *p++;
+val += *p++;
+return p;
+}
+
+#endif
+
+int main (void)
+{
+   return 0;
+}


[gcc r15-2844] AVR: Tidy up code for __[x]load insns.

2024-08-09 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:a90c74ab161eab09802920fbd894bf55bc4fa797

commit r15-2844-ga90c74ab161eab09802920fbd894bf55bc4fa797
Author: Georg-Johann Lay 
Date:   Fri Aug 9 12:15:28 2024 +0200

AVR: Tidy up code for __[x]load insns.

gcc/
* config/avr/avr.md (*load__libgcc, *xload__libgcc):
Tidy up code.

Diff:
---
 gcc/config/avr/avr.md | 30 +-
 1 file changed, 9 insertions(+), 21 deletions(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index fce5349bbe5f..84dfe4c40ecf 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -536,7 +536,7 @@
 ;; "load_sf_libgcc"
 (define_insn_and_split "load__libgcc"
   [(set (reg:MOVMODE 22)
-(match_operand:MOVMODE 0 "memory_operand" "m,m"))]
+(match_operand:MOVMODE 0 "memory_operand" "m"))]
   "avr_load_libgcc_p (operands[0])
&& REG_P (XEXP (operands[0], 0))
&& REG_Z == REGNO (XEXP (operands[0], 0))"
@@ -544,24 +544,18 @@
   "&& reload_completed"
   [(parallel [(set (reg:MOVMODE 22)
(match_dup 0))
-  (clobber (reg:CC REG_CC))])]
-  ""
-  [(set_attr "isa" "rjmp,jmp")])
+  (clobber (reg:CC REG_CC))])])
 
 (define_insn "*load__libgcc"
   [(set (reg:MOVMODE 22)
-(match_operand:MOVMODE 0 "memory_operand" "m,m"))
+(match_operand:MOVMODE 0 "memory_operand" "m"))
(clobber (reg:CC REG_CC))]
   "avr_load_libgcc_p (operands[0])
&& REG_P (XEXP (operands[0], 0))
&& REG_Z == REGNO (XEXP (operands[0], 0))
&& reload_completed"
-  {
-operands[0] = GEN_INT ();
-return "%~call __load_%0";
-  }
-  [(set_attr "length" "1,2")
-   (set_attr "isa" "rjmp,jmp")])
+  "%~call __load_"
+  [(set_attr "type" "xcall")])
 
 
 ;; "xload8qi_A"
@@ -657,7 +651,6 @@
 ;; "xload_si_libgcc" "xload_sq_libgcc" "xload_usq_libgcc" "xload_sa_libgcc" 
"xload_usa_libgcc"
 ;; "xload_sf_libgcc"
 ;; "xload_psi_libgcc"
-
 (define_insn_and_split "xload__libgcc"
   [(set (reg:MOVMODE 22)
 (mem:MOVMODE (lo_sum:PSI (reg:QI 21)
@@ -668,8 +661,8 @@
   "#"
   "&& reload_completed"
   [(parallel [(set (reg:MOVMODE 22)
-  (mem:MOVMODE (lo_sum:PSI (reg:QI 21)
-   (reg:HI REG_Z
+   (mem:MOVMODE (lo_sum:PSI (reg:QI 21)
+(reg:HI REG_Z
   (clobber (reg:CC REG_CC))])])
 
 (define_insn "*xload__libgcc"
@@ -679,12 +672,7 @@
(clobber (reg:CC REG_CC))]
   "avr_xload_libgcc_p (mode)
&& reload_completed"
-  {
-rtx x_bytes = GEN_INT ();
-
-output_asm_insn ("%~call __xload_%0", &x_bytes);
-return "";
-  }
+  "%~call __xload_"
   [(set_attr "type" "xcall")])
 
 
@@ -2278,7 +2266,7 @@
   [(set (match_operand:PSI 0 "register_operand" "=r")
 (plus:PSI (lshiftrt:PSI (match_operand:PSI 1 "register_operand"  "r")
 (const_int 23))
- (match_operand:PSI 2 "register_operand" 
"0")))]
+  (match_operand:PSI 2 "register_operand"
"0")))]
   ""
   "#"
   "&& reload_completed"


[gcc r15-2872] AVR: Add function avr.cc::ra_in_progress().

2024-08-11 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:29a323676913600b448e011c7d27df01aa20c6dc

commit r15-2872-g29a323676913600b448e011c7d27df01aa20c6dc
Author: Georg-Johann Lay 
Date:   Sun Aug 11 15:18:22 2024 +0200

AVR: Add function avr.cc::ra_in_progress().

It returns lra_in_progress resp. reload_in_progress depending on avr_lra_p.
Currently, direct use of ra_in_progress() is only made with -mlog=.

gcc/
* config/avr/avr.cc (ra_in_progress): New static function.
(avr_legitimate_address_p, avr_addr_space_legitimate_address_p)
(extra_constraint_Q): Use it with -mlog=.

Diff:
---
 gcc/config/avr/avr.cc | 19 +--
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 27df4bc41468..8d59a6babedf 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -330,6 +330,13 @@ avr_adiw_reg_p (rtx reg)
 }
 
 
+static bool
+ra_in_progress ()
+{
+  return avr_lra_p ? lra_in_progress : reload_in_progress;
+}
+
+
 namespace {
 
 static const pass_data avr_pass_data_recompute_notes =
@@ -3560,8 +3567,8 @@ avr_legitimate_address_p (machine_mode mode, rtx x, bool 
strict)
   if (avr_log.legitimate_address_p)
 {
   avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
-"reload_completed=%d reload_in_progress=%d %s:",
-ok, mode, strict, reload_completed, reload_in_progress,
+"reload_completed=%d ra_in_progress=%d %s:",
+ok, mode, strict, reload_completed, ra_in_progress (),
 reg_renumber ? "(reg_renumber)" : "");
 
   if (GET_CODE (x) == PLUS
@@ -13973,8 +13980,8 @@ extra_constraint_Q (rtx x)
|| xx == arg_pointer_rtx);
 
   if (avr_log.constraints)
-   avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
-  ok, reload_completed, reload_in_progress, x);
+   avr_edump ("\n%?=%d reload_completed=%d ra_in_progress=%d\n %r\n",
+  ok, reload_completed, ra_in_progress (), x);
 }
 
   return ok;
@@ -15038,8 +15045,8 @@ avr_addr_space_legitimate_address_p (machine_mode mode, 
rtx x, bool strict,
   if (avr_log.legitimate_address_p)
 {
   avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
-"reload_completed=%d reload_in_progress=%d %s:",
-ok, mode, strict, reload_completed, reload_in_progress,
+"reload_completed=%d ra_in_progress=%d %s:",
+ok, mode, strict, reload_completed, ra_in_progress (),
 reg_renumber ? "(reg_renumber)" : "");
 
   if (GET_CODE (x) == PLUS


[gcc r15-2873] AVR: -mlra is not documeted in TEXI.

2024-08-11 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:149a23ee2568ce1efcfb4cb7704ecc97d4c32274

commit r15-2873-g149a23ee2568ce1efcfb4cb7704ecc97d4c32274
Author: Georg-Johann Lay 
Date:   Sun Aug 11 15:36:07 2024 +0200

AVR: -mlra is not documeted in TEXI.

gcc/
* config/avr/avr.opt (mlra): Set Undocumented flag.

Diff:
---
 gcc/config/avr/avr.opt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/config/avr/avr.opt b/gcc/config/avr/avr.opt
index 947489eddf08..444ed7edb26b 100644
--- a/gcc/config/avr/avr.opt
+++ b/gcc/config/avr/avr.opt
@@ -19,7 +19,7 @@
 ; .
 
 mlra
-Target Var(avr_lra_p) UInteger Init(0) Optimization
+Target Var(avr_lra_p) UInteger Init(0) Optimization Undocumented
 Usa LRA for reload instead of the old reload framework.  This option is 
experimental, and it may be removed in future versions of the compiler.
 
 mcall-prologues


[gcc r15-2888] AVR: target/85624 - Fix non-matching alignment in clrmem* insns.

2024-08-12 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:68da681e614c2750f648dac2cd0b2595999ca5d9

commit r15-2888-g68da681e614c2750f648dac2cd0b2595999ca5d9
Author: Georg-Johann Lay 
Date:   Mon Aug 12 14:39:24 2024 +0200

AVR: target/85624 - Fix non-matching alignment in clrmem* insns.

The clrmem* patterns don't use the provided alignment information,
hence the setmemhi expander can just pass down 0 as alignment to
the clrmem* insns.

PR target/85624
gcc/
* config/avr/avr.md (setmemhi): Set alignment to 0.

gcc/testsuite/
* gcc.target/avr/torture/pr85624.c: New test.

Diff:
---
 gcc/config/avr/avr.md  | 2 ++
 gcc/testsuite/gcc.target/avr/torture/pr85624.c | 7 +++
 2 files changed, 9 insertions(+)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 84dfe4c40ecf..359343e563d5 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -1355,6 +1355,8 @@
 gen_int_mode (INTVAL (operands[1]), mode));
 rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
 operands[0] = gen_rtx_MEM (BLKmode, addr0);
+// Alignment is unused; just set it to 0.
+operands[3] = const0_rtx;
   })
 
 
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr85624.c 
b/gcc/testsuite/gcc.target/avr/torture/pr85624.c
new file mode 100644
index ..b183d4558df7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr85624.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+
+int foo (void)
+{
+  volatile int arr[3] __attribute__((aligned(128))) = { 0 };
+  return arr[2];
+}


[gcc r14-10595] AVR: target/85624 - Use HImode for clrmemqi alignment.

2024-08-16 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:507b4e147588c0fafe952b7226dd764ebeebb103

commit r14-10595-g507b4e147588c0fafe952b7226dd764ebeebb103
Author: Georg-Johann Lay 
Date:   Fri Aug 16 18:13:34 2024 +0200

AVR: target/85624 - Use HImode for clrmemqi alignment.

gcc/
PR target/85624
* config/avr/avr.md (*clrmemqi*): Use HImode for alignment operand.

gcc/testsuite/
* gcc.target/avr/torture/pr85624.c: New test.

Diff:
---
 gcc/config/avr/avr.md  | 4 ++--
 gcc/testsuite/gcc.target/avr/torture/pr85624.c | 7 +++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index dabf4c0fc5a..55de11079c3 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -1374,7 +1374,7 @@
   [(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
 (const_int 0))
(use (match_operand:QI 1 "register_operand" "r"))
-   (use (match_operand:QI 2 "const_int_operand" "n"))
+   (use (match_operand:HI 2 "const_int_operand" "n"))
(clobber (match_scratch:HI 3 "=0"))
(clobber (match_scratch:QI 4 "=&1"))]
   ""
@@ -1392,7 +1392,7 @@
   [(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
 (const_int 0))
(use (match_operand:QI 1 "register_operand" "r"))
-   (use (match_operand:QI 2 "const_int_operand" "n"))
+   (use (match_operand:HI 2 "const_int_operand" "n"))
(clobber (match_scratch:HI 3 "=0"))
(clobber (match_scratch:QI 4 "=&1"))
(clobber (reg:CC REG_CC))]
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr85624.c 
b/gcc/testsuite/gcc.target/avr/torture/pr85624.c
new file mode 100644
index 000..b183d4558df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr85624.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+
+int foo (void)
+{
+  volatile int arr[3] __attribute__((aligned(128))) = { 0 };
+  return arr[2];
+}


[gcc r15-2956] AVR: target/85624 - Use HImode for clrmemqi alignment.

2024-08-16 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:c8981bde45d365330a5e7c2e33c8dbaf3495248a

commit r15-2956-gc8981bde45d365330a5e7c2e33c8dbaf3495248a
Author: Georg-Johann Lay 
Date:   Fri Aug 16 18:13:34 2024 +0200

AVR: target/85624 - Use HImode for clrmemqi alignment.

gcc/
PR target/85624
* config/avr/avr.md (*clrmemqi*): Use HImode for alignment operand.

(cherry picked from commit 507b4e147588c0fafe952b7226dd764ebeebb103)

Diff:
---
 gcc/config/avr/avr.md | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 359343e563d..28841e40db1 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -1355,8 +1355,6 @@
 gen_int_mode (INTVAL (operands[1]), mode));
 rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
 operands[0] = gen_rtx_MEM (BLKmode, addr0);
-// Alignment is unused; just set it to 0.
-operands[3] = const0_rtx;
   })
 
 
@@ -1364,7 +1362,7 @@
   [(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
 (const_int 0))
(use (match_operand:QI 1 "register_operand" "r"))
-   (use (match_operand:QI 2 "const_int_operand" "n"))
+   (use (match_operand:HI 2 "const_int_operand" "n"))
(clobber (match_scratch:HI 3 "=0"))
(clobber (match_scratch:QI 4 "=&1"))]
   ""
@@ -1382,7 +1380,7 @@
   [(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
 (const_int 0))
(use (match_operand:QI 1 "register_operand" "r"))
-   (use (match_operand:QI 2 "const_int_operand" "n"))
+   (use (match_operand:HI 2 "const_int_operand" "n"))
(clobber (match_scratch:HI 3 "=0"))
(clobber (match_scratch:QI 4 "=&1"))
(clobber (reg:CC REG_CC))]


[gcc r15-966] AVR: tree-optimization/115307 - Work around isinf bloat from early passes.

2024-06-01 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:fabb545026f714b7d1cbe586f4c5bbf6430bdde3

commit r15-966-gfabb545026f714b7d1cbe586f4c5bbf6430bdde3
Author: Georg-Johann Lay 
Date:   Sat Jun 1 10:38:00 2024 +0200

AVR: tree-optimization/115307 - Work around isinf bloat from early passes.

PR tree-optimization/115307
gcc/
* config/avr/avr.md (SFDF): New mode iterator.
(isinf2) [sf, df]: New expanders.

gcc/testsuite/
* gcc.target/avr/torture/pr115307-isinf.c: New test.

Diff:
---
 gcc/config/avr/avr.md   | 16 
 .../gcc.target/avr/torture/pr115307-isinf.c | 21 +
 2 files changed, 37 insertions(+)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index d4fcff46123..75d35d5e14b 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -292,6 +292,8 @@
 (define_mode_iterator SPLIT34 [SI SF PSI
SQ USQ SA USA])
 
+(define_mode_iterator SFDF [SF DF])
+
 ;; Where the most significant bit is located.
 (define_mode_attr MSB  [(QI "7") (QQ "7") (UQQ "7")
 (HI "15") (HQ "15") (UHQ "15") (HA "15") (UHA "15")
@@ -10047,6 +10049,20 @@
  (const_int 1)
  (match_dup 2)))])
 
+
+;; Work around PR115307: Early passes expand isinf/f/l to a bloat.
+;; These passes do not consider costs, and there is no way to
+;; hook in or otherwise disable the generated bloat.
+
+;; isinfsf2  isinfdf2
+(define_expand "isinf2"
+  [(parallel [(match_operand:HI 0)
+  (match_operand:SFDF 1)])]
+  ""
+  {
+FAIL;
+  })
+
 
 ;; Fixed-point instructions
 (include "avr-fixed.md")
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c 
b/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c
new file mode 100644
index 000..6368bd205c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+int call_isinff (float f)
+{
+int isinff (float);
+return isinff (f);
+}
+
+int call_isinf (double f)
+{
+int isinf (double);
+return isinf (f);
+}
+
+int call_isinfl (long double f)
+{
+int isinfl (long double);
+return isinfl (f);
+}
+
+/* { dg-final { scan-assembler-not "unord" } } */


[gcc r14-10266] AVR: tree-optimization/115307 - Work around isinf bloat from early passes.

2024-06-01 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:9d08c55f7c99329f4289ad3a4157c2d8d8a78d8c

commit r14-10266-g9d08c55f7c99329f4289ad3a4157c2d8d8a78d8c
Author: Georg-Johann Lay 
Date:   Sat Jun 1 10:38:00 2024 +0200

AVR: tree-optimization/115307 - Work around isinf bloat from early passes.

PR tree-optimization/115307
gcc/
* config/avr/avr.md (SFDF): New mode iterator.
(isinf2) [sf, df]: New expanders.

gcc/testsuite/
* gcc.target/avr/torture/pr115307-isinf.c: New test.

(cherry picked from commit fabb545026f714b7d1cbe586f4c5bbf6430bdde3)

Diff:
---
 gcc/config/avr/avr.md   | 16 
 .../gcc.target/avr/torture/pr115307-isinf.c | 21 +
 2 files changed, 37 insertions(+)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index d4fcff46123..75d35d5e14b 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -292,6 +292,8 @@
 (define_mode_iterator SPLIT34 [SI SF PSI
SQ USQ SA USA])
 
+(define_mode_iterator SFDF [SF DF])
+
 ;; Where the most significant bit is located.
 (define_mode_attr MSB  [(QI "7") (QQ "7") (UQQ "7")
 (HI "15") (HQ "15") (UHQ "15") (HA "15") (UHA "15")
@@ -10047,6 +10049,20 @@
  (const_int 1)
  (match_dup 2)))])
 
+
+;; Work around PR115307: Early passes expand isinf/f/l to a bloat.
+;; These passes do not consider costs, and there is no way to
+;; hook in or otherwise disable the generated bloat.
+
+;; isinfsf2  isinfdf2
+(define_expand "isinf2"
+  [(parallel [(match_operand:HI 0)
+  (match_operand:SFDF 1)])]
+  ""
+  {
+FAIL;
+  })
+
 
 ;; Fixed-point instructions
 (include "avr-fixed.md")
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c 
b/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c
new file mode 100644
index 000..6368bd205c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+int call_isinff (float f)
+{
+int isinff (float);
+return isinff (f);
+}
+
+int call_isinf (double f)
+{
+int isinf (double);
+return isinf (f);
+}
+
+int call_isinfl (long double f)
+{
+int isinfl (long double);
+return isinfl (f);
+}
+
+/* { dg-final { scan-assembler-not "unord" } } */


[gcc r15-968] AVR: target/115317 - Make isinf(-Inf) return -1.

2024-06-01 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:f12454278dc725fec3520a5d870e967d79292ee6

commit r15-968-gf12454278dc725fec3520a5d870e967d79292ee6
Author: Georg-Johann Lay 
Date:   Sat Jun 1 12:46:31 2024 +0200

AVR: target/115317 - Make isinf(-Inf) return -1.

PR target/115317
libgcc/config/avr/libf7/
* libf7-asm.sx (__isinf): Map -Inf to -1.

gcc/testsuite/
* gcc.target/avr/torture/pr115317-isinf.c: New test.

Diff:
---
 .../gcc.target/avr/torture/pr115317-isinf.c| 55 ++
 libgcc/config/avr/libf7/libf7-asm.sx   | 19 +---
 2 files changed, 67 insertions(+), 7 deletions(-)

diff --git a/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c 
b/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c
new file mode 100644
index 000..10f7b553fb9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+
+extern int isinff (float);
+extern int isinf (double);
+extern int isinfl (long double);
+
+int tst_isinf (float x, int val)
+{
+  double y;
+  long double z;
+
+  __asm ("" : "+r"(x));
+  if (isinff (x) != val)
+__builtin_exit (__LINE__);
+
+  y = x;
+  __asm ("" : "+r"(y));
+  if (isinf (y) != val)
+  __builtin_exit (__LINE__);
+
+  z = x;
+  __asm ("" : "+r"(z));
+  if (isinfl (z) != val)
+  __builtin_exit (__LINE__);
+}
+
+static float make_f (__UINT32_TYPE__ i)
+{
+  float f;
+  __builtin_memcpy (&f, &i, 4);
+  return f;
+}
+
+int main (void)
+{
+  tst_isinf (__builtin_huge_valf(), 1);
+  tst_isinf (-__builtin_huge_valf(), -1);
+  tst_isinf (__builtin_nanf(""), 0);
+  tst_isinf (0.0f, 0);
+  tst_isinf (-0.0f, 0);
+  tst_isinf (1.0f, 0);
+  tst_isinf (-1.0f, 0);
+  tst_isinf (make_f (0x7f80), 1);
+  tst_isinf (make_f (0xff80), -1);
+  tst_isinf (make_f (0x7f7f), 0);
+  tst_isinf (make_f (0xff7f), 0);
+  tst_isinf (make_f (0x7f81), 0);
+  tst_isinf (make_f (0xff81), 0);
+  tst_isinf (make_f (0x0080), 0);
+  tst_isinf (make_f (0x8080), 0);
+  tst_isinf (make_f (0x0040), 0);
+  tst_isinf (make_f (0x8040), 0);
+  
+  return 0;
+}
diff --git a/libgcc/config/avr/libf7/libf7-asm.sx 
b/libgcc/config/avr/libf7/libf7-asm.sx
index 1f8f60ab282..bef62f3a46a 100644
--- a/libgcc/config/avr/libf7/libf7-asm.sx
+++ b/libgcc/config/avr/libf7/libf7-asm.sx
@@ -1639,19 +1639,24 @@ _ENDF __copysign
 
 
 #ifdef F7MOD_D_isinf_
+;;; +Inf  ->  +1
+;;; -Inf  ->  -1
 _DEFUN __isinf
 DALIAS isinf
 LALIAS isinfl
+;; Save sign for later
+pushR25
 F7call  class_D
+pop TMP
+ldi R24,0
+ldi R25,0
 ;; Inf: T = Z = 1.
-brtc 0f
+brtc 0f ; ordinary number
+brne 0f ; Nan
 ldi R24,1
-breq 1f
-0:
-clr R24
-1:
-clr R25
-ret
+sbrcTMP,7
+sbiwR24,2
+0:  ret
 _ENDF __isinf
 #endif /* F7MOD_D_isinf_ */


[gcc r14-10268] AVR: target/115317 - Make isinf(-Inf) return -1.

2024-06-01 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:d7f42794d94e5a26f396253b1698ea1930337df3

commit r14-10268-gd7f42794d94e5a26f396253b1698ea1930337df3
Author: Georg-Johann Lay 
Date:   Sat Jun 1 12:46:31 2024 +0200

AVR: target/115317 - Make isinf(-Inf) return -1.

PR target/115317
libgcc/config/avr/libf7/
* libf7-asm.sx (__isinf): Map -Inf to -1.

gcc/testsuite/
* gcc.target/avr/torture/pr115317-isinf.c: New test.

(cherry picked from commit f12454278dc725fec3520a5d870e967d79292ee6)

Diff:
---
 .../gcc.target/avr/torture/pr115317-isinf.c| 55 ++
 libgcc/config/avr/libf7/libf7-asm.sx   | 19 +---
 2 files changed, 67 insertions(+), 7 deletions(-)

diff --git a/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c 
b/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c
new file mode 100644
index 000..10f7b553fb9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+
+extern int isinff (float);
+extern int isinf (double);
+extern int isinfl (long double);
+
+int tst_isinf (float x, int val)
+{
+  double y;
+  long double z;
+
+  __asm ("" : "+r"(x));
+  if (isinff (x) != val)
+__builtin_exit (__LINE__);
+
+  y = x;
+  __asm ("" : "+r"(y));
+  if (isinf (y) != val)
+  __builtin_exit (__LINE__);
+
+  z = x;
+  __asm ("" : "+r"(z));
+  if (isinfl (z) != val)
+  __builtin_exit (__LINE__);
+}
+
+static float make_f (__UINT32_TYPE__ i)
+{
+  float f;
+  __builtin_memcpy (&f, &i, 4);
+  return f;
+}
+
+int main (void)
+{
+  tst_isinf (__builtin_huge_valf(), 1);
+  tst_isinf (-__builtin_huge_valf(), -1);
+  tst_isinf (__builtin_nanf(""), 0);
+  tst_isinf (0.0f, 0);
+  tst_isinf (-0.0f, 0);
+  tst_isinf (1.0f, 0);
+  tst_isinf (-1.0f, 0);
+  tst_isinf (make_f (0x7f80), 1);
+  tst_isinf (make_f (0xff80), -1);
+  tst_isinf (make_f (0x7f7f), 0);
+  tst_isinf (make_f (0xff7f), 0);
+  tst_isinf (make_f (0x7f81), 0);
+  tst_isinf (make_f (0xff81), 0);
+  tst_isinf (make_f (0x0080), 0);
+  tst_isinf (make_f (0x8080), 0);
+  tst_isinf (make_f (0x0040), 0);
+  tst_isinf (make_f (0x8040), 0);
+  
+  return 0;
+}
diff --git a/libgcc/config/avr/libf7/libf7-asm.sx 
b/libgcc/config/avr/libf7/libf7-asm.sx
index 1f8f60ab282..bef62f3a46a 100644
--- a/libgcc/config/avr/libf7/libf7-asm.sx
+++ b/libgcc/config/avr/libf7/libf7-asm.sx
@@ -1639,19 +1639,24 @@ _ENDF __copysign
 
 
 #ifdef F7MOD_D_isinf_
+;;; +Inf  ->  +1
+;;; -Inf  ->  -1
 _DEFUN __isinf
 DALIAS isinf
 LALIAS isinfl
+;; Save sign for later
+pushR25
 F7call  class_D
+pop TMP
+ldi R24,0
+ldi R25,0
 ;; Inf: T = Z = 1.
-brtc 0f
+brtc 0f ; ordinary number
+brne 0f ; Nan
 ldi R24,1
-breq 1f
-0:
-clr R24
-1:
-clr R25
-ret
+sbrcTMP,7
+sbiwR24,2
+0:  ret
 _ENDF __isinf
 #endif /* F7MOD_D_isinf_ */


[gcc r13-8816] AVR: target/115317 - Make isinf(-Inf) return -1.

2024-06-01 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:b45d7281c1b4eb2cf61280b9f7064229b7ca7581

commit r13-8816-gb45d7281c1b4eb2cf61280b9f7064229b7ca7581
Author: Georg-Johann Lay 
Date:   Sat Jun 1 12:46:31 2024 +0200

AVR: target/115317 - Make isinf(-Inf) return -1.

PR target/115317
libgcc/config/avr/libf7/
* libf7-asm.sx (__isinf): Map -Inf to -1.

gcc/testsuite/
* gcc.target/avr/torture/pr115317-isinf.c: New test.

(cherry picked from commit f12454278dc725fec3520a5d870e967d79292ee6)

Diff:
---
 .../gcc.target/avr/torture/pr115317-isinf.c| 55 ++
 libgcc/config/avr/libf7/libf7-asm.sx   | 19 +---
 2 files changed, 67 insertions(+), 7 deletions(-)

diff --git a/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c 
b/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c
new file mode 100644
index 000..10f7b553fb9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+
+extern int isinff (float);
+extern int isinf (double);
+extern int isinfl (long double);
+
+int tst_isinf (float x, int val)
+{
+  double y;
+  long double z;
+
+  __asm ("" : "+r"(x));
+  if (isinff (x) != val)
+__builtin_exit (__LINE__);
+
+  y = x;
+  __asm ("" : "+r"(y));
+  if (isinf (y) != val)
+  __builtin_exit (__LINE__);
+
+  z = x;
+  __asm ("" : "+r"(z));
+  if (isinfl (z) != val)
+  __builtin_exit (__LINE__);
+}
+
+static float make_f (__UINT32_TYPE__ i)
+{
+  float f;
+  __builtin_memcpy (&f, &i, 4);
+  return f;
+}
+
+int main (void)
+{
+  tst_isinf (__builtin_huge_valf(), 1);
+  tst_isinf (-__builtin_huge_valf(), -1);
+  tst_isinf (__builtin_nanf(""), 0);
+  tst_isinf (0.0f, 0);
+  tst_isinf (-0.0f, 0);
+  tst_isinf (1.0f, 0);
+  tst_isinf (-1.0f, 0);
+  tst_isinf (make_f (0x7f80), 1);
+  tst_isinf (make_f (0xff80), -1);
+  tst_isinf (make_f (0x7f7f), 0);
+  tst_isinf (make_f (0xff7f), 0);
+  tst_isinf (make_f (0x7f81), 0);
+  tst_isinf (make_f (0xff81), 0);
+  tst_isinf (make_f (0x0080), 0);
+  tst_isinf (make_f (0x8080), 0);
+  tst_isinf (make_f (0x0040), 0);
+  tst_isinf (make_f (0x8040), 0);
+  
+  return 0;
+}
diff --git a/libgcc/config/avr/libf7/libf7-asm.sx 
b/libgcc/config/avr/libf7/libf7-asm.sx
index df315d35c73..84790d2f52d 100644
--- a/libgcc/config/avr/libf7/libf7-asm.sx
+++ b/libgcc/config/avr/libf7/libf7-asm.sx
@@ -1639,19 +1639,24 @@ _ENDF __copysign
 
 
 #ifdef F7MOD_D_isinf_
+;;; +Inf  ->  +1
+;;; -Inf  ->  -1
 _DEFUN __isinf
 DALIAS isinf
 LALIAS isinfl
+;; Save sign for later
+pushR25
 F7call  class_D
+pop TMP
+ldi R24,0
+ldi R25,0
 ;; Inf: T = Z = 1.
-brtc 0f
+brtc 0f ; ordinary number
+brne 0f ; Nan
 ldi R24,1
-breq 1f
-0:
-clr R24
-1:
-clr R25
-ret
+sbrcTMP,7
+sbiwR24,2
+0:  ret
 _ENDF __isinf
 #endif /* F7MOD_D_isinf_ */


[gcc r13-8817] AVR: tree-optimization/115307 - Work around isinf bloat from early passes.

2024-06-01 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:c57d73f4cd5ca61327406fc2521a2235dd49d12e

commit r13-8817-gc57d73f4cd5ca61327406fc2521a2235dd49d12e
Author: Georg-Johann Lay 
Date:   Sat Jun 1 10:38:00 2024 +0200

AVR: tree-optimization/115307 - Work around isinf bloat from early passes.

PR tree-optimization/115307
gcc/
* config/avr/avr.md (SFDF): New mode iterator.
(isinf2) [sf, df]: New expanders.

gcc/testsuite/
* gcc.target/avr/torture/pr115307-isinf.c: New test.

(cherry picked from commit fabb545026f714b7d1cbe586f4c5bbf6430bdde3)

Diff:
---
 gcc/config/avr/avr.md   | 16 
 .../gcc.target/avr/torture/pr115307-isinf.c | 21 +
 2 files changed, 37 insertions(+)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 866ce47d033..46f7812cea2 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -285,6 +285,8 @@
 (define_mode_iterator SPLIT34 [SI SF PSI
SQ USQ SA USA])
 
+(define_mode_iterator SFDF [SF DF])
+
 ;; Define code iterators
 ;; Define two incarnations so that we can build the cartesian product.
 (define_code_iterator any_extend  [sign_extend zero_extend])
@@ -9780,6 +9782,20 @@
 operands[4] = GEN_INT (bitno % 8);
   })
 
+
+;; Work around PR115307: Early passes expand isinf/f/l to a bloat.
+;; These passes do not consider costs, and there is no way to
+;; hook in or otherwise disable the generated bloat.
+
+;; isinfsf2  isinfdf2
+(define_expand "isinf2"
+  [(parallel [(match_operand:HI 0)
+  (match_operand:SFDF 1)])]
+  ""
+  {
+FAIL;
+  })
+
 
 ;; Fixed-point instructions
 (include "avr-fixed.md")
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c 
b/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c
new file mode 100644
index 000..6368bd205c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+int call_isinff (float f)
+{
+int isinff (float);
+return isinff (f);
+}
+
+int call_isinf (double f)
+{
+int isinf (double);
+return isinf (f);
+}
+
+int call_isinfl (long double f)
+{
+int isinfl (long double);
+return isinfl (f);
+}
+
+/* { dg-final { scan-assembler-not "unord" } } */


[gcc r15-1343] AVR: target/115419 - Tie breaks are rounded-to-even.

2024-06-14 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:2830b0b8655f0d1a62b416af8ade31f5b96f0ffb

commit r15-1343-g2830b0b8655f0d1a62b416af8ade31f5b96f0ffb
Author: Georg-Johann Lay 
Date:   Fri Jun 14 18:24:13 2024 +0200

AVR: target/115419 - Tie breaks are rounded-to-even.

libgcc/config/avr/libf7/
PR target/115419
* libf7.c (f7_get_double): Round tie breaks to even LSB.

Diff:
---
 libgcc/config/avr/libf7/libf7.c | 20 +++-
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/libgcc/config/avr/libf7/libf7.c b/libgcc/config/avr/libf7/libf7.c
index 375becb854c1..6fae4fc1a2de 100644
--- a/libgcc/config/avr/libf7/libf7.c
+++ b/libgcc/config/avr/libf7/libf7.c
@@ -440,11 +440,21 @@ f7_double_t f7_get_double (const f7_t *aa)
 
   mant &= 0x00ff;
 
-  // FIXME: For subnormals, rounding is premature and should be
-  //   done *after* the mantissa has been shifted into place
-  //   (or the round value be shifted left accordingly).
-  // Round.
-  mant += 1u << (F7_MANT_BITS - (1 + DBL_DIG_MANT) - 1);
+  // PR115419: The least significant nibble tells how to round:
+  // Tie breaks are rounded to even (Banker's rounding).
+  uint8_t lsn = mant & 0xff;
+  lsn &= 0xf;
+  // The LSB of the outgoing double is at bit 3.
+  if (lsn & (1 << 3))
+++lsn;
+  if (lsn > (1 << 2))
+{
+  // FIXME: For subnormals, rounding is premature and should be
+  //done *after* the mantissa has been shifted into place
+  //(or the round value be shifted left accordingly).
+  // Round.
+  mant += 1u << (F7_MANT_BITS - (1 + DBL_DIG_MANT) - 1);
+}
 
   uint8_t dex;
   register uint64_t r18 __asm ("r18") = mant;


[gcc r15-4054] testsuite - Fix gcc.c-torture/execute/ieee/pr108540-1.c

2024-10-04 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:a0cc6941d8c8fa88441fdae1ffb35396a412ec6b

commit r15-4054-ga0cc6941d8c8fa88441fdae1ffb35396a412ec6b
Author: Georg-Johann Lay 
Date:   Thu Oct 3 13:14:52 2024 +0200

testsuite - Fix gcc.c-torture/execute/ieee/pr108540-1.c

  PR testsuite/108540
gcc/testsuite/
* gcc.c-torture/execute/ieee/pr108540-1.c: Un-preprocess
__SIZE_TYPE__ and __INT64_TYPE__.
* gcc.c-torture/execute/ieee/pr108540-1.x: New file, requires 
double64.

Diff:
---
 gcc/testsuite/gcc.c-torture/execute/ieee/pr108540-1.c | 6 +++---
 gcc/testsuite/gcc.c-torture/execute/ieee/pr108540-1.x | 7 +++
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/pr108540-1.c 
b/gcc/testsuite/gcc.c-torture/execute/ieee/pr108540-1.c
index ebd4c502ee5d..db094418a791 100644
--- a/gcc/testsuite/gcc.c-torture/execute/ieee/pr108540-1.c
+++ b/gcc/testsuite/gcc.c-torture/execute/ieee/pr108540-1.c
@@ -1,7 +1,7 @@
 /* PR tree-optimization/108540 */
 
 __attribute__((noipa)) void
-bar (const char *cp, unsigned long size, char sign, int dsgn)
+bar (const char *cp, __SIZE_TYPE__ size, char sign, int dsgn)
 {
   if (__builtin_strcmp (cp, "ZERO") != 0 || size != 4 || sign != '-' || dsgn 
!= 1)
 __builtin_abort ();
@@ -11,7 +11,7 @@ __attribute__((noipa)) void
 foo (int x, int ch, double d)
 {
   const char *cp = "";
-  unsigned long size = 0;
+  __SIZE_TYPE__ size = 0;
   char sign = '\0';
   switch (x)
 {
@@ -41,7 +41,7 @@ foo (int x, int ch, double d)
sign = '\0';
   if (ch == 'a' || ch == 'A')
{
- union U { long long l; double d; } u;
+ union U { __INT64_TYPE__ l; double d; } u;
  int dsgn;
  u.d = d;
  if (u.l < 0)
diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/pr108540-1.x 
b/gcc/testsuite/gcc.c-torture/execute/ieee/pr108540-1.x
new file mode 100644
index ..06d93efeb991
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/ieee/pr108540-1.x
@@ -0,0 +1,7 @@
+load_lib target-supports.exp
+
+if { ! [check_effective_target_double64] } {
+return 1
+}
+
+return 0


[gcc r15-4073] AVR: Implement TARGET_FLOATN_MODE.

2024-10-04 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:98a1a886e4c0c58ad9f9846caf5697ff00e4f24a

commit r15-4073-g98a1a886e4c0c58ad9f9846caf5697ff00e4f24a
Author: Georg-Johann Lay 
Date:   Fri Oct 4 15:38:59 2024 +0200

AVR: Implement TARGET_FLOATN_MODE.

gcc/
* config/avr/avr.cc (avr_floatn_mode): New static function.
(TARGET_FLOATN_MODE): New define.

Diff:
---
 gcc/config/avr/avr.cc | 21 +
 1 file changed, 21 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 92013c3845db..b73c251b64b4 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -15473,6 +15473,24 @@ avr_c_mode_for_floating_type (tree_index ti)
 }
 
 
+/* Implement `TARGET_FLOATN_MODE'.  */
+
+static opt_scalar_float_mode
+avr_floatn_mode (int n, bool /*extended*/)
+{
+  if (n == 32)
+return SFmode;
+
+  // Notice that -m[long-]double= just tells which library (AVR-LibC
+  // or libgcc/libf7) is providing symbols like sin.  DFmode support
+  // is provided by libf7 no matter what.
+  if (n == 64)
+return DFmode;
+
+  return opt_scalar_float_mode ();
+}
+
+
 /* Worker function for `FLOAT_LIB_COMPARE_RETURNS_BOOL'.  */
 
 bool
@@ -15705,6 +15723,9 @@ avr_use_lra_p ()
 #undef TARGET_C_MODE_FOR_FLOATING_TYPE
 #define TARGET_C_MODE_FOR_FLOATING_TYPE avr_c_mode_for_floating_type
 
+#undef  TARGET_FLOATN_MODE
+#define TARGET_FLOATN_MODE avr_floatn_mode
+
 gcc_target targetm = TARGET_INITIALIZER;


  1   2   3   >