This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[AVR] Add 'OS_main' attribute. (Need middle-end approval.)
- From: Anatoly Sokolov <aesok at post dot ru>
- To: gcc-patches at gcc dot gnu dot org
- Cc: aesok at post dot ru, eweddington at cso dot atmel dot com
- Date: Thu, 3 Apr 2008 19:57:42 +0400
- Subject: [AVR] Add 'OS_main' attribute. (Need middle-end approval.)
Hello.
This patch adds an 'OS_main' attribute to the AVR port. The 'main' functions
with 'OS_main' attribute do not save any "call-saved" registers, requiring
less stack space.
This patch add the 'prologue_contains' function in 'function.c' file.
Please consider this for approval.
2008-04-03 Anatoly Sokolov <aesok@post.ru>
* rtl.h (prologue_contains): New declaration.
* function.c (prologue_contains): New function.
* config/avr/avr.h (machine_function): Add 'is_OS_main' field.
* config/avr/avr.c (avr_OS_main_function_p): Add new function.
(avr_attribute_table): Add 'OS_main' function attribute.
(avr_regs_to_save, expand_prologue, expand_epilogue, output_movhi):
Handle functions with 'OS_main' attribute.
Index: gcc/function.c
===================================================================
--- gcc/function.c (revision 133869)
+++ gcc/function.c (working copy)
@@ -4698,6 +4698,14 @@
}
int
+prologue_contains (const_rtx insn)
+{
+ if (contains (insn, &prologue))
+ return 1;
+ return 0;
+}
+
+int
prologue_epilogue_contains (const_rtx insn)
{
if (contains (insn, &prologue))
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h (revision 133869)
+++ gcc/rtl.h (working copy)
@@ -2128,6 +2128,7 @@
/* In function.c */
extern void reposition_prologue_and_epilogue_notes (void);
+extern int prologue_contains (const_rtx);
extern int prologue_epilogue_contains (const_rtx);
extern int sibcall_epilogue_contains (const_rtx);
extern void mark_temp_addr_taken (rtx);
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c (revision 133869)
+++ gcc/config/avr/avr.c (working copy)
@@ -52,6 +52,7 @@
static int interrupt_function_p (tree);
static int signal_function_p (tree);
static int avr_OS_task_function_p (tree);
+static int avr_OS_main_function_p (tree);
static int avr_regs_to_save (HARD_REG_SET *);
static int sequent_regs_live (void);
static const char *ptrreg_to_str (int);
@@ -465,6 +466,19 @@
return a != NULL_TREE;
}
+/* Return nonzero if FUNC is a OS_main function. */
+
+static int
+avr_OS_main_function_p (tree func)
+{
+ tree a;
+
+ gcc_assert (TREE_CODE (func) == FUNCTION_DECL);
+
+ a = lookup_attribute ("OS_main", TYPE_ATTRIBUTES (TREE_TYPE (func)));
+ return a != NULL_TREE;
+}
+
/* Return the number of hard registers to push/pop in the prologue/epilogue
of the current function, and optionally store these registers in SET. */
@@ -481,9 +495,10 @@
count = 0;
/* No need to save any registers if the function never returns or
- is have "OS_task" attribute. */
+ is have "OS_task" or "OS_main" attribute. */
if (TREE_THIS_VOLATILE (current_function_decl)
- || cfun->machine->is_OS_task)
+ || cfun->machine->is_OS_task
+ || cfun->machine->is_OS_main)
return 0;
for (reg = 0; reg < 32; reg++)
@@ -610,6 +625,7 @@
cfun->machine->is_interrupt = interrupt_function_p (current_function_decl);
cfun->machine->is_signal = signal_function_p (current_function_decl);
cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl);
+ cfun->machine->is_OS_main = avr_OS_main_function_p (current_function_decl);
/* Prologue: naked. */
if (cfun->machine->is_naked)
@@ -623,6 +639,7 @@
&& !cfun->machine->is_interrupt
&& !cfun->machine->is_signal
&& !cfun->machine->is_OS_task
+ && !cfun->machine->is_OS_main
&& live_seq);
if (cfun->machine->is_interrupt || cfun->machine->is_signal)
@@ -692,7 +709,7 @@
}
if (frame_pointer_needed)
{
- if(!cfun->machine->is_OS_task)
+ if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
{
/* Push frame pointer. */
insn = emit_move_insn (pushword, frame_pointer_rtx);
@@ -846,6 +863,7 @@
&& !cfun->machine->is_interrupt
&& !cfun->machine->is_signal
&& !cfun->machine->is_OS_task
+ && !cfun->machine->is_OS_main
&& live_seq);
if (minimize && (frame_pointer_needed || live_seq > 4))
@@ -908,7 +926,7 @@
emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
}
}
- if(!cfun->machine->is_OS_task)
+ if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
{
/* Restore previous frame_pointer. */
emit_insn (gen_pophi (frame_pointer_rtx));
@@ -1684,7 +1702,10 @@
else if (TARGET_NO_INTERRUPTS
|| (reload_completed
&& cfun->machine->is_signal
- && prologue_epilogue_contains (insn)))
+ && prologue_epilogue_contains (insn))
+ || (reload_completed
+ && cfun->machine->is_OS_main
+ && prologue_contains (insn)))
{
*l = 2;
return (AS2 (out,__SP_H__,%B1) CR_TAB
@@ -4610,6 +4631,7 @@
{ "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
{ "naked", 0, 0, false, true, true, avr_handle_fntype_attribute },
{ "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute },
+ { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
Index: gcc/config/avr/avr.h
===================================================================
--- gcc/config/avr/avr.h (revision 133869)
+++ gcc/config/avr/avr.h (working copy)
@@ -1039,7 +1039,11 @@
as specified by the "signal" attribute. */
int is_signal;
- /* 'true' - if current function is a signal function
+ /* 'true' - if current function is a task function
as specified by the "OS_task" attribute. */
int is_OS_task;
+
+ /* 'true' - if current function is a 'main' function
+ as specified by the "OS_main" attribute. */
+ int is_OS_main;
};
Anatoly