This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: One more optimize_mode_switching() problem
On Feb 7, 2001, Richard Henderson <rth@redhat.com> wrote:
> On Wed, Feb 07, 2001 at 04:13:24PM -0200, Alexandre Oliva wrote:
>> If the last insn of a function is a DFmode store, and prologue and
>> epilogue must run in single mode, the mode switching would be inserted
>> before the store, because there was not NOTE_INSN_BASIC_BLOCK after it
>> that ptr->insn_ptr could be pointed to.
> This doesn't seem right at all. If you need to change modes
> on exit of a function, you should be using insert_insn_on_edge
> to the EXIT_BLOCK.
Ok. I bit the bullet and ended up fixing it by implementing the
optimization I had suggested in my previous message too. I find it a
bit hackish, but I don't see a cleaner way to get the entry mode of
the exit block taken into account. How do you feel about this? Ok to
install, if it survives a battery of testing?
Index: gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* lcm.c (compute_earliest): Let EXIT_BLOCK be handled as a regular
basic block.
(optimize_mode_switching) [NORMAL_MODE]: Set up EXIT_BLOCK as a
regular basic block, and arrange for all edges into it to switch
to normal mode.
Index: gcc/lcm.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/lcm.c,v
retrieving revision 1.22
diff -u -p -r1.22 lcm.c
--- gcc/lcm.c 2001/02/07 17:44:47 1.22
+++ gcc/lcm.c 2001/02/09 16:11:08
@@ -205,7 +205,11 @@ compute_earliest (edge_list, n_exprs, an
sbitmap_copy (earliest[x], antin[succ->index]);
else
{
- if (succ == EXIT_BLOCK_PTR)
+ /* We refer to the EXIT_BLOCK index, instead of testing for
+ EXIT_BLOCK_PTR, so that EXIT_BLOCK_PTR's index can be
+ changed so as to pretend it's a regular block, so that
+ its antin can be taken into account. */
+ if (succ->index == EXIT_BLOCK)
sbitmap_zero (earliest[x]);
else
{
@@ -1019,6 +1023,10 @@ optimize_mode_switching (file)
int n_entities;
int max_num_modes = 0;
+#ifdef NORMAL_MODE
+ n_basic_blocks++;
+#endif
+
for (e = N_ENTITIES - 1, n_entities = 0; e >= 0; e--)
if (OPTIMIZE_MODE_SWITCHING (e))
{
@@ -1030,9 +1038,21 @@ optimize_mode_switching (file)
max_num_modes = num_modes[e];
}
+#ifdef NORMAL_MODE
+ n_basic_blocks--;
+#endif
+
if (! n_entities)
return 0;
+#ifdef NORMAL_MODE
+ n_basic_blocks++;
+ if (VARRAY_SIZE (basic_block_info) < n_basic_blocks)
+ VARRAY_GROW (basic_block_info, n_basic_blocks);
+ BASIC_BLOCK (n_basic_blocks - 1) = EXIT_BLOCK_PTR;
+ EXIT_BLOCK_PTR->index = n_basic_blocks - 1;
+#endif
+
/* Create the bitmap vectors. */
antic = sbitmap_vector_alloc (n_basic_blocks, n_entities);
@@ -1087,29 +1107,6 @@ optimize_mode_switching (file)
}
}
- /* If this is a predecessor of the exit block, and we must
- force a mode on exit, make note of that. */
-#ifdef NORMAL_MODE
- if (NORMAL_MODE (e) != no_mode && last_mode != NORMAL_MODE (e))
- for (eg = BASIC_BLOCK (bb)->succ; eg; eg = eg->succ_next)
- if (eg->dest == EXIT_BLOCK_PTR)
- {
- rtx insn = BLOCK_END (bb);
-
- /* Find the last insn before a USE and/or JUMP. */
- while ((GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == USE)
- || GET_CODE (insn) == JUMP_INSN)
- insn = PREV_INSN (insn);
- if (insn != BLOCK_END (bb) && NEXT_INSN (insn))
- insn = NEXT_INSN (insn);
- last_mode = NORMAL_MODE (e);
- add_seginfo (info + bb,
- new_seginfo (last_mode, insn, bb, live_now));
- RESET_BIT (transp[bb], j);
- }
-#endif
-
info[bb].computing = last_mode;
/* Check for blocks without ANY mode requirements. */
if (last_mode == no_mode)
@@ -1149,6 +1146,9 @@ optimize_mode_switching (file)
info[bb].seginfo->mode = no_mode;
}
}
+
+ bb = n_basic_blocks - 1;
+ info[bb].seginfo->mode = mode;
}
}
#endif /* NORMAL_MODE */
@@ -1253,10 +1253,41 @@ optimize_mode_switching (file)
free_edge_list (edge_list);
}
+#ifdef NORMAL_MODE
+ n_basic_blocks--;
+ VARRAY_POP (basic_block_info);
+ EXIT_BLOCK_PTR->index = EXIT_BLOCK;
+#endif
+
/* Now output the remaining mode sets in all the segments. */
for (j = n_entities - 1; j >= 0; j--)
{
int no_mode = num_modes[entity_map[j]];
+
+#ifdef NORMAL_MODE
+ if (bb_info[j][n_basic_blocks].seginfo->mode != no_mode)
+ {
+ edge eg;
+ struct seginfo *ptr = bb_info[j][n_basic_blocks].seginfo;
+
+ for (eg = EXIT_BLOCK_PTR->pred; eg; eg = eg->pred_next)
+ {
+ rtx mode_set;
+
+ if (bb_info[j][eg->src->index].computing == ptr->mode)
+ continue;
+
+ start_sequence ();
+ EMIT_MODE_SET (entity_map[j], ptr->mode, ptr->regs_live);
+ mode_set = gen_sequence ();
+ end_sequence ();
+
+ need_commit = 1;
+ insert_insn_on_edge (mode_set, eg);
+ }
+
+ }
+#endif
for (bb = n_basic_blocks - 1; bb >= 0; bb--)
{
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist *Please* write to mailing lists, not to me