diff mbox series

[avr,applied] Fix PR target/113927: Simple code triggers a stack frame

Message ID f1800c49-d5a8-4f5d-87b2-67c2cef59cea@gjlay.de
State New
Headers show
Series [avr,applied] Fix PR target/113927: Simple code triggers a stack frame | expand

Commit Message

Georg-Johann Lay Feb. 15, 2024, 12:49 p.m. UTC
Applied this patch

Johann

--

AVR: target 113927 - Simple code triggers stack frame for Reduced Tiny.

The -mmcu=avrtiny cores have no ADIW and SBIW instructions.  This was
implemented by clearing all regs out of regclass ADDW_REGS so that
constraint "w" never matched.  This corrupted the subset relations of
the register classes as they appear in enum reg_class.

This patch keeps ADDW_REGS like for all other cores, i.e. it contains
R24...R31.  Instead of tests like  test_hard_reg_class (ADDW_REGS, *)
the code now uses  avr_adiw_reg_p (*).  And all insns with constraint "w"
get "isa" insn attribute value of "adiw".

Plus, a new built-in macro __AVR_HAVE_ADIW__ is provided, which is more
specific than __AVR_TINY__.

gcc/
	PR target/113927
	* config/avr/avr.h (AVR_HAVE_ADIW): New macro.
	* config/avr/avr-protos.h (avr_adiw_reg_p): New proto.
	* config/avr/avr.cc (avr_adiw_reg_p): New function.
	(avr_conditional_register_usage) [AVR_TINY]: Don't clear ADDW_REGS.
	Replace test_hard_reg_class (ADDW_REGS, ...) with calls to
	* config/avr/avr.md: Same.
	(attr "isa") <tiny, no_tiny>: Remove.
	<adiw, no_adiw>: Add.
	(define_insn, define_insn_and_split): When an alternative has
	constraint "w", then set attribute "isa" to "adiw".
	* config/avr/avr-c.cc (avr_cpu_cpp_builtins) [AVR_HAVE_ADIW]:
	Built-in define __AVR_HAVE_ADIW__.
	* doc/invoke.texi (AVR Options): Document it.
diff mbox series

Patch

diff --git a/gcc/config/avr/avr-c.cc b/gcc/config/avr/avr-c.cc
index 60905a76556..5e7f759ed73 100644
--- a/gcc/config/avr/avr-c.cc
+++ b/gcc/config/avr/avr-c.cc
@@ -307,6 +307,7 @@  avr_cpu_cpp_builtins (struct cpp_reader *pfile)
   if (AVR_HAVE_ELPMX)    cpp_define (pfile, "__AVR_HAVE_ELPMX__");
   if (AVR_HAVE_MOVW)     cpp_define (pfile, "__AVR_HAVE_MOVW__");
   if (AVR_HAVE_LPMX)     cpp_define (pfile, "__AVR_HAVE_LPMX__");
+  if (AVR_HAVE_ADIW)     cpp_define (pfile, "__AVR_HAVE_ADIW__");
 
   if (avr_arch->asm_only)
     cpp_define (pfile, "__AVR_ASM_ONLY__");
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 46b75f96b9c..7d1f815c664 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -123,6 +123,7 @@  extern enum reg_class avr_mode_code_base_reg_class (machine_mode, addr_space_t,
 extern bool avr_regno_mode_code_ok_for_base_p (int, machine_mode, addr_space_t, RTX_CODE, RTX_CODE);
 extern rtx avr_incoming_return_addr_rtx (void);
 extern rtx avr_legitimize_reload_address (rtx*, machine_mode, int, int, int, int, rtx (*)(rtx,int));
+extern bool avr_adiw_reg_p (rtx);
 extern bool avr_mem_flash_p (rtx);
 extern bool avr_mem_memx_p (rtx);
 extern bool avr_load_libgcc_p (rtx);
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index d21b286ed8b..4a55f14bff7 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -292,6 +292,17 @@  avr_to_int_mode (rtx x)
     : simplify_gen_subreg (int_mode_for_mode (mode).require (), x, mode, 0);
 }
 
