1169689Skan/* CPU mode switching
2169689Skan   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3169689Skan   Free Software Foundation, Inc.
4169689Skan
5169689SkanThis file is part of GCC.
6169689Skan
7169689SkanGCC is free software; you can redistribute it and/or modify it under
8169689Skanthe terms of the GNU General Public License as published by the Free
9169689SkanSoftware Foundation; either version 2, or (at your option) any later
10169689Skanversion.
11169689Skan
12169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
13169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
14169689SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15169689Skanfor more details.
16169689Skan
17169689SkanYou should have received a copy of the GNU General Public License
18169689Skanalong with GCC; see the file COPYING.  If not, write to the Free
19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan02110-1301, USA.  */
21169689Skan
22169689Skan#include "config.h"
23169689Skan#include "system.h"
24169689Skan#include "coretypes.h"
25169689Skan#include "tm.h"
26169689Skan#include "rtl.h"
27169689Skan#include "regs.h"
28169689Skan#include "hard-reg-set.h"
29169689Skan#include "flags.h"
30169689Skan#include "real.h"
31169689Skan#include "insn-config.h"
32169689Skan#include "recog.h"
33169689Skan#include "basic-block.h"
34169689Skan#include "output.h"
35169689Skan#include "tm_p.h"
36169689Skan#include "function.h"
37169689Skan#include "tree-pass.h"
38169689Skan#include "timevar.h"
39169689Skan
40169689Skan/* We want target macros for the mode switching code to be able to refer
41169689Skan   to instruction attribute values.  */
42169689Skan#include "insn-attr.h"
43169689Skan
44169689Skan#ifdef OPTIMIZE_MODE_SWITCHING
45169689Skan
46169689Skan/* The algorithm for setting the modes consists of scanning the insn list
47169689Skan   and finding all the insns which require a specific mode.  Each insn gets
48169689Skan   a unique struct seginfo element.  These structures are inserted into a list
49169689Skan   for each basic block.  For each entity, there is an array of bb_info over
50169689Skan   the flow graph basic blocks (local var 'bb_info'), and contains a list
51169689Skan   of all insns within that basic block, in the order they are encountered.
52169689Skan
53169689Skan   For each entity, any basic block WITHOUT any insns requiring a specific
54169689Skan   mode are given a single entry, without a mode.  (Each basic block
55169689Skan   in the flow graph must have at least one entry in the segment table.)
56169689Skan
57169689Skan   The LCM algorithm is then run over the flow graph to determine where to
58169689Skan   place the sets to the highest-priority value in respect of first the first
59169689Skan   insn in any one block.  Any adjustments required to the transparency
60169689Skan   vectors are made, then the next iteration starts for the next-lower
61169689Skan   priority mode, till for each entity all modes are exhausted.
62169689Skan
63169689Skan   More details are located in the code for optimize_mode_switching().  */
64169689Skan
65169689Skan/* This structure contains the information for each insn which requires
66169689Skan   either single or double mode to be set.
67169689Skan   MODE is the mode this insn must be executed in.
68169689Skan   INSN_PTR is the insn to be executed (may be the note that marks the
69169689Skan   beginning of a basic block).
70169689Skan   BBNUM is the flow graph basic block this insn occurs in.
71169689Skan   NEXT is the next insn in the same basic block.  */
72169689Skanstruct seginfo
73169689Skan{
74169689Skan  int mode;
75169689Skan  rtx insn_ptr;
76169689Skan  int bbnum;
77169689Skan  struct seginfo *next;
78169689Skan  HARD_REG_SET regs_live;
79169689Skan};
80169689Skan
81169689Skanstruct bb_info
82169689Skan{
83169689Skan  struct seginfo *seginfo;
84169689Skan  int computing;
85169689Skan};
86169689Skan
87169689Skan/* These bitmaps are used for the LCM algorithm.  */
88169689Skan
89169689Skanstatic sbitmap *antic;
90169689Skanstatic sbitmap *transp;
91169689Skanstatic sbitmap *comp;
92169689Skan
93169689Skanstatic struct seginfo * new_seginfo (int, rtx, int, HARD_REG_SET);
94169689Skanstatic void add_seginfo (struct bb_info *, struct seginfo *);
95169689Skanstatic void reg_dies (rtx, HARD_REG_SET);
96169689Skanstatic void reg_becomes_live (rtx, rtx, void *);
97169689Skanstatic void make_preds_opaque (basic_block, int);
98169689Skan
99169689Skan
100169689Skan/* This function will allocate a new BBINFO structure, initialized
101169689Skan   with the MODE, INSN, and basic block BB parameters.  */
102169689Skan
103169689Skanstatic struct seginfo *
104169689Skannew_seginfo (int mode, rtx insn, int bb, HARD_REG_SET regs_live)
105169689Skan{
106169689Skan  struct seginfo *ptr;
107169689Skan  ptr = XNEW (struct seginfo);
108169689Skan  ptr->mode = mode;
109169689Skan  ptr->insn_ptr = insn;
110169689Skan  ptr->bbnum = bb;
111169689Skan  ptr->next = NULL;
112169689Skan  COPY_HARD_REG_SET (ptr->regs_live, regs_live);
113169689Skan  return ptr;
114169689Skan}
115169689Skan
116169689Skan/* Add a seginfo element to the end of a list.
117169689Skan   HEAD is a pointer to the list beginning.
118169689Skan   INFO is the structure to be linked in.  */
119169689Skan
120169689Skanstatic void
121169689Skanadd_seginfo (struct bb_info *head, struct seginfo *info)
122169689Skan{
123169689Skan  struct seginfo *ptr;
124169689Skan
125169689Skan  if (head->seginfo == NULL)
126169689Skan    head->seginfo = info;
127169689Skan  else
128169689Skan    {
129169689Skan      ptr = head->seginfo;
130169689Skan      while (ptr->next != NULL)
131169689Skan	ptr = ptr->next;
132169689Skan      ptr->next = info;
133169689Skan    }
134169689Skan}
135169689Skan
136169689Skan/* Make all predecessors of basic block B opaque, recursively, till we hit
137169689Skan   some that are already non-transparent, or an edge where aux is set; that
138169689Skan   denotes that a mode set is to be done on that edge.
139169689Skan   J is the bit number in the bitmaps that corresponds to the entity that
140169689Skan   we are currently handling mode-switching for.  */
141169689Skan
142169689Skanstatic void
143169689Skanmake_preds_opaque (basic_block b, int j)
144169689Skan{
145169689Skan  edge e;
146169689Skan  edge_iterator ei;
147169689Skan
148169689Skan  FOR_EACH_EDGE (e, ei, b->preds)
149169689Skan    {
150169689Skan      basic_block pb = e->src;
151169689Skan
152169689Skan      if (e->aux || ! TEST_BIT (transp[pb->index], j))
153169689Skan	continue;
154169689Skan
155169689Skan      RESET_BIT (transp[pb->index], j);
156169689Skan      make_preds_opaque (pb, j);
157169689Skan    }
158169689Skan}
159169689Skan
160169689Skan/* Record in LIVE that register REG died.  */
161169689Skan
162169689Skanstatic void
163169689Skanreg_dies (rtx reg, HARD_REG_SET live)
164169689Skan{
165169689Skan  int regno, nregs;
166169689Skan
167169689Skan  if (!REG_P (reg))
168169689Skan    return;
169169689Skan
170169689Skan  regno = REGNO (reg);
171169689Skan  if (regno < FIRST_PSEUDO_REGISTER)
172169689Skan    for (nregs = hard_regno_nregs[regno][GET_MODE (reg)] - 1; nregs >= 0;
173169689Skan	 nregs--)
174169689Skan      CLEAR_HARD_REG_BIT (live, regno + nregs);
175169689Skan}
176169689Skan
177169689Skan/* Record in LIVE that register REG became live.
178169689Skan   This is called via note_stores.  */
179169689Skan
180169689Skanstatic void
181169689Skanreg_becomes_live (rtx reg, rtx setter ATTRIBUTE_UNUSED, void *live)
182169689Skan{
183169689Skan  int regno, nregs;
184169689Skan
185169689Skan  if (GET_CODE (reg) == SUBREG)
186169689Skan    reg = SUBREG_REG (reg);
187169689Skan
188169689Skan  if (!REG_P (reg))
189169689Skan    return;
190169689Skan
191169689Skan  regno = REGNO (reg);
192169689Skan  if (regno < FIRST_PSEUDO_REGISTER)
193169689Skan    for (nregs = hard_regno_nregs[regno][GET_MODE (reg)] - 1; nregs >= 0;
194169689Skan	 nregs--)
195169689Skan      SET_HARD_REG_BIT (* (HARD_REG_SET *) live, regno + nregs);
196169689Skan}
197169689Skan
198169689Skan/* Make sure if MODE_ENTRY is defined the MODE_EXIT is defined
199169689Skan   and vice versa.  */
200169689Skan#if defined (MODE_ENTRY) != defined (MODE_EXIT)
201169689Skan #error "Both MODE_ENTRY and MODE_EXIT must be defined"
202169689Skan#endif
203169689Skan
204169689Skan#if defined (MODE_ENTRY) && defined (MODE_EXIT)
205169689Skan/* Split the fallthrough edge to the exit block, so that we can note
206169689Skan   that there NORMAL_MODE is required.  Return the new block if it's
207169689Skan   inserted before the exit block.  Otherwise return null.  */
208169689Skan
209169689Skanstatic basic_block
210169689Skancreate_pre_exit (int n_entities, int *entity_map, const int *num_modes)
211169689Skan{
212169689Skan  edge eg;
213169689Skan  edge_iterator ei;
214169689Skan  basic_block pre_exit;
215169689Skan
216169689Skan  /* The only non-call predecessor at this stage is a block with a
217169689Skan     fallthrough edge; there can be at most one, but there could be
218169689Skan     none at all, e.g. when exit is called.  */
219169689Skan  pre_exit = 0;
220169689Skan  FOR_EACH_EDGE (eg, ei, EXIT_BLOCK_PTR->preds)
221169689Skan    if (eg->flags & EDGE_FALLTHRU)
222169689Skan      {
223169689Skan	basic_block src_bb = eg->src;
224169689Skan	regset live_at_end = src_bb->il.rtl->global_live_at_end;
225169689Skan	rtx last_insn, ret_reg;
226169689Skan
227169689Skan	gcc_assert (!pre_exit);
228169689Skan	/* If this function returns a value at the end, we have to
229169689Skan	   insert the final mode switch before the return value copy
230169689Skan	   to its hard register.  */
231169689Skan	if (EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 1
232169689Skan	    && NONJUMP_INSN_P ((last_insn = BB_END (src_bb)))
233169689Skan	    && GET_CODE (PATTERN (last_insn)) == USE
234169689Skan	    && GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG)
235169689Skan	  {
236169689Skan	    int ret_start = REGNO (ret_reg);
237169689Skan	    int nregs = hard_regno_nregs[ret_start][GET_MODE (ret_reg)];
238169689Skan	    int ret_end = ret_start + nregs;
239169689Skan	    int short_block = 0;
240169689Skan	    int maybe_builtin_apply = 0;
241169689Skan	    int forced_late_switch = 0;
242169689Skan	    rtx before_return_copy;
243169689Skan
244169689Skan	    do
245169689Skan	      {
246169689Skan		rtx return_copy = PREV_INSN (last_insn);
247169689Skan		rtx return_copy_pat, copy_reg;
248169689Skan		int copy_start, copy_num;
249169689Skan		int j;
250169689Skan
251169689Skan		if (INSN_P (return_copy))
252169689Skan		  {
253169689Skan		    if (GET_CODE (PATTERN (return_copy)) == USE
254169689Skan			&& GET_CODE (XEXP (PATTERN (return_copy), 0)) == REG
255169689Skan			&& (FUNCTION_VALUE_REGNO_P
256169689Skan			    (REGNO (XEXP (PATTERN (return_copy), 0)))))
257169689Skan		      {
258169689Skan			maybe_builtin_apply = 1;
259169689Skan			last_insn = return_copy;
260169689Skan			continue;
261169689Skan		      }
262169689Skan		    /* If the return register is not (in its entirety)
263169689Skan		       likely spilled, the return copy might be
264169689Skan		       partially or completely optimized away.  */
265169689Skan		    return_copy_pat = single_set (return_copy);
266169689Skan		    if (!return_copy_pat)
267169689Skan		      {
268169689Skan			return_copy_pat = PATTERN (return_copy);
269169689Skan			if (GET_CODE (return_copy_pat) != CLOBBER)
270169689Skan			  break;
271169689Skan		      }
272169689Skan		    copy_reg = SET_DEST (return_copy_pat);
273169689Skan		    if (GET_CODE (copy_reg) == REG)
274169689Skan		      copy_start = REGNO (copy_reg);
275169689Skan		    else if (GET_CODE (copy_reg) == SUBREG
276169689Skan			     && GET_CODE (SUBREG_REG (copy_reg)) == REG)
277169689Skan		      copy_start = REGNO (SUBREG_REG (copy_reg));
278169689Skan		    else
279169689Skan		      break;
280169689Skan		    if (copy_start >= FIRST_PSEUDO_REGISTER)
281169689Skan		      break;
282169689Skan		    copy_num
283169689Skan		      = hard_regno_nregs[copy_start][GET_MODE (copy_reg)];
284169689Skan
285169689Skan		    /* If the return register is not likely spilled, - as is
286169689Skan		       the case for floating point on SH4 - then it might
287169689Skan		       be set by an arithmetic operation that needs a
288169689Skan		       different mode than the exit block.  */
289169689Skan		    for (j = n_entities - 1; j >= 0; j--)
290169689Skan		      {
291169689Skan			int e = entity_map[j];
292169689Skan			int mode = MODE_NEEDED (e, return_copy);
293169689Skan
294169689Skan			if (mode != num_modes[e] && mode != MODE_EXIT (e))
295169689Skan			  break;
296169689Skan		      }
297169689Skan		    if (j >= 0)
298169689Skan		      {
299169689Skan			/* For the SH4, floating point loads depend on fpscr,
300169689Skan			   thus we might need to put the final mode switch
301169689Skan			   after the return value copy.  That is still OK,
302169689Skan			   because a floating point return value does not
303169689Skan			   conflict with address reloads.  */
304169689Skan			if (copy_start >= ret_start
305169689Skan			    && copy_start + copy_num <= ret_end
306169689Skan			    && OBJECT_P (SET_SRC (return_copy_pat)))
307169689Skan			  forced_late_switch = 1;
308169689Skan			break;
309169689Skan		      }
310169689Skan
311169689Skan		    if (copy_start >= ret_start
312169689Skan			&& copy_start + copy_num <= ret_end)
313169689Skan		      nregs -= copy_num;
314169689Skan		    else if (!maybe_builtin_apply
315169689Skan			     || !FUNCTION_VALUE_REGNO_P (copy_start))
316169689Skan		      break;
317169689Skan		    last_insn = return_copy;
318169689Skan		  }
319169689Skan		/* ??? Exception handling can lead to the return value
320169689Skan		   copy being already separated from the return value use,
321169689Skan		   as in  unwind-dw2.c .
322169689Skan		   Similarly, conditionally returning without a value,
323169689Skan		   and conditionally using builtin_return can lead to an
324169689Skan		   isolated use.  */
325169689Skan		if (return_copy == BB_HEAD (src_bb))
326169689Skan		  {
327169689Skan		    short_block = 1;
328169689Skan		    break;
329169689Skan		  }
330169689Skan		last_insn = return_copy;
331169689Skan	      }
332169689Skan	    while (nregs);
333169689Skan
334169689Skan	    /* If we didn't see a full return value copy, verify that there
335169689Skan	       is a plausible reason for this.  If some, but not all of the
336169689Skan	       return register is likely spilled, we can expect that there
337169689Skan	       is a copy for the likely spilled part.  */
338169689Skan	    gcc_assert (!nregs
339169689Skan			|| forced_late_switch
340169689Skan			|| short_block
341169689Skan			|| !(CLASS_LIKELY_SPILLED_P
342169689Skan			     (REGNO_REG_CLASS (ret_start)))
343169689Skan			|| (nregs
344169689Skan			    != hard_regno_nregs[ret_start][GET_MODE (ret_reg)])
345169689Skan			/* For multi-hard-register floating point
346169689Skan		   	   values, sometimes the likely-spilled part
347169689Skan		   	   is ordinarily copied first, then the other
348169689Skan		   	   part is set with an arithmetic operation.
349169689Skan		   	   This doesn't actually cause reload
350169689Skan		   	   failures, so let it pass.  */
351169689Skan			|| (GET_MODE_CLASS (GET_MODE (ret_reg)) != MODE_INT
352169689Skan			    && nregs != 1));
353169689Skan
354169689Skan	    if (INSN_P (last_insn))
355169689Skan	      {
356169689Skan		before_return_copy
357169689Skan		  = emit_note_before (NOTE_INSN_DELETED, last_insn);
358169689Skan		/* Instructions preceding LAST_INSN in the same block might
359169689Skan		   require a different mode than MODE_EXIT, so if we might
360169689Skan		   have such instructions, keep them in a separate block
361169689Skan		   from pre_exit.  */
362169689Skan		if (last_insn != BB_HEAD (src_bb))
363169689Skan		  src_bb = split_block (src_bb,
364169689Skan					PREV_INSN (before_return_copy))->dest;
365169689Skan	      }
366169689Skan	    else
367169689Skan	      before_return_copy = last_insn;
368169689Skan	    pre_exit = split_block (src_bb, before_return_copy)->src;
369169689Skan	  }
370169689Skan	else
371169689Skan	  {
372169689Skan	    pre_exit = split_edge (eg);
373169689Skan	    COPY_REG_SET (pre_exit->il.rtl->global_live_at_start, live_at_end);
374169689Skan	    COPY_REG_SET (pre_exit->il.rtl->global_live_at_end, live_at_end);
375169689Skan	  }
376169689Skan      }
377169689Skan
378169689Skan  return pre_exit;
379169689Skan}
380169689Skan#endif
381169689Skan
382169689Skan/* Find all insns that need a particular mode setting, and insert the
383169689Skan   necessary mode switches.  Return true if we did work.  */
384169689Skan
385169689Skanstatic int
386169689Skanoptimize_mode_switching (void)
387169689Skan{
388169689Skan  rtx insn;
389169689Skan  int e;
390169689Skan  basic_block bb;
391169689Skan  int need_commit = 0;
392169689Skan  sbitmap *kill;
393169689Skan  struct edge_list *edge_list;
394169689Skan  static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING;
395169689Skan#define N_ENTITIES ARRAY_SIZE (num_modes)
396169689Skan  int entity_map[N_ENTITIES];
397169689Skan  struct bb_info *bb_info[N_ENTITIES];
398169689Skan  int i, j;
399169689Skan  int n_entities;
400169689Skan  int max_num_modes = 0;
401169689Skan  bool emited = false;
402169689Skan  basic_block post_entry ATTRIBUTE_UNUSED, pre_exit ATTRIBUTE_UNUSED;
403169689Skan
404169689Skan  clear_bb_flags ();
405169689Skan
406169689Skan  for (e = N_ENTITIES - 1, n_entities = 0; e >= 0; e--)
407169689Skan    if (OPTIMIZE_MODE_SWITCHING (e))
408169689Skan      {
409169689Skan	int entry_exit_extra = 0;
410169689Skan
411169689Skan	/* Create the list of segments within each basic block.
412169689Skan	   If NORMAL_MODE is defined, allow for two extra
413169689Skan	   blocks split from the entry and exit block.  */
414169689Skan#if defined (MODE_ENTRY) && defined (MODE_EXIT)
415169689Skan	entry_exit_extra = 3;
416169689Skan#endif
417169689Skan	bb_info[n_entities]
418169689Skan	  = XCNEWVEC (struct bb_info, last_basic_block + entry_exit_extra);
419169689Skan	entity_map[n_entities++] = e;
420169689Skan	if (num_modes[e] > max_num_modes)
421169689Skan	  max_num_modes = num_modes[e];
422169689Skan      }
423169689Skan
424169689Skan  if (! n_entities)
425169689Skan    return 0;
426169689Skan
427169689Skan#if defined (MODE_ENTRY) && defined (MODE_EXIT)
428169689Skan  /* Split the edge from the entry block, so that we can note that
429169689Skan     there NORMAL_MODE is supplied.  */
430169689Skan  post_entry = split_edge (single_succ_edge (ENTRY_BLOCK_PTR));
431169689Skan  pre_exit = create_pre_exit (n_entities, entity_map, num_modes);
432169689Skan#endif
433169689Skan
434169689Skan  /* Create the bitmap vectors.  */
435169689Skan
436169689Skan  antic = sbitmap_vector_alloc (last_basic_block, n_entities);
437169689Skan  transp = sbitmap_vector_alloc (last_basic_block, n_entities);
438169689Skan  comp = sbitmap_vector_alloc (last_basic_block, n_entities);
439169689Skan
440169689Skan  sbitmap_vector_ones (transp, last_basic_block);
441169689Skan
442169689Skan  for (j = n_entities - 1; j >= 0; j--)
443169689Skan    {
444169689Skan      int e = entity_map[j];
445169689Skan      int no_mode = num_modes[e];
446169689Skan      struct bb_info *info = bb_info[j];
447169689Skan
448169689Skan      /* Determine what the first use (if any) need for a mode of entity E is.
449169689Skan	 This will be the mode that is anticipatable for this block.
450169689Skan	 Also compute the initial transparency settings.  */
451169689Skan      FOR_EACH_BB (bb)
452169689Skan	{
453169689Skan	  struct seginfo *ptr;
454169689Skan	  int last_mode = no_mode;
455169689Skan	  HARD_REG_SET live_now;
456169689Skan
457169689Skan	  REG_SET_TO_HARD_REG_SET (live_now,
458169689Skan				   bb->il.rtl->global_live_at_start);
459169689Skan
460169689Skan	  /* Pretend the mode is clobbered across abnormal edges.  */
461169689Skan	  {
462169689Skan	    edge_iterator ei;
463169689Skan	    edge e;
464169689Skan	    FOR_EACH_EDGE (e, ei, bb->preds)
465169689Skan	      if (e->flags & EDGE_COMPLEX)
466169689Skan		break;
467169689Skan	    if (e)
468169689Skan	      {
469169689Skan		ptr = new_seginfo (no_mode, BB_HEAD (bb), bb->index, live_now);
470169689Skan		add_seginfo (info + bb->index, ptr);
471169689Skan		RESET_BIT (transp[bb->index], j);
472169689Skan	      }
473169689Skan	  }
474169689Skan
475169689Skan	  for (insn = BB_HEAD (bb);
476169689Skan	       insn != NULL && insn != NEXT_INSN (BB_END (bb));
477169689Skan	       insn = NEXT_INSN (insn))
478169689Skan	    {
479169689Skan	      if (INSN_P (insn))
480169689Skan		{
481169689Skan		  int mode = MODE_NEEDED (e, insn);
482169689Skan		  rtx link;
483169689Skan
484169689Skan		  if (mode != no_mode && mode != last_mode)
485169689Skan		    {
486169689Skan		      last_mode = mode;
487169689Skan		      ptr = new_seginfo (mode, insn, bb->index, live_now);
488169689Skan		      add_seginfo (info + bb->index, ptr);
489169689Skan		      RESET_BIT (transp[bb->index], j);
490169689Skan		    }
491169689Skan#ifdef MODE_AFTER
492169689Skan		  last_mode = MODE_AFTER (last_mode, insn);
493169689Skan#endif
494169689Skan		  /* Update LIVE_NOW.  */
495169689Skan		  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
496169689Skan		    if (REG_NOTE_KIND (link) == REG_DEAD)
497169689Skan		      reg_dies (XEXP (link, 0), live_now);
498169689Skan
499169689Skan		  note_stores (PATTERN (insn), reg_becomes_live, &live_now);
500169689Skan		  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
501169689Skan		    if (REG_NOTE_KIND (link) == REG_UNUSED)
502169689Skan		      reg_dies (XEXP (link, 0), live_now);
503169689Skan		}
504169689Skan	    }
505169689Skan
506169689Skan	  info[bb->index].computing = last_mode;
507169689Skan	  /* Check for blocks without ANY mode requirements.  */
508169689Skan	  if (last_mode == no_mode)
509169689Skan	    {
510169689Skan	      ptr = new_seginfo (no_mode, BB_END (bb), bb->index, live_now);
511169689Skan	      add_seginfo (info + bb->index, ptr);
512169689Skan	    }
513169689Skan	}
514169689Skan#if defined (MODE_ENTRY) && defined (MODE_EXIT)
515169689Skan      {
516169689Skan	int mode = MODE_ENTRY (e);
517169689Skan
518169689Skan	if (mode != no_mode)
519169689Skan	  {
520169689Skan	    bb = post_entry;
521169689Skan
522169689Skan	    /* By always making this nontransparent, we save
523169689Skan	       an extra check in make_preds_opaque.  We also
524169689Skan	       need this to avoid confusing pre_edge_lcm when
525169689Skan	       antic is cleared but transp and comp are set.  */
526169689Skan	    RESET_BIT (transp[bb->index], j);
527169689Skan
528169689Skan	    /* Insert a fake computing definition of MODE into entry
529169689Skan	       blocks which compute no mode. This represents the mode on
530169689Skan	       entry.  */
531169689Skan	    info[bb->index].computing = mode;
532169689Skan
533169689Skan	    if (pre_exit)
534169689Skan	      info[pre_exit->index].seginfo->mode = MODE_EXIT (e);
535169689Skan	  }
536169689Skan      }
537169689Skan#endif /* NORMAL_MODE */
538169689Skan    }
539169689Skan
540169689Skan  kill = sbitmap_vector_alloc (last_basic_block, n_entities);
541169689Skan  for (i = 0; i < max_num_modes; i++)
542169689Skan    {
543169689Skan      int current_mode[N_ENTITIES];
544169689Skan      sbitmap *delete;
545169689Skan      sbitmap *insert;
546169689Skan
547169689Skan      /* Set the anticipatable and computing arrays.  */
548169689Skan      sbitmap_vector_zero (antic, last_basic_block);
549169689Skan      sbitmap_vector_zero (comp, last_basic_block);
550169689Skan      for (j = n_entities - 1; j >= 0; j--)
551169689Skan	{
552169689Skan	  int m = current_mode[j] = MODE_PRIORITY_TO_MODE (entity_map[j], i);
553169689Skan	  struct bb_info *info = bb_info[j];
554169689Skan
555169689Skan	  FOR_EACH_BB (bb)
556169689Skan	    {
557169689Skan	      if (info[bb->index].seginfo->mode == m)
558169689Skan		SET_BIT (antic[bb->index], j);
559169689Skan
560169689Skan	      if (info[bb->index].computing == m)
561169689Skan		SET_BIT (comp[bb->index], j);
562169689Skan	    }
563169689Skan	}
564169689Skan
565169689Skan      /* Calculate the optimal locations for the
566169689Skan	 placement mode switches to modes with priority I.  */
567169689Skan
568169689Skan      FOR_EACH_BB (bb)
569169689Skan	sbitmap_not (kill[bb->index], transp[bb->index]);
570169689Skan      edge_list = pre_edge_lcm (n_entities, transp, comp, antic,
571169689Skan				kill, &insert, &delete);
572169689Skan
573169689Skan      for (j = n_entities - 1; j >= 0; j--)
574169689Skan	{
575169689Skan	  /* Insert all mode sets that have been inserted by lcm.  */
576169689Skan	  int no_mode = num_modes[entity_map[j]];
577169689Skan
578169689Skan	  /* Wherever we have moved a mode setting upwards in the flow graph,
579169689Skan	     the blocks between the new setting site and the now redundant
580169689Skan	     computation ceases to be transparent for any lower-priority
581169689Skan	     mode of the same entity.  First set the aux field of each
582169689Skan	     insertion site edge non-transparent, then propagate the new
583169689Skan	     non-transparency from the redundant computation upwards till
584169689Skan	     we hit an insertion site or an already non-transparent block.  */
585169689Skan	  for (e = NUM_EDGES (edge_list) - 1; e >= 0; e--)
586169689Skan	    {
587169689Skan	      edge eg = INDEX_EDGE (edge_list, e);
588169689Skan	      int mode;
589169689Skan	      basic_block src_bb;
590169689Skan	      HARD_REG_SET live_at_edge;
591169689Skan	      rtx mode_set;
592169689Skan
593169689Skan	      eg->aux = 0;
594169689Skan
595169689Skan	      if (! TEST_BIT (insert[e], j))
596169689Skan		continue;
597169689Skan
598169689Skan	      eg->aux = (void *)1;
599169689Skan
600169689Skan	      mode = current_mode[j];
601169689Skan	      src_bb = eg->src;
602169689Skan
603169689Skan	      REG_SET_TO_HARD_REG_SET (live_at_edge,
604169689Skan				       src_bb->il.rtl->global_live_at_end);
605169689Skan
606169689Skan	      start_sequence ();
607169689Skan	      EMIT_MODE_SET (entity_map[j], mode, live_at_edge);
608169689Skan	      mode_set = get_insns ();
609169689Skan	      end_sequence ();
610169689Skan
611169689Skan	      /* Do not bother to insert empty sequence.  */
612169689Skan	      if (mode_set == NULL_RTX)
613169689Skan		continue;
614169689Skan
615169689Skan	      /* We should not get an abnormal edge here.  */
616169689Skan	      gcc_assert (! (eg->flags & EDGE_ABNORMAL));
617169689Skan
618169689Skan	      need_commit = 1;
619169689Skan	      insert_insn_on_edge (mode_set, eg);
620169689Skan	    }
621169689Skan
622169689Skan	  FOR_EACH_BB_REVERSE (bb)
623169689Skan	    if (TEST_BIT (delete[bb->index], j))
624169689Skan	      {
625169689Skan		make_preds_opaque (bb, j);
626169689Skan		/* Cancel the 'deleted' mode set.  */
627169689Skan		bb_info[j][bb->index].seginfo->mode = no_mode;
628169689Skan	      }
629169689Skan	}
630169689Skan
631169689Skan      sbitmap_vector_free (delete);
632169689Skan      sbitmap_vector_free (insert);
633169689Skan      clear_aux_for_edges ();
634169689Skan      free_edge_list (edge_list);
635169689Skan    }
636169689Skan
637169689Skan  /* Now output the remaining mode sets in all the segments.  */
638169689Skan  for (j = n_entities - 1; j >= 0; j--)
639169689Skan    {
640169689Skan      int no_mode = num_modes[entity_map[j]];
641169689Skan
642169689Skan      FOR_EACH_BB_REVERSE (bb)
643169689Skan	{
644169689Skan	  struct seginfo *ptr, *next;
645169689Skan	  for (ptr = bb_info[j][bb->index].seginfo; ptr; ptr = next)
646169689Skan	    {
647169689Skan	      next = ptr->next;
648169689Skan	      if (ptr->mode != no_mode)
649169689Skan		{
650169689Skan		  rtx mode_set;
651169689Skan
652169689Skan		  start_sequence ();
653169689Skan		  EMIT_MODE_SET (entity_map[j], ptr->mode, ptr->regs_live);
654169689Skan		  mode_set = get_insns ();
655169689Skan		  end_sequence ();
656169689Skan
657169689Skan		  /* Insert MODE_SET only if it is nonempty.  */
658169689Skan		  if (mode_set != NULL_RTX)
659169689Skan		    {
660169689Skan		      emited = true;
661169689Skan		      if (NOTE_P (ptr->insn_ptr)
662169689Skan			  && (NOTE_LINE_NUMBER (ptr->insn_ptr)
663169689Skan			      == NOTE_INSN_BASIC_BLOCK))
664169689Skan			emit_insn_after (mode_set, ptr->insn_ptr);
665169689Skan		      else
666169689Skan			emit_insn_before (mode_set, ptr->insn_ptr);
667169689Skan		    }
668169689Skan		}
669169689Skan
670169689Skan	      free (ptr);
671169689Skan	    }
672169689Skan	}
673169689Skan
674169689Skan      free (bb_info[j]);
675169689Skan    }
676169689Skan
677169689Skan  /* Finished. Free up all the things we've allocated.  */
678169689Skan
679169689Skan  sbitmap_vector_free (kill);
680169689Skan  sbitmap_vector_free (antic);
681169689Skan  sbitmap_vector_free (transp);
682169689Skan  sbitmap_vector_free (comp);
683169689Skan
684169689Skan  if (need_commit)
685169689Skan    commit_edge_insertions ();
686169689Skan
687169689Skan#if defined (MODE_ENTRY) && defined (MODE_EXIT)
688169689Skan  cleanup_cfg (CLEANUP_NO_INSN_DEL);
689169689Skan#else
690169689Skan  if (!need_commit && !emited)
691169689Skan    return 0;
692169689Skan#endif
693169689Skan
694169689Skan  max_regno = max_reg_num ();
695169689Skan  allocate_reg_info (max_regno, FALSE, FALSE);
696169689Skan  update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
697169689Skan				    (PROP_DEATH_NOTES | PROP_KILL_DEAD_CODE
698169689Skan				     | PROP_SCAN_DEAD_CODE));
699169689Skan
700169689Skan  return 1;
701169689Skan}
702169689Skan
703169689Skan#endif /* OPTIMIZE_MODE_SWITCHING */
704169689Skan
705169689Skanstatic bool
706169689Skangate_mode_switching (void)
707169689Skan{
708169689Skan#ifdef OPTIMIZE_MODE_SWITCHING
709169689Skan  return true;
710169689Skan#else
711169689Skan  return false;
712169689Skan#endif
713169689Skan}
714169689Skan
715169689Skanstatic unsigned int
716169689Skanrest_of_handle_mode_switching (void)
717169689Skan{
718169689Skan#ifdef OPTIMIZE_MODE_SWITCHING
719169689Skan  no_new_pseudos = 0;
720169689Skan  optimize_mode_switching ();
721169689Skan  no_new_pseudos = 1;
722169689Skan#endif /* OPTIMIZE_MODE_SWITCHING */
723169689Skan  return 0;
724169689Skan}
725169689Skan
726169689Skan
727169689Skanstruct tree_opt_pass pass_mode_switching =
728169689Skan{
729169689Skan  "mode-sw",                            /* name */
730169689Skan  gate_mode_switching,                  /* gate */
731169689Skan  rest_of_handle_mode_switching,        /* execute */
732169689Skan  NULL,                                 /* sub */
733169689Skan  NULL,                                 /* next */
734169689Skan  0,                                    /* static_pass_number */
735169689Skan  TV_MODE_SWITCH,                       /* tv_id */
736169689Skan  0,                                    /* properties_required */
737169689Skan  0,                                    /* properties_provided */
738169689Skan  0,                                    /* properties_destroyed */
739169689Skan  0,                                    /* todo_flags_start */
740169689Skan  TODO_dump_func,                       /* todo_flags_finish */
741169689Skan  0                                     /* letter */
742169689Skan};
743