On 08.01.2018 18:39, Denis Chertykov wrote:
2018-01-08 20:19 GMT+04:00 Georg-Johann Lay <a...@gjlay.de>:
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?

I like it.

Please commit.

Committed a different approach:

1) The effect is the same as OS_task, hence named the
   option -mmain-is-OS_task.  OS_main is too strict
   because that'd assume that IRQs are off when main is
   entered, hence due to that rare case (and when main
   needs a frame) OS_task is the right feature.

2) Instead of fiddling with prologue / epilogue directly,
   now just add OS_task to main.

3) Some restrictions have been removed re. diagnostics
   when naked, OS_task, OS_main are specified at the
   same time.  Instead, the logic follows now just
   what the attributes are requesting (e.g. OS_main
   supersedes OS_task and naked supersedes OS_main).

The original subject has a typo: The PR is PR83738.


        PR target/83738
        * doc/invoke.texi (AVR Options) [-mmain-is-OS_task]: Document it.
        * config/avr/avr.opt (-mmain-is-OS_task): New target option.
        * config/avr/avr.c (avr_set_current_function): Don't error if
        naked, OS_task or OS_main are specified at the same time.
        (avr_function_ok_for_sibcall): Don't disable sibcalls for OS_task,
        OS_main.
        (avr_insert_attributes) [-mmain-is-OS_task] <main>: Add OS_task
        attribute.
        * common/config/avr/avr-common.c (avr_option_optimization_table):
        Switch on -mmain-is-OS_task 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_mmain_is_OS_task, 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)
@@ -1030,9 +1030,6 @@ avr_no_gccisr_function_p (tree func)
 static void
 avr_set_current_function (tree decl)
 {
-  location_t loc;
-  const char *isr;
-
   if (decl == NULL_TREE
       || current_function_decl == NULL_TREE
       || current_function_decl == error_mark_node
@@ -1040,7 +1037,7 @@ avr_set_current_function (tree decl)
       || cfun->machine->attributes_checked_p)
     return;
 
-  loc = DECL_SOURCE_LOCATION (decl);
+  location_t loc = DECL_SOURCE_LOCATION (decl);
 
   cfun->machine->is_naked = avr_naked_function_p (decl);
   cfun->machine->is_signal = avr_signal_function_p (decl);
@@ -1049,21 +1046,19 @@ avr_set_current_function (tree decl)
   cfun->machine->is_OS_main = avr_OS_main_function_p (decl);
   cfun->machine->is_no_gccisr = avr_no_gccisr_function_p (decl);
 
-  isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
+  const char *isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
 
   /* Too much attributes make no sense as they request conflicting features. */
 
-  if (cfun->machine->is_OS_task + cfun->machine->is_OS_main
-      + (cfun->machine->is_signal || cfun->machine->is_interrupt) > 1)
-    error_at (loc, "function attributes %qs, %qs and %qs are mutually"
-              " exclusive", "OS_task", "OS_main", isr);
-
-  /* 'naked' will hide effects of 'OS_task' and 'OS_main'.  */
-
-  if (cfun->machine->is_naked
-      && (cfun->machine->is_OS_task || cfun->machine->is_OS_main))
-    warning_at (loc, OPT_Wattributes, "function attributes %qs and %qs have"
-                " no effect on %qs function", "OS_task", "OS_main", "naked");
+  if (cfun->machine->is_OS_task
+      && (cfun->machine->is_signal || cfun->machine->is_interrupt))
+    error_at (loc, "function attributes %qs and %qs are mutually exclusive",
+              "OS_task", isr);
+
+  if (cfun->machine->is_OS_main
+      && (cfun->machine->is_signal || cfun->machine->is_interrupt))
+    error_at (loc, "function attributes %qs and %qs are mutually exclusive",
+              "OS_main", isr);
 
   if (cfun->machine->is_interrupt || cfun->machine->is_signal)
     {
@@ -3526,12 +3521,7 @@ avr_function_ok_for_sibcall (tree decl_c
   if (cfun->machine->is_interrupt
       || cfun->machine->is_signal
       || cfun->machine->is_naked
-      || avr_naked_function_p (decl_callee)
-      /* FIXME: For OS_task and OS_main, this might be over-conservative.  */
-      || (avr_OS_task_function_p (decl_callee)
-          != cfun->machine->is_OS_task)
-      || (avr_OS_main_function_p (decl_callee)
-          != cfun->machine->is_OS_main))
+      || avr_naked_function_p (decl_callee))
     {
       return false;
     }
@@ -10101,13 +10091,29 @@ avr_pgm_check_var_decl (tree node)
 }
 
 
-/* Add the section attribute if the variable is in progmem.  */
+/* Implement `TARGET_INSERT_ATTRIBUTES'.  */
 
 static void
 avr_insert_attributes (tree node, tree *attributes)
 {
   avr_pgm_check_var_decl (node);
 
+  if (TARGET_MAIN_IS_OS_TASK
+      && TREE_CODE (node) == FUNCTION_DECL
+      && MAIN_NAME_P (DECL_NAME (node))
+      // FIXME:  We'd like to also test `flag_hosted' which is only
+      // available in the C-ish fronts, hence 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 (node)))
+      && NULL == lookup_attribute ("OS_task", *attributes))
+    {
+      *attributes = tree_cons (get_identifier ("OS_task"),
+                               NULL, *attributes);
+    }
+
+  /* Add the section attribute if the variable is in progmem.  */
+
   if (TREE_CODE (node) == VAR_DECL
       && (TREE_STATIC (node) || DECL_EXTERNAL (node))
       && avr_progmem_p (node, *attributes))
Index: config/avr/avr.opt
===================================================================
--- config/avr/avr.opt	(revision 256338)
+++ config/avr/avr.opt	(working copy)
@@ -64,6 +64,10 @@ mbranch-cost=
 Target Report Joined RejectNegative UInteger Var(avr_branch_cost) Init(0)
 Set the branch costs for conditional branch instructions.  Reasonable values are small, non-negative integers.  The default branch cost is 0.
 
+mmain-is-OS_task
+Target Report Mask(MAIN_IS_OS_TASK)
+Treat main as if it had attribute OS_task.
+
 morder1
 Target Report Undocumented Mask(ORDER_1)
 
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
+-mmain-is-OS_task -mrelax  -mrmw  -mstrict-X  -mtiny-stack @gol
+-mfract-convert-truncate @gol
 -mshort-calls  -nodevicelib @gol
 -Waddr-space-convert  -Wmisspelled-isr}
 
@@ -16462,6 +16463,12 @@ and @code{long long} is 4 bytes.  Please
 conform to the C standards, but it results in smaller code
 size.
 
+@item -mmain-is-OS_task
+@opindex mmain-is-OS_task
+Do not save registers in @code{main}.  The effect is similar to
+attaching attribute @ref{AVR Function Attributes,,@code{OS_task}}
+to @code{main}. It is activated per default if optimization is on.
+
 @item -mn-flash=@var{num}
 @opindex mn-flash
 Assume that the flash memory has a size of 

Reply via email to