This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] support to flip modes in sh mode-switching


Hi,

This is a new version of the patch originally posted
(http://gcc.gnu.org/ml/gcc-patches/2006-12/msg01116.html) with improvements and cleanups.


The problem was described in: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29349.

Reminder: This patch adds support in the mode-switching pass to switch modes instead of setting them. That implies that we need to track for every basic blocks that need a mode setting (see EMIT_MODE_SET) the mode values of the incoming edges when 'avin' is set. When 'avin' is not set a regular mode setting sequence must be emitted.

This optimization is useful for the sh4-300. I don't know any other architecture supported by gcc to test it. It also shares the same module than the i386 targets to support mode switching.

The improvements for this new patch came after I realized that I didn't
have to carry any mode information on edges. I only need to record the
fact that a mode is known at avin for each basic block. (The memory consumption and edge->aux issues referred in the previous post suddenly disappeared :-))


The new algorithm is now trivial: A mode can be flipped in entry of a
basic block in the union of all mode value's avins is one. It it is zero then just set regular mode switching scheme.
The implementation becomes trivial as well. Just compute the union of each avin sbitmaps for every entities.
The only real global modification is that the real mode setting is now postponed until all the value have been computed.


LCL guaranties that a mode will never been reset to the same value it was in avin (why would it do that if the value is available ?). Furthermore, mode values are exclusives. I've added a assertion to check this.

Tracking modes is done by using the 'avin' information for each mode that is computed by pre_edge_lcm. 'avin' was originally not available outside pre_edge_lcm so I added a pre_edge_lcm_av for that purpose. EMIT_MODE_SET cannot be called for each insert, because at that time the value on the incoming edge might not be known. For that purpose the emission is delayed until all the modes had iterated (see commit_mode_set). Modes are recorded into the mode_info vector indexed by entity number and an edge identifier

Finally I added or fixed the machinery in sh.[ch]md to enable the emission of the fpchg instruction

Tested for no regression on sh-superh-elf sh4/sh4-300 targets with check-gcc and applications benchmarks.

Bootstrapped the compiler and tested for no regression on i686-pc-linux-gnu check-gcc. If there are specific flags to stress 387 modes I would be happy to run more tests.

Thanx,

Christian

	* basic-block.h (pre_edge_lcm_avs): Declare
	* config/i386/i386.h (EMIT_MODE_SET): Add ACTUALMODE parameter.
	* doc/tm.texi (EMIT_MODE_SET): Idem.
	* config/i386/sh.h (EMIT_MODE_SET): Idem. Call emit_fpu_flip.
	* config/sh/sh-protos.h	(emit_fpu_flip): Add proto.
	* config/sh/sh.c (emit_fpu_flip): New function.
	* config/sh/sh.md (toggle_pr): Defined for TARGET_SH4_300.
	Defined if TARGET_FPU_SINGLE.
	* lcm.c (pre_edge_lcm_avs): Renamed from pre_edge_lcm.
	Call clear_aux_for_edges. Fix comments.
	(pre_edge_lcm): New wrapper function to call pre_edge_lcm_avs.
	(pre_edge_rev_lcm): Idem
	* mode-switching.c (init_modes_infos): New function.
	(free_modes_infos): Idem.
	(add_mode_set): Idem.
	(get_mode): Idem.
	(commit_mode_sets): Idem.
	(merge_modes): Idem.
	(set_avin_mode): New macro.
	(test_avin_mode): Idem.
	(optimize_mode_switching): Add support to maintain
        information for mode switching.



