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