public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATH] support to flip modes and delayed slot sh bug
@ 2007-01-05 15:40 Christian BRUEL
  2007-01-05 15:49 ` Christian BRUEL
  0 siblings, 1 reply; 2+ messages in thread
From: Christian BRUEL @ 2007-01-05 15:40 UTC (permalink / raw)
  To: gcc-patches; +Cc: ubizjak, amylaar

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

Hello,

Here is a new patch for the mode flipping support that fixes two issues 
found from the previous version 
(http://gcc.gnu.org/ml/gcc-patches/2006-12/msg01645.html):

- Fix flip status in entry of exception handler.

- Temporary workaround a bug with the insertion of fpchg flip 
instruction in a delayed branch slot :

Here is a partial dump of the toggle_pr pattern that is bogusly 
speculated into a delay slot (taken from fpchg1.c added in the 
testsuite, part of the patch), although there is an explicit use of it 
in the fallthru basic block.

before the dbr trace I have :

------------------------------------------------------------------------
(assume mode is Simple in entry)

(jump_insn 18 17 20 (set (pc)
         (if_then_else (ne (reg:SI 147 t)
                 (const_int 0 [0x0]))
             (label_ref:SI 77)
             (pc))) 207 {branch_true} (insn_list:REG_DEP_TRUE 17 (nil))
     (expr_list:REG_DEAD (reg:SI 147 t)
         (expr_list:REG_BR_PROB (const_int 3300 [0xce4])
             (nil))))

;; fallthru
;; here execute instructions in "Simple float mode"
(use (reg/v:PSI 151)

...

(barrier 66 65 77)

(code_label 77 66 76 9 "" [1 uses])

(note 76 77 71 [bb 5] NOTE_INSN_BASIC_BLOCK)

(insn 71 76 38 (set (reg:PSI 151 )
         (xor:PSI (reg:PSI 151 )
             (const_int 524288 [0x80000]))) 289 {toggle_pr} (nil)
     (nil))

;; here execute instructions in "Double float mode"
(use (reg/v:PSI 151)

--------------------------------------------------------------------------------------
which ends up after fill_eager_delay_slots in reorg.c :
--------------------------------------------------------------------------------------
(insn 142 17 20 (sequence [
             (jump_insn 18 17 71 (set (pc)
                     (if_then_else (ne (reg:SI 147 t)
                             (const_int 0 [0x0]))
                         (label_ref:SI 77)
                         (pc))) 207 {branch_true} 
(insn_list:REG_DEP_TRUE 17 (nil))
                 (expr_list:REG_BR_PRED (const_int 17 [0x11])
                     (expr_list:REG_DEAD (reg:SI 147 t)
                         (expr_list:REG_BR_PROB (const_int 3300 [0xce4])
                             (nil)))))
             (insn/s 71 18 20 (set (reg:PSI 151 )
                     (xor:PSI (reg:PSI 151 )
                         (const_int 524288 [0x80000]))) 289 {toggle_pr} 
(nil)
                 (nil))
         ]) -1 (nil)
     (nil))

;; fallthru
XXX ;; here execute instructions in "Simple float mode" XXX no
(use (reg/v:PSI 151)

...

(barrier 66 65 77)

(code_label 77 66 76 9 "" [1 uses])

(note 76 77 71 [bb 5] NOTE_INSN_BASIC_BLOCK)

;; here execute instructions in "Double float mode"
(use (reg/v:PSI 151)

---------------------------------------------------------------------------

this produces the wrong result because the instruction at XXX is not 
executed with the proper mode. The problems seems to come from 
fill_eager_delay_slots in reorg.c where 'mark_referenced_resources' 
failed to register PSI 151 as used.

I would like to work on a patch for this problem separately. Any advices 
welcome.

Uros, if you get a chance to test your not-yet-committed MMX patch with 
this support, feel free to send feedbacks,

sh-superh-elf tested with check-gcc, check-c++ and applications packages 
using libraries built in -m4-300/-m4. boostraped for i686-pc-linux-gnu.

Best Regards,

Christian

[-- Attachment #2: ChangeLog.ms --]
[-- Type: text/x-troff-ms, Size: 1148 bytes --]

	* basic-block.h (pre_edge_lcm_avs): Declare
	* config/i386/i386.h (EMIT_MODE_SET): Add FLIP parameter.
	* doc/tm.texi (EMIT_MODE_SET): Idem.
	* config/sh/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.
	fpscr_toggle don't go in delay slot (temporary fix).
	* 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.
	(bb_has_complex_pred): New function
	(free_modes_infos): Idem.
	(init_modes_infos): Idem
	(add_mode_set): Idem.
	(get_mode): Idem.
	(commit_mode_sets): Idem.
	(merge_modes): Idem.
	(set_flip_status): Idem
	(test_flip_status): Idem.
	(optimize_mode_switching): Add support to maintain mode information for flipping.
	* testsuite/gcc.target/sh/sh.exp: New file.
	* testsuite/gcc.target/sh/fpchg1.c: New test.
	* testsuite/gcc.target/sh/fpchg2.c: Idem.

	
	


[-- Attachment #3: patch.4.3.ms5 --]
[-- Type: text/plain, Size: 25697 bytes --]

diff --exclude='*~' -rcpN 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 --exclude='*~' -rcpN 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	2007-01-03 08:15:50.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, FLIP, HARD_REGS_LIVE)		\
    ((MODE) != I387_CW_ANY && (MODE) != I387_CW_UNINITIALIZED		\
     ? emit_i387_cw_initialization (MODE), 0				\
     : 0)
diff --exclude='*~' -rcpN 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 --exclude='*~' -rcpN 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	2007-01-03 08:16:12.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, FLIP, HARD_REGS_LIVE) \
!   ((TARGET_SH4A_FP || TARGET_SH4_300)                     \
!    && (FLIP) ? 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 --exclude='*~' -rcpN 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	2007-01-04 15:25:18.000000000 +0100
--- gcc-4.3-20061216.mode-switch/gcc/config/sh/sh.md	2007-01-05 15:14:35.000000000 +0100
***************
*** 473,478 ****
--- 473,479 ----
  (define_attr "in_delay_slot" "yes,no"
    (cond [(eq_attr "type" "cbranch") (const_string "no")
  	 (eq_attr "type" "pcload,pcload_si") (const_string "no")
+ 	 (eq_attr "type" "fpscr_toggle") (const_string "no")
  	 (eq_attr "needs_delay_slot" "yes") (const_string "no")
  	 (eq_attr "length" "2") (const_string "yes")
  	 ] (const_string "no")))
*************** 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")])
  
--- 10067,10076 ----
    "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 --exclude='*~' -rcpN 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 --exclude='*~' -rcpN 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	2007-01-03 09:51:19.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{flip}, @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{flip} is a boolean to indicate that current mode can be set by a flipping the current one.
  @end defmac
  
  @node Target Attributes
diff --exclude='*~' -rcpN 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	2007-01-03 10:17:37.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.
!    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,493 ----
    return edge_list;
  }
  
+ /* Wrapper to allocate avin/avout and call pre_edge_lcm_avs.  */
+ 
+ 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 --exclude='*~' -rcpN 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	2007-01-02 12:56:53.000000000 +0100
--- gcc-4.3-20061216.mode-switch/gcc/mode-switching.c	2007-01-05 14:05:27.000000000 +0100
*************** static void add_seginfo (struct bb_info 
*** 95,102 ****
--- 95,278 ----
  static void reg_dies (rtx, HARD_REG_SET);
  static void reg_becomes_live (rtx, rtx, void *);
  static void make_preds_opaque (basic_block, int);
+ 
+ /* Bitmap to compute mode flipping.  */
+ 
+ static sbitmap *mode_in_flip;  /* flip in mode status for each basic blocks.  */
+ static sbitmap *mode_out_flip; /* flip out mode status for each basic blocks.  */
+ /* 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
  \f
  
+ /* Return true when one of the predecessor edges of BB is marked with
+    EDGE_COMPLEX. (similar to bb_has_eh_pred in basic_block.h).  */
+ static bool
+ bb_has_complex_pred (basic_block bb)
+ {
+   edge e;
+   edge_iterator ei;
+ 
+   FOR_EACH_EDGE (e, ei, bb->preds)
+     {
+       if (e->flags & EDGE_COMPLEX)
+ 	return true;
+     }
+   return false;
+ }
+ 
+ /* Test avin modes.  
+    if 'out' is 'true' we want to know if the mode out of the basic block
+    can be flipped. If 'in' is true we want to know if the mode entering the basic
+    block can be flipped.  */
+ 
+ static int
+ test_flip_status(int entity, basic_block bb, bool out)
+ {
+   if (out)
+     return TEST_BIT (mode_out_flip[bb->index], entity);
+   else
+     return TEST_BIT (mode_in_flip[bb->index], entity);
+ }
+ 
+ /* Merges the avin modes.  */
+ 
+ static void
+ set_flip_status (sbitmap *avin, sbitmap *avout)
+ {
+   basic_block bb;
+ 
+   FOR_EACH_BB (bb)
+     {
+       int i = bb->index;
+ 
+       /* Merge modes for each entity for each bb. 
+ 	 If multiple avin modes are set for the same bb, they are not
+ 	 exclusive and a flip may not be emitted.
+ 	 If more that 2 modes can be defined, flip may not be emitted.  */
+       if (! bb_has_complex_pred (bb))
+ 	{
+ 	  sbitmap_a_xor_b (mode_in_flip[i], mode_in_flip[i], avin[i]);
+ 	  sbitmap_a_xor_b (mode_out_flip[i], mode_out_flip[i], avout[i]);
+ 	}
+     }
+ }
+ 
+ /* 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 = XNEWVEC (int *, n_entities);
+ 
+   for (j = 0; j < n_entities; j++)
+     {
+       modes_needed[j] = XNEWVEC (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 bitmaps for modes.  */
+   mode_in_flip = sbitmap_vector_alloc (last_basic_block, n_entities);
+   mode_out_flip = sbitmap_vector_alloc (last_basic_block, n_entities);
+   sbitmap_vector_zero (mode_in_flip, last_basic_block);
+   sbitmap_vector_zero (mode_out_flip, 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 (mode_in_flip);
+   sbitmap_vector_free (mode_out_flip);
+ }
+ 
+ /* 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_flip_status (j, src_bb, true);
+ 
+       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;
+ }
+ 
  /* This function will allocate a new BBINFO structure, initialized
     with the MODE, INSN, and basic block BB parameters.  */
  
*************** 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];
--- 566,571 ----
*************** optimize_mode_switching (void)
*** 400,405 ****
--- 575,582 ----
    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 ****
--- 613,620 ----
    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 ****
--- 717,725 ----
      }
  
    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 ****
--- 729,735 ----
        /* 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--)
  	{
--- 750,760 ----
  
        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 modes for all entities.  */
!       set_flip_status (avin, avout);
  
        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;
  
--- 771,776 ----
*************** 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)
--- 779,786 ----
  
  	      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.  */
--- 795,804 ----
        sbitmap_vector_free (delete);
        sbitmap_vector_free (insert);
        clear_aux_for_edges ();
! 
!       /* Keep an edge_list for later.  */
!       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 ****
--- 806,821 ----
      {
        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_flip_status (j, bb, false);
+ 
  	  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)
  		    {
--- 824,837 ----
  		  rtx mode_set;
  
  		  start_sequence ();
! 		  EMIT_MODE_SET (entity_map[j], ptr->mode, last_mode,
! 				 ptr->regs_live);
  		  mode_set = get_insns ();
  		  end_sequence ();
  
+ 		  /* modes are are localy set.  */
+ 		  last_mode = 1;
+ 
  		  /* Insert MODE_SET only if it is nonempty.  */
  		  if (mode_set != NULL_RTX)
  		    {
*************** optimize_mode_switching (void)
*** 674,685 ****
--- 852,868 ----
        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 ();
diff --exclude='*~' -rcpN gcc-4.3-20061216/gcc/testsuite/gcc.target/sh/fpchg1.c gcc-4.3-20061216.mode-switch/gcc/testsuite/gcc.target/sh/fpchg1.c
*** gcc-4.3-20061216/gcc/testsuite/gcc.target/sh/fpchg1.c	1970-01-01 01:00:00.000000000 +0100
--- gcc-4.3-20061216.mode-switch/gcc/testsuite/gcc.target/sh/fpchg1.c	2007-01-05 12:02:23.000000000 +0100
***************
*** 0 ****
--- 1,24 ----
+ /* { dg-do run } */
+ /* { dg-options "-O1 -m4-300" } */
+ 
+ /* Check that the fpchg instruction is not moved in a delay slot if the
+    fallthru block uses the mode.  */
+ 
+ __attribute__ ((weak))
+ void barrier(void)
+ {
+ }
+ 
+ float f;
+ int i;
+ double d;
+ 
+ int main()
+ {
+   i = 4;
+ 
+   barrier();
+ 
+   i = (f + (i && f && d));
+   return i;
+ }
diff --exclude='*~' -rcpN gcc-4.3-20061216/gcc/testsuite/gcc.target/sh/fpchg2.c gcc-4.3-20061216.mode-switch/gcc/testsuite/gcc.target/sh/fpchg2.c
*** gcc-4.3-20061216/gcc/testsuite/gcc.target/sh/fpchg2.c	1970-01-01 01:00:00.000000000 +0100
--- gcc-4.3-20061216.mode-switch/gcc/testsuite/gcc.target/sh/fpchg2.c	2007-01-05 13:42:02.000000000 +0100
***************
*** 0 ****
--- 1,16 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -m4-300" } */
+ 
+ /* Make sure that fpchg is preferred over lfd.s fpscr.  */
+ /* { dg-final { scan-assembler "fpchg" } } */
+ /* { dg-final { scan-assembler-not "fpscr" } } */
+ 
+ extern float c;
+ 
+ void
+ foo(int j)
+ {
+   while (j--)
+     c++;
+ 
+ }
diff --exclude='*~' -rcpN gcc-4.3-20061216/gcc/testsuite/gcc.target/sh/sh.exp gcc-4.3-20061216.mode-switch/gcc/testsuite/gcc.target/sh/sh.exp
*** gcc-4.3-20061216/gcc/testsuite/gcc.target/sh/sh.exp	1970-01-01 01:00:00.000000000 +0100
--- gcc-4.3-20061216.mode-switch/gcc/testsuite/gcc.target/sh/sh.exp	2007-01-05 09:57:28.000000000 +0100
***************
*** 0 ****
--- 1,41 ----
+ #   Copyright (C) 2007 Free Software Foundation, Inc.
+ 
+ # This program is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation; either version 2 of the License, or
+ # (at your option) any later version.
+ # 
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ # GNU General Public License for more details.
+ # 
+ # You should have received a copy of the GNU General Public License
+ # along with this program; if not, write to the Free Software
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
+ 
+ # GCC testsuite that uses the `gcc-dg.exp' driver, just a single option, no
+ # looping over tests.
+ 
+ # Exit immediately if this isn't a IS target.
+ if ![istarget sh-*-*] then {
+   return
+ }
+ 
+ # Load support procs.
+ load_lib gcc-dg.exp
+ 
+ # If a testcase doesn't have special options, use these.
+ global DEFAULT_CFLAGS
+ if ![info exists DEFAULT_CFLAGS] then {
+     set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+ }
+ 
+ # Initialize `dg'.
+ dg-init
+ 
+ # Main loop.
+ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] "" $DEFAULT_CFLAGS
+ 
+ # All done.
+ dg-finish

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