+
+/* Return true if hard register REG supports the ADIW and SBIW instructions.  */
+
+bool
+avr_adiw_reg_p (rtx reg)
+{
+  return (AVR_HAVE_ADIW
+	  && test_hard_reg_class (ADDW_REGS, reg));
+}
+
+
 namespace {
 
 static const pass_data avr_pass_data_recompute_notes =
@@ -6272,7 +6283,7 @@  avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
       /* Word registers >= R24 can use SBIW/ADIW with 0..63.  */
 
       if (i == 0
-	  && test_hard_reg_class (ADDW_REGS, reg8))
+	  && avr_adiw_reg_p (reg8))
 	{
 	  int val16 = trunc_int_for_mode (INTVAL (xval), HImode);
 
@@ -8186,7 +8197,7 @@  avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
       if (!started
 	  && i % 2 == 0
 	  && i + 2 <= n_bytes
-	  && test_hard_reg_class (ADDW_REGS, reg8))
+	  && avr_adiw_reg_p (reg8))
 	{
 	  rtx xval16 = simplify_gen_subreg (HImode, xval, imode, i);
 	  unsigned int val16 = UINTVAL (xval16) & GET_MODE_MASK (HImode);
@@ -8678,7 +8689,7 @@  avr_out_plus_set_ZN (rtx *xop, int *plen)
     }
 
   if (n_bytes == 2
-      && test_hard_reg_class (ADDW_REGS, xreg)
+      && avr_adiw_reg_p (xreg)
       && IN_RANGE (INTVAL (xval), 1, 63))
     {
       // Add 16-bit value in [1..63] to a w register.
@@ -8705,7 +8716,7 @@  avr_out_plus_set_ZN (rtx *xop, int *plen)
 
       if (i == 0
 	  && n_bytes >= 2
-	  && test_hard_reg_class (ADDW_REGS, op[0]))
+	  && avr_adiw_reg_p (op[0]))
 	{
 	  op[1] = simplify_gen_subreg (HImode, xval, mode, 0);
 	  if (IN_RANGE (INTVAL (op[1]), 0, 63))
@@ -13312,7 +13323,6 @@  avr_conditional_register_usage (void)
 	  reg_alloc_order[i] = tiny_reg_alloc_order[i];
 	}
 
-      CLEAR_HARD_REG_SET (reg_class_contents[(int) ADDW_REGS]);
       CLEAR_HARD_REG_SET (reg_class_contents[(int) NO_LD_REGS]);
     }
 }
@@ -14043,7 +14053,7 @@  avr_out_cpymem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
 {
   addr_space_t as = (addr_space_t) INTVAL (op[0]);
   machine_mode loop_mode = GET_MODE (op[1]);
-  bool sbiw_p = test_hard_reg_class (ADDW_REGS, op[1]);
+  bool sbiw_p = avr_adiw_reg_p (op[1]);
   rtx xop[3];
 
   if (plen)
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index 7f7e23183b2..ff2738df78c 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -65,6 +65,7 @@  enum
 #define AVR_HAVE_JMP_CALL (avr_arch->have_jmp_call && ! AVR_SHORT_CALLS)
 #define AVR_HAVE_MUL (avr_arch->have_mul)
 #define AVR_HAVE_MOVW (avr_arch->have_movw_lpmx)
+#define AVR_HAVE_ADIW (!AVR_TINY)
 #define AVR_HAVE_LPM (!AVR_TINY)
 #define AVR_HAVE_LPMX (avr_arch->have_movw_lpmx)
 #define AVR_HAVE_ELPM (avr_arch->have_elpm)
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 68470b12e3d..49e586723ab 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -176,10 +176,11 @@  (define_attr "adjust_len"
 ;; lpm  : ISA has no LPMX                lpmx  : ISA has LPMX
 ;; elpm : ISA has ELPM but no ELPMX      elpmx : ISA has ELPMX
 ;; no_xmega: non-XMEGA core              xmega : XMEGA core
-;; no_tiny:  non-TINY core               tiny  : TINY core
+;; no_adiw:  ISA has no ADIW, SBIW       adiw  : ISA has ADIW, SBIW
 
 (define_attr "isa"
-  "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx, no_xmega,xmega, no_tiny,tiny,
+  "mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx, no_xmega,xmega,
+   no_adiw,adiw,
    standard"
   (const_string "standard"))
 
@@ -231,16 +232,16 @@  (define_attr "enabled" ""
               (match_test "AVR_XMEGA"))
          (const_int 1)
 
-         (and (eq_attr "isa" "tiny")
-              (match_test "AVR_TINY"))
-         (const_int 1)
-
          (and (eq_attr "isa" "no_xmega")
               (match_test "!AVR_XMEGA"))
          (const_int 1)
 
-         (and (eq_attr "isa" "no_tiny")
-              (match_test "!AVR_TINY"))
+         (and (eq_attr "isa" "adiw")
+              (match_test "AVR_HAVE_ADIW"))
+         (const_int 1)
+
+         (and (eq_attr "isa" "no_adiw")
+              (match_test "!AVR_HAVE_ADIW"))
          (const_int 1)
 
          ] (const_int 0)))
