public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: [PING PATCH] Extend mode-switching to support toggle
       [not found] ` <CAMqJFCqACoQEtjz_HM=SW1EH0-nrqYSrxLG4_ANja5XcS90_0g@mail.gmail.com>
@ 2014-04-15 11:52   ` Christian Bruel
  2014-04-17 14:00     ` [ PATCH] Extend mode-switching to support toggle (1/2) Christian Bruel
  0 siblings, 1 reply; 3+ messages in thread
From: Christian Bruel @ 2014-04-15 11:52 UTC (permalink / raw)
  To: Joern Rennecke
  Cc: Steven Bosscher, Kaz Kojima, Uros Bizjak, jh, ebotcazou, gcc-patches


On 04/15/2014 01:13 PM, Joern Rennecke wrote:
> On 15 April 2014 10:20, Christian Bruel <christian.bruel@st.com> wrote:
>> Hello,
>>
>> I guess it's for RTL maintainers. Also interested by mode-switching.c
>> last contributors (from past ChangeLog entries) comments,
>>
>> http://gcc.gnu.org/ml/gcc-patches/2014-04/msg00196.html
> This only helps if there are exactly two modes for an entity.
> An interface which extends EMIT_MODE_SET with a parameter for the known
> mode would be more versatile.  I.e. if you need to manipulate a control register
> with an AND and OR to set a specific mode with no knowledge of the previous
> mode, having the known previous mode allows to use a single add or xor
> to make the desired switch.  An unknown mode could be represented by no_mode
> or -1.

yes, I didn't have a 3 state (or more) toggling in mind. My
implementation only works for 2 states entities (flip on/off a bit).
More than that would require not using a XOR and should expose the
test/set_toggle_status machinery to a machine description part. This is
a limitation of my proposal, If this will be a missing extension for a
target, we will need to move the test/set toggle machinery out of the
machine independent part. Maybe overkill as of today.

I agree that extending the current EMIT_MODE_SET might be more flexible
than a new EMIT_TOGGLE. I was balancing between the two interfaces...
thanks for this point.

> While you are at it, you should also hookize the thing.

OK,

>
> FWIW, I have noted down some weaknesses/improvement opportunities of
> the mode switching pass in: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29349 .
> This also touches the fpchg issue
Thanks, I have also some example where this can be improved, hoping to
resurrect this problem one day.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [ PATCH] Extend mode-switching to support toggle (1/2)
  2014-04-15 11:52   ` [PING PATCH] Extend mode-switching to support toggle Christian Bruel
@ 2014-04-17 14:00     ` Christian Bruel
  2014-05-09 19:47       ` Jeff Law
  0 siblings, 1 reply; 3+ messages in thread
From: Christian Bruel @ 2014-04-17 14:00 UTC (permalink / raw)
  To: gcc-patches, Joern Rennecke, Kaz Kojima, ebotcazou, Steven Bosscher