* Re: [PATH] support to flip modes and delayed slot sh bug
  2007-01-05 15:40 [PATH] support to flip modes and delayed slot sh bug Christian BRUEL
@ 2007-01-05 15:49 ` Christian BRUEL
  0 siblings, 0 replies; 2+ messages in thread
From: Christian BRUEL @ 2007-01-05 15:49 UTC (permalink / raw)
  To: Christian BRUEL; +Cc: gcc-patches, ubizjak, amylaar

In fact, the description of the problem is not accurate. The problem 
comes after a second flip instruction is emitted in the fallthru block 
to switch from float to double.

This is either a problem with 'mark_referenced_resources' or with the 
fpscr reservation model description.

Best Regards,

Christian

Christian BRUEL wrote:
> Hello,
> 
> Here is a new patch for the mode flipping support that fixes two issues 
> found from the previous version 
> (http://gcc.gnu.org/ml/gcc-patches/2006-12/msg01645.html):
> 
> - Fix flip status in entry of exception handler.
> 
> - Temporary workaround a bug with the insertion of fpchg flip 
> instruction in a delayed branch slot :
> 
> Here is a partial dump of the toggle_pr pattern that is bogusly 
> speculated into a delay slot (taken from fpchg1.c added in the 
> testsuite, part of the patch), although there is an explicit use of it 
> in the fallthru basic block.
> 
> before the dbr trace I have :
> 
> ------------------------------------------------------------------------
> (assume mode is Simple in entry)
> 
> (jump_insn 18 17 20 (set (pc)
>         (if_then_else (ne (reg:SI 147 t)
>                 (const_int 0 [0x0]))
>             (label_ref:SI 77)
>             (pc))) 207 {branch_true} (insn_list:REG_DEP_TRUE 17 (nil))
>     (expr_list:REG_DEAD (reg:SI 147 t)
>         (expr_list:REG_BR_PROB (const_int 3300 [0xce4])
>             (nil))))
> 
> ;; fallthru
> ;; here execute instructions in "Simple float mode"
> (use (reg/v:PSI 151)
> 
> ...
> 
> (barrier 66 65 77)
> 
> (code_label 77 66 76 9 "" [1 uses])
> 
> (note 76 77 71 [bb 5] NOTE_INSN_BASIC_BLOCK)
> 
> (insn 71 76 38 (set (reg:PSI 151 )
>         (xor:PSI (reg:PSI 151 )
>             (const_int 524288 [0x80000]))) 289 {toggle_pr} (nil)
>     (nil))
> 
> ;; here execute instructions in "Double float mode"
> (use (reg/v:PSI 151)
> 
> -------------------------------------------------------------------------------------- 
> 
> which ends up after fill_eager_delay_slots in reorg.c :
> -------------------------------------------------------------------------------------- 
> 
> (insn 142 17 20 (sequence [
>             (jump_insn 18 17 71 (set (pc)
>                     (if_then_else (ne (reg:SI 147 t)
>                             (const_int 0 [0x0]))
>                         (label_ref:SI 77)
>                         (pc))) 207 {branch_true} (insn_list:REG_DEP_TRUE 
> 17 (nil))
>                 (expr_list:REG_BR_PRED (const_int 17 [0x11])
>                     (expr_list:REG_DEAD (reg:SI 147 t)
>                         (expr_list:REG_BR_PROB (const_int 3300 [0xce4])
>                             (nil)))))
>             (insn/s 71 18 20 (set (reg:PSI 151 )
>                     (xor:PSI (reg:PSI 151 )
>                         (const_int 524288 [0x80000]))) 289 {toggle_pr} 
> (nil)
>                 (nil))
>         ]) -1 (nil)
>     (nil))
> 
> ;; fallthru
> XXX ;; here execute instructions in "Simple float mode" XXX no
> (use (reg/v:PSI 151)
> 
> ...
> 
> (barrier 66 65 77)
> 
> (code_label 77 66 76 9 "" [1 uses])
> 
> (note 76 77 71 [bb 5] NOTE_INSN_BASIC_BLOCK)
> 
> ;; here execute instructions in "Double float mode"
> (use (reg/v:PSI 151)
> 
> ---------------------------------------------------------------------------
> 
> this produces the wrong result because the instruction at XXX is not 
> executed with the proper mode. The problems seems to come from 
> fill_eager_delay_slots in reorg.c where 'mark_referenced_resources' 
> failed to register PSI 151 as used.
> 
> I would like to work on a patch for this problem separately. Any advices 
> welcome.
> 
> Uros, if you get a chance to test your not-yet-committed MMX patch with 
> this support, feel free to send feedbacks,
> 
> sh-superh-elf tested with check-gcc, check-c++ and applications packages 
> using libraries built in -m4-300/-m4. boostraped for i686-pc-linux-gnu.
> 
> Best Regards,
> 
> Christian
> 
> 
> ------------------------------------------------------------------------
> 
> 	* basic-block.h (pre_edge_lcm_avs): Declare
> 	* config/i386/i386.h (EMIT_MODE_SET): Add FLIP parameter.
> 	* doc/tm.texi (EMIT_MODE_SET): Idem.
> 	* config/sh/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.
> 	fpscr_toggle don't go in delay slot (temporary fix).
> 	* 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.
> 	(bb_has_complex_pred): New function
> 	(free_modes_infos): Idem.
> 	(init_modes_infos): Idem
> 	(add_mode_set): Idem.
> 	(get_mode): Idem.
> 	(commit_mode_sets): Idem.
> 	(merge_modes): Idem.
> 	(set_flip_status): Idem
> 	(test_flip_status): Idem.
> 	(optimize_mode_switching): Add support to maintain mode information for flipping.
> 	* testsuite/gcc.target/sh/sh.exp: New file.
> 	* testsuite/gcc.target/sh/fpchg1.c: New test.
> 	* testsuite/gcc.target/sh/fpchg2.c: Idem.
> 
> 	
> 	
> 
> 
> 
> ------------------------------------------------------------------------
> 
> diff --exclude='*~' -rcpN 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 --exclude='*~' -rcpN 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	2007-01-03 08:15:50.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, FLIP, HARD_REGS_LIVE)		\
>     ((MODE) != I387_CW_ANY && (MODE) != I387_CW_UNINITIALIZED		\
>      ? emit_i387_cw_initialization (MODE), 0				\
>      : 0)
> diff --exclude='*~' -rcpN 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 --exclude='*~' -rcpN 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	2007-01-03 08:16:12.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, FLIP, HARD_REGS_LIVE) \
> !   ((TARGET_SH4A_FP || TARGET_SH4_300)                     \
> !    && (FLIP) ? 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 --exclude='*~' -rcpN 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	2007-01-04 15:25:18.000000000 +0100
> --- gcc-4.3-20061216.mode-switch/gcc/config/sh/sh.md	2007-01-05 15:14:35.000000000 +0100
> ***************
> *** 473,478 ****
> --- 473,479 ----
>   (define_attr "in_delay_slot" "yes,no"
>     (cond [(eq_attr "type" "cbranch") (const_string "no")
>   	 (eq_attr "type" "pcload,pcload_si") (const_string "no")
> + 	 (eq_attr "type" "fpscr_toggle") (const_string "no")
>   	 (eq_attr "needs_delay_slot" "yes") (const_string "no")
>   	 (eq_attr "length" "2") (const_string "yes")
>   	 ] (const_string "no")))
> *************** 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")])
>   
> --- 10067,10076 ----
>     "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 --exclude='*~' -rcpN 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 --exclude='*~' -rcpN 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	2007-01-03 09:51:19.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{flip}, @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{flip} is a boolean to indicate that current mode can be set by a flipping the current one.
>   @end defmac
>   
>   @node Target Attributes
> diff --exclude='*~' -rcpN 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	2007-01-03 10:17:37.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.
> !    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,493 ----
>     return edge_list;
>   }
>   
> + /* Wrapper to allocate avin/avout and call pre_edge_lcm_avs.  */
> + 
> + 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 --exclude='*~' -rcpN 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	2007-01-02 12:56:53.000000000 +0100
> --- gcc-4.3-20061216.mode-switch/gcc/mode-switching.c	2007-01-05 14:05:27.000000000 +0100
> *************** static void add_seginfo (struct bb_info 
> *** 95,102 ****
> --- 95,278 ----
>   static void reg_dies (rtx, HARD_REG_SET);
>   static void reg_becomes_live (rtx, rtx, void *);
>   static void make_preds_opaque (basic_block, int);
> + 
> + /* Bitmap to compute mode flipping.  */
> + 
> + static sbitmap *mode_in_flip;  /* flip in mode status for each basic blocks.  */
> + static sbitmap *mode_out_flip; /* flip out mode status for each basic blocks.  */
> + /* 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
>   \f
>   
> + /* Return true when one of the predecessor edges of BB is marked with
> +    EDGE_COMPLEX. (similar to bb_has_eh_pred in basic_block.h).  */
> + static bool
> + bb_has_complex_pred (basic_block bb)
> + {
> +   edge e;
> +   edge_iterator ei;
> + 
> +   FOR_EACH_EDGE (e, ei, bb->preds)
> +     {
> +       if (e->flags & EDGE_COMPLEX)
> + 	return true;
> +     }
> +   return false;
> + }
> + 
> + /* Test avin modes.  
> +    if 'out' is 'true' we want to know if the mode out of the basic block
> +    can be flipped. If 'in' is true we want to know if the mode entering the basic
> +    block can be flipped.  */
> + 
> + static int
> + test_flip_status(int entity, basic_block bb, bool out)
> + {
> +   if (out)
> +     return TEST_BIT (mode_out_flip[bb->index], entity);
> +   else
> +     return TEST_BIT (mode_in_flip[bb->index], entity);
> + }
> + 
> + /* Merges the avin modes.  */
> + 
> + static void
> + set_flip_status (sbitmap *avin, sbitmap *avout)
> + {
> +   basic_block bb;
> + 
> +   FOR_EACH_BB (bb)
> +     {
> +       int i = bb->index;
> + 
> +       /* Merge modes for each entity for each bb. 
> + 	 If multiple avin modes are set for the same bb, they are not
> + 	 exclusive and a flip may not be emitted.
> + 	 If more that 2 modes can be defined, flip may not be emitted.  */
> +       if (! bb_has_complex_pred (bb))
> + 	{
> + 	  sbitmap_a_xor_b (mode_in_flip[i], mode_in_flip[i], avin[i]);
> + 	  sbitmap_a_xor_b (mode_out_flip[i], mode_out_flip[i], avout[i]);
> + 	}
> +     }
> + }
> + 
> + /* 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 = XNEWVEC (int *, n_entities);
> + 
> +   for (j = 0; j < n_entities; j++)
> +     {
> +       modes_needed[j] = XNEWVEC (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 bitmaps for modes.  */
> +   mode_in_flip = sbitmap_vector_alloc (last_basic_block, n_entities);
> +   mode_out_flip = sbitmap_vector_alloc (last_basic_block, n_entities);
> +   sbitmap_vector_zero (mode_in_flip, last_basic_block);
> +   sbitmap_vector_zero (mode_out_flip, 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 (mode_in_flip);
> +   sbitmap_vector_free (mode_out_flip);
> + }
> + 
> + /* 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_flip_status (j, src_bb, true);
> + 
> +       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;
> + }
> + 
>   /* This function will allocate a new BBINFO structure, initialized
>      with the MODE, INSN, and basic block BB parameters.  */
>   
> *************** 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];
> --- 566,571 ----
> *************** optimize_mode_switching (void)
> *** 400,405 ****
> --- 575,582 ----
>     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 ****
> --- 613,620 ----
>     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 ****
> --- 717,725 ----
>       }
>   
>     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 ****
> --- 729,735 ----
>         /* 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--)
>   	{
> --- 750,760 ----
>   
>         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 modes for all entities.  */
> !       set_flip_status (avin, avout);
>   
>         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;
>   
> --- 771,776 ----
> *************** 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)
> --- 779,786 ----
>   
>   	      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.  */
> --- 795,804 ----
>         sbitmap_vector_free (delete);
>         sbitmap_vector_free (insert);
>         clear_aux_for_edges ();
> ! 
> !       /* Keep an edge_list for later.  */
> !       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 ****
> --- 806,821 ----
>       {
>         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_flip_status (j, bb, false);
> + 
>   	  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)
>   		    {
> --- 824,837 ----
>   		  rtx mode_set;
>   
>   		  start_sequence ();
> ! 		  EMIT_MODE_SET (entity_map[j], ptr->mode, last_mode,
> ! 				 ptr->regs_live);
>   		  mode_set = get_insns ();
>   		  end_sequence ();
>   
> + 		  /* modes are are localy set.  */
> + 		  last_mode = 1;
> + 
>   		  /* Insert MODE_SET only if it is nonempty.  */
>   		  if (mode_set != NULL_RTX)
>   		    {
> *************** optimize_mode_switching (void)
> *** 674,685 ****
> --- 852,868 ----
>         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 ();
> diff --exclude='*~' -rcpN gcc-4.3-20061216/gcc/testsuite/gcc.target/sh/fpchg1.c gcc-4.3-20061216.mode-switch/gcc/testsuite/gcc.target/sh/fpchg1.c
> *** gcc-4.3-20061216/gcc/testsuite/gcc.target/sh/fpchg1.c	1970-01-01 01:00:00.000000000 +0100
> --- gcc-4.3-20061216.mode-switch/gcc/testsuite/gcc.target/sh/fpchg1.c	2007-01-05 12:02:23.000000000 +0100
> ***************
> *** 0 ****
> --- 1,24 ----
> + /* { dg-do run } */
> + /* { dg-options "-O1 -m4-300" } */
> + 
> + /* Check that the fpchg instruction is not moved in a delay slot if the
> +    fallthru block uses the mode.  */
> + 
> + __attribute__ ((weak))
> + void barrier(void)
> + {
> + }
> + 
> + float f;
> + int i;
> + double d;
> + 
> + int main()
> + {
> +   i = 4;
> + 
> +   barrier();
> + 
> +   i = (f + (i && f && d));
> +   return i;
> + }
> diff --exclude='*~' -rcpN gcc-4.3-20061216/gcc/testsuite/gcc.target/sh/fpchg2.c gcc-4.3-20061216.mode-switch/gcc/testsuite/gcc.target/sh/fpchg2.c
> *** gcc-4.3-20061216/gcc/testsuite/gcc.target/sh/fpchg2.c	1970-01-01 01:00:00.000000000 +0100
> --- gcc-4.3-20061216.mode-switch/gcc/testsuite/gcc.target/sh/fpchg2.c	2007-01-05 13:42:02.000000000 +0100
> ***************
> *** 0 ****
> --- 1,16 ----
> + /* { dg-do compile } */
> + /* { dg-options "-O2 -m4-300" } */
> + 
> + /* Make sure that fpchg is preferred over lfd.s fpscr.  */
> + /* { dg-final { scan-assembler "fpchg" } } */
> + /* { dg-final { scan-assembler-not "fpscr" } } */
> + 
> + extern float c;
> + 
> + void
> + foo(int j)
> + {
> +   while (j--)
> +     c++;
> + 
> + }
> diff --exclude='*~' -rcpN gcc-4.3-20061216/gcc/testsuite/gcc.target/sh/sh.exp gcc-4.3-20061216.mode-switch/gcc/testsuite/gcc.target/sh/sh.exp
> *** gcc-4.3-20061216/gcc/testsuite/gcc.target/sh/sh.exp	1970-01-01 01:00:00.000000000 +0100
> --- gcc-4.3-20061216.mode-switch/gcc/testsuite/gcc.target/sh/sh.exp	2007-01-05 09:57:28.000000000 +0100
> ***************
> *** 0 ****
> --- 1,41 ----
> + #   Copyright (C) 2007 Free Software Foundation, Inc.
> + 
> + # This program is free software; you can redistribute it and/or modify
> + # it under the terms of the GNU General Public License as published by
> + # the Free Software Foundation; either version 2 of the License, or
> + # (at your option) any later version.
> + # 
> + # This program is distributed in the hope that it will be useful,
> + # but WITHOUT ANY WARRANTY; without even the implied warranty of
> + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + # GNU General Public License for more details.
> + # 
> + # You should have received a copy of the GNU General Public License
> + # along with this program; if not, write to the Free Software
> + # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
> + 
> + # GCC testsuite that uses the `gcc-dg.exp' driver, just a single option, no
> + # looping over tests.
> + 
> + # Exit immediately if this isn't a IS target.
> + if ![istarget sh-*-*] then {
> +   return
> + }
> + 
> + # Load support procs.
> + load_lib gcc-dg.exp
> + 
> + # If a testcase doesn't have special options, use these.
> + global DEFAULT_CFLAGS
> + if ![info exists DEFAULT_CFLAGS] then {
> +     set DEFAULT_CFLAGS " -ansi -pedantic-errors"
> + }
> + 
> + # Initialize `dg'.
> + dg-init
> + 
> + # Main loop.
> + dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] "" $DEFAULT_CFLAGS
> + 
> + # All done.
> + dg-finish

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

end of thread, other threads:[~2007-01-05 15:49 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-01-05 15:40 [PATH] support to flip modes and delayed slot sh bug Christian BRUEL
2007-01-05 15:49 ` Christian BRUEL

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