Hello Ramana >> > > Can you respin this now that we are in stage1 again ? > > Ramana >
Attached the rebased, rechecked set of patches. Original with comments posted in https://gcc.gnu.org/ml/gcc-patches/2014-11/msg02455.html https://gcc.gnu.org/ml/gcc-patches/2014-11/msg02458.html https://gcc.gnu.org/ml/gcc-patches/2014-11/msg02460.html https://gcc.gnu.org/ml/gcc-patches/2014-11/msg02461.html https://gcc.gnu.org/ml/gcc-patches/2014-11/msg02463.html https://gcc.gnu.org/ml/gcc-patches/2014-11/msg02467.html https://gcc.gnu.org/ml/gcc-patches/2014-11/msg02468.html many thanks, Christian
2014-09-23 Christian Bruel <christian.br...@st.com> * config/arm/arm.h (arm_option_override): Reoganized and split. (arm_option_params_internal); New function. (arm_option_check_internal): New function. (arm_option_override_internal): New function. (restrict_default): New boolean. (thumb_code, thumb1_code): Remove. * config/arm/arm.h (TREE_TARGET_THUMB, TREE_TARGET_THUMB1): New macros. (TREE_TARGET_THUM2, TREE_TARGET_ARM): Likewise. (thumb_code, thumb1_code): Remove. * config/arm/arm.md (is_thumb, is_thumb1): Check TARGET flag. diff -ruN '--exclude=.svn' a/gcc/gcc/config/arm/arm.c a1/gcc/gcc/config/arm/arm.c --- a/gcc/gcc/config/arm/arm.c 2015-02-04 09:14:26.120602737 +0100 +++ a1/gcc/gcc/config/arm/arm.c 2015-02-05 09:19:32.853338616 +0100 @@ -846,12 +846,6 @@ /* Nonzero if tuning for Cortex-A9. */ int arm_tune_cortex_a9 = 0; -/* Nonzero if generating Thumb instructions. */ -int thumb_code = 0; - -/* Nonzero if generating Thumb-1 instructions. */ -int thumb1_code = 0; - /* Nonzero if we should define __THUMB_INTERWORK__ in the preprocessor. XXX This is a bit of a hack, it's intended to help work around @@ -2623,6 +2617,148 @@ return std_gimplify_va_arg_expr (valist, type, pre_p, post_p); } +/* Check any incompatible options that the user has specified. */ +static void +arm_option_check_internal (struct gcc_options *opts) +{ + /* Make sure that the processor choice does not conflict with any of the + other command line choices. */ + if (TREE_TARGET_ARM (opts) && !(insn_flags & FL_NOTM)) + error ("target CPU does not support ARM mode"); + + /* TARGET_BACKTRACE calls leaf_function_p, which causes a crash if done + from here where no function is being compiled currently. */ + if ((TARGET_TPCS_FRAME || TARGET_TPCS_LEAF_FRAME) && TREE_TARGET_ARM (opts)) + warning (0, "enabling backtrace support is only meaningful when compiling for the Thumb"); + + if (TREE_TARGET_ARM (opts) && TARGET_CALLEE_INTERWORKING) + warning (0, "enabling callee interworking support is only meaningful when compiling for the Thumb"); + + /* If this target is normally configured to use APCS frames, warn if they + are turned off and debugging is turned on. */ + if (TREE_TARGET_ARM (opts) + && write_symbols != NO_DEBUG + && !TARGET_APCS_FRAME + && (TARGET_DEFAULT & MASK_APCS_FRAME)) + warning (0, "-g with -mno-apcs-frame may not give sensible debugging"); + + /* iWMMXt unsupported under Thumb mode. */ + if (TREE_TARGET_THUMB (opts) && TARGET_IWMMXT) + error ("iWMMXt unsupported under Thumb mode"); + + if (TARGET_HARD_TP && TREE_TARGET_THUMB1 (opts)) + error ("can not use -mtp=cp15 with 16-bit Thumb"); + + if (TREE_TARGET_THUMB (opts) && TARGET_VXWORKS_RTP && flag_pic) + { + error ("RTP PIC is incompatible with Thumb"); + flag_pic = 0; + } + + /* We only support -mslow-flash-data on armv7-m targets. */ + if (target_slow_flash_data + && ((!(arm_arch7 && !arm_arch_notm) && !arm_arch7em) + || (TREE_TARGET_THUMB1 (opts) || flag_pic || TARGET_NEON))) + error ("-mslow-flash-data only supports non-pic code on armv7-m targets"); +} + +/* Check any params depending on attributes that the user has specified. */ +static void +arm_option_params_internal (struct gcc_options *opts) +{ + /* If we are not using the default (ARM mode) section anchor offset + ranges, then set the correct ranges now. */ + if (TREE_TARGET_THUMB1 (opts)) + { + /* Thumb-1 LDR instructions cannot have negative offsets. + Permissible positive offset ranges are 5-bit (for byte loads), + 6-bit (for halfword loads), or 7-bit (for word loads). + Empirical results suggest a 7-bit anchor range gives the best + overall code size. */ + targetm.min_anchor_offset = 0; + targetm.max_anchor_offset = 127; + } + else if (TREE_TARGET_THUMB2 (opts)) + { + /* The minimum is set such that the total size of the block + for a particular anchor is 248 + 1 + 4095 bytes, which is + divisible by eight, ensuring natural spacing of anchors. */ + targetm.min_anchor_offset = -248; + targetm.max_anchor_offset = 4095; + } + else + { + targetm.min_anchor_offset = TARGET_MIN_ANCHOR_OFFSET; + targetm.max_anchor_offset = TARGET_MAX_ANCHOR_OFFSET; + } + + if (optimize_size) + { + /* If optimizing for size, bump the number of instructions that we + are prepared to conditionally execute (even on a StrongARM). */ + max_insns_skipped = 6; + + /* For THUMB2, we limit the conditional sequence to one IT block. */ + if (TREE_TARGET_THUMB2 (opts)) + max_insns_skipped = opts->x_arm_restrict_it ? 1 : 4; + } +} + +/* Reset options between modes that the user has specified. */ +static void +arm_option_override_internal (struct gcc_options *opts, + struct gcc_options *opts_set) +{ + if (TREE_TARGET_THUMB (opts) && !(insn_flags & FL_THUMB)) + { + warning (0, "target CPU does not support THUMB instructions"); + opts->x_target_flags &= ~MASK_THUMB; + } + + if (TARGET_APCS_FRAME && TREE_TARGET_THUMB (opts)) + { + /* warning (0, "ignoring -mapcs-frame because -mthumb was used"); */ + opts->x_target_flags &= ~MASK_APCS_FRAME; + } + + /* Callee super interworking implies thumb interworking. Adding + this to the flags here simplifies the logic elsewhere. */ + if (TREE_TARGET_THUMB (opts) && TARGET_CALLEE_INTERWORKING) + opts->x_target_flags |= MASK_INTERWORK; + + if (! opts_set->x_arm_restrict_it) + opts->x_arm_restrict_it = arm_arch8; + + if (!TREE_TARGET_THUMB2 (opts)) + 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; + } + + /* 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; + + /* In Thumb1 mode, we emit the epilogue in RTL, but the last insn + - epilogue_insns - does not accurately model the corresponding insns + emitted in the asm file. In particular, see the comment in thumb_exit + 'Find out how many of the (return) argument registers we can corrupt'. + As a consequence, the epilogue may clobber registers without fipa-ra + finding out about it. Therefore, disable fipa-ra in Thumb1 mode. + TODO: Accurately model clobbers for epilogue_insns and reenable + fipa-ra. */ + if (TREE_TARGET_THUMB1 (opts)) + opts->x_flag_ipa_ra = 0; + + /* Thumb2 inline assembly code should always use unified syntax. + This will apply to ARM and Thumb1 eventually. */ + opts->x_inline_asm_unified = TREE_TARGET_THUMB2 (opts); +} + /* Fix up any incompatible options that the user has specified. */ static void arm_option_override (void) @@ -2769,10 +2905,9 @@ tune_flags = arm_selected_tune->flags; current_tune = arm_selected_tune->tune; - /* Make sure that the processor choice does not conflict with any of the - other command line choices. */ - if (TARGET_ARM && !(insn_flags & FL_NOTM)) - error ("target CPU does not support ARM mode"); + /* TBD: Dwarf info for apcs frame is not handled yet. */ + if (TARGET_APCS_FRAME) + flag_shrink_wrap = false; /* BPABI targets use linker tricks to allow interworking on cores without thumb support. */ @@ -2782,31 +2917,6 @@ target_flags &= ~MASK_INTERWORK; } - if (TARGET_THUMB && !(insn_flags & FL_THUMB)) - { - warning (0, "target CPU does not support THUMB instructions"); - target_flags &= ~MASK_THUMB; - } - - if (TARGET_APCS_FRAME && TARGET_THUMB) - { - /* warning (0, "ignoring -mapcs-frame because -mthumb was used"); */ - target_flags &= ~MASK_APCS_FRAME; - } - - /* Callee super interworking implies thumb interworking. Adding - this to the flags here simplifies the logic elsewhere. */ - if (TARGET_THUMB && TARGET_CALLEE_INTERWORKING) - target_flags |= MASK_INTERWORK; - - /* TARGET_BACKTRACE calls leaf_function_p, which causes a crash if done - from here where no function is being compiled currently. */ - if ((TARGET_TPCS_FRAME || TARGET_TPCS_LEAF_FRAME) && TARGET_ARM) - warning (0, "enabling backtrace support is only meaningful when compiling for the Thumb"); - - if (TARGET_ARM && TARGET_CALLEE_INTERWORKING) - warning (0, "enabling callee interworking support is only meaningful when compiling for the Thumb"); - if (TARGET_APCS_STACK && !TARGET_APCS_FRAME) { warning (0, "-mapcs-stack-check incompatible with -mno-apcs-frame"); @@ -2822,14 +2932,6 @@ if (TARGET_APCS_REENT) warning (0, "APCS reentrant code not supported. Ignored"); - /* If this target is normally configured to use APCS frames, warn if they - are turned off and debugging is turned on. */ - if (TARGET_ARM - && write_symbols != NO_DEBUG - && !TARGET_APCS_FRAME - && (TARGET_DEFAULT & MASK_APCS_FRAME)) - warning (0, "-g with -mno-apcs-frame may not give sensible debugging"); - if (TARGET_APCS_FLOAT) warning (0, "passing floating point arguments in fp regs not yet supported"); @@ -2851,8 +2953,6 @@ arm_ld_sched = (tune_flags & FL_LDSCHED) != 0; arm_tune_strongarm = (tune_flags & FL_STRONG) != 0; - thumb_code = TARGET_ARM == 0; - thumb1_code = TARGET_THUMB1 != 0; arm_tune_wbuf = (tune_flags & FL_WBUF) != 0; arm_tune_xscale = (tune_flags & FL_XSCALE) != 0; arm_arch_iwmmxt = (insn_flags & FL_IWMMXT) != 0; @@ -2862,32 +2962,6 @@ arm_tune_cortex_a9 = (arm_tune == cortexa9) != 0; arm_arch_crc = (insn_flags & FL_CRC32) != 0; arm_m_profile_small_mul = (insn_flags & FL_SMALLMUL) != 0; - if (arm_restrict_it == 2) - arm_restrict_it = arm_arch8 && TARGET_THUMB2; - - if (!TARGET_THUMB2) - arm_restrict_it = 0; - - /* If we are not using the default (ARM mode) section anchor offset - ranges, then set the correct ranges now. */ - if (TARGET_THUMB1) - { - /* Thumb-1 LDR instructions cannot have negative offsets. - Permissible positive offset ranges are 5-bit (for byte loads), - 6-bit (for halfword loads), or 7-bit (for word loads). - Empirical results suggest a 7-bit anchor range gives the best - overall code size. */ - targetm.min_anchor_offset = 0; - targetm.max_anchor_offset = 127; - } - else if (TARGET_THUMB2) - { - /* The minimum is set such that the total size of the block - for a particular anchor is 248 + 1 + 4095 bytes, which is - divisible by eight, ensuring natural spacing of anchors. */ - targetm.min_anchor_offset = -248; - targetm.max_anchor_offset = 4095; - } /* V5 code we generate is completely interworking capable, so we turn off TARGET_INTERWORK here to avoid many tests later on. */ @@ -2906,6 +2980,9 @@ if (TARGET_IWMMXT_ABI && !TARGET_IWMMXT) error ("iwmmxt abi requires an iwmmxt capable cpu"); + if (! optimize_size) + max_insns_skipped = current_tune->max_insns_skipped; + if (!global_options_set.x_arm_fpu_index) { const char *target_fpu_name; @@ -2947,10 +3024,6 @@ if (TARGET_IWMMXT && TARGET_NEON) error ("iWMMXt and NEON are incompatible"); - /* iWMMXt unsupported under Thumb mode. */ - if (TARGET_THUMB && TARGET_IWMMXT) - error ("iWMMXt unsupported under Thumb mode"); - /* __fp16 support currently assumes the core has ldrh. */ if (!arm_arch4 && arm_fp16_format != ARM_FP16_FORMAT_NONE) sorry ("__fp16 and no ldrh"); @@ -2995,9 +3068,6 @@ target_thread_pointer = TP_SOFT; } - if (TARGET_HARD_TP && TARGET_THUMB1) - error ("can not use -mtp=cp15 with 16-bit Thumb"); - /* Override the default structure alignment for AAPCS ABI. */ if (!global_options_set.x_arm_structure_size_boundary) { @@ -3020,12 +3090,6 @@ } } - if (!TARGET_ARM && TARGET_VXWORKS_RTP && flag_pic) - { - error ("RTP PIC is incompatible with Thumb"); - flag_pic = 0; - } - /* If stack checking is disabled, we can use r10 as the PIC register, which keeps r9 available. The EABI specifies r9 as the PIC register. */ if (flag_pic && TARGET_SINGLE_PIC_BASE) @@ -3093,25 +3157,6 @@ unaligned_access = 0; } - if (TARGET_THUMB1 && flag_schedule_insns) - { - /* Don't warn since it's on by default in -O2. */ - flag_schedule_insns = 0; - } - - if (optimize_size) - { - /* If optimizing for size, bump the number of instructions that we - are prepared to conditionally execute (even on a StrongARM). */ - max_insns_skipped = 6; - - /* For THUMB2, we limit the conditional sequence to one IT block. */ - if (TARGET_THUMB2) - max_insns_skipped = MAX_INSN_PER_IT_BLOCK; - } - else - max_insns_skipped = current_tune->max_insns_skipped; - /* Hot/Cold partitioning is not currently supported, since we can't handle literal pool placement in that case. */ if (flag_reorder_blocks_and_partition) @@ -3189,45 +3234,19 @@ global_options.x_param_values, global_options_set.x_param_values); - /* Disable shrink-wrap when optimizing function for size, since it tends to - generate additional returns. */ - if (optimize_function_for_size_p (cfun) && TARGET_THUMB2) - flag_shrink_wrap = false; - /* TBD: Dwarf info for apcs frame is not handled yet. */ - if (TARGET_APCS_FRAME) - flag_shrink_wrap = false; - - /* We only support -mslow-flash-data on armv7-m targets. */ - if (target_slow_flash_data - && ((!(arm_arch7 && !arm_arch_notm) && !arm_arch7em) - || (TARGET_THUMB1 || flag_pic || TARGET_NEON))) - error ("-mslow-flash-data only supports non-pic code on armv7-m targets"); - /* Currently, for slow flash data, we just disable literal pools. */ if (target_slow_flash_data) arm_disable_literal_pool = true; - /* Thumb2 inline assembly code should always use unified syntax. - This will apply to ARM and Thumb1 eventually. */ - if (TARGET_THUMB2) - inline_asm_unified = 1; - /* Disable scheduling fusion by default if it's not armv7 processor or doesn't prefer ldrd/strd. */ if (flag_schedule_fusion == 2 && (!arm_arch7 || !current_tune->prefer_ldrd_strd)) flag_schedule_fusion = 0; - /* In Thumb1 mode, we emit the epilogue in RTL, but the last insn - - epilogue_insns - does not accurately model the corresponding insns - emitted in the asm file. In particular, see the comment in thumb_exit - 'Find out how many of the (return) argument registers we can corrupt'. - As a consequence, the epilogue may clobber registers without fipa-ra - finding out about it. Therefore, disable fipa-ra in Thumb1 mode. - TODO: Accurately model clobbers for epilogue_insns and reenable - fipa-ra. */ - if (TARGET_THUMB1) - flag_ipa_ra = 0; + 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 (); diff -ruN '--exclude=.svn' a/gcc/gcc/config/arm/arm.h a1/gcc/gcc/config/arm/arm.h --- a/gcc/gcc/config/arm/arm.h 2015-01-20 15:58:49.230503992 +0100 +++ a1/gcc/gcc/config/arm/arm.h 2015-01-22 13:48:29.338437070 +0100 @@ -252,5 +252,12 @@ #define SUBTARGET_CPP_SPEC "" #endif +/* Tree Target Specification. */ +#define TREE_TARGET_THUMB(opts) (TARGET_THUMB_P (opts->x_target_flags)) +#define TREE_TARGET_ARM(opts) (!TARGET_THUMB_P (opts->x_target_flags)) +#define TREE_TARGET_THUMB1(opts) (TARGET_THUMB_P (opts->x_target_flags) \ + && !arm_arch_thumb2) +#define TREE_TARGET_THUMB2(opts) (TARGET_THUMB_P (opts->x_target_flags) \ + && arm_arch_thumb2) /* Run-time Target Specification. */ #define TARGET_SOFT_FLOAT (arm_float_abi == ARM_FLOAT_ABI_SOFT) /* Use hardware floating point instructions. */ @@ -525,12 +532,6 @@ /* Nonzero if this chip can benefit from load scheduling. */ extern int arm_ld_sched; -/* Nonzero if generating Thumb code, either Thumb-1 or Thumb-2. */ -extern int thumb_code; - -/* Nonzero if generating Thumb-1 code. */ -extern int thumb1_code; - /* Nonzero if this chip is a StrongARM. */ extern int arm_tune_strongarm; diff -ruN '--exclude=.svn' a/gcc/gcc/config/arm/arm.md a1/gcc/gcc/config/arm/arm.md --- a/gcc/gcc/config/arm/arm.md 2015-01-26 11:04:05.937275841 +0100 +++ a1/gcc/gcc/config/arm/arm.md 2015-02-05 09:19:32.857338621 +0100 @@ -69,13 +69,17 @@ ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when ; generating ARM code. This is used to control the length of some insn ; patterns that share the same RTL in both ARM and Thumb code. -(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code"))) +(define_attr "is_thumb" "yes,no" + (const (if_then_else (symbol_ref "TARGET_THUMB") + (const_string "yes") (const_string "no")))) ; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6. (define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6"))) ; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code. -(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code"))) +(define_attr "is_thumb1" "yes,no" + (const (if_then_else (symbol_ref "TARGET_THUMB1") + (const_string "yes") (const_string "no")))) ; We use this attribute to disable alternatives that can produce 32-bit ; instructions inside an IT-block in Thumb2 state. ARMv8 deprecates IT blocks
Christian Bruel <christian.br...@st.com> * config/arm/arm-c.c (cpp_def_or_undef): New functions. (arm_cpp_builtins): Likewise. * config/arm/arm.h (TARGET_CPU_CPP_BUILTINS): Move mode dependant macros to arm_cpp_builtins. * config/arm/arm-protos.h (arm_cpp_builtins): Declare. diff -ruN '--exclude=.svn' a1/gcc/gcc/config/arm/arm-c.c a2/gcc/gcc/config/arm/arm-c.c --- a1/gcc/gcc/config/arm/arm-c.c 2015-01-13 12:34:38.910459998 +0100 +++ a2/gcc/gcc/config/arm/arm-c.c 2015-01-15 13:32:30.683013516 +0100 @@ -51,3 +51,73 @@ { arm_lang_output_object_attributes_hook = arm_output_c_attributes; } + +/* Define or undefine macro. */ + +static void +cpp_def_or_undef (struct cpp_reader *in, const char *str, bool def_p) +{ + if (def_p) + cpp_define (in, str); + else + cpp_undef (in, str); +} + +/* Define or undefine macros based on the current target. If the user does + #pragma GCC target, we need to adjust the macros dynamically. */ + +void +arm_cpp_builtins (struct cpp_reader *in, bool thumb_p) +{ + bool target_32bit_p = !thumb_p || arm_arch_thumb2; + bool thumb2_p = thumb_p && arm_arch_thumb2; + bool have_ldrex_p = (arm_arch6 && !thumb_p) || arm_arch7; + bool have_ldrexbh_p = (arm_arch6k && !thumb_p) || arm_arch7; + bool have_ldrexd_p = ((arm_arch6k && !thumb_p) || arm_arch7) + && arm_arch_notm; + + int arm_feature_ldrex = (have_ldrex_p ? 4 : 0) + | (have_ldrexbh_p ? 3 : 0) | (have_ldrexd_p ? 8 : 0); + + cpp_def_or_undef (in, "__thumb__", thumb_p); + if (arm_arch_thumb2) + cpp_def_or_undef (in, "__thumb2__", thumb_p); + if (TARGET_BIG_END) + cpp_def_or_undef (in, "__THUMBEB__", thumb_p); + else + cpp_def_or_undef (in, "__THUMBEL__", thumb_p); + + cpp_def_or_undef (in, "__ARM_32BIT_STATE", target_32bit_p); /* TARGET_32BIT */ + + if (arm_arch5e && (arm_arch_notm || arm_arch7)) /* TARGET_ARM_QBIT */ + cpp_def_or_undef (in, "__ARM_FEATURE_QBIT", target_32bit_p); + + if (arm_arch6 && (arm_arch_notm || arm_arch7)) /* TARGET_ARM_SAT */ + cpp_def_or_undef (in, "__ARM_FEATURE_SAT", target_32bit_p); + + if (arm_arch5e && (arm_arch_notm || arm_arch7em)) /* TARGET_DSP_MULTIPLY */ + cpp_def_or_undef (in, "__ARM_FEATURE_DSP", target_32bit_p); + + if (arm_arch6 && (arm_arch_notm || arm_arch7em)) /* TARGET_INT_SIMD */ + cpp_def_or_undef (in, "__ARM_FEATURE_SIMD32", target_32bit_p); + + /* TARGET_IDIV */ + cpp_def_or_undef (in, "__ARM_ARCH_EXT_IDIV__", + ((!thumb_p && arm_arch_arm_hwdiv) + || (thumb2_p && arm_arch_thumb_hwdiv))); + + cpp_def_or_undef (in, "__ARM_FEATURE_IDIV", + ((!thumb_p && arm_arch_arm_hwdiv) + || (thumb2_p && arm_arch_thumb_hwdiv))); + + if (arm_feature_ldrex) + cpp_define_formatted (in, "__ARM_FEATURE_LDREX=%d", arm_feature_ldrex); + else + cpp_undef (in, "__ARM_FEATURE_LDREX"); + + cpp_def_or_undef (in, "__ARM_FEATURE_CLZ", + ((TARGET_ARM_ARCH >= 5 && !thumb_p) || TARGET_ARM_ARCH_ISA_THUMB >=2)); + + cpp_def_or_undef (in, "__ARM_ASM_SYNTAX_UNIFIED__", inline_asm_unified); +} + diff -ruN '--exclude=.svn' a1/gcc/gcc/config/arm/arm.h a2/gcc/gcc/config/arm/arm.h --- a1/gcc/gcc/config/arm/arm.h 2015-01-22 13:48:29.338437070 +0100 +++ a2/gcc/gcc/config/arm/arm.h 2015-01-22 13:52:58.062879846 +0100 @@ -48,29 +48,12 @@ #define TARGET_CPU_CPP_BUILTINS() \ do \ { \ - if (TARGET_DSP_MULTIPLY) \ - builtin_define ("__ARM_FEATURE_DSP"); \ - if (TARGET_ARM_QBIT) \ - builtin_define ("__ARM_FEATURE_QBIT"); \ - if (TARGET_ARM_SAT) \ - builtin_define ("__ARM_FEATURE_SAT"); \ if (TARGET_CRYPTO) \ builtin_define ("__ARM_FEATURE_CRYPTO"); \ if (unaligned_access) \ builtin_define ("__ARM_FEATURE_UNALIGNED"); \ if (TARGET_CRC32) \ builtin_define ("__ARM_FEATURE_CRC32"); \ - if (TARGET_32BIT) \ - builtin_define ("__ARM_32BIT_STATE"); \ - if (TARGET_ARM_FEATURE_LDREX) \ - builtin_define_with_int_value ( \ - "__ARM_FEATURE_LDREX", TARGET_ARM_FEATURE_LDREX); \ - if ((TARGET_ARM_ARCH >= 5 && !TARGET_THUMB) \ - || TARGET_ARM_ARCH_ISA_THUMB >=2) \ - builtin_define ("__ARM_FEATURE_CLZ"); \ - if (TARGET_INT_SIMD) \ - builtin_define ("__ARM_FEATURE_SIMD32"); \ - \ builtin_define_with_int_value ( \ "__ARM_SIZEOF_MINIMAL_ENUM", \ flag_short_enums ? 1 : 4); \ @@ -89,10 +72,6 @@ if (arm_arch_notm) \ builtin_define ("__ARM_ARCH_ISA_ARM"); \ builtin_define ("__APCS_32__"); \ - if (TARGET_THUMB) \ - builtin_define ("__thumb__"); \ - if (TARGET_THUMB2) \ - builtin_define ("__thumb2__"); \ if (TARGET_ARM_ARCH_ISA_THUMB) \ builtin_define_with_int_value ( \ "__ARM_ARCH_ISA_THUMB", \ @@ -102,15 +81,9 @@ { \ builtin_define ("__ARMEB__"); \ builtin_define ("__ARM_BIG_ENDIAN"); \ - if (TARGET_THUMB) \ - builtin_define ("__THUMBEB__"); \ } \ else \ - { \ builtin_define ("__ARMEL__"); \ - if (TARGET_THUMB) \ - builtin_define ("__THUMBEL__"); \ - } \ \ if (TARGET_SOFT_FLOAT) \ builtin_define ("__SOFTFP__"); \ @@ -163,13 +136,8 @@ builtin_define ("__ARM_PCS"); \ builtin_define ("__ARM_EABI__"); \ } \ - if (TARGET_IDIV) \ - { \ - builtin_define ("__ARM_ARCH_EXT_IDIV__"); \ - builtin_define ("__ARM_FEATURE_IDIV"); \ - } \ - if (inline_asm_unified) \ - builtin_define ("__ARM_ASM_SYNTAX_UNIFIED__");\ + /* Remaining macros depends on TARGET_THUMB. */\ + arm_cpp_builtins (pfile, TARGET_THUMB); \ } while (0) #include "config/arm/arm-opts.h" diff -ruN '--exclude=.svn' a1/gcc/gcc/config/arm/arm-protos.h a2/gcc/gcc/config/arm/arm-protos.h --- a1/gcc/gcc/config/arm/arm-protos.h 2015-01-22 13:48:29.342437077 +0100 +++ a2/gcc/gcc/config/arm/arm-protos.h 2015-01-22 13:52:58.098879905 +0100 @@ -222,8 +222,6 @@ extern void arm_pr_no_long_calls (struct cpp_reader *); extern void arm_pr_long_calls_off (struct cpp_reader *); -extern void arm_lang_object_attributes_init(void); - extern const char *arm_mangle_type (const_tree); extern const char *arm_mangle_builtin_type (const_tree); @@ -323,6 +321,10 @@ /* Defined in gcc/common/config/arm-common.c. */ extern const char *arm_rewrite_selected_cpu (const char *name); +/* Defined in gcc/common/config/arm-c.c. */ +extern void arm_lang_object_attributes_init(void); +extern void arm_cpp_builtins (struct cpp_reader *, bool); + extern bool arm_is_constant_pool_ref (rtx); /* Flags used to identify the presence of processor capabilities. */
2014-09-23 Christian Bruel <christian.br...@st.com> * config/arm/arm-protos.h (arm_declare_function_name): Declare. (is_called_in_ARM_mode): Remove. * config/arm/arm.c (is_called_in_ARM_mode): Declare static bool. (arm_declare_function_name): Moved from from ARM_DECLARE_FUNCTION_NAME. * config/arm/arm.h (ARM_DECLARE_FUNCTION_NAME): Call arm_declare_function_name. diff -ruN '--exclude=.svn' a2/gcc/gcc/config/arm/arm.c a3/gcc/gcc/config/arm/arm.c --- a2/gcc/gcc/config/arm/arm.c 2015-02-05 09:20:13.225397216 +0100 +++ a3/gcc/gcc/config/arm/arm.c 2015-02-05 09:20:12.653396291 +0100 @@ -23645,6 +23645,23 @@ fprintf (f, "}\n"); } +/* Return nonzero if FUNC must be entered in ARM mode. */ +static bool +is_called_in_ARM_mode (tree func) +{ + gcc_assert (TREE_CODE (func) == FUNCTION_DECL); + + /* Ignore the problem about functions whose address is taken. */ + if (TARGET_CALLEE_INTERWORKING && TREE_PUBLIC (func)) + return true; + +#ifdef ARM_PE + return lookup_attribute ("interfacearm", DECL_ATTRIBUTES (func)) != NULL_TREE; +#else + return false; +#endif +} + /* Generate code to return from a thumb function. If 'reg_containing_return_addr' is -1, then the return address is actually on the stack, at the stack pointer. */ @@ -24080,22 +24097,6 @@ return 0; } -/* Return nonzero if FUNC must be entered in ARM mode. */ -int -is_called_in_ARM_mode (tree func) -{ - gcc_assert (TREE_CODE (func) == FUNCTION_DECL); - - /* Ignore the problem about functions whose address is taken. */ - if (TARGET_CALLEE_INTERWORKING && TREE_PUBLIC (func)) - return TRUE; - -#ifdef ARM_PE - return lookup_attribute ("interfacearm", DECL_ATTRIBUTES (func)) != NULL_TREE; -#else - return FALSE; -#endif -} /* Given the stack offsets and register mask in OFFSETS, decide how many additional registers to push instead of subtracting a constant @@ -29435,6 +29436,25 @@ && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0))); } +void +arm_declare_function_name (FILE *stream, const char *name, tree decl) +{ + if (TARGET_THUMB) + { + if (is_called_in_ARM_mode (decl) + || (TARGET_THUMB1 && !TARGET_THUMB1_ONLY + && cfun->is_thunk)) + fprintf (stream, "\t.code 32\n"); + else if (TARGET_THUMB1) + fprintf (stream, "\t.code\t16\n\t.thumb_func\n"); + else + fprintf (stream, "\t.thumb\n\t.thumb_func\n"); + } + + if (TARGET_POKE_FUNCTION_NAME) + arm_poke_function_name (stream, (const char *) name); +} + /* If MEM is in the form of [base+offset], extract the two parts of address and set to BASE and OFFSET, otherwise return false after clearing BASE and OFFSET. */ @@ -29555,4 +29575,5 @@ *pri = tmp; return; } + #include "gt-arm.h" diff -ruN '--exclude=.svn' a2/gcc/gcc/config/arm/arm.h a3/gcc/gcc/config/arm/arm.h --- a2/gcc/gcc/config/arm/arm.h 2015-01-22 13:52:58.062879846 +0100 +++ a3/gcc/gcc/config/arm/arm.h 2015-01-22 13:53:11.218901428 +0100 @@ -2185,23 +2185,7 @@ ? 1 : 0) #define ARM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \ - do \ - { \ - if (TARGET_THUMB) \ - { \ - if (is_called_in_ARM_mode (DECL) \ - || (TARGET_THUMB1 && !TARGET_THUMB1_ONLY \ - && cfun->is_thunk)) \ - fprintf (STREAM, "\t.code 32\n") ; \ - else if (TARGET_THUMB1) \ - fprintf (STREAM, "\t.code\t16\n\t.thumb_func\n") ; \ - else \ - fprintf (STREAM, "\t.thumb\n\t.thumb_func\n") ; \ - } \ - if (TARGET_POKE_FUNCTION_NAME) \ - arm_poke_function_name (STREAM, (const char *) NAME); \ - } \ - while (0) + arm_declare_function_name ((STREAM), (NAME), (DECL)); /* For aliases of functions we use .thumb_set instead. */ #define ASM_OUTPUT_DEF_FROM_DECLS(FILE, DECL1, DECL2) \ diff -ruN '--exclude=.svn' a2/gcc/gcc/config/arm/arm-protos.h a3/gcc/gcc/config/arm/arm-protos.h --- a2/gcc/gcc/config/arm/arm-protos.h 2015-01-22 13:52:58.098879905 +0100 +++ a3/gcc/gcc/config/arm/arm-protos.h 2015-01-22 13:53:11.222901435 +0100 @@ -30,6 +30,7 @@ extern int arm_volatile_func (void); extern void arm_expand_prologue (void); extern void arm_expand_epilogue (bool); +extern void arm_declare_function_name (FILE *, const char *, tree); extern void thumb2_expand_return (bool); extern const char *arm_strip_name_encoding (const char *); extern void arm_asm_output_labelref (FILE *, const char *); @@ -185,9 +186,6 @@ extern void thumb1_expand_prologue (void); extern void thumb1_expand_epilogue (void); extern const char *thumb1_output_interwork (void); -#ifdef TREE_CODE -extern int is_called_in_ARM_mode (tree); -#endif extern int thumb_shiftable_const (unsigned HOST_WIDE_INT); #ifdef RTX_CODE extern enum arm_cond_code maybe_get_arm_condition_code (rtx);
2014-09-23 Christian Bruel <christian.br...@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 -ruN '--exclude=.svn' a3/gcc/gcc/config/arm/arm.c a4/gcc/gcc/config/arm/arm.c --- a3/gcc/gcc/config/arm/arm.c 2015-02-05 09:20:12.653396291 +0100 +++ a4/gcc/gcc/config/arm/arm.c 2015-02-05 09:20:12.193395549 +0100 @@ -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 @@ -2704,6 +2717,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, @@ -2726,6 +2742,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; @@ -2733,15 +2753,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 @@ -2753,6 +2775,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. */ @@ -3244,12 +3268,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 @@ -3403,13 +3435,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", @@ -24097,6 +24136,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 @@ -25659,9 +25715,6 @@ { int val; - if (TARGET_UNIFIED_ASM) - asm_fprintf (asm_out_file, "\t.syntax unified\n"); - if (TARGET_BPABI) { const char *fpu_name; @@ -29436,9 +29489,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 (!strncmp (argstr, "thumb", 5)) + { + opts->x_target_flags |= MASK_THUMB; + arm_option_check_internal (opts); + return true; + } + + if (!strncmp (argstr, "arm", 3)) + { + 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) @@ -29450,6 +29690,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 -ruN '--exclude=.svn' a3/gcc/gcc/config/arm/arm.h a4/gcc/gcc/config/arm/arm.h --- a3/gcc/gcc/config/arm/arm.h 2015-01-22 13:53:11.218901428 +0100 +++ a4/gcc/gcc/config/arm/arm.h 2015-01-22 13:56:30.235226925 +0100 @@ -2360,4 +2360,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 -ruN '--exclude=.svn' a3/gcc/gcc/config/arm/arm.md a4/gcc/gcc/config/arm/arm.md --- a3/gcc/gcc/config/arm/arm.md 2015-02-05 09:20:12.657396298 +0100 +++ a4/gcc/gcc/config/arm/arm.md 2015-02-05 09:20:12.233395613 +0100 @@ -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 -ruN '--exclude=.svn' a3/gcc/gcc/config/arm/arm.opt a4/gcc/gcc/config/arm/arm.opt --- a3/gcc/gcc/config/arm/arm.opt 2015-01-22 13:53:11.222901435 +0100 +++ a4/gcc/gcc/config/arm/arm.opt 2015-02-09 12:34:43.188559954 +0100 @@ -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 @@ -240,7 +240,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 @@ -269,5 +269,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 -ruN '--exclude=.svn' a3/gcc/gcc/config/arm/arm-protos.h a4/gcc/gcc/config/arm/arm-protos.h --- a3/gcc/gcc/config/arm/arm-protos.h 2015-01-22 13:53:11.222901435 +0100 +++ a4/gcc/gcc/config/arm/arm-protos.h 2015-01-22 13:56:30.239226931 +0100 @@ -214,6 +214,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 *); @@ -316,6 +319,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 -ruN '--exclude=.svn' a3/gcc/gcc/doc/extend.texi a4/gcc/gcc/doc/extend.texi --- a3/gcc/gcc/doc/extend.texi 2015-02-05 09:18:12.909233395 +0100 +++ a4/gcc/gcc/doc/extend.texi 2015-02-05 09:21:38.749534626 +0100 @@ -3996,10 +3996,25 @@ strings to specify multiple options, or separate the options with a comma (@samp{,}). -The @code{target} attribute is presently implemented for -x86, PowerPC, and Nios II targets only. +The @code{target} attribute is implemented for +ARM, x86, PowerPC, and Nios II targets. + The options supported are specific to each target. +for ARM, the following options are allowed: + +@table @samp +@item thumb +@cindex @code{target("thumb")} attribute +Force Thumb1 Thumb2 code generation depending on the architecture. + +@item arm +@cindex @code{target("arm")} attribute +Force ARM code generation. +@end table + +Functions from different modes can be inlined , unless the callee has asm statements. + On the x86, the following options are allowed: @table @samp @@ -17795,8 +17810,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 -ruN '--exclude=.svn' a3/gcc/gcc/doc/invoke.texi a4/gcc/gcc/doc/invoke.texi --- a3/gcc/gcc/doc/invoke.texi 2015-02-05 09:18:12.913233401 +0100 +++ a4/gcc/gcc/doc/invoke.texi 2015-02-05 09:18:24.465248626 +0100 @@ -13149,6 +13149,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 -ruN '--exclude=.svn' a3/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c a4/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c --- a3/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c 1970-01-01 01:00:00.000000000 +0100 +++ a4/gcc/gcc/testsuite/gcc.target/arm/attr_arm.c 2015-01-15 13:35:12.135273352 +0100 @@ -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 -ruN '--exclude=.svn' a3/gcc/gcc/testsuite/gcc.target/arm/attr_arm-err.c a4/gcc/gcc/testsuite/gcc.target/arm/attr_arm-err.c --- a3/gcc/gcc/testsuite/gcc.target/arm/attr_arm-err.c 1970-01-01 01:00:00.000000000 +0100 +++ a4/gcc/gcc/testsuite/gcc.target/arm/attr_arm-err.c 2015-01-15 13:35:12.139273358 +0100 @@ -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 -ruN '--exclude=.svn' a3/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c a4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c --- a3/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c 1970-01-01 01:00:00.000000000 +0100 +++ a4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb.c 2015-01-15 13:35:12.139273358 +0100 @@ -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 -ruN '--exclude=.svn' a3/gcc/gcc/testsuite/gcc.target/arm/attr_thumb-static.c a4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb-static.c --- a3/gcc/gcc/testsuite/gcc.target/arm/attr_thumb-static.c 1970-01-01 01:00:00.000000000 +0100 +++ a4/gcc/gcc/testsuite/gcc.target/arm/attr_thumb-static.c 2015-01-15 13:35:12.139273358 +0100 @@ -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(); +}
2014-09-23 Christian Bruel <christian.br...@st.com> * config/arm/arm.h (REGISTER_TARGET_PRAGMAS): Call arm_register_target_pragmas. * config/arm/arm-protos.h (arm_register_target_pragmas): Declare. * config/arm/arm-c.c (arm_register_target_pragmas): New function. (arm_pragma_target_parse): Likewise. diff -ruN '--exclude=.svn' a4/gcc/gcc/config/arm/arm-c.c a5/gcc/gcc/config/arm/arm-c.c --- a4/gcc/gcc/config/arm/arm-c.c 2015-01-15 13:35:07.195265398 +0100 +++ a5/gcc/gcc/config/arm/arm-c.c 2015-01-15 13:36:28.935397056 +0100 @@ -20,7 +20,6 @@ #include "system.h" #include "coretypes.h" #include "tm.h" -#include "tm_p.h" #include "hash-set.h" #include "machmode.h" #include "vec.h" @@ -31,7 +30,11 @@ #include "wide-int.h" #include "inchash.h" #include "tree.h" +#include "tm_p.h" #include "c-family/c-common.h" +#include "target.h" +#include "target-def.h" +#include "c-family/c-pragma.h" /* Output C specific EABI object attributes. These can not be done in arm.c because they require information from the C frontend. */ @@ -121,3 +124,79 @@ cpp_def_or_undef (in, "__ARM_ASM_SYNTAX_UNIFIED__", inline_asm_unified); } +/* Hook to validate the current #pragma GCC target and set the arch custom + mode state. If ARGS is NULL, then POP_TARGET is used to reset + the options. */ +static bool +arm_pragma_target_parse (tree args, tree pop_target) +{ + tree prev_tree = build_target_option_node (&global_options); + tree cur_tree; + struct cl_target_option *prev_opt; + struct cl_target_option *cur_opt; + bool cur_mode, prev_mode; + + if (! args) + { + cur_tree = ((pop_target) ? pop_target : target_option_default_node); + cl_target_option_restore (&global_options, + TREE_TARGET_OPTION (cur_tree)); + } + else + { + cur_tree = arm_valid_target_attribute_tree (args, &global_options, + &global_options_set); + if (cur_tree == NULL_TREE) + { + cl_target_option_restore (&global_options, + TREE_TARGET_OPTION (prev_tree)); + return false; + } + } + + target_option_current_node = cur_tree; + arm_reset_previous_fndecl (); + + /* Figure out the previous mode. */ + prev_opt = TREE_TARGET_OPTION (prev_tree); + cur_opt = TREE_TARGET_OPTION (cur_tree); + + gcc_assert (prev_opt); + gcc_assert (cur_opt); + + cur_mode = TARGET_THUMB_P (cur_opt->x_target_flags); + prev_mode = TARGET_THUMB_P (prev_opt->x_target_flags); + + if (prev_mode != cur_mode) + { + /* For the definitions, ensure all newly defined macros are considered + as used for -Wunused-macros. There is no point warning about the + compiler predefined macros. */ + cpp_options *cpp_opts = cpp_get_options (parse_in); + unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros; + cpp_opts->warn_unused_macros = 0; + + /* Update macros. */ + arm_cpp_builtins (parse_in, cur_mode); + + cpp_opts->warn_unused_macros = saved_warn_unused_macros; + } + + return true; +} + +/* Register target pragmas. We need to add the hook for parsing #pragma GCC + option here rather than in arm.c since it will pull in various preprocessor + functions, and those are not present in languages like fortran without a + preprocessor. */ + +void +arm_register_target_pragmas (void) +{ + /* Update pragma hook to allow parsing #pragma GCC target. */ + targetm.target_option.pragma_parse = arm_pragma_target_parse; + +#ifdef REGISTER_SUBTARGET_PRAGMAS + REGISTER_SUBTARGET_PRAGMAS (); +#endif +} diff -ruN '--exclude=.svn' a4/gcc/gcc/config/arm/arm.h a5/gcc/gcc/config/arm/arm.h --- a4/gcc/gcc/config/arm/arm.h 2015-01-22 13:56:30.235226925 +0100 +++ a5/gcc/gcc/config/arm/arm.h 2015-01-22 13:56:45.251251411 +0100 @@ -2098,7 +2098,8 @@ c_register_pragma (0, "long_calls", arm_pr_long_calls); \ c_register_pragma (0, "no_long_calls", arm_pr_no_long_calls); \ c_register_pragma (0, "long_calls_off", arm_pr_long_calls_off); \ - arm_lang_object_attributes_init(); \ + arm_lang_object_attributes_init(); \ + arm_register_target_pragmas(); \ } while (0) /* Condition code information. */ diff -ruN '--exclude=.svn' a4/gcc/gcc/config/arm/arm-protos.h a5/gcc/gcc/config/arm/arm-protos.h --- a4/gcc/gcc/config/arm/arm-protos.h 2015-01-22 13:56:30.239226931 +0100 +++ a5/gcc/gcc/config/arm/arm-protos.h 2015-01-22 13:56:45.255251418 +0100 @@ -326,6 +326,7 @@ /* Defined in gcc/common/config/arm-c.c. */ extern void arm_lang_object_attributes_init(void); +extern void arm_register_target_pragmas (void); extern void arm_cpp_builtins (struct cpp_reader *, bool); extern bool arm_is_constant_pool_ref (rtx); diff -ruN '--exclude=.svn' a4/gcc/gcc/testsuite/gcc.target/arm/pragma_attribute.c a5/gcc/gcc/testsuite/gcc.target/arm/pragma_attribute.c --- a4/gcc/gcc/testsuite/gcc.target/arm/pragma_attribute.c 1970-01-01 01:00:00.000000000 +0100 +++ a5/gcc/gcc/testsuite/gcc.target/arm/pragma_attribute.c 2015-01-15 13:36:28.935397056 +0100 @@ -0,0 +1,35 @@ +/* Test for #prama target macros. */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb1_ok } */ + +#pragma GCC target ("thumb") + +#ifndef __thumb__ +#error "__thumb__ is not defined" +#endif + +#ifdef __thumb2__ +#ifndef __ARM_32BIT_STATE +#error "__ARM_32BIT_STATE is not defined" +#endif +#else /* thumb1 */ +#ifdef __ARM_32BIT_STATE +#error "__ARM_32BIT_STATE is defined" +#endif +#endif /* thumb1 */ + +#pragma GCC target ("arm") + +#ifdef __thumb__ +#error "__thumb__ is defined" +#endif + +#if defined (__thumb2__) || defined (__thumb1__) +#error "thumb is defined" +#endif + +#ifndef __ARM_32BIT_STATE +#error "__ARM_32BIT_STATE is not defined" +#endif + +#pragma GCC reset_options
2014-09-23 Christian Bruel <christian.br...@st.com> * config/arm/arm.c (add_attribute, arm_insert_attributes): New functions (TARGET_INSERT_ATTRIBUTES): Define. (thumb_flipper): New var. * config/arm/arm.opt (-mflip-thumb): New switch. diff -ruN '--exclude=.svn' gnu_trunk.devs5/gcc/gcc/config/arm/arm.c gnu_trunk.devs6/gcc/gcc/config/arm/arm.c --- gnu_trunk.devs5/gcc/gcc/config/arm/arm.c 2015-02-05 09:21:44.449543733 +0100 +++ gnu_trunk.devs6/gcc/gcc/config/arm/arm.c 2015-02-05 09:21:56.821563455 +0100 @@ -99,6 +99,7 @@ #include "tm-constrs.h" #include "rtl-iter.h" #include "sched-int.h" +#include "tree.h" /* Forward definitions of types. */ typedef struct minipool_node Mnode; @@ -232,6 +233,7 @@ static void arm_file_end (void); static void arm_file_start (void); +static void arm_insert_attributes (tree, tree *); static void arm_setup_incoming_varargs (cumulative_args_t, machine_mode, tree, int *, int); @@ -390,6 +392,9 @@ #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE arm_attribute_table +#undef TARGET_INSERT_ATTRIBUTES +#define TARGET_INSERT_ATTRIBUTES arm_insert_attributes + #undef TARGET_ASM_FILE_START #define TARGET_ASM_FILE_START arm_file_start #undef TARGET_ASM_FILE_END @@ -2717,6 +2722,10 @@ } } +/* True if -mflip-thumb should next add an attribute for the default + mode, false if it should next add an attribute for the opposite mode. */ +static GTY(()) bool thumb_flipper; + /* Options after initial target override. */ static GTY(()) tree init_optimize; @@ -3282,6 +3291,9 @@ options. */ target_option_default_node = target_option_current_node = build_target_option_node (&global_options); + + /* Init initial mode for testing. */ + thumb_flipper = TARGET_THUMB; } static void @@ -29624,6 +29636,52 @@ return build_target_option_node (opts); } +static void +add_attribute (const char * mode, tree *attributes) +{ + size_t len = strlen (mode); + tree value = build_string (len, mode); + + TREE_TYPE (value) = build_array_type (char_type_node, + build_index_type (size_int (len))); + + *attributes = tree_cons (get_identifier ("target"), + build_tree_list (NULL_TREE, value), + *attributes); +} + +/* For testing. Insert thumb or arm modes alternatively on functions. */ + +static void +arm_insert_attributes (tree fndecl, tree * attributes) +{ + const char *mode; + + if (! TARGET_FLIP_THUMB) + return; + + if (TREE_CODE (fndecl) != FUNCTION_DECL || DECL_EXTERNAL(fndecl) + || DECL_BUILT_IN (fndecl) || DECL_ARTIFICIAL (fndecl)) + return; + + /* Nested definitions must inherit mode. */ + if (current_function_decl) + { + mode = TARGET_THUMB ? "thumb" : "arm"; + add_attribute (mode, attributes); + return; + } + + /* If there is already a setting don't change it. */ + if (lookup_attribute ("target", *attributes) != NULL) + return; + + mode = thumb_flipper ? "thumb" : "arm"; + add_attribute (mode, attributes); + + thumb_flipper = !thumb_flipper; +} + /* Hook to validate attribute((target("string"))). */ static bool @@ -29635,13 +29693,15 @@ tree cur_tree, new_optimize; gcc_assert ((fndecl != NULL_TREE) && (args != NULL_TREE)); + tree old_optimize = build_optimization_node (&global_options); + /* 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; + func_optimize = old_optimize; /* Init func_options. */ memset (&func_options, 0, sizeof (func_options)); @@ -29659,14 +29719,17 @@ 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; + if (cur_tree == NULL_TREE) + ret = false; + else + { + DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = cur_tree; - DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize; + if (old_optimize != new_optimize) + DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize; + } return ret; } diff -ruN '--exclude=.svn' gnu_trunk.devs5/gcc/gcc/config/arm/arm.opt gnu_trunk.devs6/gcc/gcc/config/arm/arm.opt --- gnu_trunk.devs5/gcc/gcc/config/arm/arm.opt 2015-01-22 13:56:45.255251418 +0100 +++ gnu_trunk.devs6/gcc/gcc/config/arm/arm.opt 2015-01-21 18:18:16.166984018 +0100 @@ -122,6 +122,10 @@ EnumValue Enum(float_abi_type) String(hard) Value(ARM_FLOAT_ABI_HARD) +mflip-thumb +Target Report Var(TARGET_FLIP_THUMB) +Switch ARM/Thumb modes on alternating functions for compiler testing + mfp16-format= Target RejectNegative Joined Enum(arm_fp16_format_type) Var(arm_fp16_format) Init(ARM_FP16_FORMAT_NONE) Specify the __fp16 floating-point format