[-- Attachment #1: Type: text/plain, Size: 339 bytes --]

Hello,

He is a new version of the patch. It hookizes the mode-setting and
mode-toggling macros. Split in 2 parts.

Successfully bootstrapped/regtested on ix86 and SH4/SH4a.

I was able to do a limited build on Epiphany, if someone could give it a
try on it that would be great.

comments ? suggestions ?

many thanks,

Christian










[-- Attachment #2: mode_switch-hook.patch --]
[-- Type: text/x-patch, Size: 33926 bytes --]

2014-04-02  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 (emit_fpu_toggle): New function.
	(sh4_emit_mode_set, sh4_mode_needed): Hookify.
	(sh4_mode_after, sh4_mode_entry, sh4_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.

--- gcc/config/epiphany/epiphany-protos.h	(revision 209415)
+++ gcc/config/epiphany/epiphany-protos.h	(working copy)
@@ -45,9 +45,7 @@ extern void emit_set_fp_mode (int entity, int mode
 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);
--- gcc/config/epiphany/epiphany.c	(revision 209415)
+++ gcc/config/epiphany/epiphany.c	(working copy)
@@ -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
@@ -2306,8 +2320,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)
@@ -2415,7 +2429,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 ;
@@ -2502,6 +2516,18 @@ epiphany_mode_after (int entity, int last_mode, rt
   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)
 {
--- gcc/config/epiphany/epiphany.h	(revision 209415)
+++ gcc/config/epiphany/epiphany.h	(working copy)
@@ -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.  */
--- gcc/config/epiphany/mode-switch-use.c	(revision 209415)
+++ gcc/config/epiphany/mode-switch-use.c	(working copy)
@@ -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)
--- gcc/config/i386/i386-protos.h	(revision 209415)
+++ gcc/config/i386/i386-protos.h	(working copy)
@@ -166,17 +166,8 @@ extern bool ix86_secondary_memory_needed (enum reg
 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]);
--- gcc/config/i386/i386.c	(revision 209415)
+++ gcc/config/i386/i386.c	(working copy)
@@ -16135,7 +16135,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)
@@ -16233,7 +16233,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)
@@ -16266,7 +16266,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)
@@ -16283,6 +16283,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.  */
@@ -16398,7 +16404,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)
@@ -47127,6 +47137,24 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree *
 #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;
 \f
 #include "gt-i386.h"
--- gcc/config/i386/i386.h	(revision 209415)
+++ gcc/config/i386/i386.h	(working copy)
@@ -2310,43 +2310,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))
 \f
 /* Avoid renaming of stack registers, as doing so in combination with
    scheduling just increases amount of live registers at time and in
--- gcc/config/sh/sh.c	(revision 209415)
+++ gcc/config/sh/sh.c	(working copy)
@@ -202,6 +202,17 @@ 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 sh4_emit_mode_set (int, int, HARD_REG_SET);
+static int sh4_mode_needed (int, rtx);
+static int sh4_mode_after (int, int, rtx);
+static int sh4_mode_entry (int);
+static int sh4_mode_exit (int);
+static void sh4_toggle_init (int);
+static int sh4_mode_priority (int entity, int n);
+static void sh4_toggle_destroy (void);
+static void sh4_toggle_set (sbitmap *, sbitmap *);
+static bool sh4_toggle_test (int, int, bool);
+
 static rtx mark_constant_pool_use (rtx);
 static tree sh_handle_interrupt_handler_attribute (tree *, tree, tree,
 						   int, bool *);
@@ -564,6 +575,24 @@ static const struct attribute_spec sh_attribute_ta
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED sh_frame_pointer_required
 
+#undef TARGET_MODE_EMIT
+#define TARGET_MODE_EMIT sh4_emit_mode_set
+
+#undef TARGET_MODE_NEEDED
+#define TARGET_MODE_NEEDED sh4_mode_needed
+
+#undef TARGET_MODE_AFTER
+#define TARGET_MODE_AFTER sh4_mode_after
+
+#undef TARGET_MODE_ENTRY
+#define TARGET_MODE_ENTRY sh4_mode_entry
+
+#undef TARGET_MODE_EXIT
+#define TARGET_MODE_EXIT sh4_mode_exit
+
+#undef TARGET_MODE_PRIORITY
+#define TARGET_MODE_PRIORITY sh4_mode_priority
+
 /* Return regmode weight for insn.  */
 #define INSN_REGMODE_WEIGHT(INSN, MODE)\
   regmode_weight[((MODE) == SImode) ? 0 : 1][INSN_UID (INSN)]
@@ -13501,4 +13530,45 @@ sh_try_omit_signzero_extend (rtx extended_op, rtx
   return NULL_RTX;
 }
 
