diff options
Diffstat (limited to 'gcc/config/arm')
-rw-r--r-- | gcc/config/arm/arm-builtins.c | 2 | ||||
-rw-r--r-- | gcc/config/arm/arm-c.c | 19 | ||||
-rw-r--r-- | gcc/config/arm/arm-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 65 | ||||
-rw-r--r-- | gcc/config/arm/arm_neon.h | 72 | ||||
-rw-r--r-- | gcc/config/arm/iterators.md | 6 | ||||
-rw-r--r-- | gcc/config/arm/neon.md | 64 | ||||
-rw-r--r-- | gcc/config/arm/thumb2.md | 24 |
8 files changed, 169 insertions, 84 deletions
diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c index db6b29d310d..90fb40fed24 100644 --- a/gcc/config/arm/arm-builtins.c +++ b/gcc/config/arm/arm-builtins.c @@ -2246,7 +2246,7 @@ arm_expand_neon_builtin (int fcode, tree exp, rtx target) neon_builtin_datum *d = &neon_builtin_data[fcode - ARM_BUILTIN_NEON_PATTERN_START]; enum insn_code icode = d->code; - builtin_arg args[SIMD_MAX_BUILTIN_ARGS]; + builtin_arg args[SIMD_MAX_BUILTIN_ARGS + 1]; int num_args = insn_data[d->code].n_operands; int is_void = 0; int k; diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c index 5810608873e..195905fa25b 100644 --- a/gcc/config/arm/arm-c.c +++ b/gcc/config/arm/arm-c.c @@ -221,9 +221,6 @@ arm_pragma_target_parse (tree args, tree pop_target) } } - 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); @@ -238,11 +235,8 @@ arm_pragma_target_parse (tree args, tree pop_target) compiler predefined macros. */ cpp_options *cpp_opts = cpp_get_options (parse_in); unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros; - unsigned char saved_warn_builtin_macro_redefined - = cpp_opts->warn_builtin_macro_redefined; cpp_opts->warn_unused_macros = 0; - cpp_opts->warn_builtin_macro_redefined = 0; /* Update macros. */ gcc_assert (cur_opt->x_target_flags == target_flags); @@ -261,8 +255,19 @@ arm_pragma_target_parse (tree args, tree pop_target) arm_cpu_builtins (parse_in); - cpp_opts->warn_builtin_macro_redefined = saved_warn_builtin_macro_redefined; cpp_opts->warn_unused_macros = saved_warn_unused_macros; + + /* Make sure that target_reinit is called for next function, since + TREE_TARGET_OPTION might change with the #pragma even if there is + no target attribute attached to the function. */ + arm_reset_previous_fndecl (); + + /* If going to the default mode, we restore the initial states. + if cur_tree is a new target, states will be saved/restored on a per + function basis in arm_set_current_function. */ + if (cur_tree == target_option_default_node) + save_restore_target_globals (cur_tree); + } return true; diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 28f226324a0..8261ed80290 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -332,6 +332,7 @@ extern bool arm_autoinc_modes_ok_p (machine_mode, enum arm_auto_incmodes); extern void arm_emit_eabi_attribute (const char *, int, int); extern void arm_reset_previous_fndecl (void); +extern void save_restore_target_globals (tree); /* Defined in gcc/common/config/arm-common.c. */ extern const char *arm_rewrite_selected_cpu (const char *name); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index f152afa4019..d8a2745f86b 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -3446,8 +3446,7 @@ arm_option_override (void) /* 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); + target_option_default_node = build_target_option_node (&global_options); /* Init initial mode for testing. */ thumb_flipper = TARGET_THUMB; @@ -12381,6 +12380,10 @@ neon_valid_immediate (rtx op, machine_mode mode, int inverse, if (!vfp3_const_double_rtx (el0) && el0 != CONST0_RTX (GET_MODE (el0))) return -1; + /* FP16 vectors cannot be represented. */ + if (GET_MODE_INNER (mode) == HFmode) + return -1; + r0 = CONST_DOUBLE_REAL_VALUE (el0); for (i = 1; i < n_elts; i++) @@ -29746,6 +29749,25 @@ arm_is_constant_pool_ref (rtx x) /* Remember the last target of arm_set_current_function. */ static GTY(()) tree arm_previous_fndecl; +/* Restore or save the TREE_TARGET_GLOBALS from or to NEW_TREE. */ + +void +save_restore_target_globals (tree new_tree) +{ + /* If we have a previous state, use it. */ + 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 + { + /* Call target_reinit and save the state for TARGET_GLOBALS. */ + TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts (); + } + + arm_option_params_internal (); +} + /* Invalidate arm_previous_fndecl. */ void arm_reset_previous_fndecl (void) @@ -29768,38 +29790,23 @@ arm_set_current_function (tree fndecl) tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); - arm_previous_fndecl = fndecl; + /* If current function has no attributes but previous one did, + use the default node." */ + if (! new_tree && old_tree) + new_tree = target_option_default_node; + + /* If nothing to do return. #pragma GCC reset or #pragma GCC pop to + the default have been handled by save_restore_target_globals from + arm_pragma_target_parse. */ if (old_tree == new_tree) return; - if (new_tree && new_tree != target_option_default_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 - TREE_TARGET_GLOBALS (new_tree) - = save_target_globals_default_opts (); - } - - else if (old_tree && old_tree != target_option_default_node) - { - new_tree = target_option_current_node; + arm_previous_fndecl = fndecl; - 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 (); - } + /* First set the target options. */ + cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree)); - arm_option_params_internal (); + save_restore_target_globals (new_tree); } /* Implement TARGET_OPTION_PRINT. */ diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h index b311b3a06fb..47816d52187 100644 --- a/gcc/config/arm/arm_neon.h +++ b/gcc/config/arm/arm_neon.h @@ -5302,14 +5302,26 @@ vget_lane_s32 (int32x2_t __a, const int __b) were marked always-inline so there were no call sites, the declaration would nonetheless raise an error. Hence, we must use a macro instead. */ -#define vget_lane_f16(__v, __idx) \ - __extension__ \ - ({ \ - float16x4_t __vec = (__v); \ - __builtin_arm_lane_check (4, __idx); \ - float16_t __res = __vec[__idx]; \ - __res; \ - }) + /* For big-endian, GCC's vector indices are reversed within each 64 + bits compared to the architectural lane indices used by Neon + intrinsics. */ +#ifdef __ARM_BIG_ENDIAN +#define __ARM_NUM_LANES(__v) (sizeof (__v) / sizeof (__v[0])) +#define __arm_lane(__vec, __idx) (__idx ^ (__ARM_NUM_LANES(__vec) - 1)) +#define __arm_laneq(__vec, __idx) (__idx ^ (__ARM_NUM_LANES(__vec)/2 - 1)) +#else +#define __arm_lane(__vec, __idx) __idx +#define __arm_laneq(__vec, __idx) __idx +#endif + +#define vget_lane_f16(__v, __idx) \ + __extension__ \ + ({ \ + float16x4_t __vec = (__v); \ + __builtin_arm_lane_check (4, __idx); \ + float16_t __res = __vec[__arm_lane(__vec, __idx)]; \ + __res; \ + }) #endif __extension__ static __inline float32_t __attribute__ ((__always_inline__)) @@ -5379,14 +5391,14 @@ vgetq_lane_s32 (int32x4_t __a, const int __b) } #if defined (__ARM_FP16_FORMAT_IEEE) || defined (__ARM_FP16_FORMAT_ALTERNATIVE) -#define vgetq_lane_f16(__v, __idx) \ - __extension__ \ - ({ \ - float16x8_t __vec = (__v); \ - __builtin_arm_lane_check (8, __idx); \ - float16_t __res = __vec[__idx]; \ - __res; \ - }) +#define vgetq_lane_f16(__v, __idx) \ + __extension__ \ + ({ \ + float16x8_t __vec = (__v); \ + __builtin_arm_lane_check (8, __idx); \ + float16_t __res = __vec[__arm_laneq(__vec, __idx)]; \ + __res; \ + }) #endif __extension__ static __inline float32_t __attribute__ ((__always_inline__)) @@ -5458,13 +5470,13 @@ vset_lane_s32 (int32_t __a, int32x2_t __b, const int __c) #if defined (__ARM_FP16_FORMAT_IEEE) || defined (__ARM_FP16_FORMAT_ALTERNATIVE) #define vset_lane_f16(__e, __v, __idx) \ __extension__ \ - ({ \ - float16_t __elem = (__e); \ - float16x4_t __vec = (__v); \ - __builtin_arm_lane_check (4, __idx); \ - __vec[__idx] = __elem; \ - __vec; \ - }) + ({ \ + float16_t __elem = (__e); \ + float16x4_t __vec = (__v); \ + __builtin_arm_lane_check (4, __idx); \ + __vec[__arm_lane (__vec, __idx)] = __elem; \ + __vec; \ + }) #endif __extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) @@ -5536,13 +5548,13 @@ vsetq_lane_s32 (int32_t __a, int32x4_t __b, const int __c) #if defined (__ARM_FP16_FORMAT_IEEE) || defined (__ARM_FP16_FORMAT_ALTERNATIVE) #define vsetq_lane_f16(__e, __v, __idx) \ __extension__ \ - ({ \ - float16_t __elem = (__e); \ - float16x8_t __vec = (__v); \ - __builtin_arm_lane_check (8, __idx); \ - __vec[__idx] = __elem; \ - __vec; \ - }) + ({ \ + float16_t __elem = (__e); \ + float16x8_t __vec = (__v); \ + __builtin_arm_lane_check (8, __idx); \ + __vec[__arm_laneq (__vec, __idx)] = __elem; \ + __vec; \ + }) #endif __extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index 974cf51cb60..aba1023cdd0 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -99,7 +99,7 @@ (define_mode_iterator VQI [V16QI V8HI V4SI]) ;; Quad-width vector modes, with TImode added, for moves. -(define_mode_iterator VQXMOV [V16QI V8HI V4SI V4SF V2DI TI]) +(define_mode_iterator VQXMOV [V16QI V8HI V8HF V4SI V4SF V2DI TI]) ;; Opaque structure types wider than TImode. (define_mode_iterator VSTRUCT [EI OI CI XI]) @@ -114,7 +114,7 @@ (define_mode_iterator VN [V8HI V4SI V2DI]) ;; All supported vector modes (except singleton DImode). -(define_mode_iterator VDQ [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF V2DI]) +(define_mode_iterator VDQ [V8QI V16QI V4HI V8HI V2SI V4SI V4HF V8HF V2SF V4SF V2DI]) ;; All supported vector modes (except those with 64-bit integer elements). (define_mode_iterator VDQW [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF]) @@ -428,6 +428,7 @@ ;; Register width from element mode (define_mode_attr V_reg [(V8QI "P") (V16QI "q") (V4HI "P") (V8HI "q") + (V4HF "P") (V8HF "q") (V2SI "P") (V4SI "q") (V2SF "P") (V4SF "q") (DI "P") (V2DI "q") @@ -576,6 +577,7 @@ (define_mode_attr Is_float_mode [(V8QI "false") (V16QI "false") (V4HI "false") (V8HI "false") (V2SI "false") (V4SI "false") + (V4HF "true") (V8HF "true") (V2SF "true") (V4SF "true") (DI "false") (V2DI "false")]) diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md index aff5023f4fd..55b61eb362c 100644 --- a/gcc/config/arm/neon.md +++ b/gcc/config/arm/neon.md @@ -137,6 +137,36 @@ } }) +(define_expand "movv4hf" + [(set (match_operand:V4HF 0 "s_register_operand") + (match_operand:V4HF 1 "s_register_operand"))] + "TARGET_NEON && TARGET_FP16" +{ + /* We need to use force_reg to avoid CANNOT_CHANGE_MODE_CLASS + causing an ICE on big-endian because it cannot extract subregs in + this case. */ + if (can_create_pseudo_p ()) + { + if (!REG_P (operands[0])) + operands[1] = force_reg (V4HFmode, operands[1]); + } +}) + +(define_expand "movv8hf" + [(set (match_operand:V8HF 0 "") + (match_operand:V8HF 1 ""))] + "TARGET_NEON && TARGET_FP16" +{ + /* We need to use force_reg to avoid CANNOT_CHANGE_MODE_CLASS + causing an ICE on big-endian because it cannot extract subregs in + this case. */ + if (can_create_pseudo_p ()) + { + if (!REG_P (operands[0])) + operands[1] = force_reg (V8HFmode, operands[1]); + } +}) + (define_insn "*neon_mov<mode>" [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "=w,Ut,w") (match_operand:VSTRUCT 1 "general_operand" " w,w, Ut"))] @@ -299,11 +329,11 @@ [(set_attr "type" "neon_load1_1reg<q>")]) (define_insn "vec_set<mode>_internal" - [(set (match_operand:VD 0 "s_register_operand" "=w,w") - (vec_merge:VD - (vec_duplicate:VD + [(set (match_operand:VD_LANE 0 "s_register_operand" "=w,w") + (vec_merge:VD_LANE + (vec_duplicate:VD_LANE (match_operand:<V_elem> 1 "nonimmediate_operand" "Um,r")) - (match_operand:VD 3 "s_register_operand" "0,0") + (match_operand:VD_LANE 3 "s_register_operand" "0,0") (match_operand:SI 2 "immediate_operand" "i,i")))] "TARGET_NEON" { @@ -385,7 +415,7 @@ (define_insn "vec_extract<mode>" [(set (match_operand:<V_elem> 0 "nonimmediate_operand" "=Um,r") (vec_select:<V_elem> - (match_operand:VD 1 "s_register_operand" "w,w") + (match_operand:VD_LANE 1 "s_register_operand" "w,w") (parallel [(match_operand:SI 2 "immediate_operand" "i,i")])))] "TARGET_NEON" { @@ -2829,6 +2859,22 @@ if (BYTES_BIG_ENDIAN) [(set_attr "type" "neon_from_gp<q>")] ) +(define_insn "neon_vdup_nv4hf" + [(set (match_operand:V4HF 0 "s_register_operand" "=w") + (vec_duplicate:V4HF (match_operand:HF 1 "s_register_operand" "r")))] + "TARGET_NEON" + "vdup.16\t%P0, %1" + [(set_attr "type" "neon_from_gp")] +) + +(define_insn "neon_vdup_nv8hf" + [(set (match_operand:V8HF 0 "s_register_operand" "=w") + (vec_duplicate:V8HF (match_operand:HF 1 "s_register_operand" "r")))] + "TARGET_NEON" + "vdup.16\t%q0, %1" + [(set_attr "type" "neon_from_gp_q")] +) + (define_insn "neon_vdup_n<mode>" [(set (match_operand:V32 0 "s_register_operand" "=w,w") (vec_duplicate:V32 (match_operand:<V_elem> 1 "s_register_operand" "r,t")))] @@ -4361,8 +4407,8 @@ if (BYTES_BIG_ENDIAN) ) (define_insn "neon_vld1_dup<mode>" - [(set (match_operand:VD 0 "s_register_operand" "=w") - (vec_duplicate:VD (match_operand:<V_elem> 1 "neon_struct_operand" "Um")))] + [(set (match_operand:VD_LANE 0 "s_register_operand" "=w") + (vec_duplicate:VD_LANE (match_operand:<V_elem> 1 "neon_struct_operand" "Um")))] "TARGET_NEON" "vld1.<V_sz_elem>\t{%P0[]}, %A1" [(set_attr "type" "neon_load1_all_lanes<q>")] @@ -4378,8 +4424,8 @@ if (BYTES_BIG_ENDIAN) ) (define_insn "neon_vld1_dup<mode>" - [(set (match_operand:VQ 0 "s_register_operand" "=w") - (vec_duplicate:VQ (match_operand:<V_elem> 1 "neon_struct_operand" "Um")))] + [(set (match_operand:VQ2 0 "s_register_operand" "=w") + (vec_duplicate:VQ2 (match_operand:<V_elem> 1 "neon_struct_operand" "Um")))] "TARGET_NEON" { return "vld1.<V_sz_elem>\t{%e0[], %f0[]}, %A1"; diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md index 3e762018e4d..39a3d806918 100644 --- a/gcc/config/arm/thumb2.md +++ b/gcc/config/arm/thumb2.md @@ -663,15 +663,27 @@ (set_attr "type" "multiple")] ) -(define_insn "*thumb2_ior_scc_strict_it" - [(set (match_operand:SI 0 "s_register_operand" "=l,l") +(define_insn_and_split "*thumb2_ior_scc_strict_it" + [(set (match_operand:SI 0 "s_register_operand" "=&r") (ior:SI (match_operator:SI 2 "arm_comparison_operator" [(match_operand 3 "cc_register" "") (const_int 0)]) - (match_operand:SI 1 "s_register_operand" "0,?l")))] + (match_operand:SI 1 "s_register_operand" "r")))] "TARGET_THUMB2 && arm_restrict_it" - "@ - it\\t%d2\;mov%d2\\t%0, #1\;it\\t%d2\;orr%d2\\t%0, %1 - mov\\t%0, #1\;orr\\t%0, %1\;it\\t%D2\;mov%D2\\t%0, %1" + "#" ; orr\\t%0, %1, #1\;it\\t%D2\;mov%D2\\t%0, %1 + "&& reload_completed" + [(set (match_dup 0) (ior:SI (match_dup 1) (const_int 1))) + (cond_exec (match_dup 4) + (set (match_dup 0) (match_dup 1)))] + { + machine_mode mode = GET_MODE (operands[3]); + rtx_code rc = GET_CODE (operands[2]); + + if (mode == CCFPmode || mode == CCFPEmode) + rc = reverse_condition_maybe_unordered (rc); + else + rc = reverse_condition (rc); + operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx); + } [(set_attr "conds" "use") (set_attr "length" "8") (set_attr "type" "multiple")] |