diff -rcp gcc-4.3-20061216/gcc/basic-block.h gcc-4.3-20061216.mode-switch/gcc/basic-block.h
*** gcc-4.3-20061216/gcc/basic-block.h	2006-11-25 11:34:13.000000000 +0100
--- gcc-4.3-20061216.mode-switch/gcc/basic-block.h	2006-12-19 15:18:36.000000000 +0100
*************** extern void free_propagate_block_info (s
*** 863,868 ****
--- 863,871 ----
  extern struct edge_list *pre_edge_lcm (int, sbitmap *, sbitmap *,
  				       sbitmap *, sbitmap *, sbitmap **,
  				       sbitmap **);
+ extern struct edge_list *pre_edge_lcm_avs (int, sbitmap *, sbitmap *,
+ 					   sbitmap *, sbitmap *, sbitmap *,
+ 					   sbitmap *, sbitmap **, sbitmap **);
  extern struct edge_list *pre_edge_rev_lcm (int, sbitmap *,
  					   sbitmap *, sbitmap *,
  					   sbitmap *, sbitmap **,
diff -rcp gcc-4.3-20061216/gcc/config/i386/i386.h gcc-4.3-20061216.mode-switch/gcc/config/i386/i386.h
*** gcc-4.3-20061216/gcc/config/i386/i386.h	2006-12-13 19:07:47.000000000 +0100
--- gcc-4.3-20061216.mode-switch/gcc/config/i386/i386.h	2006-12-21 16:27:55.000000000 +0100
*************** enum ix86_stack_slot
*** 2246,2252 ****
     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) 			\
    ((MODE) != I387_CW_ANY && (MODE) != I387_CW_UNINITIALIZED		\
     ? emit_i387_cw_initialization (MODE), 0				\
     : 0)
--- 2246,2252 ----
     is the set of hard registers live at the point where the insn(s)
     are to be inserted.  */
  
! #define EMIT_MODE_SET(ENTITY, MODE, FLIPMODE, HARD_REGS_LIVE)		\
    ((MODE) != I387_CW_ANY && (MODE) != I387_CW_UNINITIALIZED		\
     ? emit_i387_cw_initialization (MODE), 0				\
     : 0)
diff -rcp gcc-4.3-20061216/gcc/config/sh/sh.c gcc-4.3-20061216.mode-switch/gcc/config/sh/sh.c
*** gcc-4.3-20061216/gcc/config/sh/sh.c	2006-12-05 18:26:05.000000000 +0100
--- gcc-4.3-20061216.mode-switch/gcc/config/sh/sh.c	2006-12-22 08:54:01.000000000 +0100
*************** get_free_reg (HARD_REG_SET regs_live)
*** 8524,8529 ****
--- 8524,8536 ----
    return gen_rtx_REG (Pmode, 7);
  }
  
+ /* This function switches the fpscr.  */
+ void
+ emit_fpu_flip (void)
+ {
+   emit_insn (gen_toggle_pr ());
+ }
+ 
  /* This function will set the fpscr from memory.
     MODE is the mode we are setting it to.  */
  void
diff -rcp gcc-4.3-20061216/gcc/config/sh/sh.h gcc-4.3-20061216.mode-switch/gcc/config/sh/sh.h
*** gcc-4.3-20061216/gcc/config/sh/sh.h	2006-12-08 17:37:42.000000000 +0100
--- gcc-4.3-20061216.mode-switch/gcc/config/sh/sh.h	2006-12-21 16:27:42.000000000 +0100
*************** extern int current_function_interrupt;
*** 3418,3425 ****
  #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))
--- 3418,3427 ----
  #define MODE_PRIORITY_TO_MODE(ENTITY, N) \
    ((TARGET_FPU_SINGLE != 0) ^ (N) ? FP_MODE_SINGLE : FP_MODE_DOUBLE)
  
! #define EMIT_MODE_SET(ENTITY, MODE, FLIPMODE, HARD_REGS_LIVE) \
!   ((TARGET_SH4A_FP || TARGET_SH4_300)           \
!    && (FLIPMODE) ? emit_fpu_flip ()             \
!    : fpscr_set_from_mem ((MODE), (HARD_REGS_LIVE)))
  
  #define MD_CAN_REDIRECT_BRANCH(INSN, SEQ) \
    sh_can_redirect_branch ((INSN), (SEQ))