@@ -1325,7 +1326,9 @@  (define_insn_and_split "*clrmemhi_split"
               (use (match_dup 2))
               (clobber (match_dup 3))
               (clobber (match_dup 4))
-              (clobber (reg:CC REG_CC))])])
+              (clobber (reg:CC REG_CC))])]
+  ""
+  [(set_attr "isa" "adiw,*")])
 
 
 (define_insn "*clrmemhi"
@@ -1340,7 +1343,8 @@  (define_insn "*clrmemhi"
   "@
 	0:\;st %a0+,__zero_reg__\;sbiw %A1,1\;brne 0b
 	0:\;st %a0+,__zero_reg__\;subi %A1,1\;sbci %B1,0\;brne 0b"
-  [(set_attr "length" "3,4")])
+  [(set_attr "length" "3,4")
+   (set_attr "isa" "adiw,*")])
 
 (define_expand "strlenhi"
   [(set (match_dup 4)
@@ -1627,7 +1631,9 @@  (define_insn_and_split "*add<mode>3_split"
   [(parallel [(set (match_dup 0)
                    (plus:ALL2 (match_dup 1)
                               (match_dup 2)))
-              (clobber (reg:CC REG_CC))])])
+              (clobber (reg:CC REG_CC))])]
+  ""
+  [(set_attr "isa" "*,*,adiw,*")])
 
 (define_insn "*add<mode>3"
   [(set (match_operand:ALL2 0 "register_operand"                   "=??r,d,!w    ,d")
@@ -1639,6 +1645,7 @@  (define_insn "*add<mode>3"
     return avr_out_plus (insn, operands);
   }
   [(set_attr "length" "2")
+   (set_attr "isa" "*,*,adiw,*")
    (set_attr "adjust_len" "plus")])
 
 ;; Adding a constant to NO_LD_REGS might have lead to a reload of
@@ -2306,7 +2313,9 @@  (define_insn_and_split "*addhi3.lt0_split"
                                    (const_int 0))
                             (match_dup 2)))
               (clobber (match_dup 3))
