target.def (mode_switching): New hook vector.

2014-05-13  Christian Bruel  <christian.bruel@st.com>

	* 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
This commit is contained in:
Christian Bruel 2014-05-13 10:50:51 +02:00 committed by Christian Bruel
parent 455464ab33
commit 06b9060214
15 changed files with 293 additions and 230 deletions

View File

@ -1,3 +1,44 @@
2014-05-13 Christian Bruel <christian.bruel@st.com>
* 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 <jakub@redhat.com>
PR target/61060

View File

@ -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);

View File

@ -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)
{

View File

@ -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. */

View File

@ -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)

View File

@ -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]);

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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))

View File

@ -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__}

View File

@ -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__}

View File

@ -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 (targetm.mode_switching.entry && targetm.mode_switching.exit)
{
int mode = targetm.mode_switching.entry (e);
if (mode != no_mode)
{
bb = post_entry;
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);
/* 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;
/* 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 = MODE_EXIT (e);
}
}
#endif /* NORMAL_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;
}

View File

@ -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)

View File

@ -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