+static void
+sh4_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode,
+		   HARD_REG_SET regs_live)
+{
+  fpscr_set_from_mem (mode, regs_live);
+}
+
+static int
+sh4_mode_needed (int entity ATTRIBUTE_UNUSED, rtx insn)
+{
+  return recog_memoized (insn) >= 0  ? get_attr_fp_mode (insn) : FP_MODE_NONE;
+}
+
+static int
+sh4_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
+sh4_mode_entry (int entity ATTRIBUTE_UNUSED)
+{
+  return NORMAL_MODE (entity);
+}
+
+static int
+sh4_mode_exit (int entity ATTRIBUTE_UNUSED)
+{
+  return sh_cfun_attr_renesas_p () ? FP_MODE_NONE : NORMAL_MODE (entity);
+}
+
+static int
+sh4_mode_priority (int entity ATTRIBUTE_UNUSED, int n)
+{
+  return ((TARGET_FPU_SINGLE != 0) ^ (n) ? FP_MODE_SINGLE : FP_MODE_DOUBLE);
+}
+
 #include "gt-sh.h"
--- gcc/config/sh/sh.h	(revision 209415)
+++ gcc/config/sh/sh.h	(working copy)
@@ -2241,32 +2241,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))
 
--- gcc/doc/tm.texi	(revision 209415)
+++ gcc/doc/tm.texi	(working copy)
@@ -9717,9 +9717,9 @@ You can have multiple entities that are mode-switc
 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
 
@@ -9736,51 +9736,29 @@ represented as numbers 0 @dots{} N @minus{} 1.  N
 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__}
--- gcc/doc/tm.texi.in	(revision 209415)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -7386,9 +7386,9 @@ You can have multiple entities that are mode-switc
 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
 
@@ -7405,51 +7405,17 @@ represented as numbers 0 @dots{} N @minus{} 1.  N
 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__}
--- gcc/mode-switching.c	(revision 209415)
+++ gcc/mode-switching.c	(working copy)
@@ -195,13 +195,6 @@ reg_becomes_live (rtx reg, const_rtx setter ATTRIB
     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,
 		    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,
 
   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,13 +491,18 @@ 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 ();
 
   /* Create the bitmap vectors.  */
@@ -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;
 }
--- gcc/target.def	(revision 209415)
+++ gcc/target.def	(working copy)
@@ -5345,5 +5345,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)
+
--- gcc/target.h	(revision 209415)
+++ gcc/target.h	(working copy)
@@ -51,6 +51,8 @@
 #include "insn-modes.h"
 #include "insn-codes.h"
 #include "double-int.h"
+#include "tm.h"
+#include "hard-reg-set.h"
 
 #ifdef ENABLE_CHECKING
 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [ PATCH] Extend mode-switching to support toggle (1/2)
  2014-04-17 14:00     ` [ PATCH] Extend mode-switching to support toggle (1/2) Christian Bruel
@ 2014-05-09 19:47       ` Jeff Law
  0 siblings, 0 replies; 3+ messages in thread
From: Jeff Law @ 2014-05-09 19:47 UTC (permalink / raw)
  To: Christian Bruel, gcc-patches, Joern Rennecke, Kaz Kojima,
	ebotcazou, Steven Bosscher

On 04/17/14 07:58, Christian Bruel wrote:
> Hello,
>
> He is a new version of the patch. It hookizes the mode-setting and
> mode-toggling macros. Split in 2 parts.
>
> Successfully bootstrapped/regtested on ix86 and SH4/SH4a.
>
> I was able to do a limited build on Epiphany, if someone could give it a
> try on it that would be great.
>
> comments ? suggestions ?
I can't really vouch for the sh & ephiphany bits, but those bits look 
reasonable.  The rest looks good.  OK for the trunk.

Thanks,
Jeff

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-05-09 19:47 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <534CF9D7.70605@st.com>
     [not found] ` <CAMqJFCqACoQEtjz_HM=SW1EH0-nrqYSrxLG4_ANja5XcS90_0g@mail.gmail.com>
2014-04-15 11:52   ` [PING PATCH] Extend mode-switching to support toggle Christian Bruel
2014-04-17 14:00     ` [ PATCH] Extend mode-switching to support toggle (1/2) Christian Bruel
2014-05-09 19:47       ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).