diff -rcp gcc-4.3-20061216/gcc/config/sh/sh.md gcc-4.3-20061216.mode-switch/gcc/config/sh/sh.md
*** gcc-4.3-20061216/gcc/config/sh/sh.md	2006-11-29 15:35:38.000000000 +0100
--- gcc-4.3-20061216.mode-switch/gcc/config/sh/sh.md	2006-12-19 14:30:01.000000000 +0100
*************** mov.l\\t1f,r0\\n\\
*** 10066,10080 ****
    "fschg"
    [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
  
- ;; There's no way we can use it today, since optimize mode switching
- ;; doesn't enable us to know from which mode we're switching to the
- ;; mode it requests, to tell whether we can use a relative mode switch
- ;; (like toggle_pr) or an absolute switch (like loading fpscr from
- ;; memory).
  (define_insn "toggle_pr"
    [(set (reg:PSI FPSCR_REG)
  	(xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
!   "TARGET_SH4A_FP && ! TARGET_FPU_SINGLE"
    "fpchg"
    [(set_attr "type" "fpscr_toggle")])
  
--- 10066,10075 ----
    "fschg"
    [(set_attr "type" "fpscr_toggle") (set_attr "fp_set" "unknown")])
  
  (define_insn "toggle_pr"
    [(set (reg:PSI FPSCR_REG)
  	(xor:PSI (reg:PSI FPSCR_REG) (const_int 524288)))]
!   "(TARGET_SH4A_FP || TARGET_SH4_300)"
    "fpchg"
    [(set_attr "type" "fpscr_toggle")])
  
diff -rcp gcc-4.3-20061216/gcc/config/sh/sh-protos.h gcc-4.3-20061216.mode-switch/gcc/config/sh/sh-protos.h
*** gcc-4.3-20061216/gcc/config/sh/sh-protos.h	2006-11-03 15:52:19.000000000 +0100
--- gcc-4.3-20061216.mode-switch/gcc/config/sh/sh-protos.h	2006-12-18 16:13:12.000000000 +0100
*************** extern int check_use_sfunc_addr (rtx, rt
*** 151,156 ****
--- 151,157 ----
  #ifdef HARD_CONST
  extern void fpscr_set_from_mem (int, HARD_REG_SET);
  #endif
+ extern void emit_fpu_flip (void);
  
  extern void sh_pr_interrupt (struct cpp_reader *);
  extern void sh_pr_trapa (struct cpp_reader *);
diff -rcp gcc-4.3-20061216/gcc/doc/tm.texi gcc-4.3-20061216.mode-switch/gcc/doc/tm.texi
*** gcc-4.3-20061216/gcc/doc/tm.texi	2006-12-13 00:53:37.000000000 +0100
--- gcc-4.3-20061216.mode-switch/gcc/doc/tm.texi	2006-12-21 16:44:24.000000000 +0100
*************** for @var{entity}.  For any fixed @var{en
*** 8833,8842 ****
  @code{num_modes_for_mode_switching[@var{entity}] - 1}.
  @end defmac
  
! @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.
  @end defmac
  
  @node Target Attributes
--- 8833,8842 ----
  @code{num_modes_for_mode_switching[@var{entity}] - 1}.
  @end defmac
  
! @defmac EMIT_MODE_SET (@var{entity}, @var{mode}, @var{actualmode}, @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. @var{flipmode} flip the mode instead of setting it.
  @end defmac
  
  @node Target Attributes
diff -rcp gcc-4.3-20061216/gcc/lcm.c gcc-4.3-20061216.mode-switch/gcc/lcm.c
*** gcc-4.3-20061216/gcc/lcm.c	2006-02-06 19:20:47.000000000 +0100
--- gcc-4.3-20061216.mode-switch/gcc/lcm.c	2006-12-21 14:42:30.000000000 +0100
*************** compute_insert_delete (struct edge_list 
*** 371,387 ****
      }
  }
  
! /* Given local properties TRANSP, ANTLOC, AVOUT, KILL return the insert and
!    delete vectors for edge based LCM.  Returns an edgelist which is used to
!    map the insert vector to what edge an expression should be inserted on.  */
  
  struct edge_list *
! pre_edge_lcm (int n_exprs, sbitmap *transp,
! 	      sbitmap *avloc, sbitmap *antloc, sbitmap *kill,
! 	      sbitmap **insert, sbitmap **delete)
  {
    sbitmap *antin, *antout, *earliest;
-   sbitmap *avin, *avout;
    sbitmap *later, *laterin;
    struct edge_list *edge_list;
    int num_edges;
--- 371,388 ----
      }
  }
  
! /* Given local properties TRANSP, ANTLOC, AVLOC, KILL return the insert and
!    delete vectors for edge based LCM, and return the AVIN, AVOUT bitmap
!    information. Returns an edgelist which is used to map the insert vector to
!    what edge an expression should be inserted on.  */
  
  struct edge_list *
! pre_edge_lcm_avs (int n_exprs, sbitmap *transp,
! 		  sbitmap *avloc, sbitmap *antloc, sbitmap *kill,
! 		  sbitmap *avin, sbitmap *avout,
! 		  sbitmap **insert, sbitmap **delete)
  {
    sbitmap *antin, *antout, *earliest;
    sbitmap *later, *laterin;
    struct edge_list *edge_list;
    int num_edges;
*************** pre_edge_lcm (int n_exprs, sbitmap *tran
*** 403,412 ****
  #endif
  
    /* Compute global availability.  */
-   avin = sbitmap_vector_alloc (last_basic_block, n_exprs);
-   avout = sbitmap_vector_alloc (last_basic_block, n_exprs);
    compute_available (avloc, kill, avout, avin);
-   sbitmap_vector_free (avin);
  
    /* Compute global anticipatability.  */
    antin = sbitmap_vector_alloc (last_basic_block, n_exprs);
--- 404,410 ----
*************** pre_edge_lcm (int n_exprs, sbitmap *tran
*** 432,438 ****
  
    sbitmap_vector_free (antout);
    sbitmap_vector_free (antin);
-   sbitmap_vector_free (avout);
  
    later = sbitmap_vector_alloc (num_edges, n_exprs);
  
--- 430,435 ----
*************** pre_edge_lcm (int n_exprs, sbitmap *tran
*** 469,474 ****
--- 466,492 ----
    return edge_list;
  }
  
+ struct edge_list *
+ pre_edge_lcm (int n_exprs, sbitmap *transp,
+ 	      sbitmap *avloc, sbitmap *antloc, sbitmap *kill, 
+ 	      sbitmap **insert, sbitmap **delete)
+ {
+   struct edge_list *edge_list;
+   sbitmap *avin, *avout;
+ 
+   avin = sbitmap_vector_alloc (last_basic_block, n_exprs);
+   avout = sbitmap_vector_alloc (last_basic_block, n_exprs);
+ 
+   edge_list = pre_edge_lcm_avs (n_exprs, transp, avloc, antloc, kill,
+ 				 avin, avout, insert, delete);
+ 
+   sbitmap_vector_free (avout);
+   sbitmap_vector_free (avin);
+ 
+   return edge_list;
+ }
+ 
+ 
  /* Compute the AVIN and AVOUT vectors from the AVLOC and KILL vectors.
     Return the number of passes we performed to iterate to a solution.  */
  
diff -rcp gcc-4.3-20061216/gcc/mode-switching.c gcc-4.3-20061216.mode-switch/gcc/mode-switching.c
*** gcc-4.3-20061216/gcc/mode-switching.c	2006-09-05 23:41:23.000000000 +0200
--- gcc-4.3-20061216.mode-switch/gcc/mode-switching.c	2006-12-22 08:57:49.000000000 +0100
*************** struct bb_info
*** 84,89 ****
--- 84,214 ----
    int computing;
  };
  
+ /* Bitmap to record the union of all mode avins.  */
+ 
+ static sbitmap *modes_in;   /* avin mode for basic block.  */
+ 
+ #define set_avin_mode(j, bb) SET_BIT (modes_in[(bb)->index], (j))
+ 
+ #define test_avin_mode(j, bb) TEST_BIT (modes_in[(bb)->index], (j))
+ 
+ /* To support mode switching, the algorithm cannot set the modes after
+    the insert and delete bitmaps are computed by pre_edge_lcm, because 'avin'
+    is computed iteratively for each possible modes for each entity.
+    The mode emission will be done after all mode are processed.
+    (see commit_mode_sets).  */
+ 
+ static int **modes_needed;  /* modes needs to be inserted on this edge.  */
+ 
+ /* Indicates that edge mode information is unknown. Cannot use 'no_mode'
+    because its value depends of its entity */
+ #define NO_MODE -1
+ 
+ /* Allocates and initializes modes_infos.  */
+ 
+ static void
+ init_modes_infos (int n_entities)
+ {
+   int j;
+   int num_edges = 0;
+   basic_block bb;
+ 
+   /* How many edges do we have ?  */
+ 
+   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
+       num_edges += EDGE_COUNT (bb->succs);
+ 
+   modes_needed = xmalloc (sizeof (int *) * n_entities);
+ 
+   for (j = 0; j < n_entities; j++)
+     {
+       modes_needed[j] = xmalloc (sizeof (int) * num_edges);
+ 
+       /* Initial NO_MODE value is -1, because 0 is a value mode.  */
+       memset (modes_needed[j], NO_MODE, num_edges * sizeof (int));
+     }
+ 
+   /* Allocates bitmap for avin modes.  */
+   modes_in = sbitmap_vector_alloc (last_basic_block, n_entities);
+   sbitmap_vector_zero (modes_in, last_basic_block);
+ }
+ 
+ /* frees memory used to hold the modes information.  */
+ 
+ static void
+ free_modes_infos (int n_entities)
+ {
+   int j;
+ 
+   for (j = 0; j < n_entities; j++)
+     free (modes_needed[j]);
+ 
+   free (modes_needed);
+   sbitmap_vector_free (modes_in);
+ }
+ 
+ /* records the mode associated with edge e for entity j.  */
+ 
+ static void
+ add_mode_set (int j, int e, int mode)
+ {
+   modes_needed[j][e] = mode;
+ }
+ 
+ /* returns the mode needed on edge e for entity j. -1 if none.  */
+ 
+ static int
+ get_mode (int j, int e)
+ {
+   return modes_needed[j][e];
+ }
+ 
+ /* Finally, after all the modes after been inserted after lcm, we can
+    process with the mode emission.  */
+ 
+ static int
+ commit_mode_sets (struct edge_list *edge_list, int j)
+ {
+   int need_commit = 0;
+   int e;
+ 
+   for (e = 0; e < NUM_EDGES (edge_list); e++)
+     {
+       HARD_REG_SET live_at_edge;
+       edge eg = INDEX_EDGE (edge_list, e);
+       basic_block src_bb = eg->src;
+       int mode, prev_mode;
+       rtx mode_set;
+ 
+       if ((mode = get_mode (j, e)) == NO_MODE)
+ 	continue;
+ 
+       prev_mode = test_avin_mode (j, src_bb);
+ 
+       REG_SET_TO_HARD_REG_SET (live_at_edge,
+ 			       src_bb->il.rtl->global_live_at_end);
+ 
+       start_sequence ();
+       EMIT_MODE_SET (entity_map[j], mode, prev_mode, live_at_edge);
+ 
+       mode_set = get_insns ();
+       end_sequence ();      
+ 
+       /* Do not bother to insert empty sequence.  */
+       if (mode_set == NULL_RTX)
+ 	continue;
+ 
+       /* We should not get an abnormal edge here.  */
+       gcc_assert (! (eg->flags & EDGE_ABNORMAL));
+ 	  
+       need_commit = 1;
+       insert_insn_on_edge (mode_set, eg);
+     }
+ 
+   return need_commit;
+ }
+ 
+ 
  /* These bitmaps are used for the LCM algorithm.  */
  
  static sbitmap *antic;
*************** create_pre_exit (int n_entities, int *en
*** 379,384 ****
--- 504,529 ----
  }
  #endif
  
+ 
+ /* This function merges the avin modes.  */
+ 
+ static void
+ merge_modes (sbitmap *avin)
+ {
+   basic_block bb;
+ 
+   FOR_EACH_BB (bb)
+     {
+       int i = bb->index;
+ 
+       /* Modes are exclusives.  */
+       gcc_assert (! sbitmap_any_common_bits (modes_in[i], avin[i]));
+ 
+       /* Merge modes for each entity.  */
+       sbitmap_a_or_b (modes_in[i], modes_in[i], avin[i]);
+     }
+ }
+ 
  /* Find all insns that need a particular mode setting, and insert the
     necessary mode switches.  Return true if we did work.  */
  
*************** optimize_mode_switching (void)
*** 390,396 ****
    basic_block bb;
    int need_commit = 0;
    sbitmap *kill;
-   struct edge_list *edge_list;
    static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING;
  #define N_ENTITIES ARRAY_SIZE (num_modes)
    int entity_map[N_ENTITIES];
--- 535,540 ----
*************** optimize_mode_switching (void)
*** 400,405 ****
--- 544,551 ----
    int max_num_modes = 0;
    bool emited = false;
    basic_block post_entry ATTRIBUTE_UNUSED, pre_exit ATTRIBUTE_UNUSED;
+   sbitmap *avin, *avout;
+   struct edge_list *edge_list = 0;
  
    clear_bb_flags ();
  
*************** optimize_mode_switching (void)
*** 436,441 ****
--- 582,589 ----
    antic = sbitmap_vector_alloc (last_basic_block, n_entities);
    transp = sbitmap_vector_alloc (last_basic_block, n_entities);
    comp = sbitmap_vector_alloc (last_basic_block, n_entities);
+   avin = sbitmap_vector_alloc (last_basic_block, n_entities);
+   avout = sbitmap_vector_alloc (last_basic_block, n_entities);
  
    sbitmap_vector_ones (transp, last_basic_block);
  
*************** optimize_mode_switching (void)
*** 538,543 ****
--- 686,694 ----
      }
  
    kill = sbitmap_vector_alloc (last_basic_block, n_entities);
+ 
+   init_modes_infos (n_entities);
+ 
    for (i = 0; i < max_num_modes; i++)
      {
        int current_mode[N_ENTITIES];
*************** optimize_mode_switching (void)
*** 547,552 ****
--- 698,704 ----
        /* Set the anticipatable and computing arrays.  */
        sbitmap_vector_zero (antic, last_basic_block);
        sbitmap_vector_zero (comp, last_basic_block);
+ 
        for (j = n_entities - 1; j >= 0; j--)
  	{
  	  int m = current_mode[j] = MODE_PRIORITY_TO_MODE (entity_map[j], i);
*************** optimize_mode_switching (void)
*** 567,574 ****
  
        FOR_EACH_BB (bb)
  	sbitmap_not (kill[bb->index], transp[bb->index]);
!       edge_list = pre_edge_lcm (n_entities, transp, comp, antic,
! 				kill, &insert, &delete);
  
        for (j = n_entities - 1; j >= 0; j--)
  	{
--- 719,729 ----
  
        FOR_EACH_BB (bb)
  	sbitmap_not (kill[bb->index], transp[bb->index]);
!       edge_list = pre_edge_lcm_avs (n_entities, transp, comp, antic,
! 				kill, avin, avout, &insert, &delete);
! 
!       /* Merge avin modes for all entities at once.  */
!       merge_modes (avin);
  
        for (j = n_entities - 1; j >= 0; j--)
  	{
*************** optimize_mode_switching (void)
*** 585,594 ****
  	  for (e = NUM_EDGES (edge_list) - 1; e >= 0; e--)
  	    {
  	      edge eg = INDEX_EDGE (edge_list, e);
- 	      int mode;
- 	      basic_block src_bb;
- 	      HARD_REG_SET live_at_edge;
- 	      rtx mode_set;
  
  	      eg->aux = 0;
  
--- 740,745 ----
*************** optimize_mode_switching (void)
*** 597,622 ****
  
  	      eg->aux = (void *)1;
  
! 	      mode = current_mode[j];
! 	      src_bb = eg->src;
! 
! 	      REG_SET_TO_HARD_REG_SET (live_at_edge,
! 				       src_bb->il.rtl->global_live_at_end);
! 
! 	      start_sequence ();
! 	      EMIT_MODE_SET (entity_map[j], mode, live_at_edge);
! 	      mode_set = get_insns ();
! 	      end_sequence ();
! 
! 	      /* Do not bother to insert empty sequence.  */
! 	      if (mode_set == NULL_RTX)
! 		continue;
! 
! 	      /* We should not get an abnormal edge here.  */
! 	      gcc_assert (! (eg->flags & EDGE_ABNORMAL));
! 
! 	      need_commit = 1;
! 	      insert_insn_on_edge (mode_set, eg);
  	    }
  
  	  FOR_EACH_BB_REVERSE (bb)
--- 748,755 ----
  
  	      eg->aux = (void *)1;
  
! 	      /* Remember we need to emit it.  */
! 	      add_mode_set(j, e, current_mode[j]);
  	    }
  
  	  FOR_EACH_BB_REVERSE (bb)
*************** optimize_mode_switching (void)
*** 631,637 ****
        sbitmap_vector_free (delete);
        sbitmap_vector_free (insert);
        clear_aux_for_edges ();
!       free_edge_list (edge_list);
      }
  
    /* Now output the remaining mode sets in all the segments.  */
--- 764,773 ----
        sbitmap_vector_free (delete);
        sbitmap_vector_free (insert);
        clear_aux_for_edges ();
! 
!       /* Keep last edge_list instance for after.  */
!       if (i != max_num_modes - 1)
! 	free_edge_list (edge_list);
      }
  
    /* Now output the remaining mode sets in all the segments.  */
*************** optimize_mode_switching (void)
*** 639,647 ****
--- 775,790 ----
      {
        int no_mode = num_modes[entity_map[j]];
  
+       /* In case there was no mode inserted. the mode information on the edge
+ 	 might not be complete. 
+ 	 Update mode info on edges and commit pending mode sets.  */
+       need_commit |= commit_mode_sets (edge_list, j);
+ 
        FOR_EACH_BB_REVERSE (bb)
  	{
  	  struct seginfo *ptr, *next;
+ 	  int last_mode = test_avin_mode(j, bb);
+ 
  	  for (ptr = bb_info[j][bb->index].seginfo; ptr; ptr = next)
  	    {
  	      next = ptr->next;
*************** optimize_mode_switching (void)
*** 650,659 ****
  		  rtx mode_set;
  
  		  start_sequence ();
! 		  EMIT_MODE_SET (entity_map[j], ptr->mode, ptr->regs_live);
  		  mode_set = get_insns ();
  		  end_sequence ();
  
  		  /* Insert MODE_SET only if it is nonempty.  */
  		  if (mode_set != NULL_RTX)
  		    {
--- 793,805 ----
  		  rtx mode_set;
  
  		  start_sequence ();
! 		  EMIT_MODE_SET (entity_map[j], ptr->mode, last_mode,
! 				 ptr->regs_live);
  		  mode_set = get_insns ();
  		  end_sequence ();
  
+ 		  last_mode = ptr->mode;
+ 
  		  /* Insert MODE_SET only if it is nonempty.  */
  		  if (mode_set != NULL_RTX)
  		    {
*************** optimize_mode_switching (void)
*** 674,685 ****
--- 820,836 ----
        free (bb_info[j]);
      }
  
+   free_edge_list (edge_list); 
+   free_modes_infos (n_entities);
+ 
    /* Finished. Free up all the things we've allocated.  */
  
    sbitmap_vector_free (kill);
    sbitmap_vector_free (antic);
    sbitmap_vector_free (transp);
    sbitmap_vector_free (comp);
+   sbitmap_vector_free (avout);
+   sbitmap_vector_free (avin);
  
    if (need_commit)
      commit_edge_insertions ();


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]