From 06b906021422980e8b9b7aea0509d24e94777a19 Mon Sep 17 00:00:00 2001 From: Christian Bruel Date: Tue, 13 May 2014 10:50:51 +0200 Subject: [PATCH] target.def (mode_switching): New hook vector. 2014-05-13 Christian Bruel * target.def (mode_switching): New hook vector. (mode_emit, mode_needed, mode_after, mode_entry): New hooks. (mode_exit, modepriority_to_mode): Likewise. * mode-switching.c (MODE_NEEDED, MODE_AFTER, MODE_ENTRY): Hookify. (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise. (default_priority_to_mode): Define. * targhooks.h (default_priority_to_mode): Declare. * target.h: Include tm.h and hard-reg-set.h. * doc/tm.texi.in (EMIT_MODE_SET, MODE_NEEDED, MODE_AFTER, MODE_ENTRY) (MODE_EXIT, MODE_PRIORITY_TO_MODE): Delete and hookify. * doc/tm.texi Regenerate. * config/sh/sh.h (MODE_NEEDED, MODE_AFTER, MODE_ENTRY): Delete (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise. * config/sh/sh.c (sh_emit_mode_set, sh_mode_priority): Hookify. (sh_mode_needed, sh_mode_after, sh_mode_entry, sh_mode_exit): Likewise. * config/i386/i386.h (MODE_NEEDED, MODE_AFTER, MODE_ENTRY): Delete (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise. * config/i386/i386-protos.h (ix86_mode_needed, ix86_mode_after) (ix86_mode_entrym, ix86_emit_mode_set): Remove external declaration. * config/i386/i386.c (ix86_mode_needed, ix86_mode_after, ix86_mode_exit, (ix86_mode_entry, ix86_mode_priority, ix86_emit_mode_set): Hookify. * config/epiphany/epiphany.h (MODE_NEEDED, MODE_AFTER, MODE_ENTRY): Delete (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise. * config/sh/sh.h (MODE_NEEDED, MODE_AFTER, MODE_ENTRY): Delete (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise. * config/sh/sh.c (sh4_emit_mode_set, sh4_mode_needed): Hookify. (sh4_mode_after, sh4_mode_entry, sh4_mode_exit): Likewise. * config/epiphany/epiphany-protos.h (epiphany_mode_needed) (emit_set_fp_mode, epiphany_mode_entry_exit, epiphany_mode_after) (epiphany_mode_priority_to_mode): Remove declaration. * config/epiphany/epiphany.c (emit_set_fp_mode): Hookify. (epiphany_mode_needed, epiphany_mode_priority_to_mode): Likewise. (epiphany_mode_entry, epiphany_mode_exit, epiphany_mode_after): Likewise. (epiphany_mode_priority_to_mode): Change priority type. Hookify. (epiphany_mode_needed, epiphany_mode_entry_exit): Hookify. (epiphany_mode_after, epiphany_mode_entry, emit_set_fp_mode): Hookify. From-SVN: r210354 --- gcc/ChangeLog | 41 ++++++++++ gcc/config/epiphany/epiphany-protos.h | 2 - gcc/config/epiphany/epiphany.c | 32 +++++++- gcc/config/epiphany/epiphany.h | 13 --- gcc/config/epiphany/mode-switch-use.c | 2 +- gcc/config/i386/i386-protos.h | 9 --- gcc/config/i386/i386.c | 36 ++++++++- gcc/config/i386/i386.h | 37 --------- gcc/config/sh/sh.c | 66 +++++++++++++++ gcc/config/sh/sh.h | 23 ------ gcc/doc/tm.texi | 64 +++++---------- gcc/doc/tm.texi.in | 52 +++--------- gcc/mode-switching.c | 112 +++++++++++++------------- gcc/target.def | 38 +++++++++ gcc/target.h | 2 + 15 files changed, 296 insertions(+), 233 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a829af0f9af..456f74061f3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,44 @@ +2014-05-13 Christian Bruel + + * target.def (mode_switching): New hook vector. + (mode_emit, mode_needed, mode_after, mode_entry): New hooks. + (mode_exit, modepriority_to_mode): Likewise. + * mode-switching.c (MODE_NEEDED, MODE_AFTER, MODE_ENTRY): Hookify. + (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise. + (default_priority_to_mode): Define. + * targhooks.h (default_priority_to_mode): Declare. + * target.h: Include tm.h and hard-reg-set.h. + * doc/tm.texi.in (EMIT_MODE_SET, MODE_NEEDED, MODE_AFTER, MODE_ENTRY) + (MODE_EXIT, MODE_PRIORITY_TO_MODE): Delete and hookify. + * doc/tm.texi Regenerate. + * config/sh/sh.h (MODE_NEEDED, MODE_AFTER, MODE_ENTRY): Delete + (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise. + * config/sh/sh.c (sh_emit_mode_set, sh_mode_priority): Hookify. + (sh_mode_needed, sh_mode_after, sh_mode_entry, sh_mode_exit): Likewise. + * config/i386/i386.h (MODE_NEEDED, MODE_AFTER, MODE_ENTRY): Delete + (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise. + * config/i386/i386-protos.h (ix86_mode_needed, ix86_mode_after) + (ix86_mode_entrym, ix86_emit_mode_set): Remove external declaration. + * config/i386/i386.c (ix86_mode_needed, ix86_mode_after, ix86_mode_exit, + (ix86_mode_entry, ix86_mode_priority, ix86_emit_mode_set): Hookify. + * config/epiphany/epiphany.h (MODE_NEEDED, MODE_AFTER, MODE_ENTRY): + Delete + (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise. + * config/sh/sh.h (MODE_NEEDED, MODE_AFTER, MODE_ENTRY): Delete + (MODE_EXIT, MODE_PRIORITY_TO_MODE, EMIT_MODE_SET): Likewise. + * config/sh/sh.c (sh4_emit_mode_set, sh4_mode_needed): Hookify. + (sh4_mode_after, sh4_mode_entry, sh4_mode_exit): Likewise. + * config/epiphany/epiphany-protos.h (epiphany_mode_needed) + (emit_set_fp_mode, epiphany_mode_entry_exit, epiphany_mode_after) + (epiphany_mode_priority_to_mode): Remove declaration. + * config/epiphany/epiphany.c (emit_set_fp_mode): Hookify. + (epiphany_mode_needed, epiphany_mode_priority_to_mode): Likewise. + (epiphany_mode_entry, epiphany_mode_exit, epiphany_mode_after): + Likewise. + (epiphany_mode_priority_to_mode): Change priority type. Hookify. + (epiphany_mode_needed, epiphany_mode_entry_exit): Hookify. + (epiphany_mode_after, epiphany_mode_entry, emit_set_fp_mode): Hookify. + 2014-05-13 Jakub Jelinek PR target/61060 diff --git a/gcc/config/epiphany/epiphany-protos.h b/gcc/config/epiphany/epiphany-protos.h index 9121e0c3c97..bfa48021443 100644 --- a/gcc/config/epiphany/epiphany-protos.h +++ b/gcc/config/epiphany/epiphany-protos.h @@ -45,9 +45,7 @@ extern void emit_set_fp_mode (int entity, int mode, HARD_REG_SET regs_live); extern void epiphany_insert_mode_switch_use (rtx insn, int, int); extern void epiphany_expand_set_fp_mode (rtx *operands); extern int epiphany_mode_needed (int entity, rtx insn); -extern int epiphany_mode_entry_exit (int entity, bool); extern int epiphany_mode_after (int entity, int last_mode, rtx insn); -extern int epiphany_mode_priority_to_mode (int entity, unsigned priority); extern bool epiphany_epilogue_uses (int regno); extern bool epiphany_optimize_mode_switching (int entity); extern bool epiphany_is_interrupt_p (tree); diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c index ebe6f05302d..7ee5d0a8019 100644 --- a/gcc/config/epiphany/epiphany.c +++ b/gcc/config/epiphany/epiphany.c @@ -152,6 +152,20 @@ static rtx frame_insn (rtx); /* We further restrict the minimum to be a multiple of eight. */ #define TARGET_MIN_ANCHOR_OFFSET (optimize_size ? 0 : -2040) +/* Mode switching hooks. */ + +#define TARGET_MODE_EMIT emit_set_fp_mode + +#define TARGET_MODE_NEEDED epiphany_mode_needed + +#define TARGET_MODE_PRIORITY epiphany_mode_priority + +#define TARGET_MODE_ENTRY epiphany_mode_entry + +#define TARGET_MODE_EXIT epiphany_mode_exit + +#define TARGET_MODE_AFTER epiphany_mode_after + #include "target-def.h" #undef TARGET_ASM_ALIGNED_HI_OP @@ -2319,8 +2333,8 @@ epiphany_optimize_mode_switching (int entity) gcc_unreachable (); } -int -epiphany_mode_priority_to_mode (int entity, unsigned priority) +static int +epiphany_mode_priority (int entity, int priority) { if (entity == EPIPHANY_MSW_ENTITY_AND || entity == EPIPHANY_MSW_ENTITY_OR || entity== EPIPHANY_MSW_ENTITY_CONFIG) @@ -2428,7 +2442,7 @@ epiphany_mode_needed (int entity, rtx insn) } } -int +static int epiphany_mode_entry_exit (int entity, bool exit) { int normal_mode = epiphany_normal_fp_mode ; @@ -2515,6 +2529,18 @@ epiphany_mode_after (int entity, int last_mode, rtx insn) return last_mode; } +static int +epiphany_mode_entry (int entity) +{ + return epiphany_mode_entry_exit (entity, false); +} + +static int +epiphany_mode_exit (int entity) +{ + return epiphany_mode_entry_exit (entity, true); +} + void emit_set_fp_mode (int entity, int mode, HARD_REG_SET regs_live ATTRIBUTE_UNUSED) { diff --git a/gcc/config/epiphany/epiphany.h b/gcc/config/epiphany/epiphany.h index 1ca92e07b9e..f64652e4895 100644 --- a/gcc/config/epiphany/epiphany.h +++ b/gcc/config/epiphany/epiphany.h @@ -899,19 +899,6 @@ enum epiphany_function_type { 2, 2, 2, \ FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE, FP_MODE_NONE } -#define MODE_NEEDED(ENTITY, INSN) epiphany_mode_needed((ENTITY), (INSN)) - -#define MODE_PRIORITY_TO_MODE(ENTITY, N) \ - (epiphany_mode_priority_to_mode ((ENTITY), (N))) - -#define EMIT_MODE_SET(ENTITY, MODE, HARD_REGS_LIVE) \ - emit_set_fp_mode ((ENTITY), (MODE), (HARD_REGS_LIVE)) - -#define MODE_ENTRY(ENTITY) (epiphany_mode_entry_exit ((ENTITY), false)) -#define MODE_EXIT(ENTITY) (epiphany_mode_entry_exit ((ENTITY), true)) -#define MODE_AFTER(ENTITY, LAST_MODE, INSN) \ - (epiphany_mode_after ((ENTITY), (LAST_MODE), (INSN))) - #define TARGET_INSERT_MODE_SWITCH_USE epiphany_insert_mode_switch_use /* Mode switching entities. */ diff --git a/gcc/config/epiphany/mode-switch-use.c b/gcc/config/epiphany/mode-switch-use.c index 9617041a310..cc80d103c55 100644 --- a/gcc/config/epiphany/mode-switch-use.c +++ b/gcc/config/epiphany/mode-switch-use.c @@ -58,7 +58,7 @@ insert_uses (void) { if (!INSN_P (insn)) continue; - mode = MODE_NEEDED (e, insn); + mode = epiphany_mode_needed (e, insn); if (mode == no_mode) continue; if (target_insert_mode_switch_use) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 6e329788088..39462bd6211 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -166,17 +166,8 @@ extern bool ix86_secondary_memory_needed (enum reg_class, enum reg_class, extern bool ix86_cannot_change_mode_class (enum machine_mode, enum machine_mode, enum reg_class); -extern int ix86_mode_needed (int, rtx); -extern int ix86_mode_after (int, int, rtx); -extern int ix86_mode_entry (int); -extern int ix86_mode_exit (int); - extern bool ix86_libc_has_function (enum function_class fn_class); -#ifdef HARD_CONST -extern void ix86_emit_mode_set (int, int, HARD_REG_SET); -#endif - extern void x86_order_regs_for_local_alloc (void); extern void x86_function_profiler (FILE *, int); extern void x86_emit_floatuns (rtx [2]); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 7a7a3fcc5ea..99f0657a9cf 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -16148,7 +16148,7 @@ ix86_i387_mode_needed (int entity, rtx insn) /* Return mode that entity must be switched into prior to the execution of insn. */ -int +static int ix86_mode_needed (int entity, rtx insn) { switch (entity) @@ -16246,7 +16246,7 @@ ix86_avx_u128_mode_entry (void) /* Return a mode that ENTITY is assumed to be switched to at function entry. */ -int +static int ix86_mode_entry (int entity) { switch (entity) @@ -16279,7 +16279,7 @@ ix86_avx_u128_mode_exit (void) /* Return a mode that ENTITY is assumed to be switched to at function exit. */ -int +static int ix86_mode_exit (int entity) { switch (entity) @@ -16296,6 +16296,12 @@ ix86_mode_exit (int entity) } } +static int +ix86_mode_priority (int entity ATTRIBUTE_UNUSED, int n) +{ + return n; +} + /* Output code to initialize control word copies used by trunc?f?i and rounding patterns. CURRENT_MODE is set to current control word, while NEW_MODE is set to new control word. */ @@ -16411,7 +16417,11 @@ ix86_avx_emit_vzeroupper (HARD_REG_SET regs_live) /* Generate one or more insns to set ENTITY to MODE. */ -void +/* Generate one or more insns to set ENTITY to MODE. HARD_REG_LIVE + is the set of hard registers live at the point where the insn(s) + are to be inserted. */ + +static void ix86_emit_mode_set (int entity, int mode, HARD_REG_SET regs_live) { switch (entity) @@ -47157,6 +47167,24 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) #define TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P \ ix86_float_exceptions_rounding_supported_p +#undef TARGET_MODE_EMIT +#define TARGET_MODE_EMIT ix86_emit_mode_set + +#undef TARGET_MODE_NEEDED +#define TARGET_MODE_NEEDED ix86_mode_needed + +#undef TARGET_MODE_AFTER +#define TARGET_MODE_AFTER ix86_mode_after + +#undef TARGET_MODE_ENTRY +#define TARGET_MODE_ENTRY ix86_mode_entry + +#undef TARGET_MODE_EXIT +#define TARGET_MODE_EXIT ix86_mode_exit + +#undef TARGET_MODE_PRIORITY +#define TARGET_MODE_PRIORITY ix86_mode_priority + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-i386.h" diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 1a884d86c35..6e2ac156bdb 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2312,43 +2312,6 @@ enum avx_u128_state #define NUM_MODES_FOR_MODE_SWITCHING \ { AVX_U128_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY } -/* ENTITY is an integer specifying a mode-switched entity. If - `OPTIMIZE_MODE_SWITCHING' is defined, you must define this macro to - return an integer value not larger than the corresponding element - in `NUM_MODES_FOR_MODE_SWITCHING', to denote the mode that ENTITY - must be switched into prior to the execution of INSN. */ - -#define MODE_NEEDED(ENTITY, I) ix86_mode_needed ((ENTITY), (I)) - -/* If this macro is defined, it is evaluated for every INSN during - mode switching. It determines the mode that an insn results in (if - different from the incoming mode). */ - -#define MODE_AFTER(ENTITY, MODE, I) ix86_mode_after ((ENTITY), (MODE), (I)) - -/* If this macro is defined, it is evaluated for every ENTITY that - needs mode switching. It should evaluate to an integer, which is - a mode that ENTITY is assumed to be switched to at function entry. */ - -#define MODE_ENTRY(ENTITY) ix86_mode_entry (ENTITY) - -/* If this macro is defined, it is evaluated for every ENTITY that - needs mode switching. It should evaluate to an integer, which is - a mode that ENTITY is assumed to be switched to at function exit. */ - -#define MODE_EXIT(ENTITY) ix86_mode_exit (ENTITY) - -/* This macro specifies the order in which modes for ENTITY are - processed. 0 is the highest priority. */ - -#define MODE_PRIORITY_TO_MODE(ENTITY, N) (N) - -/* Generate one or more insns to set ENTITY to MODE. HARD_REG_LIVE - is the set of hard registers live at the point where the insn(s) - are to be inserted. */ - -#define EMIT_MODE_SET(ENTITY, MODE, HARD_REGS_LIVE) \ - ix86_emit_mode_set ((ENTITY), (MODE), (HARD_REGS_LIVE)) /* Avoid renaming of stack registers, as doing so in combination with scheduling just increases amount of live registers at time and in diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 26a5d79f137..31ea83d1c31 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -202,6 +202,13 @@ static void push_regs (HARD_REG_SET *, int); static int calc_live_regs (HARD_REG_SET *); static HOST_WIDE_INT rounded_frame_size (int); static bool sh_frame_pointer_required (void); +static void sh_emit_mode_set (int, int, HARD_REG_SET); +static int sh_mode_needed (int, rtx); +static int sh_mode_after (int, int, rtx); +static int sh_mode_entry (int); +static int sh_mode_exit (int); +static int sh_mode_priority (int entity, int n); + static rtx mark_constant_pool_use (rtx); static tree sh_handle_interrupt_handler_attribute (tree *, tree, tree, int, bool *); @@ -564,6 +571,24 @@ static const struct attribute_spec sh_attribute_table[] = #undef TARGET_FRAME_POINTER_REQUIRED #define TARGET_FRAME_POINTER_REQUIRED sh_frame_pointer_required +#undef TARGET_MODE_EMIT +#define TARGET_MODE_EMIT sh_emit_mode_set + +#undef TARGET_MODE_NEEDED +#define TARGET_MODE_NEEDED sh_mode_needed + +#undef TARGET_MODE_AFTER +#define TARGET_MODE_AFTER sh_mode_after + +#undef TARGET_MODE_ENTRY +#define TARGET_MODE_ENTRY sh_mode_entry + +#undef TARGET_MODE_EXIT +#define TARGET_MODE_EXIT sh_mode_exit + +#undef TARGET_MODE_PRIORITY +#define TARGET_MODE_PRIORITY sh_mode_priority + /* Return regmode weight for insn. */ #define INSN_REGMODE_WEIGHT(INSN, MODE)\ regmode_weight[((MODE) == SImode) ? 0 : 1][INSN_UID (INSN)] @@ -13549,4 +13574,45 @@ sh_try_omit_signzero_extend (rtx extended_op, rtx insn) return NULL_RTX; } +static void +sh_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode, + HARD_REG_SET regs_live) +{ + fpscr_set_from_mem (mode, regs_live); +} + +static int +sh_mode_needed (int entity ATTRIBUTE_UNUSED, rtx insn) +{ + return recog_memoized (insn) >= 0 ? get_attr_fp_mode (insn) : FP_MODE_NONE; +} + +static int +sh_mode_after (int entity ATTRIBUTE_UNUSED, int mode, rtx insn) +{ + if (TARGET_HITACHI && recog_memoized (insn) >= 0 && + get_attr_fp_set (insn) != FP_SET_NONE) + return (int) get_attr_fp_set (insn); + else + return mode; +} + +static int +sh_mode_entry (int entity ATTRIBUTE_UNUSED) +{ + return NORMAL_MODE (entity); +} + +static int +sh_mode_exit (int entity ATTRIBUTE_UNUSED) +{ + return sh_cfun_attr_renesas_p () ? FP_MODE_NONE : NORMAL_MODE (entity); +} + +static int +sh_mode_priority (int entity ATTRIBUTE_UNUSED, int n) +{ + return ((TARGET_FPU_SINGLE != 0) ^ (n) ? FP_MODE_SINGLE : FP_MODE_DOUBLE); +} + #include "gt-sh.h" diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 00ee0edffda..e42b8d31b68 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -2218,32 +2218,9 @@ extern int current_function_interrupt; ? (TARGET_FMOVD ? FP_MODE_DOUBLE : FP_MODE_NONE) \ : ACTUAL_NORMAL_MODE (ENTITY)) -#define MODE_ENTRY(ENTITY) NORMAL_MODE (ENTITY) - -#define MODE_EXIT(ENTITY) \ - (sh_cfun_attr_renesas_p () ? FP_MODE_NONE : NORMAL_MODE (ENTITY)) - #define EPILOGUE_USES(REGNO) ((TARGET_SH2E || TARGET_SH4) \ && (REGNO) == FPSCR_REG) -#define MODE_NEEDED(ENTITY, INSN) \ - (recog_memoized (INSN) >= 0 \ - ? get_attr_fp_mode (INSN) \ - : FP_MODE_NONE) - -#define MODE_AFTER(ENTITY, MODE, INSN) \ - (TARGET_HITACHI \ - && recog_memoized (INSN) >= 0 \ - && get_attr_fp_set (INSN) != FP_SET_NONE \ - ? (int) get_attr_fp_set (INSN) \ - : (MODE)) - -#define MODE_PRIORITY_TO_MODE(ENTITY, N) \ - ((TARGET_FPU_SINGLE != 0) ^ (N) ? FP_MODE_SINGLE : FP_MODE_DOUBLE) - -#define EMIT_MODE_SET(ENTITY, MODE, HARD_REGS_LIVE) \ - fpscr_set_from_mem ((MODE), (HARD_REGS_LIVE)) - #define MD_CAN_REDIRECT_BRANCH(INSN, SEQ) \ sh_can_redirect_branch ((INSN), (SEQ)) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 92312f519f1..1a26bcd0448 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -9725,9 +9725,9 @@ You can have multiple entities that are mode-switched, and select at run time which entities actually need it. @code{OPTIMIZE_MODE_SWITCHING} should return nonzero for any @var{entity} that needs mode-switching. If you define this macro, you also have to define -@code{NUM_MODES_FOR_MODE_SWITCHING}, @code{MODE_NEEDED}, -@code{MODE_PRIORITY_TO_MODE} and @code{EMIT_MODE_SET}. -@code{MODE_AFTER}, @code{MODE_ENTRY}, and @code{MODE_EXIT} +@code{NUM_MODES_FOR_MODE_SWITCHING}, @code{TARGET_MODE_NEEDED}, +@code{TARGET_MODE_PRIORITY} and @code{TARGET_MODE_EMIT}. +@code{TARGET_MODE_AFTER}, @code{TARGET_MODE_ENTRY}, and @code{TARGET_MODE_EXIT} are optional. @end defmac @@ -9744,51 +9744,29 @@ represented as numbers 0 @dots{} N @minus{} 1. N is used to specify that no mod switch is needed / supplied. @end defmac -@defmac MODE_NEEDED (@var{entity}, @var{insn}) -@var{entity} is an integer specifying a mode-switched entity. If -@code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro to -return an integer value not larger than the corresponding element in -@code{NUM_MODES_FOR_MODE_SWITCHING}, to denote the mode that @var{entity} must -be switched into prior to the execution of @var{insn}. -@end defmac +@deftypefn {Target Hook} void TARGET_MODE_EMIT (int @var{entity}, int @var{mode}, HARD_REG_SET @var{regs_live}) +Generate one or more insns to set @var{entity} to @var{mode}. @var{hard_reg_live} is the set of hard registers live at the point where the insn(s) are to be inserted. Sets of a lower numbered entity will be emitted before sets of a higher numbered entity to a mode of the same or lower priority. +@end deftypefn -@defmac MODE_AFTER (@var{entity}, @var{mode}, @var{insn}) -@var{entity} is an integer specifying a mode-switched entity. If -this macro is defined, it is evaluated for every @var{insn} during -mode switching. It determines the mode that an insn results in (if -different from the incoming mode). -@end defmac +@deftypefn {Target Hook} int TARGET_MODE_NEEDED (int @var{entity}, rtx @var{insn}) +@var{entity} is an integer specifying a mode-switched entity. If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro to return an integer value not larger than the corresponding element in @code{NUM_MODES_FOR_MODE_SWITCHING}, to denote the mode that @var{entity} must be switched into prior to the execution of @var{insn}. +@end deftypefn -@defmac MODE_ENTRY (@var{entity}) -If this macro is defined, it is evaluated for every @var{entity} that needs -mode switching. It should evaluate to an integer, which is a mode that -@var{entity} is assumed to be switched to at function entry. If @code{MODE_ENTRY} -is defined then @code{MODE_EXIT} must be defined. -@end defmac +@deftypefn {Target Hook} int TARGET_MODE_AFTER (int @var{entity}, int @var{mode}, rtx @var{insn}) +@var{entity} is an integer specifying a mode-switched entity. If this macro is defined, it is evaluated for every @var{insn} during mode switching. It determines the mode that an insn results in (if different from the incoming mode). +@end deftypefn -@defmac MODE_EXIT (@var{entity}) -If this macro is defined, it is evaluated for every @var{entity} that needs -mode switching. It should evaluate to an integer, which is a mode that -@var{entity} is assumed to be switched to at function exit. If @code{MODE_EXIT} -is defined then @code{MODE_ENTRY} must be defined. -@end defmac +@deftypefn {Target Hook} int TARGET_MODE_ENTRY (int @var{entity}) +If this macro is defined, it is evaluated for every @var{entity} that needs mode switching. It should evaluate to an integer, which is a mode that @var{entity} is assumed to be switched to at function entry. If @code{TARGET_MODE_ENTRY} is defined then @code{TARGET_MODE_EXIT} must be defined. +@end deftypefn -@defmac MODE_PRIORITY_TO_MODE (@var{entity}, @var{n}) -This macro specifies the order in which modes for @var{entity} are processed. -0 is the highest priority, @code{NUM_MODES_FOR_MODE_SWITCHING[@var{entity}] - 1} the -lowest. The value of the macro should be an integer designating a mode -for @var{entity}. For any fixed @var{entity}, @code{mode_priority_to_mode} -(@var{entity}, @var{n}) shall be a bijection in 0 @dots{} -@code{num_modes_for_mode_switching[@var{entity}] - 1}. -@end defmac +@deftypefn {Target Hook} int TARGET_MODE_EXIT (int @var{entity}) +If this macro is defined, it is evaluated for every @var{entity} that needs mode switching. It should evaluate to an integer, which is a mode that @var{entity} is assumed to be switched to at function exit. If @code{TARGET_MODE_EXIT} is defined then @code{TARGET_MODE_ENTRY} must be defined. +@end deftypefn -@defmac EMIT_MODE_SET (@var{entity}, @var{mode}, @var{hard_regs_live}) -Generate one or more insns to set @var{entity} to @var{mode}. -@var{hard_reg_live} is the set of hard registers live at the point where -the insn(s) are to be inserted. -Sets of a lower numbered entity will be emitted before sets of a higher -numbered entity to a mode of the same or lower priority. -@end defmac +@deftypefn {Target Hook} int TARGET_MODE_PRIORITY (int @var{entity}, int @var{n}) +This macro specifies the order in which modes for @var{entity} are processed. 0 is the highest priority, @code{NUM_MODES_FOR_MODE_SWITCHING[@var{entity}] - 1} the lowest. The value of the macro should be an integer designating a mode for @var{entity}. For any fixed @var{entity}, @code{mode_priority} (@var{entity}, @var{n}) shall be a bijection in 0 @dots{} @code{num_modes_for_mode_switching[@var{entity}] - 1}. +@end deftypefn @node Target Attributes @section Defining target-specific uses of @code{__attribute__} diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 7a91da04956..9c81f201664 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7383,9 +7383,9 @@ You can have multiple entities that are mode-switched, and select at run time which entities actually need it. @code{OPTIMIZE_MODE_SWITCHING} should return nonzero for any @var{entity} that needs mode-switching. If you define this macro, you also have to define -@code{NUM_MODES_FOR_MODE_SWITCHING}, @code{MODE_NEEDED}, -@code{MODE_PRIORITY_TO_MODE} and @code{EMIT_MODE_SET}. -@code{MODE_AFTER}, @code{MODE_ENTRY}, and @code{MODE_EXIT} +@code{NUM_MODES_FOR_MODE_SWITCHING}, @code{TARGET_MODE_NEEDED}, +@code{TARGET_MODE_PRIORITY} and @code{TARGET_MODE_EMIT}. +@code{TARGET_MODE_AFTER}, @code{TARGET_MODE_ENTRY}, and @code{TARGET_MODE_EXIT} are optional. @end defmac @@ -7402,51 +7402,17 @@ represented as numbers 0 @dots{} N @minus{} 1. N is used to specify that no mod switch is needed / supplied. @end defmac -@defmac MODE_NEEDED (@var{entity}, @var{insn}) -@var{entity} is an integer specifying a mode-switched entity. If -@code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro to -return an integer value not larger than the corresponding element in -@code{NUM_MODES_FOR_MODE_SWITCHING}, to denote the mode that @var{entity} must -be switched into prior to the execution of @var{insn}. -@end defmac +@hook TARGET_MODE_EMIT -@defmac MODE_AFTER (@var{entity}, @var{mode}, @var{insn}) -@var{entity} is an integer specifying a mode-switched entity. If -this macro is defined, it is evaluated for every @var{insn} during -mode switching. It determines the mode that an insn results in (if -different from the incoming mode). -@end defmac +@hook TARGET_MODE_NEEDED -@defmac MODE_ENTRY (@var{entity}) -If this macro is defined, it is evaluated for every @var{entity} that needs -mode switching. It should evaluate to an integer, which is a mode that -@var{entity} is assumed to be switched to at function entry. If @code{MODE_ENTRY} -is defined then @code{MODE_EXIT} must be defined. -@end defmac +@hook TARGET_MODE_AFTER -@defmac MODE_EXIT (@var{entity}) -If this macro is defined, it is evaluated for every @var{entity} that needs -mode switching. It should evaluate to an integer, which is a mode that -@var{entity} is assumed to be switched to at function exit. If @code{MODE_EXIT} -is defined then @code{MODE_ENTRY} must be defined. -@end defmac +@hook TARGET_MODE_ENTRY -@defmac MODE_PRIORITY_TO_MODE (@var{entity}, @var{n}) -This macro specifies the order in which modes for @var{entity} are processed. -0 is the highest priority, @code{NUM_MODES_FOR_MODE_SWITCHING[@var{entity}] - 1} the -lowest. The value of the macro should be an integer designating a mode -for @var{entity}. For any fixed @var{entity}, @code{mode_priority_to_mode} -(@var{entity}, @var{n}) shall be a bijection in 0 @dots{} -@code{num_modes_for_mode_switching[@var{entity}] - 1}. -@end defmac +@hook TARGET_MODE_EXIT -@defmac EMIT_MODE_SET (@var{entity}, @var{mode}, @var{hard_regs_live}) -Generate one or more insns to set @var{entity} to @var{mode}. -@var{hard_reg_live} is the set of hard registers live at the point where -the insn(s) are to be inserted. -Sets of a lower numbered entity will be emitted before sets of a higher -numbered entity to a mode of the same or lower priority. -@end defmac +@hook TARGET_MODE_PRIORITY @node Target Attributes @section Defining target-specific uses of @code{__attribute__} diff --git a/gcc/mode-switching.c b/gcc/mode-switching.c index 1ae8120ee4d..b70b2e59581 100644 --- a/gcc/mode-switching.c +++ b/gcc/mode-switching.c @@ -195,13 +195,6 @@ reg_becomes_live (rtx reg, const_rtx setter ATTRIBUTE_UNUSED, void *live) add_to_hard_reg_set ((HARD_REG_SET *) live, GET_MODE (reg), regno); } -/* Make sure if MODE_ENTRY is defined the MODE_EXIT is defined - and vice versa. */ -#if defined (MODE_ENTRY) != defined (MODE_EXIT) - #error "Both MODE_ENTRY and MODE_EXIT must be defined" -#endif - -#if defined (MODE_ENTRY) && defined (MODE_EXIT) /* Split the fallthrough edge to the exit block, so that we can note that there NORMAL_MODE is required. Return the new block if it's inserted before the exit block. Otherwise return null. */ @@ -349,9 +342,11 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes) for (j = n_entities - 1; j >= 0; j--) { int e = entity_map[j]; - int mode = MODE_NEEDED (e, return_copy); + int mode = + targetm.mode_switching.needed (e, return_copy); - if (mode != num_modes[e] && mode != MODE_EXIT (e)) + if (mode != num_modes[e] + && mode != targetm.mode_switching.exit (e)) break; } if (j >= 0) @@ -450,7 +445,6 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes) return pre_exit; } -#endif /* Find all insns that need a particular mode setting, and insert the necessary mode switches. Return true if we did work. */ @@ -472,7 +466,8 @@ optimize_mode_switching (void) int n_entities; int max_num_modes = 0; bool emitted ATTRIBUTE_UNUSED = false; - basic_block post_entry ATTRIBUTE_UNUSED, pre_exit ATTRIBUTE_UNUSED; + basic_block post_entry = 0; + basic_block pre_exit = 0; for (e = N_ENTITIES - 1, n_entities = 0; e >= 0; e--) if (OPTIMIZE_MODE_SWITCHING (e)) @@ -482,9 +477,9 @@ optimize_mode_switching (void) /* Create the list of segments within each basic block. If NORMAL_MODE is defined, allow for two extra blocks split from the entry and exit block. */ -#if defined (MODE_ENTRY) && defined (MODE_EXIT) - entry_exit_extra = 3; -#endif + if (targetm.mode_switching.entry && targetm.mode_switching.exit) + entry_exit_extra = 3; + bb_info[n_entities] = XCNEWVEC (struct bb_info, last_basic_block_for_fn (cfun) + entry_exit_extra); @@ -496,12 +491,17 @@ optimize_mode_switching (void) if (! n_entities) return 0; -#if defined (MODE_ENTRY) && defined (MODE_EXIT) - /* Split the edge from the entry block, so that we can note that - there NORMAL_MODE is supplied. */ - post_entry = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))); - pre_exit = create_pre_exit (n_entities, entity_map, num_modes); -#endif + /* Make sure if MODE_ENTRY is defined the MODE_EXIT is defined and vice versa. */ + gcc_assert ((targetm.mode_switching.entry && targetm.mode_switching.exit) + || (!targetm.mode_switching.entry && !targetm.mode_switching.exit)); + + if (targetm.mode_switching.entry && targetm.mode_switching.exit) + { + /* Split the edge from the entry block, so that we can note that + there NORMAL_MODE is supplied. */ + post_entry = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))); + pre_exit = create_pre_exit (n_entities, entity_map, num_modes); + } df_analyze (); @@ -556,7 +556,7 @@ optimize_mode_switching (void) { if (INSN_P (insn)) { - int mode = MODE_NEEDED (e, insn); + int mode = targetm.mode_switching.needed (e, insn); rtx link; if (mode != no_mode && mode != last_mode) @@ -567,9 +567,10 @@ optimize_mode_switching (void) add_seginfo (info + bb->index, ptr); bitmap_clear_bit (transp[bb->index], j); } -#ifdef MODE_AFTER - last_mode = MODE_AFTER (e, last_mode, insn); -#endif + + if (targetm.mode_switching.after) + last_mode = targetm.mode_switching.after (e, last_mode, insn); + /* Update LIVE_NOW. */ for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) if (REG_NOTE_KIND (link) == REG_DEAD) @@ -595,30 +596,30 @@ optimize_mode_switching (void) bitmap_clear_bit (transp[bb->index], j); } } -#if defined (MODE_ENTRY) && defined (MODE_EXIT) - { - int mode = MODE_ENTRY (e); - - if (mode != no_mode) - { - bb = post_entry; - - /* By always making this nontransparent, we save - an extra check in make_preds_opaque. We also - need this to avoid confusing pre_edge_lcm when - antic is cleared but transp and comp are set. */ - bitmap_clear_bit (transp[bb->index], j); - - /* Insert a fake computing definition of MODE into entry - blocks which compute no mode. This represents the mode on - entry. */ - info[bb->index].computing = mode; + if (targetm.mode_switching.entry && targetm.mode_switching.exit) + { + int mode = targetm.mode_switching.entry (e); - if (pre_exit) - info[pre_exit->index].seginfo->mode = MODE_EXIT (e); - } - } -#endif /* NORMAL_MODE */ + if (mode != no_mode) + { + bb = post_entry; + + /* By always making this nontransparent, we save + an extra check in make_preds_opaque. We also + need this to avoid confusing pre_edge_lcm when + antic is cleared but transp and comp are set. */ + bitmap_clear_bit (transp[bb->index], j); + + /* Insert a fake computing definition of MODE into entry + blocks which compute no mode. This represents the mode on + entry. */ + info[bb->index].computing = mode; + + if (pre_exit) + info[pre_exit->index].seginfo->mode = + targetm.mode_switching.exit (e); + } + } } kill = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), n_entities); @@ -633,7 +634,8 @@ optimize_mode_switching (void) bitmap_vector_clear (comp, last_basic_block_for_fn (cfun)); for (j = n_entities - 1; j >= 0; j--) { - int m = current_mode[j] = MODE_PRIORITY_TO_MODE (entity_map[j], i); + int m = current_mode[j] = + targetm.mode_switching.priority (entity_map[j], i); struct bb_info *info = bb_info[j]; FOR_EACH_BB_FN (bb, cfun) @@ -688,7 +690,7 @@ optimize_mode_switching (void) rtl_profile_for_edge (eg); start_sequence (); - EMIT_MODE_SET (entity_map[j], mode, live_at_edge); + targetm.mode_switching.emit (entity_map[j], mode, live_at_edge); mode_set = get_insns (); end_sequence (); default_rtl_profile (); @@ -736,7 +738,9 @@ optimize_mode_switching (void) rtl_profile_for_bb (bb); start_sequence (); - EMIT_MODE_SET (entity_map[j], ptr->mode, ptr->regs_live); + targetm.mode_switching.emit (entity_map[j], + ptr->mode, + ptr->regs_live); mode_set = get_insns (); end_sequence (); @@ -777,12 +781,10 @@ optimize_mode_switching (void) if (need_commit) commit_edge_insertions (); -#if defined (MODE_ENTRY) && defined (MODE_EXIT) - cleanup_cfg (CLEANUP_NO_INSN_DEL); -#else - if (!need_commit && !emitted) + if (targetm.mode_switching.entry && targetm.mode_switching.exit) + cleanup_cfg (CLEANUP_NO_INSN_DEL); + else if (!need_commit && !emitted) return 0; -#endif return 1; } diff --git a/gcc/target.def b/gcc/target.def index febd3207bed..dd167bb6afb 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -5373,5 +5373,43 @@ bool, false) /* Leave the boolean fields at the end. */ +/* Functions related to mode switching. */ +#undef HOOK_PREFIX +#define HOOK_PREFIX "TARGET_MODE_" +HOOK_VECTOR (TARGET_TOGGLE_, mode_switching) + +DEFHOOK +(emit, + "Generate one or more insns to set @var{entity} to @var{mode}. @var{hard_reg_live} is the set of hard registers live at the point where the insn(s) are to be inserted. Sets of a lower numbered entity will be emitted before sets of a higher numbered entity to a mode of the same or lower priority.", + void, (int entity, int mode, HARD_REG_SET regs_live), NULL) + +DEFHOOK +(needed, + "@var{entity} is an integer specifying a mode-switched entity. If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro to return an integer value not larger than the corresponding element in @code{NUM_MODES_FOR_MODE_SWITCHING}, to denote the mode that @var{entity} must be switched into prior to the execution of @var{insn}.", + int, (int entity, rtx insn), NULL) + +DEFHOOK +(after, + "@var{entity} is an integer specifying a mode-switched entity. If this macro is defined, it is evaluated for every @var{insn} during mode switching. It determines the mode that an insn results in (if different from the incoming mode).", + int, (int entity, int mode, rtx insn), NULL) + +DEFHOOK +(entry, + "If this macro is defined, it is evaluated for every @var{entity} that needs mode switching. It should evaluate to an integer, which is a mode that @var{entity} is assumed to be switched to at function entry. If @code{TARGET_MODE_ENTRY} is defined then @code{TARGET_MODE_EXIT} must be defined.", + int, (int entity), NULL) + +DEFHOOK +(exit, + "If this macro is defined, it is evaluated for every @var{entity} that needs mode switching. It should evaluate to an integer, which is a mode that @var{entity} is assumed to be switched to at function exit. If @code{TARGET_MODE_EXIT} is defined then @code{TARGET_MODE_ENTRY} must be defined.", + int, (int entity), NULL) + +DEFHOOK +(priority, + "This macro specifies the order in which modes for @var{entity} are processed. 0 is the highest priority, @code{NUM_MODES_FOR_MODE_SWITCHING[@var{entity}] - 1} the lowest. The value of the macro should be an integer designating a mode for @var{entity}. For any fixed @var{entity}, @code{mode_priority} (@var{entity}, @var{n}) shall be a bijection in 0 @dots{} @code{num_modes_for_mode_switching[@var{entity}] - 1}.", + int, (int entity, int n), NULL) + +HOOK_VECTOR_END (mode_switching) + /* Close the 'struct gcc_target' definition. */ HOOK_VECTOR_END (C90_EMPTY_HACK) + diff --git a/gcc/target.h b/gcc/target.h index 31123d97b3e..7be94b82558 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -51,6 +51,8 @@ #include "insn-modes.h" #include "insn-codes.h" #include "wide-int.h" +#include "tm.h" +#include "hard-reg-set.h" #ifdef ENABLE_CHECKING -- 2.30.2