* [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (4th) @ 2015-05-06 14:25 Christian Bruel 2015-05-06 23:04 ` Sandra Loosemore 2015-05-07 8:13 ` [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (4th) Christian Bruel 0 siblings, 2 replies; 15+ messages in thread From: Christian Bruel @ 2015-05-06 14:25 UTC (permalink / raw) To: gcc-patches, Ramana Radhakrishnan, Richard Earnshaw, Nicholas Clifton [-- Attachment #1: Type: text/plain, Size: 373 bytes --] 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 [-- Attachment #2: p4.patch --] [-- Type: text/x-patch, Size: 21142 bytes --] 2014-09-23 Christian Bruel <christian.bruel@st.com> * 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. diff '--exclude=.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm.c gnu_trunk.p4/gcc/gcc/config/arm/arm.c --- gnu_trunk.p3/gcc/gcc/config/arm/arm.c 2015-05-06 14:31:48.750726995 +0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm.c 2015-05-06 15:03:29.393992051 +0200 @@ -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 +#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 @@ -430,6 +437,12 @@ #undef TARGET_SCHED_ADJUST_COST #define TARGET_SCHED_ADJUST_COST arm_adjust_cost +#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 @@ -2750,6 +2763,9 @@ } } +/* 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 |= MASK_INTERWORK; + /* need to remember initial values so combinaisons of options like + -mflip-thumb -mthumb -fno-schedule-insns work for any attribute. */ + cl_optimization *to = TREE_OPTIMIZATION (init_optimize); + if (! opts_set->x_arm_restrict_it) opts->x_arm_restrict_it = arm_arch8; @@ -2779,15 +2799,17 @@ opts->x_arm_restrict_it = 0; if (TREE_TARGET_THUMB1 (opts)) - { - /* Don't warn since it's on by default in -O2. */ - opts->x_flag_schedule_insns = 0; - } + /* Don't warn since it's on by default in -O2. */ + opts->x_flag_schedule_insns = 0; + else + opts->x_flag_schedule_insns = to->x_flag_schedule_insns; /* 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 = false; + else + opts->x_flag_shrink_wrap = to->x_flag_shrink_wrap; /* 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 = 0; + else + opts->x_flag_ipa_ra = to->x_flag_ipa_ra; /* 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 = 0; + /* Need to remember initial options before they are overriden. */ + init_optimize = 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); /* 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 = target_option_current_node + = build_target_option_node (&global_options); } 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_REGNUM); 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; } +/* Check that FUNC is called with a different mode. */ + +bool +arm_change_mode_p (tree func) +{ + if (TREE_CODE (func) != FUNCTION_DECL) + return false; + + tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (func); + + if (!callee_tree) + callee_tree = target_option_default_node; + + struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree); + + return (TREE_TARGET_THUMB (callee_opts) != TARGET_THUMB); +} /* 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; - 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))); } +/* 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 = 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 == arm_previous_fndecl) + return; + + tree old_tree = (arm_previous_fndecl + ? DECL_FUNCTION_SPECIFIC_TARGET (arm_previous_fndecl) + : NULL_TREE); + + tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); + + arm_previous_fndecl = fndecl; + if (old_tree == 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) + = save_target_globals_default_opts (); + } + + else if (old_tree) + { + new_tree = 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 == target_option_default_node) + restore_target_globals (&default_target_globals); + else + TREE_TARGET_GLOBALS (new_tree) + = 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_UNUSED) +{ + /* Overidde default hook: Always OK to inline between different modes. + Function with mode specific instructions, e.g using asm, must be explicitely + protected with noinline. */ + return true; +} + +/* Inner function to process the attribute((target(...))), take an argument and + set the current options from the argument. If we have a list, recursively + go over the list. */ + +static bool +arm_valid_target_attribute_rec (tree args, struct gcc_options *opts) +{ + if (TREE_CODE (args) == TREE_LIST) + { + bool ret = true; + for (; args; args = TREE_CHAIN (args)) + if (TREE_VALUE (args) + && !arm_valid_target_attribute_rec (TREE_VALUE (args), opts)) + ret = false; + return ret; + } + + else if (TREE_CODE (args) != STRING_CST) + { + error ("attribute %<target%> argument not a string"); + return false; + } + + char *argstr = ASTRDUP (TREE_STRING_POINTER (args)); + while (argstr && *argstr != '\0') + { + while (ISSPACE (*argstr)) + argstr++; + + if (!strcmp (argstr, "thumb")) + { + opts->x_target_flags |= MASK_THUMB; + arm_option_check_internal (opts); + return true; + } + + if (!strcmp (argstr, "arm")) + { + opts->x_target_flags &= ~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=xxx. */ + 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 = true; + struct gcc_options func_options; + tree cur_tree, new_optimize; + gcc_assert ((fndecl != NULL_TREE) && (args != NULL_TREE)); + + /* Get the optimization options of the current function. */ + tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); + + /* If the function changed the optimization levels as well as setting target + options, start with the optimizations specified. */ + if (!func_optimize) + func_optimize = 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 = arm_valid_target_attribute_tree (args, &func_options, + &global_options_set); + + if (cur_tree == NULL_TREE) + ret = false; + + new_optimize = build_optimization_node (&func_options); + + DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = cur_tree; + + DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = 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"); if (TARGET_POKE_FUNCTION_NAME) arm_poke_function_name (stream, (const char *) name); diff '--exclude=.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm.h gnu_trunk.p4/gcc/gcc/config/arm/arm.h --- gnu_trunk.p3/gcc/gcc/config/arm/arm.h 2015-05-06 14:31:48.750726995 +0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm.h 2015-05-06 14:36:32.227213416 +0200 @@ -2332,4 +2332,8 @@ #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=.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm.md gnu_trunk.p4/gcc/gcc/config/arm/arm.md --- gnu_trunk.p3/gcc/gcc/config/arm/arm.md 2015-05-06 14:31:40.678713158 +0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm.md 2015-05-06 14:36:32.231213422 +0200 @@ -7722,6 +7722,13 @@ && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))" "* { + rtx op = 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 = 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=.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm.opt gnu_trunk.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 mthumb -Target Report RejectNegative Mask(THUMB) +Target Report RejectNegative Mask(THUMB) Save Generate code for Thumb state mthumb-interwork @@ -246,7 +246,7 @@ Only generate absolute relocations on word sized values. 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. mold-rtx-costs @@ -275,5 +275,5 @@ Assume loading data from flash is slower than fetching instructions. 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=.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm-protos.h gnu_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.750726995 +0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm-protos.h 2015-05-06 14:36:32.231213422 +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 extern void arm_pr_long_calls (struct cpp_reader *); @@ -317,6 +320,8 @@ extern void arm_emit_eabi_attribute (const char *, int, int); +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); diff '--exclude=.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-06 14:50:05.632612233 +0200 @@ -3419,6 +3419,25 @@ the compiler rejects attempts to specify an alternative. @end table +@item target (@var{options}) +@cindex @code{target} function attribute +As discussed in @ref{Common Function Attributes}, this attribute +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 Thumb1 Thumb2 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 using the caller mode. + @node AVR Function Attributes @subsection AVR Function Attributes @@ -18436,8 +18455,9 @@ @xref{Function Attributes}, for more information about the @code{target} attribute and the attribute syntax. -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 @table @code diff '--exclude=.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-06 14:36:32.331213593 +0200 @@ -13434,6 +13434,10 @@ configuring GCC with the @option{--with-mode=}@var{state} configure option. +You can also override the ARM and Thumb mode for each function +by using the @code{target("thumb")} and @code{target("arm")} function attributes +(@pxref{Function Attributes}) or pragmas (@pxref{Function Specific Option Pragmas}). + @item -mtpcs-frame @opindex mtpcs-frame Generate a stack frame that is compliant with the Thumb Procedure Call diff '--exclude=.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=.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=*" } { "-march=armv6-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=.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 01:00:00.000000000 +0100 +++ gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c 2015-05-06 14: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=.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_thumb-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__)) +foo (void) +{ + __asm__ (""); +} + +static void +__attribute__((__noinline__)) +__attribute__((target("thumb"))) +bar (void) +{ + __asm__ (""); +} + +int main() +{ + foo(); + bar(); +} ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (4th) 2015-05-06 14:25 [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (4th) Christian Bruel @ 2015-05-06 23:04 ` Sandra Loosemore 2015-05-08 8:31 ` Ramana Radhakrishnan 2015-05-07 8:13 ` [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (4th) Christian Bruel 1 sibling, 1 reply; 15+ messages in thread From: Sandra Loosemore @ 2015-05-06 23:04 UTC (permalink / raw) To: Christian Bruel Cc: gcc-patches, Ramana Radhakrishnan, Richard Earnshaw, Nicholas Clifton On 05/06/2015 08:24 AM, Christian Bruel wrote: > diff '--exclude=.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-06 14:50:05.632612233 +0200 > @@ -3419,6 +3419,25 @@ > the compiler rejects attempts to specify an alternative. > @end table > > +@item target (@var{options}) > +@cindex @code{target} function attribute > +As discussed in @ref{Common Function Attributes}, this attribute > +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 Thumb1 Thumb2 code generation depending on the architecture. "Force Thumb or Thumb-2 code generation, depending on the architecture." (I believe that's ARM's official terminology, rather than "Thumb1" or "Thumb2".) > + > +@item arm > +@cindex @code{target("arm")} function attribute, ARM > +Force ARM code generation. > +@end table > + > +Functions from different modes can be inlined using the caller mode. "...the caller's mode." > + > @node AVR Function Attributes > @subsection AVR Function Attributes > > @@ -18436,8 +18455,9 @@ > @xref{Function Attributes}, for more information about the > @code{target} attribute and the attribute syntax. > > -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 > > @table @code Please also add a cross-reference to ARM Function Attributes in the main entry for @item target in Common Function Attributes, in this paragraph: 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. > diff '--exclude=.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-06 14:36:32.331213593 +0200 > @@ -13434,6 +13434,10 @@ > configuring GCC with the @option{--with-mode=}@var{state} > configure option. > > +You can also override the ARM and Thumb mode for each function > +by using the @code{target("thumb")} and @code{target("arm")} function attributes > +(@pxref{Function Attributes}) or pragmas (@pxref{Function Specific Option Pragmas}). You can make the first reference point at the ARM Function Attributes node, now that it exists, instead of the generic Function Attributes section. > + > @item -mtpcs-frame > @opindex mtpcs-frame > Generate a stack frame that is compliant with the Thumb Procedure Call -Sandra ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (4th) 2015-05-06 23:04 ` Sandra Loosemore @ 2015-05-08 8:31 ` Ramana Radhakrishnan 2015-05-18 7:18 ` Christian Bruel 2015-05-18 8:16 ` [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (5th) Christian Bruel 0 siblings, 2 replies; 15+ messages in thread From: Ramana Radhakrishnan @ 2015-05-08 8:31 UTC (permalink / raw) To: Sandra Loosemore, Christian Bruel; +Cc: gcc-patches, Richard Earnshaw, nickc I'm still playing with the code, so this is a partial review. We should prevent inlining of ARM state functions into functions we know will be T16 if !TARGET_SOFT_FLOAT on the grounds that the architecture doesn't have floating point instruction encodings in the T16 ISA (Thumb1). We'll just cause internal compiler errors if we allow this. On 07/05/15 00:03, Sandra Loosemore wrote: > On 05/06/2015 08:24 AM, Christian Bruel wrote: >> diff '--exclude=.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-06 14:50:05.632612233 +0200 >> @@ -3419,6 +3419,25 @@ >> the compiler rejects attempts to specify an alternative. >> @end table >> >> +@item target (@var{options}) >> +@cindex @code{target} function attribute >> +As discussed in @ref{Common Function Attributes}, this attribute >> +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 Thumb1 Thumb2 code generation depending on the architecture. > > "Force Thumb or Thumb-2 code generation, depending on the architecture." I'd rather it said something like "Force code generation in the Thumb (T16/ T32) ISA. The exact instructions chosen depends on the architecture levels chosen." >> + >> +@item arm >> +@cindex @code{target("arm")} function attribute, ARM >> +Force ARM code generation. "Force code generation in the ARM (A32) ISA." >> +@end table >> + >> +Functions from different modes can be inlined using the caller mode. Rewrite this based on the review comment about inlining in the Thumb16 state from ARM state. > > "...the caller's mode." > >> + >> @node AVR Function Attributes >> @subsection AVR Function Attributes >> >> @@ -18436,8 +18455,9 @@ >> @xref{Function Attributes}, for more information about the >> @code{target} attribute and the attribute syntax. >> >> -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. >> + I'd rather say this once we have proper support with arch, cpu and fpu options enabled. Until such a time I think this hunk is a bit premature. Ramana ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (4th) 2015-05-08 8:31 ` Ramana Radhakrishnan @ 2015-05-18 7:18 ` Christian Bruel 2015-05-18 8:16 ` [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (5th) Christian Bruel 1 sibling, 0 replies; 15+ messages in thread From: Christian Bruel @ 2015-05-18 7:18 UTC (permalink / raw) To: Ramana Radhakrishnan; +Cc: gcc-patches, Richard Earnshaw, nickc Hi Ramana, On 05/08/2015 10:31 AM, Ramana Radhakrishnan wrote: > > I'm still playing with the code, so this is a partial review. > > We should prevent inlining of ARM state functions into functions we know > will be T16 if !TARGET_SOFT_FLOAT on the grounds that the architecture > doesn't have floating point instruction encodings in the T16 ISA > (Thumb1). We'll just cause internal compiler errors if we allow this. > I tried to forge a bit with this situation, but I couldn't generate such inconsistencies, as the situation is rejected with a : "sorry, unimplemented: Thumb-1 hard-float VFP ABI" when using -march=armv6 -mthumb -mhard-float (would that match with T16 && !TARGET_SOFT_FLOAT) Do you have the example producing an ICE ? That would be interesting to add it in the testsuite. by the way, I think the error message should be changed from "sorry, unimplemented: Thumb-1 hard-float VFP ABI" to a user error: "Can't use Thumb-1 hard-float VFP ABI" Christian ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (5th) 2015-05-08 8:31 ` Ramana Radhakrishnan 2015-05-18 7:18 ` Christian Bruel @ 2015-05-18 8:16 ` Christian Bruel 2015-06-01 10:39 ` Kyrill Tkachov 1 sibling, 1 reply; 15+ messages in thread From: Christian Bruel @ 2015-05-18 8:16 UTC (permalink / raw) To: Ramana Radhakrishnan, Sandra Loosemore Cc: gcc-patches, Richard Earnshaw, nickc [-- Attachment #1: Type: text/plain, Size: 497 bytes --] Hi, Here is again a new version for patch [4/6]: (Implements and document the hooks to support target_attributes.) - Rewrote for conflicts introduced by the new macros defined in https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01198.html - Take your comments and Sandra's for documentation - I'd like to leave the inlining question apart with its own patch until we settle it. Is it OK with you ? https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01527.html many thanks, Christian [-- Attachment #2: p4.patch --] [-- Type: text/x-patch, Size: 21763 bytes --] 2014-09-23 Christian Bruel <christian.bruel@st.com> * 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/Thumb target attribute. * doc/invoke.texi: Likewise. 2014-09-23 Christian Bruel <christian.bruel@st.com> * 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=.svn' -ruN gnu_trunk.p2/gcc/gcc/config/arm/arm.c gnu_trunk.p4/gcc/gcc/config/arm/arm.c --- gnu_trunk.p2/gcc/gcc/config/arm/arm.c 2015-05-18 09:59:22.711435629 +0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm.c 2015-05-13 13:51:47.427088369 +0200 @@ -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" @@ -265,6 +266,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 *); @@ -413,6 +417,9 @@ #undef TARGET_ASM_FUNCTION_EPILOGUE #define TARGET_ASM_FUNCTION_EPILOGUE arm_output_function_epilogue +#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 @@ -431,6 +438,12 @@ #undef TARGET_SCHED_ADJUST_COST #define TARGET_SCHED_ADJUST_COST arm_adjust_cost +#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 @@ -2777,6 +2790,9 @@ max_insns_skipped = current_tune->max_insns_skipped; } +/* 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, @@ -2799,23 +2815,29 @@ if (TARGET_THUMB_P (opts->x_target_flags) && TARGET_CALLEE_INTERWORKING) opts->x_target_flags |= MASK_INTERWORK; + /* need to remember initial values so combinaisons of options like + -mflip-thumb -mthumb -fno-schedule-insns work for any attribute. */ + cl_optimization *to = TREE_OPTIMIZATION (init_optimize); + if (! opts_set->x_arm_restrict_it) opts->x_arm_restrict_it = arm_arch8; if (!TARGET_THUMB2_P (opts->x_target_flags)) opts->x_arm_restrict_it = 0; + /* Don't warn since it's on by default in -O2. */ if (TARGET_THUMB1_P (opts->x_target_flags)) - { - /* Don't warn since it's on by default in -O2. */ - opts->x_flag_schedule_insns = 0; - } + opts->x_flag_schedule_insns = 0; + else + opts->x_flag_schedule_insns = to->x_flag_schedule_insns; /* Disable shrink-wrap when optimizing function for size, since it tends to generate additional returns. */ if (optimize_function_for_size_p (cfun) && TARGET_THUMB2_P (opts->x_target_flags)) opts->x_flag_shrink_wrap = false; + else + opts->x_flag_shrink_wrap = to->x_flag_shrink_wrap; /* In Thumb1 mode, we emit the epilogue in RTL, but the last insn - epilogue_insns - does not accurately model the corresponding insns @@ -2827,6 +2849,8 @@ fipa-ra. */ if (TARGET_THUMB1_P (opts->x_target_flags)) opts->x_flag_ipa_ra = 0; + else + opts->x_flag_ipa_ra = to->x_flag_ipa_ra; /* Thumb2 inline assembly code should always use unified syntax. This will apply to ARM and Thumb1 eventually. */ @@ -3329,12 +3353,20 @@ && (!arm_arch7 || !current_tune->prefer_ldrd_strd)) flag_schedule_fusion = 0; + /* Need to remember initial options before they are overriden. */ + init_optimize = 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); /* 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 = target_option_current_node + = build_target_option_node (&global_options); } static void @@ -3488,13 +3520,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_REGNUM); 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", @@ -24190,6 +24229,24 @@ mark_reg_pointer (arg_pointer_rtx, PARM_BOUNDARY); } +/* Check that FUNC is called with a different mode. */ + +bool +arm_change_mode_p (tree func) +{ + if (TREE_CODE (func) != FUNCTION_DECL) + return false; + + tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (func); + + if (!callee_tree) + callee_tree = target_option_default_node; + + struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree); + int flags = callee_opts ->x_target_flags; + + return (TARGET_THUMB_P (flags) != TARGET_THUMB); +} /* Like arm_compute_initial_elimination offset. Simpler because there isn't an ABI specified frame pointer for Thumb. Instead, we set it @@ -25517,9 +25574,6 @@ { int val; - if (TARGET_UNIFIED_ASM) - asm_fprintf (asm_out_file, "\t.syntax unified\n"); - if (TARGET_BPABI) { const char *fpu_name; @@ -29266,9 +29320,196 @@ && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0))); } +/* 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 = 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 == arm_previous_fndecl) + return; + + tree old_tree = (arm_previous_fndecl + ? DECL_FUNCTION_SPECIFIC_TARGET (arm_previous_fndecl) + : NULL_TREE); + + tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); + + arm_previous_fndecl = fndecl; + if (old_tree == 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) + = save_target_globals_default_opts (); + } + + else if (old_tree) + { + new_tree = 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 == target_option_default_node) + restore_target_globals (&default_target_globals); + else + TREE_TARGET_GLOBALS (new_tree) + = 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_UNUSED) +{ + /* Overidde default hook: Always OK to inline between different modes. + Function with mode specific instructions, e.g using asm, must be explicitely + protected with noinline. */ + return true; +} + +/* Inner function to process the attribute((target(...))), take an argument and + set the current options from the argument. If we have a list, recursively + go over the list. */ + +static bool +arm_valid_target_attribute_rec (tree args, struct gcc_options *opts) +{ + if (TREE_CODE (args) == TREE_LIST) + { + bool ret = true; + for (; args; args = TREE_CHAIN (args)) + if (TREE_VALUE (args) + && !arm_valid_target_attribute_rec (TREE_VALUE (args), opts)) + ret = false; + return ret; + } + + else if (TREE_CODE (args) != STRING_CST) + { + error ("attribute %<target%> argument not a string"); + return false; + } + + char *argstr = ASTRDUP (TREE_STRING_POINTER (args)); + while (argstr && *argstr != '\0') + { + while (ISSPACE (*argstr)) + argstr++; + + if (!strcmp (argstr, "thumb")) + { + opts->x_target_flags |= MASK_THUMB; + arm_option_check_internal (opts); + return true; + } + + if (!strcmp (argstr, "arm")) + { + opts->x_target_flags &= ~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=xxx. */ + 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 = true; + struct gcc_options func_options; + tree cur_tree, new_optimize; + gcc_assert ((fndecl != NULL_TREE) && (args != NULL_TREE)); + + /* Get the optimization options of the current function. */ + tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); + + /* If the function changed the optimization levels as well as setting target + options, start with the optimizations specified. */ + if (!func_optimize) + func_optimize = 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 = arm_valid_target_attribute_tree (args, &func_options, + &global_options_set); + + if (cur_tree == NULL_TREE) + ret = false; + + new_optimize = build_optimization_node (&func_options); + + DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = cur_tree; + + DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = 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) @@ -29280,6 +29521,8 @@ else fprintf (stream, "\t.thumb\n\t.thumb_func\n"); } + else + fprintf (stream, "\t.arm\n"); if (TARGET_POKE_FUNCTION_NAME) arm_poke_function_name (stream, (const char *) name); diff '--exclude=.svn' -ruN gnu_trunk.p2/gcc/gcc/config/arm/arm.h gnu_trunk.p4/gcc/gcc/config/arm/arm.h --- gnu_trunk.p2/gcc/gcc/config/arm/arm.h 2015-05-18 09:59:22.715435636 +0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm.h 2015-05-18 09:10:32.898017110 +0200 @@ -2258,4 +2258,8 @@ #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=.svn' -ruN gnu_trunk.p2/gcc/gcc/config/arm/arm.md gnu_trunk.p4/gcc/gcc/config/arm/arm.md --- gnu_trunk.p2/gcc/gcc/config/arm/arm.md 2015-05-18 09:36:56.844875186 +0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm.md 2015-05-18 09:10:32.898017110 +0200 @@ -7738,6 +7738,13 @@ && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))" "* { + rtx op = 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")] @@ -7755,6 +7762,13 @@ && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))" "* { + rtx op = 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=.svn' -ruN gnu_trunk.p2/gcc/gcc/config/arm/arm.opt gnu_trunk.p4/gcc/gcc/config/arm/arm.opt --- gnu_trunk.p2/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-13 12:59:54.625164421 +0200 @@ -182,7 +182,7 @@ Specify the minimum bit alignment of structures mthumb -Target Report RejectNegative Mask(THUMB) +Target Report RejectNegative Mask(THUMB) Save Generate code for Thumb state mthumb-interwork @@ -246,7 +246,7 @@ Only generate absolute relocations on word sized values. 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. mold-rtx-costs @@ -275,5 +275,5 @@ Assume loading data from flash is slower than fetching instructions. 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=.svn' -ruN gnu_trunk.p2/gcc/gcc/config/arm/arm-protos.h gnu_trunk.p4/gcc/gcc/config/arm/arm-protos.h --- gnu_trunk.p2/gcc/gcc/config/arm/arm-protos.h 2015-05-18 09:59:19.267429002 +0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm-protos.h 2015-05-13 12:59:54.653164472 +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 extern void arm_pr_long_calls (struct cpp_reader *); @@ -326,6 +329,8 @@ extern void arm_emit_eabi_attribute (const char *, int, int); +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); diff '--exclude=.svn' -ruN gnu_trunk.p2/gcc/gcc/doc/extend.texi gnu_trunk.p4/gcc/gcc/doc/extend.texi --- gnu_trunk.p2/gcc/gcc/doc/extend.texi 2015-05-13 09:07:31.339106236 +0200 +++ gnu_trunk.p4/gcc/gcc/doc/extend.texi 2015-05-18 09:08:54.221837117 +0200 @@ -3067,8 +3067,9 @@ or separate the options with a comma (@samp{,}) within a single string. 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. @item unused @cindex @code{unused} function attribute @@ -3417,6 +3418,27 @@ 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 +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 code generation in the Thumb (T16/T32) ISA, depending on the +architecture level. + +@item arm +@cindex @code{target("arm")} function attribute, ARM +Force code generation in the ARM (A32) ISA. +@end table + +Functions from different modes can be inlined in the caller's mode. + @end table @node AVR Function Attributes diff '--exclude=.svn' -ruN gnu_trunk.p2/gcc/gcc/doc/invoke.texi gnu_trunk.p4/gcc/gcc/doc/invoke.texi --- gnu_trunk.p2/gcc/gcc/doc/invoke.texi 2015-05-18 09:36:52.304866524 +0200 +++ gnu_trunk.p4/gcc/gcc/doc/invoke.texi 2015-05-18 09:10:29.078010152 +0200 @@ -13508,6 +13508,10 @@ configuring GCC with the @option{--with-mode=}@var{state} configure option. +You can also override the ARM and Thumb mode for each function +by using the @code{target("thumb")} and @code{target("arm")} function attributes +(@pxref{ARM Function Attributes}) or pragmas (@pxref{Function Specific Option Pragmas}). + @item -mtpcs-frame @opindex mtpcs-frame Generate a stack frame that is compliant with the Thumb Procedure Call diff '--exclude=.svn' -ruN gnu_trunk.p2/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c --- gnu_trunk.p2/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-07 18:15:34.177443930 +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=.svn' -ruN gnu_trunk.p2/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.p2/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-07 18:15:34.177443930 +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=*" } { "-march=armv6-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=.svn' -ruN gnu_trunk.p2/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c --- gnu_trunk.p2/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c 1970-01-01 01:00:00.000000000 +0100 +++ gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c 2015-05-07 18:15:34.177443930 +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=.svn' -ruN gnu_trunk.p2/gcc/gcc/testsuite/gcc.target/arm/attr_thumb-static.c gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb-static.c --- gnu_trunk.p2/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-07 18:15:34.177443930 +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__)) +foo (void) +{ + __asm__ (""); +} + +static void +__attribute__((__noinline__)) +__attribute__((target("thumb"))) +bar (void) +{ + __asm__ (""); +} + +int main() +{ + foo(); + bar(); +} ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (5th) 2015-05-18 8:16 ` [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (5th) Christian Bruel @ 2015-06-01 10:39 ` Kyrill Tkachov 2015-06-01 11:30 ` Christian Bruel 0 siblings, 1 reply; 15+ messages in thread From: Kyrill Tkachov @ 2015-06-01 10:39 UTC (permalink / raw) To: Christian Bruel, Ramana Radhakrishnan, Sandra Loosemore Cc: gcc-patches, Richard Earnshaw, nickc On 18/05/15 09:14, Christian Bruel wrote: > Hi, Hi Christian, A couple comments inline. Overall, the approach looks ok to me, though I think we'll have to generalise arm_valid_target_attribute_rec in the future if we want to allow other target attributes. Thanks, Kyrill > > Here is again a new version for patch [4/6]: (Implements and document > the hooks to support target_attributes.) > > - Rewrote for conflicts introduced by the new macros defined in > https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01198.html > > - Take your comments and Sandra's for documentation > > - I'd like to leave the inlining question apart with its own patch > until we settle it. Is it OK with you ? > https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01527.html > > many thanks, > > Christian > > p4.patch > > > 2014-09-23 Christian Bruel<christian.bruel@st.com> > > * 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/Thumb target attribute. > * doc/invoke.texi: Likewise. > > 2014-09-23 Christian Bruel<christian.bruel@st.com> > > * 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 Full stops at end of "New test" <snip> +/* Check that FUNC is called with a different mode. */ + +bool +arm_change_mode_p (tree func) +{ + if (TREE_CODE (func) != FUNCTION_DECL) + return false; + + tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (func); + + if (!callee_tree) + callee_tree = target_option_default_node; + + struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree); + int flags = callee_opts ->x_target_flags; No space after callee_opts. <snip> +/* 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 = 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 == arm_previous_fndecl) + return; + + tree old_tree = (arm_previous_fndecl + ? DECL_FUNCTION_SPECIFIC_TARGET (arm_previous_fndecl) + : NULL_TREE); + + tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); + + arm_previous_fndecl = fndecl; + if (old_tree == 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) + = save_target_globals_default_opts (); + } + + else if (old_tree) + { + new_tree = 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 == target_option_default_node) + restore_target_globals (&default_target_globals); + else + TREE_TARGET_GLOBALS (new_tree) + = save_target_globals_default_opts (); + } + + arm_option_params_internal (&global_options); I thought the more common approach was to define TARGET_OPTION_RESTORE that was supposed to restore the backend state, including calling arm_option_params_internal? That way, cl_target_option_restore would do all that needs to be done to restore the backend. <snip> diff '--exclude=.svn' -ruN gnu_trunk.p2/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c --- gnu_trunk.p2/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-07 18:15:34.177443930 +0200 @@ -0,0 +1,13 @@ +/* Check that attribute target arm is recogniwed. */ s/recogniwed/recognized/ > +/* { 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=.svn' -ruN gnu_trunk.p2/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.p2/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-07 18:15:34.177443930 +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=*" } { "-march=armv6-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=.svn' -ruN gnu_trunk.p2/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c > --- gnu_trunk.p2/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c 1970-01-01 01:00:00.000000000 +0100 > +++ gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c 2015-05-07 18:15:34.177443930 +0200 > @@ -0,0 +1,13 @@ > +/* Check that attribute target thumb is recogniwed. */ s/recogniwed/recognized/ ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (5th) 2015-06-01 10:39 ` Kyrill Tkachov @ 2015-06-01 11:30 ` Christian Bruel 2015-06-01 12:41 ` Kyrill Tkachov 0 siblings, 1 reply; 15+ messages in thread From: Christian Bruel @ 2015-06-01 11:30 UTC (permalink / raw) To: Kyrill Tkachov, Ramana Radhakrishnan, Sandra Loosemore Cc: gcc-patches, Richard Earnshaw, nickc hi Kyrill On 06/01/2015 12:39 PM, Kyrill Tkachov wrote: > > On 18/05/15 09:14, Christian Bruel wrote: >> Hi, > > Hi Christian, > A couple comments inline. > Overall, the approach looks ok to me, though I think we'll have to > generalise arm_valid_target_attribute_rec in the future if we want > to allow other target attributes. > the other fpu target attributes will be part of another set of developments, specific parsing strings will be added as they are implemented. > + > +/* 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 == arm_previous_fndecl) > + return; > + > + tree old_tree = (arm_previous_fndecl > + ? DECL_FUNCTION_SPECIFIC_TARGET (arm_previous_fndecl) > + : NULL_TREE); > + > + tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); > + > + arm_previous_fndecl = fndecl; > + if (old_tree == 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) > + = save_target_globals_default_opts (); > + } > + > + else if (old_tree) > + { > + new_tree = 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 == target_option_default_node) > + restore_target_globals (&default_target_globals); > + else > + TREE_TARGET_GLOBALS (new_tree) > + = save_target_globals_default_opts (); > + } > + > + arm_option_params_internal (&global_options); > > > I thought the more common approach was to define TARGET_OPTION_RESTORE > that was supposed to restore the backend state, including calling arm_option_params_internal? > That way, cl_target_option_restore would do all that needs to be done to restore the backend. > TARGET_OPTION_RESTORE is fine to restore target-specific information from struct cl_target_option. Other global states might as well be expressed within set_current_function (e.g indeed I might use TARGET_OPTION_RESTORE to switch arm_fpu_attr in the fpu neon attribute). But IMHO arm_option_params_internal are fine to be called there since the 2 params only depend from x_target_flags without the need of a new macro. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (5th) 2015-06-01 11:30 ` Christian Bruel @ 2015-06-01 12:41 ` Kyrill Tkachov 2015-06-01 12:55 ` Christian Bruel 2015-06-08 9:26 ` Christian Bruel 0 siblings, 2 replies; 15+ messages in thread From: Kyrill Tkachov @ 2015-06-01 12:41 UTC (permalink / raw) To: Christian Bruel, Ramana Radhakrishnan, Sandra Loosemore Cc: gcc-patches, Richard Earnshaw, nickc On 01/06/15 12:29, Christian Bruel wrote: > hi Kyrill > > > On 06/01/2015 12:39 PM, Kyrill Tkachov wrote: >> On 18/05/15 09:14, Christian Bruel wrote: >>> Hi, >> Hi Christian, >> A couple comments inline. >> Overall, the approach looks ok to me, though I think we'll have to >> generalise arm_valid_target_attribute_rec in the future if we want >> to allow other target attributes. >> > the other fpu target attributes will be part of another set of > developments, specific parsing strings will be added as they are > implemented. Ok, so you plan on working on fpu attributes as well? > >> + >> +/* 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 == arm_previous_fndecl) >> + return; >> + >> + tree old_tree = (arm_previous_fndecl >> + ? DECL_FUNCTION_SPECIFIC_TARGET (arm_previous_fndecl) >> + : NULL_TREE); >> + >> + tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); >> + >> + arm_previous_fndecl = fndecl; >> + if (old_tree == 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) >> + = save_target_globals_default_opts (); >> + } >> + >> + else if (old_tree) >> + { >> + new_tree = 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 == target_option_default_node) >> + restore_target_globals (&default_target_globals); >> + else >> + TREE_TARGET_GLOBALS (new_tree) >> + = save_target_globals_default_opts (); >> + } >> + >> + arm_option_params_internal (&global_options); >> >> >> I thought the more common approach was to define TARGET_OPTION_RESTORE >> that was supposed to restore the backend state, including calling arm_option_params_internal? >> That way, cl_target_option_restore would do all that needs to be done to restore the backend. >> > TARGET_OPTION_RESTORE is fine to restore target-specific > information from struct cl_target_option. Other global states might as > well be expressed within set_current_function (e.g indeed I might use > TARGET_OPTION_RESTORE to switch arm_fpu_attr in the fpu neon attribute). > But IMHO arm_option_params_internal are fine to be called there since > the 2 params only depend from x_target_flags without the need of a new > macro. Ok, I see. The patch looks ok to me modulo the typo nits I pointed out, but I think Ramana should have the final say here as he's already started reviewing it and it adds quite a lot of functionality. Thanks, Kyrill > > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (5th) 2015-06-01 12:41 ` Kyrill Tkachov @ 2015-06-01 12:55 ` Christian Bruel 2015-06-08 9:26 ` Christian Bruel 1 sibling, 0 replies; 15+ messages in thread From: Christian Bruel @ 2015-06-01 12:55 UTC (permalink / raw) To: Kyrill Tkachov, Ramana Radhakrishnan, Sandra Loosemore Cc: gcc-patches, Richard Earnshaw, nickc On 06/01/2015 02:41 PM, Kyrill Tkachov wrote: > > On 01/06/15 12:29, Christian Bruel wrote: >> hi Kyrill >> >> >> On 06/01/2015 12:39 PM, Kyrill Tkachov wrote: >>> On 18/05/15 09:14, Christian Bruel wrote: >>>> Hi, >>> Hi Christian, >>> A couple comments inline. >>> Overall, the approach looks ok to me, though I think we'll have to >>> generalise arm_valid_target_attribute_rec in the future if we want >>> to allow other target attributes. >>> >> the other fpu target attributes will be part of another set of >> developments, specific parsing strings will be added as they are >> implemented. > > Ok, so you plan on working on fpu attributes as well? I have a prototype for fpu=neon, it works locally but there are still a few corner cases and testing to sort out before sending a draft. There are so many architectural variants to check that I might ask for help once it is a little bit more robust, and some might be similar with aarch64's simd. > >> >>> + >>> +/* 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 == arm_previous_fndecl) >>> + return; >>> + >>> + tree old_tree = (arm_previous_fndecl >>> + ? DECL_FUNCTION_SPECIFIC_TARGET (arm_previous_fndecl) >>> + : NULL_TREE); >>> + >>> + tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); >>> + >>> + arm_previous_fndecl = fndecl; >>> + if (old_tree == 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) >>> + = save_target_globals_default_opts (); >>> + } >>> + >>> + else if (old_tree) >>> + { >>> + new_tree = 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 == target_option_default_node) >>> + restore_target_globals (&default_target_globals); >>> + else >>> + TREE_TARGET_GLOBALS (new_tree) >>> + = save_target_globals_default_opts (); >>> + } >>> + >>> + arm_option_params_internal (&global_options); >>> >>> >>> I thought the more common approach was to define TARGET_OPTION_RESTORE >>> that was supposed to restore the backend state, including calling arm_option_params_internal? >>> That way, cl_target_option_restore would do all that needs to be done to restore the backend. >>> >> TARGET_OPTION_RESTORE is fine to restore target-specific >> information from struct cl_target_option. Other global states might as >> well be expressed within set_current_function (e.g indeed I might use >> TARGET_OPTION_RESTORE to switch arm_fpu_attr in the fpu neon attribute). >> But IMHO arm_option_params_internal are fine to be called there since >> the 2 params only depend from x_target_flags without the need of a new >> macro. > > Ok, I see. > The patch looks ok to me modulo the typo nits I pointed out, but I think Ramana > should have the final say here as he's already started reviewing it and it adds quite > a lot of functionality. OK thanks, I'll wait for Ramana's final words. Cheers Christian > > Thanks, > Kyrill > >> >> > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (5th) 2015-06-01 12:41 ` Kyrill Tkachov 2015-06-01 12:55 ` Christian Bruel @ 2015-06-08 9:26 ` Christian Bruel 2015-06-08 9:33 ` Ramana Radhakrishnan 1 sibling, 1 reply; 15+ messages in thread From: Christian Bruel @ 2015-06-08 9:26 UTC (permalink / raw) To: Kyrill Tkachov, Ramana Radhakrishnan, Sandra Loosemore Cc: gcc-patches, Richard Earnshaw, nickc Hi Ramana, > > Ok, I see. > The patch looks ok to me modulo the typo nits I pointed out, but I think Ramana > should have the final say here as he's already started reviewing it and it adds quite > a lot of functionality. > > Thanks, > Kyrill > do you have other feedbacks for the remaining parts ? many thanks Christian ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (5th) 2015-06-08 9:26 ` Christian Bruel @ 2015-06-08 9:33 ` Ramana Radhakrishnan 2015-06-10 8:26 ` [PATCH, ARM] (commited) attribute target (thumb,arm) [4/6] Christian Bruel 0 siblings, 1 reply; 15+ messages in thread From: Ramana Radhakrishnan @ 2015-06-08 9:33 UTC (permalink / raw) To: Christian Bruel, Kyrill Tkachov, Ramana Radhakrishnan, Sandra Loosemore Cc: gcc-patches, Richard Earnshaw, nickc On 08/06/15 09:45, Christian Bruel wrote: > Hi Ramana, > >> >> Ok, I see. >> The patch looks ok to me modulo the typo nits I pointed out, but I >> think Ramana >> should have the final say here as he's already started reviewing it >> and it adds quite >> a lot of functionality. >> >> Thanks, >> Kyrill >> > > do you have other feedbacks for the remaining parts ? > > many thanks > > Christian This is OK, thanks. Ramana ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] (commited) attribute target (thumb,arm) [4/6] 2015-06-08 9:33 ` Ramana Radhakrishnan @ 2015-06-10 8:26 ` Christian Bruel 2015-06-15 10:15 ` James Greenhalgh 0 siblings, 1 reply; 15+ messages in thread From: Christian Bruel @ 2015-06-10 8:26 UTC (permalink / raw) To: Ramana Radhakrishnan, Kyrill Tkachov, Ramana Radhakrishnan, Sandra Loosemore Cc: gcc-patches, Richard Earnshaw, nickc [-- Attachment #1: Type: text/plain, Size: 572 bytes --] Hi, Commited [4/6] as attached (r224314) thanks Christian On 06/08/2015 11:26 AM, Ramana Radhakrishnan wrote: > > > On 08/06/15 09:45, Christian Bruel wrote: >> Hi Ramana, >> >>> >>> Ok, I see. >>> The patch looks ok to me modulo the typo nits I pointed out, but I >>> think Ramana >>> should have the final say here as he's already started reviewing it >>> and it adds quite >>> a lot of functionality. >>> >>> Thanks, >>> Kyrill >>> >> >> do you have other feedbacks for the remaining parts ? >> >> many thanks >> >> Christian > > > This is OK, thanks. > > Ramana > [-- Attachment #2: commited.txt --] [-- Type: text/plain, Size: 21594 bytes --] Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 224313) +++ gcc/doc/extend.texi (revision 224314) @@ -3098,8 +3098,9 @@ or separate the options with a comma (@samp{,}) within a single string. 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. @item unused @cindex @code{unused} function attribute @@ -3448,8 +3449,29 @@ 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 +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 code generation in the Thumb (T16/T32) ISA, depending on the +architecture level. + +@item arm +@cindex @code{target("arm")} function attribute, ARM +Force code generation in the ARM (A32) ISA. @end table +Functions from different modes can be inlined in the caller's mode. + +@end table + @node AVR Function Attributes @subsection AVR Function Attributes Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 224313) +++ gcc/doc/invoke.texi (revision 224314) @@ -13512,6 +13512,10 @@ configuring GCC with the @option{--with-mode=}@var{state} configure option. +You can also override the ARM and Thumb mode for each function +by using the @code{target("thumb")} and @code{target("arm")} function attributes +(@pxref{ARM Function Attributes}) or pragmas (@pxref{Function Specific Option Pragmas}). + @item -mtpcs-frame @opindex mtpcs-frame Generate a stack frame that is compliant with the Thumb Procedure Call Index: gcc/ChangeLog =================================================================== --- gcc/ChangeLog (revision 224313) +++ gcc/ChangeLog (revision 224314) @@ -1,3 +1,28 @@ +2015-06-09 Christian Bruel <christian.bruel@st.com> + + PR target/52144 + * config/arm/arm.opt (THUMB, arm_restrict_it, inline_asm_unified): Save. + * config/arm/arm-protos.h (arm_valid_target_attribute_tree): Declare. + (arm_reset_previous_fndecl, arm_change_mode_p): Likewise. + * config/arm/arm.h (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/Thumb target attribute. + * doc/invoke.texi: Likewise. + 2015-06-09 Alexandre Oliva <aoliva@redhat.com> Revert: Index: gcc/testsuite/gcc.target/arm/attr_arm-err.c =================================================================== --- gcc/testsuite/gcc.target/arm/attr_arm-err.c (revision 0) +++ gcc/testsuite/gcc.target/arm/attr_arm-err.c (revision 224314) @@ -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=*" } { "-march=armv6-m" } } */ +/* { dg-add-options arm_arch_v6m } */ + +int __attribute__((target("arm"))) +foo(int a) +{ /* { dg-error "does not support" } */ + return a ? 1 : 5; +} + + Index: gcc/testsuite/gcc.target/arm/attr_thumb.c =================================================================== --- gcc/testsuite/gcc.target/arm/attr_thumb.c (revision 0) +++ gcc/testsuite/gcc.target/arm/attr_thumb.c (revision 224314) @@ -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; +} + Index: gcc/testsuite/gcc.target/arm/attr_thumb-static.c =================================================================== --- gcc/testsuite/gcc.target/arm/attr_thumb-static.c (revision 0) +++ gcc/testsuite/gcc.target/arm/attr_thumb-static.c (revision 224314) @@ -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__)) +foo (void) +{ + __asm__ (""); +} + +static void +__attribute__((__noinline__)) +__attribute__((target("thumb"))) +bar (void) +{ + __asm__ (""); +} + +int main() +{ + foo(); + bar(); +} Index: gcc/testsuite/gcc.target/arm/attr_arm.c =================================================================== --- gcc/testsuite/gcc.target/arm/attr_arm.c (revision 0) +++ gcc/testsuite/gcc.target/arm/attr_arm.c (revision 224314) @@ -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; +} + Index: gcc/testsuite/ChangeLog =================================================================== --- gcc/testsuite/ChangeLog (revision 224313) +++ gcc/testsuite/ChangeLog (revision 224314) @@ -1,3 +1,11 @@ +2015-06-09 Christian Bruel <christian.bruel@st.com> + + PR target/52144 + * 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 + 2015-06-10 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> PR target/66200 Index: gcc/config/arm/arm.c =================================================================== --- gcc/config/arm/arm.c (revision 224313) +++ gcc/config/arm/arm.c (revision 224314) @@ -81,6 +81,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" @@ -252,6 +253,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 *); @@ -400,6 +404,9 @@ #undef TARGET_ASM_FUNCTION_EPILOGUE #define TARGET_ASM_FUNCTION_EPILOGUE arm_output_function_epilogue +#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 @@ -418,6 +425,12 @@ #undef TARGET_SCHED_ADJUST_COST #define TARGET_SCHED_ADJUST_COST arm_adjust_cost +#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 @@ -2778,6 +2791,9 @@ max_insns_skipped = current_tune->max_insns_skipped; } +/* 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, @@ -2800,6 +2816,10 @@ if (TARGET_THUMB_P (opts->x_target_flags) && TARGET_CALLEE_INTERWORKING) opts->x_target_flags |= MASK_INTERWORK; + /* need to remember initial values so combinaisons of options like + -mflip-thumb -mthumb -fno-schedule-insns work for any attribute. */ + cl_optimization *to = TREE_OPTIMIZATION (init_optimize); + if (! opts_set->x_arm_restrict_it) opts->x_arm_restrict_it = arm_arch8; @@ -2806,11 +2826,11 @@ if (!TARGET_THUMB2_P (opts->x_target_flags)) opts->x_arm_restrict_it = 0; + /* Don't warn since it's on by default in -O2. */ if (TARGET_THUMB1_P (opts->x_target_flags)) - { - /* Don't warn since it's on by default in -O2. */ - opts->x_flag_schedule_insns = 0; - } + opts->x_flag_schedule_insns = 0; + else + opts->x_flag_schedule_insns = to->x_flag_schedule_insns; /* Disable shrink-wrap when optimizing function for size, since it tends to generate additional returns. */ @@ -2817,6 +2837,8 @@ if (optimize_function_for_size_p (cfun) && TARGET_THUMB2_P (opts->x_target_flags)) opts->x_flag_shrink_wrap = false; + else + opts->x_flag_shrink_wrap = to->x_flag_shrink_wrap; /* In Thumb1 mode, we emit the epilogue in RTL, but the last insn - epilogue_insns - does not accurately model the corresponding insns @@ -2828,6 +2850,8 @@ fipa-ra. */ if (TARGET_THUMB1_P (opts->x_target_flags)) opts->x_flag_ipa_ra = 0; + else + opts->x_flag_ipa_ra = to->x_flag_ipa_ra; /* Thumb2 inline assembly code should always use unified syntax. This will apply to ARM and Thumb1 eventually. */ @@ -3330,6 +3354,9 @@ && (!arm_arch7 || !current_tune->prefer_ldrd_strd)) flag_schedule_fusion = 0; + /* Need to remember initial options before they are overriden. */ + init_optimize = 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); @@ -3336,6 +3363,11 @@ /* 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 = target_option_current_node + = build_target_option_node (&global_options); } static void @@ -3489,13 +3521,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_REGNUM); 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", @@ -24193,7 +24232,25 @@ mark_reg_pointer (arg_pointer_rtx, PARM_BOUNDARY); } +/* Check that FUNC is called with a different mode. */ +bool +arm_change_mode_p (tree func) +{ + if (TREE_CODE (func) != FUNCTION_DECL) + return false; + + tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (func); + + if (!callee_tree) + callee_tree = target_option_default_node; + + struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree); + int flags = callee_opts->x_target_flags; + + return (TARGET_THUMB_P (flags) != TARGET_THUMB); +} + /* Like arm_compute_initial_elimination offset. Simpler because there isn't an ABI specified frame pointer for Thumb. Instead, we set it to point at the base of the local variables after static stack @@ -25520,9 +25577,6 @@ { int val; - if (TARGET_UNIFIED_ASM) - asm_fprintf (asm_out_file, "\t.syntax unified\n"); - if (TARGET_BPABI) { const char *fpu_name; @@ -29269,9 +29323,196 @@ && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0))); } +/* 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 = 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 == arm_previous_fndecl) + return; + + tree old_tree = (arm_previous_fndecl + ? DECL_FUNCTION_SPECIFIC_TARGET (arm_previous_fndecl) + : NULL_TREE); + + tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); + + arm_previous_fndecl = fndecl; + if (old_tree == 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) + = save_target_globals_default_opts (); + } + + else if (old_tree) + { + new_tree = 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 == target_option_default_node) + restore_target_globals (&default_target_globals); + else + TREE_TARGET_GLOBALS (new_tree) + = 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_UNUSED) +{ + /* Overidde default hook: Always OK to inline between different modes. + Function with mode specific instructions, e.g using asm, must be explicitely + protected with noinline. */ + return true; +} + +/* Inner function to process the attribute((target(...))), take an argument and + set the current options from the argument. If we have a list, recursively + go over the list. */ + +static bool +arm_valid_target_attribute_rec (tree args, struct gcc_options *opts) +{ + if (TREE_CODE (args) == TREE_LIST) + { + bool ret = true; + for (; args; args = TREE_CHAIN (args)) + if (TREE_VALUE (args) + && !arm_valid_target_attribute_rec (TREE_VALUE (args), opts)) + ret = false; + return ret; + } + + else if (TREE_CODE (args) != STRING_CST) + { + error ("attribute %<target%> argument not a string"); + return false; + } + + char *argstr = ASTRDUP (TREE_STRING_POINTER (args)); + while (argstr && *argstr != '\0') + { + while (ISSPACE (*argstr)) + argstr++; + + if (!strcmp (argstr, "thumb")) + { + opts->x_target_flags |= MASK_THUMB; + arm_option_check_internal (opts); + return true; + } + + if (!strcmp (argstr, "arm")) + { + opts->x_target_flags &= ~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=xxx. */ + 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 = true; + struct gcc_options func_options; + tree cur_tree, new_optimize; + gcc_assert ((fndecl != NULL_TREE) && (args != NULL_TREE)); + + /* Get the optimization options of the current function. */ + tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); + + /* If the function changed the optimization levels as well as setting target + options, start with the optimizations specified. */ + if (!func_optimize) + func_optimize = 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 = arm_valid_target_attribute_tree (args, &func_options, + &global_options_set); + + if (cur_tree == NULL_TREE) + ret = false; + + new_optimize = build_optimization_node (&func_options); + + DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = cur_tree; + + DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = 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) @@ -29283,6 +29524,8 @@ else fprintf (stream, "\t.thumb\n\t.thumb_func\n"); } + else + fprintf (stream, "\t.arm\n"); if (TARGET_POKE_FUNCTION_NAME) arm_poke_function_name (stream, (const char *) name); Index: gcc/config/arm/arm.h =================================================================== --- gcc/config/arm/arm.h (revision 224313) +++ gcc/config/arm/arm.h (revision 224314) @@ -2258,4 +2258,8 @@ #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 */ Index: gcc/config/arm/arm-protos.h =================================================================== --- gcc/config/arm/arm-protos.h (revision 224313) +++ gcc/config/arm/arm-protos.h (revision 224314) @@ -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 extern void arm_pr_long_calls (struct cpp_reader *); @@ -326,6 +329,8 @@ extern void arm_emit_eabi_attribute (const char *, int, int); +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); Index: gcc/config/arm/arm.opt =================================================================== --- gcc/config/arm/arm.opt (revision 224313) +++ gcc/config/arm/arm.opt (revision 224314) @@ -182,7 +182,7 @@ Specify the minimum bit alignment of structures mthumb -Target Report RejectNegative Mask(THUMB) +Target Report RejectNegative Mask(THUMB) Save Generate code for Thumb state mthumb-interwork @@ -246,7 +246,7 @@ Only generate absolute relocations on word sized values. 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. mold-rtx-costs @@ -275,5 +275,5 @@ Assume loading data from flash is slower than fetching instructions. 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. Index: gcc/config/arm/arm.md =================================================================== --- gcc/config/arm/arm.md (revision 224313) +++ gcc/config/arm/arm.md (revision 224314) @@ -7787,6 +7787,13 @@ && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))" "* { + rtx op = 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")] @@ -7804,6 +7811,13 @@ && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))" "* { + rtx op = 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")] ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] (commited) attribute target (thumb,arm) [4/6] 2015-06-10 8:26 ` [PATCH, ARM] (commited) attribute target (thumb,arm) [4/6] Christian Bruel @ 2015-06-15 10:15 ` James Greenhalgh 2015-06-15 12:05 ` Christian Bruel 0 siblings, 1 reply; 15+ messages in thread From: James Greenhalgh @ 2015-06-15 10:15 UTC (permalink / raw) To: Christian Bruel Cc: Ramana Radhakrishnan, Kyrylo Tkachov, Ramana Radhakrishnan, Sandra Loosemore, gcc-patches, Richard Earnshaw, nickc On Wed, Jun 10, 2015 at 08:57:37AM +0100, Christian Bruel wrote: > Hi, > > Commited [4/6] as attached (r224314) > > thanks > > Christian > > On 06/08/2015 11:26 AM, Ramana Radhakrishnan wrote: > > On 08/06/15 09:45, Christian Bruel wrote: > >> > >> do you have other feedbacks for the remaining parts ? > >> > >> many thanks > >> > > > > This is OK, thanks. > > > > Ramana Hi Christian, This patch is causing an ICE for me in my arm-none-linux-gnueabihf testing. It looks like something isn't saving/restoring/initialising data structures needed for IRA. I've raised https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66541 , the bug looks very similar to pr64047 ( https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64047 ). Thanks, James --- .../gcc/cc1 bug.c -O2 -ftree-parallelize-loops=4 -O2 -flto -fno-use-linker-plugin -ftree-parallelize-loops=4 -o pr52429.s foo Analyzing compilation unit Performing interprocedural optimizations <*free_lang_data> <visibility> <build_ssa_passes> <opt_local_passes> <free-inline-summary> <whole-program> <profile_estimate> <icf> <devirt> <cp> <inline> <pure-const> <static-var> <single-use> <comdats>Assembling functions: foo .../gcc/testsuite/gcc.dg/torture/pr52429.c: In function âfooâ: .../gcc/testsuite/gcc.dg/torture/pr52429.c:11:1: internal compiler error: Segmentation fault int i; ^ 0xafa15f crash_signal .../gcc/toplev.c:369 0x97c2b4 record_operand_costs .../gcc/ira-costs.c:1305 0x97c7a4 scan_one_insn .../gcc/ira-costs.c:1483 0x97c7a4 process_bb_for_costs .../gcc/ira-costs.c:1604 0x97d715 find_costs_and_classes .../gcc/ira-costs.c:1711 0x97ec3a ira_set_pseudo_classes(bool, _IO_FILE*) .../gcc/ira-costs.c:2245 0xffd743 alloc_global_sched_pressure_data .../gcc/haifa-sched.c:7119 0xffd743 sched_init() .../gcc/haifa-sched.c:7269 0xffebcf haifa_sched_init() .../gcc/haifa-sched.c:7281 0xaab8dc schedule_insns .../gcc/sched-rgn.c:3411 0xaac0b3 schedule_insns .../gcc/sched-rgn.c:3405 0xaac0b3 rest_of_handle_sched .../gcc/sched-rgn.c:3624 0xaac0b3 execute .../gcc/sched-rgn.c:3732 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <http://gcc.gnu.org/bugs.html> for instructions. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] (commited) attribute target (thumb,arm) [4/6] 2015-06-15 10:15 ` James Greenhalgh @ 2015-06-15 12:05 ` Christian Bruel 0 siblings, 0 replies; 15+ messages in thread From: Christian Bruel @ 2015-06-15 12:05 UTC (permalink / raw) To: James Greenhalgh Cc: Ramana Radhakrishnan, Kyrylo Tkachov, Ramana Radhakrishnan, Sandra Loosemore, gcc-patches, Richard Earnshaw, nickc On 06/15/2015 12:00 PM, James Greenhalgh wrote: > On Wed, Jun 10, 2015 at 08:57:37AM +0100, Christian Bruel wrote: >> Hi, >> >> Commited [4/6] as attached (r224314) >> >> thanks >> >> Christian >> >> On 06/08/2015 11:26 AM, Ramana Radhakrishnan wrote: >>> On 08/06/15 09:45, Christian Bruel wrote: >>>> >>>> do you have other feedbacks for the remaining parts ? >>>> >>>> many thanks >>>> >>> >>> This is OK, thanks. >>> >>> Ramana > > Hi Christian, > > This patch is causing an ICE for me in my arm-none-linux-gnueabihf testing. > It looks like something isn't saving/restoring/initialising data > structures needed for IRA. > > I've raised https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66541 , the bug > looks very similar to pr64047 > ( https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64047 ). > > Thanks, > James > Hi James, OK, I'll have a look. pr52429.c is reported as UNSUPPORTED with my runs of arm-none-eabi (no threads), but I can reproduce with a manual run. Cheers Christian > --- > .../gcc/cc1 bug.c -O2 -ftree-parallelize-loops=4 -O2 -flto -fno-use-linker-plugin -ftree-parallelize-loops=4 -o pr52429.s > > foo > Analyzing compilation unit > Performing interprocedural optimizations > <*free_lang_data> <visibility> <build_ssa_passes> <opt_local_passes> <free-inline-summary> <whole-program> <profile_estimate> <icf> <devirt> <cp> <inline> <pure-const> <static-var> <single-use> <comdats>Assembling functions: > foo > .../gcc/testsuite/gcc.dg/torture/pr52429.c: In function âfooâ: > .../gcc/testsuite/gcc.dg/torture/pr52429.c:11:1: internal compiler error: Segmentation fault > int i; > ^ > 0xafa15f crash_signal > .../gcc/toplev.c:369 > 0x97c2b4 record_operand_costs > .../gcc/ira-costs.c:1305 > 0x97c7a4 scan_one_insn > .../gcc/ira-costs.c:1483 > 0x97c7a4 process_bb_for_costs > .../gcc/ira-costs.c:1604 > 0x97d715 find_costs_and_classes > .../gcc/ira-costs.c:1711 > 0x97ec3a ira_set_pseudo_classes(bool, _IO_FILE*) > .../gcc/ira-costs.c:2245 > 0xffd743 alloc_global_sched_pressure_data > .../gcc/haifa-sched.c:7119 > 0xffd743 sched_init() > .../gcc/haifa-sched.c:7269 > 0xffebcf haifa_sched_init() > .../gcc/haifa-sched.c:7281 > 0xaab8dc schedule_insns > .../gcc/sched-rgn.c:3411 > 0xaac0b3 schedule_insns > .../gcc/sched-rgn.c:3405 > 0xaac0b3 rest_of_handle_sched > .../gcc/sched-rgn.c:3624 > 0xaac0b3 execute > .../gcc/sched-rgn.c:3732 > Please submit a full bug report, > with preprocessed source if appropriate. > Please include the complete backtrace with any bug report. > See <http://gcc.gnu.org/bugs.html> for instructions. > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (4th) 2015-05-06 14:25 [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (4th) Christian Bruel 2015-05-06 23:04 ` Sandra Loosemore @ 2015-05-07 8:13 ` Christian Bruel 1 sibling, 0 replies; 15+ messages in thread From: Christian Bruel @ 2015-05-07 8:13 UTC (permalink / raw) To: gcc-patches, Ramana Radhakrishnan, Richard Earnshaw, Nicholas Clifton, sandra [-- Attachment #1: Type: text/plain, Size: 523 bytes --] + 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 > [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: p4.patch --] [-- Type: text/x-patch; name="p4.patch", Size: 22542 bytes --] 2014-09-23 Christian Bruel <christian.bruel@st.com> * 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 <christian.bruel@st.com> * 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=.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm.c gnu_trunk.p4/gcc/gcc/config/arm/arm.c --- gnu_trunk.p3/gcc/gcc/config/arm/arm.c 2015-05-06 14:31:48.750726995 +0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm.c 2015-05-06 15:03:29.393992051 +0200 @@ -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 +#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 @@ -430,6 +437,12 @@ #undef TARGET_SCHED_ADJUST_COST #define TARGET_SCHED_ADJUST_COST arm_adjust_cost +#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 @@ -2750,6 +2763,9 @@ } } +/* 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 |= MASK_INTERWORK; + /* need to remember initial values so combinaisons of options like + -mflip-thumb -mthumb -fno-schedule-insns work for any attribute. */ + cl_optimization *to = TREE_OPTIMIZATION (init_optimize); + if (! opts_set->x_arm_restrict_it) opts->x_arm_restrict_it = arm_arch8; @@ -2779,15 +2799,17 @@ opts->x_arm_restrict_it = 0; if (TREE_TARGET_THUMB1 (opts)) - { - /* Don't warn since it's on by default in -O2. */ - opts->x_flag_schedule_insns = 0; - } + /* Don't warn since it's on by default in -O2. */ + opts->x_flag_schedule_insns = 0; + else + opts->x_flag_schedule_insns = to->x_flag_schedule_insns; /* 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 = false; + else + opts->x_flag_shrink_wrap = to->x_flag_shrink_wrap; /* 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 = 0; + else + opts->x_flag_ipa_ra = to->x_flag_ipa_ra; /* 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 = 0; + /* Need to remember initial options before they are overriden. */ + init_optimize = 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); /* 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 = target_option_current_node + = build_target_option_node (&global_options); } 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_REGNUM); 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; } +/* Check that FUNC is called with a different mode. */ + +bool +arm_change_mode_p (tree func) +{ + if (TREE_CODE (func) != FUNCTION_DECL) + return false; + + tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (func); + + if (!callee_tree) + callee_tree = target_option_default_node; + + struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree); + + return (TREE_TARGET_THUMB (callee_opts) != TARGET_THUMB); +} /* 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; - 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))); } +/* 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 = 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 == arm_previous_fndecl) + return; + + tree old_tree = (arm_previous_fndecl + ? DECL_FUNCTION_SPECIFIC_TARGET (arm_previous_fndecl) + : NULL_TREE); + + tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); + + arm_previous_fndecl = fndecl; + if (old_tree == 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) + = save_target_globals_default_opts (); + } + + else if (old_tree) + { + new_tree = 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 == target_option_default_node) + restore_target_globals (&default_target_globals); + else + TREE_TARGET_GLOBALS (new_tree) + = 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_UNUSED) +{ + /* Overidde default hook: Always OK to inline between different modes. + Function with mode specific instructions, e.g using asm, must be explicitely + protected with noinline. */ + return true; +} + +/* Inner function to process the attribute((target(...))), take an argument and + set the current options from the argument. If we have a list, recursively + go over the list. */ + +static bool +arm_valid_target_attribute_rec (tree args, struct gcc_options *opts) +{ + if (TREE_CODE (args) == TREE_LIST) + { + bool ret = true; + for (; args; args = TREE_CHAIN (args)) + if (TREE_VALUE (args) + && !arm_valid_target_attribute_rec (TREE_VALUE (args), opts)) + ret = false; + return ret; + } + + else if (TREE_CODE (args) != STRING_CST) + { + error ("attribute %<target%> argument not a string"); + return false; + } + + char *argstr = ASTRDUP (TREE_STRING_POINTER (args)); + while (argstr && *argstr != '\0') + { + while (ISSPACE (*argstr)) + argstr++; + + if (!strcmp (argstr, "thumb")) + { + opts->x_target_flags |= MASK_THUMB; + arm_option_check_internal (opts); + return true; + } + + if (!strcmp (argstr, "arm")) + { + opts->x_target_flags &= ~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=xxx. */ + 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 = true; + struct gcc_options func_options; + tree cur_tree, new_optimize; + gcc_assert ((fndecl != NULL_TREE) && (args != NULL_TREE)); + + /* Get the optimization options of the current function. */ + tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); + + /* If the function changed the optimization levels as well as setting target + options, start with the optimizations specified. */ + if (!func_optimize) + func_optimize = 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 = arm_valid_target_attribute_tree (args, &func_options, + &global_options_set); + + if (cur_tree == NULL_TREE) + ret = false; + + new_optimize = build_optimization_node (&func_options); + + DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = cur_tree; + + DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = 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"); if (TARGET_POKE_FUNCTION_NAME) arm_poke_function_name (stream, (const char *) name); diff '--exclude=.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm.h gnu_trunk.p4/gcc/gcc/config/arm/arm.h --- gnu_trunk.p3/gcc/gcc/config/arm/arm.h 2015-05-06 14:31:48.750726995 +0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm.h 2015-05-06 14:36:32.227213416 +0200 @@ -2332,4 +2332,8 @@ #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=.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm.md gnu_trunk.p4/gcc/gcc/config/arm/arm.md --- gnu_trunk.p3/gcc/gcc/config/arm/arm.md 2015-05-06 14:31:40.678713158 +0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm.md 2015-05-06 14:36:32.231213422 +0200 @@ -7722,6 +7722,13 @@ && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))" "* { + rtx op = 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 = 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=.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm.opt gnu_trunk.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 mthumb -Target Report RejectNegative Mask(THUMB) +Target Report RejectNegative Mask(THUMB) Save Generate code for Thumb state mthumb-interwork @@ -246,7 +246,7 @@ Only generate absolute relocations on word sized values. 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. mold-rtx-costs @@ -275,5 +275,5 @@ Assume loading data from flash is slower than fetching instructions. 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=.svn' -ruN gnu_trunk.p3/gcc/gcc/config/arm/arm-protos.h gnu_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.750726995 +0200 +++ gnu_trunk.p4/gcc/gcc/config/arm/arm-protos.h 2015-05-06 14:36:32.231213422 +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 extern void arm_pr_long_calls (struct cpp_reader *); @@ -317,6 +320,8 @@ extern void arm_emit_eabi_attribute (const char *, int, int); +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); diff '--exclude=.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. 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. @item unused @cindex @code{unused} function attribute @@ -3417,6 +3418,26 @@ 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 +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 @node AVR Function Attributes @@ -18436,8 +18457,9 @@ @xref{Function Attributes}, for more information about the @code{target} attribute and the attribute syntax. -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 @table @code diff '--exclude=.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=}@var{state} configure option. +You can also override the ARM and Thumb mode for each function +by using the @code{target("thumb")} and @code{target("arm")} function attributes +(@pxref{ARM Function Attributes}) or pragmas (@pxref{Function Specific Option Pragmas}). + @item -mtpcs-frame @opindex mtpcs-frame Generate a stack frame that is compliant with the Thumb Procedure Call diff '--exclude=.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=.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=*" } { "-march=armv6-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=.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 01:00:00.000000000 +0100 +++ gnu_trunk.p4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c 2015-05-06 14: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=.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_thumb-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__)) +foo (void) +{ + __asm__ (""); +} + +static void +__attribute__((__noinline__)) +__attribute__((target("thumb"))) +bar (void) +{ + __asm__ (""); +} + +int main() +{ + foo(); + bar(); +} ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2015-06-15 10:43 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-05-06 14:25 [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (4th) Christian Bruel 2015-05-06 23:04 ` Sandra Loosemore 2015-05-08 8:31 ` Ramana Radhakrishnan 2015-05-18 7:18 ` Christian Bruel 2015-05-18 8:16 ` [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (5th) Christian Bruel 2015-06-01 10:39 ` Kyrill Tkachov 2015-06-01 11:30 ` Christian Bruel 2015-06-01 12:41 ` Kyrill Tkachov 2015-06-01 12:55 ` Christian Bruel 2015-06-08 9:26 ` Christian Bruel 2015-06-08 9:33 ` Ramana Radhakrishnan 2015-06-10 8:26 ` [PATCH, ARM] (commited) attribute target (thumb,arm) [4/6] Christian Bruel 2015-06-15 10:15 ` James Greenhalgh 2015-06-15 12:05 ` Christian Bruel 2015-05-07 8:13 ` [PATCH, ARM] attribute target (thumb,arm) [4/6] respin (4th) Christian Bruel
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).