From patchwork Thu Jul 22 12:56:14 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jie Zhang X-Patchwork-Id: 59567 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id D98F1B6EF1 for ; Thu, 22 Jul 2010 22:56:30 +1000 (EST) Received: (qmail 27077 invoked by alias); 22 Jul 2010 12:56:28 -0000 Received: (qmail 27048 invoked by uid 22791); 22 Jul 2010 12:56:25 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 22 Jul 2010 12:56:19 +0000 Received: (qmail 17872 invoked from network); 22 Jul 2010 12:56:17 -0000 Received: from unknown (HELO ?192.168.1.100?) (jie@127.0.0.2) by mail.codesourcery.com with ESMTPA; 22 Jul 2010 12:56:17 -0000 Message-ID: <4C483FEE.5040605@codesourcery.com> Date: Thu, 22 Jul 2010 20:56:14 +0800 From: Jie Zhang User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.7) Gecko/20100713 Lightning/1.0b2 Thunderbird/3.1.1 MIME-Version: 1.0 To: GCC Patches Subject: [PATCH] Fix "naked" attribute (PR target/44290) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org The "naked" attribute should imply "noinline" and "noclone". This patch implements this for all the 5 targets which currently support the "naked" attribute: ARM, AVR, MCORE, RX, SPU. IPA-SRA should not apply to functions with "noclone" attribute. This patch adds a check to tree_versionable_function_p in ipa_sra_preliminary_function_checks. Bootstrapped and regression tested on x86_64. Testing for ARM NEON is OK, too. cc1 builds well for AVR, MCORE, RX, SPU. The two new tests pass on AVR, MCORE, RX. cc1 builds well for SPU, but the test cases cause ICE, even the patch is not applied. It seems that SPU target has a bug for the "naked" attribute somewhere. This is not a regression, I think. Is it OK? Regards, PR target/44290 * tree-sra.c (ipa_sra_preliminary_function_checks): Return false if ! tree_versionable_function_p. * config/arm/arm.c (arm_insert_attributes): New. (TARGET_INSERT_ATTRIBUTES): Define. * config/avr/avr.c (avr_insert_attributes): Insert "noinline" and "noclone" if "naked". * config/mcore/mcore.c (mcore_insert_attributes): New. (TARGET_INSERT_ATTRIBUTES): Define. * config/rx/rx.c (rx_insert_attributes): New. (TARGET_INSERT_ATTRIBUTES): Define. * config/spu/spu.c (spu_insert_attributes): New. (TARGET_INSERT_ATTRIBUTES): Define. * doc/extend.texi: Remove IP2K from the description of naked attribute. Add MCORE instead. testsuite/ PR target/44290 * gcc.dg/pr44290-1.c: New test. * gcc.dg/pr44290-2.c: New test. Index: doc/extend.texi =================================================================== --- doc/extend.texi (revision 162396) +++ doc/extend.texi (working copy) @@ -2743,7 +2743,7 @@ and newer. @item naked @cindex function without a prologue/epilogue code -Use this attribute on the ARM, AVR, IP2K, RX and SPU ports to indicate that +Use this attribute on the ARM, AVR, MCORE, RX and SPU ports to indicate that the specified function does not need prologue/epilogue sequences generated by the compiler. It is up to the programmer to provide these sequences. The only statements that can be safely included in naked functions are Index: testsuite/gcc.dg/pr44290-1.c =================================================================== --- testsuite/gcc.dg/pr44290-1.c (revision 0) +++ testsuite/gcc.dg/pr44290-1.c (revision 0) @@ -0,0 +1,18 @@ +/* { dg-do compile { target arm*-*-* avr-*-* mcore-*-* rx-*-* spu-*-* } } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +static void __attribute__((naked)) +foo(void *from, void *to) +{ + asm volatile("dummy"::"r"(from), "r"(to)); +} + +unsigned int fie[2]; + +void fum(void *to) +{ + foo(fie, to); +} + +/* { dg-final { scan-tree-dump "foo \\\(void \\\* from, void \\\* to\\\)" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ Index: testsuite/gcc.dg/pr44290-2.c =================================================================== --- testsuite/gcc.dg/pr44290-2.c (revision 0) +++ testsuite/gcc.dg/pr44290-2.c (revision 0) @@ -0,0 +1,24 @@ +/* { dg-do compile { target arm*-*-* avr-*-* mcore-*-* rx-*-* spu-*-* } } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +static unsigned long __attribute__((naked)) +foo (unsigned long base) +{ + asm volatile ("dummy"); +} +unsigned long +bar (void) +{ + static int start, set; + + if (!set) + { + set = 1; + start = foo (0); + } + + return foo (start); +} + +/* { dg-final { scan-tree-dump "foo \\\(long unsigned int base\\\)" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ Index: tree-sra.c =================================================================== --- tree-sra.c (revision 162396) +++ tree-sra.c (working copy) @@ -4285,6 +4285,13 @@ modify_function (struct cgraph_node *nod static bool ipa_sra_preliminary_function_checks (struct cgraph_node *node) { + if (!tree_versionable_function_p (current_function_decl)) + { + if (dump_file) + fprintf (dump_file, "Function isn't allowed to be versioned.\n"); + return false; + } + if (!cgraph_node_can_be_local_p (node)) { if (dump_file) Index: config/spu/spu.c =================================================================== --- config/spu/spu.c (revision 162396) +++ config/spu/spu.c (working copy) @@ -182,6 +182,7 @@ static int spu_sched_reorder (FILE *, in static tree spu_handle_fndecl_attribute (tree * node, tree name, tree args, int flags, bool *no_add_attrs); +static void spu_insert_attributes (tree, tree *); static tree spu_handle_vector_attribute (tree * node, tree name, tree args, int flags, bool *no_add_attrs); @@ -371,6 +372,9 @@ static const struct attribute_spec spu_a #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE spu_attribute_table +#undef TARGET_INSERT_ATTRIBUTES +#define TARGET_INSERT_ATTRIBUTES spu_insert_attributes + #undef TARGET_ASM_INTEGER #define TARGET_ASM_INTEGER spu_assemble_integer @@ -3922,6 +3926,24 @@ spu_naked_function_p (tree func) return a != NULL_TREE; } +/* A "naked" attribute implies "noinline" and "noclone". */ + +static void +spu_insert_attributes (tree node, tree *attributes) +{ + if (TREE_CODE (node) != FUNCTION_DECL + || lookup_attribute ("naked", *attributes) == NULL) + return; + + if (lookup_attribute ("noinline", *attributes) == NULL) + *attributes = tree_cons (get_identifier ("noinline"), + NULL, *attributes); + + if (lookup_attribute ("noclone", *attributes) == NULL) + *attributes = tree_cons (get_identifier ("noclone"), + NULL, *attributes); +} + int spu_initial_elimination_offset (int from, int to) { Index: config/rx/rx.c =================================================================== --- config/rx/rx.c (revision 162396) +++ config/rx/rx.c (working copy) @@ -2086,6 +2086,24 @@ rx_handle_func_attribute (tree * node, return NULL_TREE; } +/* A "naked" attribute implies "noinline" and "noclone". */ + +static void +rx_insert_attributes (tree node, tree *attributes) +{ + if (TREE_CODE (node) != FUNCTION_DECL + || lookup_attribute ("naked", *attributes) == NULL) + return; + + if (lookup_attribute ("noinline", *attributes) == NULL) + *attributes = tree_cons (get_identifier ("noinline"), + NULL, *attributes); + + if (lookup_attribute ("noclone", *attributes) == NULL) + *attributes = tree_cons (get_identifier ("noclone"), + NULL, *attributes); +} + /* Table of RX specific attributes. */ const struct attribute_spec rx_attribute_table[] = { @@ -2726,6 +2744,9 @@ rx_memory_move_cost (enum machine_mode m #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE rx_attribute_table +#undef TARGET_INSERT_ATTRIBUTES +#define TARGET_INSERT_ATTRIBUTES rx_insert_attributes + #undef TARGET_ASM_FILE_START #define TARGET_ASM_FILE_START rx_file_start Index: config/avr/avr.c =================================================================== --- config/avr/avr.c (revision 162396) +++ config/avr/avr.c (working copy) @@ -4905,6 +4905,20 @@ avr_insert_attributes (tree node, tree * thing const in the first place? */ TREE_READONLY (node) = 1; } + + /* A "naked" attribute implies "noinline" and "noclone". */ + + if (TREE_CODE (node) != FUNCTION_DECL + || lookup_attribute ("naked", *attributes) == NULL) + return; + + if (lookup_attribute ("noinline", *attributes) == NULL) + *attributes = tree_cons (get_identifier ("noinline"), + NULL, *attributes); + + if (lookup_attribute ("noclone", *attributes) == NULL) + *attributes = tree_cons (get_identifier ("noclone"), + NULL, *attributes); } /* A get_unnamed_section callback for switching to progmem_section. */ Index: config/mcore/mcore.c =================================================================== --- config/mcore/mcore.c (revision 162396) +++ config/mcore/mcore.c (working copy) @@ -128,6 +128,7 @@ static void mcore_mark_dllimport static int mcore_dllexport_p (tree); static int mcore_dllimport_p (tree); static tree mcore_handle_naked_attribute (tree *, tree, tree, int, bool *); +static void mcore_insert_attributes (tree, tree *); #ifdef OBJECT_FORMAT_ELF static void mcore_asm_named_section (const char *, unsigned int, tree); @@ -186,6 +187,8 @@ static const struct attribute_spec mcore #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE mcore_attribute_table +#undef TARGET_INSERT_ATTRIBUTES +#define TARGET_INSERT_ATTRIBUTES mcore_insert_attributes #undef TARGET_ASM_UNIQUE_SECTION #define TARGET_ASM_UNIQUE_SECTION mcore_unique_section #undef TARGET_ASM_FUNCTION_RODATA_SECTION @@ -3058,6 +3061,24 @@ mcore_handle_naked_attribute (tree * nod return NULL_TREE; } +/* A "naked" attribute implies "noinline" and "noclone". */ + +static void +mcore_insert_attributes (tree node, tree *attributes) +{ + if (TREE_CODE (node) != FUNCTION_DECL + || lookup_attribute ("naked", *attributes) == NULL) + return; + + if (lookup_attribute ("noinline", *attributes) == NULL) + *attributes = tree_cons (get_identifier ("noinline"), + NULL, *attributes); + + if (lookup_attribute ("noclone", *attributes) == NULL) + *attributes = tree_cons (get_identifier ("noclone"), + NULL, *attributes); +} + /* ??? It looks like this is PE specific? Oh well, this is what the old code did as well. */ Index: config/arm/arm.c =================================================================== --- config/arm/arm.c (revision 162396) +++ config/arm/arm.c (working copy) @@ -116,6 +116,7 @@ static unsigned long arm_compute_save_re static unsigned long arm_compute_save_reg_mask (void); static unsigned long arm_isr_value (tree); static unsigned long arm_compute_func_type (void); +static void arm_insert_attributes (tree, tree *); static tree arm_handle_fndecl_attribute (tree *, tree, tree, int, bool *); static tree arm_handle_pcs_attribute (tree *, tree, tree, int, bool *); static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *); @@ -315,6 +316,9 @@ static const struct attribute_spec arm_a #undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES #define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES arm_set_default_type_attributes +#undef TARGET_INSERT_ATTRIBUTES +#define TARGET_INSERT_ATTRIBUTES arm_insert_attributes + #undef TARGET_SCHED_ADJUST_COST #define TARGET_SCHED_ADJUST_COST arm_adjust_cost @@ -4592,6 +4596,24 @@ arm_pr_long_calls_off (struct cpp_reader arm_pragma_long_calls = OFF; } +/* A "naked" attribute implies "noinline" and "noclone". */ + +static void +arm_insert_attributes (tree node, tree *attributes) +{ + if (TREE_CODE (node) != FUNCTION_DECL + || lookup_attribute ("naked", *attributes) == NULL) + return; + + if (lookup_attribute ("noinline", *attributes) == NULL) + *attributes = tree_cons (get_identifier ("noinline"), + NULL, *attributes); + + if (lookup_attribute ("noclone", *attributes) == NULL) + *attributes = tree_cons (get_identifier ("noclone"), + NULL, *attributes); +} + /* Handle an attribute requiring a FUNCTION_DECL; arguments as in struct attribute_spec.handler. */ static tree