This PR skips saving of any registers in main.

Attribute OS_main can do this as well, however we can just drop
any saves / restores in all optimized compilation -- not even
the test suite needs these saves.

The feature can still be switched off by new -mno-OS_main

Ok for trunk?


gcc/
        Don't save registers in main().

        PR target/83737
        * doc/invoke.texi (AVR Options) [-mOS_main]: Document it.
        * config/avr/avr.opt (-mOS_main): New target option.
        * config/avr/avr.c (avr_in_main_p): New static function.
        (avr_regs_to_save) [avr_in_main_p]: Return 0.
        (avr_prologue_setup_frame): Don't save any regs if avr_in_main_p.
        (avr_expand_epilogue): Same.
        * common/config/avr/avr-common.c (avr_option_optimization_table):
        Switch on -mOS_main for optimizing compilations.
Index: common/config/avr/avr-common.c
===================================================================
--- common/config/avr/avr-common.c	(revision 256338)
+++ common/config/avr/avr-common.c	(working copy)
@@ -31,6 +31,7 @@ static const struct default_options avr_
     // a frame without need when it tries to be smart around calls.
     { OPT_LEVELS_ALL, OPT_fcaller_saves, NULL, 0 },
     { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_mgas_isr_prologues, NULL, 1 },
+    { OPT_LEVELS_1_PLUS, OPT_mOS_main, NULL, 1 },
     { OPT_LEVELS_NONE, 0, NULL, 0 }
   };
 
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(revision 256338)
+++ config/avr/avr.c	(working copy)
@@ -1167,6 +1167,23 @@ avr_starting_frame_offset (void)
 }
 
 
+/* Return true if we are supposed to be in main().  This is only used
+   to determine if the callee-saved registers don't need to be saved
+   because the caller of main (crt*.o) doesn't use any of them.  */
+
+static bool
+avr_in_main_p ()
+{
+  return (TARGET_OS_MAIN
+          && MAIN_NAME_P (DECL_NAME (current_function_decl))
+          // FIXME:  We'd like to also test `flag_hosted' which is only
+          // available in the C-ish fronts, so no such test for now.
+          // Instead, we test the return type of "main" which is not exactly
+          // the same but good enough.
+          && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))));
+}
+
+
 /* Return the number of hard registers to push/pop in the prologue/epilogue
    of the current function, and optionally store these registers in SET.  */
 
@@ -1180,10 +1197,11 @@ avr_regs_to_save (HARD_REG_SET *set)
     CLEAR_HARD_REG_SET (*set);
   count = 0;
 
-  /* No need to save any registers if the function never returns or
-     has the "OS_task" or "OS_main" attribute.  */
+  /* No need to save any registers if the function never returns or has the
+     "OS_task" or "OS_main" attribute.  Dito if we are in "main".  */
 
   if (TREE_THIS_VOLATILE (current_function_decl)
+      || avr_in_main_p()
       || cfun->machine->is_OS_task
       || cfun->machine->is_OS_main)
     return 0;
@@ -1651,6 +1669,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT
                    && size < size_max
                    && live_seq
                    && !isr_p
+                   && !avr_in_main_p()
                    && !cfun->machine->is_OS_task
                    && !cfun->machine->is_OS_main
                    && !AVR_TINY);
@@ -1713,7 +1732,9 @@ avr_prologue_setup_frame (HOST_WIDE_INT
           emit_push_byte (reg, true);
 
       if (frame_pointer_needed
-          && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
+          && (!(avr_in_main_p()
+                || cfun->machine->is_OS_task
+                || cfun->machine->is_OS_main)))
         {
           /* Push frame pointer.  Always be consistent about the
              ordering of pushes -- epilogue_restores expects the
@@ -1834,6 +1855,9 @@ avr_prologue_setup_frame (HOST_WIDE_INT
           if (cfun->machine->is_interrupt)
             irq_state = 1;
 
+          /* IRQs might be on when entering "main", hence avr_in_main_p
+             is *not* included in the following test.  */
+
           if (TARGET_NO_INTERRUPTS
               || cfun->machine->is_signal
               || cfun->machine->is_OS_main)
@@ -2122,6 +2146,7 @@ avr_expand_epilogue (bool sibcall_p)
               && !isr_p
               && !cfun->machine->is_OS_task
               && !cfun->machine->is_OS_main
+              && !avr_in_main_p()
               && !AVR_TINY);
 
   if (minimize
@@ -2227,7 +2252,9 @@ avr_expand_epilogue (bool sibcall_p)
     } /* size != 0 */
 
   if (frame_pointer_needed
-      && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
+      && !(avr_in_main_p()
+           || cfun->machine->is_OS_task
+           || cfun->machine->is_OS_main))
     {
       /* Restore previous frame_pointer.  See avr_expand_prologue for
          rationale for not using pophi.  */
Index: config/avr/avr.opt
===================================================================
--- config/avr/avr.opt	(revision 256338)
+++ config/avr/avr.opt	(working copy)
@@ -70,6 +70,10 @@ Target Report Undocumented Mask(ORDER_1)
 morder2
 Target Report Undocumented Mask(ORDER_2)
 
+mOS_main
+Target Report Mask(OS_MAIN)
+Treat main as if it had attribute OS_main.
+
 mtiny-stack
 Target Report Mask(TINY_STACK)
 Change only the low 8 bits of the stack pointer.
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 256338)
+++ doc/invoke.texi	(working copy)
@@ -669,7 +669,8 @@ -imacros @var{file}  -imultilib @var{dir
 -mbranch-cost=@var{cost} @gol
 -mcall-prologues  -mgas-isr-prologues  -mint8 @gol
 -mn_flash=@var{size}  -mno-interrupts @gol
--mrelax  -mrmw  -mstrict-X  -mtiny-stack  -mfract-convert-truncate @gol
+-mOS_main -mrelax  -mrmw  -mstrict-X  -mtiny-stack @gol
+-mfract-convert-truncate @gol
 -mshort-calls  -nodevicelib @gol
 -Waddr-space-convert  -Wmisspelled-isr}
 
@@ -16472,6 +16473,12 @@ Assume that the flash memory has a size
 Generated code is not compatible with hardware interrupts.
 Code size is smaller.
 
+@item -mOS_main
+@opindex mOS_main
+Do not save registers in @code{main}.  The effect is similar to
+attaching attribute @ref{AVR Function Attributes,,@code{OS_main}}
+to @code{main}. It is activated per default if optimization is on.
+
 @item -mrelax
 @opindex mrelax
 Try to replace @code{CALL} resp.@: @code{JMP} instruction by the shorter

Reply via email to