-              (clobber (reg:CC REG_CC))])])
+              (clobber (reg:CC REG_CC))])]
+  ""
+  [(set_attr "isa" "adiw,*")])
 
 (define_insn "*addhi3.lt0"
   [(set (match_operand:HI 0 "register_operand"                   "=w,r")
@@ -2319,7 +2328,8 @@  (define_insn "*addhi3.lt0"
   "@
 	sbrc %1,7\;adiw %0,1
 	lsl %1\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__"
-  [(set_attr "length" "2,3")])
+  [(set_attr "length" "2,3")
+   (set_attr "isa" "adiw,*")])
 
 (define_insn_and_split "*addpsi3.lt0_split"
   [(set (match_operand:PSI 0 "register_operand"                         "=r")
@@ -6634,6 +6644,7 @@  (define_insn "cmp<mode>3"
     return avr_out_compare (insn, operands, NULL);
   }
   [(set_attr "length" "2,2,2,3,4,2,4")
+   (set_attr "isa" "adiw,*,*,*,*,*,*")
    (set_attr "adjust_len" "tsthi,tsthi,*,*,*,compare,compare")])
 
 (define_insn "*cmppsi"
@@ -7607,7 +7618,7 @@  (define_peephole ; "*dec-and-branchsi!=-1.d.clobber"
   {
     const char *op;
     int jump_mode;
-    if (test_hard_reg_class (ADDW_REGS, operands[0]))
+    if (avr_adiw_reg_p (operands[0]))
       output_asm_insn ("sbiw %0,1" CR_TAB
                        "sbc %C0,__zero_reg__" CR_TAB
                        "sbc %D0,__zero_reg__", operands);
@@ -7650,7 +7661,7 @@  (define_peephole ; "*dec-and-branchhi!=-1"
   {
     const char *op;
     int jump_mode;
-    if (test_hard_reg_class (ADDW_REGS, operands[0]))
+    if (avr_adiw_reg_p (operands[0]))
       output_asm_insn ("sbiw %0,1", operands);
     else
       output_asm_insn ("subi %A0,1" CR_TAB
@@ -7691,7 +7702,7 @@  (define_peephole ; "*dec-and-branchhi!=-1.d.clobber"
   {
     const char *op;
     int jump_mode;
-    if (test_hard_reg_class (ADDW_REGS, operands[0]))
+    if (avr_adiw_reg_p (operands[0]))
       output_asm_insn ("sbiw %0,1", operands);
     else
       output_asm_insn ("subi %A0,1" CR_TAB
@@ -8065,7 +8076,7 @@  (define_insn_and_split "delay_cycles_2"
               (clobber (match_dup 2))
               (clobber (reg:CC REG_CC))])]
   ""
-  [(set_attr "isa" "no_tiny,tiny")])
+  [(set_attr "isa" "adiw,no_adiw")])
 
 (define_insn "*delay_cycles_2"
   [(unspec_volatile [(match_operand:HI 0 "const_int_operand" "n,n")
@@ -8080,7 +8091,7 @@  (define_insn "*delay_cycles_2"
 	ldi %A2,lo8(%0)\;ldi %B2,hi8(%0)\n1:	sbiw %A2,1\;brne 1b
 	ldi %A2,lo8(%0)\;ldi %B2,hi8(%0)\n1:	subi %A2,1\;sbci %B2,0\;brne 1b"
   [(set_attr "length" "4,5")
-   (set_attr "isa" "no_tiny,tiny")])
+   (set_attr "isa" "adiw,no_adiw")])
 
 (define_insn_and_split "delay_cycles_3"
   [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n")
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 0de184f6241..511114cde59 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -24146,6 +24146,9 @@  If @var{device} is not a device but only a core architecture like
 @item __AVR_XMEGA__
 The device / architecture belongs to the XMEGA family of devices.
 
+@item __AVR_HAVE_ADIW__
+The device has the @code{ADIW} and @code{SBIW} instructions.
+
 @item __AVR_HAVE_ELPM__
 The device has the @code{ELPM} instruction.
 
@@ -24153,14 +24156,14 @@  The device has the @code{ELPM} instruction.
 The device has the @code{ELPM R@var{n},Z} and @code{ELPM
 R@var{n},Z+} instructions.
 
-@item __AVR_HAVE_MOVW__
-The device has the @code{MOVW} instruction to perform 16-bit
-register-register moves.
-
 @item __AVR_HAVE_LPMX__
 The device has the @code{LPM R@var{n},Z} and
 @code{LPM R@var{n},Z+} instructions.
 
+@item __AVR_HAVE_MOVW__
+The device has the @code{MOVW} instruction to perform 16-bit
+register-register moves.
+
 @item __AVR_HAVE_MUL__
 The device has a hardware multiplier.