From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30557 invoked by alias); 7 May 2015 08:13:53 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 29845 invoked by uid 89); 7 May 2015 08:13:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.8 required=5.0 tests=AWL,BAYES_99,KAM_LAZY_DOMAIN_SECURITY,KAM_STOCKGEN,RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 X-HELO: mx08-00178001.pphosted.com Received: from mx08-00178001.pphosted.com (HELO mx08-00178001.pphosted.com) (91.207.212.93) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Thu, 07 May 2015 08:13:50 +0000 Received: from pps.filterd (m0046660.ppops.net [127.0.0.1]) by mx08-00178001.pphosted.com (8.14.5/8.14.5) with SMTP id t478DYDD020910; Thu, 7 May 2015 10:13:40 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-00178001.pphosted.com with ESMTP id 1u67070xb2-1 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT); Thu, 07 May 2015 10:13:40 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 5641D34; Thu, 7 May 2015 08:13:38 +0000 (GMT) Received: from Webmail-eu.st.com (safex1hubcas5.st.com [10.75.90.71]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 1EC0C4FA1; Thu, 7 May 2015 08:13:38 +0000 (GMT) Received: from [164.129.122.197] (164.129.122.197) by webmail-eu.st.com (10.75.90.13) with Microsoft SMTP Server (TLS) id 8.3.342.0; Thu, 7 May 2015 10:13:37 +0200 Message-ID: <554B1EB1.1050607@st.com> Date: Thu, 07 May 2015 08:13:00 -0000 From: Christian Bruel User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.6.0 MIME-Version: 1.0 To: , Ramana Radhakrishnan , Richard Earnshaw , Nicholas Clifton , Subject: Re: [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (4th) References: <554A243B.8010902@st.com> In-Reply-To: <554A243B.8010902@st.com> Content-Type: multipart/mixed; boundary="------------070802070509060005040602" X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.14.151,1.0.33,0.0.0000 definitions=2015-05-07_02:2015-05-05,2015-05-07,1970-01-01 signatures=0 X-IsSubscribed: yes X-SW-Source: 2015-05/txt/msg00517.txt.bz2 --------------070802070509060005040602 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Content-length: 523 + Sandra's doc review fixes. tested with make doc pdf thanks Christian On 05/06/2015 04:24 PM, Christian Bruel wrote: > Implements and document the hooks to support target_attributes. > > The emission of blx is handled directly for armv5 to overcome a bug with > the current binutils that fails with calls to a static symbol in a > different section. (e.g .text -> .text.startup) in different modes. > > (ref https://sourceware.org/bugzilla/show_bug.cgi?id=17505) > > Regtests included > > Thanks > > Christian > --------------070802070509060005040602 Content-Type: text/x-patch; name="p4.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="p4.patch" Content-length: 22203 2014-09-23 Christian Bruel * config/arm/arm.opt (THUMB, arm_restrict_it, inline_asm_unified): Save. * config/arm/arm.h (arm_valid_target_attribute_tree): Declare. (arm_reset_previous_fndecl, arm_change_mode_p): Likewise. (SWITCHABLE_TARGET): Define. * config/arm/arm.c (arm_reset_previous_fndecl): New functions. (arm_valid_target_attribute_tree, arm_change_mode_p): Likewise. (arm_valid_target_attribute_p): Likewise. (arm_set_current_function, arm_can_inline_p): Likewise. (arm_valid_target_attribute_rec): Likewise. (arm_previous_fndecl): New variable. (TARGET_SET_CURRENT_FUNCTION, TARGET_OPTION_VALID_ATTRIBUTE_P): Define. (TARGET_CAN_INLINE_P): Define. (arm_asm_trampoline_template): Emit mode. (arm_file_start): Don't set unified syntax. (arm_declare_function_name): Set unified syntax and mode. (arm_option_override): Init target_option_default_node. and target_option_current_node. * config/arm/arm.md (*call_value_symbol): Set mode when possible. (*call_symbol): Likewise. * doc/extend.texi: Document ARM target and pragma attribute. * doc/invoke.texi: Likewise. 2014-09-23 Christian Bruel * gcc.target/arm/attr_arm.c: New test * gcc.target/arm/attr_arm-err.c: New test * gcc.target/arm/attr_thumb.c: New test * gcc.target/arm/attr_thumb-static.c: New test diff '--exclude=3D.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm.c gnu_trun= k.p4/gcc/gcc/config/arm/arm.c --- gnu_trunk.p3/gcc/gcc/config/arm/arm.c 2015-05-06 14:31:48.750726995 +02= 00 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm.c 2015-05-06 15:03:29.393992051 +02= 00 @@ -94,6 +94,7 @@ #include "opts.h" #include "dumpfile.h" #include "gimple-expr.h" +#include "target-globals.h" #include "builtins.h" #include "tm-constrs.h" #include "rtl-iter.h" @@ -264,6 +265,9 @@ static void arm_expand_builtin_va_start (tree, rtx); static tree arm_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq= *); static void arm_option_override (void); +static void arm_set_current_function (tree); +static bool arm_can_inline_p (tree, tree); +static bool arm_valid_target_attribute_p (tree, tree, tree, int); static unsigned HOST_WIDE_INT arm_shift_truncation_mask (machine_mode); static bool arm_macro_fusion_p (void); static bool arm_cannot_copy_insn_p (rtx_insn *); @@ -412,6 +416,9 @@ #undef TARGET_ASM_FUNCTION_EPILOGUE #define TARGET_ASM_FUNCTION_EPILOGUE arm_output_function_epilogue =20 +#undef TARGET_CAN_INLINE_P +#define TARGET_CAN_INLINE_P arm_can_inline_p + #undef TARGET_OPTION_OVERRIDE #define TARGET_OPTION_OVERRIDE arm_option_override =20 @@ -430,6 +437,12 @@ #undef TARGET_SCHED_ADJUST_COST #define TARGET_SCHED_ADJUST_COST arm_adjust_cost =20 +#undef TARGET_SET_CURRENT_FUNCTION +#define TARGET_SET_CURRENT_FUNCTION arm_set_current_function + +#undef TARGET_OPTION_VALID_ATTRIBUTE_P +#define TARGET_OPTION_VALID_ATTRIBUTE_P arm_valid_target_attribute_p + #undef TARGET_SCHED_REORDER #define TARGET_SCHED_REORDER arm_sched_reorder =20 @@ -2750,6 +2763,9 @@ } } =20 +/* Options after initial target override. */ +static GTY(()) tree init_optimize; + /* Reset options between modes that the user has specified. */ static void arm_option_override_internal (struct gcc_options *opts, @@ -2772,6 +2788,10 @@ if (TREE_TARGET_THUMB (opts) && TARGET_CALLEE_INTERWORKING) opts->x_target_flags |=3D MASK_INTERWORK; =20 + /* need to remember initial values so combinaisons of options like + -mflip-thumb -mthumb -fno-schedule-insns work for any attribute. */ + cl_optimization *to =3D TREE_OPTIMIZATION (init_optimize); + if (! opts_set->x_arm_restrict_it) opts->x_arm_restrict_it =3D arm_arch8; =20 @@ -2779,15 +2799,17 @@ opts->x_arm_restrict_it =3D 0; =20 if (TREE_TARGET_THUMB1 (opts)) - { - /* Don't warn since it's on by default in -O2. */ - opts->x_flag_schedule_insns =3D 0; - } + /* Don't warn since it's on by default in -O2. */ + opts->x_flag_schedule_insns =3D 0; + else + opts->x_flag_schedule_insns =3D to->x_flag_schedule_insns; =20 /* Disable shrink-wrap when optimizing function for size, since it tends= to generate additional returns. */ if (optimize_function_for_size_p (cfun) && TREE_TARGET_THUMB2 (opts)) opts->x_flag_shrink_wrap =3D false; + else + opts->x_flag_shrink_wrap =3D to->x_flag_shrink_wrap; =20 /* In Thumb1 mode, we emit the epilogue in RTL, but the last insn - epilogue_insns - does not accurately model the corresponding insns @@ -2799,6 +2821,8 @@ fipa-ra. */ if (TREE_TARGET_THUMB1 (opts)) opts->x_flag_ipa_ra =3D 0; + else + opts->x_flag_ipa_ra =3D to->x_flag_ipa_ra; =20 /* Thumb2 inline assembly code should always use unified syntax. This will apply to ARM and Thumb1 eventually. */ @@ -3291,12 +3315,20 @@ && (!arm_arch7 || !current_tune->prefer_ldrd_strd)) flag_schedule_fusion =3D 0; =20 + /* Need to remember initial options before they are overriden. */ + init_optimize =3D build_optimization_node (&global_options); + arm_option_override_internal (&global_options, &global_options_set); arm_option_check_internal (&global_options); arm_option_params_internal (&global_options); =20 /* Register global variables with the garbage collector. */ arm_add_gc_roots (); + + /* Save the initial options in case the user does function specific + options. */ + target_option_default_node =3D target_option_current_node + =3D build_target_option_node (&global_options); } =20 static void @@ -3450,13 +3482,20 @@ static void arm_asm_trampoline_template (FILE *f) { + if (TARGET_UNIFIED_ASM) + fprintf (f, "\t.syntax unified\n"); + else + fprintf (f, "\t.syntax divided\n"); + if (TARGET_ARM) { + fprintf (f, "\t.arm\n"); asm_fprintf (f, "\tldr\t%r, [%r, #0]\n", STATIC_CHAIN_REGNUM, PC_REG= NUM); asm_fprintf (f, "\tldr\t%r, [%r, #0]\n", PC_REGNUM, PC_REGNUM); } else if (TARGET_THUMB2) { + fprintf (f, "\t.thumb\n"); /* The Thumb-2 trampoline is similar to the arm implementation. Unlike 16-bit Thumb, we enter the stub in thumb mode. */ asm_fprintf (f, "\tldr.w\t%r, [%r, #4]\n", @@ -23903,6 +23942,23 @@ return 0; } =20 +/* Check that FUNC is called with a different mode. */ + +bool +arm_change_mode_p (tree func) +{ + if (TREE_CODE (func) !=3D FUNCTION_DECL) + return false; + + tree callee_tree =3D DECL_FUNCTION_SPECIFIC_TARGET (func); + + if (!callee_tree) + callee_tree =3D target_option_default_node; + + struct cl_target_option *callee_opts =3D TREE_TARGET_OPTION (callee_tree= ); + + return (TREE_TARGET_THUMB (callee_opts) !=3D TARGET_THUMB); +} =20 /* Given the stack offsets and register mask in OFFSETS, decide how many additional registers to push instead of subtracting a constant @@ -25518,9 +25574,6 @@ { int val; =20 - if (TARGET_UNIFIED_ASM) - asm_fprintf (asm_out_file, "\t.syntax unified\n"); - if (TARGET_BPABI) { const char *fpu_name; @@ -29271,9 +29324,196 @@ && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0))); } =20 +/* Remember the last target of arm_set_current_function. */ +static GTY(()) tree arm_previous_fndecl; + +/* Invalidate arm_previous_fndecl. */ +void +arm_reset_previous_fndecl (void) +{ + arm_previous_fndecl =3D NULL_TREE; +} + +/* Establish appropriate back-end context for processing the function + FNDECL. The argument might be NULL to indicate processing at top + level, outside of any function scope. */ +static void +arm_set_current_function (tree fndecl) +{ + if (!fndecl || fndecl =3D=3D arm_previous_fndecl) + return; + + tree old_tree =3D (arm_previous_fndecl + ? DECL_FUNCTION_SPECIFIC_TARGET (arm_previous_fndecl) + : NULL_TREE); + + tree new_tree =3D DECL_FUNCTION_SPECIFIC_TARGET (fndecl); + + arm_previous_fndecl =3D fndecl; + if (old_tree =3D=3D new_tree) + ; + + else if (new_tree) + { + cl_target_option_restore (&global_options, + TREE_TARGET_OPTION (new_tree)); + + if (TREE_TARGET_GLOBALS (new_tree)) + restore_target_globals (TREE_TARGET_GLOBALS (new_tree)); + else + TREE_TARGET_GLOBALS (new_tree) + =3D save_target_globals_default_opts (); + } + + else if (old_tree) + { + new_tree =3D target_option_current_node; + + cl_target_option_restore (&global_options, + TREE_TARGET_OPTION (new_tree)); + if (TREE_TARGET_GLOBALS (new_tree)) + restore_target_globals (TREE_TARGET_GLOBALS (new_tree)); + else if (new_tree =3D=3D target_option_default_node) + restore_target_globals (&default_target_globals); + else + TREE_TARGET_GLOBALS (new_tree) + =3D save_target_globals_default_opts (); + } + + arm_option_params_internal (&global_options); +} + +/* Hook to determine if one function can safely inline another. */ + +static bool +arm_can_inline_p (tree caller ATTRIBUTE_UNUSED, tree callee ATTRIBUTE_UNUS= ED) +{ + /* Overidde default hook: Always OK to inline between different modes.=20 + Function with mode specific instructions, e.g using asm, must be expl= icitely=20 + protected with noinline. */ + return true; +} + +/* Inner function to process the attribute((target(...))), take an argumen= t and + set the current options from the argument. If we have a list, recursiv= ely + go over the list. */ + +static bool +arm_valid_target_attribute_rec (tree args, struct gcc_options *opts) +{ + if (TREE_CODE (args) =3D=3D TREE_LIST) + { + bool ret =3D true; + for (; args; args =3D TREE_CHAIN (args)) + if (TREE_VALUE (args) + && !arm_valid_target_attribute_rec (TREE_VALUE (args), opts)) + ret =3D false; + return ret; + } + + else if (TREE_CODE (args) !=3D STRING_CST) + { + error ("attribute % argument not a string"); + return false; + } + + char *argstr =3D ASTRDUP (TREE_STRING_POINTER (args)); + while (argstr && *argstr !=3D '\0') + { + while (ISSPACE (*argstr)) + argstr++; + + if (!strcmp (argstr, "thumb")) + { + opts->x_target_flags |=3D MASK_THUMB; + arm_option_check_internal (opts); + return true; + } + + if (!strcmp (argstr, "arm")) + { + opts->x_target_flags &=3D ~MASK_THUMB; + arm_option_check_internal (opts); + return true; + } + + warning (0, "attribute(target(\"%s\")) is unknown", argstr); + return false; + } + + return false; +} + +/* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. = */ + +tree +arm_valid_target_attribute_tree (tree args, struct gcc_options *opts, + struct gcc_options *opts_set) +{ + if (!arm_valid_target_attribute_rec (args, opts)) + return NULL_TREE; + + /* Do any overrides, such as global options arch=3Dxxx. */ + arm_option_override_internal (opts, opts_set); + + return build_target_option_node (opts); +} + +/* Hook to validate attribute((target("string"))). */ + +static bool +arm_valid_target_attribute_p (tree fndecl, tree ARG_UNUSED (name), + tree args, int ARG_UNUSED (flags)) +{ + bool ret =3D true; + struct gcc_options func_options; + tree cur_tree, new_optimize; + gcc_assert ((fndecl !=3D NULL_TREE) && (args !=3D NULL_TREE)); + + /* Get the optimization options of the current function. */ + tree func_optimize =3D DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); + + /* If the function changed the optimization levels as well as setting ta= rget + options, start with the optimizations specified. */ + if (!func_optimize) + func_optimize =3D optimization_default_node; + + /* Init func_options. */ + memset (&func_options, 0, sizeof (func_options)); + init_options_struct (&func_options, NULL); + lang_hooks.init_options_struct (&func_options); + + /* Initialize func_options to the defaults. */ + cl_optimization_restore (&func_options, + TREE_OPTIMIZATION (func_optimize)); + + cl_target_option_restore (&func_options, + TREE_TARGET_OPTION (target_option_default_node)); + + /* Set func_options flags with new target mode. */ + cur_tree =3D arm_valid_target_attribute_tree (args, &func_options, + &global_options_set); + + if (cur_tree =3D=3D NULL_TREE) + ret =3D false; + + new_optimize =3D build_optimization_node (&func_options); + + DECL_FUNCTION_SPECIFIC_TARGET (fndecl) =3D cur_tree; + + DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) =3D new_optimize; + + return ret; +} + void arm_declare_function_name (FILE *stream, const char *name, tree decl) { + if (TARGET_UNIFIED_ASM) + fprintf (stream, "\t.syntax unified\n"); + else + fprintf (stream, "\t.syntax divided\n"); + if (TARGET_THUMB) { if (is_called_in_ARM_mode (decl) @@ -29285,6 +29525,8 @@ else fprintf (stream, "\t.thumb\n\t.thumb_func\n"); } + else + fprintf (stream, "\t.arm\n"); =20 if (TARGET_POKE_FUNCTION_NAME) arm_poke_function_name (stream, (const char *) name); diff '--exclude=3D.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm.h gnu_trun= k.p4/gcc/gcc/config/arm/arm.h --- gnu_trunk.p3/gcc/gcc/config/arm/arm.h 2015-05-06 14:31:48.750726995 +02= 00 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm.h 2015-05-06 14:36:32.227213416 +02= 00 @@ -2332,4 +2332,8 @@ =20 #define DRIVER_SELF_SPECS MCPU_MTUNE_NATIVE_SPECS #define TARGET_SUPPORTS_WIDE_INT 1 + +/* For switching between functions with different target attributes. */ +#define SWITCHABLE_TARGET 1 + #endif /* ! GCC_ARM_H */ diff '--exclude=3D.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm.md gnu_tru= nk.p4/gcc/gcc/config/arm/arm.md --- gnu_trunk.p3/gcc/gcc/config/arm/arm.md 2015-05-06 14:31:40.678713158 +0= 200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm.md 2015-05-06 14:36:32.231213422 +0= 200 @@ -7722,6 +7722,13 @@ && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))" "* { + rtx op =3D operands[0]; + + /* Switch mode now when possible. */ + if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op)) + && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op))) + return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\"; + return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\"; }" [(set_attr "type" "call")] @@ -7739,6 +7746,13 @@ && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))" "* { + rtx op =3D operands[1]; + + /* Switch mode now when possible. */ + if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op)) + && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op))) + return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\"; + return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\"; }" [(set_attr "type" "call")] diff '--exclude=3D.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm.opt gnu_tr= unk.p4/gcc/gcc/config/arm/arm.opt --- gnu_trunk.p3/gcc/gcc/config/arm/arm.opt 2015-03-30 10:44:52.901327167 += 0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm.opt 2015-05-06 14:36:32.231213422 += 0200 @@ -182,7 +182,7 @@ Specify the minimum bit alignment of structures =20 mthumb -Target Report RejectNegative Mask(THUMB) +Target Report RejectNegative Mask(THUMB) Save Generate code for Thumb state =20 mthumb-interwork @@ -246,7 +246,7 @@ Only generate absolute relocations on word sized values. =20 mrestrict-it -Target Report Var(arm_restrict_it) Init(2) +Target Report Var(arm_restrict_it) Init(2) Save Generate IT blocks appropriate for ARMv8. =20 mold-rtx-costs @@ -275,5 +275,5 @@ Assume loading data from flash is slower than fetching instructions. =20 masm-syntax-unified -Target Report Var(inline_asm_unified) Init(0) +Target Report Var(inline_asm_unified) Init(0) Save Assume unified syntax for Thumb inline assembly code. diff '--exclude=3D.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm-protos.h g= nu_trunk.p4/gcc/gcc/config/arm/arm-protos.h --- gnu_trunk.p3/gcc/gcc/config/arm/arm-protos.h 2015-05-06 14:31:48.750726= 995 +0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm-protos.h 2015-05-06 14:36:32.231213= 422 +0200 @@ -210,6 +210,9 @@ extern int arm_dllimport_p (tree); extern void arm_mark_dllexport (tree); extern void arm_mark_dllimport (tree); +extern bool arm_change_mode_p (tree); +extern tree arm_valid_target_attribute_tree (tree, struct gcc_options *, + struct gcc_options *); #endif =20 extern void arm_pr_long_calls (struct cpp_reader *); @@ -317,6 +320,8 @@ =20 extern void arm_emit_eabi_attribute (const char *, int, int); =20 +extern void arm_reset_previous_fndecl (void); + /* Defined in gcc/common/config/arm-common.c. */ extern const char *arm_rewrite_selected_cpu (const char *name); =20 diff '--exclude=3D.svn' -ruN gnu_trunk.p3/gcc/gcc/doc/extend.texi gnu_trunk= .p4/gcc/gcc/doc/extend.texi --- gnu_trunk.p3/gcc/gcc/doc/extend.texi 2015-05-06 09:00:31.232943164 +0200 +++ gnu_trunk.p4/gcc/gcc/doc/extend.texi 2015-05-07 09:43:01.087775682 +0200 @@ -3067,8 +3067,9 @@ or separate the options with a comma (@samp{,}) within a single string. =20 The options supported are specific to each target; refer to @ref{x86 -Function Attributes}, @ref{PowerPC Function Attributes}, and -@ref{Nios II Function Attributes}, for details. +Function Attributes}, @ref{PowerPC Function Attributes}, +@ref{ARM Function Attributes},and @ref{Nios II Function Attributes}, +for details. =20 @item unused @cindex @code{unused} function attribute @@ -3417,6 +3418,26 @@ =20 Variadic functions always use the @code{"aapcs"} calling convention and the compiler rejects attempts to specify an alternative. + +@item target (@var{options}) +@cindex @code{target} function attribute +As discussed in @ref{Common Function Attributes}, this attribute=20 +allows specification of target-specific compilation options. + +On ARM, the following options are allowed: + +@table @samp +@item thumb +@cindex @code{target("thumb")} function attribute, ARM +Force Thumb Thumb-2 code generation, depending on the architecture. + +@item arm +@cindex @code{target("arm")} function attribute, ARM +Force ARM code generation. +@end table + +Functions from different modes can be inlined in the caller's mode. + @end table =20 @node AVR Function Attributes @@ -18436,8 +18457,9 @@ @xref{Function Attributes}, for more information about the @code{target} attribute and the attribute syntax. =20 -The @code{#pragma GCC target} pragma is presently implemented for -x86, PowerPC, and Nios II targets only. +The @code{#pragma GCC target} pragma is implemented for +ARM, x86, PowerPC, and Nios II targets. + @end table =20 @table @code diff '--exclude=3D.svn' -ruN gnu_trunk.p3/gcc/gcc/doc/invoke.texi gnu_trunk= .p4/gcc/gcc/doc/invoke.texi --- gnu_trunk.p3/gcc/gcc/doc/invoke.texi 2015-05-06 09:00:31.232943164 +0200 +++ gnu_trunk.p4/gcc/gcc/doc/invoke.texi 2015-05-07 09:10:04.612347618 +0200 @@ -13434,6 +13434,10 @@ configuring GCC with the @option{--with-mode=3D}@var{state} configure option. =20 +You can also override the ARM and Thumb mode for each function +by using the @code{target("thumb")} and @code{target("arm")} function attr= ibutes +(@pxref{ARM Function Attributes}) or pragmas (@pxref{Function Specific Opt= ion Pragmas}). + @item -mtpcs-frame @opindex mtpcs-frame Generate a stack frame that is compliant with the Thumb Procedure Call diff '--exclude=3D.svn' -ruN gnu_trunk.p3/gcc/gcc/testsuite/gcc.target/arm/= attr_arm.c gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c --- gnu_trunk.p3/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c 1970-01-01 01:= 00:00.000000000 +0100 +++ gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c 2015-05-06 14:= 36:32.335213601 +0200 @@ -0,0 +1,13 @@ +/* Check that attribute target arm is recogniwed. */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_arm_ok } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler ".arm" } } */ +/* { dg-final { scan-assembler-not "ite" } } */ + +int __attribute__((target("arm"))) +foo(int a) +{ + return a ? 1 : 5; +} + diff '--exclude=3D.svn' -ruN gnu_trunk.p3/gcc/gcc/testsuite/gcc.target/arm/= attr_arm-err.c gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_arm-err.c --- gnu_trunk.p3/gcc/gcc/testsuite/gcc.target/arm/attr_arm-err.c 1970-01-01= 01:00:00.000000000 +0100 +++ gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_arm-err.c 2015-05-06= 14:36:32.335213601 +0200 @@ -0,0 +1,13 @@ +/* Check that attribute target arm is rejected for M profile. */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_arm_ok } */ +/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-march= =3D*" } { "-march=3Darmv6-m" } } */ +/* { dg-add-options arm_arch_v6m } */ + +int __attribute__((target("arm"))) +foo(int a) +{ /* { dg-error "does not support" } */ + return a ? 1 : 5; +} + + diff '--exclude=3D.svn' -ruN gnu_trunk.p3/gcc/gcc/testsuite/gcc.target/arm/= attr_thumb.c gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c --- gnu_trunk.p3/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c 1970-01-01 0= 1:00:00.000000000 +0100 +++ gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c 2015-05-06 1= 4:36:32.335213601 +0200 @@ -0,0 +1,13 @@ +/* Check that attribute target thumb is recogniwed. */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb2_ok } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler ".thumb" } } */ +/* { dg-final { scan-assembler "ite" } } */ + +int __attribute__((target("thumb"))) +foo(int a) +{ + return a ? 1 : 5; +} + diff '--exclude=3D.svn' -ruN gnu_trunk.p3/gcc/gcc/testsuite/gcc.target/arm/= attr_thumb-static.c gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_thum= b-static.c --- gnu_trunk.p3/gcc/gcc/testsuite/gcc.target/arm/attr_thumb-static.c 1970-= 01-01 01:00:00.000000000 +0100 +++ gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb-static.c 2015-= 05-06 14:36:32.335213601 +0200 @@ -0,0 +1,24 @@ +/* Check that a change mode to a static function is correctly handled. */ +/* { dg-do run } */ +/* { dg-require-effective-target arm_thumb1_ok } */ + +static void + __attribute__((__noinline__))=20 +foo (void) +{ + __asm__ (""); +} + +static void +__attribute__((__noinline__))=20 +__attribute__((target("thumb"))) +bar (void) +{ + __asm__ (""); +} + +int main() +{ + foo(); + bar(); +} --------------070802070509060005040602--