xref: /dflybsd-src/contrib/gcc-8.0/gcc/mode-switching.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* CPU mode switching
2*38fd1498Szrj    Copyright (C) 1998-2018 Free Software Foundation, Inc.
3*38fd1498Szrj 
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj 
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
7*38fd1498Szrj the terms of the GNU General Public License as published by the Free
8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj version.
10*38fd1498Szrj 
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*38fd1498Szrj for more details.
15*38fd1498Szrj 
16*38fd1498Szrj You should have received a copy of the GNU General Public License
17*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
19*38fd1498Szrj 
20*38fd1498Szrj #include "config.h"
21*38fd1498Szrj #include "system.h"
22*38fd1498Szrj #include "coretypes.h"
23*38fd1498Szrj #include "backend.h"
24*38fd1498Szrj #include "target.h"
25*38fd1498Szrj #include "rtl.h"
26*38fd1498Szrj #include "cfghooks.h"
27*38fd1498Szrj #include "df.h"
28*38fd1498Szrj #include "memmodel.h"
29*38fd1498Szrj #include "tm_p.h"
30*38fd1498Szrj #include "regs.h"
31*38fd1498Szrj #include "emit-rtl.h"
32*38fd1498Szrj #include "cfgrtl.h"
33*38fd1498Szrj #include "cfganal.h"
34*38fd1498Szrj #include "lcm.h"
35*38fd1498Szrj #include "cfgcleanup.h"
36*38fd1498Szrj #include "tree-pass.h"
37*38fd1498Szrj 
38*38fd1498Szrj /* We want target macros for the mode switching code to be able to refer
39*38fd1498Szrj    to instruction attribute values.  */
40*38fd1498Szrj #include "insn-attr.h"
41*38fd1498Szrj 
42*38fd1498Szrj #ifdef OPTIMIZE_MODE_SWITCHING
43*38fd1498Szrj 
44*38fd1498Szrj /* The algorithm for setting the modes consists of scanning the insn list
45*38fd1498Szrj    and finding all the insns which require a specific mode.  Each insn gets
46*38fd1498Szrj    a unique struct seginfo element.  These structures are inserted into a list
47*38fd1498Szrj    for each basic block.  For each entity, there is an array of bb_info over
48*38fd1498Szrj    the flow graph basic blocks (local var 'bb_info'), which contains a list
49*38fd1498Szrj    of all insns within that basic block, in the order they are encountered.
50*38fd1498Szrj 
51*38fd1498Szrj    For each entity, any basic block WITHOUT any insns requiring a specific
52*38fd1498Szrj    mode are given a single entry without a mode (each basic block in the
53*38fd1498Szrj    flow graph must have at least one entry in the segment table).
54*38fd1498Szrj 
55*38fd1498Szrj    The LCM algorithm is then run over the flow graph to determine where to
56*38fd1498Szrj    place the sets to the highest-priority mode with respect to the first
57*38fd1498Szrj    insn in any one block.  Any adjustments required to the transparency
58*38fd1498Szrj    vectors are made, then the next iteration starts for the next-lower
59*38fd1498Szrj    priority mode, till for each entity all modes are exhausted.
60*38fd1498Szrj 
61*38fd1498Szrj    More details can be found in the code of optimize_mode_switching.  */
62*38fd1498Szrj 
63*38fd1498Szrj /* This structure contains the information for each insn which requires
64*38fd1498Szrj    either single or double mode to be set.
65*38fd1498Szrj    MODE is the mode this insn must be executed in.
66*38fd1498Szrj    INSN_PTR is the insn to be executed (may be the note that marks the
67*38fd1498Szrj    beginning of a basic block).
68*38fd1498Szrj    BBNUM is the flow graph basic block this insn occurs in.
69*38fd1498Szrj    NEXT is the next insn in the same basic block.  */
70*38fd1498Szrj struct seginfo
71*38fd1498Szrj {
72*38fd1498Szrj   int mode;
73*38fd1498Szrj   rtx_insn *insn_ptr;
74*38fd1498Szrj   int bbnum;
75*38fd1498Szrj   struct seginfo *next;
76*38fd1498Szrj   HARD_REG_SET regs_live;
77*38fd1498Szrj };
78*38fd1498Szrj 
79*38fd1498Szrj struct bb_info
80*38fd1498Szrj {
81*38fd1498Szrj   struct seginfo *seginfo;
82*38fd1498Szrj   int computing;
83*38fd1498Szrj   int mode_out;
84*38fd1498Szrj   int mode_in;
85*38fd1498Szrj };
86*38fd1498Szrj 
87*38fd1498Szrj static struct seginfo * new_seginfo (int, rtx_insn *, int, HARD_REG_SET);
88*38fd1498Szrj static void add_seginfo (struct bb_info *, struct seginfo *);
89*38fd1498Szrj static void reg_dies (rtx, HARD_REG_SET *);
90*38fd1498Szrj static void reg_becomes_live (rtx, const_rtx, void *);
91*38fd1498Szrj 
92*38fd1498Szrj /* Clear ode I from entity J in bitmap B.  */
93*38fd1498Szrj #define clear_mode_bit(b, j, i) \
94*38fd1498Szrj        bitmap_clear_bit (b, (j * max_num_modes) + i)
95*38fd1498Szrj 
96*38fd1498Szrj /* Test mode I from entity J in bitmap B.  */
97*38fd1498Szrj #define mode_bit_p(b, j, i) \
98*38fd1498Szrj        bitmap_bit_p (b, (j * max_num_modes) + i)
99*38fd1498Szrj 
100*38fd1498Szrj /* Set mode I from entity J in bitmal B.  */
101*38fd1498Szrj #define set_mode_bit(b, j, i) \
102*38fd1498Szrj        bitmap_set_bit (b, (j * max_num_modes) + i)
103*38fd1498Szrj 
104*38fd1498Szrj /* Emit modes segments from EDGE_LIST associated with entity E.
105*38fd1498Szrj    INFO gives mode availability for each mode.  */
106*38fd1498Szrj 
107*38fd1498Szrj static bool
commit_mode_sets(struct edge_list * edge_list,int e,struct bb_info * info)108*38fd1498Szrj commit_mode_sets (struct edge_list *edge_list, int e, struct bb_info *info)
109*38fd1498Szrj {
110*38fd1498Szrj   bool need_commit = false;
111*38fd1498Szrj 
112*38fd1498Szrj   for (int ed = NUM_EDGES (edge_list) - 1; ed >= 0; ed--)
113*38fd1498Szrj     {
114*38fd1498Szrj       edge eg = INDEX_EDGE (edge_list, ed);
115*38fd1498Szrj       int mode;
116*38fd1498Szrj 
117*38fd1498Szrj       if ((mode = (int)(intptr_t)(eg->aux)) != -1)
118*38fd1498Szrj 	{
119*38fd1498Szrj 	  HARD_REG_SET live_at_edge;
120*38fd1498Szrj 	  basic_block src_bb = eg->src;
121*38fd1498Szrj 	  int cur_mode = info[src_bb->index].mode_out;
122*38fd1498Szrj 	  rtx_insn *mode_set;
123*38fd1498Szrj 
124*38fd1498Szrj 	  REG_SET_TO_HARD_REG_SET (live_at_edge, df_get_live_out (src_bb));
125*38fd1498Szrj 
126*38fd1498Szrj 	  rtl_profile_for_edge (eg);
127*38fd1498Szrj 	  start_sequence ();
128*38fd1498Szrj 
129*38fd1498Szrj 	  targetm.mode_switching.emit (e, mode, cur_mode, live_at_edge);
130*38fd1498Szrj 
131*38fd1498Szrj 	  mode_set = get_insns ();
132*38fd1498Szrj 	  end_sequence ();
133*38fd1498Szrj 	  default_rtl_profile ();
134*38fd1498Szrj 
135*38fd1498Szrj 	  /* Do not bother to insert empty sequence.  */
136*38fd1498Szrj 	  if (mode_set == NULL)
137*38fd1498Szrj 	    continue;
138*38fd1498Szrj 
139*38fd1498Szrj 	  /* We should not get an abnormal edge here.  */
140*38fd1498Szrj 	  gcc_assert (! (eg->flags & EDGE_ABNORMAL));
141*38fd1498Szrj 
142*38fd1498Szrj 	  need_commit = true;
143*38fd1498Szrj 	  insert_insn_on_edge (mode_set, eg);
144*38fd1498Szrj 	}
145*38fd1498Szrj     }
146*38fd1498Szrj 
147*38fd1498Szrj   return need_commit;
148*38fd1498Szrj }
149*38fd1498Szrj 
150*38fd1498Szrj /* Allocate a new BBINFO structure, initialized with the MODE, INSN,
151*38fd1498Szrj    and basic block BB parameters.
152*38fd1498Szrj    INSN may not be a NOTE_INSN_BASIC_BLOCK, unless it is an empty
153*38fd1498Szrj    basic block; that allows us later to insert instructions in a FIFO-like
154*38fd1498Szrj    manner.  */
155*38fd1498Szrj 
156*38fd1498Szrj static struct seginfo *
new_seginfo(int mode,rtx_insn * insn,int bb,HARD_REG_SET regs_live)157*38fd1498Szrj new_seginfo (int mode, rtx_insn *insn, int bb, HARD_REG_SET regs_live)
158*38fd1498Szrj {
159*38fd1498Szrj   struct seginfo *ptr;
160*38fd1498Szrj 
161*38fd1498Szrj   gcc_assert (!NOTE_INSN_BASIC_BLOCK_P (insn)
162*38fd1498Szrj 	      || insn == BB_END (NOTE_BASIC_BLOCK (insn)));
163*38fd1498Szrj   ptr = XNEW (struct seginfo);
164*38fd1498Szrj   ptr->mode = mode;
165*38fd1498Szrj   ptr->insn_ptr = insn;
166*38fd1498Szrj   ptr->bbnum = bb;
167*38fd1498Szrj   ptr->next = NULL;
168*38fd1498Szrj   COPY_HARD_REG_SET (ptr->regs_live, regs_live);
169*38fd1498Szrj   return ptr;
170*38fd1498Szrj }
171*38fd1498Szrj 
172*38fd1498Szrj /* Add a seginfo element to the end of a list.
173*38fd1498Szrj    HEAD is a pointer to the list beginning.
174*38fd1498Szrj    INFO is the structure to be linked in.  */
175*38fd1498Szrj 
176*38fd1498Szrj static void
add_seginfo(struct bb_info * head,struct seginfo * info)177*38fd1498Szrj add_seginfo (struct bb_info *head, struct seginfo *info)
178*38fd1498Szrj {
179*38fd1498Szrj   struct seginfo *ptr;
180*38fd1498Szrj 
181*38fd1498Szrj   if (head->seginfo == NULL)
182*38fd1498Szrj     head->seginfo = info;
183*38fd1498Szrj   else
184*38fd1498Szrj     {
185*38fd1498Szrj       ptr = head->seginfo;
186*38fd1498Szrj       while (ptr->next != NULL)
187*38fd1498Szrj 	ptr = ptr->next;
188*38fd1498Szrj       ptr->next = info;
189*38fd1498Szrj     }
190*38fd1498Szrj }
191*38fd1498Szrj 
192*38fd1498Szrj /* Record in LIVE that register REG died.  */
193*38fd1498Szrj 
194*38fd1498Szrj static void
reg_dies(rtx reg,HARD_REG_SET * live)195*38fd1498Szrj reg_dies (rtx reg, HARD_REG_SET *live)
196*38fd1498Szrj {
197*38fd1498Szrj   int regno;
198*38fd1498Szrj 
199*38fd1498Szrj   if (!REG_P (reg))
200*38fd1498Szrj     return;
201*38fd1498Szrj 
202*38fd1498Szrj   regno = REGNO (reg);
203*38fd1498Szrj   if (regno < FIRST_PSEUDO_REGISTER)
204*38fd1498Szrj     remove_from_hard_reg_set (live, GET_MODE (reg), regno);
205*38fd1498Szrj }
206*38fd1498Szrj 
207*38fd1498Szrj /* Record in LIVE that register REG became live.
208*38fd1498Szrj    This is called via note_stores.  */
209*38fd1498Szrj 
210*38fd1498Szrj static void
reg_becomes_live(rtx reg,const_rtx setter ATTRIBUTE_UNUSED,void * live)211*38fd1498Szrj reg_becomes_live (rtx reg, const_rtx setter ATTRIBUTE_UNUSED, void *live)
212*38fd1498Szrj {
213*38fd1498Szrj   int regno;
214*38fd1498Szrj 
215*38fd1498Szrj   if (GET_CODE (reg) == SUBREG)
216*38fd1498Szrj     reg = SUBREG_REG (reg);
217*38fd1498Szrj 
218*38fd1498Szrj   if (!REG_P (reg))
219*38fd1498Szrj     return;
220*38fd1498Szrj 
221*38fd1498Szrj   regno = REGNO (reg);
222*38fd1498Szrj   if (regno < FIRST_PSEUDO_REGISTER)
223*38fd1498Szrj     add_to_hard_reg_set ((HARD_REG_SET *) live, GET_MODE (reg), regno);
224*38fd1498Szrj }
225*38fd1498Szrj 
226*38fd1498Szrj /* Split the fallthrough edge to the exit block, so that we can note
227*38fd1498Szrj    that there NORMAL_MODE is required.  Return the new block if it's
228*38fd1498Szrj    inserted before the exit block.  Otherwise return null.  */
229*38fd1498Szrj 
230*38fd1498Szrj static basic_block
create_pre_exit(int n_entities,int * entity_map,const int * num_modes)231*38fd1498Szrj create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
232*38fd1498Szrj {
233*38fd1498Szrj   edge eg;
234*38fd1498Szrj   edge_iterator ei;
235*38fd1498Szrj   basic_block pre_exit;
236*38fd1498Szrj 
237*38fd1498Szrj   /* The only non-call predecessor at this stage is a block with a
238*38fd1498Szrj      fallthrough edge; there can be at most one, but there could be
239*38fd1498Szrj      none at all, e.g. when exit is called.  */
240*38fd1498Szrj   pre_exit = 0;
241*38fd1498Szrj   FOR_EACH_EDGE (eg, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
242*38fd1498Szrj     if (eg->flags & EDGE_FALLTHRU)
243*38fd1498Szrj       {
244*38fd1498Szrj 	basic_block src_bb = eg->src;
245*38fd1498Szrj 	rtx_insn *last_insn;
246*38fd1498Szrj 	rtx ret_reg;
247*38fd1498Szrj 
248*38fd1498Szrj 	gcc_assert (!pre_exit);
249*38fd1498Szrj 	/* If this function returns a value at the end, we have to
250*38fd1498Szrj 	   insert the final mode switch before the return value copy
251*38fd1498Szrj 	   to its hard register.  */
252*38fd1498Szrj 	if (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == 1
253*38fd1498Szrj 	    && NONJUMP_INSN_P ((last_insn = BB_END (src_bb)))
254*38fd1498Szrj 	    && GET_CODE (PATTERN (last_insn)) == USE
255*38fd1498Szrj 	    && GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG)
256*38fd1498Szrj 	  {
257*38fd1498Szrj 	    int ret_start = REGNO (ret_reg);
258*38fd1498Szrj 	    int nregs = REG_NREGS (ret_reg);
259*38fd1498Szrj 	    int ret_end = ret_start + nregs;
260*38fd1498Szrj 	    bool short_block = false;
261*38fd1498Szrj 	    bool multi_reg_return = false;
262*38fd1498Szrj 	    bool forced_late_switch = false;
263*38fd1498Szrj 	    rtx_insn *before_return_copy;
264*38fd1498Szrj 
265*38fd1498Szrj 	    do
266*38fd1498Szrj 	      {
267*38fd1498Szrj 		rtx_insn *return_copy = PREV_INSN (last_insn);
268*38fd1498Szrj 		rtx return_copy_pat, copy_reg;
269*38fd1498Szrj 		int copy_start, copy_num;
270*38fd1498Szrj 		int j;
271*38fd1498Szrj 
272*38fd1498Szrj 		if (NONDEBUG_INSN_P (return_copy))
273*38fd1498Szrj 		  {
274*38fd1498Szrj 		    /* When using SJLJ exceptions, the call to the
275*38fd1498Szrj 		       unregister function is inserted between the
276*38fd1498Szrj 		       clobber of the return value and the copy.
277*38fd1498Szrj 		       We do not want to split the block before this
278*38fd1498Szrj 		       or any other call; if we have not found the
279*38fd1498Szrj 		       copy yet, the copy must have been deleted.  */
280*38fd1498Szrj 		    if (CALL_P (return_copy))
281*38fd1498Szrj 		      {
282*38fd1498Szrj 			short_block = true;
283*38fd1498Szrj 			break;
284*38fd1498Szrj 		      }
285*38fd1498Szrj 		    return_copy_pat = PATTERN (return_copy);
286*38fd1498Szrj 		    switch (GET_CODE (return_copy_pat))
287*38fd1498Szrj 		      {
288*38fd1498Szrj 		      case USE:
289*38fd1498Szrj 			/* Skip USEs of multiple return registers.
290*38fd1498Szrj 			   __builtin_apply pattern is also handled here.  */
291*38fd1498Szrj 			if (GET_CODE (XEXP (return_copy_pat, 0)) == REG
292*38fd1498Szrj 			    && (targetm.calls.function_value_regno_p
293*38fd1498Szrj 				(REGNO (XEXP (return_copy_pat, 0)))))
294*38fd1498Szrj 			  {
295*38fd1498Szrj 			    multi_reg_return = true;
296*38fd1498Szrj 			    last_insn = return_copy;
297*38fd1498Szrj 			    continue;
298*38fd1498Szrj 			  }
299*38fd1498Szrj 			break;
300*38fd1498Szrj 
301*38fd1498Szrj 		      case ASM_OPERANDS:
302*38fd1498Szrj 			/* Skip barrier insns.  */
303*38fd1498Szrj 			if (!MEM_VOLATILE_P (return_copy_pat))
304*38fd1498Szrj 			  break;
305*38fd1498Szrj 
306*38fd1498Szrj 			/* Fall through.  */
307*38fd1498Szrj 
308*38fd1498Szrj 		      case ASM_INPUT:
309*38fd1498Szrj 		      case UNSPEC_VOLATILE:
310*38fd1498Szrj 			last_insn = return_copy;
311*38fd1498Szrj 			continue;
312*38fd1498Szrj 
313*38fd1498Szrj 		      default:
314*38fd1498Szrj 			break;
315*38fd1498Szrj 		      }
316*38fd1498Szrj 
317*38fd1498Szrj 		    /* If the return register is not (in its entirety)
318*38fd1498Szrj 		       likely spilled, the return copy might be
319*38fd1498Szrj 		       partially or completely optimized away.  */
320*38fd1498Szrj 		    return_copy_pat = single_set (return_copy);
321*38fd1498Szrj 		    if (!return_copy_pat)
322*38fd1498Szrj 		      {
323*38fd1498Szrj 			return_copy_pat = PATTERN (return_copy);
324*38fd1498Szrj 			if (GET_CODE (return_copy_pat) != CLOBBER)
325*38fd1498Szrj 			  break;
326*38fd1498Szrj 			else if (!optimize)
327*38fd1498Szrj 			  {
328*38fd1498Szrj 			    /* This might be (clobber (reg [<result>]))
329*38fd1498Szrj 			       when not optimizing.  Then check if
330*38fd1498Szrj 			       the previous insn is the clobber for
331*38fd1498Szrj 			       the return register.  */
332*38fd1498Szrj 			    copy_reg = SET_DEST (return_copy_pat);
333*38fd1498Szrj 			    if (GET_CODE (copy_reg) == REG
334*38fd1498Szrj 				&& !HARD_REGISTER_NUM_P (REGNO (copy_reg)))
335*38fd1498Szrj 			      {
336*38fd1498Szrj 				if (INSN_P (PREV_INSN (return_copy)))
337*38fd1498Szrj 				  {
338*38fd1498Szrj 				    return_copy = PREV_INSN (return_copy);
339*38fd1498Szrj 				    return_copy_pat = PATTERN (return_copy);
340*38fd1498Szrj 				    if (GET_CODE (return_copy_pat) != CLOBBER)
341*38fd1498Szrj 				      break;
342*38fd1498Szrj 				  }
343*38fd1498Szrj 			      }
344*38fd1498Szrj 			  }
345*38fd1498Szrj 		      }
346*38fd1498Szrj 		    copy_reg = SET_DEST (return_copy_pat);
347*38fd1498Szrj 		    if (GET_CODE (copy_reg) == REG)
348*38fd1498Szrj 		      copy_start = REGNO (copy_reg);
349*38fd1498Szrj 		    else if (GET_CODE (copy_reg) == SUBREG
350*38fd1498Szrj 			     && GET_CODE (SUBREG_REG (copy_reg)) == REG)
351*38fd1498Szrj 		      copy_start = REGNO (SUBREG_REG (copy_reg));
352*38fd1498Szrj 		    else
353*38fd1498Szrj 		      {
354*38fd1498Szrj 			/* When control reaches end of non-void function,
355*38fd1498Szrj 			   there are no return copy insns at all.  This
356*38fd1498Szrj 			   avoids an ice on that invalid function.  */
357*38fd1498Szrj 			if (ret_start + nregs == ret_end)
358*38fd1498Szrj 			  short_block = true;
359*38fd1498Szrj 			break;
360*38fd1498Szrj 		      }
361*38fd1498Szrj 		    if (!targetm.calls.function_value_regno_p (copy_start))
362*38fd1498Szrj 		      copy_num = 0;
363*38fd1498Szrj 		    else
364*38fd1498Szrj 		      copy_num = hard_regno_nregs (copy_start,
365*38fd1498Szrj 						   GET_MODE (copy_reg));
366*38fd1498Szrj 
367*38fd1498Szrj 		    /* If the return register is not likely spilled, - as is
368*38fd1498Szrj 		       the case for floating point on SH4 - then it might
369*38fd1498Szrj 		       be set by an arithmetic operation that needs a
370*38fd1498Szrj 		       different mode than the exit block.  */
371*38fd1498Szrj 		    for (j = n_entities - 1; j >= 0; j--)
372*38fd1498Szrj 		      {
373*38fd1498Szrj 			int e = entity_map[j];
374*38fd1498Szrj 			int mode =
375*38fd1498Szrj 			  targetm.mode_switching.needed (e, return_copy);
376*38fd1498Szrj 
377*38fd1498Szrj 			if (mode != num_modes[e]
378*38fd1498Szrj 			    && mode != targetm.mode_switching.exit (e))
379*38fd1498Szrj 			  break;
380*38fd1498Szrj 		      }
381*38fd1498Szrj 		    if (j >= 0)
382*38fd1498Szrj 		      {
383*38fd1498Szrj 			/* __builtin_return emits a sequence of loads to all
384*38fd1498Szrj 			   return registers.  One of them might require
385*38fd1498Szrj 			   another mode than MODE_EXIT, even if it is
386*38fd1498Szrj 			   unrelated to the return value, so we want to put
387*38fd1498Szrj 			   the final mode switch after it.  */
388*38fd1498Szrj 			if (multi_reg_return
389*38fd1498Szrj 			    && targetm.calls.function_value_regno_p
390*38fd1498Szrj 			        (copy_start))
391*38fd1498Szrj 			  forced_late_switch = true;
392*38fd1498Szrj 
393*38fd1498Szrj 			/* For the SH4, floating point loads depend on fpscr,
394*38fd1498Szrj 			   thus we might need to put the final mode switch
395*38fd1498Szrj 			   after the return value copy.  That is still OK,
396*38fd1498Szrj 			   because a floating point return value does not
397*38fd1498Szrj 			   conflict with address reloads.  */
398*38fd1498Szrj 			if (copy_start >= ret_start
399*38fd1498Szrj 			    && copy_start + copy_num <= ret_end
400*38fd1498Szrj 			    && OBJECT_P (SET_SRC (return_copy_pat)))
401*38fd1498Szrj 			  forced_late_switch = true;
402*38fd1498Szrj 			break;
403*38fd1498Szrj 		      }
404*38fd1498Szrj 		    if (copy_num == 0)
405*38fd1498Szrj 		      {
406*38fd1498Szrj 			last_insn = return_copy;
407*38fd1498Szrj 			continue;
408*38fd1498Szrj 		      }
409*38fd1498Szrj 
410*38fd1498Szrj 		    if (copy_start >= ret_start
411*38fd1498Szrj 			&& copy_start + copy_num <= ret_end)
412*38fd1498Szrj 		      nregs -= copy_num;
413*38fd1498Szrj 		    else if (!multi_reg_return
414*38fd1498Szrj 			     || !targetm.calls.function_value_regno_p
415*38fd1498Szrj 				 (copy_start))
416*38fd1498Szrj 		      break;
417*38fd1498Szrj 		    last_insn = return_copy;
418*38fd1498Szrj 		  }
419*38fd1498Szrj 		/* ??? Exception handling can lead to the return value
420*38fd1498Szrj 		   copy being already separated from the return value use,
421*38fd1498Szrj 		   as in  unwind-dw2.c .
422*38fd1498Szrj 		   Similarly, conditionally returning without a value,
423*38fd1498Szrj 		   and conditionally using builtin_return can lead to an
424*38fd1498Szrj 		   isolated use.  */
425*38fd1498Szrj 		if (return_copy == BB_HEAD (src_bb))
426*38fd1498Szrj 		  {
427*38fd1498Szrj 		    short_block = true;
428*38fd1498Szrj 		    break;
429*38fd1498Szrj 		  }
430*38fd1498Szrj 		last_insn = return_copy;
431*38fd1498Szrj 	      }
432*38fd1498Szrj 	    while (nregs);
433*38fd1498Szrj 
434*38fd1498Szrj 	    /* If we didn't see a full return value copy, verify that there
435*38fd1498Szrj 	       is a plausible reason for this.  If some, but not all of the
436*38fd1498Szrj 	       return register is likely spilled, we can expect that there
437*38fd1498Szrj 	       is a copy for the likely spilled part.  */
438*38fd1498Szrj 	    gcc_assert (!nregs
439*38fd1498Szrj 			|| forced_late_switch
440*38fd1498Szrj 			|| short_block
441*38fd1498Szrj 			|| !(targetm.class_likely_spilled_p
442*38fd1498Szrj 			     (REGNO_REG_CLASS (ret_start)))
443*38fd1498Szrj 			|| nregs != REG_NREGS (ret_reg)
444*38fd1498Szrj 			/* For multi-hard-register floating point
445*38fd1498Szrj 		   	   values, sometimes the likely-spilled part
446*38fd1498Szrj 		   	   is ordinarily copied first, then the other
447*38fd1498Szrj 		   	   part is set with an arithmetic operation.
448*38fd1498Szrj 		   	   This doesn't actually cause reload
449*38fd1498Szrj 		   	   failures, so let it pass.  */
450*38fd1498Szrj 			|| (GET_MODE_CLASS (GET_MODE (ret_reg)) != MODE_INT
451*38fd1498Szrj 			    && nregs != 1));
452*38fd1498Szrj 
453*38fd1498Szrj 	    if (!NOTE_INSN_BASIC_BLOCK_P (last_insn))
454*38fd1498Szrj 	      {
455*38fd1498Szrj 		before_return_copy
456*38fd1498Szrj 		  = emit_note_before (NOTE_INSN_DELETED, last_insn);
457*38fd1498Szrj 		/* Instructions preceding LAST_INSN in the same block might
458*38fd1498Szrj 		   require a different mode than MODE_EXIT, so if we might
459*38fd1498Szrj 		   have such instructions, keep them in a separate block
460*38fd1498Szrj 		   from pre_exit.  */
461*38fd1498Szrj 		src_bb = split_block (src_bb,
462*38fd1498Szrj 				      PREV_INSN (before_return_copy))->dest;
463*38fd1498Szrj 	      }
464*38fd1498Szrj 	    else
465*38fd1498Szrj 	      before_return_copy = last_insn;
466*38fd1498Szrj 	    pre_exit = split_block (src_bb, before_return_copy)->src;
467*38fd1498Szrj 	  }
468*38fd1498Szrj 	else
469*38fd1498Szrj 	  {
470*38fd1498Szrj 	    pre_exit = split_edge (eg);
471*38fd1498Szrj 	  }
472*38fd1498Szrj       }
473*38fd1498Szrj 
474*38fd1498Szrj   return pre_exit;
475*38fd1498Szrj }
476*38fd1498Szrj 
477*38fd1498Szrj /* Find all insns that need a particular mode setting, and insert the
478*38fd1498Szrj    necessary mode switches.  Return true if we did work.  */
479*38fd1498Szrj 
480*38fd1498Szrj static int
optimize_mode_switching(void)481*38fd1498Szrj optimize_mode_switching (void)
482*38fd1498Szrj {
483*38fd1498Szrj   int e;
484*38fd1498Szrj   basic_block bb;
485*38fd1498Szrj   bool need_commit = false;
486*38fd1498Szrj   static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING;
487*38fd1498Szrj #define N_ENTITIES ARRAY_SIZE (num_modes)
488*38fd1498Szrj   int entity_map[N_ENTITIES];
489*38fd1498Szrj   struct bb_info *bb_info[N_ENTITIES];
490*38fd1498Szrj   int i, j;
491*38fd1498Szrj   int n_entities = 0;
492*38fd1498Szrj   int max_num_modes = 0;
493*38fd1498Szrj   bool emitted ATTRIBUTE_UNUSED = false;
494*38fd1498Szrj   basic_block post_entry = 0;
495*38fd1498Szrj   basic_block pre_exit = 0;
496*38fd1498Szrj   struct edge_list *edge_list = 0;
497*38fd1498Szrj 
498*38fd1498Szrj   /* These bitmaps are used for the LCM algorithm.  */
499*38fd1498Szrj   sbitmap *kill, *del, *insert, *antic, *transp, *comp;
500*38fd1498Szrj   sbitmap *avin, *avout;
501*38fd1498Szrj 
502*38fd1498Szrj   for (e = N_ENTITIES - 1; e >= 0; e--)
503*38fd1498Szrj     if (OPTIMIZE_MODE_SWITCHING (e))
504*38fd1498Szrj       {
505*38fd1498Szrj 	int entry_exit_extra = 0;
506*38fd1498Szrj 
507*38fd1498Szrj 	/* Create the list of segments within each basic block.
508*38fd1498Szrj 	   If NORMAL_MODE is defined, allow for two extra
509*38fd1498Szrj 	   blocks split from the entry and exit block.  */
510*38fd1498Szrj 	if (targetm.mode_switching.entry && targetm.mode_switching.exit)
511*38fd1498Szrj 	  entry_exit_extra = 3;
512*38fd1498Szrj 
513*38fd1498Szrj 	bb_info[n_entities]
514*38fd1498Szrj 	  = XCNEWVEC (struct bb_info,
515*38fd1498Szrj 		      last_basic_block_for_fn (cfun) + entry_exit_extra);
516*38fd1498Szrj 	entity_map[n_entities++] = e;
517*38fd1498Szrj 	if (num_modes[e] > max_num_modes)
518*38fd1498Szrj 	  max_num_modes = num_modes[e];
519*38fd1498Szrj       }
520*38fd1498Szrj 
521*38fd1498Szrj   if (! n_entities)
522*38fd1498Szrj     return 0;
523*38fd1498Szrj 
524*38fd1498Szrj   /* Make sure if MODE_ENTRY is defined MODE_EXIT is defined.  */
525*38fd1498Szrj   gcc_assert ((targetm.mode_switching.entry && targetm.mode_switching.exit)
526*38fd1498Szrj 	      || (!targetm.mode_switching.entry
527*38fd1498Szrj 		  && !targetm.mode_switching.exit));
528*38fd1498Szrj 
529*38fd1498Szrj   if (targetm.mode_switching.entry && targetm.mode_switching.exit)
530*38fd1498Szrj     {
531*38fd1498Szrj       /* Split the edge from the entry block, so that we can note that
532*38fd1498Szrj 	 there NORMAL_MODE is supplied.  */
533*38fd1498Szrj       post_entry = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
534*38fd1498Szrj       pre_exit = create_pre_exit (n_entities, entity_map, num_modes);
535*38fd1498Szrj     }
536*38fd1498Szrj 
537*38fd1498Szrj   df_analyze ();
538*38fd1498Szrj 
539*38fd1498Szrj   /* Create the bitmap vectors.  */
540*38fd1498Szrj   antic = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
541*38fd1498Szrj 				n_entities * max_num_modes);
542*38fd1498Szrj   transp = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
543*38fd1498Szrj 				 n_entities * max_num_modes);
544*38fd1498Szrj   comp = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
545*38fd1498Szrj 			       n_entities * max_num_modes);
546*38fd1498Szrj   avin = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
547*38fd1498Szrj 			       n_entities * max_num_modes);
548*38fd1498Szrj   avout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
549*38fd1498Szrj 				n_entities * max_num_modes);
550*38fd1498Szrj   kill = sbitmap_vector_alloc (last_basic_block_for_fn (cfun),
551*38fd1498Szrj 			       n_entities * max_num_modes);
552*38fd1498Szrj 
553*38fd1498Szrj   bitmap_vector_ones (transp, last_basic_block_for_fn (cfun));
554*38fd1498Szrj   bitmap_vector_clear (antic, last_basic_block_for_fn (cfun));
555*38fd1498Szrj   bitmap_vector_clear (comp, last_basic_block_for_fn (cfun));
556*38fd1498Szrj 
557*38fd1498Szrj   for (j = n_entities - 1; j >= 0; j--)
558*38fd1498Szrj     {
559*38fd1498Szrj       int e = entity_map[j];
560*38fd1498Szrj       int no_mode = num_modes[e];
561*38fd1498Szrj       struct bb_info *info = bb_info[j];
562*38fd1498Szrj       rtx_insn *insn;
563*38fd1498Szrj 
564*38fd1498Szrj       /* Determine what the first use (if any) need for a mode of entity E is.
565*38fd1498Szrj 	 This will be the mode that is anticipatable for this block.
566*38fd1498Szrj 	 Also compute the initial transparency settings.  */
567*38fd1498Szrj       FOR_EACH_BB_FN (bb, cfun)
568*38fd1498Szrj 	{
569*38fd1498Szrj 	  struct seginfo *ptr;
570*38fd1498Szrj 	  int last_mode = no_mode;
571*38fd1498Szrj 	  bool any_set_required = false;
572*38fd1498Szrj 	  HARD_REG_SET live_now;
573*38fd1498Szrj 
574*38fd1498Szrj 	  info[bb->index].mode_out = info[bb->index].mode_in = no_mode;
575*38fd1498Szrj 
576*38fd1498Szrj 	  REG_SET_TO_HARD_REG_SET (live_now, df_get_live_in (bb));
577*38fd1498Szrj 
578*38fd1498Szrj 	  /* Pretend the mode is clobbered across abnormal edges.  */
579*38fd1498Szrj 	  {
580*38fd1498Szrj 	    edge_iterator ei;
581*38fd1498Szrj 	    edge eg;
582*38fd1498Szrj 	    FOR_EACH_EDGE (eg, ei, bb->preds)
583*38fd1498Szrj 	      if (eg->flags & EDGE_COMPLEX)
584*38fd1498Szrj 		break;
585*38fd1498Szrj 	    if (eg)
586*38fd1498Szrj 	      {
587*38fd1498Szrj 		rtx_insn *ins_pos = BB_HEAD (bb);
588*38fd1498Szrj 		if (LABEL_P (ins_pos))
589*38fd1498Szrj 		  ins_pos = NEXT_INSN (ins_pos);
590*38fd1498Szrj 		gcc_assert (NOTE_INSN_BASIC_BLOCK_P (ins_pos));
591*38fd1498Szrj 		if (ins_pos != BB_END (bb))
592*38fd1498Szrj 		  ins_pos = NEXT_INSN (ins_pos);
593*38fd1498Szrj 		ptr = new_seginfo (no_mode, ins_pos, bb->index, live_now);
594*38fd1498Szrj 		add_seginfo (info + bb->index, ptr);
595*38fd1498Szrj 		for (i = 0; i < no_mode; i++)
596*38fd1498Szrj 		  clear_mode_bit (transp[bb->index], j, i);
597*38fd1498Szrj 	      }
598*38fd1498Szrj 	  }
599*38fd1498Szrj 
600*38fd1498Szrj 	  FOR_BB_INSNS (bb, insn)
601*38fd1498Szrj 	    {
602*38fd1498Szrj 	      if (INSN_P (insn))
603*38fd1498Szrj 		{
604*38fd1498Szrj 		  int mode = targetm.mode_switching.needed (e, insn);
605*38fd1498Szrj 		  rtx link;
606*38fd1498Szrj 
607*38fd1498Szrj 		  if (mode != no_mode && mode != last_mode)
608*38fd1498Szrj 		    {
609*38fd1498Szrj 		      any_set_required = true;
610*38fd1498Szrj 		      last_mode = mode;
611*38fd1498Szrj 		      ptr = new_seginfo (mode, insn, bb->index, live_now);
612*38fd1498Szrj 		      add_seginfo (info + bb->index, ptr);
613*38fd1498Szrj 		      for (i = 0; i < no_mode; i++)
614*38fd1498Szrj 			clear_mode_bit (transp[bb->index], j, i);
615*38fd1498Szrj 		    }
616*38fd1498Szrj 
617*38fd1498Szrj 		  if (targetm.mode_switching.after)
618*38fd1498Szrj 		    last_mode = targetm.mode_switching.after (e, last_mode,
619*38fd1498Szrj 							      insn);
620*38fd1498Szrj 
621*38fd1498Szrj 		  /* Update LIVE_NOW.  */
622*38fd1498Szrj 		  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
623*38fd1498Szrj 		    if (REG_NOTE_KIND (link) == REG_DEAD)
624*38fd1498Szrj 		      reg_dies (XEXP (link, 0), &live_now);
625*38fd1498Szrj 
626*38fd1498Szrj 		  note_stores (PATTERN (insn), reg_becomes_live, &live_now);
627*38fd1498Szrj 		  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
628*38fd1498Szrj 		    if (REG_NOTE_KIND (link) == REG_UNUSED)
629*38fd1498Szrj 		      reg_dies (XEXP (link, 0), &live_now);
630*38fd1498Szrj 		}
631*38fd1498Szrj 	    }
632*38fd1498Szrj 
633*38fd1498Szrj 	  info[bb->index].computing = last_mode;
634*38fd1498Szrj 	  /* Check for blocks without ANY mode requirements.
635*38fd1498Szrj 	     N.B. because of MODE_AFTER, last_mode might still
636*38fd1498Szrj 	     be different from no_mode, in which case we need to
637*38fd1498Szrj 	     mark the block as nontransparent.  */
638*38fd1498Szrj 	  if (!any_set_required)
639*38fd1498Szrj 	    {
640*38fd1498Szrj 	      ptr = new_seginfo (no_mode, BB_END (bb), bb->index, live_now);
641*38fd1498Szrj 	      add_seginfo (info + bb->index, ptr);
642*38fd1498Szrj 	      if (last_mode != no_mode)
643*38fd1498Szrj 		for (i = 0; i < no_mode; i++)
644*38fd1498Szrj 		  clear_mode_bit (transp[bb->index], j, i);
645*38fd1498Szrj 	    }
646*38fd1498Szrj 	}
647*38fd1498Szrj       if (targetm.mode_switching.entry && targetm.mode_switching.exit)
648*38fd1498Szrj 	{
649*38fd1498Szrj 	  int mode = targetm.mode_switching.entry (e);
650*38fd1498Szrj 
651*38fd1498Szrj 	  info[post_entry->index].mode_out =
652*38fd1498Szrj 	    info[post_entry->index].mode_in = no_mode;
653*38fd1498Szrj 	  if (pre_exit)
654*38fd1498Szrj 	    {
655*38fd1498Szrj 	      info[pre_exit->index].mode_out =
656*38fd1498Szrj 		info[pre_exit->index].mode_in = no_mode;
657*38fd1498Szrj 	    }
658*38fd1498Szrj 
659*38fd1498Szrj 	  if (mode != no_mode)
660*38fd1498Szrj 	    {
661*38fd1498Szrj 	      bb = post_entry;
662*38fd1498Szrj 
663*38fd1498Szrj 	      /* By always making this nontransparent, we save
664*38fd1498Szrj 		 an extra check in make_preds_opaque.  We also
665*38fd1498Szrj 		 need this to avoid confusing pre_edge_lcm when
666*38fd1498Szrj 		 antic is cleared but transp and comp are set.  */
667*38fd1498Szrj 	      for (i = 0; i < no_mode; i++)
668*38fd1498Szrj 		clear_mode_bit (transp[bb->index], j, i);
669*38fd1498Szrj 
670*38fd1498Szrj 	      /* Insert a fake computing definition of MODE into entry
671*38fd1498Szrj 		 blocks which compute no mode. This represents the mode on
672*38fd1498Szrj 		 entry.  */
673*38fd1498Szrj 	      info[bb->index].computing = mode;
674*38fd1498Szrj 
675*38fd1498Szrj 	      if (pre_exit)
676*38fd1498Szrj 		info[pre_exit->index].seginfo->mode =
677*38fd1498Szrj 		  targetm.mode_switching.exit (e);
678*38fd1498Szrj 	    }
679*38fd1498Szrj 	}
680*38fd1498Szrj 
681*38fd1498Szrj       /* Set the anticipatable and computing arrays.  */
682*38fd1498Szrj       for (i = 0; i < no_mode; i++)
683*38fd1498Szrj 	{
684*38fd1498Szrj 	  int m = targetm.mode_switching.priority (entity_map[j], i);
685*38fd1498Szrj 
686*38fd1498Szrj 	  FOR_EACH_BB_FN (bb, cfun)
687*38fd1498Szrj 	    {
688*38fd1498Szrj 	      if (info[bb->index].seginfo->mode == m)
689*38fd1498Szrj 		set_mode_bit (antic[bb->index], j, m);
690*38fd1498Szrj 
691*38fd1498Szrj 	      if (info[bb->index].computing == m)
692*38fd1498Szrj 		set_mode_bit (comp[bb->index], j, m);
693*38fd1498Szrj 	    }
694*38fd1498Szrj 	}
695*38fd1498Szrj     }
696*38fd1498Szrj 
697*38fd1498Szrj   /* Calculate the optimal locations for the
698*38fd1498Szrj      placement mode switches to modes with priority I.  */
699*38fd1498Szrj 
700*38fd1498Szrj   FOR_EACH_BB_FN (bb, cfun)
701*38fd1498Szrj     bitmap_not (kill[bb->index], transp[bb->index]);
702*38fd1498Szrj 
703*38fd1498Szrj   edge_list = pre_edge_lcm_avs (n_entities * max_num_modes, transp, comp, antic,
704*38fd1498Szrj 				kill, avin, avout, &insert, &del);
705*38fd1498Szrj 
706*38fd1498Szrj   for (j = n_entities - 1; j >= 0; j--)
707*38fd1498Szrj     {
708*38fd1498Szrj       int no_mode = num_modes[entity_map[j]];
709*38fd1498Szrj 
710*38fd1498Szrj       /* Insert all mode sets that have been inserted by lcm.  */
711*38fd1498Szrj 
712*38fd1498Szrj       for (int ed = NUM_EDGES (edge_list) - 1; ed >= 0; ed--)
713*38fd1498Szrj 	{
714*38fd1498Szrj 	  edge eg = INDEX_EDGE (edge_list, ed);
715*38fd1498Szrj 
716*38fd1498Szrj 	  eg->aux = (void *)(intptr_t)-1;
717*38fd1498Szrj 
718*38fd1498Szrj 	  for (i = 0; i < no_mode; i++)
719*38fd1498Szrj 	    {
720*38fd1498Szrj 	      int m = targetm.mode_switching.priority (entity_map[j], i);
721*38fd1498Szrj 	      if (mode_bit_p (insert[ed], j, m))
722*38fd1498Szrj 		{
723*38fd1498Szrj 		  eg->aux = (void *)(intptr_t)m;
724*38fd1498Szrj 		  break;
725*38fd1498Szrj 		}
726*38fd1498Szrj 	    }
727*38fd1498Szrj 	}
728*38fd1498Szrj 
729*38fd1498Szrj       FOR_EACH_BB_FN (bb, cfun)
730*38fd1498Szrj 	{
731*38fd1498Szrj 	  struct bb_info *info = bb_info[j];
732*38fd1498Szrj 	  int last_mode = no_mode;
733*38fd1498Szrj 
734*38fd1498Szrj 	  /* intialize mode in availability for bb.  */
735*38fd1498Szrj 	  for (i = 0; i < no_mode; i++)
736*38fd1498Szrj 	    if (mode_bit_p (avout[bb->index], j, i))
737*38fd1498Szrj 	      {
738*38fd1498Szrj 		if (last_mode == no_mode)
739*38fd1498Szrj 		  last_mode = i;
740*38fd1498Szrj 		if (last_mode != i)
741*38fd1498Szrj 		  {
742*38fd1498Szrj 		    last_mode = no_mode;
743*38fd1498Szrj 		    break;
744*38fd1498Szrj 		  }
745*38fd1498Szrj 	      }
746*38fd1498Szrj 	  info[bb->index].mode_out = last_mode;
747*38fd1498Szrj 
748*38fd1498Szrj 	  /* intialize mode out availability for bb.  */
749*38fd1498Szrj 	  last_mode = no_mode;
750*38fd1498Szrj 	  for (i = 0; i < no_mode; i++)
751*38fd1498Szrj 	    if (mode_bit_p (avin[bb->index], j, i))
752*38fd1498Szrj 	      {
753*38fd1498Szrj 		if (last_mode == no_mode)
754*38fd1498Szrj 		  last_mode = i;
755*38fd1498Szrj 		if (last_mode != i)
756*38fd1498Szrj 		  {
757*38fd1498Szrj 		    last_mode = no_mode;
758*38fd1498Szrj 		    break;
759*38fd1498Szrj 		  }
760*38fd1498Szrj 	      }
761*38fd1498Szrj 	  info[bb->index].mode_in = last_mode;
762*38fd1498Szrj 
763*38fd1498Szrj 	  for (i = 0; i < no_mode; i++)
764*38fd1498Szrj 	    if (mode_bit_p (del[bb->index], j, i))
765*38fd1498Szrj 	      info[bb->index].seginfo->mode = no_mode;
766*38fd1498Szrj 	}
767*38fd1498Szrj 
768*38fd1498Szrj       /* Now output the remaining mode sets in all the segments.  */
769*38fd1498Szrj 
770*38fd1498Szrj       /* In case there was no mode inserted. the mode information on the edge
771*38fd1498Szrj 	 might not be complete.
772*38fd1498Szrj 	 Update mode info on edges and commit pending mode sets.  */
773*38fd1498Szrj       need_commit |= commit_mode_sets (edge_list, entity_map[j], bb_info[j]);
774*38fd1498Szrj 
775*38fd1498Szrj       /* Reset modes for next entity.  */
776*38fd1498Szrj       clear_aux_for_edges ();
777*38fd1498Szrj 
778*38fd1498Szrj       FOR_EACH_BB_FN (bb, cfun)
779*38fd1498Szrj 	{
780*38fd1498Szrj 	  struct seginfo *ptr, *next;
781*38fd1498Szrj 	  int cur_mode = bb_info[j][bb->index].mode_in;
782*38fd1498Szrj 
783*38fd1498Szrj 	  for (ptr = bb_info[j][bb->index].seginfo; ptr; ptr = next)
784*38fd1498Szrj 	    {
785*38fd1498Szrj 	      next = ptr->next;
786*38fd1498Szrj 	      if (ptr->mode != no_mode)
787*38fd1498Szrj 		{
788*38fd1498Szrj 		  rtx_insn *mode_set;
789*38fd1498Szrj 
790*38fd1498Szrj 		  rtl_profile_for_bb (bb);
791*38fd1498Szrj 		  start_sequence ();
792*38fd1498Szrj 
793*38fd1498Szrj 		  targetm.mode_switching.emit (entity_map[j], ptr->mode,
794*38fd1498Szrj 					       cur_mode, ptr->regs_live);
795*38fd1498Szrj 		  mode_set = get_insns ();
796*38fd1498Szrj 		  end_sequence ();
797*38fd1498Szrj 
798*38fd1498Szrj 		  /* modes kill each other inside a basic block.  */
799*38fd1498Szrj 		  cur_mode = ptr->mode;
800*38fd1498Szrj 
801*38fd1498Szrj 		  /* Insert MODE_SET only if it is nonempty.  */
802*38fd1498Szrj 		  if (mode_set != NULL_RTX)
803*38fd1498Szrj 		    {
804*38fd1498Szrj 		      emitted = true;
805*38fd1498Szrj 		      if (NOTE_INSN_BASIC_BLOCK_P (ptr->insn_ptr))
806*38fd1498Szrj 			/* We need to emit the insns in a FIFO-like manner,
807*38fd1498Szrj 			   i.e. the first to be emitted at our insertion
808*38fd1498Szrj 			   point ends up first in the instruction steam.
809*38fd1498Szrj 			   Because we made sure that NOTE_INSN_BASIC_BLOCK is
810*38fd1498Szrj 			   only used for initially empty basic blocks, we
811*38fd1498Szrj 			   can achieve this by appending at the end of
812*38fd1498Szrj 			   the block.  */
813*38fd1498Szrj 			emit_insn_after
814*38fd1498Szrj 			  (mode_set, BB_END (NOTE_BASIC_BLOCK (ptr->insn_ptr)));
815*38fd1498Szrj 		      else
816*38fd1498Szrj 			emit_insn_before (mode_set, ptr->insn_ptr);
817*38fd1498Szrj 		    }
818*38fd1498Szrj 
819*38fd1498Szrj 		  default_rtl_profile ();
820*38fd1498Szrj 		}
821*38fd1498Szrj 
822*38fd1498Szrj 	      free (ptr);
823*38fd1498Szrj 	    }
824*38fd1498Szrj 	}
825*38fd1498Szrj 
826*38fd1498Szrj       free (bb_info[j]);
827*38fd1498Szrj     }
828*38fd1498Szrj 
829*38fd1498Szrj   free_edge_list (edge_list);
830*38fd1498Szrj 
831*38fd1498Szrj   /* Finished. Free up all the things we've allocated.  */
832*38fd1498Szrj   sbitmap_vector_free (del);
833*38fd1498Szrj   sbitmap_vector_free (insert);
834*38fd1498Szrj   sbitmap_vector_free (kill);
835*38fd1498Szrj   sbitmap_vector_free (antic);
836*38fd1498Szrj   sbitmap_vector_free (transp);
837*38fd1498Szrj   sbitmap_vector_free (comp);
838*38fd1498Szrj   sbitmap_vector_free (avin);
839*38fd1498Szrj   sbitmap_vector_free (avout);
840*38fd1498Szrj 
841*38fd1498Szrj   if (need_commit)
842*38fd1498Szrj     commit_edge_insertions ();
843*38fd1498Szrj 
844*38fd1498Szrj   if (targetm.mode_switching.entry && targetm.mode_switching.exit)
845*38fd1498Szrj     cleanup_cfg (CLEANUP_NO_INSN_DEL);
846*38fd1498Szrj   else if (!need_commit && !emitted)
847*38fd1498Szrj     return 0;
848*38fd1498Szrj 
849*38fd1498Szrj   return 1;
850*38fd1498Szrj }
851*38fd1498Szrj 
852*38fd1498Szrj #endif /* OPTIMIZE_MODE_SWITCHING */
853*38fd1498Szrj 
854*38fd1498Szrj namespace {
855*38fd1498Szrj 
856*38fd1498Szrj const pass_data pass_data_mode_switching =
857*38fd1498Szrj {
858*38fd1498Szrj   RTL_PASS, /* type */
859*38fd1498Szrj   "mode_sw", /* name */
860*38fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
861*38fd1498Szrj   TV_MODE_SWITCH, /* tv_id */
862*38fd1498Szrj   0, /* properties_required */
863*38fd1498Szrj   0, /* properties_provided */
864*38fd1498Szrj   0, /* properties_destroyed */
865*38fd1498Szrj   0, /* todo_flags_start */
866*38fd1498Szrj   TODO_df_finish, /* todo_flags_finish */
867*38fd1498Szrj };
868*38fd1498Szrj 
869*38fd1498Szrj class pass_mode_switching : public rtl_opt_pass
870*38fd1498Szrj {
871*38fd1498Szrj public:
pass_mode_switching(gcc::context * ctxt)872*38fd1498Szrj   pass_mode_switching (gcc::context *ctxt)
873*38fd1498Szrj     : rtl_opt_pass (pass_data_mode_switching, ctxt)
874*38fd1498Szrj   {}
875*38fd1498Szrj 
876*38fd1498Szrj   /* opt_pass methods: */
877*38fd1498Szrj   /* The epiphany backend creates a second instance of this pass, so we need
878*38fd1498Szrj      a clone method.  */
clone()879*38fd1498Szrj   opt_pass * clone () { return new pass_mode_switching (m_ctxt); }
gate(function *)880*38fd1498Szrj   virtual bool gate (function *)
881*38fd1498Szrj     {
882*38fd1498Szrj #ifdef OPTIMIZE_MODE_SWITCHING
883*38fd1498Szrj       return true;
884*38fd1498Szrj #else
885*38fd1498Szrj       return false;
886*38fd1498Szrj #endif
887*38fd1498Szrj     }
888*38fd1498Szrj 
execute(function *)889*38fd1498Szrj   virtual unsigned int execute (function *)
890*38fd1498Szrj     {
891*38fd1498Szrj #ifdef OPTIMIZE_MODE_SWITCHING
892*38fd1498Szrj       optimize_mode_switching ();
893*38fd1498Szrj #endif /* OPTIMIZE_MODE_SWITCHING */
894*38fd1498Szrj       return 0;
895*38fd1498Szrj     }
896*38fd1498Szrj 
897*38fd1498Szrj }; // class pass_mode_switching
898*38fd1498Szrj 
899*38fd1498Szrj } // anon namespace
900*38fd1498Szrj 
901*38fd1498Szrj rtl_opt_pass *
make_pass_mode_switching(gcc::context * ctxt)902*38fd1498Szrj make_pass_mode_switching (gcc::context *ctxt)
903*38fd1498Szrj {
904*38fd1498Szrj   return new pass_mode_switching (ctxt);
905*38fd1498Szrj }
906